Skip to content

Conversation

@sragss
Copy link
Contributor

@sragss sragss commented Jan 7, 2026

Implements CAIP-122 compliant Sign-In-With-X (SIWX) extension for x402 v2 protocol aligned with CHANGELOG-v2.md and sign-in-with-x/TODO.md.

Supported Signature Schemes

  • eip191 - personal_sign (EOAs)
  • eip1271 - Smart contract wallets
  • eip6492 - Counterfactual smart wallets
  • siws - Sign-In-With-Solana

Missing: EIP-712 + Stellar.

Note the interface for using Smart Wallets is a bit odd, didn't want to bake the RPC into a generic extension.

  // EOA only
  const result = await verifySIWxSignature(payload);

  // Smart wallet support (EIP-1271/EIP-6492)
  const publicClient = createPublicClient({ chain: base, transport: http()
  });
  const result = await verifySIWxSignature(payload, {
    evmVerifier: publicClient.verifyMessage,
  });

Update 1/17/25

  • Added spec.md
  • Added wrapFetchWithSIWx exported from @x402/extensions/siwx to match wrapFetchWithPay
  • Added examples/typescript/{client,server}/sign-in-with-x

Implementation note: we use conditional middleware in the server example. I considered putting special logic into paymentMiddleware but decided that was against the premise of optional extensions. Another pattern that could be clean would be to put a skipIf: (req) => bool lambda as an optional param in the paymentMiddleware which takes the simple SIWx verification function.

Example logs
Server

Server running at http://localhost:4021
Routes: GET /weather, GET /joke
Payment recorded: 0x6d157C00d034541020fF73A989960D22b299d8e1 for /weather
SIWX auth: 0x6d157C00d034541020fF73A989960D22b299d8e1 for /weather
Payment recorded: 0x6d157C00d034541020fF73A989960D22b299d8e1 for /joke
SIWX auth: 0x6d157C00d034541020fF73A989960D22b299d8e1 for /joke

Client

Client address: 0x6d157C00d034541020fF73A989960D22b299d8e1
Server: http://localhost:4021

--- /weather ---
1. First request (paying)...
   Response: { weather: 'sunny', temperature: 72 }
2. Second request (SIWX auth)...
   Response: { weather: 'sunny', temperature: 72 }

--- /joke ---
1. First request (paying)...
   Response: {
  joke: 'Why do programmers prefer dark mode? Because light attracts bugs.'
}
2. Second request (SIWX auth)...
   Response: {
  joke: 'Why do programmers prefer dark mode? Because light attracts bugs.'
}

Done. Each resource required payment once, then SIWX auth worked.

sragss added 12 commits January 6, 2026 18:47
Implements CAIP-122 compliant wallet-based identity assertions for x402 v2.

- Add SIWX types following CAIP-122 standard
- Server-side: declareSIWxExtension() for 402 response generation
- Client-side: createSIWxPayload() for proof creation and signing
- Message construction following CAIP-122 format
- Header encoding/parsing (base64 per x402 v2 spec)
- Validation: temporal, domain binding, nonce checking
- Verification: cryptographic signature validation via siwe library
- JSON Schema generation for payload validation
- Test coverage for core flows
@cb-heimdall
Copy link

cb-heimdall commented Jan 7, 2026

🟡 Heimdall Review Status

Requirement Status More Info
Reviews 🟡 0/1
Denominator calculation
Show calculation
1 if user is bot 0
1 if user is external 0
2 if repo is sensitive 0
From .codeflow.yml 1
Additional review requirements
Show calculation
Max 0
0
From CODEOWNERS 0
Global minimum 0
Max 1
1
1 if commit is unverified 0
Sum 1

@vercel
Copy link

vercel bot commented Jan 7, 2026

@sragss is attempting to deploy a commit to the Coinbase Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions github-actions bot added typescript sdk Changes to core v2 packages labels Jan 7, 2026
Copy link
Contributor

@CarsonRoscoe CarsonRoscoe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing work @sragss, thank you, will give this a review shortly

@CarsonRoscoe CarsonRoscoe self-assigned this Jan 8, 2026
@github-actions github-actions bot added the examples Changes to examples label Jan 8, 2026
@phdargen
Copy link
Contributor

phdargen commented Jan 8, 2026

Thanks for your contribution @sragss, excited for this!

@CarsonRoscoe shall we have a spec document for extensions as well, like we have for schemes and transports?
The TODO.md deleted in this PR might be a good starting point for that

There is none for the discovery extension, but might be worth to add, especially for 3rd party sdk devs

@CarsonRoscoe
Copy link
Contributor

@phdargen Agreed, we should have a top level /specs/extensions folder with specs per extension

Copy link
Contributor

@CarsonRoscoe CarsonRoscoe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @sragss!

This is looking really good. Very happy with it from my readings,

My two asks are:

  1. Can you add a /specs/extensions/sign-in-with-x.md file outlining the spec as implemented? This will become the north start to ensure Go/Python implementations remain compatible
  2. Can you integrate these into an example for testing. For example, a /examples/typescript/clients/sign-in-with-x (using fetch) and /examples/typescript/servers/sign-in-with-x (using express) example that can be run to showcase how a client/server could leverage this extension to prove a client already paid? I'm imagining when running these examples, the flow would be that the server caches payments in memory, and is able to skip payments for clients who already paid. Then the first client run would make payment, while the second one would get the resource without needing payment due to siwx?

Please include a run of the client & server examples in your PR afterwards, we'll consider it additional testing

Great work, I think the examples & spec are all that I need to feel comfortable merging :)

sragss and others added 2 commits January 16, 2026 20:57
Update lockfile to include @types/node added to client example.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions github-actions bot added the specs Spec changes or additions label Jan 17, 2026
@sragss
Copy link
Contributor Author

sragss commented Jan 17, 2026

Done.

Update 1/17/25

  • Added spec.md
  • Added wrapFetchWithSIWx exported from @x402/extensions/siwx to match wrapFetchWithPay and simplify client experience
  • Added examples/typescript/{client,server}/sign-in-with-x

Implementation note: we use conditional middleware in the server example. I considered putting special logic into paymentMiddleware but decided that was against the premise of optional extensions. Another pattern that could be clean would be to put a skipIf: (req) => bool lambda as an optional param in the paymentMiddleware which takes the simple SIWx verification function. Punting on that for now.

Example logs
Server

Server running at http://localhost:4021
Routes: GET /weather, GET /joke
Payment recorded: 0x6d157C00d034541020fF73A989960D22b299d8e1 for /weather
SIWX auth: 0x6d157C00d034541020fF73A989960D22b299d8e1 for /weather
Payment recorded: 0x6d157C00d034541020fF73A989960D22b299d8e1 for /joke
SIWX auth: 0x6d157C00d034541020fF73A989960D22b299d8e1 for /joke

Client

Client address: 0x6d157C00d034541020fF73A989960D22b299d8e1
Server: http://localhost:4021

--- /weather ---
1. First request (paying)...
   Response: { weather: 'sunny', temperature: 72 }
2. Second request (SIWX auth)...
   Response: { weather: 'sunny', temperature: 72 }

--- /joke ---
1. First request (paying)...
   Response: {
  joke: 'Why do programmers prefer dark mode? Because light attracts bugs.'
}
2. Second request (SIWX auth)...
   Response: {
  joke: 'Why do programmers prefer dark mode? Because light attracts bugs.'
}

Done. Each resource required payment once, then SIWX auth worked.

sragss and others added 2 commits January 17, 2026 12:02
Adds a fetch wrapper for SIWX authentication that mirrors the
wrapFetchWithPayment pattern from @x402/fetch. The wrapper
automatically handles 402 responses with SIWX extension info.

Changes:
- Add fetch.ts with wrapFetchWithSIWx function
- Export wrapFetchWithSIWx from sign-in-with-x index
- Add DOM lib to tsconfig for Request/Response types
- Simplify client example to use the new wrapper
- Add .prettierignore and eslint globals to match other examples

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

examples Changes to examples sdk Changes to core v2 packages specs Spec changes or additions typescript

Development

Successfully merging this pull request may close these issues.

4 participants