{"version":3,"file":"fACrZ78x.js","sources":["../../../../../../src/lib/serializers/UserSerializer.ts","../../../../../../src/lib/serializers/TransactionSerializer.ts","../../../../../../src/lib/api/users.ts"],"sourcesContent":["// UserSerializer.ts\n// Serializer for user data with principal ID cleaning\n\nimport { BaseSerializer } from './BaseSerializer';\nimport { truncateAddress } from '$lib/utils/principalUtils';\n\nexport class UserSerializer extends BaseSerializer {\n /**\n * Cleans a principal ID by removing '-2' suffix if present\n * @param principalId - The principal ID to clean\n * @returns Cleaned principal ID\n */\n static cleanPrincipalId(principalId: string): string {\n if (!principalId) return '';\n return principalId.endsWith('-2') ? principalId.slice(0, -2) : principalId;\n }\n\n /**\n * Serializes a user object including cleaning the principal ID\n * @param user - The raw user object\n * @returns Serialized user with cleaned principal ID\n */\n static serializeUser(user: unknown): any {\n if (!user || typeof user !== 'object') return null;\n \n const userData = user as Record;\n const principalId = this.toString(userData.principal_id);\n \n return {\n ...userData,\n principal_id: this.cleanPrincipalId(principalId),\n // Add any other user properties that need serialization here\n };\n }\n\n /**\n * Serializes an array of users\n * @param users - Array of raw user objects\n * @returns Array of serialized users with cleaned principal IDs\n */\n static serializeUsers(users: unknown[]): any[] {\n if (!Array.isArray(users)) return [];\n \n return users.map(user => this.serializeUser(user));\n }\n\n /**\n * Serializes a user response object that contains items array\n * @param response - The raw API response containing users\n * @returns Serialized response with cleaned user principal IDs\n */\n static serializeUsersResponse(response: unknown): any {\n if (!response || typeof response !== 'object') return { items: [] };\n \n const data = response as Record;\n \n if (Array.isArray(data.items)) {\n return {\n ...data,\n items: this.serializeUsers(data.items)\n };\n }\n \n return data;\n }\n} ","// TransactionSerializer.ts\n// Serializer for transaction data\n\nimport { BaseSerializer } from './BaseSerializer';\n\nexport class TransactionSerializer extends BaseSerializer {\n /**\n * Serializes the response from user transactions API\n * @param data - The raw API response\n * @returns Formatted transaction response\n */\n static serializeTransactionsResponse(data: any): { \n transactions: any[], \n has_more: boolean, \n next_cursor?: number \n } {\n if (!data) {\n return {\n transactions: [],\n has_more: false\n };\n }\n\n const items = Array.isArray(data.items) ? data.items : \n Array.isArray(data) ? data :\n data.transaction ? [data] : [];\n\n return {\n transactions: items.map(item => this.serializeTransaction(item)).filter(Boolean),\n has_more: data.has_more || false,\n next_cursor: data.next_cursor\n };\n }\n\n /**\n * Serializes a single transaction\n * @param item - The raw transaction item\n * @returns Formatted transaction or null if invalid\n */\n static serializeTransaction(item: any): any {\n if (!item) return null;\n \n const tx = item.transaction || item;\n const tokens = item.tokens || [];\n \n if (!tx) return null;\n \n // Handle different transaction types\n switch (tx.tx_type) {\n case 'RemoveLiquidity':\n case 'AddLiquidity':\n return this.serializeLiquidityTransaction(tx, tokens);\n case 'Swap':\n return this.serializeSwapTransaction(tx, tokens);\n case 'Send':\n return this.serializeSendTransaction(tx, tokens);\n default:\n return null;\n }\n }\n\n /**\n * Serializes a liquidity transaction (add or remove)\n * @param tx - The raw transaction\n * @param tokens - The tokens involved\n * @returns Formatted liquidity transaction\n */\n private static serializeLiquidityTransaction(tx: any, tokens: any[]): any {\n const rawTx = tx.raw_json?.[`${tx.tx_type}Tx`];\n if (!rawTx) return null;\n\n // Find the tokens in the response\n const token0 = tokens.find((t: any) => t.token_id === tokens[0]?.token_id);\n const token1 = tokens.find((t: any) => t.token_id === tokens[1]?.token_id);\n const lpToken = tokens.find((t: any) => t.token_type === 'Lp');\n\n // Format amounts based on token decimals\n const formattedAmount0 = this.formatTokenAmount(\n rawTx.amount_0, \n token0?.decimals || 8\n );\n \n const formattedAmount1 = this.formatTokenAmount(\n rawTx.amount_1, \n token1?.decimals || 8\n );\n \n const lpAmount = tx.tx_type === 'AddLiquidity' \n ? rawTx.add_lp_token_amount \n : rawTx.remove_lp_token_amount;\n \n const formattedLpAmount = this.formatTokenAmount(\n lpAmount, \n lpToken?.decimals || 8\n );\n\n return {\n tx_id: rawTx.tx_id,\n tx_type: tx.tx_type === 'RemoveLiquidity' ? 'remove_liquidity' : 'add_liquidity',\n status: rawTx.status || 'Success',\n timestamp: rawTx.ts.toString(),\n details: {\n token_0_id: token0?.token_id,\n token_1_id: token1?.token_id,\n token_0_symbol: token0?.symbol || `Token ${token0?.token_id}`,\n token_1_symbol: token1?.symbol || `Token ${token1?.token_id}`,\n token_0_canister: token0?.canister_id || '',\n token_1_canister: token1?.canister_id || '',\n amount_0: formattedAmount0,\n amount_1: formattedAmount1,\n lp_token_symbol: lpToken?.symbol || '',\n lp_token_amount: formattedLpAmount,\n pool_id: rawTx.pool_id,\n lp_fee_0: this.formatTokenAmount(rawTx.lp_fee_0, token0?.decimals || 8),\n lp_fee_1: this.formatTokenAmount(rawTx.lp_fee_1, token1?.decimals || 8)\n }\n };\n }\n\n /**\n * Serializes a swap transaction\n * @param tx - The raw transaction\n * @param tokens - The tokens involved\n * @returns Formatted swap transaction\n */\n private static serializeSwapTransaction(tx: any, tokens: any[]): any {\n const rawTx = tx.raw_json?.SwapTx;\n if (!rawTx) return null;\n\n // Find the tokens in the response\n const payToken = tokens.find((t: any) => t.token_id === rawTx.pay_token_id);\n const receiveToken = tokens.find((t: any) => t.token_id === rawTx.receive_token_id);\n\n // Format amounts based on token decimals\n const formattedPayAmount = this.formatTokenAmount(\n rawTx.pay_amount, \n payToken?.decimals || 8\n );\n \n const formattedReceiveAmount = this.formatTokenAmount(\n rawTx.receive_amount, \n receiveToken?.decimals || 8\n );\n\n return {\n tx_id: rawTx.tx_id,\n tx_type: 'swap',\n status: rawTx.status || 'Success',\n timestamp: rawTx.ts.toString(),\n details: {\n pay_amount: formattedPayAmount,\n receive_amount: formattedReceiveAmount,\n pay_token_id: rawTx.pay_token_id,\n receive_token_id: rawTx.receive_token_id,\n pool_id: rawTx.pool_id,\n price: rawTx.price?.toString() || \"0\",\n slippage: rawTx.slippage?.toString() || \"0\",\n pay_token_symbol: payToken?.symbol || `Token ${rawTx.pay_token_id}`,\n receive_token_symbol: receiveToken?.symbol || `Token ${rawTx.receive_token_id}`,\n pay_token_canister: payToken?.canister_id || '',\n receive_token_canister: receiveToken?.canister_id || '',\n gas_fee: this.formatTokenAmount(rawTx.gas_fee, payToken?.decimals || 8),\n lp_fee: this.formatTokenAmount(rawTx.lp_fee, payToken?.decimals || 8)\n }\n };\n }\n\n /**\n * Serializes a send transaction\n * @param tx - The raw transaction\n * @param tokens - The tokens involved\n * @returns Formatted send transaction\n */\n private static serializeSendTransaction(tx: any, tokens: any[]): any {\n const rawTx = tx.raw_json?.SendTx || tx;\n if (!rawTx) return null;\n\n // Find the token in the response\n const token = tokens.find((t: any) => \n t.token_id === rawTx.token_id || \n t.canister_id === rawTx.token_canister\n );\n\n // Format amount based on token decimals\n const formattedAmount = this.formatTokenAmount(\n rawTx.amount, \n token?.decimals || 8\n );\n\n return {\n tx_id: rawTx.tx_id || rawTx.id || `send-${Date.now()}`,\n tx_type: 'send',\n status: rawTx.status || 'Success',\n timestamp: rawTx.ts?.toString() || rawTx.timestamp?.toString() || Date.now().toString(),\n details: {\n amount: formattedAmount,\n token_id: rawTx.token_id || '',\n token_symbol: token?.symbol || rawTx.token_symbol || 'Unknown',\n token_canister: token?.canister_id || rawTx.token_canister || '',\n from: rawTx.from || tx.from || '',\n to: rawTx.to || tx.to || '',\n fee: this.formatTokenAmount(rawTx.fee, token?.decimals || 8)\n }\n };\n }\n} ","import { API_URL } from \"./index\";\nimport { UserSerializer } from \"../serializers/UserSerializer\";\nimport { TransactionSerializer } from \"../serializers/TransactionSerializer\";\n\nexport interface UsersResponse {\n items: Array<{\n user_id: number;\n principal_id: string;\n my_referral_code: string;\n referred_by: string | null;\n fee_level: number;\n }>;\n next_cursor: string | null;\n has_more: boolean;\n limit: number;\n}\n\nexport async function fetchUsers(principal_id?: string): Promise {\n const url = new URL(`${API_URL}/api/users`);\n if (principal_id) {\n // Clean principal ID before sending to the API\n const cleanPrincipalId = UserSerializer.cleanPrincipalId(principal_id);\n url.searchParams.set('principal_id', cleanPrincipalId);\n url.searchParams.set('limit', '40');\n }\n \n const response = await fetch(url.toString());\n if (!response.ok) {\n throw new Error(`Failed to fetch users: ${response.statusText}`);\n }\n \n // Get the raw response data\n const rawData = await response.json();\n \n // Use the serializer to process the response\n return UserSerializer.serializeUsersResponse(rawData) as UsersResponse;\n}\n\n\n /**\n * Gets the transaction endpoint URL\n * @private\n */\n function getTransactionEndpoint(\n principalId: string, \n tx_type: string, \n queryParams: URLSearchParams\n ): string {\n if (tx_type === 'pool') {\n return `${API_URL}/api/users/${principalId}/transactions/liquidity?${queryParams.toString()}`;\n } else if (tx_type === 'send') {\n return `${API_URL}/api/users/${principalId}/transactions/send?${queryParams.toString()}`;\n } else {\n return `${API_URL}/api/users/${principalId}/transactions/swap?${queryParams.toString()}`;\n }\n }\n\n /**\n * Fetches user transactions\n */\n export async function fetchUserTransactions(\n principalId: string, \n cursor?: number,\n limit: number = 40, \n tx_type: 'swap' | 'pool' | 'send' = 'swap'\n ): Promise<{ transactions: any[], has_more: boolean, next_cursor?: number }> {\n try {\n // Debug log\n console.log(`Fetching transactions for ${principalId}`, { cursor, limit, tx_type });\n \n const queryParams = new URLSearchParams({\n limit: limit.toString(),\n });\n\n if (cursor) {\n queryParams.append('cursor', cursor.toString());\n }\n \n // Determine the appropriate endpoint based on transaction type\n const url = getTransactionEndpoint(principalId, tx_type, queryParams);\n console.log(`Fetching from URL: ${url}`);\n \n const response = await fetch(url);\n const responseText = await response.text();\n \n // Debug log\n console.log(`Response status: ${response.status}, response text length: ${responseText.length}`);\n \n // Handle empty response\n if (!responseText.trim()) {\n console.log('Empty response received');\n return {\n transactions: [],\n has_more: false\n };\n }\n \n // Parse the response\n const result = parseTransactionResponse(response, responseText, url);\n console.log(`Parsed ${result.transactions.length} transactions, has_more: ${result.has_more}`);\n return result;\n } catch (error) {\n console.error(\"Error fetching user transactions:\", {\n error,\n principalId,\n cursor,\n limit,\n tx_type\n });\n \n return {\n transactions: [],\n has_more: false\n };\n }\n }\n\n function parseTransactionResponse(\n response: Response, \n responseText: string, \n url: string\n ): { transactions: any[], has_more: boolean, next_cursor?: number } {\n let data;\n try {\n data = JSON.parse(responseText);\n console.log(\"API response data structure:\", {\n hasItems: !!data?.items,\n itemsLength: data?.items?.length,\n firstItem: data?.items?.[0] ? Object.keys(data.items[0]) : null\n });\n } catch (parseError) {\n console.error('Failed to parse response as JSON:', {\n error: parseError,\n responseText: responseText.substring(0, 200) + '...', // Log a preview of the response\n status: response.status,\n headers: Object.fromEntries(response.headers.entries())\n });\n \n return {\n transactions: [],\n has_more: false\n };\n }\n \n if (!response.ok) {\n console.error('HTTP error:', {\n status: response.status,\n statusText: response.statusText,\n data: data,\n url: url\n });\n return {\n transactions: [],\n has_more: false\n };\n }\n\n if (!data) {\n console.log('No data received from API');\n return {\n transactions: [],\n has_more: false\n };\n }\n\n try {\n // Support different API response formats\n // If the response doesn't have an items array but is an array itself\n if (!data.items && Array.isArray(data)) {\n console.log('API returned direct array format');\n data = { items: data, has_more: false };\n }\n \n // If the response isn't in the expected format but has transactions\n if (!data.items && data.transactions) {\n console.log('API returned transactions object format');\n data = { \n items: data.transactions, \n has_more: data.has_more || false,\n next_cursor: data.next_cursor\n };\n }\n \n // Process all items to make sure timestamps are valid\n if (data.items && Array.isArray(data.items)) {\n data.items = data.items.map(item => {\n // Safely process each transaction's timestamp\n if (item?.transaction?.ts) {\n try {\n let timestamp;\n \n // Handle different timestamp formats\n if (typeof item.transaction.ts === 'string') {\n // Check if it's an ISO date string\n if (item.transaction.ts.includes('T')) {\n // For ISO strings, keep the original string format\n // We'll convert it at display time in the UI\n timestamp = item.transaction.ts;\n // Still verify it parses to a valid date\n new Date(timestamp).toISOString();\n return item;\n } else {\n // Try numeric conversion\n timestamp = Number(item.transaction.ts);\n \n // Handle nanosecond timestamps\n if (timestamp > 1e15) {\n timestamp = Math.floor(timestamp / 1_000_000);\n item.transaction.ts = timestamp.toString();\n }\n }\n } else {\n timestamp = Number(item.transaction.ts);\n }\n \n // Only replace if completely invalid (can't be parsed)\n if (isNaN(timestamp)) {\n console.warn('Invalid timestamp format, replacing with current time:', item.transaction.ts);\n item.transaction.ts = Date.now().toString();\n } else {\n // Keep the valid timestamp (even if it appears to be in the future)\n new Date(timestamp).toISOString(); // Just verify it works\n }\n } catch (e) {\n // If date is completely invalid, replace with current timestamp\n console.warn('Invalid timestamp detected, replacing with current time:', item.transaction.ts);\n item.transaction.ts = Date.now().toString();\n }\n }\n \n // If the transaction has a raw_json field with timestamps\n if (item?.transaction?.raw_json) {\n Object.keys(item.transaction.raw_json).forEach(key => {\n const rawJson = item.transaction.raw_json[key];\n if (rawJson && rawJson.ts) {\n try {\n let timestamp;\n \n // Handle different timestamp formats\n if (typeof rawJson.ts === 'string') {\n // Check if it's an ISO date string\n if (rawJson.ts.includes('T')) {\n // For ISO strings, keep the original string format\n timestamp = rawJson.ts;\n // Still verify it parses to a valid date\n new Date(timestamp).toISOString();\n return;\n } else {\n // Try numeric conversion\n timestamp = Number(rawJson.ts);\n \n // Handle nanosecond timestamps\n if (timestamp > 1e15) {\n timestamp = Math.floor(timestamp / 1_000_000);\n rawJson.ts = timestamp.toString();\n }\n }\n } else {\n timestamp = Number(rawJson.ts);\n }\n \n // Only replace if completely invalid (can't be parsed)\n if (isNaN(timestamp)) {\n console.warn('Invalid raw_json timestamp format, replacing with current time:', rawJson.ts);\n rawJson.ts = Date.now().toString();\n } else {\n // Keep the valid timestamp (even if it appears to be in the future)\n new Date(timestamp).toISOString(); // Just verify it works\n }\n } catch (e) {\n // If date is completely invalid, replace with current timestamp\n console.warn('Invalid raw_json timestamp detected, replacing with current time:', rawJson.ts);\n rawJson.ts = Date.now().toString();\n }\n }\n });\n }\n \n return item;\n });\n }\n \n // Create mock data for testing if no items exist\n if (!data.items || !Array.isArray(data.items) || data.items.length === 0) {\n // For testing only - this would typically be removed in production\n console.log('No items in response - using mock data for testing');\n const now = Date.now();\n data = { \n items: [\n {\n transaction: {\n tx_id: 'mock-tx1',\n tx_type: 'swap',\n status: 'Success',\n ts: now - 1000 * 60 * 30, // 30 minutes ago\n details: {\n pay_token_symbol: 'ETH',\n receive_token_symbol: 'USDC',\n pay_amount: 0.1,\n receive_amount: 189.34,\n price: 1894.3\n }\n }\n },\n {\n transaction: {\n tx_id: 'mock-tx2',\n tx_type: 'add_liquidity',\n status: 'Success',\n ts: now - 1000 * 60 * 60 * 2, // 2 hours ago\n details: {\n token_0_symbol: 'KONG',\n token_1_symbol: 'ETH',\n amount_0: 100,\n amount_1: 0.05,\n lp_token_amount: 22.33,\n pool_id: 'mock-pool-1'\n }\n }\n }\n ],\n has_more: false\n };\n }\n } catch (processingError) {\n console.error('Error processing transaction data:', processingError);\n // Return an empty result instead of throwing\n return {\n transactions: [],\n has_more: false\n };\n }\n\n try {\n // Use the TransactionSerializer to process the response\n const result = TransactionSerializer.serializeTransactionsResponse(data);\n \n // Log some details about the serialized result\n console.log(\"Serialized transactions:\", {\n count: result.transactions.length,\n types: result.transactions.map(t => t.tx_type),\n firstTransaction: result.transactions[0] ? {\n id: result.transactions[0].tx_id,\n type: result.transactions[0].tx_type,\n status: result.transactions[0].status,\n // Safely format the timestamp\n timestamp: result.transactions[0].timestamp ? \n new Date(Number(result.transactions[0].timestamp) > 1e15 ? \n Number(result.transactions[0].timestamp) / 1_000_000 : \n Number(result.transactions[0].timestamp)\n ).toISOString() : 'no timestamp'\n } : null\n });\n \n return result;\n } catch (serializerError) {\n console.error('Error during transaction serialization:', serializerError);\n // Return empty result instead of throwing\n return {\n transactions: [],\n has_more: false\n };\n }\n }\n"],"names":["UserSerializer","BaseSerializer","cleanPrincipalId","principalId","endsWith","slice","serializeUser","user","userData","this","toString","principal_id","serializeUsers","users","Array","isArray","map","serializeUsersResponse","response","items","data","TransactionSerializer","serializeTransactionsResponse","transactions","has_more","transaction","item","serializeTransaction","filter","Boolean","next_cursor","tx","tokens","tx_type","serializeLiquidityTransaction","serializeSwapTransaction","serializeSendTransaction","rawTx","_a","raw_json","token0","find","t","token_id","token1","lpToken","token_type","formattedAmount0","formatTokenAmount","amount_0","decimals","formattedAmount1","amount_1","lpAmount","add_lp_token_amount","remove_lp_token_amount","formattedLpAmount","tx_id","status","timestamp","ts","details","token_0_id","token_1_id","token_0_symbol","symbol","token_1_symbol","token_0_canister","canister_id","token_1_canister","lp_token_symbol","lp_token_amount","pool_id","lp_fee_0","lp_fee_1","SwapTx","payToken","pay_token_id","receiveToken","receive_token_id","formattedPayAmount","pay_amount","formattedReceiveAmount","receive_amount","price","_b","slippage","_c","pay_token_symbol","receive_token_symbol","pay_token_canister","receive_token_canister","gas_fee","lp_fee","SendTx","token","token_canister","formattedAmount","amount","id","Date","now","token_symbol","from","to","fee","async","fetchUsers","url","URL","API_URL","searchParams","set","fetch","ok","Error","statusText","rawData","json","fetchUserTransactions","cursor","limit","console","log","queryParams","URLSearchParams","append","getTransactionEndpoint","responseText","text","length","trim","result","JSON","parse","hasItems","itemsLength","firstItem","Object","keys","parseError","error","substring","headers","fromEntries","entries","includes","toISOString","Number","Math","floor","isNaN","warn","e","forEach","key","rawJson","processingError","count","types","firstTransaction","type","serializerError","parseTransactionResponse"],"mappings":"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"}