UNPKG

@cygnus-wealth/wallet-integration-system

Version:

Multi-chain wallet integration system for CygnusWealth

117 lines (116 loc) 4.48 kB
import { TokenPriceService } from './TokenPriceService'; export class PortfolioCalculator { priceService; constructor() { this.priceService = TokenPriceService.getInstance(); } async calculatePortfolioValue(balances) { const portfolioItems = []; let totalValue = 0; const tokenPriceRequests = balances.map(balance => ({ address: balance.asset.contractAddress || balance.asset.symbol, chain: balance.chain, coingeckoId: balance.asset.metadata?.coingeckoId })); const prices = await this.priceService.getMultipleTokenPrices(tokenPriceRequests); for (const balance of balances) { const priceKey = `${balance.chain}-${balance.asset.contractAddress || balance.asset.symbol}`; const price = prices.get(priceKey); let value = 0; if (price) { value = parseFloat(balance.amount) * (price.amount || price.value || 0); balance.value = price; } const portfolioItem = { id: `${balance.walletAddress}-${balance.assetId}`, accountId: balance.walletAddress, assetId: balance.assetId, asset: balance.asset, balance: balance, value: { amount: value, currency: 'USD', timestamp: new Date() }, allocation: 0, // Will be calculated after total lastUpdated: balance.lastUpdated }; portfolioItems.push(portfolioItem); totalValue += value; } // Calculate allocations for (const item of portfolioItems) { item.allocation = totalValue > 0 ? (item.value.amount / totalValue) * 100 : 0; } const portfolio = { id: 'wallet-portfolio', name: 'Wallet Portfolio', items: portfolioItems, totalValue: { amount: totalValue, currency: 'USD', timestamp: new Date() }, lastUpdated: new Date(), metadata: { balanceCount: balances.length, chains: Array.from(new Set(balances.map(b => b.chain))) } }; return portfolio; } calculateChainBreakdown(portfolio) { const chainValues = new Map(); for (const item of portfolio.items || []) { const chain = item.balance?.chain || item.asset.chain; if (chain) { const currentValue = chainValues.get(chain) || 0; chainValues.set(chain, currentValue + (item.value.amount || 0)); } } const breakdown = new Map(); const totalValue = portfolio.totalValue.amount || 0; for (const [chain, value] of chainValues) { breakdown.set(chain, { value, percentage: totalValue > 0 ? (value / totalValue) * 100 : 0 }); } return breakdown; } calculateAssetTypeBreakdown(portfolio) { const typeValues = new Map(); for (const item of portfolio.items || []) { const type = item.asset.type; const currentValue = typeValues.get(type) || 0; typeValues.set(type, currentValue + (item.value.amount || 0)); } const breakdown = new Map(); const totalValue = portfolio.totalValue.amount || 0; for (const [type, value] of typeValues) { breakdown.set(type, { value, percentage: totalValue > 0 ? (value / totalValue) * 100 : 0 }); } return breakdown; } getTopAssets(portfolio, limit = 10) { return [...(portfolio.items || [])] .sort((a, b) => (b.value.amount || 0) - (a.value.amount || 0)) .slice(0, limit); } filterByChain(portfolio, chain) { const filteredItems = (portfolio.items || []).filter(item => (item.balance?.chain || item.asset.chain) === chain); const totalValue = filteredItems.reduce((sum, item) => sum + (item.value.amount || 0), 0); return { ...portfolio, items: filteredItems, totalValue: { amount: totalValue, currency: 'USD', timestamp: new Date() } }; } }