UNPKG

metal-presale

Version:

SDK for Metal Presales - Client and Server utilities

246 lines (189 loc) 6.08 kB
# Metal Presales SDK A secure, type-safe SDK for interacting with Metal L2 presales and tokens. ## Installation ```bash npm install metal-presale ``` ## Quick Start ### Client-Side Usage For browser/client-side applications: ```typescript import { MetalPresalesClient } from 'metal-presale/client' const metal = new MetalPresalesClient({ publicApiKey: process.env.NEXT_PUBLIC_METAL_PUBLIC_KEY!, apiBasePath: '/api/metal' // Your API route base path }) // Public operations (no server required) const holder = await metal.getHolder('user123') const portfolio = await metal.getHolderWithPortfolio('user123') const presale = await metal.getPresale('presale-id') // Server-proxied operations (requires API routes) await metal.createUser('user123') await metal.buyPresale('user123', 'presale-id', 100) await metal.buyTokens('user123', '0x...', 50) ``` ### Server-Side Usage For server-side applications and API routes: ```typescript import { MetalPresalesServer } from 'metal-presale/server' const metal = new MetalPresalesServer({ publicApiKey: process.env.NEXT_PUBLIC_METAL_PUBLIC_KEY!, secretApiKey: process.env.METAL_SECRET_KEY! }) // All operations available const holder = await metal.getOrCreateHolder('user123') const presales = await metal.getActivePresales() await metal.buyPresale('user123', { presaleId: 'abc', usdcAmount: 100 }) ``` ### Next.js API Routes (Recommended) The easiest way to set up all API routes in Next.js: 1. Create `app/api/metal/[...action]/route.ts`: ```typescript export { GET, POST } from 'metal-presale/next' ``` That's it! This automatically creates all the required endpoints: - `POST /api/metal/users/create` - `GET /api/metal/presales/active` - `POST /api/metal/presales/buy` - `POST /api/metal/tokens/buy` - `POST /api/metal/tokens/sell` - `POST /api/metal/tokens/quote-buy` - `POST /api/metal/tokens/quote-sell` ### Environment Variables ```env # Required for both client and server NEXT_PUBLIC_METAL_PUBLIC_KEY=your-public-key # Required for server-side only METAL_SECRET_KEY=your-secret-key ``` ## Core Features ### 🎯 Portfolio Management Get holder data with calculated portfolio values: ```typescript const { holder, portfolio } = await metal.getHolderWithPortfolio(userId) console.log(portfolio.buyingPower) // USDC balance console.log(portfolio.holdings) // Value of non-USDC tokens console.log(portfolio.vaulted) // Value of locked tokens console.log(portfolio.totalValue) // Total portfolio value ``` ### 🚀 Presale Operations ```typescript // Get only active presales const activePresales = await metal.getActivePresales() // Get presale with utility functions import { getPresaleProgress, getPresaleTimeRemaining, formatTimeRemaining } from 'metal-presale' const presale = await metal.getPresale(presaleId) const progress = getPresaleProgress(presale) // Returns 0-100 const timeLeft = getPresaleTimeRemaining(presale) // Returns milliseconds const timeString = formatTimeRemaining(timeLeft) // "2 days remaining" ``` ### 💰 Token Operations ```typescript // Get quotes before transactions const buyQuote = await metal.quoteBuyTokens(userId, { tokenAddress: '0x...', usdcAmount: 100 }) const sellQuote = await metal.quoteSellTokens(userId, { tokenAddress: '0x...', tokenAmount: 50 }) // Execute transactions const buyResult = await metal.buyTokens(userId, { tokenAddress: '0x...', usdcAmount: 100 }) const sellResult = await metal.sellTokens(userId, { tokenAddress: '0x...', tokenAmount: 50 }) ``` ## Utility Functions ```typescript import { calculatePortfolioSummary, isPresaleActive, getPresaleProgress, getPresaleTimeRemaining, formatTimeRemaining, filterTokensByType, calculateTotalValue, findToken, sortTokensByValue, getUnlockedTokens } from 'metal-presale' // Use these utilities for common operations const presaleTokens = filterTokensByType(holder.tokens, 'presale') const totalPresaleValue = calculateTotalValue(presaleTokens) const usdcToken = findToken(holder.tokens, 'USDC') const sortedTokens = sortTokensByValue(holder.tokens) ``` ## TypeScript Support The SDK is fully typed. All types are exported: ```typescript import type { HolderResponse, PortfolioSummary, PresaleResponse, TokenLikeItem, BuyPresaleParams, BuyTokensParams, SellTokensParams, QuoteBuyTokensParams, QuoteSellTokensParams } from 'metal-presale/client' ``` ## Security Best Practices 1. **Never expose your secret key**: The secret key should only be used server-side 2. **Use the client SDK in browsers**: It only includes public operations and API calls 3. **Set up API routes**: Use the built-in Next.js handlers for secure server operations 4. **Validate inputs**: Always validate user inputs in your API routes ## Advanced Usage ### Custom API Configuration ```typescript const metal = new MetalPresalesClient({ publicApiKey: 'your-key', apiBasePath: '/custom/api/path' // Default: '/api/metal' }) ``` ### Error Handling ```typescript try { await metal.buyPresale('user123', 'presale-id', 100) } catch (error) { if (error.message.includes('Insufficient balance')) { // Handle insufficient funds } // Handle other errors } ``` ## Migration Guide ### From Direct API Calls **Before:** ```typescript // Manual portfolio calculations const buyingPower = holder.tokens?.find(t => t.symbol === 'USDC')?.balance || 0 const holdings = holder.tokens ?.filter(t => t.symbol !== 'USDC') ?.reduce((sum, token) => sum + token.value, 0) || 0 ``` **After:** ```typescript // Automatic portfolio calculations const { portfolio } = await metal.getHolderWithPortfolio(userId) // portfolio.buyingPower, portfolio.holdings already calculated ``` ### From Manual Presale Filtering **Before:** ```typescript // Manual presale filtering const presales = await fetch('/api/presales/list') const activePresales = presales.filter(p => { // Complex logic to determine if active }) ``` **After:** ```typescript // Built-in active presale filtering const activePresales = await metal.getActivePresales() ```