@1delta/margin-fetcher 0.0.28 → 0.0.30

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 (30) hide show
  1. package/dist/lending/user-data/aave-v2-type/userCallParse.d.ts.map +1 -1
  2. package/dist/lending/user-data/aave-v2-type/userCallParse.js +2 -3
  3. package/dist/lending/user-data/compound-v3/userCallParse.d.ts.map +1 -1
  4. package/dist/lending/user-data/compound-v3/userCallParse.js +1 -2
  5. package/dist/lending/user-data/fetchUserData.d.ts.map +1 -1
  6. package/dist/lending/user-data/morpho/userCallParse.d.ts.map +1 -1
  7. package/dist/lending/user-data/morpho/userCallParse.js +43 -34
  8. package/dist/prices/defillama/index.d.ts.map +1 -1
  9. package/dist/prices/defillama/index.js +28 -7
  10. package/dist/prices/main-prices/addresses/morpho.d.ts.map +1 -1
  11. package/dist/prices/main-prices/addresses/morpho.js +353 -325
  12. package/dist/prices/main-prices/fetchOracleData.js +4 -2
  13. package/dist/yields/index.d.ts.map +1 -1
  14. package/dist/yields/index.js +57 -8
  15. package/package.json +2 -2
  16. package/src/lending/user-data/aave-v2-type/userCallParse.ts +2 -3
  17. package/src/lending/user-data/compound-v3/userCallParse.ts +1 -2
  18. package/src/lending/user-data/fetchUserData.ts +1 -0
  19. package/src/lending/user-data/morpho/userCallParse.ts +65 -51
  20. package/src/prices/defillama/index.ts +29 -8
  21. package/src/prices/main-prices/addresses/morpho.ts +353 -325
  22. package/src/prices/main-prices/fetchOracleData.ts +5 -2
  23. package/src/yields/index.ts +67 -7
  24. package/test/mainPriceMB.test.ts +1 -2
  25. package/test/mainPrices.test.ts +1 -1
  26. package/test/morphoPrice.test.ts +1 -1
  27. package/test/userDataAll.test.ts +1 -4
  28. package/test/userDataMorpho.test.ts +1 -1
  29. package/test/userDataMorphoEthereum.test.ts +77 -0
  30. package/test/userDataMorphoKatana.test.ts +75 -0
@@ -439,11 +439,14 @@ const parseMorphoResults = (
439
439
 
440
440
  const oracleId =
441
441
  ASSET_META[chainId][loanAsset]?.assetGroup ?? chainId + '-' + loanAsset
442
- const debtPrice = donePrices[oracleId]
442
+ // get price from map or just computed ones
443
+ const debtPrice = donePrices[oracleId] ?? prices[oracleId]
443
444
  const oracleIdCollateral =
444
445
  ASSET_META[chainId][collateralAsset]?.assetGroup ??
445
446
  chainId + '-' + collateralAsset
446
- const collateralPrice = donePrices[oracleIdCollateral]
447
+ // get price from map or just computed ones
448
+ const collateralPrice =
449
+ donePrices[oracleIdCollateral] ?? prices[oracleIdCollateral]
447
450
  const priceDebtToCollateral = formatMorphoPrice(
448
451
  d.toString(),
449
452
  loanAssetDecimals,
@@ -10,8 +10,8 @@ const osETH = 'StakeWise Staked ETH::OSETH'
10
10
  // const ethPlus = 'ETHPlus::ETH+'
11
11
  const ethX = 'Stader ETHx::ETHx'
12
12
  const pufEth = 'PUFETH'
13
- const stUSD = 'Angle Staked USDA::STUSD'
14
- const stEur = 'Angle Staked EURA::STEUR'
13
+ const stUSD = 'Angle Staked USDA::stUSD'
14
+ const stEur = 'Angle Staked EURA::stEUR'
15
15
  const sUsds = 'sUSDS::SUSDS'
16
16
  const srUsd = 'Reservoir srUSD::SRUSD'
17
17
  const yusd = 'YieldFi yUSD::yUSD'
@@ -28,7 +28,9 @@ const rsweth = 'Restaked Swell ETH::RSWETH'
28
28
  const ynethx = 'ynETH MAX::YNETHX'
29
29
  const usdZeroPlus = 'Staked USD0::USD0++'
30
30
  const ethZero = 'ETH0::ETH0'
31
- const usdThree = "Web 3 Dollar::USD3"
31
+ const usdThree = 'Web 3 Dollar::USD3'
32
+ const jitoSol = 'Jito Staked SOL::JitoSOL'
33
+ const thBill = 'Theo Short Duration US Treasury Fund::THBILL'
32
34
  const FeedData = {
33
35
  WSTETH: 'https://eth-api.lido.fi/v1/protocol/steth/apr/sma',
34
36
  STMATIC: 'https://polygon.lido.fi/api/stats',
@@ -61,6 +63,8 @@ const FeedData = {
61
63
  YNETHX: 'https://gateway.yieldnest.finance/api/v1/graphql',
62
64
  USDZEROPLUS: 'https://app.usual.money/api/rewards/rates/USD0++',
63
65
  ETHZERO: 'https://app.usual.money/api/rewards/rates/ETH0',
66
+ JITOSOL: 'https://www.jito.network/api/getJitoPoolStats/',
67
+ THBILL: 'https://thbill-api.theo.xyz/snapshots',
64
68
  }
65
69
 
66
70
  const LenderAPIs = {
@@ -68,6 +72,15 @@ const LenderAPIs = {
68
72
  'https://omnidex.bmaa3ajd1gjri.eu-west-2.cs.amazonlightsail.com/lending_yields',
69
73
  }
70
74
 
75
+ function averageDataLastN<T extends { data: number }>(
76
+ arr: readonly T[],
77
+ n = 7,
78
+ ): number {
79
+ const last = arr.slice(-n)
80
+ if (last.length === 0) return 0
81
+ return last.reduce((sum, x) => sum + x.data, 0) / last.length
82
+ }
83
+
71
84
  enum MeridainNetwork {
72
85
  TAIKO = 'taiko',
73
86
  }
@@ -176,6 +189,31 @@ export const fetchGeneralYields = async () => {
176
189
  return apyToAprPercent(res.apy)
177
190
  })
178
191
 
192
+ const thbillPromise = safeFetch('THBILL', async () => {
193
+ const res = await fetch(FeedData.THBILL).then((r) => r.json())
194
+ // the entries are nested as
195
+ // "cash": {
196
+ // "USDC": 0.0
197
+ // },
198
+ // "money_market": {
199
+ // "ULTRA": 30364810.9557616
200
+ // },
201
+ // "pending": {
202
+ // "tULTRA": 16220629.251993446
203
+ // }
204
+ // },
205
+
206
+ // we read the keys and assign the approx rate of 4.5% to ULTRA
207
+ const entrs = Object.values(res.history[0]?.composition ?? {}).flatMap(
208
+ (a: any) => Object.entries(a),
209
+ )
210
+ const total = entrs.reduce((acc, b) => acc + Number(b[1]), 0)
211
+ const val = entrs
212
+ .filter((a) => a[0] === 'ULTRA')
213
+ .reduce((acc, b) => acc + Number(b[1]), 0)
214
+ return (val / total) * 4.5
215
+ })
216
+
179
217
  const ethxPromise = safeFetch('ETHX', async () => {
180
218
  const res = await fetch(FeedData.ETHX).then((r) => r.json())
181
219
  return apyToAprPercent(res.value)
@@ -233,6 +271,15 @@ export const fetchGeneralYields = async () => {
233
271
  return Number(res?.rewards[0]?.apr ?? 0) * 100
234
272
  })
235
273
 
274
+ const jitoSolPromise = safeFetch('JITOSOL', async () => {
275
+ const res = await fetch(FeedData.JITOSOL, {
276
+ method: 'GET',
277
+ headers: { Accept: 'application/json' },
278
+ }).then((r) => r.json())
279
+ const val = averageDataLastN(res?.getStakePoolStats?.apy, 7)
280
+ return apyToApr(val) * 100
281
+ })
282
+
236
283
  const ethZeroPromise = safeFetch('ETHZERO', async () => {
237
284
  const res = await fetch(FeedData.ETHZERO, {
238
285
  method: 'GET',
@@ -246,7 +293,7 @@ export const fetchGeneralYields = async () => {
246
293
  method: 'GET',
247
294
  headers: { Accept: 'application/json' },
248
295
  }).then((r) => r.json())
249
- return apyToAprPercent(Number(res?.[0]?.sky_savings_rate_apy ?? 0) * 100)
296
+ return apyToApr(Number(res?.[0]?.sky_savings_rate_apy ?? 0)) * 100
250
297
  })
251
298
 
252
299
  const srusdPromise = safeFetch('SRUSD', async () => {
@@ -268,7 +315,11 @@ export const fetchGeneralYields = async () => {
268
315
  const rlpPromise = safeFetch('RLP', async () => {
269
316
  const res = await fetch(FeedData.RLP, {
270
317
  method: 'GET',
271
- headers: { Accept: 'application/json' },
318
+ headers: {
319
+ Accept: 'application/json',
320
+
321
+ 'User-Agent': '1delta/yields',
322
+ },
272
323
  }).then((r) => r.json())
273
324
  return Number(res?.value ?? 0) * 100
274
325
  })
@@ -276,7 +327,10 @@ export const fetchGeneralYields = async () => {
276
327
  const wstusrPromise = safeFetch('WSTUSR', async () => {
277
328
  const res = await fetch(FeedData.WSTUSR, {
278
329
  method: 'GET',
279
- headers: { Accept: 'application/json' },
330
+ headers: {
331
+ Accept: 'application/json',
332
+ 'User-Agent': '1delta/yields',
333
+ },
280
334
  }).then((r) => r.json())
281
335
  return Number(res?.value ?? 0) * 100
282
336
  })
@@ -292,7 +346,7 @@ export const fetchGeneralYields = async () => {
292
346
  const rswethPromise = safeFetch('RSWETH', async () => {
293
347
  const res = await fetch(FeedData.RSWETH, {
294
348
  method: 'GET',
295
- headers: { Accept: 'application/json' },
349
+ headers: { Accept: 'application/json', 'User-Agent': '1delta/yields' },
296
350
  }).then((r) => r.text())
297
351
  return Number(res) ?? 0
298
352
  })
@@ -413,6 +467,8 @@ export const fetchGeneralYields = async () => {
413
467
  ynethxData,
414
468
  ethZeroData,
415
469
  usdZeroPlusData,
470
+ jitoSolData,
471
+ thBillData,
416
472
  ] = await Promise.all([
417
473
  wstethPromise,
418
474
  ezethPromise,
@@ -444,6 +500,8 @@ export const fetchGeneralYields = async () => {
444
500
  ynethxPromise,
445
501
  ethZeroPromise,
446
502
  usdZeroPlusPromise,
503
+ jitoSolPromise,
504
+ thbillPromise,
447
505
  ])
448
506
 
449
507
  const data: YieldDataWithTimestamp = {
@@ -477,6 +535,8 @@ export const fetchGeneralYields = async () => {
477
535
  [ynethx]: ynethxData,
478
536
  [tETH]: wstethData,
479
537
  [pufEth]: pufEthData,
538
+ [jitoSol]: jitoSolData,
539
+ [thBill]: thBillData,
480
540
  ...rtokensData,
481
541
  ...hypeData,
482
542
  ...angleData,
@@ -1,7 +1,6 @@
1
1
  import { describe, it } from 'vitest'
2
2
  import { Chain } from '@1delta/asset-registry'
3
3
  import { fetchMainPrices } from '../src'
4
- import { getEvmClient } from '@1delta/providers'
5
4
 
6
5
  const chainIds =
7
6
  // [ Chain.BASE]
@@ -23,7 +22,7 @@ describe(
23
22
  'find prices',
24
23
  () => {
25
24
  it('should return prices for valid tokens', async () => {
26
- const prices = await fetchMainPrices(chainIds, getEvmClient)
25
+ const prices = await fetchMainPrices(chainIds)
27
26
 
28
27
  prettyPrint(prices)
29
28
  })
@@ -1,7 +1,6 @@
1
1
  import { describe, it } from 'vitest'
2
2
  import { fetchMainPrices } from '../src'
3
3
  import { Chain } from '@1delta/asset-registry'
4
- import { getEvmClient } from '@1delta/providers'
5
4
  import { prettyPrint } from './utils'
6
5
 
7
6
  describe(
@@ -20,6 +19,7 @@ describe(
20
19
  Chain.ETHEREUM_MAINNET,
21
20
  ],
22
21
  )
22
+ console.log(mainPrices["SOL"])
23
23
  prettyPrint(mainPrices)
24
24
  })
25
25
  },
@@ -2,7 +2,7 @@ import { describe, it } from 'vitest'
2
2
  import { fetchMorphoPriceMeta } from './morpho'
3
3
  import { Chain } from '@1delta/asset-registry'
4
4
 
5
- const chainId = Chain.ETHEREUM_MAINNET
5
+ const chainId = Chain.BASE
6
6
  describe(
7
7
  'find prices',
8
8
  () => {
@@ -1,13 +1,10 @@
1
- import { describe, it, expect, beforeAll } from 'vitest'
1
+ import { describe, it, expect } from 'vitest'
2
2
  import {
3
3
  getLenderUserDataResult,
4
4
  convertLenderUserDataResult,
5
5
  } from '../src/lending/user-data/fetchUserData'
6
- import { fetchGeneralYields, fetchMainPrices } from '../src'
7
6
  import { getEvmClient } from '@1delta/providers'
8
7
  import { Chain, Lender } from '@1delta/asset-registry'
9
- import { LenderUserQuery } from '../src/lending/user-data/types'
10
- import { fetchMorphoPublicData } from '../src/lending/morpho/publicCallBuild'
11
8
  import { prettyPrint } from './utils'
12
9
  import { TestData } from './data'
13
10
  // random user with ETH
@@ -240,7 +240,7 @@ describe(
240
240
  () => {
241
241
  beforeAll(async () => {
242
242
  ;[prices, yields] = await Promise.all([
243
- fetchMainPrices([Chain.ETHEREUM_MAINNET], getEvmClient),
243
+ fetchMainPrices([Chain.ETHEREUM_MAINNET]),
244
244
  fetchGeneralYields(),
245
245
  ])
246
246
  }, 30000)
@@ -0,0 +1,77 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import {
3
+ getLenderUserDataResult,
4
+ convertLenderUserDataResult,
5
+ } from '../src/lending/user-data/fetchUserData'
6
+ import { getEvmClient } from '@1delta/providers'
7
+ import { Chain, Lender } from '@1delta/asset-registry'
8
+ import { LenderUserQuery } from '../src/lending/user-data/types'
9
+ import { prettyPrint } from './utils'
10
+
11
+ // random user with ETH
12
+ const TEST_ADDRESS = '0xbadA9c382165b31419F4CC0eDf0Fa84f80A3C8E5'
13
+ let prices
14
+
15
+ async function getUserData(chainId: Chain, publicData: any) {
16
+ // Define user queries
17
+ const queries: LenderUserQuery[] = Object.keys(publicData.data).map((m) => ({
18
+ lender: m,
19
+ account: TEST_ADDRESS.toLowerCase(),
20
+ // params: lenders,
21
+ }))
22
+
23
+ // console.log("queries", queries)
24
+
25
+ // Fetch raw user data
26
+ const rawUserData = await getLenderUserDataResult(
27
+ chainId,
28
+ queries,
29
+ getEvmClient,
30
+ )
31
+ // Convert raw data to structured format
32
+ const userData = convertLenderUserDataResult(
33
+ chainId,
34
+ queries,
35
+ rawUserData,
36
+ prices as any,
37
+ prices as any,
38
+ { [chainId]: publicData },
39
+ )
40
+
41
+ return { userData, rawUserData, publicData, queries }
42
+ }
43
+
44
+ describe(
45
+ 'user data fetching',
46
+ () => {
47
+ it(
48
+ 'should fetch user data for Morpho on KATANA',
49
+ async () => {
50
+ try {
51
+ const chainId = Chain.ETHEREUM_MAINNET
52
+ const all = await fetch(
53
+ `https://margin-data.1delta.io/lending-multi?chains=${chainId}`,
54
+ ).then((a) => a.json())
55
+ prices = all.prices
56
+
57
+ const publicData = all.data[chainId]
58
+ const { userData } = await getUserData(chainId, publicData)
59
+
60
+ prettyPrint(
61
+ userData[
62
+ 'MORPHO_BLUE_C4E18EB6D0E9B0FA90A15BC0A98190CBF3D5BA763AF410346F5174B014CEFD8D'
63
+ ],
64
+ )
65
+
66
+ // Basic validation
67
+ expect(userData).toBeDefined()
68
+ expect(typeof userData).toBe('object')
69
+ } catch (error) {
70
+ console.log('Error fetching Morpho KATANA data:', error)
71
+ }
72
+ },
73
+ { timeout: 30000 },
74
+ )
75
+ },
76
+ { timeout: 90000 },
77
+ )
@@ -0,0 +1,75 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import {
3
+ getLenderUserDataResult,
4
+ convertLenderUserDataResult,
5
+ } from '../src/lending/user-data/fetchUserData'
6
+ import { getEvmClient } from '@1delta/providers'
7
+ import { Chain, Lender } from '@1delta/asset-registry'
8
+ import { LenderUserQuery } from '../src/lending/user-data/types'
9
+ import { prettyPrint } from './utils'
10
+
11
+ // random user with ETH
12
+ const TEST_ADDRESS = '0xaffe73AA5EBd0CD95D89ab9fa2512Fc9e2d3289b'
13
+ let prices, yields
14
+
15
+ async function getUserData(chainId: Chain, publicData: any) {
16
+ // Define user queries
17
+ const queries: LenderUserQuery[] = Object.keys(publicData.data).map((m) => ({
18
+ lender: m,
19
+ account: TEST_ADDRESS.toLowerCase(),
20
+ // params: lenders,
21
+ }))
22
+
23
+ // Fetch raw user data
24
+ const rawUserData = await getLenderUserDataResult(
25
+ chainId,
26
+ queries,
27
+ getEvmClient,
28
+ )
29
+ // Convert raw data to structured format
30
+ const userData = convertLenderUserDataResult(
31
+ chainId,
32
+ queries,
33
+ rawUserData,
34
+ prices as any,
35
+ prices as any,
36
+ { [chainId]: publicData },
37
+ )
38
+
39
+ return { userData, rawUserData, publicData, queries }
40
+ }
41
+
42
+ describe(
43
+ 'user data fetching',
44
+ () => {
45
+ it(
46
+ 'should fetch user data for Morpho on KATANA',
47
+ async () => {
48
+ try {
49
+ const chainId = Chain.KATANA
50
+ const all = await fetch(
51
+ `https://margin-data.1delta.io/lending-multi?chains=${chainId}`,
52
+ ).then((a) => a.json())
53
+ prices = all.prices
54
+ yields = all.yields
55
+ const publicData = all.data[chainId]
56
+ const { userData } = await getUserData(chainId, publicData)
57
+
58
+ prettyPrint(
59
+ userData[
60
+ 'MORPHO_BLUE_16DED80178992B02F7C467C373CFC9F4EEE7F0356DF672F6A768EC92B2FFDEFF'
61
+ ],
62
+ )
63
+
64
+ // Basic validation
65
+ expect(userData).toBeDefined()
66
+ expect(typeof userData).toBe('object')
67
+ } catch (error) {
68
+ console.log('Error fetching Morpho KATANA data:', error)
69
+ }
70
+ },
71
+ { timeout: 30000 },
72
+ )
73
+ },
74
+ { timeout: 90000 },
75
+ )