Skip to content

qntx/siwx

Sign In with X

Chain-Agnostic Wallet Authentication for Rust

CI License Rust

Type-safe Rust SDK for CAIP-122 Sign-In with X. Construct, parse, validate, and verify wallet authentication messages across any blockchain.

Quick Start | CLI | Architecture | API docs

Crates

Crate Description
siwx crates.io docs.rs Core data model, parser, validator, Verifier trait
siwx-evm crates.io docs.rs EIP-191 + EIP-1271 verification — Ethereum, Polygon, Arbitrum, …
siwx-svm crates.io docs.rs Ed25519 verification — Solana
siwx-cli crates.io CLI tool for message generation, parsing, and verification

Overview

CAIP-122 standardises wallet-based authentication across blockchains — the chain-agnostic successor to EIP-4361 (SIWE). This SDK provides:

  • Message construction — build CAIP-122 challenge messages with a builder API
  • Message parsing — round-trip FromStr / Display for the human-readable signing format
  • Temporal & domain validation — expiration, not-before, domain binding, nonce binding
  • Signature verification — pluggable Verifier trait with built-in EVM and Solana support
  • CLI tool — generate, parse, and verify messages from the command line with JSON output

The core siwx crate is chain-agnostic; chain-specific logic is in companion crates.

Quick Start

Construct message (backend)

use siwx::SiwxMessage;

let message = SiwxMessage::new(
    "example.com",                                    // domain
    "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",    // address
    "https://example.com/login",                      // uri
    "1",                                              // version
    "1",                                              // chain_id (EIP-155)
)?
.with_statement("Sign in to Example")
.with_nonce(siwx::nonce::generate_default());

// Format as the human-readable signing string
let signing_input = siwx_evm::format_message(&message);
// → "example.com wants you to sign in with your Ethereum account:\n0xd8dA…"

Verify signature (backend)

use siwx::{SiwxMessage, ValidateOpts, Verifier};
use siwx_evm::EvmVerifier;

// Parse the message returned from the frontend
let message: SiwxMessage = signing_input.parse()?;

// Validate fields & temporal constraints
message.validate(&ValidateOpts {
    domain: Some("example.com".into()),
    nonce:  Some(expected_nonce),
    ..Default::default()
})?;

// Cryptographic verification (EIP-191 with EIP-1271 fallback)
let verifier = EvmVerifier::with_rpc("https://eth.llamarpc.com");
verifier.verify(&message, &signature_bytes).await?;

CLI

Install the CLI

Shell (macOS / Linux):

curl -fsSL https://sh.qntx.fun/siwx | sh

PowerShell (Windows):

irm https://sh.qntx.fun/siwx/ps | iex

Or via Cargo:

cargo install siwx-cli

Generate message

siwx evm message \
  --domain example.com \
  --address 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 \
  --uri https://example.com/login \
  --chain-id 1 \
  --statement "Sign in to Example"
siwx svm message \
  --domain example.com \
  --address GwAF45zjfyGzUbd3i3hXxzGeuchzEZXwpRYHZM5912F1 \
  --uri https://example.com/login \
  --chain-id 5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d

Verify signature

siwx evm verify --message "..." --signature 0x...
siwx svm verify --message "..." --signature 0x...

JSON output

All commands support --json for programmatic / agent consumption:

siwx --json evm message --domain example.com --address 0x... --uri https://... --chain-id 1
{
  "chain": "ethereum",
  "message": "example.com wants you to sign in with your Ethereum account:\n...",
  "domain": "example.com",
  "address": "0x...",
  "uri": "https://...",
  "version": "1",
  "chain_id": "1",
  "nonce": "L8s2Mf7kGxPQN9a4z",
  "issued_at": "2024-01-01T00:00:00Z"
}

Architecture

Authentication Flow

sequenceDiagram
    participant Frontend
    participant Backend
    participant Wallet

    Backend->>Frontend: 1. Challenge (SiwxMessage as text)
    Frontend->>Wallet: 2. personal_sign / signMessage
    Wallet-->>Frontend: 3. Signature bytes
    Frontend->>Backend: 4. Message text + Signature
    Backend->>Backend: 5. Parse → Validate → Verify
Loading

CAIP-122 Message Format

example.com wants you to sign in with your Ethereum account:
0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045

Sign in to Example

URI: https://example.com/login
Version: 1
Chain ID: 1
Nonce: L8s2Mf7kGxPQN9a4z
Issued At: 2024-01-01T00:00:00Z

Verifier Trait

Chain-specific crates implement the Verifier trait:

pub trait Verifier: Send + Sync {
    fn verify(
        &self,
        message: &SiwxMessage,
        signature: &[u8],
    ) -> impl Future<Output = Result<(), SiwxError>> + Send;
}
Verifier Crate Signature Type Async
Eip191Verifier siwx-evm ECDSA recovery (personal_sign) No
Eip1271Verifier siwx-evm Smart contract isValidSignature (RPC) Yes
EvmVerifier siwx-evm EIP-191 first, EIP-1271 fallback Yes
Ed25519Verifier siwx-svm Ed25519 No

Extending to New Chains

Implement Verifier for your target chain:

use siwx::{SiwxError, SiwxMessage, Verifier};

pub struct MyChainVerifier;

impl Verifier for MyChainVerifier {
    async fn verify(
        &self,
        message: &SiwxMessage,
        signature: &[u8],
    ) -> Result<(), SiwxError> {
        // Your chain-specific verification logic
        todo!()
    }
}

Features

Feature Crate Description
serde siwx Serialize / Deserialize for SiwxMessage

Related Standards

Standard Relationship
CAIP-122 Core specification — Sign-In with X abstract data model
CAIP-2 Blockchain ID format (namespace:reference)
CAIP-10 Account ID format (chain_id:account_address)
EIP-4361 Sign-In with Ethereum — the EVM namespace profile
EIP-191 Ethereum personal message signatures
EIP-1271 Smart contract signature validation

License

Licensed under either of:

at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project shall be dual-licensed as above, without any additional terms or conditions.


A QNTX open-source project.

QNTX

Code is law. We write both.

About

CAIP-122 wallet authentication SDK for Rust.

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Contributors