@defisaver/positions-sdk 2.1.8 → 2.1.9-dev-spark-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2290,6 +2290,7 @@ const FluidMainnetFTokenAddresses = {
2290
2290
  [FluidMainnetDepositToken.wstETH]: '0x2411802D8BEA09be0aF8fD8D08314a63e706b29C',
2291
2291
  [FluidMainnetDepositToken.GHO]: '0x6A29A46E21C730DcA1d8b23d637c101cec605C5B',
2292
2292
  [FluidMainnetDepositToken.sUSDS]: '0x2BBE31d63E6813E3AC858C04dae43FB2a72B0D11',
2293
+ [FluidMainnetDepositToken.USDtb]: '0x15e8c742614b5D8Db4083A41Df1A14F5D2bFB400',
2293
2294
  };
2294
2295
  const FluidArbitrumFTokenAddresses = {
2295
2296
  [FluidArbitrumDepositToken.ETH]: '0x45Df0656F8aDf017590009d2f1898eeca4F0a205',
@@ -2297,6 +2298,8 @@ const FluidArbitrumFTokenAddresses = {
2297
2298
  [FluidArbitrumDepositToken.USDT]: '0x4A03F37e7d3fC243e3f99341d36f4b829BEe5E03',
2298
2299
  [FluidArbitrumDepositToken.wstETH]: '0x66C25Cd75EBdAA7E04816F643d8E46cecd3183c9',
2299
2300
  [FluidArbitrumDepositToken.ARB]: '0xbE3860FD4c3facDf8ad57Aa8c1A36D6dc4390a49',
2301
+ [FluidArbitrumDepositToken.GHO]: '0x037dFf1C12805707d7c29F163E0F09fC9102657A',
2302
+ [FluidArbitrumDepositToken.sUSDS]: '0x3459fcc94390C3372c0F7B4cD3F8795F0E5aFE96',
2300
2303
  };
2301
2304
  const FluidBaseFTokenAddresses = {
2302
2305
  [FluidBaseDepositToken.ETH]: '0x9272D6153133175175Bc276512B2336BE3931CE9',
@@ -2304,6 +2307,7 @@ const FluidBaseFTokenAddresses = {
2304
2307
  [FluidBaseDepositToken.EURC]: '0x1943FA26360f038230442525Cf1B9125b5DCB401',
2305
2308
  [FluidBaseDepositToken.wstETH]: '0x896E39f0E9af61ECA9dD2938E14543506ef2c2b5',
2306
2309
  [FluidBaseDepositToken.sUSDS]: '0xf62e339f21d8018940f188F6987Bcdf02A849619',
2310
+ [FluidBaseDepositToken.GHO]: '0x8DdbfFA3CFda2355a23d6B11105AC624BDbE3631',
2307
2311
  };
2308
2312
  export const FluidFTokens = (networkId) => {
2309
2313
  switch (networkId) {
@@ -446,7 +446,7 @@ export function getPortfolioData(provider, network, defaultProvider, addresses,
446
446
  }))).flat(),
447
447
  ...sparkMarkets.map((market) => allAddresses.map((address) => __awaiter(this, void 0, void 0, function* () {
448
448
  try {
449
- const accData = yield _getSparkAccountData(client, network, address, { selectedMarket: market, assetsData: sparkMarketsData[market.value].assetsData });
449
+ const accData = yield _getSparkAccountData(client, network, address, { selectedMarket: market, assetsData: sparkMarketsData[market.value].assetsData, eModeCategoriesData: sparkMarketsData[market.value].eModeCategoriesData });
450
450
  if (new Dec(accData.suppliedUsd).gt(0))
451
451
  positions[address.toLowerCase()].spark[market.value] = { error: '', data: accData };
452
452
  }
@@ -1,6 +1,6 @@
1
1
  import { Client } from 'viem';
2
2
  import { Blockish, EthAddress, EthereumProvider, NetworkNumber, PositionBalances } from '../types/common';
3
- import { SparkEModeCategoryDataMapping, SparkAssetsData, SparkMarketData, SparkMarketsData, SparkPositionData, SparkUsedAssets } from '../types';
3
+ import { SparkEModeCategoryDataMapping, SparkAssetsData, SparkMarketData, SparkMarketsData, SparkPositionData, SparkUsedAssets, EModeCategoriesData } from '../types';
4
4
  export declare const sparkEmodeCategoriesMapping: (extractedState: {
5
5
  assetsData: SparkAssetsData;
6
6
  }, usedAssets: SparkUsedAssets) => {
@@ -32,9 +32,11 @@ export declare const getSparkAccountBalances: (provider: EthereumProvider, netwo
32
32
  export declare const _getSparkAccountData: (provider: Client, network: NetworkNumber, address: EthAddress, extractedState: {
33
33
  selectedMarket: SparkMarketData;
34
34
  assetsData: SparkAssetsData;
35
+ eModeCategoriesData: EModeCategoriesData;
35
36
  }) => Promise<SparkPositionData>;
36
37
  export declare const getSparkAccountData: (provider: EthereumProvider, network: NetworkNumber, address: EthAddress, extractedState: {
37
38
  selectedMarket: SparkMarketData;
38
39
  assetsData: SparkAssetsData;
40
+ eModeCategoriesData: EModeCategoriesData;
39
41
  }) => Promise<SparkPositionData>;
40
42
  export declare const getSparkFullPositionData: (provider: EthereumProvider, network: NetworkNumber, address: EthAddress, market: SparkMarketData) => Promise<SparkPositionData>;
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import Dec from 'decimal.js';
11
11
  import { assetAmountInEth, assetAmountInWei, getAssetInfo } from '@defisaver/tokens';
12
- import { IncentiveKind, NetworkNumber, } from '../types/common';
12
+ import { IncentiveKind, } from '../types/common';
13
13
  import { ethToWeth, wethToEth, wethToEthByAddress, } from '../services/utils';
14
14
  import { calculateNetApy, getStakingApy, STAKING_ASSETS, } from '../staking';
15
15
  import { SparkViewContractViem, SparkIncentiveDataProviderContractViem, createViemContractFromConfigFunc, } from '../contracts';
@@ -49,18 +49,17 @@ export const _getSparkMarketsData = (provider, network, selectedMarket) => __awa
49
49
  const marketAddress = selectedMarket.providerAddress;
50
50
  const loanInfoContract = SparkViewContractViem(provider, network);
51
51
  const sparkIncentivesContract = SparkIncentiveDataProviderContractViem(provider, network);
52
- const [loanInfo, _rewardInfo] = yield Promise.all([
52
+ // eslint-disable-next-line prefer-const
53
+ let [loanInfo, rewardInfo] = yield Promise.all([
53
54
  loanInfoContract.read.getFullTokensInfo([marketAddress, selectedMarket.assets.map(a => getAssetInfo(ethToWeth(a)).address)]),
54
- network === NetworkNumber.Opt ? sparkIncentivesContract.read.getReservesIncentivesData([marketAddress]) : [],
55
+ sparkIncentivesContract.read.getReservesIncentivesData([marketAddress]),
55
56
  ]);
56
- let rewardInfo = [];
57
- if (network === NetworkNumber.Opt) {
58
- rewardInfo = rewardInfo.reduce((all, market) => {
59
- // eslint-disable-next-line no-param-reassign
60
- all[market.underlyingAsset] = market;
61
- return all;
62
- }, {});
63
- }
57
+ rewardInfo = rewardInfo.reduce((all, market) => {
58
+ // eslint-disable-next-line no-param-reassign
59
+ all[market.underlyingAsset] = market;
60
+ return all;
61
+ }, {});
62
+ const eModeCategoriesData = {};
64
63
  const assetsData = yield Promise.all(loanInfo
65
64
  .map((market, i) => __awaiter(void 0, void 0, void 0, function* () {
66
65
  const symbol = selectedMarket.assets[i];
@@ -75,6 +74,15 @@ export const _getSparkMarketsData = (provider, network, selectedMarket) => __awa
75
74
  if (new Dec(marketLiquidity).lt(0)) {
76
75
  marketLiquidity = '0';
77
76
  }
77
+ eModeCategoriesData[+market.emodeCategory.toString()] = {
78
+ id: +market.emodeCategory.toString(),
79
+ label: market.label,
80
+ liquidationBonus: new Dec(market.liquidationBonus).div(10000).toString(),
81
+ liquidationRatio: new Dec(market.liquidationThreshold).div(10000).toString(),
82
+ collateralFactor: new Dec(market.ltv).div(10000).toString(),
83
+ collateralAssets: eModeCategoriesData[+market.emodeCategory.toString()] ? [...eModeCategoriesData[+market.emodeCategory.toString()].collateralAssets, selectedMarket.assets[i]] : [selectedMarket.assets[i]],
84
+ borrowAssets: eModeCategoriesData[+market.emodeCategory.toString()] ? [...eModeCategoriesData[+market.emodeCategory.toString()].borrowAssets, selectedMarket.assets[i]] : [selectedMarket.assets[i]],
85
+ };
78
86
  return ({
79
87
  symbol: selectedMarket.assets[i],
80
88
  isIsolated: new Dec(market.debtCeilingForIsolationMode.toString()).gt(0),
@@ -147,7 +155,7 @@ export const _getSparkMarketsData = (provider, network, selectedMarket) => __awa
147
155
  return;
148
156
  rewardForMarket.aIncentiveData.rewardsTokenInformation.forEach(supplyRewardData => {
149
157
  if (supplyRewardData) {
150
- if (supplyRewardData.emissionEndTimestamp * 1000 < Date.now())
158
+ if (+(supplyRewardData.emissionEndTimestamp.toString()) * 1000 < Date.now())
151
159
  return;
152
160
  const supplyEmissionPerSecond = supplyRewardData.emissionPerSecond;
153
161
  const supplyRewardPrice = new Dec(supplyRewardData.rewardPriceFeed).div(Math.pow(10, supplyRewardData.priceFeedDecimals))
@@ -168,7 +176,7 @@ export const _getSparkMarketsData = (provider, network, selectedMarket) => __awa
168
176
  });
169
177
  rewardForMarket.vIncentiveData.rewardsTokenInformation.forEach(borrowRewardData => {
170
178
  if (borrowRewardData) {
171
- if (borrowRewardData.emissionEndTimestamp * 1000 < Date.now())
179
+ if (+(borrowRewardData.emissionEndTimestamp.toString()) * 1000 < Date.now())
172
180
  return;
173
181
  const supplyEmissionPerSecond = borrowRewardData.emissionPerSecond;
174
182
  const supplyRewardPrice = new Dec(borrowRewardData.rewardPriceFeed).div(Math.pow(10, borrowRewardData.priceFeedDecimals))
@@ -200,7 +208,9 @@ export const _getSparkMarketsData = (provider, network, selectedMarket) => __awa
200
208
  .forEach((assetData, i) => {
201
209
  payload[assetData.symbol] = Object.assign(Object.assign({}, assetData), { sortIndex: i });
202
210
  });
203
- return { assetsData: payload };
211
+ eModeCategoriesData[0].collateralAssets = Object.values(payload).map(a => a.symbol);
212
+ eModeCategoriesData[0].borrowAssets = Object.values(payload).map(a => a.symbol);
213
+ return { assetsData: payload, eModeCategoriesData };
204
214
  });
205
215
  export const getSparkMarketsData = (provider, network, selectedMarket) => __awaiter(void 0, void 0, void 0, function* () { return _getSparkMarketsData(getViemProvider(provider, network), network, selectedMarket); });
206
216
  export const EMPTY_SPARK_DATA = {
@@ -336,6 +346,6 @@ export const _getSparkAccountData = (provider, network, address, extractedState)
336
346
  export const getSparkAccountData = (provider, network, address, extractedState) => __awaiter(void 0, void 0, void 0, function* () { return _getSparkAccountData(getViemProvider(provider, network), network, address, extractedState); });
337
347
  export const getSparkFullPositionData = (provider, network, address, market) => __awaiter(void 0, void 0, void 0, function* () {
338
348
  const marketData = yield getSparkMarketsData(provider, network, market);
339
- const positionData = yield getSparkAccountData(provider, network, address, { assetsData: marketData.assetsData, selectedMarket: market });
349
+ const positionData = yield getSparkAccountData(provider, network, address, { assetsData: marketData.assetsData, selectedMarket: market, eModeCategoriesData: marketData.eModeCategoriesData });
340
350
  return positionData;
341
351
  });
@@ -149,21 +149,25 @@ export declare enum FluidMainnetDepositToken {
149
149
  USDC = "USDC",
150
150
  USDT = "USDT",
151
151
  GHO = "GHO",
152
- sUSDS = "sUSDS"
152
+ sUSDS = "sUSDS",
153
+ USDtb = "USDtb"
153
154
  }
154
155
  export declare enum FluidArbitrumDepositToken {
155
156
  ETH = "ETH",
156
157
  wstETH = "wstETH",
157
158
  USDC = "USDC",
158
159
  USDT = "USDT",
159
- ARB = "ARB"
160
+ ARB = "ARB",
161
+ GHO = "GHO",
162
+ sUSDS = "sUSDS"
160
163
  }
161
164
  export declare enum FluidBaseDepositToken {
162
165
  ETH = "ETH",
163
166
  USDC = "USDC",
164
167
  wstETH = "wstETH",
165
168
  EURC = "EURC",
166
- sUSDS = "sUSDS"
169
+ sUSDS = "sUSDS",
170
+ GHO = "GHO"
167
171
  }
168
172
  export type FluidDepositTokenByNetwork = {
169
173
  [NetworkNumber.Eth]: FluidMainnetDepositToken;
@@ -133,6 +133,7 @@ export var FluidMainnetDepositToken;
133
133
  FluidMainnetDepositToken["USDT"] = "USDT";
134
134
  FluidMainnetDepositToken["GHO"] = "GHO";
135
135
  FluidMainnetDepositToken["sUSDS"] = "sUSDS";
136
+ FluidMainnetDepositToken["USDtb"] = "USDtb";
136
137
  })(FluidMainnetDepositToken || (FluidMainnetDepositToken = {}));
137
138
  export var FluidArbitrumDepositToken;
138
139
  (function (FluidArbitrumDepositToken) {
@@ -141,6 +142,8 @@ export var FluidArbitrumDepositToken;
141
142
  FluidArbitrumDepositToken["USDC"] = "USDC";
142
143
  FluidArbitrumDepositToken["USDT"] = "USDT";
143
144
  FluidArbitrumDepositToken["ARB"] = "ARB";
145
+ FluidArbitrumDepositToken["GHO"] = "GHO";
146
+ FluidArbitrumDepositToken["sUSDS"] = "sUSDS";
144
147
  })(FluidArbitrumDepositToken || (FluidArbitrumDepositToken = {}));
145
148
  export var FluidBaseDepositToken;
146
149
  (function (FluidBaseDepositToken) {
@@ -149,6 +152,7 @@ export var FluidBaseDepositToken;
149
152
  FluidBaseDepositToken["wstETH"] = "wstETH";
150
153
  FluidBaseDepositToken["EURC"] = "EURC";
151
154
  FluidBaseDepositToken["sUSDS"] = "sUSDS";
155
+ FluidBaseDepositToken["GHO"] = "GHO";
152
156
  })(FluidBaseDepositToken || (FluidBaseDepositToken = {}));
153
157
  export var FluidVaultType;
154
158
  (function (FluidVaultType) {
@@ -1,3 +1,4 @@
1
+ import { EModeCategoriesData } from './aave';
1
2
  import { EthAddress, MMAssetData, MMPositionData, MMUsedAsset, NetworkNumber } from './common';
2
3
  export declare enum SparkVersions {
3
4
  SparkV1 = "v1default"
@@ -53,6 +54,7 @@ export interface SparkAssetsData {
53
54
  }
54
55
  export type SparkMarketsData = {
55
56
  assetsData: SparkAssetsData;
57
+ eModeCategoriesData: EModeCategoriesData;
56
58
  };
57
59
  export interface SparkUsedAsset extends MMUsedAsset {
58
60
  stableBorrowRate: string;
@@ -71,7 +73,7 @@ export interface SparkUsedAssets {
71
73
  export interface SparkHelperCommon {
72
74
  usedAssets: SparkUsedAssets;
73
75
  eModeCategory: number;
74
- eModeCategories?: object;
76
+ eModeCategoriesData?: EModeCategoriesData;
75
77
  assetsData: SparkAssetsData;
76
78
  selectedMarket?: SparkMarketData;
77
79
  network?: NetworkNumber;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defisaver/positions-sdk",
3
- "version": "2.1.8",
3
+ "version": "2.1.9-dev-spark-1",
4
4
  "description": "",
5
5
  "main": "./cjs/index.js",
6
6
  "module": "./esm/index.js",
@@ -12,7 +12,7 @@
12
12
  "dev": "tsc -p tsconfig.json --watch",
13
13
  "lint": "eslint src/ --fix",
14
14
  "lint-check": "eslint src/",
15
- "test": "mocha tests/*",
15
+ "test": "mocha tests/spark.ts",
16
16
  "test-single": "mocha ./tests/$npm_config_name.ts",
17
17
  "test:debugger": "mocha --inspect-brk tests/*",
18
18
  "version-bump": "git commit -am \"Version bump to $(npm version patch | cut -c 2-)\""
@@ -1458,21 +1458,20 @@ export const getFluidTokenData = async (
1458
1458
  token: string,
1459
1459
  ) => _getFluidTokenData(getViemProvider(provider, network), network, token);
1460
1460
 
1461
- const parseFDepositTokenData = (fTokenData: FluidFTokenDataStructOutput, userPosition: FluidUserEarnPositionStructOutput, fTokenAddress?: string) => {
1462
- const supplyRate = new Dec(fTokenData.supplyRate).div(100).toString();
1463
- const rewardsRate = new Dec(fTokenData.rewardsRate).div(1e12).toString();
1461
+ const parseFDepositTokenData = (fTokenData: FluidFTokenDataStructOutput, userPosition: FluidUserEarnPositionStructOutput, apiData: any, fTokenAddress?: string) => {
1464
1462
  const decimals = fTokenData.decimals.toString();
1465
-
1466
1463
  const depositRate = new Dec(getEthAmountForDecimals(fTokenData.convertToShares.toString(), decimals)).toString();
1467
1464
  const withdrawRate = new Dec(getEthAmountForDecimals(fTokenData.convertToAssets.toString(), decimals)).toString();
1468
-
1465
+ const supplyRate = new Dec(apiData?.supplyRate || '0').div(100).toString();
1466
+ const rewardRates = apiData?.rewards?.reduce((acc: Dec, item: any) => acc.add(new Dec(item.rate || '0').div(100)), new Dec(0)) || '0';
1467
+ const stakeRate = new Dec(apiData?.asset?.stakingApr || '0').div(100).toString();
1469
1468
  return {
1470
1469
  fTokenAddress,
1471
1470
  fTokenSymbol: fTokenData.symbol,
1472
1471
  decimals,
1473
1472
  totalDeposited: getEthAmountForDecimals(fTokenData.totalAssets.toString(), decimals),
1474
1473
  withdrawable: getEthAmountForDecimals(fTokenData.withdrawable.toString(), decimals),
1475
- apy: new Dec(supplyRate).add(rewardsRate).toString(),
1474
+ apy: new Dec(supplyRate).plus(rewardRates).plus(stakeRate).toString(),
1476
1475
  depositRate,
1477
1476
  withdrawRate,
1478
1477
  deposited: getEthAmountForDecimals(userPosition.underlyingAssets.toString(), decimals),
@@ -1483,9 +1482,21 @@ const parseFDepositTokenData = (fTokenData: FluidFTokenDataStructOutput, userPos
1483
1482
  export const _getFluidDepositData = async (provider: Client, network: NetworkNumber, token: string, address: EthAddress) => {
1484
1483
  const view = FluidViewContractViem(provider, network);
1485
1484
  const fTokenAddress = getFTokenAddress(token, network);
1486
- const [userPosition, fTokenData] = await view.read.getUserEarnPositionWithFToken([fTokenAddress, address]);
1485
+ const [
1486
+ [userPosition, fTokenData],
1487
+ rewardsApiResponse,
1488
+ ] = await Promise.all([
1489
+ view.read.getUserEarnPositionWithFToken([fTokenAddress, address]),
1490
+ fetch(`https://api.fluid.instadapp.io/v2/lending/${network}/tokens/${fTokenAddress}`),
1491
+ ]);
1492
+ let rewardsData = { rewards: [] };
1493
+ if (!rewardsApiResponse.ok) {
1494
+ console.log('External API Failure: Failed to fetch fluid rewards APY');
1495
+ } else {
1496
+ rewardsData = await rewardsApiResponse.json();
1497
+ }
1487
1498
 
1488
- return parseFDepositTokenData(fTokenData, userPosition, fTokenAddress);
1499
+ return parseFDepositTokenData(fTokenData, userPosition, rewardsData, fTokenAddress);
1489
1500
  };
1490
1501
 
1491
1502
  export const getFluidDepositData = async (
@@ -1497,7 +1508,22 @@ export const getFluidDepositData = async (
1497
1508
 
1498
1509
  export const _getAllUserEarnPositionsWithFTokens = async (provider: Client, network: NetworkNumber, user: EthAddress) => {
1499
1510
  const view = FluidViewContractViem(provider, network);
1500
- const [userPositions, fTokensData] = await view.read.getAllUserEarnPositionsWithFTokens([user]);
1511
+ const [
1512
+ [userPositions, fTokensData],
1513
+ rewardsApiResponse,
1514
+ ] = await Promise.all([
1515
+ view.read.getAllUserEarnPositionsWithFTokens([user]),
1516
+ fetch(`https://api.fluid.instadapp.io/v2/lending/${network}/tokens`),
1517
+ ]);
1518
+
1519
+ let rewardsData = {
1520
+ data: [{ address: ZERO_ADDRESS, rewards: [] }],
1521
+ };
1522
+ if (!rewardsApiResponse.ok) {
1523
+ console.log('External API Failure: Failed to fetch fluid rewards APY');
1524
+ } else {
1525
+ rewardsData = await rewardsApiResponse.json();
1526
+ }
1501
1527
 
1502
1528
  const parsedRes = fTokensData.reduce<ReturnType<typeof parseFDepositTokenData>[]>((acc, fTokenData, i) => {
1503
1529
  const userPosition = userPositions[i];
@@ -1505,7 +1531,8 @@ export const _getAllUserEarnPositionsWithFTokens = async (provider: Client, netw
1505
1531
 
1506
1532
  if (Number(deposited) > 0) {
1507
1533
  const fTokenAddress = fTokenData.tokenAddress;
1508
- acc.push(parseFDepositTokenData(fTokenData, userPosition, fTokenAddress));
1534
+ const apiData = rewardsData.data.find((item: any) => compareAddresses(item.address, fTokenAddress));
1535
+ acc.push(parseFDepositTokenData(fTokenData, userPosition, apiData, fTokenAddress));
1509
1536
  }
1510
1537
 
1511
1538
  return acc;
@@ -1572,19 +1599,22 @@ const tokensWithoutChainlinkPrices = ['sUSDS', 'USDA', 'ezETH', 'rsETH', 'weETHs
1572
1599
 
1573
1600
  const handleTokenWithoutChainlinkPrice = (token: string, prices: Record<string, string>) => {
1574
1601
  if (token === 'sUSDS') {
1575
- return new Dec('105276929').div(1e8).toString();
1602
+ return new Dec('107057929').div(1e8).toString();
1576
1603
  }
1577
1604
  if (token === 'USDA') {
1578
1605
  return new Dec('100000000').div(1e8).toString();
1579
1606
  }
1607
+ if (token === 'wstUSR') {
1608
+ return new Dec('111280000').div(1e8).toString();
1609
+ }
1580
1610
  if (token === 'ezETH') {
1581
- return new Dec(prices.ETH).mul(1.049).toString();
1611
+ return new Dec(prices.ETH).mul(1.06).toString();
1582
1612
  }
1583
1613
  if (token === 'rsETH') {
1584
- return new Dec(prices.wstETH).mul(1.0454).toString();
1614
+ return new Dec(prices.wstETH).mul(1.0557).toString();
1585
1615
  }
1586
1616
  if (token === 'weETHs') {
1587
- return new Dec(prices.wstETH).mul(1.026).toString();
1617
+ return new Dec(prices.wstETH).mul(1.032).toString();
1588
1618
  }
1589
1619
  if (token === 'LBTC') {
1590
1620
  return prices.WBTC;
@@ -8,7 +8,7 @@ import {
8
8
  SparkAssetsData, SparkHelperCommon, SparkMarketData, SparkUsedAssets,
9
9
  } from '../../types';
10
10
  import { calculateNetApy } from '../../staking';
11
- import { ethToWeth, wethToEth } from '../../services/utils';
11
+ import { ethToWeth, getNativeAssetFromWrapped, wethToEth } from '../../services/utils';
12
12
  import { SparkViewContractViem } from '../../contracts';
13
13
  import { EthAddress, EthereumProvider, NetworkNumber } from '../../types/common';
14
14
  import { borrowOperations } from '../../constants';
@@ -19,10 +19,10 @@ export const sparkIsInIsolationMode = ({ usedAssets, assetsData }: { usedAssets:
19
19
  export const sparkGetCollSuppliedAssets = ({ usedAssets }: { usedAssets: SparkUsedAssets }) => Object.values(usedAssets).filter(({ isSupplied, collateral }) => isSupplied && collateral);
20
20
 
21
21
  export const sparkGetSuppliableAssets = ({
22
- usedAssets, eModeCategory, eModeCategories, assetsData, selectedMarket, network, ...rest
22
+ usedAssets, eModeCategory, assetsData, selectedMarket, network, ...rest
23
23
  }: SparkHelperCommon) => {
24
24
  const data = {
25
- usedAssets, eModeCategory, eModeCategories, assetsData, selectedMarket, network, ...rest,
25
+ usedAssets, eModeCategory, assetsData, selectedMarket, network, ...rest,
26
26
  };
27
27
 
28
28
  const collAccountAssets = sparkGetCollSuppliedAssets(data);
@@ -37,41 +37,44 @@ export const sparkGetSuppliableAssets = ({
37
37
  };
38
38
 
39
39
  export const sparkGetSuppliableAsCollAssets = ({
40
- usedAssets, eModeCategory, eModeCategories, assetsData, selectedMarket, network, ...rest
40
+ usedAssets, eModeCategory, assetsData, selectedMarket, network, ...rest
41
41
  }: SparkHelperCommon) => sparkGetSuppliableAssets({
42
- usedAssets, eModeCategory, eModeCategories, assetsData, selectedMarket, network, ...rest,
42
+ usedAssets, eModeCategory, assetsData, selectedMarket, network, ...rest,
43
43
  }).filter(({ canBeCollateral }) => canBeCollateral);
44
44
 
45
45
  export const sparkGetEmodeMutableProps = ({
46
46
  eModeCategory,
47
+ eModeCategoriesData,
47
48
  assetsData,
48
49
  }: SparkHelperCommon, _asset: string) => {
49
- const asset = wethToEth(_asset);
50
+ const asset = getNativeAssetFromWrapped(_asset);
50
51
 
51
52
  const assetData = assetsData[asset];
53
+ const eModeCategoryData: { collateralAssets: string[], collateralFactor: string, liquidationRatio: string } = eModeCategoriesData?.[eModeCategory] || { collateralAssets: [], collateralFactor: '0', liquidationRatio: '0' };
54
+
52
55
  if (
53
56
  eModeCategory === 0
54
- || assetData.eModeCategory !== eModeCategory
55
- || new Dec(assetData?.eModeCategoryData?.collateralFactor || 0).eq(0)
57
+ || !eModeCategoryData.collateralAssets.includes(asset)
58
+ || new Dec(eModeCategoryData.collateralFactor || 0).eq(0)
56
59
  ) {
57
60
  const { liquidationRatio, collateralFactor } = assetData;
58
61
  return ({ liquidationRatio, collateralFactor });
59
62
  }
60
- const { liquidationRatio, collateralFactor } = assetData.eModeCategoryData;
63
+ const { liquidationRatio, collateralFactor } = eModeCategoryData;
61
64
  return ({ liquidationRatio, collateralFactor });
62
65
  };
63
66
 
64
67
  export const sparkGetAggregatedPositionData = ({
65
68
  usedAssets,
66
69
  eModeCategory,
67
- eModeCategories,
70
+ eModeCategoriesData,
68
71
  assetsData,
69
72
  selectedMarket,
70
73
  network,
71
74
  ...rest
72
75
  }: SparkHelperCommon): SparkAggregatedPositionData => {
73
76
  const data = {
74
- usedAssets, eModeCategory, eModeCategories, assetsData, selectedMarket, network, ...rest,
77
+ usedAssets, eModeCategory, eModeCategoriesData, assetsData, selectedMarket, network, ...rest,
75
78
  };
76
79
  const payload = {} as SparkAggregatedPositionData;
77
80
  payload.suppliedUsd = getAssetsTotal(usedAssets, ({ isSupplied }: { isSupplied: boolean }) => isSupplied, ({ suppliedUsd }: { suppliedUsd: string }) => suppliedUsd);
@@ -2421,6 +2421,7 @@ const FluidMainnetFTokenAddresses = {
2421
2421
  [FluidMainnetDepositToken.wstETH]: '0x2411802D8BEA09be0aF8fD8D08314a63e706b29C',
2422
2422
  [FluidMainnetDepositToken.GHO]: '0x6A29A46E21C730DcA1d8b23d637c101cec605C5B',
2423
2423
  [FluidMainnetDepositToken.sUSDS]: '0x2BBE31d63E6813E3AC858C04dae43FB2a72B0D11',
2424
+ [FluidMainnetDepositToken.USDtb]: '0x15e8c742614b5D8Db4083A41Df1A14F5D2bFB400',
2424
2425
  };
2425
2426
 
2426
2427
  const FluidArbitrumFTokenAddresses = {
@@ -2429,6 +2430,8 @@ const FluidArbitrumFTokenAddresses = {
2429
2430
  [FluidArbitrumDepositToken.USDT]: '0x4A03F37e7d3fC243e3f99341d36f4b829BEe5E03',
2430
2431
  [FluidArbitrumDepositToken.wstETH]: '0x66C25Cd75EBdAA7E04816F643d8E46cecd3183c9',
2431
2432
  [FluidArbitrumDepositToken.ARB]: '0xbE3860FD4c3facDf8ad57Aa8c1A36D6dc4390a49',
2433
+ [FluidArbitrumDepositToken.GHO]: '0x037dFf1C12805707d7c29F163E0F09fC9102657A',
2434
+ [FluidArbitrumDepositToken.sUSDS]: '0x3459fcc94390C3372c0F7B4cD3F8795F0E5aFE96',
2432
2435
  };
2433
2436
 
2434
2437
  const FluidBaseFTokenAddresses = {
@@ -2437,6 +2440,7 @@ const FluidBaseFTokenAddresses = {
2437
2440
  [FluidBaseDepositToken.EURC]: '0x1943FA26360f038230442525Cf1B9125b5DCB401',
2438
2441
  [FluidBaseDepositToken.wstETH]: '0x896E39f0E9af61ECA9dD2938E14543506ef2c2b5',
2439
2442
  [FluidBaseDepositToken.sUSDS]: '0xf62e339f21d8018940f188F6987Bcdf02A849619',
2443
+ [FluidBaseDepositToken.GHO]: '0x8DdbfFA3CFda2355a23d6B11105AC624BDbE3631',
2440
2444
  };
2441
2445
 
2442
2446
  export const FluidFTokens = (networkId: NetworkNumber) => {
@@ -456,7 +456,7 @@ export async function getPortfolioData(provider: EthereumProvider, network: Netw
456
456
  })).flat(),
457
457
  ...sparkMarkets.map((market) => allAddresses.map(async (address) => {
458
458
  try {
459
- const accData = await _getSparkAccountData(client, network, address, { selectedMarket: market, assetsData: sparkMarketsData[market.value].assetsData });
459
+ const accData = await _getSparkAccountData(client, network, address, { selectedMarket: market, assetsData: sparkMarketsData[market.value].assetsData, eModeCategoriesData: sparkMarketsData[market.value].eModeCategoriesData });
460
460
  if (new Dec(accData.suppliedUsd).gt(0)) positions[address.toLowerCase() as EthAddress].spark[market.value] = { error: '', data: accData };
461
461
  } catch (error) {
462
462
  console.error(`Error fetching Spark account data for address ${address} on market ${market.value}:`, error);
@@ -24,6 +24,7 @@ import {
24
24
  SparkPositionData,
25
25
  SparkUsedAsset,
26
26
  SparkUsedAssets,
27
+ EModeCategoriesData,
27
28
  } from '../types';
28
29
  import { sparkGetAggregatedPositionData, sparkIsInIsolationMode } from '../helpers/sparkHelpers';
29
30
  import { aprToApy, calculateBorrowingAssetLimit } from '../moneymarket';
@@ -68,19 +69,19 @@ export const _getSparkMarketsData = async (provider: Client, network: NetworkNum
68
69
  const loanInfoContract = SparkViewContractViem(provider, network);
69
70
  const sparkIncentivesContract = SparkIncentiveDataProviderContractViem(provider, network);
70
71
 
71
- const [loanInfo, _rewardInfo] = await Promise.all([
72
+ // eslint-disable-next-line prefer-const
73
+ let [loanInfo, rewardInfo] = await Promise.all([
72
74
  loanInfoContract.read.getFullTokensInfo([marketAddress, selectedMarket.assets.map(a => getAssetInfo(ethToWeth(a)).address) as EthAddress[]]),
73
- network === NetworkNumber.Opt ? sparkIncentivesContract.read.getReservesIncentivesData([marketAddress]) : [],
75
+ sparkIncentivesContract.read.getReservesIncentivesData([marketAddress]),
74
76
  ]);
75
77
 
76
- let rewardInfo: any[] = [];
77
- if (network === NetworkNumber.Opt) {
78
- rewardInfo = rewardInfo.reduce((all, market) => {
79
- // eslint-disable-next-line no-param-reassign
80
- all[market.underlyingAsset] = market;
81
- return all;
82
- }, {});
83
- }
78
+ rewardInfo = rewardInfo.reduce((all: any, market: any) => {
79
+ // eslint-disable-next-line no-param-reassign
80
+ all[market.underlyingAsset] = market;
81
+ return all;
82
+ }, {});
83
+
84
+ const eModeCategoriesData: EModeCategoriesData = {};
84
85
 
85
86
  const assetsData: SparkAssetData[] = await Promise.all(loanInfo
86
87
  .map(async (market, i) => {
@@ -98,6 +99,17 @@ export const _getSparkMarketsData = async (provider: Client, network: NetworkNum
98
99
  if (new Dec(marketLiquidity).lt(0)) {
99
100
  marketLiquidity = '0';
100
101
  }
102
+
103
+ eModeCategoriesData[+market.emodeCategory.toString()] = {
104
+ id: +market.emodeCategory.toString(),
105
+ label: market.label,
106
+ liquidationBonus: new Dec(market.liquidationBonus).div(10000).toString(),
107
+ liquidationRatio: new Dec(market.liquidationThreshold).div(10000).toString(),
108
+ collateralFactor: new Dec(market.ltv).div(10000).toString(),
109
+ collateralAssets: eModeCategoriesData[+market.emodeCategory.toString()] ? [...eModeCategoriesData[+market.emodeCategory.toString()].collateralAssets, selectedMarket.assets[i]] : [selectedMarket.assets[i]],
110
+ borrowAssets: eModeCategoriesData[+market.emodeCategory.toString()] ? [...eModeCategoriesData[+market.emodeCategory.toString()].borrowAssets, selectedMarket.assets[i]] : [selectedMarket.assets[i]],
111
+ };
112
+
101
113
  return ({
102
114
  symbol: selectedMarket.assets[i],
103
115
  isIsolated: new Dec(market.debtCeilingForIsolationMode.toString()).gt(0),
@@ -173,7 +185,7 @@ export const _getSparkMarketsData = async (provider: Client, network: NetworkNum
173
185
  if (!rewardForMarket) return;
174
186
  (rewardForMarket.aIncentiveData.rewardsTokenInformation as any[]).forEach(supplyRewardData => {
175
187
  if (supplyRewardData) {
176
- if (supplyRewardData.emissionEndTimestamp * 1000 < Date.now()) return;
188
+ if (+(supplyRewardData.emissionEndTimestamp.toString()) * 1000 < Date.now()) return;
177
189
  const supplyEmissionPerSecond = supplyRewardData.emissionPerSecond;
178
190
  const supplyRewardPrice = new Dec(supplyRewardData.rewardPriceFeed).div(10 ** supplyRewardData.priceFeedDecimals)
179
191
  .toString();
@@ -194,7 +206,7 @@ export const _getSparkMarketsData = async (provider: Client, network: NetworkNum
194
206
  });
195
207
  (rewardForMarket.vIncentiveData.rewardsTokenInformation as any[]).forEach(borrowRewardData => {
196
208
  if (borrowRewardData) {
197
- if (borrowRewardData.emissionEndTimestamp * 1000 < Date.now()) return;
209
+ if (+(borrowRewardData.emissionEndTimestamp.toString()) * 1000 < Date.now()) return;
198
210
  const supplyEmissionPerSecond = borrowRewardData.emissionPerSecond;
199
211
  const supplyRewardPrice = new Dec(borrowRewardData.rewardPriceFeed).div(10 ** borrowRewardData.priceFeedDecimals)
200
212
  .toString();
@@ -228,7 +240,10 @@ export const _getSparkMarketsData = async (provider: Client, network: NetworkNum
228
240
  payload[assetData.symbol] = { ...assetData, sortIndex: i };
229
241
  });
230
242
 
231
- return { assetsData: payload };
243
+ eModeCategoriesData[0].collateralAssets = Object.values(payload).map(a => a.symbol);
244
+ eModeCategoriesData[0].borrowAssets = Object.values(payload).map(a => a.symbol);
245
+
246
+ return { assetsData: payload, eModeCategoriesData };
232
247
  };
233
248
 
234
249
  export const getSparkMarketsData = async (
@@ -317,7 +332,12 @@ export const getSparkAccountBalances = async (
317
332
  address: EthAddress,
318
333
  ): Promise<PositionBalances> => _getSparkAccountBalances(getViemProvider(provider, network, { batch: { multicall: true } }), network, block, addressMapping, address);
319
334
 
320
- export const _getSparkAccountData = async (provider: Client, network: NetworkNumber, address: EthAddress, extractedState: { selectedMarket: SparkMarketData, assetsData: SparkAssetsData }) => {
335
+ export const _getSparkAccountData = async (
336
+ provider: Client,
337
+ network: NetworkNumber,
338
+ address: EthAddress,
339
+ extractedState: { selectedMarket: SparkMarketData, assetsData: SparkAssetsData, eModeCategoriesData: EModeCategoriesData },
340
+ ) => {
321
341
  const {
322
342
  selectedMarket: market, assetsData,
323
343
  } = extractedState;
@@ -435,11 +455,11 @@ export const getSparkAccountData = async (
435
455
  provider: EthereumProvider,
436
456
  network: NetworkNumber,
437
457
  address: EthAddress,
438
- extractedState: { selectedMarket: SparkMarketData, assetsData: SparkAssetsData },
458
+ extractedState: { selectedMarket: SparkMarketData, assetsData: SparkAssetsData, eModeCategoriesData: EModeCategoriesData },
439
459
  ) => _getSparkAccountData(getViemProvider(provider, network), network, address, extractedState);
440
460
 
441
461
  export const getSparkFullPositionData = async (provider: EthereumProvider, network: NetworkNumber, address: EthAddress, market: SparkMarketData): Promise<SparkPositionData> => {
442
462
  const marketData = await getSparkMarketsData(provider, network, market);
443
- const positionData = await getSparkAccountData(provider, network, address, { assetsData: marketData.assetsData, selectedMarket: market });
463
+ const positionData = await getSparkAccountData(provider, network, address, { assetsData: marketData.assetsData, selectedMarket: market, eModeCategoriesData: marketData.eModeCategoriesData });
444
464
  return positionData;
445
465
  };
@@ -157,6 +157,7 @@ export enum FluidMainnetDepositToken {
157
157
  USDT = 'USDT',
158
158
  GHO = 'GHO',
159
159
  sUSDS = 'sUSDS',
160
+ USDtb = 'USDtb',
160
161
  }
161
162
 
162
163
  export enum FluidArbitrumDepositToken {
@@ -165,6 +166,8 @@ export enum FluidArbitrumDepositToken {
165
166
  USDC = 'USDC',
166
167
  USDT = 'USDT',
167
168
  ARB = 'ARB',
169
+ GHO = 'GHO',
170
+ sUSDS = 'sUSDS',
168
171
  }
169
172
 
170
173
  export enum FluidBaseDepositToken {
@@ -173,6 +176,7 @@ export enum FluidBaseDepositToken {
173
176
  wstETH = 'wstETH',
174
177
  EURC = 'EURC',
175
178
  sUSDS = 'sUSDS',
179
+ GHO = 'GHO',
176
180
  }
177
181
 
178
182
  export type FluidDepositTokenByNetwork = {
@@ -1,3 +1,4 @@
1
+ import { EModeCategoriesData } from './aave';
1
2
  import {
2
3
  EthAddress,
3
4
  IncentiveData,
@@ -63,7 +64,7 @@ export interface SparkAssetsData {
63
64
  [token: string]: SparkAssetData,
64
65
  }
65
66
 
66
- export type SparkMarketsData = { assetsData: SparkAssetsData };
67
+ export type SparkMarketsData = { assetsData: SparkAssetsData, eModeCategoriesData: EModeCategoriesData };
67
68
 
68
69
  export interface SparkUsedAsset extends MMUsedAsset {
69
70
  stableBorrowRate: string,
@@ -84,7 +85,7 @@ export interface SparkUsedAssets {
84
85
  export interface SparkHelperCommon {
85
86
  usedAssets: SparkUsedAssets,
86
87
  eModeCategory: number,
87
- eModeCategories?: object,
88
+ eModeCategoriesData?: EModeCategoriesData,
88
89
  assetsData: SparkAssetsData,
89
90
  selectedMarket?: SparkMarketData,
90
91
  network?: NetworkNumber,