amped-defi 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 (189) hide show
  1. package/README.md +757 -0
  2. package/dist/__mocks__/@sodax/sdk.d.ts +24 -0
  3. package/dist/__mocks__/@sodax/sdk.d.ts.map +1 -0
  4. package/dist/__mocks__/@sodax/sdk.js +24 -0
  5. package/dist/__mocks__/@sodax/sdk.js.map +1 -0
  6. package/dist/__tests__/setup.d.ts +4 -0
  7. package/dist/__tests__/setup.d.ts.map +1 -0
  8. package/dist/__tests__/setup.js +32 -0
  9. package/dist/__tests__/setup.js.map +1 -0
  10. package/dist/index.d.ts +66 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +281 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/policy/policyEngine.d.ts +119 -0
  15. package/dist/policy/policyEngine.d.ts.map +1 -0
  16. package/dist/policy/policyEngine.js +322 -0
  17. package/dist/policy/policyEngine.js.map +1 -0
  18. package/dist/providers/spokeProviderFactory.d.ts +38 -0
  19. package/dist/providers/spokeProviderFactory.d.ts.map +1 -0
  20. package/dist/providers/spokeProviderFactory.js +212 -0
  21. package/dist/providers/spokeProviderFactory.js.map +1 -0
  22. package/dist/sodax/client.d.ts +34 -0
  23. package/dist/sodax/client.d.ts.map +1 -0
  24. package/dist/sodax/client.js +99 -0
  25. package/dist/sodax/client.js.map +1 -0
  26. package/dist/tools/bridge.d.ts +105 -0
  27. package/dist/tools/bridge.d.ts.map +1 -0
  28. package/dist/tools/bridge.js +334 -0
  29. package/dist/tools/bridge.js.map +1 -0
  30. package/dist/tools/discovery.d.ts +141 -0
  31. package/dist/tools/discovery.d.ts.map +1 -0
  32. package/dist/tools/discovery.js +777 -0
  33. package/dist/tools/discovery.js.map +1 -0
  34. package/dist/tools/moneyMarket.d.ts +227 -0
  35. package/dist/tools/moneyMarket.d.ts.map +1 -0
  36. package/dist/tools/moneyMarket.js +867 -0
  37. package/dist/tools/moneyMarket.js.map +1 -0
  38. package/dist/tools/portfolio.d.ts +43 -0
  39. package/dist/tools/portfolio.d.ts.map +1 -0
  40. package/dist/tools/portfolio.js +538 -0
  41. package/dist/tools/portfolio.js.map +1 -0
  42. package/dist/tools/swap.d.ts +71 -0
  43. package/dist/tools/swap.d.ts.map +1 -0
  44. package/dist/tools/swap.js +762 -0
  45. package/dist/tools/swap.js.map +1 -0
  46. package/dist/tools/walletManagement.d.ts +80 -0
  47. package/dist/tools/walletManagement.d.ts.map +1 -0
  48. package/dist/tools/walletManagement.js +289 -0
  49. package/dist/tools/walletManagement.js.map +1 -0
  50. package/dist/types.d.ts +205 -0
  51. package/dist/types.d.ts.map +1 -0
  52. package/dist/types.js +5 -0
  53. package/dist/types.js.map +1 -0
  54. package/dist/utils/errorUtils.d.ts +2 -0
  55. package/dist/utils/errorUtils.d.ts.map +1 -0
  56. package/dist/utils/errorUtils.js +19 -0
  57. package/dist/utils/errorUtils.js.map +1 -0
  58. package/dist/utils/errors.d.ts +144 -0
  59. package/dist/utils/errors.d.ts.map +1 -0
  60. package/dist/utils/errors.js +310 -0
  61. package/dist/utils/errors.js.map +1 -0
  62. package/dist/utils/positionAggregator.d.ts +122 -0
  63. package/dist/utils/positionAggregator.d.ts.map +1 -0
  64. package/dist/utils/positionAggregator.js +377 -0
  65. package/dist/utils/positionAggregator.js.map +1 -0
  66. package/dist/utils/priceService.d.ts +45 -0
  67. package/dist/utils/priceService.d.ts.map +1 -0
  68. package/dist/utils/priceService.js +108 -0
  69. package/dist/utils/priceService.js.map +1 -0
  70. package/dist/utils/sodaxApi.d.ts +92 -0
  71. package/dist/utils/sodaxApi.d.ts.map +1 -0
  72. package/dist/utils/sodaxApi.js +143 -0
  73. package/dist/utils/sodaxApi.js.map +1 -0
  74. package/dist/utils/tokenResolver.d.ts +54 -0
  75. package/dist/utils/tokenResolver.d.ts.map +1 -0
  76. package/dist/utils/tokenResolver.js +252 -0
  77. package/dist/utils/tokenResolver.js.map +1 -0
  78. package/dist/wallet/backendConfig.d.ts +37 -0
  79. package/dist/wallet/backendConfig.d.ts.map +1 -0
  80. package/dist/wallet/backendConfig.js +125 -0
  81. package/dist/wallet/backendConfig.js.map +1 -0
  82. package/dist/wallet/backends/BankrBackend.d.ts +73 -0
  83. package/dist/wallet/backends/BankrBackend.d.ts.map +1 -0
  84. package/dist/wallet/backends/BankrBackend.js +315 -0
  85. package/dist/wallet/backends/BankrBackend.js.map +1 -0
  86. package/dist/wallet/backends/BankrWalletProvider.d.ts +75 -0
  87. package/dist/wallet/backends/BankrWalletProvider.d.ts.map +1 -0
  88. package/dist/wallet/backends/BankrWalletProvider.js +243 -0
  89. package/dist/wallet/backends/BankrWalletProvider.js.map +1 -0
  90. package/dist/wallet/backends/EnvBackend.d.ts +50 -0
  91. package/dist/wallet/backends/EnvBackend.d.ts.map +1 -0
  92. package/dist/wallet/backends/EnvBackend.js +114 -0
  93. package/dist/wallet/backends/EnvBackend.js.map +1 -0
  94. package/dist/wallet/backends/EvmWalletSkillBackend.d.ts +40 -0
  95. package/dist/wallet/backends/EvmWalletSkillBackend.d.ts.map +1 -0
  96. package/dist/wallet/backends/EvmWalletSkillBackend.js +81 -0
  97. package/dist/wallet/backends/EvmWalletSkillBackend.js.map +1 -0
  98. package/dist/wallet/backends/index.d.ts +10 -0
  99. package/dist/wallet/backends/index.d.ts.map +1 -0
  100. package/dist/wallet/backends/index.js +10 -0
  101. package/dist/wallet/backends/index.js.map +1 -0
  102. package/dist/wallet/index.d.ts +9 -0
  103. package/dist/wallet/index.d.ts.map +1 -0
  104. package/dist/wallet/index.js +12 -0
  105. package/dist/wallet/index.js.map +1 -0
  106. package/dist/wallet/providers/AmpedWalletProvider.d.ts +107 -0
  107. package/dist/wallet/providers/AmpedWalletProvider.d.ts.map +1 -0
  108. package/dist/wallet/providers/AmpedWalletProvider.js +208 -0
  109. package/dist/wallet/providers/AmpedWalletProvider.js.map +1 -0
  110. package/dist/wallet/providers/BankrBackend.d.ts +105 -0
  111. package/dist/wallet/providers/BankrBackend.d.ts.map +1 -0
  112. package/dist/wallet/providers/BankrBackend.js +327 -0
  113. package/dist/wallet/providers/BankrBackend.js.map +1 -0
  114. package/dist/wallet/providers/LocalKeyBackend.d.ts +62 -0
  115. package/dist/wallet/providers/LocalKeyBackend.d.ts.map +1 -0
  116. package/dist/wallet/providers/LocalKeyBackend.js +152 -0
  117. package/dist/wallet/providers/LocalKeyBackend.js.map +1 -0
  118. package/dist/wallet/providers/chainConfig.d.ts +209 -0
  119. package/dist/wallet/providers/chainConfig.d.ts.map +1 -0
  120. package/dist/wallet/providers/chainConfig.js +175 -0
  121. package/dist/wallet/providers/chainConfig.js.map +1 -0
  122. package/dist/wallet/providers/index.d.ts +30 -0
  123. package/dist/wallet/providers/index.d.ts.map +1 -0
  124. package/dist/wallet/providers/index.js +32 -0
  125. package/dist/wallet/providers/index.js.map +1 -0
  126. package/dist/wallet/providers/types.d.ts +156 -0
  127. package/dist/wallet/providers/types.d.ts.map +1 -0
  128. package/dist/wallet/providers/types.js +11 -0
  129. package/dist/wallet/providers/types.js.map +1 -0
  130. package/dist/wallet/skillWalletAdapter.d.ts +96 -0
  131. package/dist/wallet/skillWalletAdapter.d.ts.map +1 -0
  132. package/dist/wallet/skillWalletAdapter.js +280 -0
  133. package/dist/wallet/skillWalletAdapter.js.map +1 -0
  134. package/dist/wallet/types.d.ts +134 -0
  135. package/dist/wallet/types.d.ts.map +1 -0
  136. package/dist/wallet/types.js +138 -0
  137. package/dist/wallet/types.js.map +1 -0
  138. package/dist/wallet/walletManager.d.ts +111 -0
  139. package/dist/wallet/walletManager.d.ts.map +1 -0
  140. package/dist/wallet/walletManager.js +476 -0
  141. package/dist/wallet/walletManager.js.map +1 -0
  142. package/dist/wallet/walletRegistry.d.ts +95 -0
  143. package/dist/wallet/walletRegistry.d.ts.map +1 -0
  144. package/dist/wallet/walletRegistry.js +184 -0
  145. package/dist/wallet/walletRegistry.js.map +1 -0
  146. package/index.js +2 -0
  147. package/openclaw.plugin.json +37 -0
  148. package/package.json +69 -0
  149. package/src/__mocks__/@sodax/sdk.ts +28 -0
  150. package/src/__tests__/errors.test.ts +238 -0
  151. package/src/__tests__/policyEngine.test.ts +354 -0
  152. package/src/__tests__/positionAggregator.test.ts +271 -0
  153. package/src/__tests__/setup.ts +35 -0
  154. package/src/__tests__/sodaxApi.test.ts +203 -0
  155. package/src/__tests__/walletRegistry.test.ts +155 -0
  156. package/src/index.ts +376 -0
  157. package/src/policy/policyEngine.ts +389 -0
  158. package/src/providers/spokeProviderFactory.ts +283 -0
  159. package/src/sodax/client.ts +113 -0
  160. package/src/tools/bridge.ts +425 -0
  161. package/src/tools/discovery.ts +989 -0
  162. package/src/tools/moneyMarket.ts +1265 -0
  163. package/src/tools/portfolio.ts +697 -0
  164. package/src/tools/swap.ts +926 -0
  165. package/src/tools/walletManagement.ts +359 -0
  166. package/src/types.ts +228 -0
  167. package/src/utils/errorUtils.ts +16 -0
  168. package/src/utils/errors.ts +396 -0
  169. package/src/utils/positionAggregator.ts +559 -0
  170. package/src/utils/priceService.ts +153 -0
  171. package/src/utils/sodaxApi.ts +261 -0
  172. package/src/utils/tokenResolver.ts +286 -0
  173. package/src/wallet/backendConfig.ts +151 -0
  174. package/src/wallet/backends/BankrBackend.ts +399 -0
  175. package/src/wallet/backends/BankrWalletProvider.ts +329 -0
  176. package/src/wallet/backends/EnvBackend.ts +149 -0
  177. package/src/wallet/backends/EvmWalletSkillBackend.ts +110 -0
  178. package/src/wallet/backends/index.ts +10 -0
  179. package/src/wallet/index.ts +14 -0
  180. package/src/wallet/providers/AmpedWalletProvider.ts +267 -0
  181. package/src/wallet/providers/BankrBackend.ts +407 -0
  182. package/src/wallet/providers/LocalKeyBackend.ts +184 -0
  183. package/src/wallet/providers/chainConfig.ts +194 -0
  184. package/src/wallet/providers/index.ts +62 -0
  185. package/src/wallet/providers/types.ts +186 -0
  186. package/src/wallet/skillWalletAdapter.ts +335 -0
  187. package/src/wallet/types.ts +248 -0
  188. package/src/wallet/walletManager.ts +561 -0
  189. package/src/wallet/walletRegistry.ts +216 -0
@@ -0,0 +1,377 @@
1
+ /**
2
+ * Cross-Chain Money Market Position Aggregator
3
+ *
4
+ * Aggregates user positions across all supported chains to provide a unified view
5
+ * of their money market portfolio, including:
6
+ * - Total supplied/borrowed across all chains
7
+ * - Health factor and liquidation risk
8
+ * - Available borrowing power
9
+ * - Net position (supply - borrow)
10
+ * - Cross-chain collateral utilization
11
+ */
12
+ import { getSodaxClient } from '../sodax/client';
13
+ import { getSpokeProvider } from '../providers/spokeProviderFactory';
14
+ import { getWalletManager } from '../wallet/walletManager';
15
+ import { normalizeChainId } from '../wallet/types';
16
+ // ============================================================================
17
+ // Position Aggregation Functions
18
+ // ============================================================================
19
+ /**
20
+ * Aggregate money market positions across all supported chains
21
+ *
22
+ * @param walletId - The wallet identifier
23
+ * @param options - Aggregation options
24
+ * @returns Complete cross-chain position view
25
+ */
26
+ export async function aggregateCrossChainPositions(walletId, options = {}) {
27
+ const startTime = Date.now();
28
+ // Get wallet
29
+ const walletManager = getWalletManager();
30
+ const wallet = await walletManager.resolve(walletId);
31
+ const walletAddress = await wallet.getAddress();
32
+ // Get supported chains from SODAX
33
+ const sodax = getSodaxClient();
34
+ const sodaxChains = sodax.config.getSupportedSpokeChains();
35
+ // Map SDK chains to string IDs
36
+ const allSodaxChains = sodaxChains.map((c) => typeof c === 'string' ? c : c.id);
37
+ // Filter chains by what the wallet supports
38
+ // This is important for Bankr which only supports ethereum/polygon/base
39
+ const walletSupportedChains = wallet.supportedChains;
40
+ const filteredChains = allSodaxChains.filter((chainId) => wallet.supportsChain(normalizeChainId(chainId)));
41
+ // Determine which chains to query
42
+ const chainsToQuery = options.chainIds || filteredChains;
43
+ console.log('[positionAggregator] Wallet chain filter', {
44
+ walletType: wallet.type,
45
+ walletSupports: walletSupportedChains,
46
+ sodaxChains: allSodaxChains,
47
+ filteredChains: filteredChains,
48
+ normalizedFiltered: filteredChains.map(normalizeChainId),
49
+ });
50
+ console.log('[positionAggregator] Querying positions across chains', {
51
+ walletId,
52
+ address: walletAddress,
53
+ chains: chainsToQuery,
54
+ });
55
+ // Query positions from all chains in parallel
56
+ const chainResults = await Promise.allSettled(chainsToQuery.map(chainId => queryChainPositions(walletId, walletAddress, chainId)));
57
+ // Collect all positions
58
+ const allPositions = [];
59
+ const chainSummaries = [];
60
+ chainResults.forEach((result, index) => {
61
+ const chainId = chainsToQuery[index];
62
+ if (result.status === 'fulfilled') {
63
+ const { positions, summary } = result.value;
64
+ if (positions.length > 0 || options.includeZeroBalances) {
65
+ allPositions.push(...positions);
66
+ chainSummaries.push(summary);
67
+ }
68
+ }
69
+ else {
70
+ console.warn(`[positionAggregator] Failed to query chain ${chainId}:`, result.reason);
71
+ }
72
+ });
73
+ // Calculate aggregated summary
74
+ const summary = calculateAggregatedSummary(allPositions);
75
+ // Calculate collateral utilization
76
+ const collateralUtilization = calculateCollateralUtilization(allPositions, summary);
77
+ // Calculate risk metrics
78
+ const riskMetrics = calculateRiskMetrics(allPositions, summary);
79
+ const view = {
80
+ walletId,
81
+ address: walletAddress,
82
+ timestamp: new Date().toISOString(),
83
+ summary,
84
+ chainSummaries: chainSummaries.sort((a, b) => b.netWorthUsd - a.netWorthUsd),
85
+ positions: allPositions.sort((a, b) => (parseFloat(b.supply.balanceUsd) + parseFloat(b.borrow.balanceUsd)) -
86
+ (parseFloat(a.supply.balanceUsd) + parseFloat(a.borrow.balanceUsd))),
87
+ collateralUtilization,
88
+ riskMetrics,
89
+ };
90
+ console.log('[positionAggregator] Aggregation complete', {
91
+ durationMs: Date.now() - startTime,
92
+ totalPositions: allPositions.length,
93
+ totalSupplyUsd: summary.totalSupplyUsd,
94
+ totalBorrowUsd: summary.totalBorrowUsd,
95
+ healthFactor: summary.healthFactor,
96
+ });
97
+ return view;
98
+ }
99
+ /**
100
+ * Query positions for a single chain
101
+ *
102
+ * IMPORTANT: getUserReservesHumanized() only returns raw balances without token metadata.
103
+ * To get token symbols/names, we must:
104
+ * 1. Fetch getReservesHumanized() for token metadata
105
+ * 2. Format with formatReservesUSD(buildReserveDataWithPrice())
106
+ * 3. Join with formatUserSummary(buildUserSummaryRequest())
107
+ *
108
+ * Reference: sodax-frontend/packages/dapp-kit/src/hooks/mm/useUserFormattedSummary.ts
109
+ */
110
+ async function queryChainPositions(walletId, address, chainId) {
111
+ try {
112
+ // Use address for spoke provider lookup
113
+ const spokeProvider = await getSpokeProvider(walletId, chainId);
114
+ const sodax = getSodaxClient();
115
+ // Step 1: Fetch reserves with token metadata (symbols, names, decimals)
116
+ // This is the key fix - getUserReservesHumanized alone doesn't include token metadata
117
+ const reserves = await sodax.moneyMarket.data.getReservesHumanized();
118
+ // Step 2: Format reserves with USD prices
119
+ const formattedReserves = sodax.moneyMarket.data.formatReservesUSD(sodax.moneyMarket.data.buildReserveDataWithPrice(reserves));
120
+ // Step 3: Fetch user-specific balances
121
+ const userReserves = await sodax.moneyMarket.data.getUserReservesHumanized(spokeProvider);
122
+ // Step 4: Join reserves metadata with user balances via formatUserSummary
123
+ const userSummary = sodax.moneyMarket.data.formatUserSummary(sodax.moneyMarket.data.buildUserSummaryRequest(reserves, formattedReserves, userReserves));
124
+ // Extract user reserves from the formatted summary
125
+ // The formatted summary has userReservesData with proper token metadata
126
+ const userReservesData = userSummary.userReservesData || [];
127
+ // Convert to TokenPosition format
128
+ const positions = userReservesData.map((reserve) => {
129
+ // Get supply balance (underlyingBalance is the human-readable supply amount)
130
+ const supplyBalance = reserve.underlyingBalance || '0';
131
+ const supplyBalanceUsd = reserve.underlyingBalanceUSD || '0';
132
+ // Get borrow balance (variableBorrows is the human-readable borrow amount)
133
+ const borrowBalance = reserve.variableBorrows || reserve.totalBorrows || '0';
134
+ const borrowBalanceUsd = reserve.variableBorrowsUSD || reserve.totalBorrowsUSD || '0';
135
+ // Get APY values (formatted reserves have these)
136
+ const supplyApy = parseFloat(reserve.reserve?.supplyAPY || '0') * 100;
137
+ const borrowApy = parseFloat(reserve.reserve?.variableBorrowAPY || '0') * 100;
138
+ return {
139
+ chainId,
140
+ token: {
141
+ address: reserve.underlyingAsset || reserve.reserve?.underlyingAsset || '',
142
+ symbol: reserve.reserve?.symbol || '',
143
+ name: reserve.reserve?.name || '',
144
+ decimals: reserve.reserve?.decimals || 18,
145
+ logoURI: reserve.reserve?.iconSymbol || undefined,
146
+ },
147
+ supply: {
148
+ balance: supplyBalance,
149
+ balanceUsd: supplyBalanceUsd,
150
+ balanceRaw: reserve.scaledATokenBalance || '0',
151
+ apy: supplyApy,
152
+ isCollateral: reserve.usageAsCollateralEnabledOnUser ?? false,
153
+ },
154
+ borrow: {
155
+ balance: borrowBalance,
156
+ balanceUsd: borrowBalanceUsd,
157
+ balanceRaw: reserve.scaledVariableDebt || '0',
158
+ apy: borrowApy,
159
+ },
160
+ loanToValue: parseFloat(reserve.reserve?.baseLTVasCollateral || '0') / 10000,
161
+ liquidationThreshold: parseFloat(reserve.reserve?.reserveLiquidationThreshold || '0') / 10000,
162
+ };
163
+ });
164
+ // Filter out positions with zero balance (unless explicitly requested)
165
+ const activePositions = positions.filter(p => parseFloat(p.supply.balance) > 0 || parseFloat(p.borrow.balance) > 0);
166
+ // Calculate chain summary
167
+ const supplyUsd = activePositions.reduce((sum, p) => sum + parseFloat(p.supply.balanceUsd || '0'), 0);
168
+ const borrowUsd = activePositions.reduce((sum, p) => sum + parseFloat(p.borrow.balanceUsd || '0'), 0);
169
+ // Calculate health factor for this chain
170
+ const healthFactor = calculateChainHealthFactor(activePositions);
171
+ const summary = {
172
+ chainId,
173
+ supplyUsd,
174
+ borrowUsd,
175
+ netWorthUsd: supplyUsd - borrowUsd,
176
+ healthFactor,
177
+ positionCount: activePositions.length,
178
+ };
179
+ console.log(`[positionAggregator] Chain ${chainId}: ${activePositions.length} positions, supply=$${supplyUsd.toFixed(2)}, borrow=$${borrowUsd.toFixed(2)}`);
180
+ return { positions: activePositions, summary };
181
+ }
182
+ catch (error) {
183
+ console.error(`[positionAggregator] Error querying ${chainId}:`, error);
184
+ throw error;
185
+ }
186
+ }
187
+ // ============================================================================
188
+ // Calculation Helpers
189
+ // ============================================================================
190
+ /**
191
+ * Calculate aggregated summary across all positions
192
+ */
193
+ function calculateAggregatedSummary(positions) {
194
+ let totalSupplyUsd = 0;
195
+ let totalBorrowUsd = 0;
196
+ let weightedSupplyApy = 0;
197
+ let weightedBorrowApy = 0;
198
+ positions.forEach(pos => {
199
+ const supplyUsd = parseFloat(pos.supply.balanceUsd || '0');
200
+ const borrowUsd = parseFloat(pos.borrow.balanceUsd || '0');
201
+ totalSupplyUsd += supplyUsd;
202
+ totalBorrowUsd += borrowUsd;
203
+ weightedSupplyApy += supplyUsd * pos.supply.apy;
204
+ weightedBorrowApy += borrowUsd * pos.borrow.apy;
205
+ });
206
+ // Calculate weighted average APYs
207
+ const avgSupplyApy = totalSupplyUsd > 0 ? weightedSupplyApy / totalSupplyUsd : 0;
208
+ const avgBorrowApy = totalBorrowUsd > 0 ? weightedBorrowApy / totalBorrowUsd : 0;
209
+ // Calculate health factor
210
+ const healthFactor = calculateHealthFactor(positions);
211
+ // Determine liquidation risk
212
+ let liquidationRisk = 'none';
213
+ if (healthFactor !== null) {
214
+ if (healthFactor < 1.1)
215
+ liquidationRisk = 'high';
216
+ else if (healthFactor < 1.5)
217
+ liquidationRisk = 'medium';
218
+ else if (healthFactor < 2)
219
+ liquidationRisk = 'low';
220
+ }
221
+ // Calculate available borrow (simplified - would need proper oracle prices)
222
+ // This is a conservative estimate based on average LTV
223
+ const avgLtv = positions.length > 0
224
+ ? positions.reduce((sum, p) => sum + p.loanToValue, 0) / positions.length
225
+ : 0;
226
+ const availableBorrowUsd = totalSupplyUsd * avgLtv - totalBorrowUsd;
227
+ return {
228
+ totalSupplyUsd,
229
+ totalBorrowUsd,
230
+ netWorthUsd: totalSupplyUsd - totalBorrowUsd,
231
+ availableBorrowUsd: Math.max(0, availableBorrowUsd),
232
+ healthFactor,
233
+ liquidationRisk,
234
+ weightedSupplyApy: avgSupplyApy,
235
+ weightedBorrowApy: avgBorrowApy,
236
+ netApy: totalSupplyUsd > 0
237
+ ? (avgSupplyApy * totalSupplyUsd - avgBorrowApy * totalBorrowUsd) / totalSupplyUsd
238
+ : 0,
239
+ };
240
+ }
241
+ /**
242
+ * Calculate collateral utilization metrics
243
+ */
244
+ function calculateCollateralUtilization(positions, summary) {
245
+ // Only count collateral-enabled supplies
246
+ const totalCollateralUsd = positions
247
+ .filter(p => p.supply.isCollateral)
248
+ .reduce((sum, p) => sum + parseFloat(p.supply.balanceUsd || '0'), 0);
249
+ const usedCollateralUsd = summary.totalBorrowUsd;
250
+ const availableCollateralUsd = Math.max(0, totalCollateralUsd - usedCollateralUsd);
251
+ const utilizationRate = totalCollateralUsd > 0 ? (usedCollateralUsd / totalCollateralUsd) * 100 : 0;
252
+ return {
253
+ totalCollateralUsd,
254
+ usedCollateralUsd,
255
+ availableCollateralUsd,
256
+ utilizationRate,
257
+ };
258
+ }
259
+ /**
260
+ * Calculate risk metrics
261
+ */
262
+ function calculateRiskMetrics(positions, summary) {
263
+ // Calculate max LTV across all positions (weighted by supply)
264
+ let totalSupply = 0;
265
+ let weightedLtvSum = 0;
266
+ let liquidationThresholdSum = 0;
267
+ positions.forEach(pos => {
268
+ const supplyUsd = parseFloat(pos.supply.balanceUsd || '0');
269
+ totalSupply += supplyUsd;
270
+ weightedLtvSum += supplyUsd * pos.loanToValue;
271
+ liquidationThresholdSum += supplyUsd * pos.liquidationThreshold;
272
+ });
273
+ const maxLtv = totalSupply > 0 ? weightedLtvSum / totalSupply : 0;
274
+ const avgLiquidationThreshold = totalSupply > 0 ? liquidationThresholdSum / totalSupply : 0;
275
+ // Current LTV
276
+ const currentLtv = summary.totalSupplyUsd > 0
277
+ ? summary.totalBorrowUsd / summary.totalSupplyUsd
278
+ : 0;
279
+ // Buffer until liquidation (percentage points)
280
+ const bufferUntilLiquidation = Math.max(0, avgLiquidationThreshold - currentLtv) * 100;
281
+ // Safe max borrow (at 80% of liquidation threshold for safety)
282
+ const safeMaxBorrowUsd = summary.totalSupplyUsd * avgLiquidationThreshold * 0.8;
283
+ return {
284
+ maxLtv,
285
+ currentLtv,
286
+ bufferUntilLiquidation,
287
+ safeMaxBorrowUsd,
288
+ };
289
+ }
290
+ /**
291
+ * Calculate health factor for a set of positions
292
+ * Health Factor = (Total Collateral in ETH * Liquidation Threshold) / Total Borrow in ETH
293
+ */
294
+ function calculateHealthFactor(positions) {
295
+ let totalCollateralEth = 0;
296
+ let totalBorrowEth = 0;
297
+ positions.forEach(pos => {
298
+ const supplyUsd = parseFloat(pos.supply.balanceUsd || '0');
299
+ const borrowUsd = parseFloat(pos.borrow.balanceUsd || '0');
300
+ // Only count collateral-enabled supplies
301
+ if (pos.supply.isCollateral) {
302
+ totalCollateralEth += supplyUsd * pos.liquidationThreshold;
303
+ }
304
+ totalBorrowEth += borrowUsd;
305
+ });
306
+ if (totalBorrowEth === 0) {
307
+ return totalCollateralEth > 0 ? Infinity : null;
308
+ }
309
+ return totalCollateralEth / totalBorrowEth;
310
+ }
311
+ /**
312
+ * Calculate health factor for a single chain
313
+ */
314
+ function calculateChainHealthFactor(positions) {
315
+ return calculateHealthFactor(positions);
316
+ }
317
+ // ============================================================================
318
+ // Utility Functions
319
+ // ============================================================================
320
+ /**
321
+ * Format health factor for display
322
+ */
323
+ export function formatHealthFactor(hf) {
324
+ if (hf === null)
325
+ return 'N/A';
326
+ if (hf === Infinity)
327
+ return '∞';
328
+ return hf.toFixed(2);
329
+ }
330
+ /**
331
+ * Get health factor color/styling indicator
332
+ */
333
+ export function getHealthFactorStatus(hf) {
334
+ if (hf === null)
335
+ return { status: 'healthy', color: 'green' };
336
+ if (hf === Infinity)
337
+ return { status: 'healthy', color: 'green' };
338
+ if (hf < 1.1)
339
+ return { status: 'critical', color: 'red' };
340
+ if (hf < 1.5)
341
+ return { status: 'danger', color: 'orange' };
342
+ if (hf < 2)
343
+ return { status: 'caution', color: 'yellow' };
344
+ return { status: 'healthy', color: 'green' };
345
+ }
346
+ /**
347
+ * Get recommendation based on position health
348
+ */
349
+ export function getPositionRecommendation(view) {
350
+ const recommendations = [];
351
+ const { summary } = view;
352
+ // Health factor recommendations
353
+ if (summary.healthFactor !== null && summary.healthFactor < 1.5) {
354
+ recommendations.push('⚠️ Health factor is low. Consider repaying debt or adding collateral.');
355
+ }
356
+ // Borrowing capacity recommendations
357
+ if (summary.availableBorrowUsd > 1000 && summary.healthFactor !== null && summary.healthFactor > 2) {
358
+ recommendations.push(`💡 You have $${summary.availableBorrowUsd.toFixed(2)} in available borrowing power.`);
359
+ }
360
+ // Collateral utilization
361
+ if (view.collateralUtilization.utilizationRate > 80) {
362
+ recommendations.push('⚠️ High collateral utilization. Avoid borrowing more to maintain safety margin.');
363
+ }
364
+ // Net APY optimization
365
+ if (summary.netApy < 0) {
366
+ recommendations.push('📉 Your borrowing costs exceed supply earnings. Consider reducing debt or finding higher APY supply opportunities.');
367
+ }
368
+ // Cross-chain opportunities
369
+ const highApyChains = view.chainSummaries
370
+ .filter(cs => cs.supplyUsd > 100)
371
+ .sort((a, b) => (b.healthFactor || Infinity) - (a.healthFactor || Infinity));
372
+ if (highApyChains.length > 1) {
373
+ recommendations.push(`🌐 You have positions across ${highApyChains.length} chains. Monitor each chain's health factor independently.`);
374
+ }
375
+ return recommendations;
376
+ }
377
+ //# sourceMappingURL=positionAggregator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"positionAggregator.js","sourceRoot":"","sources":["../../src/utils/positionAggregator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Price Service - Fetches USD prices from SODAX reserves
3
+ *
4
+ * Uses the money market reserve data to get accurate USD prices
5
+ * for tokens supported by the protocol.
6
+ *
7
+ * @module utils/priceService
8
+ */
9
+ export interface TokenPrice {
10
+ symbol: string;
11
+ priceUsd: number;
12
+ underlyingAsset: string;
13
+ }
14
+ export interface PriceMap {
15
+ /** Map of symbol (lowercase) to USD price */
16
+ bySymbol: Map<string, number>;
17
+ /** Map of address (lowercase) to USD price */
18
+ byAddress: Map<string, number>;
19
+ /** Last update timestamp */
20
+ timestamp: number;
21
+ }
22
+ /**
23
+ * Fetch token prices from SODAX money market reserves
24
+ *
25
+ * The reserves contain `priceInMarketReferenceCurrency` which represents
26
+ * the price in 8 decimal USD (100000000 = $1.00)
27
+ */
28
+ export declare function fetchTokenPrices(): Promise<PriceMap>;
29
+ /**
30
+ * Get USD price for a token by symbol
31
+ */
32
+ export declare function getTokenPriceBySymbol(symbol: string): Promise<number | null>;
33
+ /**
34
+ * Get USD price for a token by address
35
+ */
36
+ export declare function getTokenPriceByAddress(address: string): Promise<number | null>;
37
+ /**
38
+ * Calculate USD value for a token amount
39
+ */
40
+ export declare function calculateUsdValue(symbol: string, amount: string | number): Promise<number | null>;
41
+ /**
42
+ * Clear the price cache (useful for testing)
43
+ */
44
+ export declare function clearPriceCache(): void;
45
+ //# sourceMappingURL=priceService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"priceService.d.ts","sourceRoot":"","sources":["../../src/utils/priceService.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,QAAQ;IACvB,6CAA6C;IAC7C,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,8CAA8C;IAC9C,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,4BAA4B;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB;AAaD;;;;;GAKG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,QAAQ,CAAC,CA2C1D;AAcD;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAgBlF;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAGpF;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GAAG,MAAM,GACtB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAMxB;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,IAAI,CAEtC"}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Price Service - Fetches USD prices from SODAX reserves
3
+ *
4
+ * Uses the money market reserve data to get accurate USD prices
5
+ * for tokens supported by the protocol.
6
+ *
7
+ * @module utils/priceService
8
+ */
9
+ import { getSodaxClient } from '../sodax/client';
10
+ // ============================================================================
11
+ // Cache
12
+ // ============================================================================
13
+ let cachedPrices = null;
14
+ const CACHE_TTL_MS = 60_000; // 1 minute cache
15
+ // ============================================================================
16
+ // Price Fetching
17
+ // ============================================================================
18
+ /**
19
+ * Fetch token prices from SODAX money market reserves
20
+ *
21
+ * The reserves contain `priceInMarketReferenceCurrency` which represents
22
+ * the price in 8 decimal USD (100000000 = $1.00)
23
+ */
24
+ export async function fetchTokenPrices() {
25
+ // Return cached if fresh
26
+ if (cachedPrices && Date.now() - cachedPrices.timestamp < CACHE_TTL_MS) {
27
+ return cachedPrices;
28
+ }
29
+ console.log('[priceService] Fetching token prices from SODAX reserves');
30
+ const sodax = await getSodaxClient();
31
+ const reserves = await sodax.moneyMarket.data.getReservesHumanized();
32
+ const bySymbol = new Map();
33
+ const byAddress = new Map();
34
+ // Market reference currency decimals (typically 8)
35
+ const PRICE_DECIMALS = 8;
36
+ for (const reserve of reserves.reservesData) {
37
+ // priceInMarketReferenceCurrency is a string representing the raw value
38
+ const priceRaw = BigInt(reserve.priceInMarketReferenceCurrency);
39
+ const priceUsd = Number(priceRaw) / Math.pow(10, PRICE_DECIMALS);
40
+ // Use symbol for matching (e.g., "sodaUSDC" -> "USDC")
41
+ const symbol = reserve.symbol.toLowerCase();
42
+ const normalizedSymbol = normalizeSymbol(reserve.symbol);
43
+ const address = reserve.underlyingAsset.toLowerCase();
44
+ bySymbol.set(symbol, priceUsd);
45
+ bySymbol.set(normalizedSymbol, priceUsd);
46
+ byAddress.set(address, priceUsd);
47
+ console.log(`[priceService] ${reserve.symbol}: $${priceUsd.toFixed(4)}`);
48
+ }
49
+ cachedPrices = {
50
+ bySymbol,
51
+ byAddress,
52
+ timestamp: Date.now(),
53
+ };
54
+ console.log(`[priceService] Cached ${bySymbol.size} token prices`);
55
+ return cachedPrices;
56
+ }
57
+ /**
58
+ * Normalize SODAX symbol to standard symbol
59
+ * e.g., "sodaUSDC" -> "usdc", "sodaETH" -> "eth"
60
+ */
61
+ function normalizeSymbol(symbol) {
62
+ const lower = symbol.toLowerCase();
63
+ if (lower.startsWith('soda')) {
64
+ return lower.slice(4); // Remove 'soda' prefix
65
+ }
66
+ return lower;
67
+ }
68
+ /**
69
+ * Get USD price for a token by symbol
70
+ */
71
+ export async function getTokenPriceBySymbol(symbol) {
72
+ const prices = await fetchTokenPrices();
73
+ const normalizedSymbol = symbol.toLowerCase();
74
+ // Try exact match first
75
+ if (prices.bySymbol.has(normalizedSymbol)) {
76
+ return prices.bySymbol.get(normalizedSymbol);
77
+ }
78
+ // Try with 'soda' prefix
79
+ const sodaSymbol = 'soda' + normalizedSymbol;
80
+ if (prices.bySymbol.has(sodaSymbol)) {
81
+ return prices.bySymbol.get(sodaSymbol);
82
+ }
83
+ return null;
84
+ }
85
+ /**
86
+ * Get USD price for a token by address
87
+ */
88
+ export async function getTokenPriceByAddress(address) {
89
+ const prices = await fetchTokenPrices();
90
+ return prices.byAddress.get(address.toLowerCase()) ?? null;
91
+ }
92
+ /**
93
+ * Calculate USD value for a token amount
94
+ */
95
+ export async function calculateUsdValue(symbol, amount) {
96
+ const price = await getTokenPriceBySymbol(symbol);
97
+ if (price === null)
98
+ return null;
99
+ const amountNum = typeof amount === 'string' ? parseFloat(amount) : amount;
100
+ return amountNum * price;
101
+ }
102
+ /**
103
+ * Clear the price cache (useful for testing)
104
+ */
105
+ export function clearPriceCache() {
106
+ cachedPrices = null;
107
+ }
108
+ //# sourceMappingURL=priceService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"priceService.js","sourceRoot":"","sources":["../../src/utils/priceService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * SODAX API Client
3
+ *
4
+ * Provides access to SODAX backend API endpoints for querying intents,
5
+ * user history, and other off-chain data.
6
+ */
7
+ export interface SodaxApiConfig {
8
+ baseUrl?: string;
9
+ apiKey?: string;
10
+ timeoutMs?: number;
11
+ }
12
+ export interface PaginationParams {
13
+ offset?: number;
14
+ limit?: number;
15
+ }
16
+ export interface PaginatedResponse<T> {
17
+ items: T[];
18
+ total: number;
19
+ offset: number;
20
+ limit: number;
21
+ }
22
+ export interface IntentState {
23
+ exists: boolean;
24
+ remainingInput: string;
25
+ receivedOutput: string;
26
+ pendingPayment: boolean;
27
+ }
28
+ export interface IntentEvent {
29
+ eventType: string;
30
+ txHash: string;
31
+ logIndex: number;
32
+ blockNumber: number;
33
+ intentState: IntentState;
34
+ }
35
+ export interface IntentDetails {
36
+ intentId: string;
37
+ creator: string;
38
+ inputToken: string;
39
+ outputToken: string;
40
+ inputAmount: string;
41
+ minOutputAmount: string;
42
+ deadline: string;
43
+ allowPartialFill: boolean;
44
+ srcChain: number;
45
+ dstChain: number;
46
+ srcAddress: string;
47
+ dstAddress: string;
48
+ solver: string;
49
+ data: string;
50
+ }
51
+ export interface UserIntent {
52
+ intentHash: string;
53
+ txHash: string;
54
+ logIndex: number;
55
+ chainId: number;
56
+ blockNumber: number;
57
+ open: boolean;
58
+ intent: IntentDetails;
59
+ events: IntentEvent[];
60
+ createdAt: string;
61
+ }
62
+ export interface UserIntentFilters {
63
+ open?: boolean;
64
+ srcChain?: number;
65
+ dstChain?: number;
66
+ inputToken?: string;
67
+ outputToken?: string;
68
+ }
69
+ export declare class SodaxApiClient {
70
+ private baseUrl;
71
+ private apiKey?;
72
+ private timeoutMs;
73
+ constructor(config?: SodaxApiConfig);
74
+ /**
75
+ * Get intent by intentHash
76
+ * Most reliable lookup method - works for all intents
77
+ */
78
+ getIntentByHash(intentHash: string): Promise<UserIntent | null>;
79
+ /**
80
+ * Get intent by transaction hash
81
+ * NOTE: This expects the HUB chain (Sonic) transaction hash, NOT spoke chain tx
82
+ */
83
+ getIntentByTxHash(txHash: string): Promise<UserIntent | null>;
84
+ getUserIntents(userAddress: string, pagination?: PaginationParams, filters?: UserIntentFilters): Promise<PaginatedResponse<UserIntent>>;
85
+ getOpenIntents(userAddress: string, pagination?: PaginationParams): Promise<PaginatedResponse<UserIntent>>;
86
+ getIntentHistory(userAddress: string, pagination?: PaginationParams): Promise<PaginatedResponse<UserIntent>>;
87
+ private fetchWithTimeout;
88
+ private isValidAddress;
89
+ }
90
+ export declare function getSodaxApiClient(config?: SodaxApiConfig): SodaxApiClient;
91
+ export declare function resetSodaxApiClient(): void;
92
+ //# sourceMappingURL=sodaxApi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sodaxApi.d.ts","sourceRoot":"","sources":["../../src/utils/sodaxApi.ts"],"names":[],"mappings":"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"}