Examples and Use Cases
Overview
This section provides complete, production-ready examples for common use cases with the Node.js SDK. Each example includes error handling, security considerations, and best practices.
AI Agent Examples
1. Autonomous Trading Bot
const { Web3Auth } = require('@web3auth/node-sdk')
const { ethers } = require('ethers')
class TradingBot {
constructor(config) {
this.web3auth = new Web3Auth({
clientId: config.clientId,
web3AuthNetwork: 'sapphire_mainnet',
})
this.config = config
this.wallet = null
this.provider = null
}
async initialize() {
await this.web3auth.init()
// Authenticate the bot
const provider = await this.web3auth.connect({
verifier: this.config.verifier,
verifierId: this.config.botId,
idToken: this.config.botToken,
})
// Set up wallet
const privateKey = await provider.request({ method: 'eth_private_key' })
this.wallet = new ethers.Wallet(privateKey)
this.provider = new ethers.providers.JsonRpcProvider(this.config.rpcUrl)
this.wallet = this.wallet.connect(this.provider)
console.log('Trading bot initialized:', this.wallet.address)
}
async executeTradeStrategy() {
try {
const balance = await this.wallet.getBalance()
console.log('Current balance:', ethers.utils.formatEther(balance), 'ETH')
// Example: Simple DEX swap logic
const shouldTrade = await this.analyzeMarket()
if (shouldTrade) {
await this.executeTrade(shouldTrade)
}
} catch (error) {
console.error('Trade execution failed:', error)
await this.handleTradingError(error)
}
}
async analyzeMarket() {
// Implement your trading logic here
// This is a simplified example
const price = await this.getCurrentPrice('ETH/USDC')
const trend = await this.getTrend()
return {
action: 'buy',
amount: '0.1',
token: 'USDC',
confidence: 0.8,
}
}
async executeTrade(tradeParams) {
console.log('Executing trade:', tradeParams)
// Example DEX interaction (Uniswap V3)
const uniswapRouter = new ethers.Contract(
'0xE592427A0AEce92De3Edee1F18E0157C05861564',
[
'function exactInputSingle((address,address,uint24,address,uint256,uint256,uint256,uint160)) external payable returns (uint256)',
],
this.wallet
)
const params = {
tokenIn: '0xA0b86a33E6441E51DBF5c4dF02a7b29fAdab0215', // USDC
tokenOut: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', // WETH
fee: 3000,
recipient: this.wallet.address,
deadline: Math.floor(Date.now() / 1000) + 600,
amountIn: ethers.utils.parseUnits(tradeParams.amount, 6),
amountOutMinimum: 0,
sqrtPriceLimitX96: 0,
}
const tx = await uniswapRouter.exactInputSingle(params)
await tx.wait()
console.log('Trade completed:', tx.hash)
}
async getCurrentPrice(pair) {
// Implement price fetching logic
return 2000 // Simplified
}
async getTrend() {
// Implement trend analysis
return 'bullish'
}
async handleTradingError(error) {
// Implement error handling and notifications
console.log('Notifying administrators of trading error')
}
}
// Usage
const bot = new TradingBot({
clientId: process.env.WEB3AUTH_CLIENT_ID,
verifier: 'trading-bot-verifier',
botId: 'bot-001',
botToken: process.env.BOT_JWT_TOKEN,
rpcUrl: 'https://rpc.ankr.com/eth',
})
await bot.initialize()
// Run trading loop
setInterval(async () => {
await bot.executeTradeStrategy()
}, 60000) // Every minute
2. DeFi Yield Farming Bot
class YieldFarmingBot {
constructor(config) {
this.web3auth = new Web3Auth(config.web3auth)
this.config = config
this.protocols = new Map() // Store protocol interfaces
}
async initialize() {
await this.web3auth.init()
const provider = await this.web3auth.connect({
verifier: this.config.verifier,
verifierId: this.config.botId,
idToken: this.config.botToken,
})
const privateKey = await provider.request({ method: 'eth_private_key' })
this.wallet = new ethers.Wallet(privateKey).connect(
new ethers.providers.JsonRpcProvider(this.config.rpcUrl)
)
// Initialize protocol interfaces
await this.initializeProtocols()
}
async initializeProtocols() {
// Compound
this.protocols.set('compound', {
comptroller: new ethers.Contract(
'0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B',
['function enterMarkets(address[] calldata cTokens) external returns (uint[] memory)'],
this.wallet
),
// Add other protocol contracts
})
// Aave
this.protocols.set('aave', {
lendingPool: new ethers.Contract(
'0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9',
[
'function deposit(address asset, uint256 amount, address onBehalfOf, uint16 referralCode)',
],
this.wallet
),
})
}
async optimizeYield() {
try {
// 1. Analyze current positions
const positions = await this.getCurrentPositions()
// 2. Find best yield opportunities
const opportunities = await this.scanYieldOpportunities()
// 3. Execute rebalancing if profitable
const rebalancePlan = this.calculateOptimalRebalance(positions, opportunities)
if (rebalancePlan.profitable) {
await this.executeRebalance(rebalancePlan)
}
} catch (error) {
console.error('Yield optimization failed:', error)
}
}
async getCurrentPositions() {
const positions = []
// Check Compound positions
// Check Aave positions
// Check Uniswap LP positions
return positions
}
async scanYieldOpportunities() {
const opportunities = []
// Scan lending rates
const compoundRate = await this.getCompoundAPY('USDC')
const aaveRate = await this.getAaveAPY('USDC')
opportunities.push(
{ protocol: 'compound', asset: 'USDC', apy: compoundRate },
{ protocol: 'aave', asset: 'USDC', apy: aaveRate }
)
return opportunities.sort((a, b) => b.apy - a.apy)
}
calculateOptimalRebalance(positions, opportunities) {
// Implement rebalancing logic
return {
profitable: true,
moves: [{ from: 'compound', to: 'aave', asset: 'USDC', amount: '1000' }],
expectedGain: 0.05, // 5% APY improvement
}
}
async executeRebalance(plan) {
for (const move of plan.moves) {
console.log(`Moving ${move.amount} ${move.asset} from ${move.from} to ${move.to}`)
// Withdraw from source
await this.withdrawFromProtocol(move.from, move.asset, move.amount)
// Deposit to destination
await this.depositToProtocol(move.to, move.asset, move.amount)
}
}
async getCompoundAPY(asset) {
// Implement Compound APY fetching
return 3.5 // 3.5% APY
}
async getAaveAPY(asset) {
// Implement Aave APY fetching
return 4.2 // 4.2% APY
}
}
Backend Service Examples
1. User Wallet Service
const express = require('express')
const { Web3Auth } = require('@web3auth/node-sdk')
class UserWalletService {
constructor() {
this.app = express()
this.userSessions = new Map()
this.setupMiddleware()
this.setupRoutes()
}
setupMiddleware() {
this.app.use(express.json())
this.app.use(this.authMiddleware.bind(this))
this.app.use(this.rateLimitMiddleware.bind(this))
}
async authMiddleware(req, res, next) {
if (req.path.startsWith('/api/public/')) {
return next()
}
const token = req.headers.authorization?.replace('Bearer ', '')
if (!token) {
return res.status(401).json({ error: 'Authentication required' })
}
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET)
req.user = decoded
next()
} catch (error) {
res.status(401).json({ error: 'Invalid token' })
}
}
rateLimitMiddleware(req, res, next) {
// Implement rate limiting
next()
}
setupRoutes() {
// Create wallet for user
this.app.post('/api/wallet/create', async (req, res) => {
try {
const userId = req.user.sub
const { email, name } = req.user
// Check if wallet already exists
if (this.userSessions.has(userId)) {
return res.status(400).json({ error: 'Wallet already exists' })
}
// Create Web3Auth instance for user
const web3auth = new Web3Auth({
clientId: process.env.WEB3AUTH_CLIENT_ID,
web3AuthNetwork: 'sapphire_mainnet',
})
await web3auth.init()
// Create JWT for user
const idToken = this.createJWTForUser(userId, email, name)
// Connect with Web3Auth
const provider = await web3auth.connect({
verifier: 'wallet-service-verifier',
verifierId: userId,
idToken: idToken,
})
// Get wallet address
const accounts = await provider.request({ method: 'eth_accounts' })
const address = accounts[0]
// Store session
this.userSessions.set(userId, {
web3auth,
provider,
address,
createdAt: new Date(),
})
res.json({
success: true,
address: address,
message: 'Wallet created successfully',
})
} catch (error) {
console.error('Wallet creation failed:', error)
res.status(500).json({ error: 'Failed to create wallet' })
}
})
// Get wallet info
this.app.get('/api/wallet/info', async (req, res) => {
try {
const userId = req.user.sub
const session = this.userSessions.get(userId)
if (!session) {
return res.status(404).json({ error: 'Wallet not found' })
}
// Get balance
const balance = await session.provider.request({
method: 'eth_getBalance',
params: [session.address, 'latest'],
})
res.json({
address: session.address,
balance: ethers.utils.formatEther(balance),
createdAt: session.createdAt,
})
} catch (error) {
console.error('Failed to get wallet info:', error)
res.status(500).json({ error: 'Failed to get wallet info' })
}
})
// Send transaction
this.app.post('/api/wallet/send', async (req, res) => {
try {
const userId = req.user.sub
const { to, amount, data } = req.body
const session = this.userSessions.get(userId)
if (!session) {
return res.status(404).json({ error: 'Wallet not found' })
}
// Validate transaction
if (!ethers.utils.isAddress(to)) {
return res.status(400).json({ error: 'Invalid recipient address' })
}
// Create transaction
const tx = {
to: to,
value: ethers.utils.parseEther(amount),
data: data || '0x',
}
// Sign and send transaction
const txHash = await session.provider.request({
method: 'eth_sendTransaction',
params: [tx],
})
res.json({
success: true,
transactionHash: txHash,
message: 'Transaction sent successfully',
})
} catch (error) {
console.error('Transaction failed:', error)
res.status(500).json({ error: 'Transaction failed' })
}
})
// Sign message
this.app.post('/api/wallet/sign', async (req, res) => {
try {
const userId = req.user.sub
const { message } = req.body
const session = this.userSessions.get(userId)
if (!session) {
return res.status(404).json({ error: 'Wallet not found' })
}
const signature = await session.provider.request({
method: 'personal_sign',
params: [message, session.address],
})
res.json({
signature: signature,
message: message,
address: session.address,
})
} catch (error) {
console.error('Message signing failed:', error)
res.status(500).json({ error: 'Failed to sign message' })
}
})
// Delete wallet
this.app.delete('/api/wallet', async (req, res) => {
try {
const userId = req.user.sub
const session = this.userSessions.get(userId)
if (session) {
// Stateless SDK - no logout needed, just remove from memory
this.userSessions.delete(userId)
}
res.json({
success: true,
message: 'Wallet deleted successfully',
})
} catch (error) {
console.error('Wallet deletion failed:', error)
res.status(500).json({ error: 'Failed to delete wallet' })
}
})
}
createJWTForUser(userId, email, name) {
const payload = {
iss: process.env.JWT_ISSUER,
aud: process.env.WEB3AUTH_CLIENT_ID,
sub: userId,
email: email,
name: name,
iat: Math.floor(Date.now() / 1000),
exp: Math.floor(Date.now() / 1000) + 3600,
}
return jwt.sign(payload, process.env.JWT_SECRET)
}
start(port = 3000) {
this.app.listen(port, () => {
console.log(`User wallet service running on port ${port}`)
})
}
}
// Usage
const walletService = new UserWalletService()
walletService.start()
2. Multi-Chain Portfolio Manager
class PortfolioManager {
constructor(config) {
this.config = config
this.chains = new Map()
this.web3auth = new Web3Auth(config.web3auth)
}
async initialize() {
await this.web3auth.init()
// Initialize multiple chains
const chainConfigs = [
{ id: '0x1', name: 'Ethereum', rpc: 'https://rpc.ankr.com/eth' },
{ id: '0x89', name: 'Polygon', rpc: 'https://rpc.ankr.com/polygon' },
{ id: '0x38', name: 'BSC', rpc: 'https://bsc-dataseed.binance.org' },
]
for (const chain of chainConfigs) {
await this.initializeChain(chain)
}
}
async initializeChain(chainConfig) {
// Connect to chain
const provider = await this.web3auth.connect({
verifier: this.config.verifier,
verifierId: this.config.userId,
idToken: this.config.userToken,
chainId: chainConfig.id,
})
const privateKey = await provider.request({ method: 'eth_private_key' })
const wallet = new ethers.Wallet(privateKey).connect(
new ethers.providers.JsonRpcProvider(chainConfig.rpc)
)
this.chains.set(chainConfig.id, {
config: chainConfig,
provider,
wallet,
})
}
async getPortfolioSummary() {
const summary = {
totalValue: 0,
chains: {},
tokens: {},
}
for (const [chainId, chain] of this.chains) {
const chainSummary = await this.getChainSummary(chainId)
summary.chains[chainId] = chainSummary
summary.totalValue += chainSummary.totalValue
}
return summary
}
async getChainSummary(chainId) {
const chain = this.chains.get(chainId)
const summary = {
name: chain.config.name,
nativeBalance: 0,
tokens: [],
totalValue: 0,
}
// Get native token balance
const balance = await chain.wallet.getBalance()
summary.nativeBalance = parseFloat(ethers.utils.formatEther(balance))
// Get token balances (implement token detection)
const tokens = await this.getTokenBalances(chainId)
summary.tokens = tokens
// Calculate total value (implement price fetching)
summary.totalValue = await this.calculateChainValue(summary)
return summary
}
async getTokenBalances(chainId) {
// Implement token balance fetching
// This would integrate with token lists and balance checkers
return []
}
async calculateChainValue(chainSummary) {
// Implement value calculation with price feeds
return chainSummary.nativeBalance * 2000 // Simplified
}
async rebalancePortfolio(targetAllocations) {
// Implement cross-chain rebalancing logic
for (const allocation of targetAllocations) {
console.log(`Rebalancing ${allocation.asset} to ${allocation.percentage}%`)
// Execute rebalancing trades
}
}
}
Production Deployment Example
Docker Configuration
# Dockerfile
FROM node:18-alpine
WORKDIR /app
# Copy package files
COPY package*.json ./
RUN npm ci --only=production
# Copy source code
COPY src/ ./src/
# Create non-root user
RUN addgroup -g 1001 -S nodejs
RUN adduser -S web3auth -u 1001
USER web3auth
EXPOSE 3000
CMD ["node", "src/index.js"]
Environment Configuration
# docker-compose.yml
version: '3.8'
services:
web3auth-service:
build: .
ports:
- '3000:3000'
environment:
- NODE_ENV=production
- WEB3AUTH_CLIENT_ID=${WEB3AUTH_CLIENT_ID}
- JWT_SECRET=${JWT_SECRET}
- JWT_ISSUER=${JWT_ISSUER}
- REDIS_URL=${REDIS_URL}
depends_on:
- redis
restart: unless-stopped
redis:
image: redis:7-alpine
ports:
- '6379:6379'
volumes:
- redis_data:/data
restart: unless-stopped
volumes:
redis_data:
Kubernetes Deployment
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web3auth-service
spec:
replicas: 3
selector:
matchLabels:
app: web3auth-service
template:
metadata:
labels:
app: web3auth-service
spec:
containers:
- name: web3auth-service
image: your-registry/web3auth-service:latest
ports:
- containerPort: 3000
env:
- name: WEB3AUTH_CLIENT_ID
valueFrom:
secretKeyRef:
name: web3auth-secrets
key: client-id
- name: JWT_SECRET
valueFrom:
secretKeyRef:
name: web3auth-secrets
key: jwt-secret
resources:
requests:
memory: '256Mi'
cpu: '250m'
limits:
memory: '512Mi'
cpu: '500m'
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 5
periodSeconds: 5
Monitoring and Observability
const promClient = require('prom-client')
class Web3AuthMetrics {
constructor() {
// Create metrics
this.authAttempts = new promClient.Counter({
name: 'web3auth_authentication_attempts_total',
help: 'Total number of authentication attempts',
labelNames: ['status', 'verifier'],
})
this.authDuration = new promClient.Histogram({
name: 'web3auth_authentication_duration_seconds',
help: 'Duration of authentication attempts',
labelNames: ['verifier'],
})
this.activeConnections = new promClient.Gauge({
name: 'web3auth_active_connections',
help: 'Number of active Web3Auth connections',
})
// Register default metrics
promClient.register.setDefaultLabels({
app: 'web3auth-service',
version: process.env.APP_VERSION || '1.0.0',
})
promClient.collectDefaultMetrics()
}
recordAuthAttempt(status, verifier) {
this.authAttempts.inc({ status, verifier })
}
recordAuthDuration(duration, verifier) {
this.authDuration.observe({ verifier }, duration)
}
setActiveConnections(count) {
this.activeConnections.set(count)
}
getMetrics() {
return promClient.register.metrics()
}
}
// Usage in your service
const metrics = new Web3AuthMetrics()
// In your authentication handler
const startTime = Date.now()
try {
const provider = await web3auth.connect(loginParams)
metrics.recordAuthAttempt('success', loginParams.verifier)
} catch (error) {
metrics.recordAuthAttempt('failure', loginParams.verifier)
} finally {
const duration = (Date.now() - startTime) / 1000
metrics.recordAuthDuration(duration, loginParams.verifier)
}
These examples provide a solid foundation for implementing the Web3Auth Node.js SDK in various production scenarios. Each example includes error handling, security considerations, and monitoring capabilities essential for backend services.