@anders94/siwe
v1.0.0
Published
A lightweight Sign In With Ethereum TypeScript module.
Downloads
12
Readme
@anders94/siwe
A lightweight TypeScript implementation of Sign-In with Ethereum (EIP-4361).
Why this library?
Most SIWE implementations depend on heavy Ethereum libraries like ethers.js or viem. This library uses only @noble/secp256k1 and @noble/hashes for cryptographic operations, resulting in a much smaller bundle size for applications that don't need a full Ethereum library.
Installation
npm install @anders94/siweUsage
Creating a SIWE message
import { SiweMessage } from '@anders94/siwe';
const message = new SiweMessage({
domain: 'myapp.com',
address: '0x1234567890123456789012345678901234567890',
statement: 'Sign in to My App',
uri: 'https://myapp.com',
version: '1',
chainId: 1,
nonce: 'randomNonce123',
issuedAt: new Date().toISOString(),
expirationTime: new Date(Date.now() + 3600000).toISOString(), // optional
notBefore: new Date().toISOString(), // optional
requestId: 'request-123', // optional
resources: ['https://myapp.com/api'] // optional
});
// Get the message string to be signed
const messageString = message.prepareMessage();Parsing a SIWE message
import { SiweMessage } from '@anders94/siwe';
const messageString = `myapp.com wants you to sign in with your Ethereum account:
0x1234567890123456789012345678901234567890
Sign in to My App
URI: https://myapp.com
Version: 1
Chain ID: 1
Nonce: randomNonce123
Issued At: 2024-01-01T00:00:00.000Z`;
const message = SiweMessage.fromString(messageString);Validating a signature
import { SiweMessage } from '@anders94/siwe';
const message = new SiweMessage({
domain: 'myapp.com',
address: userAddress,
uri: 'https://myapp.com',
version: '1',
chainId: 1,
nonce: 'randomNonce123',
issuedAt: new Date().toISOString()
});
try {
// Validates signature and checks expiration/notBefore times
await message.validate(signature);
console.log('Signature valid!');
} catch (error) {
console.error('Validation failed:', error.message);
}Low-level signature verification
import { checkSignature } from '@anders94/siwe';
const isValid = await checkSignature(message, signature, expectedAddress);API
SiweMessage
Constructor Options
| Property | Type | Required | Description |
|----------|------|----------|-------------|
| domain | string | Yes | The domain requesting the sign-in |
| address | string | Yes | Ethereum address (0x-prefixed) |
| uri | string | Yes | URI of the resource |
| version | string | Yes | SIWE version (typically "1") |
| chainId | number | Yes | EIP-155 chain ID |
| nonce | string | Yes | Randomized token for replay protection |
| issuedAt | string | Yes | ISO 8601 timestamp |
| statement | string | No | Human-readable message |
| expirationTime | string | No | ISO 8601 expiration time |
| notBefore | string | No | ISO 8601 time before which message is invalid |
| requestId | string | No | Request identifier |
| resources | string[] | No | List of resource URIs |
Methods
prepareMessage(): string- Returns the EIP-4361 formatted message stringtoMessage(): string- Alias forprepareMessage()validate(signature: string): Promise<SiweMessage>- Validates signature and time constraintsstatic fromString(str: string): SiweMessage- Parses an EIP-4361 message string
checkSignature
function checkSignature(
message: string,
signature: string,
expectedAddress: string
): Promise<boolean>Low-level function to verify an Ethereum signature matches an expected address.
License
MIT
