npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

auth-fingerprint

v1.0.24

Published

Secure fingerprint hashing, signing & integrated HTTP API client with timestamped verification for Node.js

Readme

📦 auth-fingerprint

Secure fingerprint hashing, signing & one-time verification for Node.js. Prevent replay attacks with timestamped signatures. 🔐


✨ Features

  • 🔑 HMAC-SHA256 based hashing & verification
  • ⏳ Timestamp included (expiry support)
  • 🚫 Time-based validation (replay protection)
  • 🖥 Works with any object: { ip, browser, os }
  • ⚡ Lightweight & dependency-free (only Node.js crypto)
  • 🪙 NEW: ERC-20 token operations (balance, transfer, deposit history)
  • 💰 NEW: Native ETH transactions with ethers.js integration
  • 🔗 NEW: Blockchain RPC utilities and helpers

📦 Installation

npm install auth-fingerprint

🎥 Tutorial Video

Watch our comprehensive tutorial to get started quickly with auth-fingerprint:

Auth-Fingerprint Tutorial

What you'll learn:

  • 🔧 Installation and setup
  • 🔑 Basic fingerprint hashing and verification
  • ✍️ Digital signature methods
  • 🌐 API authentication integration
  • 🛡️ Server-side verification
  • 💡 Real-world use cases and best practices

Duration: ~15 minutes | Beginner-friendly


🚀 Usage Examples

1. Basic Authentication Setup

const { 
  hashFingerprint, 
  verifyFingerprint, 
  signFingerprint, 
  verifySignature 
} = require("auth-fingerprint");

// Your secret key (store securely in environment variables)
const SECRET_KEY = process.env.AUTH_SECRET || "your-secure-secret-key";

// Device fingerprint from client request
const deviceFingerprint = {
  ip: "192.168.1.100",
  userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
  acceptLanguage: "en-US,en;q=0.9",
  screenResolution: "1920x1080"
};

2. Session Token Generation (Hash Method)

// Generate session token
function createSessionToken(userFingerprint) {
  const result = hashFingerprint(userFingerprint, SECRET_KEY);
  
  console.log("Session created:", {
    hash: result.hash.substring(0, 16) + "...",
    timestamp: new Date(result.timestamp).toISOString(),
    expiresIn: "1 minute"
  });
  
  return result;
}

const sessionToken = createSessionToken(deviceFingerprint);

3. Session Validation

// Validate session token
function validateSession(fingerprint, hash, timestamp) {
  const verification = verifyFingerprint(fingerprint, hash, timestamp, SECRET_KEY);
  
  if (verification.success) {
    console.log("✅ Session valid for user:", verification.data.ip);
    return { valid: true, user: verification.data };
  } else {
    console.log("❌ Session invalid:", verification.reason);
    return { valid: false, reason: verification.reason };
  }
}

// Test validation
const validation = validateSession(
  deviceFingerprint, 
  sessionToken.hash, 
  sessionToken.timestamp
);

4. Digital Signatures (Recommended)

// Create signed authentication payload
function createAuthPayload(userFingerprint, userId) {
  const payload = signFingerprint({
    ...userFingerprint,
    userId: userId,
    action: "login"
  }, SECRET_KEY);
  
  console.log("Auth payload created:", {
    userId: payload.fingerprint.userId,
    signature: payload.signature.substring(0, 16) + "...",
    timestamp: new Date(payload.timestamp).toISOString()
  });
  
  return payload;
}

// Verify signed payload
function verifyAuthPayload(signedPayload, customTolerance = 300000) { // 5 minutes
  const verification = verifySignature(signedPayload, SECRET_KEY, customTolerance);
  
  if (verification.success) {
    console.log("✅ Authentication successful for user:", verification.data.userId);
    return { authenticated: true, user: verification.data };
  } else {
    console.log("❌ Authentication failed:", verification.reason);
    return { authenticated: false, reason: verification.reason };
  }
}

// Example usage
const authPayload = createAuthPayload(deviceFingerprint, "user123");
const authResult = verifyAuthPayload(authPayload);

5. Express.js Middleware Integration

const express = require('express');
const app = express();

// Custom authentication middleware
function authMiddleware(req, res, next) {
  const authHeader = req.headers['x-auth-signature'];
  
  if (!authHeader) {
    return res.status(401).json({ error: 'Missing authentication' });
  }
  
  try {
    const payload = JSON.parse(Buffer.from(authHeader, 'base64').toString());
    const verification = verifySignature(payload, SECRET_KEY, 600000); // 10 minutes
    
    if (verification.success) {
      req.user = verification.data;
      next();
    } else {
      res.status(401).json({ error: 'Invalid authentication', reason: verification.reason });
    }
  } catch (error) {
    res.status(400).json({ error: 'Malformed authentication header' });
  }
}

// Protected route
app.get('/api/profile', authMiddleware, (req, res) => {
  res.json({
    message: 'Profile data',
    user: req.user.userId,
    loginTime: new Date(req.user.timestamp).toISOString()
  });
});

⚙️ API

hashFingerprint(fingerprint, secret)

Creates a timestamped hash of the fingerprint object.

Parameters:

  • fingerprint (object) - The fingerprint data (e.g. { ip, browser, os })
  • secret (string) - Secret key for HMAC signing

Returns:

  • { hash: string, timestamp: number } - Hash and timestamp

verifyFingerprint(fingerprint, hash, timestamp, secret, tolerance?)

Verifies a fingerprint hash with timestamp validation.

Parameters:

  • fingerprint (object) - Original fingerprint data
  • hash (string) - Hash to verify
  • timestamp (number) - Original timestamp
  • secret (string) - Same secret key used for hashing
  • tolerance (number, optional) - Validity window in ms (default: 60000 = 1 minute)

Returns:

  • { success: true, data: object } - If verification succeeds
  • { success: false, reason: "expired" | "mismatch" } - If verification fails

signFingerprint(fingerprint, secret)

Creates a signed payload with fingerprint, timestamp, and signature.

Parameters:

  • fingerprint (object) - The fingerprint data (e.g. { ip, browser, os })
  • secret (string) - Secret key for HMAC signing

Returns:

  • { fingerprint: object, timestamp: number, signature: string } - Complete signed payload

verifySignature(payload, secret, tolerance?)

Verifies a signed payload with timestamp validation.

Parameters:

  • payload (object) - Signed payload from signFingerprint
  • secret (string) - Same secret key used for signing
  • tolerance (number, optional) - Validity window in ms (default: 60000 = 1 minute)

Returns:

  • { success: true, data: object } - If verification succeeds
  • { success: false, reason: "expired" | "mismatch" } - If verification fails

🔐 Security Notes

  • Default expiry = 1 minute (2000ms)
  • Uses timing-safe comparison to prevent timing attacks
  • Deterministic serialization ensures consistent hashing
  • HMAC-SHA256 provides cryptographic security

🌐 Integrated API Client

The package includes api.js - a complete HTTP client with built-in fingerprint authentication:

Real-World API Authentication

const { API_CALL } = require('auth-fingerprint/api');
const { getDeviceFingerprint } = require('auth-fingerprint/api');

// E-commerce API example
class SecureAPIClient {
  constructor(baseURL, apiSecret) {
    this.baseURL = baseURL;
    this.apiSecret = apiSecret;
  }

  // Login with device fingerprinting
  async login(credentials, req) {
    const deviceFingerprint = getDeviceFingerprint(req);
    
    const response = await API_CALL({
      method: 'POST',
      url: '/auth/login',
      baseURL: this.baseURL,
      body: {
        ...credentials,
        deviceId: deviceFingerprint.ip + deviceFingerprint.userAgent
      },
      auth: {
        enabled: true,
        method: 'signature',
        secret: this.apiSecret,
        fingerprint: deviceFingerprint
      }
    });

    if (response.success) {
      console.log('✅ Login successful:', response.data.user);
      return response.data.token;
    } else {
      throw new Error('Login failed: ' + response.error);
    }
  }

  // Make authenticated requests
  async makeSecureRequest(endpoint, data, userFingerprint) {
    return await API_CALL({
      method: 'POST',
      url: endpoint,
      baseURL: this.baseURL,
      body: data,
      auth: {
        enabled: true,
        method: 'signature',
        secret: this.apiSecret,
        fingerprint: {
          ...userFingerprint,
          timestamp: Date.now()
        }
      },
      headers: {
        'Content-Type': 'application/json',
        'X-API-Version': '2.0'
      }
    });
  }

  // Get user profile with authentication
  async getUserProfile(userId, userFingerprint) {
    try {
      const response = await this.makeSecureRequest(
        `/users/${userId}/profile`,
        { action: 'get_profile' },
        userFingerprint
      );
      
      return response.data;
    } catch (error) {
      console.error('Profile fetch failed:', error.message);
      return null;
    }
  }

  // Update user settings
  async updateSettings(userId, settings, userFingerprint) {
    return await this.makeSecureRequest(
      `/users/${userId}/settings`,
      { settings, action: 'update_settings' },
      userFingerprint
    );
  }
}

// Usage example
const apiClient = new SecureAPIClient(
  'https://api.myapp.com',
  process.env.API_SECRET
);

// In your Express route
app.post('/login', async (req, res) => {
  try {
    const token = await apiClient.login(req.body, req);
    res.json({ success: true, token });
  } catch (error) {
    res.status(401).json({ error: error.message });
  }
});

Server-side Verification Middleware

const express = require('express');
const { 
  verifyRequestAuth, 
  verifyRequestSignature, 
  authMiddleware,
  getDeviceFingerprint 
} = require('auth-fingerprint/api');

const app = express();
app.use(express.json());

// Custom security middleware
function securityMiddleware(options = {}) {
  return (req, res, next) => {
    const fingerprint = getDeviceFingerprint(req);
    
    // Rate limiting by IP
    const rateLimitKey = `rate_limit_${fingerprint.ip}`;
    // Implement your rate limiting logic here
    
    // Device change detection
    if (req.session && req.session.lastFingerprint) {
      const lastDevice = req.session.lastFingerprint;
      if (lastDevice.userAgent !== fingerprint.userAgent) {
        console.log('⚠️ Device change detected for user');
        // Implement additional security measures
      }
    }
    
    req.deviceFingerprint = fingerprint;
    next();
  };
}

// Apply security middleware
app.use(securityMiddleware());

// Protected routes with different auth methods
app.use('/api/v1/secure', authMiddleware('signature'));
app.use('/api/v1/admin', authMiddleware('hash'));

// Secure endpoint example
app.post('/api/v1/secure/transfer', (req, res) => {
  const { amount, recipient } = req.body;
  const userDevice = req.authData;
  
  // Log security event
  console.log(`💰 Transfer request: ${amount} to ${recipient}`);
  console.log(`🔒 From device: ${userDevice.ip} - ${userDevice.userAgent}`);
  
  // Implement transfer logic with additional security checks
  if (amount > 1000) {
    // Require additional verification for large amounts
    return res.status(403).json({ 
      error: 'Large transfer requires additional verification',
      requiresVerification: true 
    });
  }
  
  res.json({ 
    success: true, 
    message: 'Transfer initiated',
    transactionId: 'tx_' + Date.now(),
    deviceVerified: true
  });
});

// Health check with device info
app.get('/api/health', (req, res) => {
  res.json({
    status: 'healthy',
    timestamp: new Date().toISOString(),
    device: req.deviceFingerprint
  });
});

app.listen(3000, () => {
  console.log('🚀 Secure API server running on port 3000');
});

📝 Real-World Use Cases

🏦 Banking & Financial Services

// Detect suspicious login attempts
function detectSuspiciousActivity(currentFingerprint, userHistory) {
  const lastKnownDevice = userHistory.lastDevice;
  
  const suspiciousFactors = {
    newLocation: currentFingerprint.ip !== lastKnownDevice.ip,
    newDevice: currentFingerprint.userAgent !== lastKnownDevice.userAgent,
    unusualTime: isUnusualLoginTime(new Date()),
    rapidRequests: checkRateLimit(currentFingerprint.ip)
  };
  
  const riskScore = Object.values(suspiciousFactors).filter(Boolean).length;
  
  if (riskScore >= 2) {
    return { requiresVerification: true, riskScore, factors: suspiciousFactors };
  }
  
  return { requiresVerification: false, riskScore };
}

🛒 E-commerce Security

// Prevent cart manipulation and session hijacking
function secureCheckout(cartData, userFingerprint, sessionToken) {
  // Verify session integrity
  const sessionValid = verifyFingerprint(
    userFingerprint, 
    sessionToken.hash, 
    sessionToken.timestamp, 
    process.env.SESSION_SECRET,
    1800000 // 30 minutes
  );
  
  if (!sessionValid.success) {
    throw new Error('Session expired or invalid');
  }
  
  // Additional cart validation
  const cartSignature = signFingerprint({
    ...userFingerprint,
    cartTotal: cartData.total,
    items: cartData.items.length
  }, process.env.CART_SECRET);
  
  return { sessionValid: true, cartSignature };
}

🏢 Enterprise API Gateway

// Microservices authentication
class ServiceAuthenticator {
  constructor(serviceSecret) {
    this.secret = serviceSecret;
  }
  
  // Generate service-to-service token
  generateServiceToken(serviceId, permissions) {
    return signFingerprint({
      serviceId,
      permissions,
      environment: process.env.NODE_ENV
    }, this.secret);
  }
  
  // Verify incoming service requests
  verifyServiceRequest(req) {
    const authHeader = req.headers['x-service-auth'];
    if (!authHeader) return { valid: false, reason: 'missing_auth' };
    
    try {
      const payload = JSON.parse(Buffer.from(authHeader, 'base64').toString());
      const verification = verifySignature(payload, this.secret, 300000); // 5 minutes
      
      return verification.success 
        ? { valid: true, service: verification.data }
        : { valid: false, reason: verification.reason };
    } catch (error) {
      return { valid: false, reason: 'invalid_format' };
    }
  }
}

📱 Mobile App Security

// Device binding for mobile apps
function bindDeviceToUser(userId, deviceInfo) {
  const deviceFingerprint = {
    deviceId: deviceInfo.uniqueId,
    platform: deviceInfo.platform,
    version: deviceInfo.version,
    model: deviceInfo.model
  };
  
  const deviceToken = signFingerprint({
    userId,
    ...deviceFingerprint,
    bindingTime: Date.now()
  }, process.env.DEVICE_SECRET);
  
  // Store device binding in database
  return {
    deviceToken,
    expiresAt: Date.now() + (30 * 24 * 60 * 60 * 1000) // 30 days
  };
}

🚀 Production Deployment Guide

1. Environment Setup

# Install the package
npm install auth-fingerprint

# Set environment variables
echo "AUTH_SECRET=your-super-secure-secret-key-here" >> .env
echo "API_SECRET=your-api-secret-key-here" >> .env
echo "NODE_ENV=production" >> .env

2. Production Server Setup

const express = require('express');
const helmet = require('helmet');
const rateLimit = require('express-rate-limit');
const { authMiddleware, getDeviceFingerprint } = require('auth-fingerprint/api');

const app = express();

// Security middleware
app.use(helmet());
app.use(express.json({ limit: '10mb' }));

// Rate limiting
const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100, // limit each IP to 100 requests per windowMs
  message: 'Too many requests from this IP'
});
app.use('/api/', limiter);

// Authentication middleware for different security levels
app.use('/api/public', (req, res, next) => next()); // No auth required
app.use('/api/protected', authMiddleware('signature')); // Standard auth
app.use('/api/admin', authMiddleware('hash')); // High security

// Health check
app.get('/health', (req, res) => {
  res.json({ 
    status: 'healthy', 
    timestamp: new Date().toISOString(),
    environment: process.env.NODE_ENV 
  });
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`🚀 Production server running on port ${PORT}`);
});

3. Client Integration Example

const { API_CALL } = require('auth-fingerprint/api');

// Authenticated API call with built-in fingerprint authentication
const response = await API_CALL({
  method: 'POST',
  url: '/secure/data',
  baseURL: 'https://api.example.com',
  body: { userId: 123 },
  auth: { enabled: true, method: 'signature' }
});

console.log('Response:', response.response);

📋 Complete API Reference

API_CALL Configuration

const response = await API_CALL({
  method: 'GET|POST|PUT|DELETE|PATCH',     // HTTP method
  url: '/endpoint',                        // API endpoint
  baseURL: 'https://api.example.com',      // Base URL
  body: { data: 'value' },                 // Request body
  headers: {                               // Custom headers
    'Authorization': 'Bearer token',
    'X-CSRF-Token': 'csrf-token'
  },
  params: { page: 1, limit: 10 },         // URL parameters
  auth: {                                  // Authentication config
    enabled: true,                         // Enable fingerprint auth
    method: 'signature',                   // 'hash' or 'signature'
    secret: 'custom-secret',               // Custom secret key
    fingerprint: { ip: '1.2.3.4' }        // Custom fingerprint
  }
});

🪙 Blockchain Operations (NEW)

ERC-20 Token Operations

Get ERC-20 Token Balance

const { getERC20Balance, formatTokenBalance } = require('auth-fingerprint/erc_20');

const rpcUrl = "https://eth.llamarpc.com";
const tokenAddress = "0x6982508145454Ce325dDbE47a25d4ec3d2311933"; // PEPE token
const walletAddress = "0x742d35Cc6634C0532925a3b8D0C9e3e0C0e0e0e0";

// Get raw balance
const balance = await getERC20Balance(rpcUrl, tokenAddress, walletAddress);
console.log("Raw balance:", balance);

// Format balance to human-readable format
const formattedBalance = formatTokenBalance(balance, 18); // 18 decimals
console.log("Formatted balance:", formattedBalance, "tokens");

Send ERC-20 Tokens

const { sendErc20, toBigInt } = require('auth-fingerprint/erc_20');

const rpcUrl = "https://eth-sepolia.api.onfinality.io/public";
const privateKey = "your-private-key";
const tokenAddress = "0xB9081a3d73A977F427d077953312762b9A10774B";
const recipient = "0x5875ed358C4a3Cd38eBf3f086454dbAC657aaDbA";
const amount = "1.5"; // 1.5 tokens
const decimals = 18;

// Send ERC-20 tokens
await sendErc20(rpcUrl, privateKey, tokenAddress, recipient, amount, decimals);

// Convert amount to BigInt manually
const amountInWei = toBigInt(amount, decimals);
console.log("Amount in smallest unit:", amountInWei.toString());

Get Deposit History

const { getDepositHistory } = require('auth-fingerprint/erc_20');

const tokenAddress = "0x6982508145454Ce325dDbE47a25d4ec3d2311933";
const walletAddress = "0x742d35Cc6634C0532925a3b8D0C9e3e0C0e0e0e0";
const rpcUrl = "https://eth.llamarpc.com";

// Get deposits from last 24 hours
const deposits = await getDepositHistory(tokenAddress, walletAddress, rpcUrl);

console.log("Recent deposits:");
deposits.forEach(deposit => {
  console.log({
    from: deposit.from,
    amount: formatTokenBalance(deposit.amount, 18),
    timestamp: deposit.timestamp,
    txHash: deposit.txHash
  });
});

Native ETH Operations

Send Native ETH

const { sendNativeToken } = require('auth-fingerprint/lib');

const rpcUrl = "https://eth-sepolia.api.onfinality.io/public";
const privateKey = "your-private-key";
const recipient = "0x5875ed358C4a3Cd38eBf3f086454dbAC657aaDbA";
const amount = "0.001"; // 0.001 ETH

// Send ETH
const result = await sendNativeToken(rpcUrl, privateKey, recipient, amount);

if (result.success) {
  console.log("Transaction sent! Hash:", result.hash);
  console.log("Confirmations:", result.confirmations);
} else {
  console.error("Transaction failed:", result.error);
}

Get Native ETH Balance

const { getNativeBalance, formatNativeBalance } = require('auth-fingerprint/lib');

const rpcUrl = "https://eth.llamarpc.com";
const walletAddress = "0x742d35Cc6634C0532925a3b8D0C9e3e0C0e0e0e0";

// Get balance in wei
const balanceWei = await getNativeBalance(rpcUrl, walletAddress);
console.log("Balance in wei:", balanceWei);

// Format to ETH
const balanceEth = formatNativeBalance(balanceWei);
console.log("Balance in ETH:", balanceEth);

Blockchain Utilities

Transaction Information

const { 
  getTransactionByHash, 
  getTransactionReceipt, 
  getBlockNumber 
} = require('auth-fingerprint/lib');

const rpcUrl = "https://eth.llamarpc.com";
const txHash = "0x1234567890abcdef1234567890abcdef12345678";

// Get transaction details
const tx = await getTransactionByHash(rpcUrl, txHash);
console.log("Transaction details:", {
  from: tx.from,
  to: tx.to,
  value: tx.value,
  gasPrice: tx.gasPrice,
  blockNumber: tx.blockNumber
});

// Get transaction receipt
const receipt = await getTransactionReceipt(rpcUrl, txHash);
console.log("Transaction receipt:", {
  status: receipt.status,
  gasUsed: receipt.gasUsed,
  logs: receipt.logs.length
});

// Get current block number
const blockNumber = await getBlockNumber(rpcUrl);
console.log("Current block:", parseInt(blockNumber, 16));

Complete DeFi Wallet Example

const { 
  sendErc20, 
  getERC20Balance, 
  formatTokenBalance,
  getDepositHistory 
} = require('auth-fingerprint/erc_20');
const { 
  sendNativeToken, 
  getNativeBalance, 
  formatNativeBalance 
} = require('auth-fingerprint/lib');

class DeFiWallet {
  constructor(rpcUrl, privateKey) {
    this.rpcUrl = rpcUrl;
    this.privateKey = privateKey;
    this.address = "0x742d35Cc6634C0532925a3b8D0C9e3e0C0e0e0e0"; // Derive from private key
  }

  // Get portfolio overview
  async getPortfolio() {
    try {
      // Get ETH balance
      const ethBalance = await getNativeBalance(this.rpcUrl, this.address);
      const ethFormatted = formatNativeBalance(ethBalance);

      // Get USDC balance (example token)
      const usdcAddress = "0xA0b86a33E6441c8C06DD2c5685E9B0B5B8e0e0e0";
      const usdcBalance = await getERC20Balance(this.rpcUrl, usdcAddress, this.address);
      const usdcFormatted = formatTokenBalance(usdcBalance, 6); // USDC has 6 decimals

      return {
        eth: { balance: ethFormatted, symbol: 'ETH' },
        usdc: { balance: usdcFormatted, symbol: 'USDC' },
        address: this.address
      };
    } catch (error) {
      console.error('Portfolio fetch failed:', error.message);
      return null;
    }
  }

  // Send tokens with validation
  async sendToken(tokenAddress, recipient, amount, decimals = 18) {
    try {
      // Validate token balance
      const balance = await getERC20Balance(this.rpcUrl, tokenAddress, this.address);
      const formattedBalance = formatTokenBalance(balance, decimals);
      
      if (parseFloat(formattedBalance) < parseFloat(amount)) {
        throw new Error(`Insufficient balance. Have: ${formattedBalance}, Need: ${amount}`);
      }

      // Validate ETH for gas
      const ethBalance = await getNativeBalance(this.rpcUrl, this.address);
      const ethFormatted = formatNativeBalance(ethBalance);
      
      if (parseFloat(ethFormatted) < 0.001) {
        throw new Error(`Insufficient ETH for gas. Have: ${ethFormatted} ETH`);
      }

      // Execute transfer
      console.log(`🚀 Sending ${amount} tokens to ${recipient}...`);
      const result = await sendErc20(
        this.rpcUrl, 
        this.privateKey, 
        tokenAddress, 
        recipient, 
        amount, 
        decimals
      );
      
      console.log('✅ Transfer successful!');
      return result;
    } catch (error) {
      console.error('❌ Transfer failed:', error.message);
      throw error;
    }
  }

  // Get transaction history
  async getTransactionHistory(tokenAddress) {
    try {
      const deposits = await getDepositHistory(tokenAddress, this.address, this.rpcUrl);
      
      return deposits.map(deposit => ({
        type: 'deposit',
        from: deposit.from,
        amount: formatTokenBalance(deposit.amount, 18),
        timestamp: new Date(deposit.timestamp * 1000).toISOString(),
        txHash: deposit.txHash
      }));
    } catch (error) {
      console.error('History fetch failed:', error.message);
      return [];
    }
  }
}

// Usage example
async function demoWallet() {
  const wallet = new DeFiWallet(
    "https://eth-sepolia.api.onfinality.io/public",
    "your-private-key"
  );

  // Get portfolio
  const portfolio = await wallet.getPortfolio();
  console.log('💼 Portfolio:', portfolio);

  // Send USDC tokens
  try {
    await wallet.sendToken(
      "0xA0b86a33E6441c8C06DD2c5685E9B0B5B8e0e0e0", // USDC
      "0x5875ed358C4a3Cd38eBf3f086454dbAC657aaDbA",
      "10.50",
      6 // USDC decimals
    );
  } catch (error) {
    console.error('Transfer error:', error.message);
  }

  // Get transaction history
  const history = await wallet.getTransactionHistory(
    "0xA0b86a33E6441c8C06DD2c5685E9B0B5B8e0e0e0"
  );
  console.log('📊 Recent transactions:', history);
}

// Run the demo
demoWallet();

4. Monitoring & Logging

const winston = require('winston');

// Security event logging
const securityLogger = winston.createLogger({
  level: 'info',
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.json()
  ),
  transports: [
    new winston.transports.File({ filename: 'security.log' }),
    new winston.transports.Console()
  ]
});

// Log authentication events
function logAuthEvent(event, req, success = true) {
  const fingerprint = getDeviceFingerprint(req);
  
  securityLogger.info({
    event,
    success,
    ip: fingerprint.ip,
    userAgent: fingerprint.userAgent,
    timestamp: new Date().toISOString(),
    endpoint: req.path
  });
}

// Usage in middleware
app.use('/api/protected', (req, res, next) => {
  const authResult = authMiddleware('signature')(req, res, () => {});
  logAuthEvent('authentication_attempt', req, !!req.authData);
  next();
});

🔧 Troubleshooting

Common Issues

1. "Authentication failed: expired" Error

// Increase tolerance for network delays
const verification = verifySignature(payload, secret, 120000); // 2 minutes

2. "Device fingerprint mismatch" Error

// Handle dynamic IPs and user agent changes
function flexibleFingerprint(req) {
  const base = getDeviceFingerprint(req);
  return {
    // Use more stable identifiers
    userAgent: base.userAgent.split(' ')[0], // Just browser name
    acceptLanguage: base.acceptLanguage,
    timezone: req.headers['x-timezone'] || 'UTC'
  };
}

3. High Memory Usage with Large Payloads

// Limit payload size and use streaming
app.use(express.json({ limit: '1mb' }));

// For large data, use hash-based verification instead of signatures
const result = hashFingerprint(smallFingerprint, secret);

📚 Additional Resources


📜 License

ISC © 2025 Md Rijon Hossain Jibon YT