Authentication
Sign in with Ethereum (SIWE) — Better Auth session
Diffusal uses Better Auth with the SIWE (Sign-In with Ethereum) plugin for session management. Authentication is wallet-only and uses Better Auth's native two-step SIWE flow, which converges on a bearer token or session cookie used by every authenticated request.
For traders using the web app, authentication is handled automatically. For API integrators, market makers, and bot operators, the SIWE flow described below is the only programmatic option.
How It Works
SIWE (wallet signature)
│
▼
POST /api/auth/siwe/nonce
with walletAddress + chainId
│
▼
POST /api/auth/siwe/verify
with message + signature
│
▼
Better Auth Session Token
(Authorization: Bearer <token>
or better-auth.session_token cookie)
│
▼
Protected API Endpoints
/api/account/* /api/mm/* /api/portfolio/*Wallet Sign-In (SIWE)
SIWE proves wallet ownership without a password and is the only sign-in flow exposed by the API.
Step 1: Request a nonce
curl -X POST https://api.testnet.diffusal.xyz/api/auth/siwe/nonce \
-H 'Content-Type: application/json' \
-d '{"walletAddress": "0xYourAddress", "chainId": 10143}'Response:
{ "nonce": "a3f2c91d..." }Nonces expire after 5 minutes. Complete the sign-in flow before the TTL elapses.
Step 2: Build and sign the SIWE message
Construct a EIP-4361 SIWE message with the nonce from Step 1, then sign it with your wallet.
api.testnet.diffusal.xyz wants you to sign in with your Ethereum account:
0xYourAddress
Sign in to Diffusal
URI: https://api.testnet.diffusal.xyz
Version: 1
Chain ID: 10143
Nonce: a3f2c91d...
Issued At: 2026-01-01T00:00:00.000ZStep 3: Verify signature and receive session token
curl -X POST https://api.testnet.diffusal.xyz/api/auth/siwe/verify \
-H 'Content-Type: application/json' \
-d '{"message": "<SIWE_MESSAGE>", "signature": "0x...", "walletAddress": "0xYourAddress", "chainId": 10143}'Response:
{
"token": "3e9a7c12-4d5f-...",
"success": true,
"user": {
"id": "user_123",
"walletAddress": "0xYourAddress",
"chainId": 10143
}
}Store this token — you will attach it to every authenticated request.
Using Your Session Token
After authentication, attach the token to protected API calls using either method:
Bearer header (recommended for programmatic use):
curl https://api.testnet.diffusal.xyz/api/account/me \
-H 'Authorization: Bearer <token>'Session cookie (automatically set in browser flows):
Cookie: better-auth.session_token=<token>Session TTL: 7 days. After expiry, re-authenticate to obtain a new token.
Protected Endpoints
Once authenticated, you have access to:
| Endpoint Group | Description |
|---|---|
/api/account/* | Account info, profile |
/api/mm/* | Market maker orders and quotes |
/api/portfolio/* | Portfolio management |
/api/strategies/* | Multi-leg strategy execution |
Common Auth Errors
| HTTP Status | Message | Cause |
|---|---|---|
| 400 | Invalid SIWE message: no nonce | SIWE message is malformed or missing the nonce field |
| 400 | Domain mismatch: expected api.testnet.diffusal.xyz | The domain in your SIWE message does not match the API host |
| 401 | Invalid or expired nonce | Nonce was already used, or more than 5 minutes elapsed |
| 401 | Invalid SIWE signature | Signature does not match the signing address |
| 401 | Invalid or expired session | Bearer token not found in session store or session has expired |
Security Model
- Nonce-based replay protection — Each nonce is single-use and expires in 5 minutes
- Signed ownership proof via SIWE — The signature cryptographically binds the Ethereum address to the session
- Session validation on protected endpoints — Every request to protected routes validates the session token before execution