Skip to main content

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.