Connection Modes
The SDK supports two ways to connect: Linked Mode and Standalone Mode.
Linked Mode
Derives your privacy keys from an EIP-712 signature. The user signs once with their existing wallet.
typescript
import { createWalletClient, custom } from 'viem';
const walletClient = createWalletClient({
chain: mainnet,
transport: custom(window.ethereum),
});
await client.connect({
mode: 'linked',
walletClient,
});How It Works
MetaMask Wallet
│
│ Signs EIP-712 message
▼
┌─────────────────┐
│ Signature │ ──────────────────────────────────────┐
└─────────────────┘ │
▼
┌───────────────────────────┐
│ spending_key = hash(sig) │
└───────────────────────────┘
│
┌────────────────────────────┼────────────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ viewing_key │ │ nullifying_key │ │ SPK │
└─────────────────┘ └─────────────────┘ └─────────────────┘Advantages
- No seed phrase backup - Keys are derived from wallet signature
- Familiar UX - Users just sign with MetaMask
- Deterministic - Same wallet always derives same keys
Limitations
- Requires connected wallet to use
- Wallet must support EIP-712 typed data signing
Standalone Mode
Direct key input without wallet connection. Best for scripts and services.
From Spending Key
typescript
await client.connect({
mode: 'standalone',
spendingKey: BigInt('0x1234...'),
});From Mnemonic
typescript
await client.connect({
mode: 'standalone',
mnemonic: 'word1 word2 word3 ... word12',
accountIndex: 0, // Optional, default 0
});Advantages
- Works in Node.js scripts
- No wallet popup required
- Can manage multiple accounts
Security Considerations
DANGER
Never expose spending keys in client-side code. Use standalone mode only in:
- Server-side scripts
- Secure backend services
- Development/testing
Switching Modes
You can disconnect and reconnect with a different mode:
typescript
// Start in linked mode
await client.connect({ mode: 'linked', walletClient });
// Later, switch to standalone
client.disconnect();
await client.connect({ mode: 'standalone', spendingKey: ... });Checking Connection State
typescript
// Check if connected
if (client.isConnected()) {
console.log('Address:', client.getAddress());
}
// Disconnect
client.disconnect();Session Persistence
The SDK does not persist keys automatically. You need to reconnect on page reload.
For linked mode, this just means re-signing. For standalone mode, you'd need to securely store and retrieve the key.
typescript
// On app load
if (savedSpendingKey) {
await client.connect({ mode: 'standalone', spendingKey: savedSpendingKey });
} else {
await client.connect({ mode: 'linked', walletClient });
}Multi-Account Support
Both modes support account indices for managing multiple identities:
typescript
// Linked mode - different signature per account
await client.connect({
mode: 'linked',
walletClient,
accountIndex: 1, // Second account
});
// Standalone mode - different derivation path
await client.connect({
mode: 'standalone',
mnemonic: '...',
accountIndex: 1,
});Each account index produces completely separate keys and addresses.