@cygnus-wealth/data-models 0.0.2 → 1.0.0

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.
Files changed (41) hide show
  1. package/README.md +366 -63
  2. package/dist/enums/AccountType.d.ts +41 -0
  3. package/dist/enums/AccountType.js +41 -0
  4. package/dist/enums/AssetType.d.ts +114 -0
  5. package/dist/enums/AssetType.js +114 -0
  6. package/dist/enums/Chain.d.ts +57 -0
  7. package/dist/enums/Chain.js +57 -0
  8. package/dist/enums/IntegrationSource.d.ts +47 -0
  9. package/dist/enums/IntegrationSource.js +47 -4
  10. package/dist/enums/LendingPositionType.d.ts +25 -0
  11. package/dist/enums/LendingPositionType.js +26 -0
  12. package/dist/enums/TransactionType.d.ts +50 -0
  13. package/dist/enums/TransactionType.js +50 -0
  14. package/dist/index.d.ts +2 -0
  15. package/dist/index.js +1 -0
  16. package/dist/interfaces/Account.d.ts +92 -0
  17. package/dist/interfaces/ApiError.d.ts +61 -0
  18. package/dist/interfaces/ApiResponse.d.ts +60 -1
  19. package/dist/interfaces/Asset.d.ts +59 -0
  20. package/dist/interfaces/Balance.d.ts +52 -0
  21. package/dist/interfaces/BaseEntity.d.ts +61 -0
  22. package/dist/interfaces/FilterOptions.d.ts +68 -0
  23. package/dist/interfaces/IntegrationCredentials.d.ts +54 -0
  24. package/dist/interfaces/LendingPosition.d.ts +89 -4
  25. package/dist/interfaces/LiquidityPosition.d.ts +66 -2
  26. package/dist/interfaces/MarketData.d.ts +53 -0
  27. package/dist/interfaces/Metadata.d.ts +86 -0
  28. package/dist/interfaces/NFT.d.ts +55 -0
  29. package/dist/interfaces/PaginatedResponse.d.ts +59 -0
  30. package/dist/interfaces/Portfolio.d.ts +104 -2
  31. package/dist/interfaces/PortfolioAsset.d.ts +76 -0
  32. package/dist/interfaces/PortfolioAsset.js +1 -0
  33. package/dist/interfaces/PortfolioItem.d.ts +13 -0
  34. package/dist/interfaces/Price.d.ts +45 -2
  35. package/dist/interfaces/StakedPosition.d.ts +77 -0
  36. package/dist/interfaces/SyncStatus.d.ts +55 -0
  37. package/dist/interfaces/Transaction.d.ts +114 -2
  38. package/dist/types/AssetIdentifier.d.ts +61 -0
  39. package/dist/types/SortOrder.d.ts +50 -0
  40. package/dist/types/TimeRange.d.ts +51 -0
  41. package/package.json +29 -3
@@ -1,11 +1,65 @@
1
1
  import { IntegrationSource } from '../enums/IntegrationSource';
2
2
  import { Metadata } from './Metadata';
3
+ /**
4
+ * Encrypted credentials for CEX/brokerage API integration.
5
+ *
6
+ * Stores connection credentials for read-only API access to centralized exchanges,
7
+ * brokerages, and blockchain wallets. Designed for client-side encryption and
8
+ * secure storage patterns.
9
+ *
10
+ * **Security Pattern:** Credentials stored in this interface should be encrypted
11
+ * before persistence using Web Crypto API or similar client-side encryption.
12
+ * NEVER store private keys - only read-only API keys for data fetching.
13
+ *
14
+ * **Design Pattern:** Flexible credential structure supporting both API key-based
15
+ * authentication (CEX) and address-based read-only access (wallets).
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * import { IntegrationCredentials, IntegrationSource } from '@cygnus-wealth/data-models';
20
+ *
21
+ * // Kraken CEX credentials (API key + secret)
22
+ * const krakenCreds: IntegrationCredentials = {
23
+ * source: IntegrationSource.KRAKEN,
24
+ * apiKey: 'encrypted_api_key_here',
25
+ * apiSecret: 'encrypted_api_secret_here'
26
+ * };
27
+ *
28
+ * // Coinbase Pro credentials (with passphrase)
29
+ * const coinbaseCreds: IntegrationCredentials = {
30
+ * source: IntegrationSource.COINBASE,
31
+ * apiKey: 'encrypted_api_key',
32
+ * apiSecret: 'encrypted_secret',
33
+ * passphrase: 'encrypted_passphrase'
34
+ * };
35
+ *
36
+ * // MetaMask wallet (address-based read-only)
37
+ * const walletCreds: IntegrationCredentials = {
38
+ * source: IntegrationSource.METAMASK,
39
+ * walletAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
40
+ * chainId: '1' // Ethereum mainnet
41
+ * };
42
+ * ```
43
+ *
44
+ * @since 0.0.1
45
+ * @stability standard
46
+ *
47
+ * @see {@link IntegrationSource} for supported sources
48
+ * @see {@link Account} for credential usage in data fetching
49
+ */
3
50
  export interface IntegrationCredentials {
51
+ /** Integration source requiring these credentials */
4
52
  source: IntegrationSource;
53
+ /** API key for CEX/brokerage authentication (should be encrypted) */
5
54
  apiKey?: string;
55
+ /** API secret for CEX/brokerage authentication (should be encrypted) */
6
56
  apiSecret?: string;
57
+ /** Additional passphrase for some exchanges (Coinbase Pro, etc.) (should be encrypted) */
7
58
  passphrase?: string;
59
+ /** Wallet address for read-only blockchain queries (NOT private key) */
8
60
  walletAddress?: string;
61
+ /** Blockchain network ID for wallet connections (e.g., '1' for Ethereum mainnet) */
9
62
  chainId?: string;
63
+ /** Source-specific metadata (permissions, connection settings, etc.) */
10
64
  metadata?: Metadata;
11
65
  }
@@ -1,18 +1,103 @@
1
1
  import { Chain } from '../enums/Chain';
2
+ import { LendingPositionType } from '../enums/LendingPositionType';
2
3
  import { Asset } from './Asset';
3
4
  import { Price } from './Price';
4
5
  import { Metadata } from './Metadata';
6
+ /**
7
+ * DeFi money market positions for lending and borrowing.
8
+ *
9
+ * Represents user positions in lending protocols (Aave, Compound, etc.) where
10
+ * users can supply assets to earn interest (SUPPLY) or borrow assets against
11
+ * collateral (BORROW). Tracks amounts, interest rates, health factors, and
12
+ * liquidation thresholds critical for position management.
13
+ *
14
+ * **Design Pattern:** DeFi position entity discriminated by type (SUPPLY vs BORROW).
15
+ * Health factor and liquidation threshold are essential for monitoring borrow
16
+ * position safety and preventing liquidations.
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * import { LendingPosition, LendingPositionType, Chain } from '@cygnus-wealth/data-models';
21
+ *
22
+ * // Aave supply position (earning interest)
23
+ * const supplyPosition: LendingPosition = {
24
+ * id: 'aave-supply-usdc-123',
25
+ * protocol: 'Aave V3',
26
+ * chain: Chain.ETHEREUM,
27
+ * type: LendingPositionType.SUPPLY,
28
+ * asset: {
29
+ * id: 'ethereum-usdc',
30
+ * symbol: 'USDC',
31
+ * name: 'USD Coin',
32
+ * type: AssetType.CRYPTOCURRENCY,
33
+ * decimals: 6
34
+ * },
35
+ * amount: '50000', // $50k supplied
36
+ * apy: 3.5, // 3.5% APY
37
+ * accruedInterest: 125.50,
38
+ * value: {
39
+ * value: 50125.50,
40
+ * currency: 'USD',
41
+ * timestamp: new Date()
42
+ * }
43
+ * };
44
+ *
45
+ * // Aave borrow position (paying interest)
46
+ * const borrowPosition: LendingPosition = {
47
+ * id: 'aave-borrow-dai-456',
48
+ * protocol: 'Aave V3',
49
+ * chain: Chain.ETHEREUM,
50
+ * type: LendingPositionType.BORROW,
51
+ * asset: {
52
+ * id: 'ethereum-dai',
53
+ * symbol: 'DAI',
54
+ * name: 'Dai Stablecoin',
55
+ * type: AssetType.CRYPTOCURRENCY,
56
+ * decimals: 18
57
+ * },
58
+ * amount: '30000', // $30k borrowed
59
+ * apy: 5.2, // 5.2% borrow rate
60
+ * accruedInterest: -85.30, // Interest owed
61
+ * healthFactor: 2.5, // > 1.0 = safe
62
+ * liquidationThreshold: 0.85, // 85% LTV
63
+ * value: {
64
+ * value: -30085.30, // Negative for debt
65
+ * currency: 'USD',
66
+ * timestamp: new Date()
67
+ * }
68
+ * };
69
+ * ```
70
+ *
71
+ * @since 0.0.1
72
+ * @stability extended
73
+ *
74
+ * @see {@link LendingPositionType} for SUPPLY vs BORROW discrimination
75
+ * @see {@link Asset} for lent/borrowed asset definition
76
+ * @see {@link Account} for position aggregation
77
+ */
5
78
  export interface LendingPosition {
79
+ /** Unique identifier for this lending position */
6
80
  id: string;
81
+ /** Lending protocol name (e.g., 'Aave V3', 'Compound', 'Venus') */
7
82
  protocol: string;
83
+ /** Blockchain network where the lending position exists */
8
84
  chain: Chain;
9
- type: 'SUPPLY' | 'BORROW';
85
+ /** Position type: SUPPLY (lender) or BORROW (borrower) */
86
+ type: LendingPositionType;
87
+ /** Asset being supplied or borrowed */
10
88
  asset: Asset;
89
+ /** Amount supplied or borrowed (as string for precision) */
11
90
  amount: string;
91
+ /** Annual Percentage Yield (for supply) or Rate (for borrow) (e.g., 3.5 = 3.5%) */
12
92
  apy?: number;
13
- accrued_interest?: number;
14
- health_factor?: number;
15
- liquidation_threshold?: number;
93
+ /** Interest accrued (positive for supply, negative for borrow) */
94
+ accruedInterest?: number;
95
+ /** Health factor for borrow positions (ratio of collateral to debt, \>1.0 = safe) */
96
+ healthFactor?: number;
97
+ /** Liquidation threshold as ratio (0.0-1.0, e.g., 0.85 = 85% LTV before liquidation) */
98
+ liquidationThreshold?: number;
99
+ /** Current total value of position (positive for supply, negative for borrow debt) */
16
100
  value?: Price;
101
+ /** Protocol-specific metadata (collateral assets, liquidation price, etc.) */
17
102
  metadata?: Metadata;
18
103
  }
@@ -2,17 +2,81 @@ import { Chain } from '../enums/Chain';
2
2
  import { Balance } from './Balance';
3
3
  import { Price } from './Price';
4
4
  import { Metadata } from './Metadata';
5
+ /**
6
+ * DEX liquidity pool position tracking LP tokens and performance.
7
+ *
8
+ * Represents user's position in automated market maker (AMM) liquidity pools
9
+ * across various DEX protocols (Uniswap, Curve, Balancer, etc.). Tracks deposited
10
+ * tokens, LP token ownership, pool share, earned fees, and impermanent loss.
11
+ *
12
+ * **Design Pattern:** DeFi position entity capturing both the underlying tokens
13
+ * deposited and the LP token representation, along with performance metrics
14
+ * specific to liquidity provision.
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * import { LiquidityPosition, Chain } from '@cygnus-wealth/data-models';
19
+ *
20
+ * // Uniswap V2 ETH/USDC pool position
21
+ * const uniswapPosition: LiquidityPosition = {
22
+ * id: 'uniswap-eth-usdc-123',
23
+ * protocol: 'Uniswap V2',
24
+ * poolAddress: '0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc',
25
+ * poolName: 'ETH/USDC',
26
+ * chain: Chain.ETHEREUM,
27
+ * tokens: [
28
+ * {
29
+ * assetId: 'ethereum-eth',
30
+ * asset: {...},
31
+ * amount: '5.0'
32
+ * },
33
+ * {
34
+ * assetId: 'ethereum-usdc',
35
+ * asset: {...},
36
+ * amount: '10000'
37
+ * }
38
+ * ],
39
+ * lpTokenBalance: '707.106781186548', // LP token amount
40
+ * share: 0.05, // 5% of the pool
41
+ * value: {
42
+ * value: 20000,
43
+ * currency: 'USD',
44
+ * timestamp: new Date()
45
+ * },
46
+ * feesEarned: 150.50, // $150.50 earned in fees
47
+ * impermanentLoss: -25.30 // -$25.30 IL
48
+ * };
49
+ * ```
50
+ *
51
+ * @since 0.0.1
52
+ * @stability extended
53
+ *
54
+ * @see {@link Balance} for token balance structure
55
+ * @see {@link Account} for position aggregation
56
+ */
5
57
  export interface LiquidityPosition {
58
+ /** Unique identifier for this liquidity position */
6
59
  id: string;
60
+ /** DEX protocol name (e.g., 'Uniswap V3', 'Curve', 'Balancer V2') */
7
61
  protocol: string;
62
+ /** Smart contract address of the liquidity pool */
8
63
  poolAddress: string;
64
+ /** Human-readable pool name (e.g., 'ETH/USDC', 'stETH/ETH') */
9
65
  poolName: string;
66
+ /** Blockchain network where the pool exists */
10
67
  chain: Chain;
68
+ /** Array of token balances deposited in the pool (typically 2-8 tokens) */
11
69
  tokens: Balance[];
70
+ /** Amount of LP tokens held (represents pool share) */
12
71
  lpTokenBalance?: string;
72
+ /** Percentage of total pool owned (0.0-1.0, e.g., 0.05 = 5%) */
13
73
  share?: number;
74
+ /** Current total value of the position (sum of all tokens) */
14
75
  value?: Price;
15
- fees_earned?: number;
16
- impermanent_loss?: number;
76
+ /** Total trading fees earned from this position (in value.currency) */
77
+ feesEarned?: number;
78
+ /** Impermanent loss compared to holding tokens (negative = loss, positive = gain) */
79
+ impermanentLoss?: number;
80
+ /** Protocol-specific metadata (pool version, fee tier, range bounds, etc.) */
17
81
  metadata?: Metadata;
18
82
  }
@@ -1,14 +1,67 @@
1
1
  import { Price } from './Price';
2
+ /**
3
+ * Extended market data for analytics and research features.
4
+ *
5
+ * Comprehensive market information including price, market cap, trading volume,
6
+ * supply metrics, price changes, and 24-hour price range. Used for advanced
7
+ * analytics, market research, and detailed asset views.
8
+ *
9
+ * **Design Pattern:** Extends basic Price with market-specific metrics from
10
+ * CoinGecko, CoinMarketCap, or other market data providers. All fields except
11
+ * assetId, currentPrice, and lastUpdated are optional to handle varying data
12
+ * availability.
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * import { MarketData } from '@cygnus-wealth/data-models';
17
+ *
18
+ * // Comprehensive market data for analytics
19
+ * const ethMarketData: MarketData = {
20
+ * assetId: 'ethereum-eth',
21
+ * currentPrice: {
22
+ * value: 2000,
23
+ * currency: 'USD',
24
+ * timestamp: new Date()
25
+ * },
26
+ * marketCap: 240000000000, // $240B
27
+ * volume24h: 12000000000, // $12B daily volume
28
+ * priceChange24h: 50,
29
+ * priceChangePercentage24h: 2.5,
30
+ * high24h: 2050,
31
+ * low24h: 1950,
32
+ * circulatingSupply: 120000000,
33
+ * totalSupply: 120000000,
34
+ * lastUpdated: new Date()
35
+ * };
36
+ * ```
37
+ *
38
+ * @since 0.0.1
39
+ * @stability standard
40
+ *
41
+ * @see {@link Price} for base price structure
42
+ * @see {@link Asset} for asset definitions
43
+ */
2
44
  export interface MarketData {
45
+ /** Reference to Asset.id for this market data */
3
46
  assetId: string;
47
+ /** Current market price with timestamp */
4
48
  currentPrice: Price;
49
+ /** Total market capitalization (price * circulating supply) */
5
50
  marketCap?: number;
51
+ /** Trading volume in last 24 hours */
6
52
  volume24h?: number;
53
+ /** Absolute price change in last 24 hours (in currentPrice.currency) */
7
54
  priceChange24h?: number;
55
+ /** Percentage price change in last 24 hours (e.g., 2.5 = 2.5%) */
8
56
  priceChangePercentage24h?: number;
57
+ /** Highest price in last 24 hours */
9
58
  high24h?: number;
59
+ /** Lowest price in last 24 hours */
10
60
  low24h?: number;
61
+ /** Number of tokens in circulation (available for trading) */
11
62
  circulatingSupply?: number;
63
+ /** Total number of tokens that currently exist (including locked) */
12
64
  totalSupply?: number;
65
+ /** Timestamp when this market data was last updated */
13
66
  lastUpdated: Date;
14
67
  }
@@ -1,3 +1,89 @@
1
+ /**
2
+ * Extensible metadata container for source-specific and custom data.
3
+ *
4
+ * Metadata provides a flexible mechanism for storing additional information that
5
+ * doesn't fit into standardized model fields. This pattern enables the core data
6
+ * models to remain clean and source-agnostic while allowing integration domains
7
+ * to preserve source-specific details.
8
+ *
9
+ * **Design Pattern: Extension Object**
10
+ * The Metadata interface implements the Extension Object pattern, allowing models
11
+ * to be extended without modifying their core structure. This maintains backward
12
+ * compatibility while enabling forward extensibility.
13
+ *
14
+ * **Use Cases**:
15
+ * - Source-specific identifiers (e.g., Robinhood internal IDs, CEX trade IDs)
16
+ * - Integration-specific flags or configuration
17
+ * - Experimental data during feature development
18
+ * - Custom tags or labels added by consuming domains
19
+ * - Raw response data for debugging
20
+ *
21
+ * **Guidelines**:
22
+ * - Keys should be namespaced to avoid conflicts (e.g., `"robinhood:accountId"`)
23
+ * - Values should be JSON-serializable
24
+ * - Do NOT store sensitive data (API keys, private keys, passwords)
25
+ * - Document custom metadata keys in consuming domain documentation
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * // Asset with Coinbase-specific metadata
30
+ * const asset: Asset = {
31
+ * id: "btc-bitcoin",
32
+ * symbol: "BTC",
33
+ * name: "Bitcoin",
34
+ * type: AssetType.CRYPTOCURRENCY,
35
+ * metadata: {
36
+ * "coinbase:currencyCode": "BTC",
37
+ * "coinbase:tradingPair": "BTC-USD",
38
+ * "coinbase:minSize": "0.00000001",
39
+ * "tags": ["major", "layer1"],
40
+ * "lastSyncedAt": "2025-01-15T10:30:00Z"
41
+ * }
42
+ * };
43
+ * ```
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * // Transaction with chain-specific metadata
48
+ * const transaction: Transaction = {
49
+ * id: "txn_123",
50
+ * hash: "0xabc...",
51
+ * type: TransactionType.SWAP,
52
+ * // ... other fields
53
+ * metadata: {
54
+ * "ethereum:gasUsed": "21000",
55
+ * "ethereum:gasPrice": "50000000000",
56
+ * "ethereum:blockNumber": "18500000",
57
+ * "uniswap:poolAddress": "0xdef...",
58
+ * "uniswap:fee": "0.003"
59
+ * }
60
+ * };
61
+ * ```
62
+ *
63
+ * @since 0.0.1
64
+ * @stability core
65
+ *
66
+ * @see {@link Asset} for usage in asset models
67
+ * @see {@link Transaction} for usage in transaction models
68
+ */
1
69
  export interface Metadata {
70
+ /**
71
+ * Arbitrary key-value pairs for extensibility.
72
+ *
73
+ * Keys should follow namespacing convention: `"source:field"` or `"domain:field"`
74
+ * to prevent collisions between different integration sources.
75
+ *
76
+ * Values must be JSON-serializable types (string, number, boolean, object, array, null).
77
+ * Avoid storing functions, circular references, or non-serializable types.
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * {
82
+ * "robinhood:accountId": "RH_ACC_123",
83
+ * "robinhood:isFractional": true,
84
+ * "custom:tags": ["watchlist", "high-priority"]
85
+ * }
86
+ * ```
87
+ */
2
88
  [key: string]: unknown;
3
89
  }
@@ -1,14 +1,69 @@
1
1
  import { Asset } from './Asset';
2
+ /**
3
+ * NFT-specific asset extensions including token IDs and metadata.
4
+ *
5
+ * Extends the base Asset interface with NFT-specific fields for collection
6
+ * information, unique token identification, visual content URIs, and trait
7
+ * attributes. Supports ERC-721, ERC-1155, SPL NFTs, and SUI Move NFTs.
8
+ *
9
+ * **Design Pattern:** Inherits all Asset fields (id, symbol, name, etc.) and
10
+ * adds NFT-specific data. The Asset.type should be AssetType.NFT for proper
11
+ * classification.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * import { NFT, AssetType, Chain } from '@cygnus-wealth/data-models';
16
+ *
17
+ * // ERC-721 NFT from OpenSea
18
+ * const nft: NFT = {
19
+ * // Asset base fields
20
+ * id: 'bayc-1234',
21
+ * symbol: 'BAYC',
22
+ * name: 'Bored Ape Yacht Club #1234',
23
+ * type: AssetType.NFT,
24
+ * chain: Chain.ETHEREUM,
25
+ * contractAddress: '0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D',
26
+ *
27
+ * // NFT-specific fields
28
+ * tokenId: '1234',
29
+ * collectionAddress: '0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D',
30
+ * collectionName: 'Bored Ape Yacht Club',
31
+ * tokenUri: 'ipfs://QmeSjSinHpPnmXmspMjwiXyN6zS4E9zccariGR3jxcaWtq/1234',
32
+ * imageUrl: 'https://example.com/bayc-1234.png',
33
+ * attributes: [
34
+ * { trait_type: 'Background', value: 'Blue' },
35
+ * { trait_type: 'Fur', value: 'Brown' },
36
+ * { trait_type: 'Rarity Score', value: 125.5, display_type: 'number' }
37
+ * ]
38
+ * };
39
+ * ```
40
+ *
41
+ * @since 0.0.1
42
+ * @stability standard
43
+ *
44
+ * @see {@link Asset} for inherited base fields
45
+ * @see {@link AssetType} - use AssetType.NFT for NFTs
46
+ */
2
47
  export interface NFT extends Asset {
48
+ /** Unique token identifier within the collection (e.g., '1234', '0x5f') */
3
49
  tokenId: string;
50
+ /** Smart contract address of the NFT collection */
4
51
  collectionAddress: string;
52
+ /** Human-readable name of the NFT collection */
5
53
  collectionName: string;
54
+ /** URI pointing to token metadata (IPFS, HTTP, or on-chain) */
6
55
  tokenUri?: string;
56
+ /** Direct URL to the NFT image for display */
7
57
  imageUrl?: string;
58
+ /** URL to animation or video content (MP4, GIF, etc.) */
8
59
  animationUrl?: string;
60
+ /** Array of trait attributes defining NFT characteristics and rarity */
9
61
  attributes?: Array<{
62
+ /** Category or type of the trait (e.g., 'Background', 'Fur', 'Eyes') */
10
63
  trait_type: string;
64
+ /** Value of the trait (can be text or numeric) */
11
65
  value: string | number;
66
+ /** Optional display hint for numeric traits (e.g., 'number', 'boost_percentage') */
12
67
  display_type?: string;
13
68
  }>;
14
69
  }
@@ -1,7 +1,66 @@
1
+ /**
2
+ * Paginated response wrapper for large datasets.
3
+ *
4
+ * Standard structure for paginated API responses enabling efficient handling
5
+ * of large collections (transactions, assets, etc.). Uses 1-indexed pages and
6
+ * provides hasMore flag for infinite scroll implementations.
7
+ *
8
+ * **Design Pattern:** Cursor-based pagination pattern with metadata for UI
9
+ * pagination controls and infinite scroll detection.
10
+ *
11
+ * @template T - Type of items in the collection
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * import { PaginatedResponse, Transaction } from '@cygnus-wealth/data-models';
16
+ *
17
+ * // First page of transactions
18
+ * const page1: PaginatedResponse<Transaction> = {
19
+ * items: [
20
+ * { id: 'tx-1', type: TransactionType.BUY, ... },
21
+ * { id: 'tx-2', type: TransactionType.SELL, ... },
22
+ * // ... 48 more items
23
+ * ],
24
+ * total: 523,
25
+ * page: 1,
26
+ * pageSize: 50,
27
+ * hasMore: true // (1 * 50) < 523
28
+ * };
29
+ *
30
+ * // Last page calculation
31
+ * const lastPage: PaginatedResponse<Transaction> = {
32
+ * items: [ ... 23 items ... ],
33
+ * total: 523,
34
+ * page: 11,
35
+ * pageSize: 50,
36
+ * hasMore: false // (11 * 50) >= 523
37
+ * };
38
+ *
39
+ * // Empty result set
40
+ * const emptyPage: PaginatedResponse<Transaction> = {
41
+ * items: [],
42
+ * total: 0,
43
+ * page: 1,
44
+ * pageSize: 50,
45
+ * hasMore: false
46
+ * };
47
+ * ```
48
+ *
49
+ * @since 0.0.1
50
+ * @stability standard
51
+ *
52
+ * @see {@link ApiResponse} for response wrapping
53
+ * @see {@link Transaction} for common paginated type
54
+ */
1
55
  export interface PaginatedResponse<T> {
56
+ /** Array of items for the current page */
2
57
  items: T[];
58
+ /** Total number of items across all pages */
3
59
  total: number;
60
+ /** Current page number (1-indexed) */
4
61
  page: number;
62
+ /** Number of items per page */
5
63
  pageSize: number;
64
+ /** Whether more pages exist after the current page (page * pageSize \< total) */
6
65
  hasMore: boolean;
7
66
  }
@@ -1,21 +1,123 @@
1
1
  import { Account } from './Account';
2
2
  import { Price } from './Price';
3
+ import { PortfolioAsset } from './PortfolioAsset';
4
+ import { Metadata } from './Metadata';
5
+ /**
6
+ * Complete user portfolio aggregating all accounts and holdings.
7
+ *
8
+ * Top-level aggregate combining all user accounts, positions, and assets into
9
+ * a unified portfolio view. Calculates total value, tracks historical performance,
10
+ * and maintains deduplicated asset lists across accounts.
11
+ *
12
+ * **Design Pattern:** Aggregate root pattern at portfolio level, composing multiple
13
+ * Account aggregates. Supports both account-based view (accounts array) and
14
+ * asset-based view (items array) for flexible UI rendering.
15
+ *
16
+ * **Aggregation Rules:**
17
+ * - totalValue = sum of all Account.totalValue
18
+ * - items = deduplicated PortfolioAssets across all accounts (same asset, different accounts)
19
+ * - performance = calculated from totalValueHistory changes
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * import { Portfolio } from '@cygnus-wealth/data-models';
24
+ *
25
+ * // Complete portfolio with multiple accounts
26
+ * const userPortfolio: Portfolio = {
27
+ * id: 'portfolio-user-123',
28
+ * userId: 'user-123',
29
+ * name: 'My Portfolio',
30
+ * accounts: [
31
+ * {
32
+ * id: 'metamask-wallet-1',
33
+ * name: 'Main Wallet',
34
+ * type: AccountType.WALLET,
35
+ * source: IntegrationSource.METAMASK,
36
+ * balances: [...],
37
+ * totalValue: { value: 50000, currency: 'USD', timestamp: new Date() }
38
+ * },
39
+ * {
40
+ * id: 'kraken-spot-1',
41
+ * name: 'Kraken Trading',
42
+ * type: AccountType.SPOT,
43
+ * source: IntegrationSource.KRAKEN,
44
+ * balances: [...],
45
+ * totalValue: { value: 30000, currency: 'USD', timestamp: new Date() }
46
+ * }
47
+ * ],
48
+ * items: [
49
+ * {
50
+ * id: 'portfolio-eth',
51
+ * assetId: 'ethereum-eth',
52
+ * asset: { symbol: 'ETH', name: 'Ethereum', ... },
53
+ * balance: { amount: '10.0', ... },
54
+ * value: { value: 20000, currency: 'USD', timestamp: new Date() },
55
+ * allocation: 0.25 // 25% of portfolio
56
+ * },
57
+ * // ... more assets
58
+ * ],
59
+ * totalValue: {
60
+ * value: 80000, // Sum of all accounts
61
+ * currency: 'USD',
62
+ * timestamp: new Date()
63
+ * },
64
+ * totalValueHistory: [
65
+ * { timestamp: new Date('2025-09-11'), value: { value: 75000, currency: 'USD', ... } },
66
+ * { timestamp: new Date('2025-10-11'), value: { value: 80000, currency: 'USD', ... } }
67
+ * ],
68
+ * performance: {
69
+ * day: 2.5, // +2.5% today
70
+ * week: 5.0, // +5.0% this week
71
+ * month: 6.67, // +6.67% this month
72
+ * year: 45.0, // +45% this year
73
+ * all_time: 60.0 // +60% all-time
74
+ * },
75
+ * lastUpdated: new Date()
76
+ * };
77
+ * ```
78
+ *
79
+ * @since 0.0.1
80
+ * @stability standard
81
+ *
82
+ * @see {@link Account} for individual account aggregation
83
+ * @see {@link PortfolioAsset} for asset composition
84
+ * @see {@link Price} for valuation structure
85
+ */
3
86
  export interface Portfolio {
87
+ /** Unique identifier for this portfolio */
4
88
  id: string;
5
- userId: string;
89
+ /** User ID owning this portfolio (for multi-user systems) */
90
+ userId?: string;
91
+ /** User-friendly portfolio name */
6
92
  name: string;
7
- accounts: Account[];
93
+ /** Array of all accounts in this portfolio */
94
+ accounts?: Account[];
95
+ /** Deduplicated array of all assets across accounts */
96
+ items?: PortfolioAsset[];
97
+ /** Total value of entire portfolio (sum of all account values) */
8
98
  totalValue: Price;
99
+ /** Historical value snapshots for performance tracking */
9
100
  totalValueHistory?: Array<{
101
+ /** Timestamp of the snapshot */
10
102
  timestamp: Date;
103
+ /** Portfolio value at that time */
11
104
  value: Price;
12
105
  }>;
106
+ /** Performance metrics as percentage changes (positive = gain, negative = loss) */
13
107
  performance?: {
108
+ /** 24-hour performance change percentage */
14
109
  day: number;
110
+ /** 7-day performance change percentage */
15
111
  week: number;
112
+ /** 30-day performance change percentage */
16
113
  month: number;
114
+ /** 365-day performance change percentage */
17
115
  year: number;
116
+ /** All-time performance change percentage */
18
117
  all_time: number;
19
118
  };
119
+ /** Timestamp of last portfolio data update */
20
120
  lastUpdated: Date;
121
+ /** Portfolio-specific metadata (theme, display preferences, etc.) */
122
+ metadata?: Metadata;
21
123
  }