@defisaver/positions-sdk 2.1.169-custom-fetching-dev → 2.1.169-custom-fetching-3-dev

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 (145) hide show
  1. package/cjs/aaveV2/index.d.ts +4 -4
  2. package/cjs/aaveV2/index.js +7 -7
  3. package/cjs/aaveV3/index.d.ts +4 -3
  4. package/cjs/aaveV3/index.js +14 -10
  5. package/cjs/aaveV3/merkl.d.ts +5 -1
  6. package/cjs/aaveV3/merkl.js +8 -3
  7. package/cjs/aaveV4/index.d.ts +4 -3
  8. package/cjs/aaveV4/index.js +19 -16
  9. package/cjs/aaveV4/merkl.d.ts +10 -2
  10. package/cjs/aaveV4/merkl.js +15 -6
  11. package/cjs/claiming/aaveV3.d.ts +2 -2
  12. package/cjs/claiming/aaveV3.js +5 -4
  13. package/cjs/claiming/king.d.ts +2 -2
  14. package/cjs/claiming/king.js +3 -2
  15. package/cjs/claiming/spark.d.ts +3 -3
  16. package/cjs/claiming/spark.js +8 -7
  17. package/cjs/claiming/uniswap.d.ts +2 -2
  18. package/cjs/claiming/uniswap.js +3 -2
  19. package/cjs/compoundV2/index.d.ts +4 -4
  20. package/cjs/compoundV2/index.js +9 -9
  21. package/cjs/compoundV3/index.d.ts +5 -4
  22. package/cjs/compoundV3/index.js +17 -13
  23. package/cjs/compoundV3/merkl.d.ts +1 -1
  24. package/cjs/compoundV3/merkl.js +2 -5
  25. package/cjs/curveUsd/index.d.ts +5 -5
  26. package/cjs/curveUsd/index.js +17 -17
  27. package/cjs/fluid/index.d.ts +23 -22
  28. package/cjs/fluid/index.js +75 -72
  29. package/cjs/fluid/merkl.d.ts +5 -3
  30. package/cjs/fluid/merkl.js +11 -6
  31. package/cjs/liquity/index.d.ts +4 -4
  32. package/cjs/liquity/index.js +23 -23
  33. package/cjs/liquityV2/index.d.ts +10 -10
  34. package/cjs/liquityV2/index.js +59 -59
  35. package/cjs/llamaLend/index.d.ts +5 -5
  36. package/cjs/llamaLend/index.js +13 -13
  37. package/cjs/maker/index.d.ts +6 -6
  38. package/cjs/maker/index.js +16 -16
  39. package/cjs/morphoBlue/index.d.ts +7 -7
  40. package/cjs/morphoBlue/index.js +28 -26
  41. package/cjs/morphoBlue/merkl.d.ts +5 -3
  42. package/cjs/morphoBlue/merkl.js +6 -8
  43. package/cjs/morphoMidnight/index.d.ts +5 -5
  44. package/cjs/morphoMidnight/index.js +18 -18
  45. package/cjs/portfolio/customDeFiData.js +45 -40
  46. package/cjs/services/merkl.d.ts +36 -2
  47. package/cjs/services/merkl.js +142 -19
  48. package/cjs/services/priceService.d.ts +12 -12
  49. package/cjs/services/priceService.js +30 -29
  50. package/cjs/services/viem.d.ts +10 -2
  51. package/cjs/services/viem.js +27 -1
  52. package/cjs/spark/index.d.ts +4 -4
  53. package/cjs/spark/index.js +9 -9
  54. package/cjs/types/merkl.d.ts +18 -0
  55. package/cjs/types/portfolio.d.ts +2 -0
  56. package/cjs/umbrella/index.d.ts +2 -2
  57. package/cjs/umbrella/index.js +5 -4
  58. package/esm/aaveV2/index.d.ts +4 -4
  59. package/esm/aaveV2/index.js +8 -8
  60. package/esm/aaveV3/index.d.ts +4 -3
  61. package/esm/aaveV3/index.js +15 -11
  62. package/esm/aaveV3/merkl.d.ts +5 -1
  63. package/esm/aaveV3/merkl.js +9 -4
  64. package/esm/aaveV4/index.d.ts +4 -3
  65. package/esm/aaveV4/index.js +20 -17
  66. package/esm/aaveV4/merkl.d.ts +10 -2
  67. package/esm/aaveV4/merkl.js +16 -7
  68. package/esm/claiming/aaveV3.d.ts +2 -2
  69. package/esm/claiming/aaveV3.js +5 -4
  70. package/esm/claiming/king.d.ts +2 -2
  71. package/esm/claiming/king.js +3 -2
  72. package/esm/claiming/spark.d.ts +3 -3
  73. package/esm/claiming/spark.js +8 -7
  74. package/esm/claiming/uniswap.d.ts +2 -2
  75. package/esm/claiming/uniswap.js +3 -2
  76. package/esm/compoundV2/index.d.ts +4 -4
  77. package/esm/compoundV2/index.js +9 -9
  78. package/esm/compoundV3/index.d.ts +5 -4
  79. package/esm/compoundV3/index.js +19 -15
  80. package/esm/compoundV3/merkl.d.ts +1 -1
  81. package/esm/compoundV3/merkl.js +3 -6
  82. package/esm/curveUsd/index.d.ts +5 -5
  83. package/esm/curveUsd/index.js +17 -17
  84. package/esm/fluid/index.d.ts +23 -22
  85. package/esm/fluid/index.js +76 -73
  86. package/esm/fluid/merkl.d.ts +5 -3
  87. package/esm/fluid/merkl.js +12 -7
  88. package/esm/liquity/index.d.ts +4 -4
  89. package/esm/liquity/index.js +23 -23
  90. package/esm/liquityV2/index.d.ts +10 -10
  91. package/esm/liquityV2/index.js +60 -60
  92. package/esm/llamaLend/index.d.ts +5 -5
  93. package/esm/llamaLend/index.js +13 -13
  94. package/esm/maker/index.d.ts +6 -6
  95. package/esm/maker/index.js +16 -16
  96. package/esm/morphoBlue/index.d.ts +7 -7
  97. package/esm/morphoBlue/index.js +29 -27
  98. package/esm/morphoBlue/merkl.d.ts +5 -3
  99. package/esm/morphoBlue/merkl.js +7 -9
  100. package/esm/morphoMidnight/index.d.ts +5 -5
  101. package/esm/morphoMidnight/index.js +18 -18
  102. package/esm/portfolio/customDeFiData.js +47 -42
  103. package/esm/services/merkl.d.ts +36 -2
  104. package/esm/services/merkl.js +136 -18
  105. package/esm/services/priceService.d.ts +12 -12
  106. package/esm/services/priceService.js +31 -30
  107. package/esm/services/viem.d.ts +10 -2
  108. package/esm/services/viem.js +25 -0
  109. package/esm/spark/index.d.ts +4 -4
  110. package/esm/spark/index.js +10 -10
  111. package/esm/types/merkl.d.ts +18 -0
  112. package/esm/types/portfolio.d.ts +2 -0
  113. package/esm/umbrella/index.d.ts +2 -2
  114. package/esm/umbrella/index.js +5 -4
  115. package/package.json +1 -1
  116. package/src/aaveV2/index.ts +7 -7
  117. package/src/aaveV3/index.ts +15 -11
  118. package/src/aaveV3/merkl.ts +9 -4
  119. package/src/aaveV4/index.ts +19 -16
  120. package/src/aaveV4/merkl.ts +16 -7
  121. package/src/claiming/aaveV3.ts +5 -3
  122. package/src/claiming/king.ts +6 -3
  123. package/src/claiming/spark.ts +9 -6
  124. package/src/claiming/uniswap.ts +4 -3
  125. package/src/compoundV2/index.ts +10 -9
  126. package/src/compoundV3/index.ts +20 -14
  127. package/src/compoundV3/merkl.ts +5 -4
  128. package/src/curveUsd/index.ts +19 -17
  129. package/src/fluid/index.ts +88 -70
  130. package/src/fluid/merkl.ts +12 -7
  131. package/src/liquity/index.ts +23 -23
  132. package/src/liquityV2/index.ts +64 -56
  133. package/src/llamaLend/index.ts +15 -13
  134. package/src/maker/index.ts +19 -16
  135. package/src/morphoBlue/index.ts +23 -20
  136. package/src/morphoBlue/merkl.ts +9 -6
  137. package/src/morphoMidnight/index.ts +13 -13
  138. package/src/portfolio/customDeFiData.ts +48 -41
  139. package/src/services/merkl.ts +152 -19
  140. package/src/services/priceService.ts +33 -30
  141. package/src/services/viem.ts +16 -0
  142. package/src/spark/index.ts +11 -8
  143. package/src/types/merkl.ts +20 -0
  144. package/src/types/portfolio.ts +2 -0
  145. package/src/umbrella/index.ts +6 -5
@@ -7,29 +7,147 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
+ import { OpportunityStatus, } from '../types';
10
11
  import { LONGER_TIMEOUT } from './utils';
11
- const MERKL_OPPORTUNITIES_URL = 'https://fe.defisaver.com/api/merkl/opportunities';
12
+ const MERKL_API_URL = 'https://fe.defisaver.com/api/merkl';
13
+ const MERKL_OPPORTUNITIES_URL = `${MERKL_API_URL}/opportunities`;
14
+ const MERKL_CAMPAIGNS_URL = `${MERKL_API_URL}/campaigns`;
15
+ // Merkl caps list pages at 100 items; opportunity ids are batched below that so a single page
16
+ // covers every id in the batch.
17
+ const MERKL_MAX_PAGE_ITEMS = 100;
18
+ const OPPORTUNITY_ID_BATCH_SIZE = 50;
19
+ // APR history is fetched per opportunity, so historical lookups are throttled to keep a block with
20
+ // many live campaigns from firing every request at once.
21
+ const APR_RECORDS_CONCURRENCY = 10;
22
+ const SECONDS_PER_DAY = 24 * 60 * 60;
23
+ const merklGet = (url, query, label) => __awaiter(void 0, void 0, void 0, function* () {
24
+ const res = yield fetch(`${url}?${new URLSearchParams(query)}`, { signal: AbortSignal.timeout(LONGER_TIMEOUT) });
25
+ if (!res.ok)
26
+ throw new Error(`Failed to fetch Merkl ${label}`);
27
+ return res.json();
28
+ });
12
29
  /**
13
- * Fetches every page matching the query. Merkl returns 20 opportunities by default, so omitting
14
- * `items` and advancing `page` avoids imposing a client-side maximum on the result set.
30
+ * Fetches every page matching the query, advancing `page` until an empty page comes back. When
31
+ * `items` is omitted, Merkl's default page size applies and no client-side maximum is imposed.
15
32
  */
16
- export const fetchAllMerklOpportunities = (query) => __awaiter(void 0, void 0, void 0, function* () {
17
- const opportunities = [];
33
+ const fetchAllMerklPages = (url, query, label, items) => __awaiter(void 0, void 0, void 0, function* () {
34
+ const results = [];
18
35
  let page = 0;
19
- let pageOpportunities;
36
+ let pageResults;
20
37
  do {
21
- const searchParams = new URLSearchParams(Object.assign(Object.assign({}, query), { page: page.toString() }));
22
- const res = yield fetch(`${MERKL_OPPORTUNITIES_URL}?${searchParams}`, {
23
- signal: AbortSignal.timeout(LONGER_TIMEOUT),
24
- });
25
- if (!res.ok)
26
- throw new Error(`Failed to fetch Merkl opportunities page ${page}`);
27
- const data = yield res.json(); // eslint-disable-line no-await-in-loop
38
+ const pageQuery = Object.assign(Object.assign(Object.assign({}, query), { page: page.toString() }), (items ? { items: items.toString() } : {}));
39
+ const data = yield merklGet(url, pageQuery, `${label} page ${page}`); // eslint-disable-line no-await-in-loop
28
40
  if (!Array.isArray(data))
29
- throw new Error(`Invalid Merkl opportunities response on page ${page}`);
30
- pageOpportunities = data;
31
- opportunities.push(...pageOpportunities);
41
+ throw new Error(`Invalid Merkl ${label} response on page ${page}`);
42
+ pageResults = data;
43
+ results.push(...pageResults);
32
44
  page += 1;
33
- } while (pageOpportunities.length > 0);
34
- return opportunities;
45
+ } while (pageResults.length > 0);
46
+ return results;
47
+ });
48
+ /**
49
+ * Fetches every opportunity matching the query. Merkl returns 20 opportunities by default, so omitting
50
+ * `items` and advancing `page` avoids imposing a client-side maximum on the result set.
51
+ */
52
+ export const fetchAllMerklOpportunities = (query) => __awaiter(void 0, void 0, void 0, function* () {
53
+ return (fetchAllMerklPages(MERKL_OPPORTUNITIES_URL, query, 'opportunities'));
54
+ });
55
+ /** Fetches every campaign matching the query, e.g. `{ mainProtocolId: 'aave', status: 'LIVE,PAST' }`. */
56
+ export const fetchAllMerklCampaigns = (query) => __awaiter(void 0, void 0, void 0, function* () {
57
+ return (fetchAllMerklPages(MERKL_CAMPAIGNS_URL, query, 'campaigns', MERKL_MAX_PAGE_ITEMS));
58
+ });
59
+ /**
60
+ * Fetches the opportunities with the given Merkl-internal ids, regardless of their current status.
61
+ * Ids Merkl no longer serves (hidden or test campaigns) are simply absent from the result.
62
+ */
63
+ export const fetchMerklOpportunitiesByIds = (ids) => __awaiter(void 0, void 0, void 0, function* () {
64
+ const batches = [];
65
+ for (let i = 0; i < ids.length; i += OPPORTUNITY_ID_BATCH_SIZE)
66
+ batches.push(ids.slice(i, i + OPPORTUNITY_ID_BATCH_SIZE));
67
+ const results = yield Promise.all(batches.map((batch) => merklGet(MERKL_OPPORTUNITIES_URL, { id: batch.join(','), items: MERKL_MAX_PAGE_ITEMS.toString() }, 'opportunities by id')));
68
+ return results.flatMap((data) => {
69
+ if (!Array.isArray(data))
70
+ throw new Error('Invalid Merkl opportunities by id response');
71
+ return data;
72
+ });
73
+ });
74
+ /**
75
+ * Returns the reward APR Merkl recorded for the opportunity at the given unix timestamp (seconds),
76
+ * or `undefined` when no campaign was computing for it then. Records are hourly buckets keyed by
77
+ * their start, newest first, so the first bucket at or before the timestamp carries the value in
78
+ * force at that moment; the window is a day wide to tolerate computation gaps.
79
+ */
80
+ export const fetchMerklOpportunityAprAt = (opportunityId, timestamp) => __awaiter(void 0, void 0, void 0, function* () {
81
+ var _a;
82
+ const records = yield merklGet(`${MERKL_OPPORTUNITIES_URL}/${opportunityId}/apr-records`, {
83
+ grain: 'HOUR',
84
+ from: (timestamp - SECONDS_PER_DAY).toString(),
85
+ to: timestamp.toString(),
86
+ items: '1',
87
+ }, `APR records for opportunity ${opportunityId}`);
88
+ if (!Array.isArray(records))
89
+ throw new Error(`Invalid Merkl APR records response for opportunity ${opportunityId}`);
90
+ return (_a = records[0]) === null || _a === void 0 ? void 0 : _a.apr;
91
+ });
92
+ const mapWithConcurrency = (items, concurrency, fn) => __awaiter(void 0, void 0, void 0, function* () {
93
+ const results = [];
94
+ for (let i = 0; i < items.length; i += concurrency) {
95
+ results.push(...yield Promise.all(items.slice(i, i + concurrency).map(fn))); // eslint-disable-line no-await-in-loop
96
+ }
97
+ return results;
98
+ });
99
+ /**
100
+ * Reconstructs the opportunities that were live at `timestamp` (unix seconds), shaped like the
101
+ * live listing so the per-protocol reward mappers can consume either without knowing which they got:
102
+ * 1. campaigns for the protocol (and chain, when the query names one) whose [start, end] covers
103
+ * the timestamp identify the opportunities that were rewarded then — the live listing can't,
104
+ * since campaigns live then are mostly PAST now and ones live now didn't exist then;
105
+ * 2. those opportunities are loaded by id (works for PAST ones too) and narrowed to `query.type`;
106
+ * 3. each one's `apr` is replaced with the value Merkl recorded at the timestamp, and ones with no
107
+ * record then are dropped, since nothing was being computed for them.
108
+ * `status` is forced to LIVE so status filters downstream keep working, `campaigns` carries the
109
+ * covering campaigns, and a reward token breakdown is synthesized from the campaign's reward token
110
+ * when Merkl no longer serves one for the opportunity (it drops them once an opportunity is PAST).
111
+ * `query.status` is ignored: it describes the present, not the requested moment.
112
+ */
113
+ export const fetchMerklOpportunitiesAt = (query, timestamp) => __awaiter(void 0, void 0, void 0, function* () {
114
+ var _a;
115
+ const campaignQuery = { status: 'LIVE,PAST', endTimestamp: timestamp.toString() };
116
+ if (query.mainProtocolId)
117
+ campaignQuery.mainProtocolId = query.mainProtocolId;
118
+ if (query.chainId)
119
+ campaignQuery.chainId = query.chainId;
120
+ // `endTimestamp` only narrows the listing upstream — the exact window check happens here
121
+ const campaigns = (yield fetchAllMerklCampaigns(campaignQuery))
122
+ .filter((c) => { var _a, _b; return c.opportunityId && +((_a = c.startTimestamp) !== null && _a !== void 0 ? _a : 0) <= timestamp && timestamp <= +((_b = c.endTimestamp) !== null && _b !== void 0 ? _b : 0); });
123
+ const campaignsByOpportunity = {};
124
+ campaigns.forEach((c) => {
125
+ if (!campaignsByOpportunity[c.opportunityId])
126
+ campaignsByOpportunity[c.opportunityId] = [];
127
+ campaignsByOpportunity[c.opportunityId].push(c);
128
+ });
129
+ const opportunityIds = Object.keys(campaignsByOpportunity);
130
+ if (!opportunityIds.length)
131
+ return [];
132
+ const types = (_a = query.type) === null || _a === void 0 ? void 0 : _a.split(',').filter(Boolean);
133
+ const opportunities = (yield fetchMerklOpportunitiesByIds(opportunityIds))
134
+ .filter((o) => !(types === null || types === void 0 ? void 0 : types.length) || types.includes(o.type));
135
+ const aprs = yield mapWithConcurrency(opportunities, APR_RECORDS_CONCURRENCY, (o) => fetchMerklOpportunityAprAt(o.id, timestamp));
136
+ return opportunities.flatMap((o, i) => {
137
+ var _a, _b, _c;
138
+ const apr = aprs[i];
139
+ if (apr === undefined)
140
+ return [];
141
+ const coveringCampaigns = campaignsByOpportunity[o.id];
142
+ const rewardToken = (_a = coveringCampaigns.find((c) => c.rewardToken)) === null || _a === void 0 ? void 0 : _a.rewardToken;
143
+ const hasBreakdown = !!((_c = (_b = o.rewardsRecord) === null || _b === void 0 ? void 0 : _b.breakdowns) === null || _c === void 0 ? void 0 : _c.length);
144
+ return [Object.assign(Object.assign({}, o), { status: OpportunityStatus.LIVE, apr, campaigns: coveringCampaigns, rewardsRecord: hasBreakdown || !rewardToken ? o.rewardsRecord : Object.assign(Object.assign({}, o.rewardsRecord), { breakdowns: [{ token: rewardToken, campaignId: coveringCampaigns[0].campaignId }] }) })];
145
+ });
146
+ });
147
+ /**
148
+ * Live opportunities when no timestamp is given, otherwise the opportunities as they were at that
149
+ * unix timestamp (seconds) — see `fetchMerklOpportunitiesAt`.
150
+ */
151
+ export const fetchMerklOpportunities = (query, asOfTimestamp) => __awaiter(void 0, void 0, void 0, function* () {
152
+ return (asOfTimestamp === undefined ? fetchAllMerklOpportunities(query) : fetchMerklOpportunitiesAt(query, asOfTimestamp));
35
153
  });
@@ -1,14 +1,14 @@
1
1
  import Dec from 'decimal.js';
2
2
  import { Client, PublicClient } from 'viem';
3
- import { EthAddress, NetworkNumber } from '../types/common';
4
- export declare const getEthPrice: (client: Client) => Promise<string>;
5
- export declare const getUSDCPrice: (client: Client) => Promise<string>;
6
- export declare const getCompPrice: (client: Client) => Promise<string>;
7
- export declare const getWstETHPrice: (client: Client, network?: NetworkNumber) => Promise<string>;
8
- export declare const getWeETHPrice: (client: Client, network?: NetworkNumber) => Promise<string>;
9
- export declare const getWsrETHPrice: (client: Client, network?: NetworkNumber) => Promise<string>;
10
- export declare const getSyrupUSDTPrice: (client: Client, network?: NetworkNumber) => Promise<string>;
11
- export declare const getWstUSRPrice: (client: Client, network?: NetworkNumber) => Promise<string>;
3
+ import { Blockish, EthAddress, NetworkNumber } from '../types/common';
4
+ export declare const getEthPrice: (client: Client, block?: Blockish) => Promise<string>;
5
+ export declare const getUSDCPrice: (client: Client, block?: Blockish) => Promise<string>;
6
+ export declare const getCompPrice: (client: Client, block?: Blockish) => Promise<string>;
7
+ export declare const getWstETHPrice: (client: Client, network?: NetworkNumber, block?: Blockish) => Promise<string>;
8
+ export declare const getWeETHPrice: (client: Client, network?: NetworkNumber, block?: Blockish) => Promise<string>;
9
+ export declare const getWsrETHPrice: (client: Client, network?: NetworkNumber, block?: Blockish) => Promise<string>;
10
+ export declare const getSyrupUSDTPrice: (client: Client, network?: NetworkNumber, block?: Blockish) => Promise<string>;
11
+ export declare const getWstUSRPrice: (client: Client, network?: NetworkNumber, block?: Blockish) => Promise<string>;
12
12
  export declare const getWstETHChainLinkPriceCalls: (client: PublicClient, network: NetworkNumber) => ({
13
13
  address: `0x${string}`;
14
14
  abi: readonly [{
@@ -1821,7 +1821,7 @@ export declare const parseWeETHPriceCalls: (_ethPrice: string, weETHrateAnswer:
1821
1821
  ethPrice: Dec;
1822
1822
  weETHRate: string;
1823
1823
  };
1824
- export declare const getWstETHPriceFluid: (client: PublicClient, network: NetworkNumber) => Promise<string>;
1825
- export declare const getBTCPriceForFluid: (client: PublicClient, network: NetworkNumber) => Promise<string>;
1826
- export declare const getEthPriceForFluid: (client: PublicClient, network: NetworkNumber) => Promise<string>;
1824
+ export declare const getWstETHPriceFluid: (client: PublicClient, network: NetworkNumber, block?: Blockish) => Promise<string>;
1825
+ export declare const getBTCPriceForFluid: (client: PublicClient, network: NetworkNumber, block?: Blockish) => Promise<string>;
1826
+ export declare const getEthPriceForFluid: (client: PublicClient, network: NetworkNumber, block?: Blockish) => Promise<string>;
1827
1827
  export declare const getChainlinkAssetAddress: (symbol: string, network: NetworkNumber) => EthAddress;
@@ -10,73 +10,74 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  import Dec from 'decimal.js';
11
11
  import { getAssetInfo } from '@defisaver/tokens';
12
12
  import { BTCPriceFeedContractViem, COMPPriceFeedContractViem, DFSFeedRegistryContractViem, ETHPriceFeedContractViem, USDCPriceFeedContractViem, WeETHPriceFeedContractViem, WstETHPriceFeedContractViem, } from '../contracts';
13
- import { NetworkNumber } from '../types/common';
13
+ import { NetworkNumber, } from '../types/common';
14
14
  import { getEthAmountForDecimals } from './utils';
15
+ import { setViemBlockNumber } from './viem';
15
16
  import { USD_QUOTE } from '../constants';
16
- export const getEthPrice = (client) => __awaiter(void 0, void 0, void 0, function* () {
17
+ export const getEthPrice = (client_1, ...args_1) => __awaiter(void 0, [client_1, ...args_1], void 0, function* (client, block = 'latest') {
17
18
  const contract = ETHPriceFeedContractViem(client, NetworkNumber.Eth);
18
- const price = yield contract.read.latestAnswer();
19
+ const price = yield contract.read.latestAnswer(setViemBlockNumber(block));
19
20
  return new Dec(price.toString()).div(1e8).toString();
20
21
  });
21
- export const getUSDCPrice = (client) => __awaiter(void 0, void 0, void 0, function* () {
22
+ export const getUSDCPrice = (client_1, ...args_1) => __awaiter(void 0, [client_1, ...args_1], void 0, function* (client, block = 'latest') {
22
23
  const contract = USDCPriceFeedContractViem(client, NetworkNumber.Eth);
23
- const price = yield contract.read.latestAnswer();
24
+ const price = yield contract.read.latestAnswer(setViemBlockNumber(block));
24
25
  return new Dec(price.toString()).div(1e8).toString();
25
26
  });
26
- export const getCompPrice = (client) => __awaiter(void 0, void 0, void 0, function* () {
27
+ export const getCompPrice = (client_1, ...args_1) => __awaiter(void 0, [client_1, ...args_1], void 0, function* (client, block = 'latest') {
27
28
  const contract = COMPPriceFeedContractViem(client, NetworkNumber.Eth);
28
- const price = yield contract.read.latestAnswer();
29
+ const price = yield contract.read.latestAnswer(setViemBlockNumber(block));
29
30
  return new Dec(price.toString()).div(1e8).toString();
30
31
  });
31
- export const getWstETHPrice = (client_1, ...args_1) => __awaiter(void 0, [client_1, ...args_1], void 0, function* (client, network = NetworkNumber.Eth) {
32
+ export const getWstETHPrice = (client_1, ...args_1) => __awaiter(void 0, [client_1, ...args_1], void 0, function* (client, network = NetworkNumber.Eth, block = 'latest') {
32
33
  const wstETHFeedContract = WstETHPriceFeedContractViem(client, network);
33
34
  const ethFeedContract = ETHPriceFeedContractViem(client, network);
34
35
  const [ethPriceWei, wstETHRateWei, decimals] = yield Promise.all([
35
- ethFeedContract.read.latestAnswer(),
36
- wstETHFeedContract.read.latestRoundData(),
37
- wstETHFeedContract.read.decimals(),
36
+ ethFeedContract.read.latestAnswer(setViemBlockNumber(block)),
37
+ wstETHFeedContract.read.latestRoundData(setViemBlockNumber(block)),
38
+ wstETHFeedContract.read.decimals(setViemBlockNumber(block)),
38
39
  ]);
39
40
  const ethPrice = new Dec(ethPriceWei.toString()).div(1e8);
40
41
  const wstETHRate = getEthAmountForDecimals(wstETHRateWei[1].toString(), decimals);
41
42
  return new Dec(ethPrice).mul(wstETHRate).toString();
42
43
  });
43
- export const getWeETHPrice = (client_1, ...args_1) => __awaiter(void 0, [client_1, ...args_1], void 0, function* (client, network = NetworkNumber.Eth) {
44
+ export const getWeETHPrice = (client_1, ...args_1) => __awaiter(void 0, [client_1, ...args_1], void 0, function* (client, network = NetworkNumber.Eth, block = 'latest') {
44
45
  const weETHFeedContract = WeETHPriceFeedContractViem(client, network);
45
46
  const ethFeedContract = ETHPriceFeedContractViem(client, network);
46
47
  const [ethPriceWei, weETHRateWei, decimals] = yield Promise.all([
47
- ethFeedContract.read.latestAnswer(),
48
- weETHFeedContract.read.latestRoundData(),
49
- weETHFeedContract.read.decimals(),
48
+ ethFeedContract.read.latestAnswer(setViemBlockNumber(block)),
49
+ weETHFeedContract.read.latestRoundData(setViemBlockNumber(block)),
50
+ weETHFeedContract.read.decimals(setViemBlockNumber(block)),
50
51
  ]);
51
52
  const ethPrice = new Dec(ethPriceWei.toString()).div(1e8);
52
53
  const weETHRate = getEthAmountForDecimals(weETHRateWei[1].toString(), decimals);
53
54
  return new Dec(ethPrice).mul(weETHRate).toString();
54
55
  });
55
- export const getWsrETHPrice = (client_1, ...args_1) => __awaiter(void 0, [client_1, ...args_1], void 0, function* (client, network = NetworkNumber.Eth) {
56
+ export const getWsrETHPrice = (client_1, ...args_1) => __awaiter(void 0, [client_1, ...args_1], void 0, function* (client, network = NetworkNumber.Eth, block = 'latest') {
56
57
  const feedRegistryContract = DFSFeedRegistryContractViem(client, network);
57
58
  const [ethPriceWei, wrsETHRateWei] = yield Promise.all([
58
- feedRegistryContract.read.latestRoundData([getAssetInfo('WETH', network).address, USD_QUOTE]),
59
- feedRegistryContract.read.latestRoundData([getAssetInfo('wrsETH', network).address, getAssetInfo('WETH', network).address]),
59
+ feedRegistryContract.read.latestRoundData([getAssetInfo('WETH', network).address, USD_QUOTE], setViemBlockNumber(block)),
60
+ feedRegistryContract.read.latestRoundData([getAssetInfo('wrsETH', network).address, getAssetInfo('WETH', network).address], setViemBlockNumber(block)),
60
61
  ]);
61
62
  const ethPrice = new Dec(ethPriceWei[1].toString()).div(1e8);
62
63
  const wrsETHRate = getEthAmountForDecimals(wrsETHRateWei[1].toString(), 18);
63
64
  return new Dec(ethPrice).mul(wrsETHRate).toString();
64
65
  });
65
- export const getSyrupUSDTPrice = (client_1, ...args_1) => __awaiter(void 0, [client_1, ...args_1], void 0, function* (client, network = NetworkNumber.Eth) {
66
+ export const getSyrupUSDTPrice = (client_1, ...args_1) => __awaiter(void 0, [client_1, ...args_1], void 0, function* (client, network = NetworkNumber.Eth, block = 'latest') {
66
67
  const feedRegistryContract = DFSFeedRegistryContractViem(client, network);
67
68
  const [usdtPriceWei, syrupUSDTRateWei] = yield Promise.all([
68
- feedRegistryContract.read.latestRoundData([getAssetInfo('USDT', network).address, USD_QUOTE]),
69
- feedRegistryContract.read.latestRoundData([getAssetInfo('syrupUSDT', network).address, getAssetInfo('USDT', network).address]),
69
+ feedRegistryContract.read.latestRoundData([getAssetInfo('USDT', network).address, USD_QUOTE], setViemBlockNumber(block)),
70
+ feedRegistryContract.read.latestRoundData([getAssetInfo('syrupUSDT', network).address, getAssetInfo('USDT', network).address], setViemBlockNumber(block)),
70
71
  ]);
71
72
  const usdtPrice = new Dec(usdtPriceWei[1].toString()).div(1e8);
72
73
  const syrupUSDTPrice = getEthAmountForDecimals(syrupUSDTRateWei[1].toString(), 18);
73
74
  return new Dec(usdtPrice).mul(syrupUSDTPrice).toString();
74
75
  });
75
- export const getWstUSRPrice = (client_1, ...args_1) => __awaiter(void 0, [client_1, ...args_1], void 0, function* (client, network = NetworkNumber.Eth) {
76
+ export const getWstUSRPrice = (client_1, ...args_1) => __awaiter(void 0, [client_1, ...args_1], void 0, function* (client, network = NetworkNumber.Eth, block = 'latest') {
76
77
  const feedRegistryContract = DFSFeedRegistryContractViem(client, network);
77
78
  const [usrPriceWei, wstUSRRateWei] = yield Promise.all([
78
- feedRegistryContract.read.latestRoundData([getAssetInfo('USR', network).address, USD_QUOTE]),
79
- feedRegistryContract.read.latestRoundData([getAssetInfo('wstUSR', network).address, getAssetInfo('USR', network).address]),
79
+ feedRegistryContract.read.latestRoundData([getAssetInfo('USR', network).address, USD_QUOTE], setViemBlockNumber(block)),
80
+ feedRegistryContract.read.latestRoundData([getAssetInfo('wstUSR', network).address, getAssetInfo('USR', network).address], setViemBlockNumber(block)),
80
81
  ]);
81
82
  const usrPrice = new Dec(usrPriceWei[1].toString()).div(1e8);
82
83
  const wstUSRPrice = getEthAmountForDecimals(wstUSRRateWei[1].toString(), 18);
@@ -212,21 +213,21 @@ export const parseWeETHPriceCalls = (_ethPrice, weETHrateAnswer, decimals) => {
212
213
  return { ethPrice, weETHRate };
213
214
  };
214
215
  // this is a fixed version, the original version is above but requires to refactor comp v3 function, so it's easier to just copy the function for now
215
- export const getWstETHPriceFluid = (client, network) => __awaiter(void 0, void 0, void 0, function* () {
216
+ export const getWstETHPriceFluid = (client_1, network_1, ...args_1) => __awaiter(void 0, [client_1, network_1, ...args_1], void 0, function* (client, network, block = 'latest') {
216
217
  const calls = getWstETHChainLinkPriceCalls(client, network);
217
- const results = yield client.multicall({ contracts: calls });
218
+ const results = yield client.multicall(Object.assign({ contracts: calls }, setViemBlockNumber(block)));
218
219
  // @ts-ignore
219
220
  const { ethPrice, wstETHRate } = parseWstETHPriceCalls(results[0].result.toString(), results[1].result[1].toString(), results[2].result.toString());
220
221
  return new Dec(ethPrice).mul(wstETHRate).toString();
221
222
  });
222
- export const getBTCPriceForFluid = (client, network) => __awaiter(void 0, void 0, void 0, function* () {
223
+ export const getBTCPriceForFluid = (client_1, network_1, ...args_1) => __awaiter(void 0, [client_1, network_1, ...args_1], void 0, function* (client, network, block = 'latest') {
223
224
  const contract = BTCPriceFeedContractViem(client, network);
224
- const price = yield contract.read.latestAnswer();
225
+ const price = yield contract.read.latestAnswer(setViemBlockNumber(block));
225
226
  return new Dec(price).div(1e8).toString();
226
227
  });
227
- export const getEthPriceForFluid = (client, network) => __awaiter(void 0, void 0, void 0, function* () {
228
+ export const getEthPriceForFluid = (client_1, network_1, ...args_1) => __awaiter(void 0, [client_1, network_1, ...args_1], void 0, function* (client, network, block = 'latest') {
228
229
  const contract = ETHPriceFeedContractViem(client, network);
229
- const price = yield contract.read.latestAnswer();
230
+ const price = yield contract.read.latestAnswer(setViemBlockNumber(block));
230
231
  return new Dec(price).div(1e8).toString();
231
232
  });
232
233
  // chainlink price feed available only on mainnet
@@ -1,4 +1,4 @@
1
- import { type Abi } from 'viem';
1
+ import { type Abi, type Client } from 'viem';
2
2
  import { Blockish, EthereumProvider, NetworkNumber } from '../types/common';
3
3
  export declare const getViemChain: (network: NetworkNumber) => {
4
4
  blockExplorers: {
@@ -4391,8 +4391,16 @@ export declare const getViemProvider: (provider: EthereumProvider, network: Netw
4391
4391
  transport?: undefined;
4392
4392
  type?: undefined;
4393
4393
  uid?: undefined;
4394
- } & import("viem").ExactPartial<Pick<import("viem").PublicActions<import("viem").Transport, undefined, undefined>, "getBlockNumber" | "call" | "createContractEventFilter" | "createEventFilter" | "estimateContractGas" | "estimateGas" | "getBlock" | "getChainId" | "getContractEvents" | "getEnsText" | "getFilterChanges" | "getGasPrice" | "getLogs" | "getTransaction" | "getTransactionCount" | "getTransactionReceipt" | "prepareTransactionRequest" | "readContract" | "sendRawTransaction" | "simulateContract" | "uninstallFilter" | "watchBlockNumber" | "watchContractEvent"> & Pick<import("viem").WalletActions<undefined, undefined>, "sendTransaction" | "writeContract">>>(fn: (client: import("viem").Client<import("viem").Transport, undefined, undefined, import("viem").PublicRpcSchema, import("viem").PublicActions<import("viem").Transport, undefined>>) => client) => import("viem").Client<import("viem").Transport, undefined, undefined, import("viem").PublicRpcSchema, { [K in keyof client]: client[K]; } & import("viem").PublicActions<import("viem").Transport, undefined>>;
4394
+ } & import("viem").ExactPartial<Pick<import("viem").PublicActions<import("viem").Transport, undefined, undefined>, "getBlockNumber" | "call" | "createContractEventFilter" | "createEventFilter" | "estimateContractGas" | "estimateGas" | "getBlock" | "getChainId" | "getContractEvents" | "getEnsText" | "getFilterChanges" | "getGasPrice" | "getLogs" | "getTransaction" | "getTransactionCount" | "getTransactionReceipt" | "prepareTransactionRequest" | "readContract" | "sendRawTransaction" | "simulateContract" | "uninstallFilter" | "watchBlockNumber" | "watchContractEvent"> & Pick<import("viem").WalletActions<undefined, undefined>, "sendTransaction" | "writeContract">>>(fn: (client: Client<import("viem").Transport, undefined, undefined, import("viem").PublicRpcSchema, import("viem").PublicActions<import("viem").Transport, undefined>>) => client) => Client<import("viem").Transport, undefined, undefined, import("viem").PublicRpcSchema, { [K in keyof client]: client[K]; } & import("viem").PublicActions<import("viem").Transport, undefined>>;
4395
4395
  };
4396
+ /**
4397
+ * Unix timestamp (seconds) of the block, for data sources keyed by time rather than block (Merkl
4398
+ * reward history). `'latest'` resolves to `undefined` without an RPC call, since live sources need
4399
+ * no timestamp. A numeric block costs one `eth_getBlockByNumber` unless the caller already knows
4400
+ * its timestamp and passes it — flows that fetch many markets at one block resolve it once and
4401
+ * hand it down.
4402
+ */
4403
+ export declare const getBlockTimestamp: (client: Client, block: Blockish, blockTimestamp?: number) => Promise<number | undefined>;
4396
4404
  export declare const setViemBlockNumber: (block: Blockish) => {
4397
4405
  blockNumber?: undefined;
4398
4406
  } | {
@@ -1,4 +1,14 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
1
10
  import { createPublicClient, custom, encodeFunctionData, } from 'viem';
11
+ import { getBlock } from 'viem/actions';
2
12
  import { arbitrum, base, mainnet, optimism, linea, plasma, } from 'viem/chains';
3
13
  import { NetworkNumber } from '../types/common';
4
14
  export const getViemChain = (network) => {
@@ -20,6 +30,21 @@ export const getViemChain = (network) => {
20
30
  }
21
31
  };
22
32
  export const getViemProvider = (provider, network, options) => createPublicClient(Object.assign({ transport: custom(provider), chain: getViemChain(network) }, options));
33
+ /**
34
+ * Unix timestamp (seconds) of the block, for data sources keyed by time rather than block (Merkl
35
+ * reward history). `'latest'` resolves to `undefined` without an RPC call, since live sources need
36
+ * no timestamp. A numeric block costs one `eth_getBlockByNumber` unless the caller already knows
37
+ * its timestamp and passes it — flows that fetch many markets at one block resolve it once and
38
+ * hand it down.
39
+ */
40
+ export const getBlockTimestamp = (client, block, blockTimestamp) => __awaiter(void 0, void 0, void 0, function* () {
41
+ if (block === 'latest')
42
+ return undefined;
43
+ if (blockTimestamp !== undefined)
44
+ return blockTimestamp;
45
+ const { timestamp } = yield getBlock(client, { blockNumber: BigInt(block) });
46
+ return Number(timestamp);
47
+ });
23
48
  export const setViemBlockNumber = (block) => {
24
49
  if (block === 'latest')
25
50
  return {};
@@ -6,8 +6,8 @@ export declare const sparkEmodeCategoriesMapping: (extractedState: {
6
6
  }, usedAssets: SparkUsedAssets) => {
7
7
  [key: number]: SparkEModeCategoryDataMapping;
8
8
  };
9
- export declare const _getSparkMarketsData: (provider: Client, network: NetworkNumber, selectedMarket: SparkMarketData) => Promise<SparkMarketsData>;
10
- export declare const getSparkMarketsData: (provider: EthereumProvider, network: NetworkNumber, selectedMarket: SparkMarketData) => Promise<SparkMarketsData>;
9
+ export declare const _getSparkMarketsData: (provider: Client, network: NetworkNumber, selectedMarket: SparkMarketData, blockNumber?: Blockish) => Promise<SparkMarketsData>;
10
+ export declare const getSparkMarketsData: (provider: EthereumProvider, network: NetworkNumber, selectedMarket: SparkMarketData, blockNumber?: Blockish) => Promise<SparkMarketsData>;
11
11
  export declare const EMPTY_SPARK_DATA: {
12
12
  usedAssets: {};
13
13
  suppliedUsd: string;
@@ -34,10 +34,10 @@ export declare const _getSparkAccountData: (provider: Client, network: NetworkNu
34
34
  selectedMarket: SparkMarketData;
35
35
  assetsData: SparkAssetsData;
36
36
  eModeCategoriesData: EModeCategoriesData;
37
- }) => Promise<SparkPositionData>;
37
+ }, blockNumber?: Blockish) => Promise<SparkPositionData>;
38
38
  export declare const getSparkAccountData: (provider: EthereumProvider, network: NetworkNumber, address: EthAddress, extractedState: {
39
39
  selectedMarket: SparkMarketData;
40
40
  assetsData: SparkAssetsData;
41
41
  eModeCategoriesData: EModeCategoriesData;
42
- }) => Promise<SparkPositionData>;
42
+ }, blockNumber?: Blockish) => Promise<SparkPositionData>;
43
43
  export declare const getSparkFullPositionData: (provider: EthereumProvider, network: NetworkNumber, address: EthAddress, market: SparkMarketData) => Promise<SparkPositionData>;
@@ -17,7 +17,7 @@ import { SparkViewContractViem, SparkIncentiveDataProviderContractViem, createVi
17
17
  import { sparkGetAggregatedPositionData, sparkIsInIsolationMode } from '../helpers/sparkHelpers';
18
18
  import { aprToApy, calculateBorrowingAssetLimit } from '../moneymarket';
19
19
  import { SPARK_V1 } from '../markets/spark';
20
- import { getViemProvider } from '../services/viem';
20
+ import { getViemProvider, setViemBlockNumber } from '../services/viem';
21
21
  export const sparkEmodeCategoriesMapping = (extractedState, usedAssets) => {
22
22
  const { assetsData } = extractedState;
23
23
  const usedAssetsValues = Object.values(usedAssets);
@@ -43,14 +43,14 @@ export const sparkEmodeCategoriesMapping = (extractedState, usedAssets) => {
43
43
  });
44
44
  return categoriesMapping;
45
45
  };
46
- export const _getSparkMarketsData = (provider, network, selectedMarket) => __awaiter(void 0, void 0, void 0, function* () {
46
+ export const _getSparkMarketsData = (provider_1, network_1, selectedMarket_1, ...args_1) => __awaiter(void 0, [provider_1, network_1, selectedMarket_1, ...args_1], void 0, function* (provider, network, selectedMarket, blockNumber = 'latest') {
47
47
  const marketAddress = selectedMarket.providerAddress;
48
48
  const loanInfoContract = SparkViewContractViem(provider, network);
49
49
  const sparkIncentivesContract = SparkIncentiveDataProviderContractViem(provider, network);
50
50
  // eslint-disable-next-line prefer-const
51
51
  let [loanInfo, rewardInfo] = yield Promise.all([
52
- loanInfoContract.read.getFullTokensInfo([marketAddress, selectedMarket.assets.map(a => getAssetInfo(ethToWeth(a)).address)]),
53
- sparkIncentivesContract.read.getReservesIncentivesData([marketAddress]),
52
+ loanInfoContract.read.getFullTokensInfo([marketAddress, selectedMarket.assets.map(a => getAssetInfo(ethToWeth(a)).address)], setViemBlockNumber(blockNumber)),
53
+ sparkIncentivesContract.read.getReservesIncentivesData([marketAddress], setViemBlockNumber(blockNumber)),
54
54
  ]);
55
55
  rewardInfo = rewardInfo.reduce((all, market) => {
56
56
  // eslint-disable-next-line no-param-reassign
@@ -207,7 +207,7 @@ export const _getSparkMarketsData = (provider, network, selectedMarket) => __awa
207
207
  eModeCategoriesData[0].borrowAssets = Object.values(filteredAssetsData).map(a => a.symbol);
208
208
  return { assetsData: filteredAssetsData, eModeCategoriesData };
209
209
  });
210
- export const getSparkMarketsData = (provider, network, selectedMarket) => __awaiter(void 0, void 0, void 0, function* () { return _getSparkMarketsData(getViemProvider(provider, network), network, selectedMarket); });
210
+ export const getSparkMarketsData = (provider_1, network_1, selectedMarket_1, ...args_1) => __awaiter(void 0, [provider_1, network_1, selectedMarket_1, ...args_1], void 0, function* (provider, network, selectedMarket, blockNumber = 'latest') { return _getSparkMarketsData(getViemProvider(provider, network), network, selectedMarket, blockNumber); });
211
211
  export const EMPTY_SPARK_DATA = {
212
212
  usedAssets: {},
213
213
  suppliedUsd: '0',
@@ -233,7 +233,7 @@ export const _getSparkAccountBalances = (provider, network, block, addressMappin
233
233
  return balances;
234
234
  });
235
235
  export const getSparkAccountBalances = (provider, network, block, addressMapping, address) => __awaiter(void 0, void 0, void 0, function* () { return _getSparkAccountBalances(getViemProvider(provider, network, { batch: { multicall: true } }), network, block, addressMapping, address); });
236
- export const _getSparkAccountData = (provider, network, address, extractedState) => __awaiter(void 0, void 0, void 0, function* () {
236
+ export const _getSparkAccountData = (provider_1, network_1, address_1, extractedState_1, ...args_1) => __awaiter(void 0, [provider_1, network_1, address_1, extractedState_1, ...args_1], void 0, function* (provider, network, address, extractedState, blockNumber = 'latest') {
237
237
  const { selectedMarket: market, assetsData, } = extractedState;
238
238
  let payload = Object.assign(Object.assign({}, EMPTY_SPARK_DATA), { lastUpdated: Date.now() });
239
239
  if (!address) {
@@ -249,9 +249,9 @@ export const _getSparkAccountData = (provider, network, address, extractedState)
249
249
  const _addresses = market.assets.map((a) => getAssetInfo(ethToWeth(a)).address);
250
250
  const middleAddressIndex = Math.floor(_addresses.length / 2); // split addresses in half to avoid gas limit by multicall
251
251
  const [userEMode, tokenBalances1, tokenBalances2] = yield Promise.all([
252
- lendingPoolContract.read.getUserEMode([address]),
253
- loanInfoContract.read.getTokenBalances([marketAddress, address, _addresses.slice(0, middleAddressIndex)]),
254
- loanInfoContract.read.getTokenBalances([marketAddress, address, _addresses.slice(middleAddressIndex, _addresses.length)]),
252
+ lendingPoolContract.read.getUserEMode([address], setViemBlockNumber(blockNumber)),
253
+ loanInfoContract.read.getTokenBalances([marketAddress, address, _addresses.slice(0, middleAddressIndex)], setViemBlockNumber(blockNumber)),
254
+ loanInfoContract.read.getTokenBalances([marketAddress, address, _addresses.slice(middleAddressIndex, _addresses.length)], setViemBlockNumber(blockNumber)),
255
255
  ]);
256
256
  const loanInfo = [...tokenBalances1, ...tokenBalances2];
257
257
  const usedAssets = {};
@@ -309,7 +309,7 @@ export const _getSparkAccountData = (provider, network, address, extractedState)
309
309
  payload.totalInterestUsd = totalInterestUsd;
310
310
  return payload;
311
311
  });
312
- export const getSparkAccountData = (provider, network, address, extractedState) => __awaiter(void 0, void 0, void 0, function* () { return _getSparkAccountData(getViemProvider(provider, network), network, address, extractedState); });
312
+ export const getSparkAccountData = (provider_1, network_1, address_1, extractedState_1, ...args_1) => __awaiter(void 0, [provider_1, network_1, address_1, extractedState_1, ...args_1], void 0, function* (provider, network, address, extractedState, blockNumber = 'latest') { return _getSparkAccountData(getViemProvider(provider, network), network, address, extractedState, blockNumber); });
313
313
  export const getSparkFullPositionData = (provider, network, address, market) => __awaiter(void 0, void 0, void 0, function* () {
314
314
  const marketData = yield getSparkMarketsData(provider, network, market);
315
315
  const positionData = yield getSparkAccountData(provider, network, address, { assetsData: marketData.assetsData, selectedMarket: market, eModeCategoriesData: marketData.eModeCategoriesData });
@@ -126,6 +126,24 @@ export type MerklOpportunity = {
126
126
  }[];
127
127
  };
128
128
  };
129
+ /** One entry of Merkl's campaign listing: a campaign plus the opportunity it rewards. */
130
+ export type MerklCampaignListItem = MerklCampaign & {
131
+ opportunityId: string;
132
+ type: string;
133
+ rewardToken?: MerklOpportunity['rewardsRecord']['breakdowns'][number]['token'];
134
+ };
135
+ /** One bucket of an opportunity's APR history (`apr` is the last value recorded in the bucket). */
136
+ export type MerklAprRecord = {
137
+ timestamp: string;
138
+ date: string;
139
+ apr: number;
140
+ open: number;
141
+ min: number;
142
+ max: number;
143
+ avg: number;
144
+ samples: number;
145
+ hasUntrustedContribution: boolean;
146
+ };
129
147
  export type MerkleRewardInfo = {
130
148
  apy: string;
131
149
  rewardTokenSymbol: string;
@@ -87,6 +87,8 @@ export interface CustomDeFiDataOptions {
87
87
  isSim?: boolean;
88
88
  /** viem multicall calldata cap in bytes; defaults to 250k (2k when isSim). */
89
89
  batchSize?: number;
90
+ /** Every read is made at this block; defaults to latest. */
91
+ blockNumber?: number;
90
92
  }
91
93
  export interface CustomDeFiData {
92
94
  positions: PortfolioPositionsData;
@@ -1,5 +1,5 @@
1
1
  import { Client } from 'viem';
2
- import { EthAddress, NetworkNumber } from '../types/common';
3
- export declare const getUmbrellaData: (provider: Client, network: NetworkNumber, address: EthAddress) => Promise<{
2
+ import { Blockish, EthAddress, NetworkNumber } from '../types/common';
3
+ export declare const getUmbrellaData: (provider: Client, network: NetworkNumber, address: EthAddress, blockNumber?: Blockish) => Promise<{
4
4
  [k: string]: any;
5
5
  }>;
@@ -9,16 +9,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import { AaveUmbrellaViewViem, AaveV3ViewContractViem } from '../contracts';
11
11
  import { compareAddresses, convertHybridArraysToObjects, getEthAmountForDecimals } from '../services/utils';
12
+ import { setViemBlockNumber } from '../services/viem';
12
13
  import { findMatching, tokenEntries } from './umbrellaUtils';
13
14
  const umbrella = '0xD400fc38ED4732893174325693a63C30ee3881a8';
14
15
  const aaveOracle = '0x54586bE62E3c3580375aE3723C145253060Ca0C2';
15
- export const getUmbrellaData = (provider, network, address) => __awaiter(void 0, void 0, void 0, function* () {
16
+ export const getUmbrellaData = (provider_1, network_1, address_1, ...args_1) => __awaiter(void 0, [provider_1, network_1, address_1, ...args_1], void 0, function* (provider, network, address, blockNumber = 'latest') {
16
17
  const umbrellaView = AaveUmbrellaViewViem(provider, network);
17
18
  const aaveV3View = AaveV3ViewContractViem(provider, network);
18
19
  const [tokensAggregatedData, additionalUmbrellaStakingData, userAggregatedData] = yield Promise.all([
19
- umbrellaView.read.getTokensAggregatedData([umbrella, aaveOracle]),
20
- aaveV3View.read.getAdditionalUmbrellaStakingData([umbrella, address]),
21
- umbrellaView.read.getUserAggregatedData([umbrella, address]),
20
+ umbrellaView.read.getTokensAggregatedData([umbrella, aaveOracle], setViemBlockNumber(blockNumber)),
21
+ aaveV3View.read.getAdditionalUmbrellaStakingData([umbrella, address], setViemBlockNumber(blockNumber)),
22
+ umbrellaView.read.getUserAggregatedData([umbrella, address], setViemBlockNumber(blockNumber)),
22
23
  ]);
23
24
  return Object.fromEntries(tokenEntries.map(([symbol, tokenAddr]) => {
24
25
  // @ts-ignore
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defisaver/positions-sdk",
3
- "version": "2.1.169-custom-fetching-dev",
3
+ "version": "2.1.169-custom-fetching-3-dev",
4
4
  "description": "",
5
5
  "main": "./cjs/index.js",
6
6
  "module": "./esm/index.js",