@liberfi.io/ui-portfolio 3.0.72 → 3.0.74

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.
@@ -1,4 +1,4 @@
1
- import { I as IPortfolioClient, P as PortfolioQuery, b as PortfolioOverview, S as SpotHoldingsData, m as SpotHistoryQuery, d as SpotHistoryData, p as CurveQuery, c as CurveData, e as PerpsPositionsData, n as PerpsHistoryQuery, f as PerpsHistoryData, g as PredictionBetsData, o as PredictionSettledQuery, h as PredictionSettledData } from '../index-Bq_qim6b.mjs';
1
+ import { I as IPortfolioClient, P as PortfolioQuery, b as PortfolioOverview, S as SpotHoldingsData, l as SpotHistoryQuery, d as SpotHistoryData, p as CurveQuery, c as CurveData, e as PerpsPositionsData, n as PerpsHistoryQuery, f as PerpsHistoryData, g as PredictionBetsData, o as PredictionSettledQuery, h as PredictionSettledData } from '../index-BK-jWEQ7.mjs';
2
2
  import '@tanstack/react-query';
3
3
  import '@liberfi.io/types';
4
4
 
@@ -9,10 +9,10 @@ declare class PortfolioClient implements IPortfolioClient {
9
9
  getSpotHoldings(query?: PortfolioQuery): Promise<SpotHoldingsData>;
10
10
  getSpotHistory(query?: SpotHistoryQuery): Promise<SpotHistoryData>;
11
11
  getChartData(query: CurveQuery): Promise<CurveData>;
12
- getPerpsPositions(_query?: PortfolioQuery): Promise<PerpsPositionsData>;
13
- getPerpsHistory(_query?: PerpsHistoryQuery): Promise<PerpsHistoryData>;
14
- getPredictionBets(_query?: PortfolioQuery): Promise<PredictionBetsData>;
15
- getPredictionSettled(_query?: PredictionSettledQuery): Promise<PredictionSettledData>;
12
+ getPerpsPositions(query?: PortfolioQuery): Promise<PerpsPositionsData>;
13
+ getPerpsHistory(query?: PerpsHistoryQuery): Promise<PerpsHistoryData>;
14
+ getPredictionBets(query?: PortfolioQuery): Promise<PredictionBetsData>;
15
+ getPredictionSettled(query?: PredictionSettledQuery): Promise<PredictionSettledData>;
16
16
  }
17
17
 
18
18
  export { PortfolioClient };
@@ -1,4 +1,4 @@
1
- import { I as IPortfolioClient, P as PortfolioQuery, b as PortfolioOverview, S as SpotHoldingsData, m as SpotHistoryQuery, d as SpotHistoryData, p as CurveQuery, c as CurveData, e as PerpsPositionsData, n as PerpsHistoryQuery, f as PerpsHistoryData, g as PredictionBetsData, o as PredictionSettledQuery, h as PredictionSettledData } from '../index-Bq_qim6b.js';
1
+ import { I as IPortfolioClient, P as PortfolioQuery, b as PortfolioOverview, S as SpotHoldingsData, l as SpotHistoryQuery, d as SpotHistoryData, p as CurveQuery, c as CurveData, e as PerpsPositionsData, n as PerpsHistoryQuery, f as PerpsHistoryData, g as PredictionBetsData, o as PredictionSettledQuery, h as PredictionSettledData } from '../index-BK-jWEQ7.js';
2
2
  import '@tanstack/react-query';
3
3
  import '@liberfi.io/types';
4
4
 
@@ -9,10 +9,10 @@ declare class PortfolioClient implements IPortfolioClient {
9
9
  getSpotHoldings(query?: PortfolioQuery): Promise<SpotHoldingsData>;
10
10
  getSpotHistory(query?: SpotHistoryQuery): Promise<SpotHistoryData>;
11
11
  getChartData(query: CurveQuery): Promise<CurveData>;
12
- getPerpsPositions(_query?: PortfolioQuery): Promise<PerpsPositionsData>;
13
- getPerpsHistory(_query?: PerpsHistoryQuery): Promise<PerpsHistoryData>;
14
- getPredictionBets(_query?: PortfolioQuery): Promise<PredictionBetsData>;
15
- getPredictionSettled(_query?: PredictionSettledQuery): Promise<PredictionSettledData>;
12
+ getPerpsPositions(query?: PortfolioQuery): Promise<PerpsPositionsData>;
13
+ getPerpsHistory(query?: PerpsHistoryQuery): Promise<PerpsHistoryData>;
14
+ getPredictionBets(query?: PortfolioQuery): Promise<PredictionBetsData>;
15
+ getPredictionSettled(query?: PredictionSettledQuery): Promise<PredictionSettledData>;
16
16
  }
17
17
 
18
18
  export { PortfolioClient };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/index.ts","../../src/client/index.ts"],"names":["parseDecimal","raw","n","PortfolioClient","endpoint","query","qs","buildQuery","dto","httpGet","h","buildHistoryQuery","parseHistoryType","parseTimestamp","params","addr","p","_query","str","lower","d"],"mappings":"oDAMO,SAASA,CAAAA,CAAaC,CAAAA,CAAwC,CACnE,GAAI,CAACA,CAAAA,CAAK,OAAO,CAAA,CACjB,IAAMC,CAAAA,CAAI,MAAA,CAAOD,CAAG,EACpB,OAAO,MAAA,CAAO,QAAA,CAASC,CAAC,CAAA,CAAIA,CAAAA,CAAI,CAClC,KCgBaC,CAAAA,CAAN,KAAkD,CACvD,WAAA,CAA6BC,CAAAA,CAAkB,CAAlB,IAAA,CAAA,QAAA,CAAAA,EAAmB,CAIhD,MAAM,WAAA,CAAYC,CAAAA,CAAoD,CACpE,IAAMC,CAAAA,CAAKC,CAAAA,CAAWF,CAAK,EACrBG,CAAAA,CAAM,MAAMC,aAAAA,CAChB,CAAA,EAAG,IAAA,CAAK,QAAQ,CAAA,mBAAA,EAAsBH,CAAE,EAC1C,CAAA,CACA,OAAO,CACL,UAAA,CAAYN,EAAaQ,CAAAA,CAAI,eAAe,CAAA,CAC5C,IAAA,CAAMR,EAAaQ,CAAAA,CAAI,aAAa,CAAA,CACpC,WAAA,CAAaR,CAAAA,CAAaQ,CAAAA,CAAI,WAAW,CAAA,CACzC,YAAaR,CAAAA,CAAaQ,CAAAA,CAAI,cAAc,CAAA,CAC5C,OAAA,CAASR,CAAAA,CAAaQ,CAAAA,CAAI,OAAO,CACnC,CACF,CAIA,MAAM,eAAA,CAAgBH,CAAAA,CAAmD,CACvE,IAAMC,CAAAA,CAAKC,EAAWF,CAAK,CAAA,CAI3B,OAAO,CACL,QAAA,CAAA,CAAA,CAJU,MAAMI,aAAAA,CAChB,CAAA,EAAG,KAAK,QAAQ,CAAA,wBAAA,EAA2BH,CAAE,CAAA,CAC/C,CAAA,EAEiB,QAAA,EAAY,EAAC,EAAG,IAAKI,CAAAA,GAAO,CACzC,YAAA,CAAcA,CAAAA,CAAE,YAAA,CAChB,IAAA,CAAMA,CAAAA,CAAE,IAAA,CACR,OAAQA,CAAAA,CAAE,MAAA,CACV,KAAA,CAAOA,CAAAA,CAAE,QAAA,EAAY,EAAA,CACrB,KAAA,CAAOA,CAAAA,CAAE,OAAS,EAAA,CAClB,OAAA,CAASV,CAAAA,CAAaU,CAAAA,CAAE,OAAO,CAAA,CAC/B,KAAA,CAAOV,CAAAA,CAAaU,CAAAA,CAAE,QAAQ,CAAA,CAC9B,KAAA,CAAOV,CAAAA,CAAaU,CAAAA,CAAE,QAAQ,CAAA,CAC9B,SAAA,CAAWV,CAAAA,CAAaU,EAAE,cAAc,CAAA,CACxC,aAAA,CAAeV,CAAAA,CAAaU,CAAAA,CAAE,aAAa,CAAA,CAC3C,WAAA,CAAaV,EAAaU,CAAAA,CAAE,WAAW,CAAA,CACvC,aAAA,CAAeA,CAAAA,CAAE,aAAA,EAAiB,EAAA,CAClC,QAAA,CAAU,KACZ,CAAA,CAAE,CACJ,CACF,CAIA,MAAM,cAAA,CAAeL,CAAAA,CAAoD,CACvE,IAAMC,CAAAA,CAAKK,CAAAA,CAAkBN,CAAK,CAAA,CAC5BG,CAAAA,CAAM,MAAMC,aAAAA,CAChB,CAAA,EAAG,KAAK,QAAQ,CAAA,uBAAA,EAA0BH,CAAE,CAAA,CAC9C,CAAA,CACA,OAAO,CACL,MAAA,CAAA,CAASE,EAAI,MAAA,EAAU,EAAC,EAAG,GAAA,CAAK,CAAA,GAAO,CACrC,IAAA,CAAMI,CAAAA,CAAiB,EAAE,IAAI,CAAA,CAC7B,WAAA,CAAa,CAAA,CAAE,aAAe,EAAA,CAC9B,SAAA,CAAW,CAAA,CAAE,SAAA,EAAa,GAC1B,aAAA,CAAe,CAAA,CAAE,aAAA,EAAiB,EAAA,CAClC,YAAA,CAAc,CAAA,CAAE,YAAA,EAAgB,EAAA,CAChC,YAAaZ,CAAAA,CAAa,CAAA,CAAE,WAAW,CAAA,CACvC,QAAA,CAAUA,CAAAA,CAAa,CAAA,CAAE,QAAQ,EACjC,QAAA,CAAUA,CAAAA,CAAa,CAAA,CAAE,QAAQ,CAAA,CACjC,eAAA,CAAiB,CAAA,CAAE,eAAA,EAAmB,GACtC,eAAA,CAAiBA,CAAAA,CAAa,CAAA,CAAE,eAAe,CAAA,CAC/C,GAAA,CAAK,CAAA,CAAE,GAAA,EAAO,GACd,MAAA,CAAQ,CAAA,CAAE,MAAA,EAAU,EAAA,CACpB,KAAA,CAAO,CAAA,CAAE,KAAA,EAAS,EAAA,CAClB,cAAe,CAAA,CAAE,aAAA,EAAiB,EAAA,CAClC,SAAA,CAAWa,CAAAA,CAAe,CAAA,CAAE,SAAS,CACvC,EAAE,CAAA,CACF,UAAA,CAAYL,CAAAA,CAAI,UAAA,EAAc,EAAA,CAC9B,OAAA,CAASA,CAAAA,CAAI,OAAA,EAAW,KAC1B,CACF,CAIA,MAAM,YAAA,CAAaH,EAAuC,CACxD,IAAMS,CAAAA,CAAS,IAAI,gBAEnB,GADAA,CAAAA,CAAO,GAAA,CAAI,QAAA,CAAUT,CAAAA,CAAM,MAAA,CAAO,QAAA,EAAU,EACxCA,CAAAA,CAAM,eAAA,EAAiB,MAAA,CACzB,IAAA,IAAWU,CAAAA,IAAQV,CAAAA,CAAM,eAAA,CACvBS,CAAAA,CAAO,OAAO,iBAAA,CAAmBC,CAAI,CAAA,CAGzC,OAAIV,CAAAA,CAAM,KAAA,EACRS,CAAAA,CAAO,GAAA,CAAI,QAAST,CAAAA,CAAM,KAAK,CAAA,CAK1B,CACL,MAAA,CAAA,CAAA,CAJU,MAAMI,aAAAA,CAChB,CAAA,EAAG,KAAK,QAAQ,CAAA,iBAAA,EAAoBK,CAAAA,CAAO,QAAA,EAAU,CAAA,CACvD,CAAA,EAEe,UAAA,EAAc,EAAC,EAAG,GAAA,CAAKE,CAAAA,GAAO,CACzC,SAAA,CAAWH,CAAAA,CAAeG,CAAAA,CAAE,SAAS,EACrC,QAAA,CAAUhB,CAAAA,CAAagB,CAAAA,CAAE,QAAQ,CAAA,CACjC,MAAA,CAAQhB,CAAAA,CAAagB,CAAAA,CAAE,MAAM,CAAA,CAC7B,aAAA,CAAehB,CAAAA,CAAagB,CAAAA,CAAE,aAAa,CAC7C,CAAA,CAAE,CACJ,CACF,CAIA,MAAM,iBAAA,CACJC,CAAAA,CAC6B,CAC7B,OAAO,CAAE,SAAA,CAAW,GAAI,UAAA,CAAY,CAAE,CACxC,CAEA,MAAM,eAAA,CAAgBA,CAAAA,CAAuD,CAC3E,OAAO,CAAE,OAAA,CAAS,EAAC,CAAG,OAAA,CAAS,KAAM,CACvC,CAEA,MAAM,iBAAA,CACJA,CAAAA,CAC6B,CAC7B,OAAO,CAAE,IAAA,CAAM,EAAC,CAAG,WAAY,CAAE,CACnC,CAEA,MAAM,oBAAA,CACJA,CAAAA,CACgC,CAChC,OAAO,CAAE,OAAA,CAAS,EAAC,CAAG,OAAA,CAAS,KAAM,CACvC,CACF,EAIA,SAASV,CAAAA,CAAWF,CAAAA,CAAgC,CAClD,GAAI,CAACA,CAAAA,CAAO,OAAO,EAAA,CACnB,IAAMS,CAAAA,CAAS,IAAI,eAAA,CACnB,GAAIT,EAAM,eAAA,EAAiB,MAAA,CACzB,IAAA,IAAWU,CAAAA,IAAQV,EAAM,eAAA,CACvBS,CAAAA,CAAO,MAAA,CAAO,iBAAA,CAAmBC,CAAI,CAAA,CAGrCV,CAAAA,CAAM,KAAA,EACRS,EAAO,GAAA,CAAI,OAAA,CAAST,CAAAA,CAAM,KAAK,CAAA,CAEjC,IAAMa,CAAAA,CAAMJ,CAAAA,CAAO,UAAS,CAC5B,OAAOI,CAAAA,CAAM,CAAA,CAAA,EAAIA,CAAG,CAAA,CAAA,CAAK,EAC3B,CAEA,SAASP,CAAAA,CAAkBN,CAAAA,CAAkC,CAC3D,GAAI,CAACA,CAAAA,CAAO,OAAO,EAAA,CACnB,IAAMS,CAAAA,CAAS,IAAI,eAAA,CACnB,GAAIT,CAAAA,CAAM,eAAA,EAAiB,MAAA,CACzB,IAAA,IAAWU,KAAQV,CAAAA,CAAM,eAAA,CACvBS,CAAAA,CAAO,MAAA,CAAO,iBAAA,CAAmBC,CAAI,CAAA,CAGrCV,CAAAA,CAAM,OACRS,CAAAA,CAAO,GAAA,CAAI,OAAA,CAAST,CAAAA,CAAM,KAAK,CAAA,CAE7BA,CAAAA,CAAM,MAAA,EACRS,EAAO,GAAA,CAAI,QAAA,CAAUT,CAAAA,CAAM,MAAM,EAE/BA,CAAAA,CAAM,KAAA,GAAU,MAAA,EAClBS,CAAAA,CAAO,IAAI,OAAA,CAAST,CAAAA,CAAM,KAAA,CAAM,QAAA,EAAU,CAAA,CAE5C,IAAMa,CAAAA,CAAMJ,EAAO,QAAA,EAAS,CAC5B,OAAOI,CAAAA,CAAM,CAAA,CAAA,EAAIA,CAAG,CAAA,CAAA,CAAK,EAC3B,CAEA,SAASN,CAAAA,CAAiBX,CAAAA,CAA8B,CACtD,IAAMkB,CAAAA,CAAQlB,CAAAA,EAAK,WAAA,GACnB,OAAIkB,CAAAA,GAAU,MAAA,EAAUA,CAAAA,GAAU,sBAC9BA,CAAAA,GAAU,SAAA,EAAaA,CAAAA,GAAU,aAAA,CAAA,SAAA,CAAA,MAGvC,CAEA,SAASN,CAAAA,CAAeZ,CAAAA,CAAqB,CAC3C,GAAI,CAACA,CAAAA,CAAK,SACV,IAAMC,CAAAA,CAAI,MAAA,CAAOD,CAAG,CAAA,CAEpB,GAAI,MAAA,CAAO,QAAA,CAASC,CAAC,CAAA,CACnB,OAAOA,CAAAA,CAAI,IAAA,CAAOA,CAAAA,CAAI,GAAA,CAAOA,CAAAA,CAG/B,IAAMkB,EAAI,IAAA,CAAK,KAAA,CAAMnB,CAAG,CAAA,CACxB,OAAO,MAAA,CAAO,QAAA,CAASmB,CAAC,CAAA,CAAIA,EAAI,CAClC","file":"index.js","sourcesContent":["import { formatAmount, formatAmountInUsd } from \"@liberfi.io/utils\";\nimport 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 return formatAmountInUsd(value);\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 return formatAmount(value);\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 { httpGet } 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 httpGet<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 httpGet<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 httpGet<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 httpGet<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"]}
1
+ {"version":3,"sources":["../../src/utils/index.ts","../../src/client/index.ts"],"names":["parseDecimal","raw","n","PortfolioClient","endpoint","query","qs","buildQuery","dto","httpGet","h","buildHistoryQuery","parseHistoryType","parseTimestamp","params","addr","p","str","lower","d"],"mappings":"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","file":"index.js","sourcesContent":["import { formatAmount, formatAmountInUsd } from \"@liberfi.io/utils\";\nimport 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 return formatAmountInUsd(value);\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 return formatAmount(value);\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 void chain;\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 { httpGet } 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 httpGet<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 httpGet<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 httpGet<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 httpGet<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 void query;\n return { positions: [], totalValue: 0 };\n }\n\n async getPerpsHistory(query?: PerpsHistoryQuery): Promise<PerpsHistoryData> {\n void query;\n return { records: [], hasMore: false };\n }\n\n async getPredictionBets(\n query?: PortfolioQuery,\n ): Promise<PredictionBetsData> {\n void query;\n return { bets: [], totalValue: 0 };\n }\n\n async getPredictionSettled(\n query?: PredictionSettledQuery,\n ): Promise<PredictionSettledData> {\n void query;\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"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/index.ts","../../src/client/index.ts"],"names":["parseDecimal","raw","n","PortfolioClient","endpoint","query","qs","buildQuery","dto","httpGet","h","buildHistoryQuery","parseHistoryType","parseTimestamp","params","addr","p","_query","str","lower","d"],"mappings":"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","file":"index.mjs","sourcesContent":["import { formatAmount, formatAmountInUsd } from \"@liberfi.io/utils\";\nimport 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 return formatAmountInUsd(value);\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 return formatAmount(value);\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 { httpGet } 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 httpGet<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 httpGet<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 httpGet<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 httpGet<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"]}
1
+ {"version":3,"sources":["../../src/utils/index.ts","../../src/client/index.ts"],"names":["parseDecimal","raw","n","PortfolioClient","endpoint","query","qs","buildQuery","dto","httpGet","h","buildHistoryQuery","parseHistoryType","parseTimestamp","params","addr","p","str","lower","d"],"mappings":"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","file":"index.mjs","sourcesContent":["import { formatAmount, formatAmountInUsd } from \"@liberfi.io/utils\";\nimport 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 return formatAmountInUsd(value);\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 return formatAmount(value);\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 void chain;\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 { httpGet } 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 httpGet<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 httpGet<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 httpGet<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 httpGet<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 void query;\n return { positions: [], totalValue: 0 };\n }\n\n async getPerpsHistory(query?: PerpsHistoryQuery): Promise<PerpsHistoryData> {\n void query;\n return { records: [], hasMore: false };\n }\n\n async getPredictionBets(\n query?: PortfolioQuery,\n ): Promise<PredictionBetsData> {\n void query;\n return { bets: [], totalValue: 0 };\n }\n\n async getPredictionSettled(\n query?: PredictionSettledQuery,\n ): Promise<PredictionSettledData> {\n void query;\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"]}
@@ -257,4 +257,4 @@ interface IPortfolioClient {
257
257
  getPredictionSettled(query?: PredictionSettledQuery): Promise<PredictionSettledData>;
258
258
  }
259
259
 
260
- export { AssetTab as A, type GetTradeHistoryReply as B, CurveType as C, type DistributionData as D, type SpotHistoryRecord as E, type CurvePoint as F, type GetPortfolioChartReply as G, type DistributionItem as H, type IPortfolioClient as I, type PerpsTradeRecord as J, type PredictionSettledRecord as K, type PortfolioQuery as P, type SpotHoldingsData as S, type TokenHoldingDTO as T, type WalletSummary as W, 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 AsyncStatus as l, type SpotHistoryQuery as m, type PerpsHistoryQuery as n, type PredictionSettledQuery as o, type CurveQuery as p, CURVE_PERIOD_VALUE as q, PerpsPositionSide as r, SpotHistoryType as s, PredictionBetStatus as t, PredictionResult as u, PredictionSource as v, type PortfolioOverviewDTO as w, type ChartDataPointDTO as x, type GetSpotHoldingsReply as y, type TradeRecordDTO as z };
260
+ export { AssetTab as A, type GetTradeHistoryReply as B, CurveType as C, type DistributionData as D, type PerpsTradeRecord as E, type PortfolioOverviewDTO as F, type GetPortfolioChartReply as G, type PredictionSettledRecord as H, type IPortfolioClient as I, type SpotHistoryRecord as J, type TradeRecordDTO as K, type PortfolioQuery as P, type SpotHoldingsData as S, type TokenHoldingDTO as T, type WalletSummary as W, 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 AsyncStatus as m, type PerpsHistoryQuery as n, type PredictionSettledQuery as o, type CurveQuery as p, CURVE_PERIOD_VALUE as q, PerpsPositionSide as r, PredictionBetStatus as s, PredictionResult as t, PredictionSource as u, SpotHistoryType as v, type ChartDataPointDTO as w, type CurvePoint as x, type DistributionItem as y, type GetSpotHoldingsReply as z };
@@ -257,4 +257,4 @@ interface IPortfolioClient {
257
257
  getPredictionSettled(query?: PredictionSettledQuery): Promise<PredictionSettledData>;
258
258
  }
259
259
 
260
- export { AssetTab as A, type GetTradeHistoryReply as B, CurveType as C, type DistributionData as D, type SpotHistoryRecord as E, type CurvePoint as F, type GetPortfolioChartReply as G, type DistributionItem as H, type IPortfolioClient as I, type PerpsTradeRecord as J, type PredictionSettledRecord as K, type PortfolioQuery as P, type SpotHoldingsData as S, type TokenHoldingDTO as T, type WalletSummary as W, 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 AsyncStatus as l, type SpotHistoryQuery as m, type PerpsHistoryQuery as n, type PredictionSettledQuery as o, type CurveQuery as p, CURVE_PERIOD_VALUE as q, PerpsPositionSide as r, SpotHistoryType as s, PredictionBetStatus as t, PredictionResult as u, PredictionSource as v, type PortfolioOverviewDTO as w, type ChartDataPointDTO as x, type GetSpotHoldingsReply as y, type TradeRecordDTO as z };
260
+ export { AssetTab as A, type GetTradeHistoryReply as B, CurveType as C, type DistributionData as D, type PerpsTradeRecord as E, type PortfolioOverviewDTO as F, type GetPortfolioChartReply as G, type PredictionSettledRecord as H, type IPortfolioClient as I, type SpotHistoryRecord as J, type TradeRecordDTO as K, type PortfolioQuery as P, type SpotHoldingsData as S, type TokenHoldingDTO as T, type WalletSummary as W, 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 AsyncStatus as m, type PerpsHistoryQuery as n, type PredictionSettledQuery as o, type CurveQuery as p, CURVE_PERIOD_VALUE as q, PerpsPositionSide as r, PredictionBetStatus as s, PredictionResult as t, PredictionSource as u, SpotHistoryType as v, type ChartDataPointDTO as w, type CurvePoint as x, type DistributionItem as y, type GetSpotHoldingsReply as z };
package/dist/index.d.mts CHANGED
@@ -3,11 +3,11 @@ import * as react from 'react';
3
3
  import { ReactNode, PropsWithChildren } from 'react';
4
4
  import { PredefinedToken } from '@liberfi.io/utils';
5
5
  import { AuthStatus } from '@liberfi.io/wallet-connector';
6
- import { A as AssetTab, C as CurveType, a as CurvePeriod, P as PortfolioQuery, b as PortfolioOverview, c as CurveData, D as DistributionData, S as SpotHoldingsData, d as SpotHistoryData, e as PerpsPositionsData, f as PerpsHistoryData, g as PredictionBetsData, h as PredictionSettledData, i as SpotHolding, j as PerpsPosition, k as PredictionBet, I as IPortfolioClient, W as WalletSummary, l as AsyncStatus, m as SpotHistoryQuery, n as PerpsHistoryQuery, o as PredictionSettledQuery, p as CurveQuery } from './index-Bq_qim6b.mjs';
7
- export { q as CURVE_PERIOD_VALUE, x as ChartDataPointDTO, F as CurvePoint, H as DistributionItem, G as GetPortfolioChartReply, y as GetSpotHoldingsReply, B as GetTradeHistoryReply, r as PerpsPositionSide, J as PerpsTradeRecord, w as PortfolioOverviewDTO, t as PredictionBetStatus, u as PredictionResult, K as PredictionSettledRecord, v as PredictionSource, E as SpotHistoryRecord, s as SpotHistoryType, T as TokenHoldingDTO, z as TradeRecordDTO } from './index-Bq_qim6b.mjs';
6
+ import { A as AssetTab, C as CurveType, a as CurvePeriod, P as PortfolioQuery, b as PortfolioOverview, c as CurveData, D as DistributionData, S as SpotHoldingsData, d as SpotHistoryData, e as PerpsPositionsData, f as PerpsHistoryData, g as PredictionBetsData, h as PredictionSettledData, i as SpotHolding, j as PerpsPosition, k as PredictionBet, I as IPortfolioClient, l as SpotHistoryQuery, W as WalletSummary, m as AsyncStatus, n as PerpsHistoryQuery, o as PredictionSettledQuery, p as CurveQuery } from './index-BK-jWEQ7.mjs';
7
+ export { q as CURVE_PERIOD_VALUE, w as ChartDataPointDTO, x as CurvePoint, y as DistributionItem, G as GetPortfolioChartReply, z as GetSpotHoldingsReply, B as GetTradeHistoryReply, r as PerpsPositionSide, E as PerpsTradeRecord, F as PortfolioOverviewDTO, s as PredictionBetStatus, t as PredictionResult, H as PredictionSettledRecord, u as PredictionSource, J as SpotHistoryRecord, v as SpotHistoryType, T as TokenHoldingDTO, K as TradeRecordDTO } from './index-BK-jWEQ7.mjs';
8
8
  import * as _tanstack_react_query from '@tanstack/react-query';
9
9
  import { UseQueryOptions } from '@tanstack/react-query';
10
- import { ActivitiesSortBy, Activity, Chain, WalletPortfolios, Portfolio, WalletPnlResolution, WalletPnlSortBy, WalletPortfolioPnls, PositionState, PortfolioPnl } from '@liberfi.io/types';
10
+ import { Activity, ActivitiesSortBy, Chain, WalletPortfolios, Portfolio, WalletPortfolioPnls, WalletPnlResolution, PositionState, WalletPnlSortBy, PortfolioPnl } from '@liberfi.io/types';
11
11
  export { PositionState } from '@liberfi.io/types';
12
12
 
13
13
  /** Action button rendered in the popover action bar. */
@@ -514,6 +514,45 @@ declare function PortfolioPnlDetailsWidget({ chain, address, limit, initialResol
514
514
 
515
515
  declare const PortfolioClientContext: react.Context<IPortfolioClient | null>;
516
516
 
517
+ type PortfolioCapability = "holdings" | "net-worth" | "activities" | "perps" | "prediction";
518
+ type PortfolioAdapterResult<T> = {
519
+ kind: "ok";
520
+ data: T;
521
+ } | {
522
+ kind: "unsupported";
523
+ capability: PortfolioCapability;
524
+ } | {
525
+ kind: "error";
526
+ error: Error;
527
+ };
528
+ interface PortfolioActivitiesListener {
529
+ (items: SpotHistoryData["trades"]): void;
530
+ }
531
+ interface PortfolioDataAdapter {
532
+ getHoldings(query?: PortfolioQuery): Promise<PortfolioAdapterResult<SpotHoldingsData>>;
533
+ getNetWorth(query?: PortfolioQuery): Promise<PortfolioAdapterResult<PortfolioOverview>>;
534
+ getActivitiesPage(query?: SpotHistoryQuery): Promise<PortfolioAdapterResult<SpotHistoryData>>;
535
+ getPerpsPositions(query?: PortfolioQuery): Promise<PortfolioAdapterResult<{
536
+ positions: never[];
537
+ totalValue: number;
538
+ }>>;
539
+ getPredictionBets(query?: PortfolioQuery): Promise<PortfolioAdapterResult<{
540
+ bets: never[];
541
+ totalValue: number;
542
+ }>>;
543
+ subscribeActivities(listener: PortfolioActivitiesListener): {
544
+ unsubscribe(): void;
545
+ };
546
+ }
547
+ interface InMemoryPortfolioData {
548
+ holdings?: SpotHoldingsData;
549
+ netWorth?: PortfolioOverview;
550
+ activities?: SpotHistoryData;
551
+ }
552
+ declare function createInMemoryPortfolioDataAdapter(data?: InMemoryPortfolioData): PortfolioDataAdapter;
553
+
554
+ declare const PortfolioDataAdapterContext: react.Context<PortfolioDataAdapter | null>;
555
+
517
556
  /** Refetch function for wallet summary. */
518
557
  type RefetchWalletSummaryFn = () => Promise<void>;
519
558
  interface PortfolioContextValue {
@@ -528,8 +567,9 @@ declare const PortfolioContext: react.Context<PortfolioContextValue>;
528
567
 
529
568
  type PortfolioClientProviderProps = PropsWithChildren<{
530
569
  client: IPortfolioClient;
570
+ adapter?: PortfolioDataAdapter;
531
571
  }>;
532
- declare function PortfolioClientProvider({ client, children, }: PortfolioClientProviderProps): react_jsx_runtime.JSX.Element;
572
+ declare function PortfolioClientProvider({ client, adapter, children, }: PortfolioClientProviderProps): react_jsx_runtime.JSX.Element;
533
573
 
534
574
  type PortfolioProviderProps = PropsWithChildren<{
535
575
  chain: Chain;
@@ -541,6 +581,8 @@ declare function usePortfolioContext(): PortfolioContextValue;
541
581
 
542
582
  declare function usePortfolioClient(): IPortfolioClient;
543
583
 
584
+ declare function usePortfolioDataAdapter(): PortfolioDataAdapter;
585
+
544
586
  declare function overviewQueryKey(query?: PortfolioQuery): unknown[];
545
587
  declare function useOverviewQuery(query?: PortfolioQuery, queryOptions?: Omit<UseQueryOptions<PortfolioOverview, Error, PortfolioOverview, unknown[]>, "queryKey" | "queryFn">): _tanstack_react_query.UseQueryResult<PortfolioOverview, Error>;
546
588
 
@@ -614,6 +656,13 @@ declare function useWalletPortfolios({ chain, address, tokenAddresses, pollMs, }
614
656
  refetch: () => Promise<void>;
615
657
  };
616
658
 
659
+ /**
660
+ * Production adapter over the existing {@link IPortfolioClient}.
661
+ * Perps/prediction stay `unsupported` until a real backend exists —
662
+ * do not translate the current empty-array stubs into success.
663
+ */
664
+ declare function createClientPortfolioDataAdapter(client: IPortfolioClient): PortfolioDataAdapter;
665
+
617
666
  /**
618
667
  * Parse a decimal string to a number, returning 0 for empty / invalid values.
619
668
  */
@@ -658,7 +707,7 @@ declare function formatTokenBalance(value: number): string;
658
707
  * Build a Solana explorer URL for a transaction hash.
659
708
  * Defaults to Solscan. Can be extended for other chains in the future.
660
709
  */
661
- declare function getExplorerUrl(txHash: string, _chain?: string): string;
710
+ declare function getExplorerUrl(txHash: string, chain?: string): string;
662
711
  /**
663
712
  * Compute asset distribution from spot holdings for the donut chart.
664
713
  * Groups tokens with < 2% into "Other".
@@ -669,4 +718,4 @@ declare function computeDistribution(holdings: SpotHolding[]): DistributionData;
669
718
  */
670
719
  declare function formatTime(epochMs: number): string;
671
720
 
672
- export { type AccountAction, AccountInfoUI, type AccountInfoUIProps, AccountInfoWidget, type AccountInfoWidgetProps, AddressRowUI, type AddressRowUIProps, AssetTab, AssetTabsUI, type AssetTabsUIProps, AsyncStatus, BalanceRowUI, type BalanceRowUIProps, BatchActionButton, type BatchActionButtonProps, ConfirmDialog, type ConfirmDialogProps, CurveCardUI, type CurveCardUIProps, CurveData, CurvePeriod, CurveQuery, CurveType, DistributionCardUI, type DistributionCardUIProps, DistributionData, HoldingsEmpty, type HoldingsEmptyProps, type HoldingsRenderProps, HoldingsSearch, type HoldingsSearchProps, HoldingsSectionWidget, type HoldingsSectionWidgetProps, HoldingsSubTabs, type HoldingsSubTabsProps, IPortfolioClient, PerpsHistoryData, PerpsHistoryQuery, PerpsPanelUI, type PerpsPanelUIProps, PerpsPosition, PerpsPositionsData, type PerpsSubTab, type PnlResolution, type PnlSortBy, PortfolioActivities, type PortfolioActivitiesProps, type PortfolioActivitiesSortBy, type PortfolioActivitiesTypeFilter, PortfolioActivitiesWidget, type PortfolioActivitiesWidgetProps, PortfolioClientContext, PortfolioClientProvider, type PortfolioClientProviderProps, PortfolioContext, type PortfolioContextValue, PortfolioNetWorthTokens, type PortfolioNetWorthTokensProps, PortfolioNetWorthTokensWidget, type PortfolioNetWorthTokensWidgetProps, PortfolioOverview, PortfolioPageSkeleton, PortfolioPageWidget, type PortfolioPageWidgetProps, PortfolioPnlDetails, type PortfolioPnlDetailsProps, PortfolioPnlDetailsWidget, type PortfolioPnlDetailsWidgetProps, PortfolioProvider, type PortfolioProviderProps, PortfolioQuery, PredictionBet, PredictionBetsData, PredictionPanelUI, type PredictionPanelUIProps, PredictionSettledData, PredictionSettledQuery, type PredictionSubTab, type RefetchWalletSummaryFn, SpotHistoryData, SpotHistoryQuery, SpotHolding, SpotHoldingsData, SpotPanelUI, type SpotPanelUIProps, type SpotSubTab, TagBadge, TagBadgeList, type TagBadgeListProps, type TagBadgeProps, type TokenPortfolio, type UseAccountInfoResult, type UseHoldingsSectionOptions, type UseHoldingsSectionResult, type UsePortfolioActivitiesScriptParams, type UsePortfolioActivitiesScriptResult, type UsePortfolioNetWorthTokensScriptParams, type UsePortfolioNetWorthTokensScriptResult, type UsePortfolioPageOptions, type UsePortfolioPageResult, type UsePortfolioPnlDetailsScriptParams, type UsePortfolioPnlDetailsScriptResult, type UseWalletPortfoliosParams, ViewingBannerUI, type ViewingBannerUIProps, type WalletOption, WalletSummary, computeDistribution, curveDataQueryKey, distributionQueryKey, formatAgeShort, formatPercent, formatSignedUsd, formatTime, formatTokenBalance, formatUsd, getExplorerUrl, overviewQueryKey, parseDecimal, perpsHistoryQueryKey, perpsPositionsQueryKey, predictionBetsQueryKey, predictionSettledQueryKey, splitUsd, spotHistoryQueryKey, spotHoldingsQueryKey, truncateAddress, truncateMiddle, useAccountInfo, useCurveDataQuery, useDistributionQuery, useHoldingsSection, useOverviewQuery, usePerpsHistoryQuery, usePerpsPositionsQuery, usePortfolioActivitiesScript, usePortfolioClient, usePortfolioContext, usePortfolioNetWorthTokensScript, usePortfolioPage, usePortfolioPnlDetailsScript, usePredictionBetsQuery, usePredictionSettledQuery, useRefetchWalletSummary, useSpotHistoryQuery, useSpotHoldingsQuery, useWalletPortfolios, useWalletSummary };
721
+ export { type AccountAction, AccountInfoUI, type AccountInfoUIProps, AccountInfoWidget, type AccountInfoWidgetProps, AddressRowUI, type AddressRowUIProps, AssetTab, AssetTabsUI, type AssetTabsUIProps, AsyncStatus, BalanceRowUI, type BalanceRowUIProps, BatchActionButton, type BatchActionButtonProps, ConfirmDialog, type ConfirmDialogProps, CurveCardUI, type CurveCardUIProps, CurveData, CurvePeriod, CurveQuery, CurveType, DistributionCardUI, type DistributionCardUIProps, DistributionData, HoldingsEmpty, type HoldingsEmptyProps, type HoldingsRenderProps, HoldingsSearch, type HoldingsSearchProps, HoldingsSectionWidget, type HoldingsSectionWidgetProps, HoldingsSubTabs, type HoldingsSubTabsProps, IPortfolioClient, PerpsHistoryData, PerpsHistoryQuery, PerpsPanelUI, type PerpsPanelUIProps, PerpsPosition, PerpsPositionsData, type PerpsSubTab, type PnlResolution, type PnlSortBy, PortfolioActivities, type PortfolioActivitiesProps, type PortfolioActivitiesSortBy, type PortfolioActivitiesTypeFilter, PortfolioActivitiesWidget, type PortfolioActivitiesWidgetProps, type PortfolioAdapterResult, type PortfolioCapability, PortfolioClientContext, PortfolioClientProvider, type PortfolioClientProviderProps, PortfolioContext, type PortfolioContextValue, type PortfolioDataAdapter, PortfolioDataAdapterContext, PortfolioNetWorthTokens, type PortfolioNetWorthTokensProps, PortfolioNetWorthTokensWidget, type PortfolioNetWorthTokensWidgetProps, PortfolioOverview, PortfolioPageSkeleton, PortfolioPageWidget, type PortfolioPageWidgetProps, PortfolioPnlDetails, type PortfolioPnlDetailsProps, PortfolioPnlDetailsWidget, type PortfolioPnlDetailsWidgetProps, PortfolioProvider, type PortfolioProviderProps, PortfolioQuery, PredictionBet, PredictionBetsData, PredictionPanelUI, type PredictionPanelUIProps, PredictionSettledData, PredictionSettledQuery, type PredictionSubTab, type RefetchWalletSummaryFn, SpotHistoryData, SpotHistoryQuery, SpotHolding, SpotHoldingsData, SpotPanelUI, type SpotPanelUIProps, type SpotSubTab, TagBadge, TagBadgeList, type TagBadgeListProps, type TagBadgeProps, type TokenPortfolio, type UseAccountInfoResult, type UseHoldingsSectionOptions, type UseHoldingsSectionResult, type UsePortfolioActivitiesScriptParams, type UsePortfolioActivitiesScriptResult, type UsePortfolioNetWorthTokensScriptParams, type UsePortfolioNetWorthTokensScriptResult, type UsePortfolioPageOptions, type UsePortfolioPageResult, type UsePortfolioPnlDetailsScriptParams, type UsePortfolioPnlDetailsScriptResult, type UseWalletPortfoliosParams, ViewingBannerUI, type ViewingBannerUIProps, type WalletOption, WalletSummary, computeDistribution, createClientPortfolioDataAdapter, createInMemoryPortfolioDataAdapter, curveDataQueryKey, distributionQueryKey, formatAgeShort, formatPercent, formatSignedUsd, formatTime, formatTokenBalance, formatUsd, getExplorerUrl, overviewQueryKey, parseDecimal, perpsHistoryQueryKey, perpsPositionsQueryKey, predictionBetsQueryKey, predictionSettledQueryKey, splitUsd, spotHistoryQueryKey, spotHoldingsQueryKey, truncateAddress, truncateMiddle, useAccountInfo, useCurveDataQuery, useDistributionQuery, useHoldingsSection, useOverviewQuery, usePerpsHistoryQuery, usePerpsPositionsQuery, usePortfolioActivitiesScript, usePortfolioClient, usePortfolioContext, usePortfolioDataAdapter, usePortfolioNetWorthTokensScript, usePortfolioPage, usePortfolioPnlDetailsScript, usePredictionBetsQuery, usePredictionSettledQuery, useRefetchWalletSummary, useSpotHistoryQuery, useSpotHoldingsQuery, useWalletPortfolios, useWalletSummary };
package/dist/index.d.ts CHANGED
@@ -3,11 +3,11 @@ import * as react from 'react';
3
3
  import { ReactNode, PropsWithChildren } from 'react';
4
4
  import { PredefinedToken } from '@liberfi.io/utils';
5
5
  import { AuthStatus } from '@liberfi.io/wallet-connector';
6
- import { A as AssetTab, C as CurveType, a as CurvePeriod, P as PortfolioQuery, b as PortfolioOverview, c as CurveData, D as DistributionData, S as SpotHoldingsData, d as SpotHistoryData, e as PerpsPositionsData, f as PerpsHistoryData, g as PredictionBetsData, h as PredictionSettledData, i as SpotHolding, j as PerpsPosition, k as PredictionBet, I as IPortfolioClient, W as WalletSummary, l as AsyncStatus, m as SpotHistoryQuery, n as PerpsHistoryQuery, o as PredictionSettledQuery, p as CurveQuery } from './index-Bq_qim6b.js';
7
- export { q as CURVE_PERIOD_VALUE, x as ChartDataPointDTO, F as CurvePoint, H as DistributionItem, G as GetPortfolioChartReply, y as GetSpotHoldingsReply, B as GetTradeHistoryReply, r as PerpsPositionSide, J as PerpsTradeRecord, w as PortfolioOverviewDTO, t as PredictionBetStatus, u as PredictionResult, K as PredictionSettledRecord, v as PredictionSource, E as SpotHistoryRecord, s as SpotHistoryType, T as TokenHoldingDTO, z as TradeRecordDTO } from './index-Bq_qim6b.js';
6
+ import { A as AssetTab, C as CurveType, a as CurvePeriod, P as PortfolioQuery, b as PortfolioOverview, c as CurveData, D as DistributionData, S as SpotHoldingsData, d as SpotHistoryData, e as PerpsPositionsData, f as PerpsHistoryData, g as PredictionBetsData, h as PredictionSettledData, i as SpotHolding, j as PerpsPosition, k as PredictionBet, I as IPortfolioClient, l as SpotHistoryQuery, W as WalletSummary, m as AsyncStatus, n as PerpsHistoryQuery, o as PredictionSettledQuery, p as CurveQuery } from './index-BK-jWEQ7.js';
7
+ export { q as CURVE_PERIOD_VALUE, w as ChartDataPointDTO, x as CurvePoint, y as DistributionItem, G as GetPortfolioChartReply, z as GetSpotHoldingsReply, B as GetTradeHistoryReply, r as PerpsPositionSide, E as PerpsTradeRecord, F as PortfolioOverviewDTO, s as PredictionBetStatus, t as PredictionResult, H as PredictionSettledRecord, u as PredictionSource, J as SpotHistoryRecord, v as SpotHistoryType, T as TokenHoldingDTO, K as TradeRecordDTO } from './index-BK-jWEQ7.js';
8
8
  import * as _tanstack_react_query from '@tanstack/react-query';
9
9
  import { UseQueryOptions } from '@tanstack/react-query';
10
- import { ActivitiesSortBy, Activity, Chain, WalletPortfolios, Portfolio, WalletPnlResolution, WalletPnlSortBy, WalletPortfolioPnls, PositionState, PortfolioPnl } from '@liberfi.io/types';
10
+ import { Activity, ActivitiesSortBy, Chain, WalletPortfolios, Portfolio, WalletPortfolioPnls, WalletPnlResolution, PositionState, WalletPnlSortBy, PortfolioPnl } from '@liberfi.io/types';
11
11
  export { PositionState } from '@liberfi.io/types';
12
12
 
13
13
  /** Action button rendered in the popover action bar. */
@@ -514,6 +514,45 @@ declare function PortfolioPnlDetailsWidget({ chain, address, limit, initialResol
514
514
 
515
515
  declare const PortfolioClientContext: react.Context<IPortfolioClient | null>;
516
516
 
517
+ type PortfolioCapability = "holdings" | "net-worth" | "activities" | "perps" | "prediction";
518
+ type PortfolioAdapterResult<T> = {
519
+ kind: "ok";
520
+ data: T;
521
+ } | {
522
+ kind: "unsupported";
523
+ capability: PortfolioCapability;
524
+ } | {
525
+ kind: "error";
526
+ error: Error;
527
+ };
528
+ interface PortfolioActivitiesListener {
529
+ (items: SpotHistoryData["trades"]): void;
530
+ }
531
+ interface PortfolioDataAdapter {
532
+ getHoldings(query?: PortfolioQuery): Promise<PortfolioAdapterResult<SpotHoldingsData>>;
533
+ getNetWorth(query?: PortfolioQuery): Promise<PortfolioAdapterResult<PortfolioOverview>>;
534
+ getActivitiesPage(query?: SpotHistoryQuery): Promise<PortfolioAdapterResult<SpotHistoryData>>;
535
+ getPerpsPositions(query?: PortfolioQuery): Promise<PortfolioAdapterResult<{
536
+ positions: never[];
537
+ totalValue: number;
538
+ }>>;
539
+ getPredictionBets(query?: PortfolioQuery): Promise<PortfolioAdapterResult<{
540
+ bets: never[];
541
+ totalValue: number;
542
+ }>>;
543
+ subscribeActivities(listener: PortfolioActivitiesListener): {
544
+ unsubscribe(): void;
545
+ };
546
+ }
547
+ interface InMemoryPortfolioData {
548
+ holdings?: SpotHoldingsData;
549
+ netWorth?: PortfolioOverview;
550
+ activities?: SpotHistoryData;
551
+ }
552
+ declare function createInMemoryPortfolioDataAdapter(data?: InMemoryPortfolioData): PortfolioDataAdapter;
553
+
554
+ declare const PortfolioDataAdapterContext: react.Context<PortfolioDataAdapter | null>;
555
+
517
556
  /** Refetch function for wallet summary. */
518
557
  type RefetchWalletSummaryFn = () => Promise<void>;
519
558
  interface PortfolioContextValue {
@@ -528,8 +567,9 @@ declare const PortfolioContext: react.Context<PortfolioContextValue>;
528
567
 
529
568
  type PortfolioClientProviderProps = PropsWithChildren<{
530
569
  client: IPortfolioClient;
570
+ adapter?: PortfolioDataAdapter;
531
571
  }>;
532
- declare function PortfolioClientProvider({ client, children, }: PortfolioClientProviderProps): react_jsx_runtime.JSX.Element;
572
+ declare function PortfolioClientProvider({ client, adapter, children, }: PortfolioClientProviderProps): react_jsx_runtime.JSX.Element;
533
573
 
534
574
  type PortfolioProviderProps = PropsWithChildren<{
535
575
  chain: Chain;
@@ -541,6 +581,8 @@ declare function usePortfolioContext(): PortfolioContextValue;
541
581
 
542
582
  declare function usePortfolioClient(): IPortfolioClient;
543
583
 
584
+ declare function usePortfolioDataAdapter(): PortfolioDataAdapter;
585
+
544
586
  declare function overviewQueryKey(query?: PortfolioQuery): unknown[];
545
587
  declare function useOverviewQuery(query?: PortfolioQuery, queryOptions?: Omit<UseQueryOptions<PortfolioOverview, Error, PortfolioOverview, unknown[]>, "queryKey" | "queryFn">): _tanstack_react_query.UseQueryResult<PortfolioOverview, Error>;
546
588
 
@@ -614,6 +656,13 @@ declare function useWalletPortfolios({ chain, address, tokenAddresses, pollMs, }
614
656
  refetch: () => Promise<void>;
615
657
  };
616
658
 
659
+ /**
660
+ * Production adapter over the existing {@link IPortfolioClient}.
661
+ * Perps/prediction stay `unsupported` until a real backend exists —
662
+ * do not translate the current empty-array stubs into success.
663
+ */
664
+ declare function createClientPortfolioDataAdapter(client: IPortfolioClient): PortfolioDataAdapter;
665
+
617
666
  /**
618
667
  * Parse a decimal string to a number, returning 0 for empty / invalid values.
619
668
  */
@@ -658,7 +707,7 @@ declare function formatTokenBalance(value: number): string;
658
707
  * Build a Solana explorer URL for a transaction hash.
659
708
  * Defaults to Solscan. Can be extended for other chains in the future.
660
709
  */
661
- declare function getExplorerUrl(txHash: string, _chain?: string): string;
710
+ declare function getExplorerUrl(txHash: string, chain?: string): string;
662
711
  /**
663
712
  * Compute asset distribution from spot holdings for the donut chart.
664
713
  * Groups tokens with < 2% into "Other".
@@ -669,4 +718,4 @@ declare function computeDistribution(holdings: SpotHolding[]): DistributionData;
669
718
  */
670
719
  declare function formatTime(epochMs: number): string;
671
720
 
672
- export { type AccountAction, AccountInfoUI, type AccountInfoUIProps, AccountInfoWidget, type AccountInfoWidgetProps, AddressRowUI, type AddressRowUIProps, AssetTab, AssetTabsUI, type AssetTabsUIProps, AsyncStatus, BalanceRowUI, type BalanceRowUIProps, BatchActionButton, type BatchActionButtonProps, ConfirmDialog, type ConfirmDialogProps, CurveCardUI, type CurveCardUIProps, CurveData, CurvePeriod, CurveQuery, CurveType, DistributionCardUI, type DistributionCardUIProps, DistributionData, HoldingsEmpty, type HoldingsEmptyProps, type HoldingsRenderProps, HoldingsSearch, type HoldingsSearchProps, HoldingsSectionWidget, type HoldingsSectionWidgetProps, HoldingsSubTabs, type HoldingsSubTabsProps, IPortfolioClient, PerpsHistoryData, PerpsHistoryQuery, PerpsPanelUI, type PerpsPanelUIProps, PerpsPosition, PerpsPositionsData, type PerpsSubTab, type PnlResolution, type PnlSortBy, PortfolioActivities, type PortfolioActivitiesProps, type PortfolioActivitiesSortBy, type PortfolioActivitiesTypeFilter, PortfolioActivitiesWidget, type PortfolioActivitiesWidgetProps, PortfolioClientContext, PortfolioClientProvider, type PortfolioClientProviderProps, PortfolioContext, type PortfolioContextValue, PortfolioNetWorthTokens, type PortfolioNetWorthTokensProps, PortfolioNetWorthTokensWidget, type PortfolioNetWorthTokensWidgetProps, PortfolioOverview, PortfolioPageSkeleton, PortfolioPageWidget, type PortfolioPageWidgetProps, PortfolioPnlDetails, type PortfolioPnlDetailsProps, PortfolioPnlDetailsWidget, type PortfolioPnlDetailsWidgetProps, PortfolioProvider, type PortfolioProviderProps, PortfolioQuery, PredictionBet, PredictionBetsData, PredictionPanelUI, type PredictionPanelUIProps, PredictionSettledData, PredictionSettledQuery, type PredictionSubTab, type RefetchWalletSummaryFn, SpotHistoryData, SpotHistoryQuery, SpotHolding, SpotHoldingsData, SpotPanelUI, type SpotPanelUIProps, type SpotSubTab, TagBadge, TagBadgeList, type TagBadgeListProps, type TagBadgeProps, type TokenPortfolio, type UseAccountInfoResult, type UseHoldingsSectionOptions, type UseHoldingsSectionResult, type UsePortfolioActivitiesScriptParams, type UsePortfolioActivitiesScriptResult, type UsePortfolioNetWorthTokensScriptParams, type UsePortfolioNetWorthTokensScriptResult, type UsePortfolioPageOptions, type UsePortfolioPageResult, type UsePortfolioPnlDetailsScriptParams, type UsePortfolioPnlDetailsScriptResult, type UseWalletPortfoliosParams, ViewingBannerUI, type ViewingBannerUIProps, type WalletOption, WalletSummary, computeDistribution, curveDataQueryKey, distributionQueryKey, formatAgeShort, formatPercent, formatSignedUsd, formatTime, formatTokenBalance, formatUsd, getExplorerUrl, overviewQueryKey, parseDecimal, perpsHistoryQueryKey, perpsPositionsQueryKey, predictionBetsQueryKey, predictionSettledQueryKey, splitUsd, spotHistoryQueryKey, spotHoldingsQueryKey, truncateAddress, truncateMiddle, useAccountInfo, useCurveDataQuery, useDistributionQuery, useHoldingsSection, useOverviewQuery, usePerpsHistoryQuery, usePerpsPositionsQuery, usePortfolioActivitiesScript, usePortfolioClient, usePortfolioContext, usePortfolioNetWorthTokensScript, usePortfolioPage, usePortfolioPnlDetailsScript, usePredictionBetsQuery, usePredictionSettledQuery, useRefetchWalletSummary, useSpotHistoryQuery, useSpotHoldingsQuery, useWalletPortfolios, useWalletSummary };
721
+ export { type AccountAction, AccountInfoUI, type AccountInfoUIProps, AccountInfoWidget, type AccountInfoWidgetProps, AddressRowUI, type AddressRowUIProps, AssetTab, AssetTabsUI, type AssetTabsUIProps, AsyncStatus, BalanceRowUI, type BalanceRowUIProps, BatchActionButton, type BatchActionButtonProps, ConfirmDialog, type ConfirmDialogProps, CurveCardUI, type CurveCardUIProps, CurveData, CurvePeriod, CurveQuery, CurveType, DistributionCardUI, type DistributionCardUIProps, DistributionData, HoldingsEmpty, type HoldingsEmptyProps, type HoldingsRenderProps, HoldingsSearch, type HoldingsSearchProps, HoldingsSectionWidget, type HoldingsSectionWidgetProps, HoldingsSubTabs, type HoldingsSubTabsProps, IPortfolioClient, PerpsHistoryData, PerpsHistoryQuery, PerpsPanelUI, type PerpsPanelUIProps, PerpsPosition, PerpsPositionsData, type PerpsSubTab, type PnlResolution, type PnlSortBy, PortfolioActivities, type PortfolioActivitiesProps, type PortfolioActivitiesSortBy, type PortfolioActivitiesTypeFilter, PortfolioActivitiesWidget, type PortfolioActivitiesWidgetProps, type PortfolioAdapterResult, type PortfolioCapability, PortfolioClientContext, PortfolioClientProvider, type PortfolioClientProviderProps, PortfolioContext, type PortfolioContextValue, type PortfolioDataAdapter, PortfolioDataAdapterContext, PortfolioNetWorthTokens, type PortfolioNetWorthTokensProps, PortfolioNetWorthTokensWidget, type PortfolioNetWorthTokensWidgetProps, PortfolioOverview, PortfolioPageSkeleton, PortfolioPageWidget, type PortfolioPageWidgetProps, PortfolioPnlDetails, type PortfolioPnlDetailsProps, PortfolioPnlDetailsWidget, type PortfolioPnlDetailsWidgetProps, PortfolioProvider, type PortfolioProviderProps, PortfolioQuery, PredictionBet, PredictionBetsData, PredictionPanelUI, type PredictionPanelUIProps, PredictionSettledData, PredictionSettledQuery, type PredictionSubTab, type RefetchWalletSummaryFn, SpotHistoryData, SpotHistoryQuery, SpotHolding, SpotHoldingsData, SpotPanelUI, type SpotPanelUIProps, type SpotSubTab, TagBadge, TagBadgeList, type TagBadgeListProps, type TagBadgeProps, type TokenPortfolio, type UseAccountInfoResult, type UseHoldingsSectionOptions, type UseHoldingsSectionResult, type UsePortfolioActivitiesScriptParams, type UsePortfolioActivitiesScriptResult, type UsePortfolioNetWorthTokensScriptParams, type UsePortfolioNetWorthTokensScriptResult, type UsePortfolioPageOptions, type UsePortfolioPageResult, type UsePortfolioPnlDetailsScriptParams, type UsePortfolioPnlDetailsScriptResult, type UseWalletPortfoliosParams, ViewingBannerUI, type ViewingBannerUIProps, type WalletOption, WalletSummary, computeDistribution, createClientPortfolioDataAdapter, createInMemoryPortfolioDataAdapter, curveDataQueryKey, distributionQueryKey, formatAgeShort, formatPercent, formatSignedUsd, formatTime, formatTokenBalance, formatUsd, getExplorerUrl, overviewQueryKey, parseDecimal, perpsHistoryQueryKey, perpsPositionsQueryKey, predictionBetsQueryKey, predictionSettledQueryKey, splitUsd, spotHistoryQueryKey, spotHoldingsQueryKey, truncateAddress, truncateMiddle, useAccountInfo, useCurveDataQuery, useDistributionQuery, useHoldingsSection, useOverviewQuery, usePerpsHistoryQuery, usePerpsPositionsQuery, usePortfolioActivitiesScript, usePortfolioClient, usePortfolioContext, usePortfolioDataAdapter, usePortfolioNetWorthTokensScript, usePortfolioPage, usePortfolioPnlDetailsScript, usePredictionBetsQuery, usePredictionSettledQuery, useRefetchWalletSummary, useSpotHistoryQuery, useSpotHoldingsQuery, useWalletPortfolios, useWalletSummary };