Security Best Practices
This guide covers essential security practices for using the SDK safely. The SDK supports two wallet modes with different security models.
Self-Custody Security
In self-custody mode (walletMode: 'local'), your private keys never leave your device:
Encryption
- KDF: PBKDF2-SHA512 with 600,000 iterations (exceeds OWASP 2024 recommendations) + random 32-byte salt
- Cipher: AES-256-GCM with random 12-byte IV and 16-byte auth tag
- Storage:
~/.loomlay/wallet.jsonwith0600permissions (owner read/write only) - Key zeroing: Private key buffers are zeroed immediately after signing
What Stays Local
- Encrypted seed phrase (in
~/.loomlay/wallet.json) - Passphrase (in-memory only, never written to disk)
- Transaction signing (decrypt → sign → zero → discard)
What Goes to the API
- Public wallet addresses (for balance lookups)
- Signed transactions (for submission to the blockchain)
- Never: private keys, seed phrases, or passphrases
Passphrase Management
The passphrase protects your encrypted wallet. Best practices:
# Recommended: Set as environment variable (avoids conversation logs)
export LOOMLAY_WALLET_PASSPHRASE=your-secure-passphrase// Or provide programmatically
const wallet = new OpenClawWallet({
apiKey: 'agent_xxx',
walletMode: 'local',
getPassphrase: async () => process.env.LOOMLAY_WALLET_PASSPHRASE!,
});If using the OpenClaw Plugin, set LOOMLAY_WALLET_PASSPHRASE as an environment variable to avoid your passphrase appearing in conversation logs.
Transaction Validation
Before signing any transaction locally, the SDK validates that the transaction's feePayer matches your local wallet address. This prevents signing malicious transactions that could drain your funds.
API Key Security
Never Commit Keys
# .gitignore
.env
.env.local
*.envNever commit API keys to version control. Even if you remove them later, they remain in git history.
Use Environment Variables
// Good: Load from environment
const wallet = new OpenClawWallet({
apiKey: process.env.LOOMLAY_API_KEY!,
});
// Bad: Hardcoded key
const wallet = new OpenClawWallet({
apiKey: 'agent_abc123...', // Never do this!
});One Key Per Application
Each API key should be used by only one application:
- Development environment: separate key
- Staging environment: separate key
- Production environment: separate key
Key Rotation
If you suspect a key is compromised:
- Generate a new key via the API
- Update your application with the new key
- Revoke the old key
// Generate new key
const newKey = await wallet.auth.createKey();
// After updating your app, revoke the old key
await wallet.auth.revokeKey({ keyId: 'old_key_id' });Seed Phrase Security
Your seed phrase is the master key to your wallet. Anyone with access to it can steal all your funds.
Storage Guidelines
- Never transmit seed phrases over the internet
- Never store in plain text files
- Never share with anyone, including support
- Store offline in a secure location (encrypted USB, hardware wallet, paper backup)
SDK Usage
The SDK only requires the seed phrase for key export:
// Seed phrase NOT needed for:
await wallet.wallet.get(); // Check balances
await wallet.trading.swap({...}); // Execute swaps
await wallet.trading.transfer({...}); // Send tokens
// Seed phrase ONLY needed for:
await wallet.wallet.exportKeys({
seedPhrase: 'your twelve word seed phrase',
});For Large Amounts
Consider using self-custody mode (walletMode: 'local') for maximum security. In custodial mode, the SDK-managed wallet stores keys server-side and is best suited for active trading amounts. For holdings above your risk tolerance, consider hardware wallet integration.
Transaction Safety
Verify Recipient Addresses
Always double-check addresses before transfers:
const recipient = '7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU';
// Verify address format
if (!recipient.match(/^[1-9A-HJ-NP-Za-km-z]{32,44}$/)) {
throw new Error('Invalid Solana address format');
}
await wallet.trading.transfer({
to: recipient,
token: 'USDC',
amount: '1000',
chain: 'solana',
});Quote Before Large Swaps
Always get a quote before executing large swaps:
// First, get a quote
const quote = await wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'USDC',
amount: '100',
quoteOnly: true,
});
console.log('Expected output:', quote.outputAmount);
console.log('Price impact:', quote.priceImpact, '%');
// Review the quote, then execute
if (quote.priceImpact < 1) {
const result = await wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'USDC',
amount: '100',
});
}Set Appropriate Slippage
// Default slippage is 0.5%
await wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'USDC',
amount: '10',
slippage: 0.5, // 0.5% - good for liquid pairs
});
// For volatile or low-liquidity tokens, you may need higher slippage
await wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'MEMECOIN',
amount: '1',
slippage: 3, // 3% - for volatile tokens
});Monitor Price Impact
High price impact indicates you're moving the market:
const quote = await wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'USDC',
amount: '1000',
quoteOnly: true,
});
if (quote.priceImpact > 2) {
console.warn('High price impact! Consider smaller trade size.');
}Environment Setup
Example .env File
# .env
# API key for LoomLay SDK
LOOMLAY_API_KEY=agent_your_key_here
# Optional: Seed phrase backup (only if you need key export)
# WARNING: Storing seed phrases in .env is risky
# Only do this if your server is highly secured
# LOOMLAY_SEED_PHRASE="word1 word2 word3 ..."Environment Validation
function validateEnv() {
const apiKey = process.env.LOOMLAY_API_KEY;
if (!apiKey) {
throw new Error('LOOMLAY_API_KEY is required');
}
if (!apiKey.startsWith('agent_')) {
throw new Error('Invalid API key format');
}
return { apiKey };
}
const { apiKey } = validateEnv();
const wallet = new OpenClawWallet({ apiKey });Production Checklist
Before deploying to production:
- API keys loaded from environment variables
-
.envfiles in.gitignore - Seed phrases stored securely offline
- Error handling for all API calls
- Rate limit handling implemented
- Transaction amounts validated before execution
- Slippage limits appropriate for token liquidity
- Self-custody mode enabled for sensitive deployments (
walletMode: 'local') -
LOOMLAY_WALLET_PASSPHRASEset via environment variable (not in code) -
~/.loomlay/wallet.jsonpermissions verified (0600)