From 5dbec74a1ef9991acad84fc96ef8120b051b12f1 Mon Sep 17 00:00:00 2001
From: Yashovardhan Agrawal <21066442+yashovardhan@users.noreply.github.com>
Date: Thu, 11 Sep 2025 14:28:36 +0400
Subject: [PATCH 1/3] temp
---
embedded-wallets/sdk/node/README.mdx | 483 +++++++++++
embedded-wallets/sdk/node/examples.mdx | 799 ++++++++++++++++++
embedded-wallets/sdk/node/usage/README.mdx | 102 +++
embedded-wallets/sdk/node/usage/connect.mdx | 482 +++++++++++
.../sdk/node/usage/evm-integration.mdx | 433 ++++++++++
.../sdk/node/usage/private-key.mdx | 316 +++++++
src/components/EWSDKCards/index.tsx | 21 +
7 files changed, 2636 insertions(+)
create mode 100644 embedded-wallets/sdk/node/README.mdx
create mode 100644 embedded-wallets/sdk/node/examples.mdx
create mode 100644 embedded-wallets/sdk/node/usage/README.mdx
create mode 100644 embedded-wallets/sdk/node/usage/connect.mdx
create mode 100644 embedded-wallets/sdk/node/usage/evm-integration.mdx
create mode 100644 embedded-wallets/sdk/node/usage/private-key.mdx
diff --git a/embedded-wallets/sdk/node/README.mdx b/embedded-wallets/sdk/node/README.mdx
new file mode 100644
index 00000000000..40b48b83a05
--- /dev/null
+++ b/embedded-wallets/sdk/node/README.mdx
@@ -0,0 +1,483 @@
+---
+title: Embedded Wallets SDK for Node.js
+sidebar_label: Getting Started
+description: 'MetaMask Embedded Wallets SDK for Node.js | Backend Documentation'
+---
+
+import TabItem from '@theme/TabItem'
+import Tabs from '@theme/Tabs'
+import SdkTroubleshootingIntro from '../_common/_sdk-troubleshooting-intro.mdx'
+
+## Overview
+
+The MetaMask Embedded Wallets Node.js SDK (formerly Web3Auth Node SDK) is a backend solution designed for server-side authentication and key management. This SDK enables seamless integration of Web3 authentication into backend applications, AI agents, and programmatic use cases.
+
+Unlike frontend SDKs, the Node.js SDK is **stateless and sessionless**, making it ideal for:
+
+- Backend AI agents
+- Server-side wallet operations
+- Programmatic blockchain interactions
+- Custodial wallet services
+
+## Key Features
+
+- **Stateless Architecture**: No session management required
+- **Multi-Chain Support**: EVM chains, Solana, and other blockchains
+- **Custom Authentication**: Mandatory custom auth with single key share
+- **Private Key Access**: Direct access to private keys for any blockchain
+- **Backend-Optimized**: Designed specifically for server environments
+
+## Requirements
+
+- Node.js 18+
+- Custom authentication setup (mandatory)
+- Web3Auth Dashboard project configuration
+
+## Installation
+
+Install the Web3Auth Node SDK and required providers:
+
+```bash npm2yarn
+npm install --save @web3auth/node-sdk
+```
+
+### Additional Dependencies
+
+For blockchain providers:
+
+```bash npm2yarn
+# For EVM chains (Ethereum, Polygon, etc.)
+npm install --save @web3auth/ethereum-provider
+
+# For Solana blockchain
+npm install --save @web3auth/solana-provider
+
+# Base package for types
+npm install --save @web3auth/base
+```
+
+## Setup
+
+:::info Prerequisites
+
+Before you start, make sure you have:
+
+1. Registered on the [**Web3Auth Dashboard**](https://dashboard.web3auth.io/)
+2. Set up a project with **custom authentication** (mandatory for Node.js SDK)
+3. Configured your custom verifier settings
+
+You can refer to the [Dashboard Setup](/embedded-wallets/dashboard/) guide to learn more.
+
+:::
+
+### 1. Custom Verifier Setup (Required)
+
+The Node.js SDK **only supports custom authentication**. You must create a custom verifier in the Web3Auth Dashboard:
+
+1. Go to [Web3Auth Dashboard](https://dashboard.web3auth.io/)
+2. Select your project
+3. Navigate to **Auth Connectors** → **Custom Authentication**
+4. Click **Create Verifier**
+5. Configure your verifier with these settings:
+
+```json
+{
+ "name": "my-backend-verifier",
+ "description": "Custom verifier for Node.js backend",
+ "verifierType": "custom",
+ "clientId": "your-auth-client-id",
+ "issuer": "https://your-auth-domain.com",
+ "jwks_endpoint": "https://your-auth-domain.com/.well-known/jwks.json"
+}
+```
+
+### 2. JWT Token Requirements
+
+Your authentication system must generate JWT tokens with these required claims:
+
+```json
+{
+ "iss": "https://your-auth-domain.com", // Issuer (must match verifier)
+ "aud": "your-web3auth-client-id", // Audience
+ "sub": "user-unique-identifier", // Subject (user ID)
+ "iat": 1640995200, // Issued at
+ "exp": 1641081600, // Expiration
+ "email": "user@example.com", // User email (optional)
+ "name": "John Doe" // User name (optional)
+}
+```
+
+### 3. Provider Configuration
+
+Configure the blockchain provider for your target network:
+
+```javascript
+const { Web3Auth } = require('@web3auth/node-sdk')
+const { EthereumPrivateKeyProvider } = require('@web3auth/ethereum-provider')
+
+// Configure Ethereum provider
+const privateKeyProvider = new EthereumPrivateKeyProvider({
+ config: {
+ chainConfig: {
+ chainNamespace: 'eip155',
+ chainId: '0x1', // Ethereum Mainnet
+ rpcTarget: 'https://rpc.ankr.com/eth',
+ displayName: 'Ethereum Mainnet',
+ blockExplorerUrl: 'https://etherscan.io/',
+ ticker: 'ETH',
+ tickerName: 'Ethereum',
+ },
+ },
+})
+```
+
+### 4. SDK Configuration
+
+Create a Web3Auth instance with your client ID, network configuration, and provider:
+
+```javascript
+const web3auth = new Web3Auth({
+ clientId: 'YOUR_CLIENT_ID', // Get your Client ID from Web3Auth Dashboard
+ web3AuthNetwork: 'sapphire_mainnet', // or 'sapphire_devnet'
+ privateKeyProvider,
+})
+```
+
+### 5. Initialize Web3Auth
+
+Initialize the Web3Auth instance during your application startup:
+
+```javascript
+await web3auth.init()
+```
+
+### 6. Authenticate Users
+
+Use the connect method with your custom authentication parameters:
+
+```javascript
+const provider = await web3auth.connect({
+ verifier: 'YOUR_VERIFIER_NAME', // Your custom verifier name
+ verifierId: 'USER_VERIFIER_ID', // User's unique identifier
+ idToken: 'USER_ID_TOKEN', // JWT token from your auth system
+})
+```
+
+## Configuration Options
+
+
+
+
+
+```javascript
+const { Web3Auth } = require('@web3auth/node-sdk')
+
+const web3auth = new Web3Auth({
+ clientId: 'YOUR_CLIENT_ID',
+ web3AuthNetwork: 'sapphire_mainnet', // or 'sapphire_devnet'
+})
+
+await web3auth.init()
+```
+
+
+
+
+
+```javascript
+const { Web3Auth } = require('@web3auth/node-sdk')
+const { EthereumPrivateKeyProvider } = require('@web3auth/ethereum-provider')
+
+// Configure provider
+const privateKeyProvider = new EthereumPrivateKeyProvider({
+ config: {
+ chainConfig: {
+ chainNamespace: 'eip155',
+ chainId: process.env.CHAIN_ID || '0x1',
+ rpcTarget: process.env.RPC_URL || 'https://rpc.ankr.com/eth',
+ displayName: 'Ethereum',
+ blockExplorerUrl: 'https://etherscan.io/',
+ ticker: 'ETH',
+ tickerName: 'Ethereum',
+ },
+ },
+})
+
+// Production configuration
+const web3auth = new Web3Auth({
+ clientId: process.env.WEB3AUTH_CLIENT_ID,
+ web3AuthNetwork: process.env.NODE_ENV === 'production' ? 'sapphire_mainnet' : 'sapphire_devnet',
+ privateKeyProvider,
+})
+
+await web3auth.init()
+```
+
+
+
+
+
+```javascript
+// Provider configuration
+const privateKeyProvider = new EthereumPrivateKeyProvider({
+ config: {
+ chainConfig: {
+ chainNamespace: 'eip155',
+ chainId: '0x1',
+ rpcTarget: 'https://rpc.ankr.com/eth',
+ displayName: 'Ethereum',
+ blockExplorerUrl: 'https://etherscan.io/',
+ ticker: 'ETH',
+ tickerName: 'Ethereum',
+ },
+ },
+})
+
+// Development
+const devConfig = {
+ clientId: 'dev-client-id',
+ web3AuthNetwork: 'sapphire_devnet',
+ privateKeyProvider,
+}
+
+// Production
+const prodConfig = {
+ clientId: process.env.WEB3AUTH_CLIENT_ID,
+ web3AuthNetwork: 'sapphire_mainnet',
+ privateKeyProvider,
+}
+
+// Testing
+const testConfig = {
+ clientId: 'test-client-id',
+ web3AuthNetwork: 'sapphire_devnet',
+ privateKeyProvider,
+}
+
+const web3auth = new Web3Auth(process.env.NODE_ENV === 'production' ? prodConfig : devConfig)
+```
+
+
+
+
+
+## Configuration Parameters
+
+### Web3Auth Configuration
+
+| Parameter | Type | Default | Description |
+| -------------------- | -------- | -------- | --------------------------------------------------- |
+| `clientId` | `string` | Required | Your Web3Auth client ID |
+| `web3AuthNetwork` | `string` | Required | Network: 'sapphire_mainnet' or 'sapphire_devnet' |
+| `privateKeyProvider` | `object` | Required | Blockchain provider configuration (Ethereum/Solana) |
+
+### Provider Configuration Parameters
+
+| Parameter | Type | Description |
+| ------------------ | -------- | ------------------------------------------------------- |
+| `chainNamespace` | `string` | Blockchain namespace ('eip155' for EVM, 'solana') |
+| `chainId` | `string` | Chain ID (e.g., '0x1' for Ethereum, '0x89' for Polygon) |
+| `rpcTarget` | `string` | RPC endpoint URL for blockchain communication |
+| `displayName` | `string` | Human-readable chain name |
+| `blockExplorerUrl` | `string` | Block explorer URL for the chain |
+| `ticker` | `string` | Native token symbol (e.g., 'ETH', 'SOL') |
+| `tickerName` | `string` | Full name of the native token |
+
+## Best Practices
+
+### Environment Variables
+
+Store sensitive configuration in environment variables:
+
+```bash
+# .env file
+WEB3AUTH_CLIENT_ID=your_client_id_here
+WEB3AUTH_NETWORK=sapphire_mainnet
+SESSION_TIMEOUT=3600
+ENABLE_LOGGING=false
+```
+
+### Configuration Validation
+
+```javascript
+function validateConfig(config) {
+ if (!config.clientId) {
+ throw new Error('Client ID is required')
+ }
+
+ if (!['sapphire_mainnet', 'sapphire_devnet'].includes(config.web3AuthNetwork)) {
+ throw new Error('Invalid Web3Auth network')
+ }
+
+ if (config.sessionTime < 300) {
+ throw new Error('Session time must be at least 5 minutes')
+ }
+
+ return config
+}
+
+const config = validateConfig({
+ clientId: process.env.WEB3AUTH_CLIENT_ID,
+ web3AuthNetwork: process.env.WEB3AUTH_NETWORK,
+ sessionTime: parseInt(process.env.SESSION_TIMEOUT),
+})
+```
+
+### Dynamic Configuration Manager
+
+```javascript
+class Web3AuthConfigManager {
+ constructor() {
+ this.config = this.loadConfig()
+ }
+
+ loadConfig() {
+ const baseConfig = {
+ clientId: process.env.WEB3AUTH_CLIENT_ID,
+ web3AuthNetwork: process.env.WEB3AUTH_NETWORK || 'sapphire_devnet',
+ usePnPKey: false,
+ }
+
+ // Environment-specific overrides
+ switch (process.env.NODE_ENV) {
+ case 'production':
+ return {
+ ...baseConfig,
+ enableLogging: false,
+ sessionTime: 86400,
+ }
+ case 'staging':
+ return {
+ ...baseConfig,
+ enableLogging: true,
+ sessionTime: 3600,
+ }
+ default:
+ return {
+ ...baseConfig,
+ enableLogging: true,
+ sessionTime: 1800,
+ }
+ }
+ }
+
+ getConfig() {
+ return this.config
+ }
+
+ updateConfig(updates) {
+ this.config = { ...this.config, ...updates }
+ }
+}
+
+// Usage
+const configManager = new Web3AuthConfigManager()
+const web3auth = new Web3Auth(configManager.getConfig())
+```
+
+## Blockchain Integration
+
+Web3Auth Node SDK supports multiple blockchain networks through different integration methods:
+
+### EVM Chains (Ethereum, Polygon, BSC, etc.)
+
+Use the provider with ethers.js or convert to viem:
+
+```javascript
+// With ethers.js
+const { ethers } = require('ethers')
+const ethProvider = new ethers.providers.Web3Provider(provider)
+const signer = ethProvider.getSigner()
+
+// Get private key directly
+const privateKey = await provider.request({ method: 'eth_private_key' })
+```
+
+### Solana Integration
+
+Access Solana wallet functionality:
+
+```javascript
+// Get Solana account info
+const solanaWallet = await provider.request({ method: 'solanaWallet' })
+const publicKey = solanaWallet.publicKey
+
+// Get private key for Solana
+const privateKey = await provider.request({ method: 'solanaPrivateKey' })
+```
+
+### Other Blockchains
+
+Access the raw private key for any blockchain integration:
+
+```javascript
+// Get the raw private key
+const privateKey = await provider.request({ method: 'private_key' })
+
+// Use with your preferred blockchain library
+// Example: Bitcoin, Cosmos, etc.
+```
+
+## Key Features
+
+### Custom Authentication Only
+
+The Node.js SDK **only supports custom authentication**. You must:
+
+1. Set up a custom verifier in the Web3Auth Dashboard
+2. Configure your authentication flow
+3. Generate valid ID tokens for users
+4. Use the verifier name and ID token in the connect method
+
+### Single Key Share
+
+The SDK operates with a single key share, making it:
+
+- **Custodial**: You have direct access to user private keys
+- **Stateless**: No session state management required
+- **Backend-optimized**: Perfect for server-side operations
+
+### Private Key Export
+
+Private key export can be controlled through the Web3Auth Dashboard:
+
+- Enable/disable private key export
+- Control which methods return private keys
+- Set up additional security measures
+
+## Security Considerations
+
+### Client ID Protection
+
+- Store client ID in environment variables
+- Use different client IDs for different environments
+- Rotate client IDs regularly in production
+
+### Network Configuration
+
+- Use `sapphire_mainnet` for production
+- Use `sapphire_devnet` for development and testing
+- Never use mainnet for testing
+
+### Session Management
+
+- Set appropriate session timeouts
+- Implement session cleanup
+- Monitor for unusual session patterns
+
+## Next Steps
+
+- **[Usage Guide](./usage)**: Learn about stateless authentication and blockchain operations
+- **[Connect Method](./usage/connect)**: Detailed authentication implementation
+- **[Private Key Access](./usage/private-key)**: Extract keys for blockchain operations
+- **[EVM Integration](./usage/evm-integration)**: Ethereum and EVM-compatible chains
+- **[Examples](./examples)**: Complete implementation examples and production patterns
+
+
diff --git a/embedded-wallets/sdk/node/examples.mdx b/embedded-wallets/sdk/node/examples.mdx
new file mode 100644
index 00000000000..19ae77adfa0
--- /dev/null
+++ b/embedded-wallets/sdk/node/examples.mdx
@@ -0,0 +1,799 @@
+---
+title: Examples and Use Cases
+description: 'Complete examples and use cases for the MetaMask Embedded Wallets Node.js SDK'
+---
+
+## 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
+
+```javascript
+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
+
+```javascript
+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
+
+```javascript
+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
+
+```javascript
+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
+# 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
+
+```yaml
+# 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
+
+```yaml
+# 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
+
+```javascript
+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.
diff --git a/embedded-wallets/sdk/node/usage/README.mdx b/embedded-wallets/sdk/node/usage/README.mdx
new file mode 100644
index 00000000000..d85f92c634d
--- /dev/null
+++ b/embedded-wallets/sdk/node/usage/README.mdx
@@ -0,0 +1,102 @@
+---
+title: Node.js SDK Usage
+sidebar_label: Overview
+description: 'Learn how to use the MetaMask Embedded Wallets Node.js SDK'
+---
+
+## Usage Overview
+
+The MetaMask Embedded Wallets Node.js SDK provides stateless authentication and blockchain operations for backend applications. Unlike frontend SDKs, this is designed for **per-request authentication** without persistent sessions.
+
+## Core Methods
+
+### Authentication & Connection
+
+- **[connect](./connect)** - Authenticate users and establish provider connection (stateless)
+
+### Blockchain Operations
+
+- **[Private Key Access](./private-key)** - Extract private keys for blockchain operations
+- **[EVM Integration](./evm-integration)** - Work with Ethereum and EVM-compatible chains
+
+## Important Notes
+
+### Stateless Design
+
+The Node.js SDK is **stateless** and **sessionless** by design:
+
+- No persistent user sessions
+- No `getUserInfo()` or `logout()` methods
+- Each request requires re-authentication
+- Perfect for backend APIs and microservices
+
+## Common Usage Pattern
+
+The typical flow when using the Node.js SDK:
+
+```javascript
+const { Web3Auth } = require('@web3auth/node-sdk')
+const { EthereumPrivateKeyProvider } = require('@web3auth/ethereum-provider')
+
+// 1. Configure provider (once, during app startup)
+const privateKeyProvider = new EthereumPrivateKeyProvider({
+ config: {
+ chainConfig: {
+ chainNamespace: 'eip155',
+ chainId: '0x1',
+ rpcTarget: 'https://rpc.ankr.com/eth',
+ },
+ },
+})
+
+// 2. Initialize Web3Auth (once, during app startup)
+const web3auth = new Web3Auth({
+ clientId: 'YOUR_CLIENT_ID',
+ web3AuthNetwork: 'sapphire_mainnet',
+ privateKeyProvider,
+})
+
+await web3auth.init()
+
+// 3. Connect user (per request)
+const provider = await web3auth.connect({
+ verifier: 'YOUR_VERIFIER',
+ verifierId: 'user@example.com',
+ idToken: 'JWT_TOKEN',
+})
+
+// 4. Use provider for blockchain operations
+const privateKey = await provider.request({ method: 'eth_private_key' })
+
+// 5. Perform blockchain operations with preferred library
+```
+
+## Error Handling
+
+Always implement proper error handling when using the SDK:
+
+```javascript
+try {
+ const provider = await web3auth.connect({
+ verifier: 'YOUR_VERIFIER',
+ verifierId: 'user@example.com',
+ idToken: 'JWT_TOKEN',
+ })
+
+ // Success - proceed with blockchain operations
+ const privateKey = await provider.request({ method: 'eth_private_key' })
+} catch (error) {
+ console.error('Authentication failed:', error.message)
+ // Handle authentication errors
+}
+```
+
+## Best Practices
+
+1. **Initialize once**: Call `init()` during application startup, not per request
+2. **Stateless requests**: Each user authentication is independent
+3. **Handle errors**: Always wrap SDK calls in try-catch blocks
+4. **Secure storage**: Protect private keys and never log them
+5. **Rate limiting**: Implement rate limiting for authentication endpoints
+6. **Token validation**: Validate JWT tokens before passing to connect method
+7. **Provider reuse**: Create providers once, reuse for multiple users
diff --git a/embedded-wallets/sdk/node/usage/connect.mdx b/embedded-wallets/sdk/node/usage/connect.mdx
new file mode 100644
index 00000000000..566f06e6e05
--- /dev/null
+++ b/embedded-wallets/sdk/node/usage/connect.mdx
@@ -0,0 +1,482 @@
+---
+title: connect
+description: 'Authenticate users and establish provider connection'
+---
+
+## Overview
+
+The `connect` method is the primary authentication method for the Node.js SDK. It authenticates users using custom authentication and returns a provider for blockchain operations.
+
+## Usage
+
+```javascript
+const provider = await web3auth.connect(loginParams)
+```
+
+## Parameters
+
+### LoginParams
+
+```typescript
+interface LoginParams {
+ verifier: string // Your custom verifier name
+ verifierId: string // User's unique identifier
+ idToken: string // Valid JWT token
+ chainId?: string // Optional chain ID to connect to
+}
+```
+
+| Parameter | Type | Description | Required |
+| ------------ | -------- | ----------------------------------------------------- | -------- |
+| `verifier` | `string` | Custom verifier name from Web3Auth Dashboard | ✅ |
+| `verifierId` | `string` | Unique identifier for the user (email, user ID, etc.) | ✅ |
+| `idToken` | `string` | Valid JWT token from your authentication system | ✅ |
+| `chainId` | `string` | Blockchain chain ID to connect to | ❌ |
+
+## Return Value
+
+Returns a `SafeEventEmitterProvider` that can be used for blockchain operations.
+
+## Examples
+
+### Basic Authentication
+
+```javascript
+const { Web3Auth } = require('@web3auth/node-sdk')
+
+const web3auth = new Web3Auth({
+ clientId: 'YOUR_CLIENT_ID',
+ web3AuthNetwork: 'sapphire_mainnet',
+})
+
+await web3auth.init()
+
+// Authenticate user
+const provider = await web3auth.connect({
+ verifier: 'my-custom-verifier',
+ verifierId: 'user@example.com',
+ idToken: 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...',
+})
+
+console.log('User authenticated successfully')
+```
+
+### Authentication with Specific Chain
+
+```javascript
+// Connect to Polygon mainnet
+const provider = await web3auth.connect({
+ verifier: 'my-custom-verifier',
+ verifierId: 'user123',
+ idToken: 'JWT_TOKEN_HERE',
+ chainId: '0x89', // Polygon mainnet
+})
+```
+
+### Authentication with Error Handling
+
+```javascript
+async function authenticateUser(userToken, userId) {
+ try {
+ const provider = await web3auth.connect({
+ verifier: 'my-auth-verifier',
+ verifierId: userId,
+ idToken: userToken,
+ })
+
+ console.log('Authentication successful')
+ return provider
+ } catch (error) {
+ console.error('Authentication failed:', error.message)
+
+ // Handle specific error types
+ if (error.message.includes('Invalid token')) {
+ throw new Error('Invalid authentication token')
+ } else if (error.message.includes('User not found')) {
+ throw new Error('User not found in verifier')
+ } else {
+ throw new Error('Authentication service unavailable')
+ }
+ }
+}
+```
+
+## ID Token Requirements
+
+The `idToken` must be a valid JWT token that includes:
+
+### Required Claims
+
+```json
+{
+ "iss": "your-issuer", // Token issuer
+ "aud": "your-audience", // Token audience
+ "sub": "user-subject-id", // Subject (user ID)
+ "iat": 1234567890, // Issued at time
+ "exp": 1234567999 // Expiration time
+}
+```
+
+### Example JWT Payload
+
+```json
+{
+ "iss": "https://auth.yourapp.com",
+ "aud": "your-web3auth-client-id",
+ "sub": "user123",
+ "email": "user@example.com",
+ "name": "John Doe",
+ "iat": 1640995200,
+ "exp": 1641081600
+}
+```
+
+## Chain ID Options
+
+If no `chainId` is specified, the SDK will use the default chain configured in your Web3Auth Dashboard.
+
+### Popular Chain IDs
+
+| Blockchain | Chain ID | Network |
+| ---------- | --------- | -------------- |
+| Ethereum | `0x1` | Mainnet |
+| Ethereum | `0x5` | Goerli Testnet |
+| Polygon | `0x89` | Mainnet |
+| Polygon | `0x80001` | Mumbai Testnet |
+| BSC | `0x38` | Mainnet |
+| BSC | `0x61` | Testnet |
+| Arbitrum | `0xa4b1` | Mainnet |
+| Optimism | `0xa` | Mainnet |
+
+## Working with the Provider
+
+Once connected, use the provider for blockchain operations:
+
+```javascript
+// Get private key
+const privateKey = await provider.request({ method: 'eth_private_key' })
+
+// Get account address
+const accounts = await provider.request({ method: 'eth_accounts' })
+const address = accounts[0]
+
+// Sign a message
+const signature = await provider.request({
+ method: 'personal_sign',
+ params: ['Hello Web3Auth!', address],
+})
+```
+
+## Error Types
+
+The `connect` method can throw various errors:
+
+| Error | Description | Solution |
+| -------------------- | --------------------------------- | -------------------------------------- |
+| `Invalid token` | JWT token is malformed or expired | Refresh and provide a new token |
+| `Verifier not found` | Verifier name doesn't exist | Check verifier name in dashboard |
+| `User not found` | VerifierId not found in verifier | Ensure user exists in your auth system |
+| `Network error` | Connection to Web3Auth failed | Check network connectivity |
+| `Invalid client ID` | Client ID is incorrect | Verify client ID in dashboard |
+
+## Next Steps
+
+After successful authentication:
+
+- [Access private keys](./private-key)
+- [Integrate with blockchains](./evm-integration)
+
+## Custom Authentication Implementation
+
+Since the Node.js SDK only supports custom authentication, here are detailed implementation examples for different scenarios:
+
+### Creating JWT Tokens
+
+```javascript
+const jwt = require('jsonwebtoken')
+
+function createJWTForUser(userId, userEmail, userName) {
+ const payload = {
+ iss: process.env.JWT_ISSUER, // Your issuer URL
+ aud: process.env.WEB3AUTH_CLIENT_ID, // Your Web3Auth client ID
+ sub: userId, // User's unique identifier
+ email: userEmail,
+ name: userName,
+ iat: Math.floor(Date.now() / 1000),
+ exp: Math.floor(Date.now() / 1000) + 60 * 60, // 1 hour expiration
+ }
+
+ return jwt.sign(payload, process.env.JWT_SECRET, { algorithm: 'HS256' })
+}
+```
+
+### Auth0 Integration
+
+```javascript
+const { auth0 } = require('auth0')
+
+class Auth0Web3AuthIntegration {
+ constructor(auth0Config, web3authConfig) {
+ this.auth0 = new auth0.AuthenticationApi({
+ domain: auth0Config.domain,
+ clientId: auth0Config.clientId,
+ clientSecret: auth0Config.clientSecret,
+ })
+
+ this.web3auth = new Web3Auth(web3authConfig)
+ }
+
+ async initialize() {
+ await this.web3auth.init()
+ }
+
+ async authenticateWithAuth0Token(auth0Token) {
+ try {
+ // Verify Auth0 token
+ const userInfo = await this.auth0.getProfile(auth0Token)
+
+ // Create custom JWT for Web3Auth
+ const customJWT = this.createCustomJWT(userInfo)
+
+ // Authenticate with Web3Auth
+ const provider = await this.web3auth.connect({
+ verifier: 'auth0-verifier',
+ verifierId: userInfo.sub,
+ idToken: customJWT,
+ })
+
+ return { provider, userInfo }
+ } catch (error) {
+ console.error('Auth0 authentication failed:', error)
+ throw error
+ }
+ }
+
+ createCustomJWT(auth0UserInfo) {
+ const payload = {
+ iss: process.env.CUSTOM_JWT_ISSUER,
+ aud: process.env.WEB3AUTH_CLIENT_ID,
+ sub: auth0UserInfo.sub,
+ email: auth0UserInfo.email,
+ name: auth0UserInfo.name,
+ picture: auth0UserInfo.picture,
+ iat: Math.floor(Date.now() / 1000),
+ exp: Math.floor(Date.now() / 1000) + 3600,
+ }
+
+ return jwt.sign(payload, process.env.JWT_SECRET)
+ }
+}
+```
+
+### Firebase Integration
+
+```javascript
+const admin = require('firebase-admin')
+
+class FirebaseWeb3AuthIntegration {
+ constructor(firebaseConfig, web3authConfig) {
+ admin.initializeApp({
+ credential: admin.credential.cert(firebaseConfig.serviceAccount),
+ databaseURL: firebaseConfig.databaseURL,
+ })
+
+ this.web3auth = new Web3Auth(web3authConfig)
+ }
+
+ async initialize() {
+ await this.web3auth.init()
+ }
+
+ async authenticateWithFirebaseToken(firebaseToken) {
+ try {
+ // Verify Firebase ID token
+ const decodedToken = await admin.auth().verifyIdToken(firebaseToken)
+
+ // Get user record for additional info
+ const userRecord = await admin.auth().getUser(decodedToken.uid)
+
+ // Create custom JWT for Web3Auth
+ const customJWT = this.createCustomJWT(decodedToken, userRecord)
+
+ // Authenticate with Web3Auth
+ const provider = await this.web3auth.connect({
+ verifier: 'firebase-verifier',
+ verifierId: decodedToken.uid,
+ idToken: customJWT,
+ })
+
+ return { provider, firebaseUser: userRecord }
+ } catch (error) {
+ console.error('Firebase authentication failed:', error)
+ throw error
+ }
+ }
+
+ createCustomJWT(decodedToken, userRecord) {
+ const payload = {
+ iss: process.env.CUSTOM_JWT_ISSUER,
+ aud: process.env.WEB3AUTH_CLIENT_ID,
+ sub: decodedToken.uid,
+ email: userRecord.email,
+ name: userRecord.displayName,
+ picture: userRecord.photoURL,
+ email_verified: userRecord.emailVerified,
+ firebase: {
+ sign_in_provider: decodedToken.firebase.sign_in_provider,
+ identities: decodedToken.firebase.identities,
+ },
+ iat: Math.floor(Date.now() / 1000),
+ exp: Math.floor(Date.now() / 1000) + 3600,
+ }
+
+ return jwt.sign(payload, process.env.JWT_SECRET)
+ }
+}
+```
+
+### Express.js API Integration
+
+```javascript
+const express = require('express')
+
+const app = express()
+app.use(express.json())
+
+// Store Web3Auth instances per user (use proper session store in production)
+const userSessions = new Map()
+
+// Initialize Web3Auth
+const web3auth = new Web3Auth({
+ clientId: process.env.WEB3AUTH_CLIENT_ID,
+ web3AuthNetwork: 'sapphire_mainnet',
+})
+
+await web3auth.init()
+
+// Authentication endpoint
+app.post('/api/auth/web3auth', async (req, res) => {
+ try {
+ const { userId, userEmail, userName } = req.body
+
+ // Validate user (implement your validation logic)
+ const isValidUser = await validateUser(userId, userEmail)
+ if (!isValidUser) {
+ return res.status(401).json({ error: 'Invalid user credentials' })
+ }
+
+ // Create JWT
+ const idToken = createJWTForUser(userId, userEmail, userName)
+
+ // Authenticate with Web3Auth
+ const provider = await web3auth.connect({
+ verifier: 'api-verifier',
+ verifierId: userId,
+ idToken: idToken,
+ })
+
+ // Store session
+ userSessions.set(userId, { provider, timestamp: Date.now() })
+
+ // Access blockchain operations
+ const privateKey = await provider.request({ method: 'eth_private_key' })
+
+ res.json({
+ success: true,
+ address: await provider.request({ method: 'eth_accounts' }),
+ sessionId: userId,
+ })
+ } catch (error) {
+ console.error('Authentication error:', error)
+ res.status(500).json({ error: 'Authentication failed' })
+ }
+})
+
+// Get wallet address endpoint
+app.get('/api/wallet/:userId/address', async (req, res) => {
+ try {
+ const { userId } = req.params
+ const session = userSessions.get(userId)
+
+ if (!session) {
+ return res.status(401).json({ error: 'No active session' })
+ }
+
+ const accounts = await session.provider.request({ method: 'eth_accounts' })
+
+ res.json({
+ address: accounts[0],
+ userId: userId,
+ })
+ } catch (error) {
+ console.error('Address retrieval error:', error)
+ res.status(500).json({ error: 'Failed to get address' })
+ }
+})
+
+app.listen(3000, () => {
+ console.log('Server running on port 3000')
+})
+```
+
+### JWT Validation
+
+```javascript
+function validateJWTPayload(payload) {
+ // Required fields
+ if (!payload.sub) throw new Error('Subject (sub) is required')
+ if (!payload.iss) throw new Error('Issuer (iss) is required')
+ if (!payload.aud) throw new Error('Audience (aud) is required')
+
+ // Expiration check
+ if (payload.exp && payload.exp < Math.floor(Date.now() / 1000)) {
+ throw new Error('Token has expired')
+ }
+
+ // Issuer validation
+ if (payload.iss !== process.env.JWT_ISSUER) {
+ throw new Error('Invalid token issuer')
+ }
+
+ return true
+}
+```
+
+### Error Handling for Authentication
+
+```javascript
+async function robustAuthentication(userId, userInfo) {
+ const maxRetries = 3
+ let lastError
+
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
+ try {
+ const idToken = createJWTForUser(userId, userInfo.email, userInfo.name)
+
+ const provider = await web3auth.connect({
+ verifier: 'robust-verifier',
+ verifierId: userId,
+ idToken: idToken,
+ })
+
+ console.log(`Authentication successful on attempt ${attempt}`)
+ return provider
+ } catch (error) {
+ lastError = error
+ console.log(`Authentication attempt ${attempt} failed:`, error.message)
+
+ // Don't retry on certain errors
+ if (error.message.includes('Invalid verifier') || error.message.includes('Malformed token')) {
+ throw error
+ }
+
+ // Wait before retry
+ if (attempt < maxRetries) {
+ await new Promise(resolve => setTimeout(resolve, 1000 * attempt))
+ }
+ }
+ }
+
+ throw new Error(`Authentication failed after ${maxRetries} attempts: ${lastError.message}`)
+}
+```
diff --git a/embedded-wallets/sdk/node/usage/evm-integration.mdx b/embedded-wallets/sdk/node/usage/evm-integration.mdx
new file mode 100644
index 00000000000..f6a04c4f72e
--- /dev/null
+++ b/embedded-wallets/sdk/node/usage/evm-integration.mdx
@@ -0,0 +1,433 @@
+---
+title: EVM Integration
+description: 'Integrate with Ethereum and EVM-compatible chains'
+---
+
+## Overview
+
+The Node.js SDK provides seamless integration with Ethereum Virtual Machine (EVM) compatible blockchains including Ethereum, Polygon, Binance Smart Chain, Arbitrum, Optimism, and more.
+
+## Supported EVM Chains
+
+| Blockchain | Chain ID | RPC Endpoint |
+| ---------------- | --------- | ------------------------------------------------ |
+| Ethereum Mainnet | `0x1` | `https://rpc.ankr.com/eth` |
+| Ethereum Goerli | `0x5` | `https://rpc.ankr.com/eth_goerli` |
+| Polygon Mainnet | `0x89` | `https://rpc.ankr.com/polygon` |
+| Polygon Mumbai | `0x80001` | `https://rpc.ankr.com/polygon_mumbai` |
+| BSC Mainnet | `0x38` | `https://bsc-dataseed.binance.org` |
+| BSC Testnet | `0x61` | `https://data-seed-prebsc-1-s1.binance.org:8545` |
+| Arbitrum One | `0xa4b1` | `https://arb1.arbitrum.io/rpc` |
+| Optimism | `0xa` | `https://mainnet.optimism.io` |
+
+## Integration with Ethers.js
+
+### Basic Setup
+
+```javascript
+const { Web3Auth } = require('@web3auth/node-sdk')
+const { ethers } = require('ethers')
+
+// Initialize Web3Auth
+const web3auth = new Web3Auth({
+ clientId: 'YOUR_CLIENT_ID',
+ web3AuthNetwork: 'sapphire_mainnet',
+})
+
+await web3auth.init()
+
+// Authenticate user
+const provider = await web3auth.connect({
+ verifier: 'my-custom-verifier',
+ verifierId: 'user@example.com',
+ idToken: 'JWT_TOKEN',
+ chainId: '0x1', // Ethereum mainnet
+})
+
+// Get private key and create wallet
+const privateKey = await provider.request({ method: 'eth_private_key' })
+const wallet = new ethers.Wallet(privateKey)
+
+// Connect to RPC provider
+const rpcProvider = new ethers.providers.JsonRpcProvider('https://rpc.ankr.com/eth')
+const connectedWallet = wallet.connect(rpcProvider)
+
+console.log('Wallet Address:', await connectedWallet.getAddress())
+```
+
+### Send Transaction
+
+```javascript
+async function sendTransaction(toAddress, amount) {
+ try {
+ // Create transaction
+ const tx = {
+ to: toAddress,
+ value: ethers.utils.parseEther(amount),
+ gasLimit: 21000,
+ }
+
+ // Send transaction
+ const txResponse = await connectedWallet.sendTransaction(tx)
+ console.log('Transaction Hash:', txResponse.hash)
+
+ // Wait for confirmation
+ const receipt = await txResponse.wait()
+ console.log('Transaction confirmed in block:', receipt.blockNumber)
+
+ return receipt
+ } catch (error) {
+ console.error('Transaction failed:', error.message)
+ throw error
+ }
+}
+
+// Usage
+await sendTransaction('0x742d35Cc6635C0532925a3b8138341B0F7E8a4e8', '0.1')
+```
+
+### Smart Contract Interaction
+
+```javascript
+// ERC-20 Token ABI (simplified)
+const erc20Abi = [
+ 'function balanceOf(address owner) view returns (uint256)',
+ 'function transfer(address to, uint256 amount) returns (bool)',
+ 'function approve(address spender, uint256 amount) returns (bool)',
+ 'function symbol() view returns (string)',
+ 'function decimals() view returns (uint8)',
+]
+
+async function interactWithERC20(tokenAddress) {
+ // Create contract instance
+ const tokenContract = new ethers.Contract(tokenAddress, erc20Abi, connectedWallet)
+
+ // Get token info
+ const symbol = await tokenContract.symbol()
+ const decimals = await tokenContract.decimals()
+ console.log(`Token: ${symbol}, Decimals: ${decimals}`)
+
+ // Get balance
+ const balance = await tokenContract.balanceOf(connectedWallet.address)
+ console.log('Token Balance:', ethers.utils.formatUnits(balance, decimals))
+
+ // Transfer tokens
+ const transferTx = await tokenContract.transfer(
+ '0x742d35Cc6635C0532925a3b8138341B0F7E8a4e8',
+ ethers.utils.parseUnits('10', decimals)
+ )
+
+ await transferTx.wait()
+ console.log('Transfer completed:', transferTx.hash)
+}
+
+// Usage with USDC on Ethereum
+await interactWithERC20('0xA0b86a33E6441E51DBF5c4dF02a7b29fAdab0215')
+```
+
+## Integration with Viem
+
+### Basic Setup
+
+```javascript
+const { createWalletClient, createPublicClient, http } = require('viem')
+const { privateKeyToAccount } = require('viem/accounts')
+const { mainnet, polygon } = require('viem/chains')
+
+// Get private key from Web3Auth
+const privateKey = await provider.request({ method: 'eth_private_key' })
+
+// Create account
+const account = privateKeyToAccount(privateKey)
+
+// Create wallet client
+const walletClient = createWalletClient({
+ account,
+ chain: mainnet,
+ transport: http('https://rpc.ankr.com/eth'),
+})
+
+// Create public client for reading
+const publicClient = createPublicClient({
+ chain: mainnet,
+ transport: http('https://rpc.ankr.com/eth'),
+})
+
+console.log('Account Address:', account.address)
+```
+
+### Send Transaction with Viem
+
+```javascript
+const { parseEther, formatEther } = require('viem')
+
+async function sendTransactionViem(toAddress, amount) {
+ try {
+ // Get current balance
+ const balance = await publicClient.getBalance({
+ address: account.address,
+ })
+ console.log('Current Balance:', formatEther(balance), 'ETH')
+
+ // Send transaction
+ const hash = await walletClient.sendTransaction({
+ to: toAddress,
+ value: parseEther(amount),
+ })
+
+ console.log('Transaction Hash:', hash)
+
+ // Wait for confirmation
+ const receipt = await publicClient.waitForTransactionReceipt({ hash })
+ console.log('Transaction confirmed in block:', receipt.blockNumber)
+
+ return receipt
+ } catch (error) {
+ console.error('Transaction failed:', error.message)
+ throw error
+ }
+}
+```
+
+### Smart Contract with Viem
+
+```javascript
+const { getContract, parseUnits, formatUnits } = require('viem')
+
+// ERC-20 ABI
+const erc20Abi = [
+ {
+ inputs: [{ name: 'owner', type: 'address' }],
+ name: 'balanceOf',
+ outputs: [{ name: '', type: 'uint256' }],
+ stateMutability: 'view',
+ type: 'function',
+ },
+ {
+ inputs: [
+ { name: 'to', type: 'address' },
+ { name: 'amount', type: 'uint256' },
+ ],
+ name: 'transfer',
+ outputs: [{ name: '', type: 'bool' }],
+ stateMutability: 'nonpayable',
+ type: 'function',
+ },
+] as const
+
+async function erc20WithViem(tokenAddress) {
+ // Create contract instance
+ const contract = getContract({
+ address: tokenAddress,
+ abi: erc20Abi,
+ publicClient,
+ walletClient,
+ })
+
+ // Read balance
+ const balance = await contract.read.balanceOf([account.address])
+ console.log('Token Balance:', formatUnits(balance, 18))
+
+ // Write operation
+ const hash = await contract.write.transfer([
+ '0x742d35Cc6635C0532925a3b8138341B0F7E8a4e8',
+ parseUnits('10', 18),
+ ])
+
+ const receipt = await publicClient.waitForTransactionReceipt({ hash })
+ console.log('Transfer completed:', receipt.transactionHash)
+}
+```
+
+## Multi-Chain Support
+
+### Chain Switching
+
+```javascript
+async function connectToChain(chainId, authParams) {
+ // Connect to specific chain (stateless)
+ const provider = await web3auth.connect({
+ ...authParams,
+ chainId,
+ })
+
+ return provider
+}
+
+// Connect to Polygon
+const polygonProvider = await connectToChain('0x89', {
+ verifier: 'my-custom-verifier',
+ verifierId: 'user@example.com',
+ idToken: 'JWT_TOKEN',
+})
+```
+
+### Multi-Chain Wallet Class
+
+```javascript
+class MultiChainEVMWallet {
+ constructor(clientId) {
+ this.web3auth = new Web3Auth({
+ clientId,
+ web3AuthNetwork: 'sapphire_mainnet',
+ })
+ this.wallets = new Map()
+ }
+
+ async initialize() {
+ await this.web3auth.init()
+ }
+
+ async connectToChain(chainId, chainConfig) {
+ // Connect to specific chain
+ const provider = await this.web3auth.connect({
+ verifier: 'my-custom-verifier',
+ verifierId: 'user@example.com',
+ idToken: 'JWT_TOKEN',
+ chainId,
+ })
+
+ // Create wallet for this chain
+ const privateKey = await provider.request({ method: 'eth_private_key' })
+ const wallet = new ethers.Wallet(privateKey)
+ const connectedWallet = wallet.connect(new ethers.providers.JsonRpcProvider(chainConfig.rpcUrl))
+
+ this.wallets.set(chainId, {
+ provider,
+ wallet: connectedWallet,
+ config: chainConfig,
+ })
+
+ return connectedWallet
+ }
+
+ getWallet(chainId) {
+ const walletData = this.wallets.get(chainId)
+ return walletData ? walletData.wallet : null
+ }
+
+ async getBalances() {
+ const balances = {}
+
+ for (const [chainId, walletData] of this.wallets) {
+ const balance = await walletData.wallet.getBalance()
+ balances[chainId] = {
+ balance: ethers.utils.formatEther(balance),
+ address: walletData.wallet.address,
+ network: walletData.config.name,
+ }
+ }
+
+ return balances
+ }
+}
+
+// Usage
+const multiWallet = new MultiChainEVMWallet('YOUR_CLIENT_ID')
+await multiWallet.initialize()
+
+// Connect to multiple chains
+await multiWallet.connectToChain('0x1', {
+ name: 'Ethereum',
+ rpcUrl: 'https://rpc.ankr.com/eth',
+})
+
+await multiWallet.connectToChain('0x89', {
+ name: 'Polygon',
+ rpcUrl: 'https://rpc.ankr.com/polygon',
+})
+
+const balances = await multiWallet.getBalances()
+console.log('Multi-chain balances:', balances)
+```
+
+## Gas Management
+
+### Estimate Gas
+
+```javascript
+async function estimateAndSendTransaction(toAddress, amount) {
+ const tx = {
+ to: toAddress,
+ value: ethers.utils.parseEther(amount),
+ }
+
+ // Estimate gas
+ const gasEstimate = await connectedWallet.estimateGas(tx)
+ console.log('Estimated Gas:', gasEstimate.toString())
+
+ // Get gas price
+ const gasPrice = await connectedWallet.getGasPrice()
+ console.log('Gas Price:', ethers.utils.formatUnits(gasPrice, 'gwei'), 'gwei')
+
+ // Add gas settings to transaction
+ tx.gasLimit = gasEstimate.mul(120).div(100) // Add 20% buffer
+ tx.gasPrice = gasPrice
+
+ // Send transaction
+ const txResponse = await connectedWallet.sendTransaction(tx)
+ return txResponse
+}
+```
+
+### EIP-1559 (Type 2) Transactions
+
+```javascript
+async function sendEIP1559Transaction(toAddress, amount) {
+ // Get fee data
+ const feeData = await connectedWallet.getFeeData()
+
+ const tx = {
+ to: toAddress,
+ value: ethers.utils.parseEther(amount),
+ type: 2, // EIP-1559
+ maxFeePerGas: feeData.maxFeePerGas,
+ maxPriorityFeePerGas: feeData.maxPriorityFeePerGas,
+ }
+
+ const txResponse = await connectedWallet.sendTransaction(tx)
+ return txResponse
+}
+```
+
+## Error Handling
+
+```javascript
+async function robustEVMTransaction(toAddress, amount) {
+ try {
+ // Check balance first
+ const balance = await connectedWallet.getBalance()
+ const amountWei = ethers.utils.parseEther(amount)
+
+ if (balance.lt(amountWei)) {
+ throw new Error('Insufficient balance')
+ }
+
+ // Send transaction with retries
+ let retries = 3
+ while (retries > 0) {
+ try {
+ const tx = await sendTransaction(toAddress, amount)
+ return tx
+ } catch (error) {
+ retries--
+
+ if (error.code === 'NONCE_EXPIRED' && retries > 0) {
+ console.log('Nonce expired, retrying...')
+ continue
+ }
+
+ throw error
+ }
+ }
+ } catch (error) {
+ console.error('EVM transaction failed:', error.message)
+ throw error
+ }
+}
+```
+
+## Next Steps
+
+- [Access private keys](./private-key)
+- [Authenticate users](./connect)
diff --git a/embedded-wallets/sdk/node/usage/private-key.mdx b/embedded-wallets/sdk/node/usage/private-key.mdx
new file mode 100644
index 00000000000..23684f6ce02
--- /dev/null
+++ b/embedded-wallets/sdk/node/usage/private-key.mdx
@@ -0,0 +1,316 @@
+---
+title: Private Key Access
+description: 'Extract private keys for blockchain operations'
+---
+
+## Overview
+
+The Node.js SDK provides direct access to user private keys, enabling integration with any blockchain network. This is a key feature that makes the SDK suitable for backend and programmatic use cases.
+
+:::warning Security Notice
+
+Private keys provide full control over user assets. Handle them securely:
+
+- Never log private keys
+- Store them encrypted if persistence is needed
+- Use secure memory handling
+- Implement proper access controls
+
+:::
+
+## Available Methods
+
+The provider offers different methods to access private keys depending on your blockchain needs:
+
+| Method | Description | Use Case |
+| ------------------ | ------------------------------ | ----------------------------------------- |
+| `eth_private_key` | Ethereum-formatted private key | EVM chains (Ethereum, Polygon, BSC, etc.) |
+| `solanaPrivateKey` | Solana private key | Solana blockchain |
+| `private_key` | Raw private key | Any blockchain |
+
+## EVM Chains (Ethereum, Polygon, BSC, etc.)
+
+### Get Ethereum Private Key
+
+```javascript
+const privateKey = await provider.request({ method: 'eth_private_key' })
+console.log('Private Key:', privateKey) // 0x1234567890abcdef...
+```
+
+### Use with Ethers.js
+
+```javascript
+const { ethers } = require('ethers')
+
+// Get private key
+const privateKey = await provider.request({ method: 'eth_private_key' })
+
+// Create wallet instance
+const wallet = new ethers.Wallet(privateKey)
+
+// Connect to a provider
+const rpcProvider = new ethers.providers.JsonRpcProvider('https://rpc.ankr.com/eth')
+const connectedWallet = wallet.connect(rpcProvider)
+
+// Get address
+const address = await connectedWallet.getAddress()
+console.log('Wallet Address:', address)
+
+// Sign a transaction
+const tx = {
+ to: '0x742d35Cc6635C0532925a3b8138341B0F7E8a4e8',
+ value: ethers.utils.parseEther('0.1'),
+}
+
+const signedTx = await connectedWallet.signTransaction(tx)
+const receipt = await connectedWallet.sendTransaction(tx)
+```
+
+### Use with Viem
+
+```javascript
+const { createWalletClient, createPublicClient, http } = require('viem')
+const { privateKeyToAccount } = require('viem/accounts')
+const { mainnet } = require('viem/chains')
+
+// Get private key
+const privateKey = await provider.request({ method: 'eth_private_key' })
+
+// Create account from private key
+const account = privateKeyToAccount(privateKey)
+
+// Create wallet client
+const walletClient = createWalletClient({
+ account,
+ chain: mainnet,
+ transport: http('https://rpc.ankr.com/eth'),
+})
+
+// Create public client for reading
+const publicClient = createPublicClient({
+ chain: mainnet,
+ transport: http('https://rpc.ankr.com/eth'),
+})
+
+// Send transaction
+const hash = await walletClient.sendTransaction({
+ to: '0x742d35Cc6635C0532925a3b8138341B0F7E8a4e8',
+ value: parseEther('0.1'),
+})
+```
+
+## Solana Integration
+
+### Get Solana Private Key
+
+```javascript
+const solanaPrivateKey = await provider.request({ method: 'solanaPrivateKey' })
+console.log('Solana Private Key:', solanaPrivateKey) // Base58 encoded
+```
+
+### Use with Solana Web3.js
+
+```javascript
+const {
+ Connection,
+ Keypair,
+ PublicKey,
+ Transaction,
+ SystemProgram,
+ LAMPORTS_PER_SOL,
+} = require('@solana/web3.js')
+const bs58 = require('bs58')
+
+// Get private key
+const solanaPrivateKey = await provider.request({ method: 'solanaPrivateKey' })
+
+// Create keypair from private key
+const secretKey = bs58.decode(solanaPrivateKey)
+const keypair = Keypair.fromSecretKey(secretKey)
+
+// Connect to Solana
+const connection = new Connection('https://api.mainnet-beta.solana.com')
+
+// Get balance
+const balance = await connection.getBalance(keypair.publicKey)
+console.log('Balance:', balance / LAMPORTS_PER_SOL, 'SOL')
+
+// Send transaction
+const transaction = new Transaction().add(
+ SystemProgram.transfer({
+ fromPubkey: keypair.publicKey,
+ toPubkey: new PublicKey('11111111111111111111111111111112'),
+ lamports: 0.1 * LAMPORTS_PER_SOL,
+ })
+)
+
+const signature = await connection.sendTransaction(transaction, [keypair])
+```
+
+## Other Blockchains
+
+### Get Raw Private Key
+
+```javascript
+const rawPrivateKey = await provider.request({ method: 'private_key' })
+console.log('Raw Private Key:', rawPrivateKey) // Hex string
+```
+
+### Example: Bitcoin Integration
+
+```javascript
+const bitcoin = require('bitcoinjs-lib')
+
+// Get raw private key
+const rawPrivateKey = await provider.request({ method: 'private_key' })
+
+// Create Bitcoin keypair
+const keyPair = bitcoin.ECPair.fromPrivateKey(Buffer.from(rawPrivateKey.slice(2), 'hex'))
+
+// Get Bitcoin address
+const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey })
+console.log('Bitcoin Address:', address)
+```
+
+## Complete Integration Example
+
+Here's a comprehensive example showing multi-chain support:
+
+```javascript
+const { Web3Auth } = require('@web3auth/node-sdk')
+const { ethers } = require('ethers')
+
+class MultiChainWallet {
+ constructor(clientId) {
+ this.web3auth = new Web3Auth({
+ clientId,
+ web3AuthNetwork: 'sapphire_mainnet',
+ })
+ }
+
+ async initialize() {
+ await this.web3auth.init()
+ }
+
+ async authenticate(verifier, verifierId, idToken) {
+ this.provider = await this.web3auth.connect({
+ verifier,
+ verifierId,
+ idToken,
+ })
+ }
+
+ async getEthereumWallet() {
+ const privateKey = await this.provider.request({ method: 'eth_private_key' })
+ return new ethers.Wallet(privateKey)
+ }
+
+ async getSolanaKeypair() {
+ const { Keypair } = require('@solana/web3.js')
+ const bs58 = require('bs58')
+
+ const solanaPrivateKey = await this.provider.request({ method: 'solanaPrivateKey' })
+ const secretKey = bs58.decode(solanaPrivateKey)
+ return Keypair.fromSecretKey(secretKey)
+ }
+
+ async getRawPrivateKey() {
+ return await this.provider.request({ method: 'private_key' })
+ }
+
+ async getAddresses() {
+ const [ethWallet, solanaKeypair] = await Promise.all([
+ this.getEthereumWallet(),
+ this.getSolanaKeypair(),
+ ])
+
+ return {
+ ethereum: ethWallet.address,
+ solana: solanaKeypair.publicKey.toString(),
+ }
+ }
+}
+
+// Usage
+const wallet = new MultiChainWallet('YOUR_CLIENT_ID')
+await wallet.initialize()
+await wallet.authenticate('verifier', 'user@example.com', 'jwt_token')
+
+const addresses = await wallet.getAddresses()
+console.log('Addresses:', addresses)
+```
+
+## Security Best Practices
+
+### 1. Secure Memory Handling
+
+```javascript
+// Use Buffer.alloc for sensitive data
+function securePrivateKeyHandling(privateKey) {
+ const keyBuffer = Buffer.from(privateKey.slice(2), 'hex')
+
+ try {
+ // Use the private key
+ const wallet = new ethers.Wallet(keyBuffer)
+ return wallet.address
+ } finally {
+ // Clear the buffer
+ keyBuffer.fill(0)
+ }
+}
+```
+
+### 2. Environment-based Key Access
+
+```javascript
+// Only allow private key access in specific environments
+function getPrivateKeySecurely() {
+ if (process.env.NODE_ENV === 'production' && !process.env.ALLOW_PRIVATE_KEY_ACCESS) {
+ throw new Error('Private key access not allowed in production')
+ }
+
+ return provider.request({ method: 'eth_private_key' })
+}
+```
+
+### 3. Audit Logging
+
+```javascript
+async function auditedPrivateKeyAccess(userId, purpose) {
+ console.log(`Private key accessed by ${userId} for ${purpose} at ${new Date().toISOString()}`)
+
+ // Log to audit system
+ await logAuditEvent({
+ action: 'private_key_access',
+ userId,
+ purpose,
+ timestamp: new Date(),
+ })
+
+ return provider.request({ method: 'eth_private_key' })
+}
+```
+
+## Disabling Private Key Export
+
+Private key export can be disabled in the Web3Auth Dashboard:
+
+1. Go to your project settings
+2. Navigate to "Advanced Settings"
+3. Toggle "Disable Private Key Export"
+4. Save changes
+
+When disabled, private key methods will throw an error:
+
+```javascript
+try {
+ const privateKey = await provider.request({ method: 'eth_private_key' })
+} catch (error) {
+ console.error('Private key export disabled:', error.message)
+}
+```
+
+## Next Steps
+
+- [EVM Integration Guide](./evm-integration)
+- [User authentication](./connect)
diff --git a/src/components/EWSDKCards/index.tsx b/src/components/EWSDKCards/index.tsx
index 266c16a9911..37c28c44bdd 100644
--- a/src/components/EWSDKCards/index.tsx
+++ b/src/components/EWSDKCards/index.tsx
@@ -107,6 +107,27 @@ export const pnpweb = (
+
)
From 5aa0e404feee13e4b83f7b53efc30f93810dfcb4 Mon Sep 17 00:00:00 2001
From: Yashovardhan Agrawal <21066442+yashovardhan@users.noreply.github.com>
Date: Tue, 30 Sep 2025 10:13:58 +0800
Subject: [PATCH 2/3] updates
---
embedded-wallets/sdk/node/README.mdx | 361 ++++++++++--------
.../sdk/node/{usage => }/connect.mdx | 0
.../sdk/node/{usage => }/evm-integration.mdx | 0
.../sdk/node/{usage => }/private-key.mdx | 0
embedded-wallets/sdk/node/usage/README.mdx | 102 -----
ew-sidebar.js | 64 +++-
src/components/NavDropdown/Products.html | 38 +-
src/utils/w3a-sdk-map.js | 6 +-
8 files changed, 280 insertions(+), 291 deletions(-)
rename embedded-wallets/sdk/node/{usage => }/connect.mdx (100%)
rename embedded-wallets/sdk/node/{usage => }/evm-integration.mdx (100%)
rename embedded-wallets/sdk/node/{usage => }/private-key.mdx (100%)
delete mode 100644 embedded-wallets/sdk/node/usage/README.mdx
diff --git a/embedded-wallets/sdk/node/README.mdx b/embedded-wallets/sdk/node/README.mdx
index 40b48b83a05..690d90d46d7 100644
--- a/embedded-wallets/sdk/node/README.mdx
+++ b/embedded-wallets/sdk/node/README.mdx
@@ -35,27 +35,12 @@ Unlike frontend SDKs, the Node.js SDK is **stateless and sessionless**, making i
## Installation
-Install the Web3Auth Node SDK and required providers:
+Install the Web3Auth Node SDK
```bash npm2yarn
npm install --save @web3auth/node-sdk
```
-### Additional Dependencies
-
-For blockchain providers:
-
-```bash npm2yarn
-# For EVM chains (Ethereum, Polygon, etc.)
-npm install --save @web3auth/ethereum-provider
-
-# For Solana blockchain
-npm install --save @web3auth/solana-provider
-
-# Base package for types
-npm install --save @web3auth/base
-```
-
## Setup
:::info Prerequisites
@@ -63,87 +48,37 @@ npm install --save @web3auth/base
Before you start, make sure you have:
1. Registered on the [**Web3Auth Dashboard**](https://dashboard.web3auth.io/)
-2. Set up a project with **custom authentication** (mandatory for Node.js SDK)
-3. Configured your custom verifier settings
-
-You can refer to the [Dashboard Setup](/embedded-wallets/dashboard/) guide to learn more.
+2. Set up a project with a custom **Auth Connection** (mandatory for Node.js SDK)
:::
-### 1. Custom Verifier Setup (Required)
+### 1. Custom Authentication Setup (Required)
-The Node.js SDK **only supports custom authentication**. You must create a custom verifier in the Web3Auth Dashboard:
+The Node.js SDK **only supports custom authentication**. You must create a custom auth connection in the Web3Auth Dashboard:
1. Go to [Web3Auth Dashboard](https://dashboard.web3auth.io/)
2. Select your project
-3. Navigate to **Auth Connectors** → **Custom Authentication**
-4. Click **Create Verifier**
-5. Configure your verifier with these settings:
-
-```json
-{
- "name": "my-backend-verifier",
- "description": "Custom verifier for Node.js backend",
- "verifierType": "custom",
- "clientId": "your-auth-client-id",
- "issuer": "https://your-auth-domain.com",
- "jwks_endpoint": "https://your-auth-domain.com/.well-known/jwks.json"
-}
-```
-
-### 2. JWT Token Requirements
-
-Your authentication system must generate JWT tokens with these required claims:
-
-```json
-{
- "iss": "https://your-auth-domain.com", // Issuer (must match verifier)
- "aud": "your-web3auth-client-id", // Audience
- "sub": "user-unique-identifier", // Subject (user ID)
- "iat": 1640995200, // Issued at
- "exp": 1641081600, // Expiration
- "email": "user@example.com", // User email (optional)
- "name": "John Doe" // User name (optional)
-}
-```
-
-### 3. Provider Configuration
-
-Configure the blockchain provider for your target network:
+3. Navigate to **Authentication** → **Custom Connections**
+4. Click **Create connections**
+5. Configure your auth connection with your custom JWT details
-```javascript
-const { Web3Auth } = require('@web3auth/node-sdk')
-const { EthereumPrivateKeyProvider } = require('@web3auth/ethereum-provider')
+> You can refer to the [Custom JWT Setup](/embedded-wallets/authentication/custom-connections/custom-jwt/) guide to learn more.
-// Configure Ethereum provider
-const privateKeyProvider = new EthereumPrivateKeyProvider({
- config: {
- chainConfig: {
- chainNamespace: 'eip155',
- chainId: '0x1', // Ethereum Mainnet
- rpcTarget: 'https://rpc.ankr.com/eth',
- displayName: 'Ethereum Mainnet',
- blockExplorerUrl: 'https://etherscan.io/',
- ticker: 'ETH',
- tickerName: 'Ethereum',
- },
- },
-})
-```
-
-### 4. SDK Configuration
+### 2. SDK Configuration
-Create a Web3Auth instance with your client ID, network configuration, and provider:
+Create a Web3Auth instance with your client ID, web3auth network name, and chain information:
```javascript
const web3auth = new Web3Auth({
clientId: 'YOUR_CLIENT_ID', // Get your Client ID from Web3Auth Dashboard
web3AuthNetwork: 'sapphire_mainnet', // or 'sapphire_devnet'
- privateKeyProvider,
+ defaultChainId: '0x1', // or '0x89' for Polygon
})
```
-### 5. Initialize Web3Auth
+> The chain information is optional and will be used to setup the provider for connecting to the chain. If not provided, the first chain in the list will be used.
+
+### 3. Initialize Web3Auth
Initialize the Web3Auth instance during your application startup:
@@ -169,8 +104,7 @@ const provider = await web3auth.connect({
defaultValue="basic-config"
values={[
{ label: "Basic Configuration", value: "basic-config" },
- { label: "Production Configuration", value: "production-config" },
- { label: "Environment-Specific", value: "env-config" },
+ { label: "Advanced Configuration", value: "advanced-config" },
]}
>
@@ -189,32 +123,15 @@ await web3auth.init()
-
+
```javascript
-const { Web3Auth } = require('@web3auth/node-sdk')
-const { EthereumPrivateKeyProvider } = require('@web3auth/ethereum-provider')
-
-// Configure provider
-const privateKeyProvider = new EthereumPrivateKeyProvider({
- config: {
- chainConfig: {
- chainNamespace: 'eip155',
- chainId: process.env.CHAIN_ID || '0x1',
- rpcTarget: process.env.RPC_URL || 'https://rpc.ankr.com/eth',
- displayName: 'Ethereum',
- blockExplorerUrl: 'https://etherscan.io/',
- ticker: 'ETH',
- tickerName: 'Ethereum',
- },
- },
-})
-
-// Production configuration
const web3auth = new Web3Auth({
- clientId: process.env.WEB3AUTH_CLIENT_ID,
- web3AuthNetwork: process.env.NODE_ENV === 'production' ? 'sapphire_mainnet' : 'sapphire_devnet',
- privateKeyProvider,
+ clientId: 'YOUR_CLIENT_ID',
+ web3AuthNetwork: 'sapphire_mainnet', // or 'sapphire_devnet'
+ defaultChainId: '0x1', // or '0x89' for Polygon
+ enableLogging: true,
+ sessionTime: 3600,
})
await web3auth.init()
@@ -222,73 +139,101 @@ await web3auth.init()
-
+
-```javascript
-// Provider configuration
-const privateKeyProvider = new EthereumPrivateKeyProvider({
- config: {
- chainConfig: {
- chainNamespace: 'eip155',
- chainId: '0x1',
- rpcTarget: 'https://rpc.ankr.com/eth',
- displayName: 'Ethereum',
- blockExplorerUrl: 'https://etherscan.io/',
- ticker: 'ETH',
- tickerName: 'Ethereum',
- },
- },
-})
+## Configuration Parameters
-// Development
-const devConfig = {
- clientId: 'dev-client-id',
- web3AuthNetwork: 'sapphire_devnet',
- privateKeyProvider,
-}
+
-// Production
-const prodConfig = {
- clientId: process.env.WEB3AUTH_CLIENT_ID,
- web3AuthNetwork: 'sapphire_mainnet',
- privateKeyProvider,
-}
+
-// Testing
-const testConfig = {
- clientId: 'test-client-id',
- web3AuthNetwork: 'sapphire_devnet',
- privateKeyProvider,
-}
+#### Web3Auth Configuration
-const web3auth = new Web3Auth(process.env.NODE_ENV === 'production' ? prodConfig : devConfig)
-```
+| Parameter | Type | Default | Description |
+| ----------------- | -------- | -------- | ---------------------------------------------------------------- |
+| `clientId` | `string` | Required | Your Web3Auth client ID |
+| `web3AuthNetwork` | `string` | Required | Network: 'sapphire_mainnet' or 'sapphire_devnet' |
+| `defaultChainId` | `string` | Optional | Chain ID to use for the default chain (e.g., '0x1' for Ethereum) |
-
+#### Advanced Configuration Parameters
-
+| Parameter | Type | Description |
+| ----------------- | --------- | ----------- | ------------------------------------------------------------------- |
+| `chains` | `object` | Optional | Chains to use for the authentication. It takes `Chains` as a value. |
+| `enableLogging` | `boolean` | Optional | Setting to true will enable logs. Default is false. |
+| `usePnPKey` | `boolean` | Optional | Setting to true will use the PnP key. Default is false. |
+| `useDKG` | `boolean` | Optional | Setting to true will use the DKG. Default is false. |
+| `checkCommitment` | `boolean` | Optional | Setting to true will check the commitment. Default is true. |
-## Configuration Parameters
+
-### Web3Auth Configuration
+
-| Parameter | Type | Default | Description |
-| -------------------- | -------- | -------- | --------------------------------------------------- |
-| `clientId` | `string` | Required | Your Web3Auth client ID |
-| `web3AuthNetwork` | `string` | Required | Network: 'sapphire_mainnet' or 'sapphire_devnet' |
-| `privateKeyProvider` | `object` | Required | Blockchain provider configuration (Ethereum/Solana) |
+```javascript
+export interface Web3AuthOptions {
+ /**
+ * Client id for web3auth.
+ * You can obtain your client id from the web3auth developer dashboard.
+ * You can set any random string for this on localhost.
+ */
+ clientId: string;
+
+ /**
+ * Web3Auth Network to use for login
+ * @defaultValue mainnet
+ */
+ web3AuthNetwork?: WEB3AUTH_NETWORK_TYPE;
+
+ /**
+ * multiple chain configurations,
+ * only provided chains will be used
+ */
+ chains?: CustomChainConfig[];
+
+ /**
+ * default chain Id to use
+ */
+ defaultChainId?: string;
+
+ /**
+ * setting to true will enable logs
+ *
+ * @defaultValue false
+ */
+ enableLogging?: boolean;
+
+ /**
+ * setting this to true returns the same key as web sdk (i.e., plug n play key)
+ * By default, this sdk returns SFAKey
+ */
+ usePnPKey?: boolean;
+
+ /**
+ * set this to true when you wants keys/shares to be generated by a dkg network
+ *
+ * Default:- false for sapphire network and always true for legacy networks.
+ * Legacy networks doesnt support non dkg flow. So this is always true for legacy networks.
+ */
+ useDKG?: boolean;
+
+ /**
+ * setting this to true will check the commitment of the shares
+ *
+ * @defaultValue true
+ */
+ checkCommitment?: boolean;
+}
+```
-### Provider Configuration Parameters
+
-| Parameter | Type | Description |
-| ------------------ | -------- | ------------------------------------------------------- |
-| `chainNamespace` | `string` | Blockchain namespace ('eip155' for EVM, 'solana') |
-| `chainId` | `string` | Chain ID (e.g., '0x1' for Ethereum, '0x89' for Polygon) |
-| `rpcTarget` | `string` | RPC endpoint URL for blockchain communication |
-| `displayName` | `string` | Human-readable chain name |
-| `blockExplorerUrl` | `string` | Block explorer URL for the chain |
-| `ticker` | `string` | Native token symbol (e.g., 'ETH', 'SOL') |
-| `tickerName` | `string` | Full name of the native token |
+
## Best Practices
@@ -481,3 +426,101 @@ Private key export can be controlled through the Web3Auth Dashboard:
- **[Examples](./examples)**: Complete implementation examples and production patterns
+
+
+## Usage Overview
+
+The MetaMask Embedded Wallets Node.js SDK provides stateless authentication and blockchain operations for backend applications. Unlike frontend SDKs, this is designed for **per-request authentication** without persistent sessions.
+
+## Core Methods
+
+### Authentication & Connection
+
+- **[connect](./connect)** - Authenticate users and establish provider connection (stateless)
+
+### Blockchain Operations
+
+- **[Private Key Access](./private-key)** - Extract private keys for blockchain operations
+- **[EVM Integration](./evm-integration)** - Work with Ethereum and EVM-compatible chains
+
+## Important Notes
+
+### Stateless Design
+
+The Node.js SDK is **stateless** and **sessionless** by design:
+
+- No persistent user sessions
+- No `getUserInfo()` or `logout()` methods
+- Each request requires re-authentication
+- Perfect for backend APIs and microservices
+
+## Common Usage Pattern
+
+The typical flow when using the Node.js SDK:
+
+```javascript
+const { Web3Auth } = require('@web3auth/node-sdk')
+const { EthereumPrivateKeyProvider } = require('@web3auth/ethereum-provider')
+
+// 1. Configure provider (once, during app startup)
+const privateKeyProvider = new EthereumPrivateKeyProvider({
+ config: {
+ chainConfig: {
+ chainNamespace: 'eip155',
+ chainId: '0x1',
+ rpcTarget: 'https://rpc.ankr.com/eth',
+ },
+ },
+})
+
+// 2. Initialize Web3Auth (once, during app startup)
+const web3auth = new Web3Auth({
+ clientId: 'YOUR_CLIENT_ID',
+ web3AuthNetwork: 'sapphire_mainnet',
+ privateKeyProvider,
+})
+
+await web3auth.init()
+
+// 3. Connect user (per request)
+const provider = await web3auth.connect({
+ verifier: 'YOUR_VERIFIER',
+ verifierId: 'user@example.com',
+ idToken: 'JWT_TOKEN',
+})
+
+// 4. Use provider for blockchain operations
+const privateKey = await provider.request({ method: 'eth_private_key' })
+
+// 5. Perform blockchain operations with preferred library
+```
+
+## Error Handling
+
+Always implement proper error handling when using the SDK:
+
+```javascript
+try {
+ const provider = await web3auth.connect({
+ verifier: 'YOUR_VERIFIER',
+ verifierId: 'user@example.com',
+ idToken: 'JWT_TOKEN',
+ })
+
+ // Success - proceed with blockchain operations
+ const privateKey = await provider.request({ method: 'eth_private_key' })
+} catch (error) {
+ console.error('Authentication failed:', error.message)
+ // Handle authentication errors
+}
+```
+
+## Best Practices
+
+1. **Initialize once**: Call `init()` during application startup, not per request
+2. **Stateless requests**: Each user authentication is independent
+3. **Handle errors**: Always wrap SDK calls in try-catch blocks
+4. **Secure storage**: Protect private keys and never log them
+5. **Rate limiting**: Implement rate limiting for authentication endpoints
+6. **Token validation**: Validate JWT tokens before passing to connect method
+7. **Provider reuse**: Create providers once, reuse for multiple users
diff --git a/embedded-wallets/sdk/node/usage/connect.mdx b/embedded-wallets/sdk/node/connect.mdx
similarity index 100%
rename from embedded-wallets/sdk/node/usage/connect.mdx
rename to embedded-wallets/sdk/node/connect.mdx
diff --git a/embedded-wallets/sdk/node/usage/evm-integration.mdx b/embedded-wallets/sdk/node/evm-integration.mdx
similarity index 100%
rename from embedded-wallets/sdk/node/usage/evm-integration.mdx
rename to embedded-wallets/sdk/node/evm-integration.mdx
diff --git a/embedded-wallets/sdk/node/usage/private-key.mdx b/embedded-wallets/sdk/node/private-key.mdx
similarity index 100%
rename from embedded-wallets/sdk/node/usage/private-key.mdx
rename to embedded-wallets/sdk/node/private-key.mdx
diff --git a/embedded-wallets/sdk/node/usage/README.mdx b/embedded-wallets/sdk/node/usage/README.mdx
deleted file mode 100644
index d85f92c634d..00000000000
--- a/embedded-wallets/sdk/node/usage/README.mdx
+++ /dev/null
@@ -1,102 +0,0 @@
----
-title: Node.js SDK Usage
-sidebar_label: Overview
-description: 'Learn how to use the MetaMask Embedded Wallets Node.js SDK'
----
-
-## Usage Overview
-
-The MetaMask Embedded Wallets Node.js SDK provides stateless authentication and blockchain operations for backend applications. Unlike frontend SDKs, this is designed for **per-request authentication** without persistent sessions.
-
-## Core Methods
-
-### Authentication & Connection
-
-- **[connect](./connect)** - Authenticate users and establish provider connection (stateless)
-
-### Blockchain Operations
-
-- **[Private Key Access](./private-key)** - Extract private keys for blockchain operations
-- **[EVM Integration](./evm-integration)** - Work with Ethereum and EVM-compatible chains
-
-## Important Notes
-
-### Stateless Design
-
-The Node.js SDK is **stateless** and **sessionless** by design:
-
-- No persistent user sessions
-- No `getUserInfo()` or `logout()` methods
-- Each request requires re-authentication
-- Perfect for backend APIs and microservices
-
-## Common Usage Pattern
-
-The typical flow when using the Node.js SDK:
-
-```javascript
-const { Web3Auth } = require('@web3auth/node-sdk')
-const { EthereumPrivateKeyProvider } = require('@web3auth/ethereum-provider')
-
-// 1. Configure provider (once, during app startup)
-const privateKeyProvider = new EthereumPrivateKeyProvider({
- config: {
- chainConfig: {
- chainNamespace: 'eip155',
- chainId: '0x1',
- rpcTarget: 'https://rpc.ankr.com/eth',
- },
- },
-})
-
-// 2. Initialize Web3Auth (once, during app startup)
-const web3auth = new Web3Auth({
- clientId: 'YOUR_CLIENT_ID',
- web3AuthNetwork: 'sapphire_mainnet',
- privateKeyProvider,
-})
-
-await web3auth.init()
-
-// 3. Connect user (per request)
-const provider = await web3auth.connect({
- verifier: 'YOUR_VERIFIER',
- verifierId: 'user@example.com',
- idToken: 'JWT_TOKEN',
-})
-
-// 4. Use provider for blockchain operations
-const privateKey = await provider.request({ method: 'eth_private_key' })
-
-// 5. Perform blockchain operations with preferred library
-```
-
-## Error Handling
-
-Always implement proper error handling when using the SDK:
-
-```javascript
-try {
- const provider = await web3auth.connect({
- verifier: 'YOUR_VERIFIER',
- verifierId: 'user@example.com',
- idToken: 'JWT_TOKEN',
- })
-
- // Success - proceed with blockchain operations
- const privateKey = await provider.request({ method: 'eth_private_key' })
-} catch (error) {
- console.error('Authentication failed:', error.message)
- // Handle authentication errors
-}
-```
-
-## Best Practices
-
-1. **Initialize once**: Call `init()` during application startup, not per request
-2. **Stateless requests**: Each user authentication is independent
-3. **Handle errors**: Always wrap SDK calls in try-catch blocks
-4. **Secure storage**: Protect private keys and never log them
-5. **Rate limiting**: Implement rate limiting for authentication endpoints
-6. **Token validation**: Validate JWT tokens before passing to connect method
-7. **Provider reuse**: Create providers once, reuse for multiple users
diff --git a/ew-sidebar.js b/ew-sidebar.js
index e724be4c3e7..1dd1756762e 100644
--- a/ew-sidebar.js
+++ b/ew-sidebar.js
@@ -3,6 +3,7 @@ import {
vue,
android,
ios,
+ node,
reactnative,
flutter,
unity,
@@ -40,24 +41,23 @@ function webTopNavButton(selectedSDK) {
-
`;
}
-function gamingTopNavButton(selectedSDK) {
- var gamingSDKs = {
- [unity]: `/embedded-wallets/sdk/unity`,
- [unreal]: `/embedded-wallets/sdk/unreal`,
+function backendTopNavButton(selectedSDK) {
+ var backendSDKs = {
+ [node]: `/embedded-wallets/sdk/node`,
};
- if (gamingSDKs.hasOwnProperty(selectedSDK)) {
- delete gamingSDKs[selectedSDK];
+ if (backendSDKs.hasOwnProperty(selectedSDK)) {
+ delete backendSDKs[selectedSDK];
}
- var sdkNames = Object.keys(gamingSDKs);
- var sdkLinks = Object.values(gamingSDKs);
+ // var sdkNames = Object.keys(backendSDKs);
+ // var sdkLinks = Object.values(backendSDKs);
var sdkVersion = getPnPVersion(selectedSDK);
return `
@@ -66,14 +66,13 @@ function gamingTopNavButton(selectedSDK) {
Web
`;
}
@@ -168,6 +171,7 @@ const sidebar = {
{ type: "link", label: "React", href: "/embedded-wallets/sdk/react" },
{ type: "link", label: "Vue", href: "/embedded-wallets/sdk/vue" },
{ type: "link", label: "JavaScript", href: "/embedded-wallets/sdk/js" },
+ { type: "link", label: "Node.js", href: "/embedded-wallets/sdk/node" },
{ type: "link", label: "Android", href: "/embedded-wallets/sdk/android" },
{ type: "link", label: "iOS", href: "/embedded-wallets/sdk/ios" },
{ type: "link", label: "React Native", href: "/embedded-wallets/sdk/react-native" },
@@ -745,7 +749,7 @@ const sidebar = {
sdk_unity: [
{
type: "html",
- value: gamingTopNavButton(unity),
+ value: mobileTopNavButton(unity),
defaultStyle: true,
},
"sdk/unity/README",
@@ -789,10 +793,32 @@ const sidebar = {
href: "https://github.com/Web3Auth/web3auth-unity-sdk/releases",
},
],
+ sdk_node: [
+ {
+ type: "html",
+ value: backendTopNavButton(node),
+ defaultStyle: true,
+ },
+ "sdk/node/README",
+ "sdk/node/connect",
+ "sdk/node/evm-integration",
+ "sdk/node/private-key",
+ "sdk/node/examples",
+ {
+ type: "link",
+ label: "Support Forum",
+ href: "https://web3auth.io/community/c/help-pnp/pnp-node/21",
+ },
+ {
+ type: "link",
+ label: "Release Notes",
+ href: "https://github.com/Web3Auth/web3auth-backend/releases",
+ },
+ ],
sdk_unreal: [
{
type: "html",
- value: gamingTopNavButton(unreal),
+ value: mobileTopNavButton(unreal),
defaultStyle: true,
},
"sdk/unreal/README",
diff --git a/src/components/NavDropdown/Products.html b/src/components/NavDropdown/Products.html
index 43982840b03..b44cdd8ebc8 100644
--- a/src/components/NavDropdown/Products.html
+++ b/src/components/NavDropdown/Products.html
@@ -183,30 +183,34 @@ JavaScript SDK
-
+
-
-
+
+
+
+
+
-
Unity SDK
+ Node SDK
-
+
-
+
-
Unreal SDK
+ Unity SDK
@@ -266,6 +270,20 @@ Flutter SDK
+
+
+
+
+
+
+
+
+
Unreal SDK
+
+
+