Skip to content

chore: Migrate SIWE dependency to @signinwithethereum/siwe v4 - #8497

Open
caveman-eth wants to merge 3 commits into
MetaMask:mainfrom
caveman-eth:update-siwe-dependencies-2
Open

chore: Migrate SIWE dependency to @signinwithethereum/siwe v4#8497
caveman-eth wants to merge 3 commits into
MetaMask:mainfrom
caveman-eth:update-siwe-dependencies-2

Conversation

@caveman-eth

@caveman-eth caveman-eth commented Apr 16, 2026

Copy link
Copy Markdown

Superseeds #8419 (couldn't reopen due to force-push).

Explanation

Current state

The monorepo depends on two SIWE (Sign-In With Ethereum / EIP-4361) packages originally maintained by Spruce:

  • @spruceid/siwe-parser v2.1.0 — used by @metamask/controller-utils to detect and parse SIWE messages via detectSIWE()
  • siwe v2.3.2 — used by @metamask/profile-sync-controller to construct SIWE login messages via new SiweMessage({...}).prepareMessage()

The Spruce siwe package is no longer actively maintained.

Stewardship of the SIWE standard has moved to the Ethereum Identity Foundation (GitHub).
@signinwithethereum/siwe is the official successor TypeScript implementation.

Similar migrations:

x402-foundation/x402 x402-foundation/x402#1917,
magiclabs/magic-js magiclabs/magic-js#1074

What this PR does

Swaps the abandoned packages for the actively maintained successors. The ParsedMessage and SiweMessage class APIs are identical - same constructors, same fields, same methods. This is purely a dependency swap with import path updates.

Files changed:

Package File Change
controller-utils package.json Replaced dependency
controller-utils src/siwe.ts Import path updated
controller-utils src/siwe.test.ts Import path updated
profile-sync-controller package.json Replaced dependency
profile-sync-controller src/sdk/authentication-jwt-bearer/flow-siwe.ts Import path updated

EIP-55 patches in client repos become obsolete

The old version strictly rejected non checksummed Ethereum addresses in SIWE messages. Because many dApps produce lowercase addresses, both MetaMask client repos maintain patches to disable the check — otherwise detectSIWE returns { isSIWEMessage: false } and users don't see the specialized SIWE approval screen.

@signinwithethereum/siwe-parser v4.2.0 (release notes) relaxes this:

  • All-lowercase and all-uppercase addresses now parse successfully with a non-fatal warning on the new warnings: string[] field of ParsedMessage
  • Only mixed-case addresses with an incorrect checksum still fail to parse
  • Verification is case-insensitive for EOA signature recovery
  • Object-constructed SiweMessage instances are normalized to EIP-55

If the client repos upgrade to this version of controller-utils, they can delete these patches and any related package.json resolutions:

References

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

Note

Medium Risk
Changes SIWE parsing and login message construction on auth-related paths; APIs are intended to be compatible, but v4.2.0 address-checksum behavior differs from the old strict parser.

Overview
Replaces unmaintained Spruce SIWE packages with @signinwithethereum successors (^4.2.0) in @metamask/controller-utils and @metamask/profile-sync-controller.

controller-utils swaps @spruceid/siwe-parser for @signinwithethereum/siwe-parser and updates imports in siwe.ts / tests. detectSIWE still uses ParsedMessage the same way.

profile-sync-controller drops the siwe package for @signinwithethereum/siwe and updates flow-siwe.ts so JWT SIWE login still builds messages via new SiweMessage({...}).prepareMessage().

Changelogs note that v4.2.0 relaxes EIP-55 parsing: all-lowercase or all-uppercase addresses parse (with optional warnings); only bad mixed-case checksums fail. That may let extension/mobile remove local parser patches once they pick up this core release.

Reviewed by Cursor Bugbot for commit 0ae4c09. Bugbot is set up for automated code reviews on this repo. Configure here.

@caveman-eth
caveman-eth requested review from a team as code owners April 16, 2026 18:42
@socket-security

socket-security Bot commented Apr 16, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​signinwithethereum/​siwe-parser@​4.2.01001009484100
Added@​signinwithethereum/​siwe@​4.2.01001009885100

View full report

Swap SpruceID-maintained SIWE packages for the @signinwithethereum scoped packages and update usages. Update package.json dependencies and imports (controller-utils: siwe.ts, siwe.test.ts; profile-sync-controller: flow-siwe.ts) and add changelog notes describing the migration. Uses @signinwithethereum/siwe-parser and @signinwithethereum/siwe ^4.2.0 — maintained by the Ethereum Identity Foundation and backward-compatible (parser v4.2.0 relaxes EIP-55 checksum enforcement and surfaces non-fatal warnings).
Replace placeholder PR links [#XXXX] with the actual PR number [MetaMask#8497] in CHANGELOG.md for packages/controller-utils and packages/profile-sync-controller. These entries document the replacement of the old siwe packages with the @signinwithethereum scoped packages.
@caveman-eth
caveman-eth force-pushed the update-siwe-dependencies-2 branch from 0889956 to 6b91d4d Compare April 28, 2026 14:26
@caveman-eth

Copy link
Copy Markdown
Author

Let me know if you guys have any questions around this.

@caveman-eth

Copy link
Copy Markdown
Author

bumping this up

@OGPoyraz

OGPoyraz commented Sep 1, 2026

Copy link
Copy Markdown
Member

Thanks for the PR @caveman-eth

PR looks good to me and hopefully be ready after fixing conflicts 🙏

@OGPoyraz
OGPoyraz self-requested a review September 1, 2026 08:06
@caveman-eth

Copy link
Copy Markdown
Author

Thanks for the PR @caveman-eth

PR looks good to me and hopefully be ready after fixing conflicts 🙏

Hey great - I've resolved the conflicts and merged in main

@OGPoyraz

OGPoyraz commented Sep 1, 2026

Copy link
Copy Markdown
Member

Hey @caveman-eth I think we have two issues here:

  1. Blocking: TS1479 build error from @signinwithethereum/siwe-parser@4.2.0's packaging
    @signinwithethereum/siwe-parser@4.2.0's package.json sets "type": "module", but only ships one unconditional .d.ts (no separate .d.cts for the CJS entry). Under our repo's Node16 module resolution, TS infers that shared .d.ts as ESM-only. So when controller-utils (compiled as CJS) does import { ParsedMessage } from '@signinwithethereum/siwe-parser', it throws:
    TS1479: The current file is a CommonJS module whose imports will produce 'require' calls;
    however, the referenced file is an ECMAScript module and cannot be imported with 'require'.
    This breaks yarn build and the wallet-cli e2e jobs. I confirmed it's not a fluke of this branch - reproduced identically on a fresh main in #10049.

Important: the package's runtime behavior is fine (dual CJS/ESM exports are correctly set up, and our Jest tests - which bypass ts-bridge - pass). This is purely a type-declaration packaging gap upstream, not a real incompatibility.

Can we publish conditional type declarations (.d.cts / .d.mts) matching their dual CJS/ESM exports, per the standard "dual package hazard" from https://github.com/signinwithethereum/siwe ?

  1. Non-blocking, unrelated to the code: fork-based changelog-check failures

This PR is from a fork (caveman-eth/metamask-core), the branch doesn't exist on origin (MetaMask/core), and those workflows try to git fetch/checkout the head branch directly from origin. This is a known limitation of those workflows with fork PRs - not something fixable from the PR branch itself. I confirmed this disappears when the same commits are pushed as a same-repo branch instead of a fork (see #10049). If you don't mind we can close this PR and continue from #10049.

When we have fix for the first issue, I can update the version and give another try?

@caveman-eth

caveman-eth commented Sep 1, 2026

Copy link
Copy Markdown
Author

@OGPoyraz, thanks for digging into this.

  1. TS1479
    Agreed. Runtime dual CJS/ESM was already in place; the gap was types. @signinwithethereum/siwe-parser and @signinwithethereum/siwe 4.2.1 are published with matching declarations:

import → .d.mts + .mjs
require → .d.cts + .cjs
Same change on both packages, since profile-sync-controller would have hit the same error on siwe.

https://www.npmjs.com/package/@signinwithethereum/siwe/v/4.2.1

Age gate: Core’s Yarn config waits 3 days after publish (npmMinimalAgeGate: 4320). 4.2.1 went up at 2026-09-01 16:50 UTC, so yarn install should accept it around 2026-09-04 16:50 UTC. Happy to bump this PR (or #10049) as soon as that window opens.

  1. Fork changelog-check
    Understood that this is a workflow limitation on fork PRs, not something we can fix on the branch. Fine to continue from chore: Migrate SIWE dependency to @signinwithethereum/siwe v4 #10049 if that is easier for CI. Changelog entries currently cite chore: Migrate SIWE dependency to @signinwithethereum/siwe v4 #8497; we can retarget those if chore: Migrate SIWE dependency to @signinwithethereum/siwe v4 #10049 is the one that merges.

@OGPoyraz

OGPoyraz commented Sep 2, 2026

Copy link
Copy Markdown
Member

Hey @caveman-eth, thanks for the quick turnaround on 4.2.1 with the .d.cts/.d.mts fix, that's exactly what we needed.

The only remaining blocker is the npmMinimalAgeGate: 4320 in our Yarn config - 4.2.1 was published on 2026-09-01 at 16:50 UTC so we can't install it until ~2026-09-04 16:50 UTC. Nothing to do on your end, just waiting out the 3-day window :)

Once that clears I'll bump both @signinwithethereum/siwe-parser and @signinwithethereum/siwe to ^4.2.1 on #10049 and we should be good to merge.

Thanks again for staying on top of this 🙏

@caveman-eth

Copy link
Copy Markdown
Author

@OGPoyraz great, sounds good. I'll ping you here after 2026-09-04 16:50 UTC :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants