@liberfi.io/ui-portfolio 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/index.d.mts +16 -0
- package/dist/client/index.d.ts +16 -0
- package/dist/client/index.js +2 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/index.mjs +2 -0
- package/dist/client/index.mjs.map +1 -0
- package/dist/index-Bm8Qidtb.d.mts +253 -0
- package/dist/index-Bm8Qidtb.d.ts +253 -0
- package/dist/index.d.mts +342 -0
- package/dist/index.d.ts +342 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +3 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { I as IPortfolioClient, P as PortfolioQuery, b as PortfolioOverview, S as SpotHoldingsData, l as SpotHistoryQuery, d as SpotHistoryData, o as CurveQuery, c as CurveData, e as PerpsPositionsData, m as PerpsHistoryQuery, f as PerpsHistoryData, g as PredictionBetsData, n as PredictionSettledQuery, h as PredictionSettledData } from '../index-Bm8Qidtb.mjs';
|
|
2
|
+
|
|
3
|
+
declare class PortfolioClient implements IPortfolioClient {
|
|
4
|
+
private readonly endpoint;
|
|
5
|
+
constructor(endpoint: string);
|
|
6
|
+
getOverview(query?: PortfolioQuery): Promise<PortfolioOverview>;
|
|
7
|
+
getSpotHoldings(query?: PortfolioQuery): Promise<SpotHoldingsData>;
|
|
8
|
+
getSpotHistory(query?: SpotHistoryQuery): Promise<SpotHistoryData>;
|
|
9
|
+
getChartData(query: CurveQuery): Promise<CurveData>;
|
|
10
|
+
getPerpsPositions(_query?: PortfolioQuery): Promise<PerpsPositionsData>;
|
|
11
|
+
getPerpsHistory(_query?: PerpsHistoryQuery): Promise<PerpsHistoryData>;
|
|
12
|
+
getPredictionBets(_query?: PortfolioQuery): Promise<PredictionBetsData>;
|
|
13
|
+
getPredictionSettled(_query?: PredictionSettledQuery): Promise<PredictionSettledData>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export { PortfolioClient };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { I as IPortfolioClient, P as PortfolioQuery, b as PortfolioOverview, S as SpotHoldingsData, l as SpotHistoryQuery, d as SpotHistoryData, o as CurveQuery, c as CurveData, e as PerpsPositionsData, m as PerpsHistoryQuery, f as PerpsHistoryData, g as PredictionBetsData, n as PredictionSettledQuery, h as PredictionSettledData } from '../index-Bm8Qidtb.js';
|
|
2
|
+
|
|
3
|
+
declare class PortfolioClient implements IPortfolioClient {
|
|
4
|
+
private readonly endpoint;
|
|
5
|
+
constructor(endpoint: string);
|
|
6
|
+
getOverview(query?: PortfolioQuery): Promise<PortfolioOverview>;
|
|
7
|
+
getSpotHoldings(query?: PortfolioQuery): Promise<SpotHoldingsData>;
|
|
8
|
+
getSpotHistory(query?: SpotHistoryQuery): Promise<SpotHistoryData>;
|
|
9
|
+
getChartData(query: CurveQuery): Promise<CurveData>;
|
|
10
|
+
getPerpsPositions(_query?: PortfolioQuery): Promise<PerpsPositionsData>;
|
|
11
|
+
getPerpsHistory(_query?: PerpsHistoryQuery): Promise<PerpsHistoryData>;
|
|
12
|
+
getPredictionBets(_query?: PortfolioQuery): Promise<PredictionBetsData>;
|
|
13
|
+
getPredictionSettled(_query?: PredictionSettledQuery): Promise<PredictionSettledData>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export { PortfolioClient };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
'use strict';var utils=require('@liberfi.io/utils');function i(r){if(!r)return 0;let e=Number(r);return Number.isFinite(e)?e:0}var a=class{constructor(e){this.endpoint=e;}async getOverview(e){let n=l(e),o=await utils.get(`${this.endpoint}/portfolio/overview${n}`);return {totalValue:i(o.totalBalanceUsd),uPnl:i(o.unrealizedPnl),realizedPnl:i(o.realizedPnl),totalProfit:i(o.totalProfitUsd),winRate:i(o.winRate)}}async getSpotHoldings(e){let n=l(e);return {holdings:((await utils.get(`${this.endpoint}/portfolio/spot/holdings${n}`)).holdings??[]).map(t=>({tokenAddress:t.tokenAddress,name:t.name,symbol:t.symbol,image:t.imageUrl??"",chain:t.chain??"",balance:i(t.balance),price:i(t.priceUsd),value:i(t.valueUsd),change24h:i(t.priceChange24h),unrealizedPnl:i(t.unrealizedPnl),realizedPnl:i(t.realizedPnl),walletAddress:t.walletAddress??"",verified:false}))}}async getSpotHistory(e){let n=u(e),o=await utils.get(`${this.endpoint}/portfolio/spot/history${n}`);return {trades:(o.trades??[]).map(t=>({type:c(t.type),tokenSymbol:t.tokenSymbol??"",tokenName:t.tokenName??"",tokenImageUrl:t.tokenImageUrl??"",tokenAddress:t.tokenAddress??"",tokenAmount:i(t.tokenAmount),valueUsd:i(t.valueUsd),priceUsd:i(t.priceUsd),sideTokenSymbol:t.sideTokenSymbol??"",sideTokenAmount:i(t.sideTokenAmount),dex:t.dex??"",txHash:t.txHash??"",chain:t.chain??"",walletAddress:t.walletAddress??"",timestamp:d(t.timestamp)})),nextCursor:o.nextCursor??"",hasNext:o.hasNext??false}}async getChartData(e){let n=new URLSearchParams;if(n.set("period",e.period.toString()),e.walletAddresses?.length)for(let t of e.walletAddresses)n.append("walletAddresses",t);return e.chain&&n.set("chain",e.chain),{points:((await utils.get(`${this.endpoint}/portfolio/chart?${n.toString()}`)).dataPoints??[]).map(t=>({timestamp:d(t.timestamp),netWorth:i(t.netWorth),change:i(t.change),changePercent:i(t.changePercent)}))}}async getPerpsPositions(e){return {positions:[],totalValue:0}}async getPerpsHistory(e){return {records:[],hasMore:false}}async getPredictionBets(e){return {bets:[],totalValue:0}}async getPredictionSettled(e){return {records:[],hasMore:false}}};function l(r){if(!r)return "";let e=new URLSearchParams;if(r.walletAddresses?.length)for(let o of r.walletAddresses)e.append("walletAddresses",o);r.chain&&e.set("chain",r.chain);let n=e.toString();return n?`?${n}`:""}function u(r){if(!r)return "";let e=new URLSearchParams;if(r.walletAddresses?.length)for(let o of r.walletAddresses)e.append("walletAddresses",o);r.chain&&e.set("chain",r.chain),r.cursor&&e.set("cursor",r.cursor),r.limit!==void 0&&e.set("limit",r.limit.toString());let n=e.toString();return n?`?${n}`:""}function c(r){let e=r?.toLowerCase();return e==="send"||e==="transfer_out"?"send":e==="receive"||e==="transfer_in"?"receive":"swap"}function d(r){if(!r)return 0;let e=Number(r);if(Number.isFinite(e))return e<1e12?e*1e3:e;let n=Date.parse(r);return Number.isFinite(n)?n:0}exports.PortfolioClient=a;//# sourceMappingURL=index.js.map
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/index.ts","../../src/client/index.ts"],"names":["parseDecimal","raw","n","PortfolioClient","endpoint","query","qs","buildQuery","dto","get","h","buildHistoryQuery","parseHistoryType","parseTimestamp","params","addr","p","_query","str","lower","d"],"mappings":"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","file":"index.js","sourcesContent":["import type { DistributionData, SpotHolding } from \"../types\";\n\n/**\n * Parse a decimal string to a number, returning 0 for empty / invalid values.\n */\nexport function parseDecimal(raw: string | undefined | null): number {\n if (!raw) return 0;\n const n = Number(raw);\n return Number.isFinite(n) ? n : 0;\n}\n\n/**\n * Format a number as a USD currency string.\n * - >= 1M → \"$1.2M\"\n * - >= 1K → \"$4.2K\"\n * - >= 1 → \"$1,234.56\"\n * - >= 0.01 → \"$0.42\"\n * - < 0.01 and > 0 → \"<$0.01\"\n * - 0 → \"$0.00\"\n */\nexport function formatUsd(value: number): string {\n const abs = Math.abs(value);\n const sign = value < 0 ? \"-\" : \"\";\n\n if (abs >= 1_000_000) {\n return `${sign}$${(abs / 1_000_000).toFixed(1)}M`;\n }\n if (abs >= 10_000) {\n return `${sign}$${(abs / 1_000).toFixed(1)}K`;\n }\n if (abs >= 1) {\n return `${sign}$${abs.toLocaleString(\"en-US\", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;\n }\n if (abs >= 0.01) {\n return `${sign}$${abs.toFixed(2)}`;\n }\n if (abs > 0) {\n return `${sign}<$0.01`;\n }\n return \"$0.00\";\n}\n\n/**\n * Format a signed USD value with + / - prefix for PnL display.\n */\nexport function formatSignedUsd(value: number): string {\n const formatted = formatUsd(Math.abs(value));\n if (value > 0) return `+${formatted}`;\n if (value < 0) return `-${formatted.replace(\"-\", \"\")}`;\n return formatted;\n}\n\n/**\n * Format a percentage value.\n * Returns \"+3.24%\" or \"-1.50%\"\n */\nexport function formatPercent(value: number): string {\n const sign = value > 0 ? \"+\" : \"\";\n return `${sign}${value.toFixed(2)}%`;\n}\n\n/**\n * Split a USD value into integer and decimal parts for display.\n * e.g., 12847.63 → { integer: \"12,847\", decimal: \".63\", sign: \"$\" }\n */\nexport function splitUsd(value: number): {\n sign: string;\n integer: string;\n decimal: string;\n} {\n const abs = Math.abs(value);\n const parts = abs.toFixed(2).split(\".\");\n const integer = Number(parts[0]).toLocaleString(\"en-US\");\n const decimal = `.${parts[1]}`;\n const sign = value < 0 ? \"-$\" : \"$\";\n return { sign, integer, decimal };\n}\n\n/**\n * Truncate an address to \"xxxx…xxxx\" format.\n */\nexport function truncateAddress(address: string, start = 4, end = 4): string {\n if (address.length <= start + end + 3) return address;\n return `${address.slice(0, start)}…${address.slice(-end)}`;\n}\n\n/**\n * Format a token balance with appropriate precision.\n */\nexport function formatTokenBalance(value: number): string {\n if (value === 0) return \"0\";\n if (value >= 1_000_000) return `${(value / 1_000_000).toFixed(2)}M`;\n if (value >= 1_000)\n return value.toLocaleString(\"en-US\", { maximumFractionDigits: 2 });\n if (value >= 1) return value.toFixed(2);\n if (value >= 0.0001) return value.toFixed(4);\n return \"<0.0001\";\n}\n\n/**\n * Build a Solana explorer URL for a transaction hash.\n * Defaults to Solscan. Can be extended for other chains in the future.\n */\nexport function getExplorerUrl(txHash: string, _chain?: string): string {\n return `https://solscan.io/tx/${txHash}`;\n}\n\n// ── Distribution Helpers ────────────────────────────────────────────────────\n\nconst DISTRIBUTION_COLORS = [\n \"#C8FF00\",\n \"#00E676\",\n \"#0066FF\",\n \"#FF6B9D\",\n \"#8B7BFF\",\n \"#FF5252\",\n \"#FFB74D\",\n \"#4DD0E1\",\n];\n\nconst OTHER_COLOR = \"#3A3A4E\";\n\n/**\n * Compute asset distribution from spot holdings for the donut chart.\n * Groups tokens with < 2% into \"Other\".\n */\nexport function computeDistribution(holdings: SpotHolding[]): DistributionData {\n const totalValue = holdings.reduce((sum, h) => sum + h.value, 0);\n if (totalValue <= 0) return { items: [] };\n\n const sorted = [...holdings].sort((a, b) => b.value - a.value);\n\n const items: DistributionData[\"items\"] = [];\n let otherValue = 0;\n let colorIdx = 0;\n\n for (const h of sorted) {\n const pct = (h.value / totalValue) * 100;\n if (pct < 2) {\n otherValue += h.value;\n } else {\n items.push({\n name: h.name,\n symbol: h.symbol,\n percent: pct,\n value: h.value,\n color: DISTRIBUTION_COLORS[colorIdx % DISTRIBUTION_COLORS.length],\n });\n colorIdx++;\n }\n }\n\n if (otherValue > 0) {\n items.push({\n name: \"Other\",\n symbol: \"OTHER\",\n percent: (otherValue / totalValue) * 100,\n value: otherValue,\n color: OTHER_COLOR,\n });\n }\n\n return { items };\n}\n\n/**\n * Format an epoch-ms timestamp for display in history tables.\n */\nexport function formatTime(epochMs: number): string {\n const d = new Date(epochMs);\n return d.toLocaleDateString(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n hour12: false,\n });\n}\n","import { get } from \"@liberfi.io/utils\";\nimport { SpotHistoryType } from \"../types\";\nimport type {\n CurveData,\n CurveQuery,\n GetPortfolioChartReply,\n GetSpotHoldingsReply,\n GetTradeHistoryReply,\n IPortfolioClient,\n PerpsHistoryData,\n PerpsHistoryQuery,\n PerpsPositionsData,\n PortfolioOverview,\n PortfolioOverviewDTO,\n PortfolioQuery,\n PredictionBetsData,\n PredictionSettledData,\n PredictionSettledQuery,\n SpotHistoryData,\n SpotHistoryQuery,\n SpotHoldingsData,\n} from \"../types\";\nimport { parseDecimal } from \"../utils\";\n\n// ── Client ──────────────────────────────────────────────────────────────────\n\nexport class PortfolioClient implements IPortfolioClient {\n constructor(private readonly endpoint: string) {}\n\n // ── Overview ──────────────────────────────────────────────────────────\n\n async getOverview(query?: PortfolioQuery): Promise<PortfolioOverview> {\n const qs = buildQuery(query);\n const dto = await get<PortfolioOverviewDTO>(\n `${this.endpoint}/portfolio/overview${qs}`,\n );\n return {\n totalValue: parseDecimal(dto.totalBalanceUsd),\n uPnl: parseDecimal(dto.unrealizedPnl),\n realizedPnl: parseDecimal(dto.realizedPnl),\n totalProfit: parseDecimal(dto.totalProfitUsd),\n winRate: parseDecimal(dto.winRate),\n };\n }\n\n // ── Spot Holdings ─────────────────────────────────────────────────────\n\n async getSpotHoldings(query?: PortfolioQuery): Promise<SpotHoldingsData> {\n const qs = buildQuery(query);\n const dto = await get<GetSpotHoldingsReply>(\n `${this.endpoint}/portfolio/spot/holdings${qs}`,\n );\n return {\n holdings: (dto.holdings ?? []).map((h) => ({\n tokenAddress: h.tokenAddress,\n name: h.name,\n symbol: h.symbol,\n image: h.imageUrl ?? \"\",\n chain: h.chain ?? \"\",\n balance: parseDecimal(h.balance),\n price: parseDecimal(h.priceUsd),\n value: parseDecimal(h.valueUsd),\n change24h: parseDecimal(h.priceChange24h),\n unrealizedPnl: parseDecimal(h.unrealizedPnl),\n realizedPnl: parseDecimal(h.realizedPnl),\n walletAddress: h.walletAddress ?? \"\",\n verified: false,\n })),\n };\n }\n\n // ── Spot History ──────────────────────────────────────────────────────\n\n async getSpotHistory(query?: SpotHistoryQuery): Promise<SpotHistoryData> {\n const qs = buildHistoryQuery(query);\n const dto = await get<GetTradeHistoryReply>(\n `${this.endpoint}/portfolio/spot/history${qs}`,\n );\n return {\n trades: (dto.trades ?? []).map((t) => ({\n type: parseHistoryType(t.type),\n tokenSymbol: t.tokenSymbol ?? \"\",\n tokenName: t.tokenName ?? \"\",\n tokenImageUrl: t.tokenImageUrl ?? \"\",\n tokenAddress: t.tokenAddress ?? \"\",\n tokenAmount: parseDecimal(t.tokenAmount),\n valueUsd: parseDecimal(t.valueUsd),\n priceUsd: parseDecimal(t.priceUsd),\n sideTokenSymbol: t.sideTokenSymbol ?? \"\",\n sideTokenAmount: parseDecimal(t.sideTokenAmount),\n dex: t.dex ?? \"\",\n txHash: t.txHash ?? \"\",\n chain: t.chain ?? \"\",\n walletAddress: t.walletAddress ?? \"\",\n timestamp: parseTimestamp(t.timestamp),\n })),\n nextCursor: dto.nextCursor ?? \"\",\n hasNext: dto.hasNext ?? false,\n };\n }\n\n // ── Chart Data ────────────────────────────────────────────────────────\n\n async getChartData(query: CurveQuery): Promise<CurveData> {\n const params = new URLSearchParams();\n params.set(\"period\", query.period.toString());\n if (query.walletAddresses?.length) {\n for (const addr of query.walletAddresses) {\n params.append(\"walletAddresses\", addr);\n }\n }\n if (query.chain) {\n params.set(\"chain\", query.chain);\n }\n const dto = await get<GetPortfolioChartReply>(\n `${this.endpoint}/portfolio/chart?${params.toString()}`,\n );\n return {\n points: (dto.dataPoints ?? []).map((p) => ({\n timestamp: parseTimestamp(p.timestamp),\n netWorth: parseDecimal(p.netWorth),\n change: parseDecimal(p.change),\n changePercent: parseDecimal(p.changePercent),\n })),\n };\n }\n\n // ── Future APIs (stubs — backend not available yet) ───────────────────\n\n async getPerpsPositions(\n _query?: PortfolioQuery,\n ): Promise<PerpsPositionsData> {\n return { positions: [], totalValue: 0 };\n }\n\n async getPerpsHistory(_query?: PerpsHistoryQuery): Promise<PerpsHistoryData> {\n return { records: [], hasMore: false };\n }\n\n async getPredictionBets(\n _query?: PortfolioQuery,\n ): Promise<PredictionBetsData> {\n return { bets: [], totalValue: 0 };\n }\n\n async getPredictionSettled(\n _query?: PredictionSettledQuery,\n ): Promise<PredictionSettledData> {\n return { records: [], hasMore: false };\n }\n}\n\n// ── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction buildQuery(query?: PortfolioQuery): string {\n if (!query) return \"\";\n const params = new URLSearchParams();\n if (query.walletAddresses?.length) {\n for (const addr of query.walletAddresses) {\n params.append(\"walletAddresses\", addr);\n }\n }\n if (query.chain) {\n params.set(\"chain\", query.chain);\n }\n const str = params.toString();\n return str ? `?${str}` : \"\";\n}\n\nfunction buildHistoryQuery(query?: SpotHistoryQuery): string {\n if (!query) return \"\";\n const params = new URLSearchParams();\n if (query.walletAddresses?.length) {\n for (const addr of query.walletAddresses) {\n params.append(\"walletAddresses\", addr);\n }\n }\n if (query.chain) {\n params.set(\"chain\", query.chain);\n }\n if (query.cursor) {\n params.set(\"cursor\", query.cursor);\n }\n if (query.limit !== undefined) {\n params.set(\"limit\", query.limit.toString());\n }\n const str = params.toString();\n return str ? `?${str}` : \"\";\n}\n\nfunction parseHistoryType(raw: string): SpotHistoryType {\n const lower = raw?.toLowerCase();\n if (lower === \"send\" || lower === \"transfer_out\") return SpotHistoryType.SEND;\n if (lower === \"receive\" || lower === \"transfer_in\")\n return SpotHistoryType.RECEIVE;\n return SpotHistoryType.SWAP;\n}\n\nfunction parseTimestamp(raw: string): number {\n if (!raw) return 0;\n const n = Number(raw);\n // If value looks like epoch seconds (< 1e12), convert to ms\n if (Number.isFinite(n)) {\n return n < 1e12 ? n * 1000 : n;\n }\n // Try ISO date string\n const d = Date.parse(raw);\n return Number.isFinite(d) ? d : 0;\n}\n"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import {get}from'@liberfi.io/utils';function i(r){if(!r)return 0;let e=Number(r);return Number.isFinite(e)?e:0}var a=class{constructor(e){this.endpoint=e;}async getOverview(e){let n=l(e),o=await get(`${this.endpoint}/portfolio/overview${n}`);return {totalValue:i(o.totalBalanceUsd),uPnl:i(o.unrealizedPnl),realizedPnl:i(o.realizedPnl),totalProfit:i(o.totalProfitUsd),winRate:i(o.winRate)}}async getSpotHoldings(e){let n=l(e);return {holdings:((await get(`${this.endpoint}/portfolio/spot/holdings${n}`)).holdings??[]).map(t=>({tokenAddress:t.tokenAddress,name:t.name,symbol:t.symbol,image:t.imageUrl??"",chain:t.chain??"",balance:i(t.balance),price:i(t.priceUsd),value:i(t.valueUsd),change24h:i(t.priceChange24h),unrealizedPnl:i(t.unrealizedPnl),realizedPnl:i(t.realizedPnl),walletAddress:t.walletAddress??"",verified:false}))}}async getSpotHistory(e){let n=u(e),o=await get(`${this.endpoint}/portfolio/spot/history${n}`);return {trades:(o.trades??[]).map(t=>({type:c(t.type),tokenSymbol:t.tokenSymbol??"",tokenName:t.tokenName??"",tokenImageUrl:t.tokenImageUrl??"",tokenAddress:t.tokenAddress??"",tokenAmount:i(t.tokenAmount),valueUsd:i(t.valueUsd),priceUsd:i(t.priceUsd),sideTokenSymbol:t.sideTokenSymbol??"",sideTokenAmount:i(t.sideTokenAmount),dex:t.dex??"",txHash:t.txHash??"",chain:t.chain??"",walletAddress:t.walletAddress??"",timestamp:d(t.timestamp)})),nextCursor:o.nextCursor??"",hasNext:o.hasNext??false}}async getChartData(e){let n=new URLSearchParams;if(n.set("period",e.period.toString()),e.walletAddresses?.length)for(let t of e.walletAddresses)n.append("walletAddresses",t);return e.chain&&n.set("chain",e.chain),{points:((await get(`${this.endpoint}/portfolio/chart?${n.toString()}`)).dataPoints??[]).map(t=>({timestamp:d(t.timestamp),netWorth:i(t.netWorth),change:i(t.change),changePercent:i(t.changePercent)}))}}async getPerpsPositions(e){return {positions:[],totalValue:0}}async getPerpsHistory(e){return {records:[],hasMore:false}}async getPredictionBets(e){return {bets:[],totalValue:0}}async getPredictionSettled(e){return {records:[],hasMore:false}}};function l(r){if(!r)return "";let e=new URLSearchParams;if(r.walletAddresses?.length)for(let o of r.walletAddresses)e.append("walletAddresses",o);r.chain&&e.set("chain",r.chain);let n=e.toString();return n?`?${n}`:""}function u(r){if(!r)return "";let e=new URLSearchParams;if(r.walletAddresses?.length)for(let o of r.walletAddresses)e.append("walletAddresses",o);r.chain&&e.set("chain",r.chain),r.cursor&&e.set("cursor",r.cursor),r.limit!==void 0&&e.set("limit",r.limit.toString());let n=e.toString();return n?`?${n}`:""}function c(r){let e=r?.toLowerCase();return e==="send"||e==="transfer_out"?"send":e==="receive"||e==="transfer_in"?"receive":"swap"}function d(r){if(!r)return 0;let e=Number(r);if(Number.isFinite(e))return e<1e12?e*1e3:e;let n=Date.parse(r);return Number.isFinite(n)?n:0}export{a as PortfolioClient};//# sourceMappingURL=index.mjs.map
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils/index.ts","../../src/client/index.ts"],"names":["parseDecimal","raw","n","PortfolioClient","endpoint","query","qs","buildQuery","dto","get","h","buildHistoryQuery","parseHistoryType","parseTimestamp","params","addr","p","_query","str","lower","d"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { DistributionData, SpotHolding } from \"../types\";\n\n/**\n * Parse a decimal string to a number, returning 0 for empty / invalid values.\n */\nexport function parseDecimal(raw: string | undefined | null): number {\n if (!raw) return 0;\n const n = Number(raw);\n return Number.isFinite(n) ? n : 0;\n}\n\n/**\n * Format a number as a USD currency string.\n * - >= 1M → \"$1.2M\"\n * - >= 1K → \"$4.2K\"\n * - >= 1 → \"$1,234.56\"\n * - >= 0.01 → \"$0.42\"\n * - < 0.01 and > 0 → \"<$0.01\"\n * - 0 → \"$0.00\"\n */\nexport function formatUsd(value: number): string {\n const abs = Math.abs(value);\n const sign = value < 0 ? \"-\" : \"\";\n\n if (abs >= 1_000_000) {\n return `${sign}$${(abs / 1_000_000).toFixed(1)}M`;\n }\n if (abs >= 10_000) {\n return `${sign}$${(abs / 1_000).toFixed(1)}K`;\n }\n if (abs >= 1) {\n return `${sign}$${abs.toLocaleString(\"en-US\", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;\n }\n if (abs >= 0.01) {\n return `${sign}$${abs.toFixed(2)}`;\n }\n if (abs > 0) {\n return `${sign}<$0.01`;\n }\n return \"$0.00\";\n}\n\n/**\n * Format a signed USD value with + / - prefix for PnL display.\n */\nexport function formatSignedUsd(value: number): string {\n const formatted = formatUsd(Math.abs(value));\n if (value > 0) return `+${formatted}`;\n if (value < 0) return `-${formatted.replace(\"-\", \"\")}`;\n return formatted;\n}\n\n/**\n * Format a percentage value.\n * Returns \"+3.24%\" or \"-1.50%\"\n */\nexport function formatPercent(value: number): string {\n const sign = value > 0 ? \"+\" : \"\";\n return `${sign}${value.toFixed(2)}%`;\n}\n\n/**\n * Split a USD value into integer and decimal parts for display.\n * e.g., 12847.63 → { integer: \"12,847\", decimal: \".63\", sign: \"$\" }\n */\nexport function splitUsd(value: number): {\n sign: string;\n integer: string;\n decimal: string;\n} {\n const abs = Math.abs(value);\n const parts = abs.toFixed(2).split(\".\");\n const integer = Number(parts[0]).toLocaleString(\"en-US\");\n const decimal = `.${parts[1]}`;\n const sign = value < 0 ? \"-$\" : \"$\";\n return { sign, integer, decimal };\n}\n\n/**\n * Truncate an address to \"xxxx…xxxx\" format.\n */\nexport function truncateAddress(address: string, start = 4, end = 4): string {\n if (address.length <= start + end + 3) return address;\n return `${address.slice(0, start)}…${address.slice(-end)}`;\n}\n\n/**\n * Format a token balance with appropriate precision.\n */\nexport function formatTokenBalance(value: number): string {\n if (value === 0) return \"0\";\n if (value >= 1_000_000) return `${(value / 1_000_000).toFixed(2)}M`;\n if (value >= 1_000)\n return value.toLocaleString(\"en-US\", { maximumFractionDigits: 2 });\n if (value >= 1) return value.toFixed(2);\n if (value >= 0.0001) return value.toFixed(4);\n return \"<0.0001\";\n}\n\n/**\n * Build a Solana explorer URL for a transaction hash.\n * Defaults to Solscan. Can be extended for other chains in the future.\n */\nexport function getExplorerUrl(txHash: string, _chain?: string): string {\n return `https://solscan.io/tx/${txHash}`;\n}\n\n// ── Distribution Helpers ────────────────────────────────────────────────────\n\nconst DISTRIBUTION_COLORS = [\n \"#C8FF00\",\n \"#00E676\",\n \"#0066FF\",\n \"#FF6B9D\",\n \"#8B7BFF\",\n \"#FF5252\",\n \"#FFB74D\",\n \"#4DD0E1\",\n];\n\nconst OTHER_COLOR = \"#3A3A4E\";\n\n/**\n * Compute asset distribution from spot holdings for the donut chart.\n * Groups tokens with < 2% into \"Other\".\n */\nexport function computeDistribution(holdings: SpotHolding[]): DistributionData {\n const totalValue = holdings.reduce((sum, h) => sum + h.value, 0);\n if (totalValue <= 0) return { items: [] };\n\n const sorted = [...holdings].sort((a, b) => b.value - a.value);\n\n const items: DistributionData[\"items\"] = [];\n let otherValue = 0;\n let colorIdx = 0;\n\n for (const h of sorted) {\n const pct = (h.value / totalValue) * 100;\n if (pct < 2) {\n otherValue += h.value;\n } else {\n items.push({\n name: h.name,\n symbol: h.symbol,\n percent: pct,\n value: h.value,\n color: DISTRIBUTION_COLORS[colorIdx % DISTRIBUTION_COLORS.length],\n });\n colorIdx++;\n }\n }\n\n if (otherValue > 0) {\n items.push({\n name: \"Other\",\n symbol: \"OTHER\",\n percent: (otherValue / totalValue) * 100,\n value: otherValue,\n color: OTHER_COLOR,\n });\n }\n\n return { items };\n}\n\n/**\n * Format an epoch-ms timestamp for display in history tables.\n */\nexport function formatTime(epochMs: number): string {\n const d = new Date(epochMs);\n return d.toLocaleDateString(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n hour12: false,\n });\n}\n","import { get } from \"@liberfi.io/utils\";\nimport { SpotHistoryType } from \"../types\";\nimport type {\n CurveData,\n CurveQuery,\n GetPortfolioChartReply,\n GetSpotHoldingsReply,\n GetTradeHistoryReply,\n IPortfolioClient,\n PerpsHistoryData,\n PerpsHistoryQuery,\n PerpsPositionsData,\n PortfolioOverview,\n PortfolioOverviewDTO,\n PortfolioQuery,\n PredictionBetsData,\n PredictionSettledData,\n PredictionSettledQuery,\n SpotHistoryData,\n SpotHistoryQuery,\n SpotHoldingsData,\n} from \"../types\";\nimport { parseDecimal } from \"../utils\";\n\n// ── Client ──────────────────────────────────────────────────────────────────\n\nexport class PortfolioClient implements IPortfolioClient {\n constructor(private readonly endpoint: string) {}\n\n // ── Overview ──────────────────────────────────────────────────────────\n\n async getOverview(query?: PortfolioQuery): Promise<PortfolioOverview> {\n const qs = buildQuery(query);\n const dto = await get<PortfolioOverviewDTO>(\n `${this.endpoint}/portfolio/overview${qs}`,\n );\n return {\n totalValue: parseDecimal(dto.totalBalanceUsd),\n uPnl: parseDecimal(dto.unrealizedPnl),\n realizedPnl: parseDecimal(dto.realizedPnl),\n totalProfit: parseDecimal(dto.totalProfitUsd),\n winRate: parseDecimal(dto.winRate),\n };\n }\n\n // ── Spot Holdings ─────────────────────────────────────────────────────\n\n async getSpotHoldings(query?: PortfolioQuery): Promise<SpotHoldingsData> {\n const qs = buildQuery(query);\n const dto = await get<GetSpotHoldingsReply>(\n `${this.endpoint}/portfolio/spot/holdings${qs}`,\n );\n return {\n holdings: (dto.holdings ?? []).map((h) => ({\n tokenAddress: h.tokenAddress,\n name: h.name,\n symbol: h.symbol,\n image: h.imageUrl ?? \"\",\n chain: h.chain ?? \"\",\n balance: parseDecimal(h.balance),\n price: parseDecimal(h.priceUsd),\n value: parseDecimal(h.valueUsd),\n change24h: parseDecimal(h.priceChange24h),\n unrealizedPnl: parseDecimal(h.unrealizedPnl),\n realizedPnl: parseDecimal(h.realizedPnl),\n walletAddress: h.walletAddress ?? \"\",\n verified: false,\n })),\n };\n }\n\n // ── Spot History ──────────────────────────────────────────────────────\n\n async getSpotHistory(query?: SpotHistoryQuery): Promise<SpotHistoryData> {\n const qs = buildHistoryQuery(query);\n const dto = await get<GetTradeHistoryReply>(\n `${this.endpoint}/portfolio/spot/history${qs}`,\n );\n return {\n trades: (dto.trades ?? []).map((t) => ({\n type: parseHistoryType(t.type),\n tokenSymbol: t.tokenSymbol ?? \"\",\n tokenName: t.tokenName ?? \"\",\n tokenImageUrl: t.tokenImageUrl ?? \"\",\n tokenAddress: t.tokenAddress ?? \"\",\n tokenAmount: parseDecimal(t.tokenAmount),\n valueUsd: parseDecimal(t.valueUsd),\n priceUsd: parseDecimal(t.priceUsd),\n sideTokenSymbol: t.sideTokenSymbol ?? \"\",\n sideTokenAmount: parseDecimal(t.sideTokenAmount),\n dex: t.dex ?? \"\",\n txHash: t.txHash ?? \"\",\n chain: t.chain ?? \"\",\n walletAddress: t.walletAddress ?? \"\",\n timestamp: parseTimestamp(t.timestamp),\n })),\n nextCursor: dto.nextCursor ?? \"\",\n hasNext: dto.hasNext ?? false,\n };\n }\n\n // ── Chart Data ────────────────────────────────────────────────────────\n\n async getChartData(query: CurveQuery): Promise<CurveData> {\n const params = new URLSearchParams();\n params.set(\"period\", query.period.toString());\n if (query.walletAddresses?.length) {\n for (const addr of query.walletAddresses) {\n params.append(\"walletAddresses\", addr);\n }\n }\n if (query.chain) {\n params.set(\"chain\", query.chain);\n }\n const dto = await get<GetPortfolioChartReply>(\n `${this.endpoint}/portfolio/chart?${params.toString()}`,\n );\n return {\n points: (dto.dataPoints ?? []).map((p) => ({\n timestamp: parseTimestamp(p.timestamp),\n netWorth: parseDecimal(p.netWorth),\n change: parseDecimal(p.change),\n changePercent: parseDecimal(p.changePercent),\n })),\n };\n }\n\n // ── Future APIs (stubs — backend not available yet) ───────────────────\n\n async getPerpsPositions(\n _query?: PortfolioQuery,\n ): Promise<PerpsPositionsData> {\n return { positions: [], totalValue: 0 };\n }\n\n async getPerpsHistory(_query?: PerpsHistoryQuery): Promise<PerpsHistoryData> {\n return { records: [], hasMore: false };\n }\n\n async getPredictionBets(\n _query?: PortfolioQuery,\n ): Promise<PredictionBetsData> {\n return { bets: [], totalValue: 0 };\n }\n\n async getPredictionSettled(\n _query?: PredictionSettledQuery,\n ): Promise<PredictionSettledData> {\n return { records: [], hasMore: false };\n }\n}\n\n// ── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction buildQuery(query?: PortfolioQuery): string {\n if (!query) return \"\";\n const params = new URLSearchParams();\n if (query.walletAddresses?.length) {\n for (const addr of query.walletAddresses) {\n params.append(\"walletAddresses\", addr);\n }\n }\n if (query.chain) {\n params.set(\"chain\", query.chain);\n }\n const str = params.toString();\n return str ? `?${str}` : \"\";\n}\n\nfunction buildHistoryQuery(query?: SpotHistoryQuery): string {\n if (!query) return \"\";\n const params = new URLSearchParams();\n if (query.walletAddresses?.length) {\n for (const addr of query.walletAddresses) {\n params.append(\"walletAddresses\", addr);\n }\n }\n if (query.chain) {\n params.set(\"chain\", query.chain);\n }\n if (query.cursor) {\n params.set(\"cursor\", query.cursor);\n }\n if (query.limit !== undefined) {\n params.set(\"limit\", query.limit.toString());\n }\n const str = params.toString();\n return str ? `?${str}` : \"\";\n}\n\nfunction parseHistoryType(raw: string): SpotHistoryType {\n const lower = raw?.toLowerCase();\n if (lower === \"send\" || lower === \"transfer_out\") return SpotHistoryType.SEND;\n if (lower === \"receive\" || lower === \"transfer_in\")\n return SpotHistoryType.RECEIVE;\n return SpotHistoryType.SWAP;\n}\n\nfunction parseTimestamp(raw: string): number {\n if (!raw) return 0;\n const n = Number(raw);\n // If value looks like epoch seconds (< 1e12), convert to ms\n if (Number.isFinite(n)) {\n return n < 1e12 ? n * 1000 : n;\n }\n // Try ISO date string\n const d = Date.parse(raw);\n return Number.isFinite(d) ? d : 0;\n}\n"]}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
declare enum AssetTab {
|
|
2
|
+
SPOT = "spot",
|
|
3
|
+
PERPS = "perps",
|
|
4
|
+
PREDICTION = "prediction"
|
|
5
|
+
}
|
|
6
|
+
declare enum CurveType {
|
|
7
|
+
NET_WORTH = "networth",
|
|
8
|
+
PNL = "pnl"
|
|
9
|
+
}
|
|
10
|
+
declare enum CurvePeriod {
|
|
11
|
+
ONE_DAY = "1D",
|
|
12
|
+
SEVEN_DAY = "7D",
|
|
13
|
+
THIRTY_DAY = "30D",
|
|
14
|
+
MAX = "Max"
|
|
15
|
+
}
|
|
16
|
+
/** Maps UI period enum to the integer value the backend expects. */
|
|
17
|
+
declare const CURVE_PERIOD_VALUE: Record<CurvePeriod, number>;
|
|
18
|
+
declare enum PerpsPositionSide {
|
|
19
|
+
LONG = "long",
|
|
20
|
+
SHORT = "short"
|
|
21
|
+
}
|
|
22
|
+
declare enum SpotHistoryType {
|
|
23
|
+
SWAP = "swap",
|
|
24
|
+
SEND = "send",
|
|
25
|
+
RECEIVE = "receive"
|
|
26
|
+
}
|
|
27
|
+
declare enum PredictionBetStatus {
|
|
28
|
+
ACTIVE = "active",
|
|
29
|
+
PENDING = "pending"
|
|
30
|
+
}
|
|
31
|
+
declare enum PredictionResult {
|
|
32
|
+
WON = "won",
|
|
33
|
+
LOST = "lost"
|
|
34
|
+
}
|
|
35
|
+
declare enum PredictionSource {
|
|
36
|
+
POLYMARKET = "polymarket",
|
|
37
|
+
DRIFT = "drift",
|
|
38
|
+
METADAO = "metadao"
|
|
39
|
+
}
|
|
40
|
+
interface PortfolioQuery {
|
|
41
|
+
walletAddresses?: string[];
|
|
42
|
+
chain?: string;
|
|
43
|
+
}
|
|
44
|
+
interface CurveQuery extends PortfolioQuery {
|
|
45
|
+
period: number;
|
|
46
|
+
}
|
|
47
|
+
interface SpotHistoryQuery extends PortfolioQuery {
|
|
48
|
+
cursor?: string;
|
|
49
|
+
limit?: number;
|
|
50
|
+
}
|
|
51
|
+
interface PortfolioOverviewDTO {
|
|
52
|
+
totalBalanceUsd: string;
|
|
53
|
+
unrealizedPnl: string;
|
|
54
|
+
realizedPnl: string;
|
|
55
|
+
totalProfitUsd: string;
|
|
56
|
+
winRate: string;
|
|
57
|
+
}
|
|
58
|
+
interface ChartDataPointDTO {
|
|
59
|
+
timestamp: string;
|
|
60
|
+
netWorth: string;
|
|
61
|
+
change: string;
|
|
62
|
+
changePercent: string;
|
|
63
|
+
}
|
|
64
|
+
interface GetPortfolioChartReply {
|
|
65
|
+
dataPoints: ChartDataPointDTO[];
|
|
66
|
+
}
|
|
67
|
+
interface TokenHoldingDTO {
|
|
68
|
+
tokenAddress: string;
|
|
69
|
+
symbol: string;
|
|
70
|
+
name: string;
|
|
71
|
+
imageUrl: string;
|
|
72
|
+
chain: string;
|
|
73
|
+
balance: string;
|
|
74
|
+
priceUsd: string;
|
|
75
|
+
valueUsd: string;
|
|
76
|
+
priceChange24h: string;
|
|
77
|
+
unrealizedPnl: string;
|
|
78
|
+
realizedPnl: string;
|
|
79
|
+
walletAddress: string;
|
|
80
|
+
}
|
|
81
|
+
interface GetSpotHoldingsReply {
|
|
82
|
+
holdings: TokenHoldingDTO[];
|
|
83
|
+
}
|
|
84
|
+
interface TradeRecordDTO {
|
|
85
|
+
type: string;
|
|
86
|
+
tokenSymbol: string;
|
|
87
|
+
tokenName: string;
|
|
88
|
+
tokenImageUrl: string;
|
|
89
|
+
tokenAddress: string;
|
|
90
|
+
tokenAmount: string;
|
|
91
|
+
valueUsd: string;
|
|
92
|
+
priceUsd: string;
|
|
93
|
+
sideTokenSymbol: string;
|
|
94
|
+
sideTokenAmount: string;
|
|
95
|
+
dex: string;
|
|
96
|
+
txHash: string;
|
|
97
|
+
chain: string;
|
|
98
|
+
walletAddress: string;
|
|
99
|
+
timestamp: string;
|
|
100
|
+
}
|
|
101
|
+
interface GetTradeHistoryReply {
|
|
102
|
+
trades: TradeRecordDTO[];
|
|
103
|
+
nextCursor: string;
|
|
104
|
+
hasNext: boolean;
|
|
105
|
+
}
|
|
106
|
+
interface PortfolioOverview {
|
|
107
|
+
totalValue: number;
|
|
108
|
+
uPnl: number;
|
|
109
|
+
realizedPnl: number;
|
|
110
|
+
totalProfit: number;
|
|
111
|
+
winRate: number;
|
|
112
|
+
}
|
|
113
|
+
interface SpotHolding {
|
|
114
|
+
tokenAddress: string;
|
|
115
|
+
name: string;
|
|
116
|
+
symbol: string;
|
|
117
|
+
image: string;
|
|
118
|
+
chain: string;
|
|
119
|
+
balance: number;
|
|
120
|
+
price: number;
|
|
121
|
+
value: number;
|
|
122
|
+
change24h: number;
|
|
123
|
+
unrealizedPnl: number;
|
|
124
|
+
realizedPnl: number;
|
|
125
|
+
walletAddress: string;
|
|
126
|
+
/** Client-side derived: true if the token is in a verified whitelist. */
|
|
127
|
+
verified: boolean;
|
|
128
|
+
}
|
|
129
|
+
interface SpotHoldingsData {
|
|
130
|
+
holdings: SpotHolding[];
|
|
131
|
+
}
|
|
132
|
+
interface SpotHistoryRecord {
|
|
133
|
+
type: SpotHistoryType;
|
|
134
|
+
tokenSymbol: string;
|
|
135
|
+
tokenName: string;
|
|
136
|
+
tokenImageUrl: string;
|
|
137
|
+
tokenAddress: string;
|
|
138
|
+
tokenAmount: number;
|
|
139
|
+
valueUsd: number;
|
|
140
|
+
priceUsd: number;
|
|
141
|
+
sideTokenSymbol: string;
|
|
142
|
+
sideTokenAmount: number;
|
|
143
|
+
dex: string;
|
|
144
|
+
txHash: string;
|
|
145
|
+
chain: string;
|
|
146
|
+
walletAddress: string;
|
|
147
|
+
timestamp: number;
|
|
148
|
+
}
|
|
149
|
+
interface SpotHistoryData {
|
|
150
|
+
trades: SpotHistoryRecord[];
|
|
151
|
+
nextCursor: string;
|
|
152
|
+
hasNext: boolean;
|
|
153
|
+
}
|
|
154
|
+
interface CurvePoint {
|
|
155
|
+
timestamp: number;
|
|
156
|
+
netWorth: number;
|
|
157
|
+
change: number;
|
|
158
|
+
changePercent: number;
|
|
159
|
+
}
|
|
160
|
+
interface CurveData {
|
|
161
|
+
points: CurvePoint[];
|
|
162
|
+
}
|
|
163
|
+
interface DistributionItem {
|
|
164
|
+
name: string;
|
|
165
|
+
symbol: string;
|
|
166
|
+
percent: number;
|
|
167
|
+
value: number;
|
|
168
|
+
color: string;
|
|
169
|
+
}
|
|
170
|
+
interface DistributionData {
|
|
171
|
+
items: DistributionItem[];
|
|
172
|
+
}
|
|
173
|
+
interface PerpsPosition {
|
|
174
|
+
id: string;
|
|
175
|
+
pair: string;
|
|
176
|
+
icon?: string;
|
|
177
|
+
side: PerpsPositionSide;
|
|
178
|
+
leverage: number;
|
|
179
|
+
size: number;
|
|
180
|
+
entryPrice: number;
|
|
181
|
+
markPrice: number;
|
|
182
|
+
uPnl: number;
|
|
183
|
+
protocol: string;
|
|
184
|
+
closeUrl: string;
|
|
185
|
+
}
|
|
186
|
+
interface PerpsPositionsData {
|
|
187
|
+
positions: PerpsPosition[];
|
|
188
|
+
totalValue: number;
|
|
189
|
+
}
|
|
190
|
+
interface PerpsTradeRecord {
|
|
191
|
+
id: string;
|
|
192
|
+
pair: string;
|
|
193
|
+
icon?: string;
|
|
194
|
+
side: PerpsPositionSide;
|
|
195
|
+
size: number;
|
|
196
|
+
pnl: number;
|
|
197
|
+
closePrice: number;
|
|
198
|
+
time: string;
|
|
199
|
+
}
|
|
200
|
+
interface PerpsHistoryData {
|
|
201
|
+
records: PerpsTradeRecord[];
|
|
202
|
+
hasMore: boolean;
|
|
203
|
+
}
|
|
204
|
+
interface PerpsHistoryQuery extends PortfolioQuery {
|
|
205
|
+
cursor?: string;
|
|
206
|
+
limit?: number;
|
|
207
|
+
}
|
|
208
|
+
interface PredictionBet {
|
|
209
|
+
id: string;
|
|
210
|
+
market: string;
|
|
211
|
+
icon?: string;
|
|
212
|
+
source: PredictionSource;
|
|
213
|
+
expiresAt: string;
|
|
214
|
+
position: "Yes" | "No";
|
|
215
|
+
stake: number;
|
|
216
|
+
potential: number;
|
|
217
|
+
status: PredictionBetStatus;
|
|
218
|
+
sellUrl: string;
|
|
219
|
+
}
|
|
220
|
+
interface PredictionBetsData {
|
|
221
|
+
bets: PredictionBet[];
|
|
222
|
+
totalValue: number;
|
|
223
|
+
}
|
|
224
|
+
interface PredictionSettledRecord {
|
|
225
|
+
id: string;
|
|
226
|
+
market: string;
|
|
227
|
+
icon?: string;
|
|
228
|
+
source: PredictionSource;
|
|
229
|
+
position: "Yes" | "No";
|
|
230
|
+
stake: number;
|
|
231
|
+
result: PredictionResult;
|
|
232
|
+
payout: number;
|
|
233
|
+
}
|
|
234
|
+
interface PredictionSettledData {
|
|
235
|
+
records: PredictionSettledRecord[];
|
|
236
|
+
hasMore: boolean;
|
|
237
|
+
}
|
|
238
|
+
interface PredictionSettledQuery extends PortfolioQuery {
|
|
239
|
+
cursor?: string;
|
|
240
|
+
limit?: number;
|
|
241
|
+
}
|
|
242
|
+
interface IPortfolioClient {
|
|
243
|
+
getOverview(query?: PortfolioQuery): Promise<PortfolioOverview>;
|
|
244
|
+
getSpotHoldings(query?: PortfolioQuery): Promise<SpotHoldingsData>;
|
|
245
|
+
getSpotHistory(query?: SpotHistoryQuery): Promise<SpotHistoryData>;
|
|
246
|
+
getChartData(query: CurveQuery): Promise<CurveData>;
|
|
247
|
+
getPerpsPositions(query?: PortfolioQuery): Promise<PerpsPositionsData>;
|
|
248
|
+
getPerpsHistory(query?: PerpsHistoryQuery): Promise<PerpsHistoryData>;
|
|
249
|
+
getPredictionBets(query?: PortfolioQuery): Promise<PredictionBetsData>;
|
|
250
|
+
getPredictionSettled(query?: PredictionSettledQuery): Promise<PredictionSettledData>;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export { AssetTab as A, type SpotHistoryRecord as B, CurveType as C, type DistributionData as D, type CurvePoint as E, type DistributionItem as F, type GetPortfolioChartReply as G, type PerpsTradeRecord as H, type IPortfolioClient as I, type PredictionSettledRecord as J, type PortfolioQuery as P, type SpotHoldingsData as S, type TokenHoldingDTO as T, CurvePeriod as a, type PortfolioOverview as b, type CurveData as c, type SpotHistoryData as d, type PerpsPositionsData as e, type PerpsHistoryData as f, type PredictionBetsData as g, type PredictionSettledData as h, type SpotHolding as i, type PerpsPosition as j, type PredictionBet as k, type SpotHistoryQuery as l, type PerpsHistoryQuery as m, type PredictionSettledQuery as n, type CurveQuery as o, CURVE_PERIOD_VALUE as p, PerpsPositionSide as q, SpotHistoryType as r, PredictionBetStatus as s, PredictionResult as t, PredictionSource as u, type PortfolioOverviewDTO as v, type ChartDataPointDTO as w, type GetSpotHoldingsReply as x, type TradeRecordDTO as y, type GetTradeHistoryReply as z };
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
declare enum AssetTab {
|
|
2
|
+
SPOT = "spot",
|
|
3
|
+
PERPS = "perps",
|
|
4
|
+
PREDICTION = "prediction"
|
|
5
|
+
}
|
|
6
|
+
declare enum CurveType {
|
|
7
|
+
NET_WORTH = "networth",
|
|
8
|
+
PNL = "pnl"
|
|
9
|
+
}
|
|
10
|
+
declare enum CurvePeriod {
|
|
11
|
+
ONE_DAY = "1D",
|
|
12
|
+
SEVEN_DAY = "7D",
|
|
13
|
+
THIRTY_DAY = "30D",
|
|
14
|
+
MAX = "Max"
|
|
15
|
+
}
|
|
16
|
+
/** Maps UI period enum to the integer value the backend expects. */
|
|
17
|
+
declare const CURVE_PERIOD_VALUE: Record<CurvePeriod, number>;
|
|
18
|
+
declare enum PerpsPositionSide {
|
|
19
|
+
LONG = "long",
|
|
20
|
+
SHORT = "short"
|
|
21
|
+
}
|
|
22
|
+
declare enum SpotHistoryType {
|
|
23
|
+
SWAP = "swap",
|
|
24
|
+
SEND = "send",
|
|
25
|
+
RECEIVE = "receive"
|
|
26
|
+
}
|
|
27
|
+
declare enum PredictionBetStatus {
|
|
28
|
+
ACTIVE = "active",
|
|
29
|
+
PENDING = "pending"
|
|
30
|
+
}
|
|
31
|
+
declare enum PredictionResult {
|
|
32
|
+
WON = "won",
|
|
33
|
+
LOST = "lost"
|
|
34
|
+
}
|
|
35
|
+
declare enum PredictionSource {
|
|
36
|
+
POLYMARKET = "polymarket",
|
|
37
|
+
DRIFT = "drift",
|
|
38
|
+
METADAO = "metadao"
|
|
39
|
+
}
|
|
40
|
+
interface PortfolioQuery {
|
|
41
|
+
walletAddresses?: string[];
|
|
42
|
+
chain?: string;
|
|
43
|
+
}
|
|
44
|
+
interface CurveQuery extends PortfolioQuery {
|
|
45
|
+
period: number;
|
|
46
|
+
}
|
|
47
|
+
interface SpotHistoryQuery extends PortfolioQuery {
|
|
48
|
+
cursor?: string;
|
|
49
|
+
limit?: number;
|
|
50
|
+
}
|
|
51
|
+
interface PortfolioOverviewDTO {
|
|
52
|
+
totalBalanceUsd: string;
|
|
53
|
+
unrealizedPnl: string;
|
|
54
|
+
realizedPnl: string;
|
|
55
|
+
totalProfitUsd: string;
|
|
56
|
+
winRate: string;
|
|
57
|
+
}
|
|
58
|
+
interface ChartDataPointDTO {
|
|
59
|
+
timestamp: string;
|
|
60
|
+
netWorth: string;
|
|
61
|
+
change: string;
|
|
62
|
+
changePercent: string;
|
|
63
|
+
}
|
|
64
|
+
interface GetPortfolioChartReply {
|
|
65
|
+
dataPoints: ChartDataPointDTO[];
|
|
66
|
+
}
|
|
67
|
+
interface TokenHoldingDTO {
|
|
68
|
+
tokenAddress: string;
|
|
69
|
+
symbol: string;
|
|
70
|
+
name: string;
|
|
71
|
+
imageUrl: string;
|
|
72
|
+
chain: string;
|
|
73
|
+
balance: string;
|
|
74
|
+
priceUsd: string;
|
|
75
|
+
valueUsd: string;
|
|
76
|
+
priceChange24h: string;
|
|
77
|
+
unrealizedPnl: string;
|
|
78
|
+
realizedPnl: string;
|
|
79
|
+
walletAddress: string;
|
|
80
|
+
}
|
|
81
|
+
interface GetSpotHoldingsReply {
|
|
82
|
+
holdings: TokenHoldingDTO[];
|
|
83
|
+
}
|
|
84
|
+
interface TradeRecordDTO {
|
|
85
|
+
type: string;
|
|
86
|
+
tokenSymbol: string;
|
|
87
|
+
tokenName: string;
|
|
88
|
+
tokenImageUrl: string;
|
|
89
|
+
tokenAddress: string;
|
|
90
|
+
tokenAmount: string;
|
|
91
|
+
valueUsd: string;
|
|
92
|
+
priceUsd: string;
|
|
93
|
+
sideTokenSymbol: string;
|
|
94
|
+
sideTokenAmount: string;
|
|
95
|
+
dex: string;
|
|
96
|
+
txHash: string;
|
|
97
|
+
chain: string;
|
|
98
|
+
walletAddress: string;
|
|
99
|
+
timestamp: string;
|
|
100
|
+
}
|
|
101
|
+
interface GetTradeHistoryReply {
|
|
102
|
+
trades: TradeRecordDTO[];
|
|
103
|
+
nextCursor: string;
|
|
104
|
+
hasNext: boolean;
|
|
105
|
+
}
|
|
106
|
+
interface PortfolioOverview {
|
|
107
|
+
totalValue: number;
|
|
108
|
+
uPnl: number;
|
|
109
|
+
realizedPnl: number;
|
|
110
|
+
totalProfit: number;
|
|
111
|
+
winRate: number;
|
|
112
|
+
}
|
|
113
|
+
interface SpotHolding {
|
|
114
|
+
tokenAddress: string;
|
|
115
|
+
name: string;
|
|
116
|
+
symbol: string;
|
|
117
|
+
image: string;
|
|
118
|
+
chain: string;
|
|
119
|
+
balance: number;
|
|
120
|
+
price: number;
|
|
121
|
+
value: number;
|
|
122
|
+
change24h: number;
|
|
123
|
+
unrealizedPnl: number;
|
|
124
|
+
realizedPnl: number;
|
|
125
|
+
walletAddress: string;
|
|
126
|
+
/** Client-side derived: true if the token is in a verified whitelist. */
|
|
127
|
+
verified: boolean;
|
|
128
|
+
}
|
|
129
|
+
interface SpotHoldingsData {
|
|
130
|
+
holdings: SpotHolding[];
|
|
131
|
+
}
|
|
132
|
+
interface SpotHistoryRecord {
|
|
133
|
+
type: SpotHistoryType;
|
|
134
|
+
tokenSymbol: string;
|
|
135
|
+
tokenName: string;
|
|
136
|
+
tokenImageUrl: string;
|
|
137
|
+
tokenAddress: string;
|
|
138
|
+
tokenAmount: number;
|
|
139
|
+
valueUsd: number;
|
|
140
|
+
priceUsd: number;
|
|
141
|
+
sideTokenSymbol: string;
|
|
142
|
+
sideTokenAmount: number;
|
|
143
|
+
dex: string;
|
|
144
|
+
txHash: string;
|
|
145
|
+
chain: string;
|
|
146
|
+
walletAddress: string;
|
|
147
|
+
timestamp: number;
|
|
148
|
+
}
|
|
149
|
+
interface SpotHistoryData {
|
|
150
|
+
trades: SpotHistoryRecord[];
|
|
151
|
+
nextCursor: string;
|
|
152
|
+
hasNext: boolean;
|
|
153
|
+
}
|
|
154
|
+
interface CurvePoint {
|
|
155
|
+
timestamp: number;
|
|
156
|
+
netWorth: number;
|
|
157
|
+
change: number;
|
|
158
|
+
changePercent: number;
|
|
159
|
+
}
|
|
160
|
+
interface CurveData {
|
|
161
|
+
points: CurvePoint[];
|
|
162
|
+
}
|
|
163
|
+
interface DistributionItem {
|
|
164
|
+
name: string;
|
|
165
|
+
symbol: string;
|
|
166
|
+
percent: number;
|
|
167
|
+
value: number;
|
|
168
|
+
color: string;
|
|
169
|
+
}
|
|
170
|
+
interface DistributionData {
|
|
171
|
+
items: DistributionItem[];
|
|
172
|
+
}
|
|
173
|
+
interface PerpsPosition {
|
|
174
|
+
id: string;
|
|
175
|
+
pair: string;
|
|
176
|
+
icon?: string;
|
|
177
|
+
side: PerpsPositionSide;
|
|
178
|
+
leverage: number;
|
|
179
|
+
size: number;
|
|
180
|
+
entryPrice: number;
|
|
181
|
+
markPrice: number;
|
|
182
|
+
uPnl: number;
|
|
183
|
+
protocol: string;
|
|
184
|
+
closeUrl: string;
|
|
185
|
+
}
|
|
186
|
+
interface PerpsPositionsData {
|
|
187
|
+
positions: PerpsPosition[];
|
|
188
|
+
totalValue: number;
|
|
189
|
+
}
|
|
190
|
+
interface PerpsTradeRecord {
|
|
191
|
+
id: string;
|
|
192
|
+
pair: string;
|
|
193
|
+
icon?: string;
|
|
194
|
+
side: PerpsPositionSide;
|
|
195
|
+
size: number;
|
|
196
|
+
pnl: number;
|
|
197
|
+
closePrice: number;
|
|
198
|
+
time: string;
|
|
199
|
+
}
|
|
200
|
+
interface PerpsHistoryData {
|
|
201
|
+
records: PerpsTradeRecord[];
|
|
202
|
+
hasMore: boolean;
|
|
203
|
+
}
|
|
204
|
+
interface PerpsHistoryQuery extends PortfolioQuery {
|
|
205
|
+
cursor?: string;
|
|
206
|
+
limit?: number;
|
|
207
|
+
}
|
|
208
|
+
interface PredictionBet {
|
|
209
|
+
id: string;
|
|
210
|
+
market: string;
|
|
211
|
+
icon?: string;
|
|
212
|
+
source: PredictionSource;
|
|
213
|
+
expiresAt: string;
|
|
214
|
+
position: "Yes" | "No";
|
|
215
|
+
stake: number;
|
|
216
|
+
potential: number;
|
|
217
|
+
status: PredictionBetStatus;
|
|
218
|
+
sellUrl: string;
|
|
219
|
+
}
|
|
220
|
+
interface PredictionBetsData {
|
|
221
|
+
bets: PredictionBet[];
|
|
222
|
+
totalValue: number;
|
|
223
|
+
}
|
|
224
|
+
interface PredictionSettledRecord {
|
|
225
|
+
id: string;
|
|
226
|
+
market: string;
|
|
227
|
+
icon?: string;
|
|
228
|
+
source: PredictionSource;
|
|
229
|
+
position: "Yes" | "No";
|
|
230
|
+
stake: number;
|
|
231
|
+
result: PredictionResult;
|
|
232
|
+
payout: number;
|
|
233
|
+
}
|
|
234
|
+
interface PredictionSettledData {
|
|
235
|
+
records: PredictionSettledRecord[];
|
|
236
|
+
hasMore: boolean;
|
|
237
|
+
}
|
|
238
|
+
interface PredictionSettledQuery extends PortfolioQuery {
|
|
239
|
+
cursor?: string;
|
|
240
|
+
limit?: number;
|
|
241
|
+
}
|
|
242
|
+
interface IPortfolioClient {
|
|
243
|
+
getOverview(query?: PortfolioQuery): Promise<PortfolioOverview>;
|
|
244
|
+
getSpotHoldings(query?: PortfolioQuery): Promise<SpotHoldingsData>;
|
|
245
|
+
getSpotHistory(query?: SpotHistoryQuery): Promise<SpotHistoryData>;
|
|
246
|
+
getChartData(query: CurveQuery): Promise<CurveData>;
|
|
247
|
+
getPerpsPositions(query?: PortfolioQuery): Promise<PerpsPositionsData>;
|
|
248
|
+
getPerpsHistory(query?: PerpsHistoryQuery): Promise<PerpsHistoryData>;
|
|
249
|
+
getPredictionBets(query?: PortfolioQuery): Promise<PredictionBetsData>;
|
|
250
|
+
getPredictionSettled(query?: PredictionSettledQuery): Promise<PredictionSettledData>;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export { AssetTab as A, type SpotHistoryRecord as B, CurveType as C, type DistributionData as D, type CurvePoint as E, type DistributionItem as F, type GetPortfolioChartReply as G, type PerpsTradeRecord as H, type IPortfolioClient as I, type PredictionSettledRecord as J, type PortfolioQuery as P, type SpotHoldingsData as S, type TokenHoldingDTO as T, CurvePeriod as a, type PortfolioOverview as b, type CurveData as c, type SpotHistoryData as d, type PerpsPositionsData as e, type PerpsHistoryData as f, type PredictionBetsData as g, type PredictionSettledData as h, type SpotHolding as i, type PerpsPosition as j, type PredictionBet as k, type SpotHistoryQuery as l, type PerpsHistoryQuery as m, type PredictionSettledQuery as n, type CurveQuery as o, CURVE_PERIOD_VALUE as p, PerpsPositionSide as q, SpotHistoryType as r, PredictionBetStatus as s, PredictionResult as t, PredictionSource as u, type PortfolioOverviewDTO as v, type ChartDataPointDTO as w, type GetSpotHoldingsReply as x, type TradeRecordDTO as y, type GetTradeHistoryReply as z };
|