@gearbox-protocol/sdk 3.0.0-vfourabi.1 → 3.0.0-vfourabi.3

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 (275) hide show
  1. package/.eslintignore +3 -0
  2. package/.github/workflows/lint_pr.yml +18 -0
  3. package/.github/workflows/pr.yml +39 -0
  4. package/.github/workflows/release.yml +47 -0
  5. package/.gitignore +19 -0
  6. package/.husky/commit-msg +1 -0
  7. package/.husky/pre-commit +1 -0
  8. package/.nvmrc +1 -0
  9. package/.releaserc.json +34 -0
  10. package/.vscode/extensions.json +7 -0
  11. package/.vscode/settings.json +16 -0
  12. package/.yarn/install-state.gz +0 -0
  13. package/.yarnrc.yml +1 -0
  14. package/ContributionAgreement +72 -0
  15. package/dist/cjs/abi/iZapper.cjs +85 -0
  16. package/dist/cjs/abi/iZapper.d.ts +123 -0
  17. package/dist/cjs/sdk/index.cjs +19830 -19764
  18. package/dist/cjs/sdk/index.d.ts +3746 -3061
  19. package/dist/esm/abi/iZapper.d.mts +123 -0
  20. package/dist/esm/abi/iZapper.mjs +83 -0
  21. package/dist/esm/sdk/index.d.mts +3746 -3061
  22. package/dist/esm/sdk/index.mjs +19807 -19765
  23. package/jest.config.js +7 -0
  24. package/package.json +32 -2
  25. package/scripts/example.ts +30 -0
  26. package/src/abi/compressors.ts +3962 -0
  27. package/src/abi/errors.ts +196 -0
  28. package/src/abi/iERC20.ts +122 -0
  29. package/src/abi/iPausable.ts +35 -0
  30. package/src/abi/iPriceFeedStore.ts +227 -0
  31. package/src/abi/iUpdatablePriceFeed.ts +16 -0
  32. package/src/abi/iVersion.ts +28 -0
  33. package/src/abi/iZapper.ts +84 -0
  34. package/src/abi/routerV300.ts +378 -0
  35. package/src/abi/v300.ts +4151 -0
  36. package/src/abi/v310.ts +5179 -0
  37. package/src/adapters/AbstractAdapter.ts +28 -0
  38. package/src/adapters/BalancerV2VaultAdapterContract.ts +19 -0
  39. package/src/adapters/BalancerV3RouterAdapterContract.ts +19 -0
  40. package/src/adapters/CamelotV3AdapterContract.ts +20 -0
  41. package/src/adapters/ConvexV1BaseRewardPoolAdapterContract.ts +20 -0
  42. package/src/adapters/ConvexV1BoosterAdapterContract.ts +20 -0
  43. package/src/adapters/Curve2AssetsAdapterContract.ts +20 -0
  44. package/src/adapters/Curve3AssetsAdapterContract.ts +20 -0
  45. package/src/adapters/Curve4AssetsAdapterContract.ts +20 -0
  46. package/src/adapters/CurveV1AdapterStETHContract.ts +20 -0
  47. package/src/adapters/CurveV1StableNGAdapterContract.ts +20 -0
  48. package/src/adapters/DaiUsdsAdapterContract.ts +21 -0
  49. package/src/adapters/ERC4626AdapterContract.ts +20 -0
  50. package/src/adapters/MellowERC4626VaultAdapterContract.ts +20 -0
  51. package/src/adapters/MellowVaultAdapterContract.ts +20 -0
  52. package/src/adapters/PendleRouterAdapterContract.ts +21 -0
  53. package/src/adapters/StakingRewardsAdapterContract.ts +21 -0
  54. package/src/adapters/UniswapV2AdapterContract.ts +20 -0
  55. package/src/adapters/UniswapV3AdapterContract.ts +170 -0
  56. package/src/adapters/VelodromeV2AdapterContract.ts +20 -0
  57. package/src/adapters/WstETHV1AdapterContract.ts +20 -0
  58. package/src/adapters/YearnV2AdapterContract.ts +20 -0
  59. package/src/adapters/abi/adapters.ts +4325 -0
  60. package/src/adapters/abi/iBalancerV3RouterAdapter.ts +126 -0
  61. package/src/adapters/abi/index.ts +2 -0
  62. package/src/adapters/index.ts +2 -0
  63. package/src/adapters/plugin.ts +90 -0
  64. package/src/adapters/types.ts +62 -0
  65. package/src/dev/AccountOpener.ts +611 -0
  66. package/src/dev/PriceFeedStore.ts +95 -0
  67. package/src/dev/SDKExample.ts +167 -0
  68. package/src/dev/abi.ts +14 -0
  69. package/src/dev/calcLiquidatableLTs.ts +77 -0
  70. package/src/dev/createAnvilClient.ts +155 -0
  71. package/src/dev/index.ts +7 -0
  72. package/src/dev/setLTZero.ts +127 -0
  73. package/src/dev/setLTs.ts +68 -0
  74. package/src/sdk/GearboxSDK.ts +488 -0
  75. package/src/sdk/abi/index.ts +1 -0
  76. package/src/sdk/abi/oracles.ts +4614 -0
  77. package/src/sdk/accounts/CreditAccountsService.ts +1123 -0
  78. package/src/sdk/accounts/index.ts +1 -0
  79. package/src/sdk/base/AddressLabeller.ts +35 -0
  80. package/src/sdk/base/BaseContract.ts +237 -0
  81. package/src/sdk/base/IAddressLabeller.ts +13 -0
  82. package/src/sdk/base/PlaceholderContract.ts +12 -0
  83. package/src/sdk/base/SDKConstruct.ts +35 -0
  84. package/src/sdk/base/TokensMeta.ts +45 -0
  85. package/src/sdk/base/index.ts +6 -0
  86. package/src/sdk/base/types.ts +102 -0
  87. package/src/sdk/bots/BotsService.ts +92 -0
  88. package/src/sdk/bots/index.ts +2 -0
  89. package/src/sdk/bots/utils.ts +19 -0
  90. package/src/sdk/chain/Provider.ts +99 -0
  91. package/src/sdk/chain/chains.ts +41 -0
  92. package/src/sdk/chain/detectChain.ts +21 -0
  93. package/src/sdk/chain/index.ts +3 -0
  94. package/src/sdk/constants/address-provider.ts +47 -0
  95. package/src/sdk/constants/addresses.ts +82 -0
  96. package/src/sdk/constants/bot-permissions.ts +36 -0
  97. package/src/sdk/constants/index.ts +6 -0
  98. package/src/sdk/constants/math.ts +23 -0
  99. package/src/sdk/constants/networks.ts +38 -0
  100. package/src/sdk/constants/periphery.ts +7 -0
  101. package/src/sdk/core/BotListV3Contract.ts +103 -0
  102. package/src/sdk/core/GearStakingV3Contract.ts +84 -0
  103. package/src/sdk/core/address-provider/AbstractAddressProviderContract.ts +101 -0
  104. package/src/sdk/core/address-provider/AddressProviderV3Contract.ts +105 -0
  105. package/src/sdk/core/address-provider/AddressProviderV3_1Contract.ts +92 -0
  106. package/src/sdk/core/address-provider/getAddressProvider.ts +45 -0
  107. package/src/sdk/core/address-provider/index.ts +4 -0
  108. package/src/sdk/core/address-provider/types.ts +17 -0
  109. package/src/sdk/core/index.ts +3 -0
  110. package/src/sdk/gauges/GaugeStakingService.ts +100 -0
  111. package/src/sdk/gauges/index.ts +2 -0
  112. package/src/sdk/gauges/utils.ts +25 -0
  113. package/src/sdk/index.ts +17 -0
  114. package/src/sdk/market/MarketConfiguratorContract.ts +78 -0
  115. package/src/sdk/market/MarketRegister.ts +330 -0
  116. package/src/sdk/market/MarketSuite.ts +83 -0
  117. package/src/sdk/market/adapters/PlaceholderAdapterContracts.ts +18 -0
  118. package/src/sdk/market/adapters/factory.ts +34 -0
  119. package/src/sdk/market/adapters/index.ts +3 -0
  120. package/src/sdk/market/adapters/types.ts +7 -0
  121. package/src/sdk/market/credit/CreditConfiguratorV300Contract.ts +164 -0
  122. package/src/sdk/market/credit/CreditConfiguratorV310Contract.ts +139 -0
  123. package/src/sdk/market/credit/CreditFacadeV300Contract.ts +206 -0
  124. package/src/sdk/market/credit/CreditFacadeV310Contract.ts +190 -0
  125. package/src/sdk/market/credit/CreditManagerV300Contract.ts +122 -0
  126. package/src/sdk/market/credit/CreditManagerV310Contract.ts +122 -0
  127. package/src/sdk/market/credit/CreditSuite.ts +65 -0
  128. package/src/sdk/market/credit/createCreditConfigurator.ts +18 -0
  129. package/src/sdk/market/credit/createCreditFacade.ts +18 -0
  130. package/src/sdk/market/credit/createCreditManager.ts +18 -0
  131. package/src/sdk/market/credit/index.ts +8 -0
  132. package/src/sdk/market/credit/types.ts +42 -0
  133. package/src/sdk/market/index.ts +7 -0
  134. package/src/sdk/market/oracle/PriceOracleBaseContract.ts +376 -0
  135. package/src/sdk/market/oracle/PriceOracleV300Contract.ts +71 -0
  136. package/src/sdk/market/oracle/PriceOracleV310Contract.ts +43 -0
  137. package/src/sdk/market/oracle/createPriceOracle.ts +22 -0
  138. package/src/sdk/market/oracle/index.ts +4 -0
  139. package/src/sdk/market/oracle/types.ts +48 -0
  140. package/src/sdk/market/pool/GaugeContract.ts +120 -0
  141. package/src/sdk/market/pool/LinearInterestRateModelContract.ts +75 -0
  142. package/src/sdk/market/pool/PoolQuotaKeeperV300Contract.ts +89 -0
  143. package/src/sdk/market/pool/PoolQuotaKeeperV310Contract.ts +89 -0
  144. package/src/sdk/market/pool/PoolSuite.ts +76 -0
  145. package/src/sdk/market/pool/PoolV300Contract.ts +144 -0
  146. package/src/sdk/market/pool/PoolV310Contract.ts +144 -0
  147. package/src/sdk/market/pool/TumblerContract.ts +73 -0
  148. package/src/sdk/market/pool/createInterestRateModel.ts +33 -0
  149. package/src/sdk/market/pool/createPool.ts +19 -0
  150. package/src/sdk/market/pool/createPoolQuotaKeeper.ts +20 -0
  151. package/src/sdk/market/pool/createRateKeeper.ts +25 -0
  152. package/src/sdk/market/pool/index.ts +6 -0
  153. package/src/sdk/market/pool/types.ts +28 -0
  154. package/src/sdk/market/pricefeeds/AbstractLPPriceFeed.ts +71 -0
  155. package/src/sdk/market/pricefeeds/AbstractPriceFeed.ts +137 -0
  156. package/src/sdk/market/pricefeeds/BalancerStablePriceFeed.ts +24 -0
  157. package/src/sdk/market/pricefeeds/BalancerWeightedPriceFeed.ts +70 -0
  158. package/src/sdk/market/pricefeeds/BoundedPriceFeed.ts +34 -0
  159. package/src/sdk/market/pricefeeds/ChainlinkPriceFeed.ts +16 -0
  160. package/src/sdk/market/pricefeeds/CompositePriceFeed.ts +25 -0
  161. package/src/sdk/market/pricefeeds/CurveCryptoPriceFeed.ts +24 -0
  162. package/src/sdk/market/pricefeeds/CurveStablePriceFeed.ts +24 -0
  163. package/src/sdk/market/pricefeeds/CurveUSDPriceFeed.ts +24 -0
  164. package/src/sdk/market/pricefeeds/Erc4626PriceFeed.ts +36 -0
  165. package/src/sdk/market/pricefeeds/MellowLRTPriceFeed.ts +26 -0
  166. package/src/sdk/market/pricefeeds/PendleTWAPPTPriceFeed.ts +44 -0
  167. package/src/sdk/market/pricefeeds/PriceFeedRef.ts +34 -0
  168. package/src/sdk/market/pricefeeds/PriceFeedsRegister.ts +293 -0
  169. package/src/sdk/market/pricefeeds/RedstonePriceFeed.ts +65 -0
  170. package/src/sdk/market/pricefeeds/RedstoneUpdater.ts +304 -0
  171. package/src/sdk/market/pricefeeds/WstETHPriceFeed.ts +24 -0
  172. package/src/sdk/market/pricefeeds/YearnPriceFeed.ts +24 -0
  173. package/src/sdk/market/pricefeeds/ZeroPriceFeed.ts +17 -0
  174. package/src/sdk/market/pricefeeds/index.ts +20 -0
  175. package/src/sdk/market/pricefeeds/types.ts +82 -0
  176. package/src/sdk/market/pricefeeds/utils.ts +24 -0
  177. package/src/sdk/plugins/index.ts +10 -0
  178. package/src/sdk/router/PathOptionFactory.ts +147 -0
  179. package/src/sdk/router/RouterV3Contract.ts +558 -0
  180. package/src/sdk/router/index.ts +2 -0
  181. package/src/sdk/router/types.ts +48 -0
  182. package/src/sdk/sdk-gov-legacy/contracts/adapters.ts +39 -0
  183. package/src/sdk/sdk-gov-legacy/contracts/contracts.ts +647 -0
  184. package/src/sdk/sdk-gov-legacy/contracts/index.ts +2 -0
  185. package/src/sdk/sdk-gov-legacy/core/constants.ts +11 -0
  186. package/src/sdk/sdk-gov-legacy/index.ts +4 -0
  187. package/src/sdk/sdk-gov-legacy/oracles/PriceFeedType.ts +24 -0
  188. package/src/sdk/sdk-gov-legacy/oracles/index.ts +1 -0
  189. package/src/sdk/sdk-gov-legacy/tokens/aave.ts +101 -0
  190. package/src/sdk/sdk-gov-legacy/tokens/aura.ts +284 -0
  191. package/src/sdk/sdk-gov-legacy/tokens/balancer.ts +421 -0
  192. package/src/sdk/sdk-gov-legacy/tokens/compound.ts +79 -0
  193. package/src/sdk/sdk-gov-legacy/tokens/convex.ts +561 -0
  194. package/src/sdk/sdk-gov-legacy/tokens/curveLP.ts +480 -0
  195. package/src/sdk/sdk-gov-legacy/tokens/decimals.ts +301 -0
  196. package/src/sdk/sdk-gov-legacy/tokens/erc4626.ts +75 -0
  197. package/src/sdk/sdk-gov-legacy/tokens/gear.ts +273 -0
  198. package/src/sdk/sdk-gov-legacy/tokens/index.ts +18 -0
  199. package/src/sdk/sdk-gov-legacy/tokens/normal.ts +613 -0
  200. package/src/sdk/sdk-gov-legacy/tokens/quoted.ts +10 -0
  201. package/src/sdk/sdk-gov-legacy/tokens/stakingRewards.ts +41 -0
  202. package/src/sdk/sdk-gov-legacy/tokens/token.ts +2354 -0
  203. package/src/sdk/sdk-gov-legacy/tokens/tokenData.ts +44 -0
  204. package/src/sdk/sdk-gov-legacy/tokens/tokenType.ts +33 -0
  205. package/src/sdk/sdk-gov-legacy/tokens/wrapped.ts +28 -0
  206. package/src/sdk/sdk-gov-legacy/tokens/yearn.ts +122 -0
  207. package/src/sdk/sdk-gov-legacy/tokens/zircuit.ts +44 -0
  208. package/src/sdk/sdk-legacy/apy/index.ts +149 -0
  209. package/src/sdk/sdk-legacy/core/assets.ts +200 -0
  210. package/src/sdk/sdk-legacy/core/creditAccount.spec.ts +1966 -0
  211. package/src/sdk/sdk-legacy/core/creditAccount.ts +816 -0
  212. package/src/sdk/sdk-legacy/core/creditManager.ts +316 -0
  213. package/src/sdk/sdk-legacy/core/creditSession.ts +352 -0
  214. package/src/sdk/sdk-legacy/core/endpoint.ts +131 -0
  215. package/src/sdk/sdk-legacy/core/eventOrTx.ts +101 -0
  216. package/src/sdk/sdk-legacy/core/pool.ts +439 -0
  217. package/src/sdk/sdk-legacy/core/strategy.ts +82 -0
  218. package/src/sdk/sdk-legacy/core/transactions.ts +865 -0
  219. package/src/sdk/sdk-legacy/gearboxRewards/api.ts +704 -0
  220. package/src/sdk/sdk-legacy/gearboxRewards/apy.ts +267 -0
  221. package/src/sdk/sdk-legacy/gearboxRewards/extraAPY.ts +165 -0
  222. package/src/sdk/sdk-legacy/gearboxRewards/index.ts +3 -0
  223. package/src/sdk/sdk-legacy/gearboxRewards/merklAPI.ts +151 -0
  224. package/src/sdk/sdk-legacy/index.ts +21 -0
  225. package/src/sdk/sdk-legacy/pathfinder/core.ts +18 -0
  226. package/src/sdk/sdk-legacy/pathfinder/index.ts +1 -0
  227. package/src/sdk/sdk-legacy/payload/creditAccount.ts +48 -0
  228. package/src/sdk/sdk-legacy/payload/creditManager.ts +133 -0
  229. package/src/sdk/sdk-legacy/payload/creditSession.ts +143 -0
  230. package/src/sdk/sdk-legacy/payload/graphPayload.ts +10 -0
  231. package/src/sdk/sdk-legacy/payload/pool.ts +198 -0
  232. package/src/sdk/sdk-legacy/payload/token.ts +13 -0
  233. package/src/sdk/sdk-legacy/tokens/tokenData.ts +57 -0
  234. package/src/sdk/sdk-legacy/types/IAirdropDistributor.ts +103 -0
  235. package/src/sdk/sdk-legacy/types/IBaseRewardPool.ts +249 -0
  236. package/src/sdk/sdk-legacy/types/IDataCompressorV3.ts +957 -0
  237. package/src/sdk/sdk-legacy/types/IDegenDistributor.ts +70 -0
  238. package/src/sdk/sdk-legacy/types/IERC20Permit.ts +35 -0
  239. package/src/sdk/sdk-legacy/types/IERC20ZapperDeposits.ts +99 -0
  240. package/src/sdk/sdk-legacy/types/IETHZapperDeposits.ts +27 -0
  241. package/src/sdk/sdk-legacy/types/IFarmingPool.ts +229 -0
  242. package/src/sdk/sdk-legacy/types/IInterestRateModel.ts +23 -0
  243. package/src/sdk/sdk-legacy/types/IMulticall3.ts +242 -0
  244. package/src/sdk/sdk-legacy/types/IOffchainOracle.ts +31 -0
  245. package/src/sdk/sdk-legacy/types/index.ts +11 -0
  246. package/src/sdk/sdk-legacy/utils/formatter.ts +46 -0
  247. package/src/sdk/sdk-legacy/utils/index.ts +3 -0
  248. package/src/sdk/sdk-legacy/utils/math.ts +6 -0
  249. package/src/sdk/sdk-legacy/utils/price.ts +27 -0
  250. package/src/sdk/types/index.ts +5 -0
  251. package/src/sdk/types/logger.ts +13 -0
  252. package/src/sdk/types/state-human.ts +224 -0
  253. package/src/sdk/types/state.ts +8 -0
  254. package/src/sdk/types/transactions.ts +22 -0
  255. package/src/sdk/types/tvl.ts +4 -0
  256. package/src/sdk/utils/AddressMap.ts +111 -0
  257. package/src/sdk/utils/bytes32ToString.ts +6 -0
  258. package/src/sdk/utils/childLogger.ts +8 -0
  259. package/src/sdk/utils/createRawTx.ts +86 -0
  260. package/src/sdk/utils/etherscan.ts +42 -0
  261. package/src/sdk/utils/filterDust.ts +20 -0
  262. package/src/sdk/utils/formatter.ts +124 -0
  263. package/src/sdk/utils/index.ts +10 -0
  264. package/src/sdk/utils/internal/Hooks.ts +51 -0
  265. package/src/sdk/utils/internal/index.ts +1 -0
  266. package/src/sdk/utils/json.ts +27 -0
  267. package/src/sdk/utils/mappers.ts +38 -0
  268. package/src/sdk/utils/retry.ts +24 -0
  269. package/src/sdk/utils/viem/detectNetwork.ts +27 -0
  270. package/src/sdk/utils/viem/index.ts +3 -0
  271. package/src/sdk/utils/viem/sendRawTx.ts +36 -0
  272. package/src/sdk/utils/viem/simulateMulticall.ts +262 -0
  273. package/tsconfig.build.json +4 -0
  274. package/tsconfig.json +16 -0
  275. package/tsup.config.ts +77 -0
@@ -0,0 +1,293 @@
1
+ import {
2
+ type Address,
3
+ getChainContractAddress,
4
+ type Hex,
5
+ multicall3Abi,
6
+ } from "viem";
7
+
8
+ import { iMarketCompressorAbi } from "../../../abi/compressors";
9
+ import type { BaseParams, PriceFeedTreeNode } from "../../base";
10
+ import { SDKConstruct } from "../../base";
11
+ import { ADDRESS_0X0, AP_MARKET_COMPRESSOR } from "../../constants";
12
+ import type { GearboxSDK } from "../../GearboxSDK";
13
+ import type { ILogger, RawTx } from "../../types";
14
+ import {
15
+ AddressMap,
16
+ bytes32ToString,
17
+ childLogger,
18
+ createRawTx,
19
+ } from "../../utils";
20
+ import type { IHooks } from "../../utils/internal";
21
+ import { Hooks } from "../../utils/internal";
22
+ import type { PartialPriceFeedTreeNode } from "./AbstractPriceFeed";
23
+ import { BalancerStablePriceFeedContract } from "./BalancerStablePriceFeed";
24
+ import { BalancerWeightedPriceFeedContract } from "./BalancerWeightedPriceFeed";
25
+ import { BoundedPriceFeedContract } from "./BoundedPriceFeed";
26
+ import { ChainlinkPriceFeedContract } from "./ChainlinkPriceFeed";
27
+ import { CompositePriceFeedContract } from "./CompositePriceFeed";
28
+ import { CurveCryptoPriceFeedContract } from "./CurveCryptoPriceFeed";
29
+ import { CurveStablePriceFeedContract } from "./CurveStablePriceFeed";
30
+ import { CurveUSDPriceFeedContract } from "./CurveUSDPriceFeed";
31
+ import { Erc4626PriceFeedContract } from "./Erc4626PriceFeed";
32
+ import { MellowLRTPriceFeedContract } from "./MellowLRTPriceFeed";
33
+ import { PendleTWAPPTPriceFeed } from "./PendleTWAPPTPriceFeed";
34
+ import { RedstonePriceFeedContract } from "./RedstonePriceFeed";
35
+ import { RedstoneUpdater } from "./RedstoneUpdater";
36
+ import type {
37
+ IPriceFeedContract,
38
+ PriceFeedContractType,
39
+ UpdatePriceFeedsResult,
40
+ } from "./types";
41
+ import { WstETHPriceFeedContract } from "./WstETHPriceFeed";
42
+ import { YearnPriceFeedContract } from "./YearnPriceFeed";
43
+ import { ZeroPriceFeedContract } from "./ZeroPriceFeed";
44
+
45
+ // eslint-disable-next-line @typescript-eslint/consistent-type-definitions
46
+ export type PriceFeedRegisterHooks = {
47
+ /**
48
+ * Emitted when transactions to update price feeds have been generated, but before they're used anywhere
49
+ */
50
+ updatesGenerated: [UpdatePriceFeedsResult];
51
+ };
52
+
53
+ /**
54
+ * PriceFeedRegister acts as a chain-level cache to avoid creating multiple contract instances.
55
+ * It's reused by PriceOracles belonging to different markets
56
+ *
57
+ **/
58
+ export class PriceFeedRegister
59
+ extends SDKConstruct
60
+ implements IHooks<PriceFeedRegisterHooks>
61
+ {
62
+ public readonly logger?: ILogger;
63
+ readonly #hooks = new Hooks<PriceFeedRegisterHooks>();
64
+ #feeds = new AddressMap<IPriceFeedContract>(undefined, "priceFeeds");
65
+ public readonly redstoneUpdater: RedstoneUpdater;
66
+
67
+ constructor(sdk: GearboxSDK) {
68
+ super(sdk);
69
+ this.logger = childLogger("PriceFeedRegister", sdk.logger);
70
+ this.redstoneUpdater = new RedstoneUpdater(sdk);
71
+ }
72
+
73
+ public addHook = this.#hooks.addHook.bind(this.#hooks);
74
+ public removeHook = this.#hooks.removeHook.bind(this.#hooks);
75
+
76
+ /**
77
+ * Returns RawTxs to update price feeds
78
+ * @param priceFeeds top-level price feeds, actual updatable price feeds will be derived. If not provided will use all price feeds that are attached
79
+ * @param logContext extra information for logging
80
+ * @returns
81
+ */
82
+ public async generatePriceFeedsUpdateTxs(
83
+ priceFeeds?: IPriceFeedContract[],
84
+ logContext: Record<string, any> = {},
85
+ ): Promise<UpdatePriceFeedsResult> {
86
+ const updateables = priceFeeds
87
+ ? priceFeeds.flatMap(pf => pf.updatableDependencies())
88
+ : this.#feeds.values();
89
+ return this.#generatePriceFeedsUpdateTxs(updateables, logContext);
90
+ }
91
+
92
+ public has(address: Address): boolean {
93
+ return this.#feeds.has(address);
94
+ }
95
+
96
+ public mustGet(address: Address): IPriceFeedContract {
97
+ return this.#feeds.mustGet(address);
98
+ }
99
+
100
+ public getOrCreate(data: PriceFeedTreeNode): IPriceFeedContract {
101
+ const existing = this.#feeds.get(data.baseParams.addr);
102
+ // it's possible to have non-loaded price feed here first from MarketCompressor.getUpdatablePriceFeeds
103
+ // we ovewrite them using full tree nodes
104
+ if (existing?.loaded) {
105
+ return existing;
106
+ }
107
+ const feed = this.create(data);
108
+ this.#feeds.upsert(data.baseParams.addr, feed);
109
+ return feed;
110
+ }
111
+
112
+ /**
113
+ * Loads PARTIAL information about all updatable price feeds from MarketCompressor
114
+ * This can later be used to load price feed updates
115
+ */
116
+ public async preloadUpdatablePriceFeeds(
117
+ marketConfigurators?: Address[],
118
+ pools?: Address[],
119
+ ): Promise<void> {
120
+ const feedsData = await this.#loadUpdatablePriceFeeds(
121
+ marketConfigurators,
122
+ pools,
123
+ );
124
+ for (const data of feedsData) {
125
+ const feed = this.create({ baseParams: data });
126
+ this.#feeds.upsert(feed.address, feed);
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Generates price update transaction via multicall3 without any market data knowledge
132
+ * @param marketConfigurators
133
+ * @param pools
134
+ * @returns
135
+ */
136
+ public async getUpdatePriceFeedsTx(
137
+ marketConfigurators?: Address[],
138
+ pools?: Address[],
139
+ ): Promise<RawTx> {
140
+ const feedsData = await this.#loadUpdatablePriceFeeds(
141
+ marketConfigurators,
142
+ pools,
143
+ );
144
+ const feeds = feedsData.map(data => this.create({ baseParams: data }));
145
+ const updates = await this.#generatePriceFeedsUpdateTxs(feeds);
146
+
147
+ return createRawTx(
148
+ getChainContractAddress({
149
+ chain: this.sdk.provider.chain,
150
+ contract: "multicall3",
151
+ }),
152
+ {
153
+ abi: multicall3Abi,
154
+ functionName: "aggregate3",
155
+ args: [
156
+ updates.txs.map(tx => ({
157
+ target: tx.to,
158
+ allowFailure: false,
159
+ callData: tx.callData,
160
+ })),
161
+ ],
162
+ },
163
+ );
164
+ }
165
+
166
+ async #generatePriceFeedsUpdateTxs(
167
+ updateables: IPriceFeedContract[],
168
+ logContext: Record<string, any> = {},
169
+ ): Promise<UpdatePriceFeedsResult> {
170
+ const txs: RawTx[] = [];
171
+ const redstonePFs: RedstonePriceFeedContract[] = [];
172
+
173
+ for (const pf of updateables) {
174
+ if (pf instanceof RedstonePriceFeedContract) {
175
+ redstonePFs.push(pf);
176
+ }
177
+ }
178
+
179
+ let maxTimestamp = 0;
180
+ if (redstonePFs.length > 0) {
181
+ const redstoneUpdates = await this.redstoneUpdater.getUpdateTxs(
182
+ redstonePFs,
183
+ logContext,
184
+ );
185
+ for (const { tx, timestamp } of redstoneUpdates) {
186
+ if (timestamp > maxTimestamp) {
187
+ maxTimestamp = timestamp;
188
+ }
189
+ txs.push(tx);
190
+ }
191
+ }
192
+
193
+ const result: UpdatePriceFeedsResult = { txs, timestamp: maxTimestamp };
194
+ this.logger?.debug(
195
+ logContext,
196
+ `generated ${txs.length} price feed update transactions, timestamp: ${maxTimestamp}`,
197
+ );
198
+ if (txs.length) {
199
+ await this.#hooks.triggerHooks("updatesGenerated", result);
200
+ }
201
+ return result;
202
+ }
203
+
204
+ async #loadUpdatablePriceFeeds(
205
+ marketConfigurators?: Address[],
206
+ pools?: Address[],
207
+ ): Promise<readonly BaseParams[]> {
208
+ const marketCompressorAddress = this.sdk.addressProvider.getAddress(
209
+ AP_MARKET_COMPRESSOR,
210
+ 3_10,
211
+ );
212
+ const configurators =
213
+ marketConfigurators ??
214
+ this.sdk.marketRegister.marketConfigurators.map(mc => mc.address);
215
+ this.logger?.debug(
216
+ { configurators, pools },
217
+ "calling getUpdatablePriceFeeds",
218
+ );
219
+ const result = await this.provider.publicClient.readContract({
220
+ address: marketCompressorAddress,
221
+ abi: iMarketCompressorAbi,
222
+ functionName: "getUpdatablePriceFeeds",
223
+ args: [
224
+ {
225
+ configurators,
226
+ pools: pools ?? [],
227
+ underlying: ADDRESS_0X0,
228
+ },
229
+ ],
230
+ // It's passed as ...rest in viem readContract action, but this might change
231
+ // @ts-ignore
232
+ // gas: 500_000_000n,
233
+ });
234
+ this.logger?.debug(`loaded ${result.length} updatable price feeds`);
235
+ return result;
236
+ }
237
+
238
+ public create(data: PartialPriceFeedTreeNode): IPriceFeedContract {
239
+ const contractType = bytes32ToString(
240
+ data.baseParams.contractType as Hex,
241
+ ) as PriceFeedContractType;
242
+
243
+ switch (contractType) {
244
+ case "PRICE_FEED::EXTERNAL":
245
+ return new ChainlinkPriceFeedContract(this.sdk, data);
246
+
247
+ case "PRICE_FEED::YEARN":
248
+ return new YearnPriceFeedContract(this.sdk, data);
249
+
250
+ case "PRICE_FEED::CURVE_STABLE":
251
+ return new CurveStablePriceFeedContract(this.sdk, data);
252
+
253
+ case "PRICE_FEED::WSTETH":
254
+ return new WstETHPriceFeedContract(this.sdk, data);
255
+
256
+ case "PRICE_FEED::BOUNDED":
257
+ return new BoundedPriceFeedContract(this.sdk, data);
258
+
259
+ case "PRICE_FEED::COMPOSITE":
260
+ return new CompositePriceFeedContract(this.sdk, data);
261
+
262
+ case "PRICE_FEED::BALANCER_STABLE":
263
+ return new BalancerStablePriceFeedContract(this.sdk, data);
264
+
265
+ case "PRICE_FEED::BALANCER_WEIGHTED":
266
+ return new BalancerWeightedPriceFeedContract(this.sdk, data);
267
+
268
+ case "PRICE_FEED::CURVE_CRYPTO":
269
+ return new CurveCryptoPriceFeedContract(this.sdk, data);
270
+
271
+ case "PRICE_FEED::REDSTONE":
272
+ return new RedstonePriceFeedContract(this.sdk, data);
273
+
274
+ case "PRICE_FEED::ERC4626":
275
+ return new Erc4626PriceFeedContract(this.sdk, data);
276
+
277
+ case "PRICE_FEED::CURVE_USD":
278
+ return new CurveUSDPriceFeedContract(this.sdk, data);
279
+
280
+ case "PRICE_FEED::ZERO":
281
+ return new ZeroPriceFeedContract(this.sdk, data);
282
+
283
+ case "PRICE_FEED::MELLOW_LRT":
284
+ return new MellowLRTPriceFeedContract(this.sdk, data);
285
+
286
+ case "PRICE_FEED::PENDLE_PT_TWAP":
287
+ return new PendleTWAPPTPriceFeed(this.sdk, data);
288
+
289
+ default:
290
+ throw new Error(`Price feed type ${contractType} not supported, `);
291
+ }
292
+ }
293
+ }
@@ -0,0 +1,65 @@
1
+ import type { Hex } from "viem";
2
+ import { bytesToString, decodeAbiParameters, toBytes } from "viem";
3
+
4
+ import { redstonePriceFeedAbi } from "../../abi";
5
+ import type { GearboxSDK } from "../../GearboxSDK";
6
+ import type { RedstonePriceFeedStateHuman } from "../../types";
7
+ import type { PartialPriceFeedTreeNode } from "./AbstractPriceFeed";
8
+ import { AbstractPriceFeedContract } from "./AbstractPriceFeed";
9
+
10
+ type abi = typeof redstonePriceFeedAbi;
11
+
12
+ export class RedstonePriceFeedContract extends AbstractPriceFeedContract<abi> {
13
+ public readonly dataServiceId: string;
14
+ public readonly dataId: string;
15
+ public readonly signers: Hex[];
16
+ public readonly signersThreshold: number;
17
+
18
+ constructor(sdk: GearboxSDK, args: PartialPriceFeedTreeNode) {
19
+ super(sdk, {
20
+ ...args,
21
+ name: `RedstonePriceFeed`,
22
+ abi: redstonePriceFeedAbi,
23
+ });
24
+ const decoder = decodeAbiParameters(
25
+ [
26
+ { type: "address" }, // [0]: pf.token(),
27
+ { type: "bytes32" }, // [1]: pf.dataFeedId(),
28
+ { type: "address" }, // [2]: pf.signerAddress0(),
29
+ { type: "address" }, // [3]: pf.signerAddress1(),
30
+ { type: "address" }, // [4]: pf.signerAddress2(),
31
+ { type: "address" }, // [5]: pf.signerAddress3(),
32
+ { type: "address" }, // [6]: pf.signerAddress4(),
33
+ { type: "address" }, // [7]: pf.signerAddress5()
34
+ { type: "address" }, // [8]: pf.signerAddress6(),
35
+ { type: "address" }, // [9]: pf.signerAddress7(),
36
+ { type: "address" }, // [10]: pf.signerAddress8(),
37
+ { type: "address" }, // [11]: pf.signerAddress9(),
38
+ { type: "uint8" }, // [12]: pf.getUniqueSignersThreshold()
39
+ { type: "uint128" }, // [13]: pf.lastPrice(),
40
+ { type: "uint40" }, // [14]: pf.lastPayloadTimestamp()
41
+ ],
42
+ args.baseParams.serializedParams,
43
+ );
44
+
45
+ this.dataId = bytesToString(toBytes(decoder[1])).replaceAll("\x00", "");
46
+ this.signers = decoder.slice(2, 11) as Hex[];
47
+ this.signersThreshold = Number(decoder[12]);
48
+ this.dataServiceId = ["GMX", "BAL"].includes(this.dataId)
49
+ ? "redstone-arbitrum-prod"
50
+ : "redstone-primary-prod";
51
+ }
52
+
53
+ public override stateHuman(
54
+ raw = true,
55
+ ): Omit<RedstonePriceFeedStateHuman, "stalenessPeriod"> {
56
+ return {
57
+ ...super.stateHuman(raw),
58
+ contractType: "PRICE_FEED::REDSTONE",
59
+ dataId: this.dataId,
60
+ signers: this.signers,
61
+ signersThreshold: this.signersThreshold,
62
+ skipCheck: true,
63
+ };
64
+ }
65
+ }
@@ -0,0 +1,304 @@
1
+ /* eslint-disable accessor-pairs */
2
+ import { DataServiceWrapper } from "@redstone-finance/evm-connector";
3
+ import type { SignedDataPackage } from "@redstone-finance/protocol";
4
+ import { RedstonePayload } from "@redstone-finance/protocol";
5
+ import type { Address, Hex } from "viem";
6
+ import { encodeAbiParameters, toBytes } from "viem";
7
+
8
+ import { SDKConstruct } from "../../base";
9
+ import type { GearboxSDK } from "../../GearboxSDK";
10
+ import type { ILogger, RawTx } from "../../types";
11
+ import { childLogger, retry } from "../../utils";
12
+ import type { RedstonePriceFeedContract } from "./RedstonePriceFeed";
13
+
14
+ interface TimestampedCalldata {
15
+ dataFeedId: string;
16
+ data: `0x${string}`;
17
+ timestamp: number;
18
+ }
19
+
20
+ interface UpdatePFTask {
21
+ priceFeed: Address;
22
+ tx: RawTx;
23
+ timestamp: number;
24
+ }
25
+
26
+ /**
27
+ * Class to update multiple redstone price feeds at once
28
+ */
29
+ export class RedstoneUpdater extends SDKConstruct {
30
+ #logger?: ILogger;
31
+ #cache = new Map<string, TimestampedCalldata>();
32
+ #historicalTimestampMs?: number;
33
+ #gateways?: string[];
34
+
35
+ constructor(sdk: GearboxSDK) {
36
+ super(sdk);
37
+ this.#logger = childLogger("RedstoneUpdater", sdk.logger);
38
+ }
39
+
40
+ /**
41
+ * Set redstone historical timestamp in milliseconds
42
+ */
43
+ public set historicalTimestamp(timestampMs: number) {
44
+ // redstone timestamps are rounded to one minute
45
+ this.#historicalTimestampMs = 60_000 * Math.floor(timestampMs / 60_000);
46
+ }
47
+
48
+ /**
49
+ * Set redstone gateways
50
+ */
51
+ public set gateways(gateways: string[]) {
52
+ this.#gateways = gateways;
53
+ }
54
+
55
+ public async getUpdateTxs(
56
+ feeds: RedstonePriceFeedContract[],
57
+ logContext: Record<string, any> = {},
58
+ ): Promise<UpdatePFTask[]> {
59
+ this.#logger?.debug(
60
+ logContext,
61
+ `generating update transactions for ${feeds.length} redstone price feeds`,
62
+ );
63
+
64
+ // Group feeds by dataServiceId and uniqueSignersCount
65
+ const groupedFeeds: Record<string, Set<string>> = {};
66
+ const priceFeeds = new Map<string, RedstonePriceFeedContract>();
67
+ for (const feed of feeds) {
68
+ const key = `${feed.dataServiceId}:${feed.signersThreshold}`;
69
+ if (!groupedFeeds[key]) {
70
+ groupedFeeds[key] = new Set();
71
+ }
72
+ groupedFeeds[key].add(feed.dataId);
73
+ priceFeeds.set(feed.dataId, feed);
74
+ }
75
+
76
+ const results: UpdatePFTask[] = [];
77
+ for (const [key, group] of Object.entries(groupedFeeds)) {
78
+ const [dataServiceId, signersStr] = key.split(":");
79
+ const uniqueSignersCount = parseInt(signersStr, 10);
80
+ const payloads = await this.#getPayloads(
81
+ dataServiceId,
82
+ group,
83
+ uniqueSignersCount,
84
+ );
85
+
86
+ for (const { dataFeedId, data, timestamp } of payloads) {
87
+ const priceFeed = priceFeeds.get(dataFeedId);
88
+ if (!priceFeed) {
89
+ throw new Error(`cannot get price feed address for ${dataFeedId}`);
90
+ }
91
+ results.push({
92
+ priceFeed: priceFeed.address.toLowerCase() as Address,
93
+ tx: priceFeed.createRawTx({
94
+ functionName: "updatePrice",
95
+ args: [data as Hex],
96
+ description: `updating price for ${dataFeedId} [${this.sdk.provider.addressLabels.get(priceFeed.address)}]`,
97
+ }),
98
+ timestamp,
99
+ });
100
+ }
101
+ }
102
+ this.#logger?.debug(
103
+ logContext,
104
+ `generated ${results.length} update transactions for redstone price feeds`,
105
+ );
106
+ return results;
107
+ }
108
+
109
+ /**
110
+ * Gets redstone payloads in one request for multiple feeds with the same dataServiceId and uniqueSignersCount
111
+ * If historicalTimestamp is set, responses will be cached
112
+ * @param dataServiceId
113
+ * @param dataFeedsIds
114
+ * @param uniqueSignersCount
115
+ * @returns
116
+ */
117
+ async #getPayloads(
118
+ dataServiceId: string,
119
+ dataFeedsIds: Set<string>,
120
+ uniqueSignersCount: number,
121
+ ): Promise<TimestampedCalldata[]> {
122
+ this.#logger?.debug(
123
+ `getting redstone payloads for ${dataFeedsIds.size} data feeds in ${dataServiceId} with ${uniqueSignersCount} signers: ${Array.from(dataFeedsIds).join(", ")}`,
124
+ );
125
+ const fromCache: TimestampedCalldata[] = [];
126
+ const uncached: string[] = [];
127
+ for (const dataFeedId of dataFeedsIds) {
128
+ const key = cacheKey(
129
+ dataServiceId,
130
+ dataFeedId,
131
+ uniqueSignersCount,
132
+ this.#historicalTimestampMs,
133
+ );
134
+ const cached = this.#cache.get(key);
135
+ if (this.#historicalTimestampMs && !!cached) {
136
+ fromCache.push(cached);
137
+ } else {
138
+ uncached.push(dataFeedId);
139
+ }
140
+ }
141
+
142
+ const fromRedstone = await this.#fetchPayloads(
143
+ dataServiceId,
144
+ new Set(uncached),
145
+ uniqueSignersCount,
146
+ );
147
+ // cache newly fetched responses
148
+ if (this.#historicalTimestampMs) {
149
+ for (const resp of fromRedstone) {
150
+ const key = cacheKey(
151
+ dataServiceId,
152
+ resp.dataFeedId,
153
+ uniqueSignersCount,
154
+ this.#historicalTimestampMs,
155
+ );
156
+ this.#cache.set(key, resp);
157
+ }
158
+ }
159
+ this.#logger?.debug(
160
+ `got ${fromRedstone.length} new redstone updates and ${fromCache.length} from cache`,
161
+ );
162
+
163
+ return [...fromCache, ...fromRedstone];
164
+ }
165
+
166
+ /**
167
+ * Fetches redstone payloads in one request for multiple feeds with the same dataServiceId and uniqueSignersCount
168
+ * Payloads are loaded in one request to avoid redstone rate limit
169
+ * @param dataServiceId
170
+ * @param dataFeedsIds
171
+ * @param uniqueSignersCount
172
+ * @returns
173
+ */
174
+ async #fetchPayloads(
175
+ dataServiceId: string,
176
+ dataFeedsIds: Set<string>,
177
+ uniqueSignersCount: number,
178
+ ): Promise<TimestampedCalldata[]> {
179
+ if (dataFeedsIds.size === 0) {
180
+ return [];
181
+ }
182
+ const dataPackagesIds = Array.from(dataFeedsIds);
183
+ const tsStr = this.#historicalTimestampMs
184
+ ? ` with historical timestamp ${this.#historicalTimestampMs}`
185
+ : "";
186
+ this.#logger?.debug(
187
+ `fetching redstone payloads for ${dataFeedsIds.size} data feeds in ${dataServiceId} with ${uniqueSignersCount} signers: ${dataPackagesIds.join(", ")}${tsStr}`,
188
+ );
189
+ const wrapper = new DataServiceWrapper({
190
+ dataServiceId,
191
+ dataPackagesIds,
192
+ uniqueSignersCount,
193
+ historicalTimestamp: this.#historicalTimestampMs,
194
+ urls: this.#gateways,
195
+ });
196
+
197
+ const dataPayload = await retry(
198
+ () => wrapper.prepareRedstonePayload(true),
199
+ { attempts: 5, interval: this.#historicalTimestampMs ? 30_500 : 250 },
200
+ );
201
+
202
+ const parsed = RedstonePayload.parse(toBytes(`0x${dataPayload}`));
203
+ const packagesByDataFeedId = groupDataPackages(parsed.signedDataPackages);
204
+
205
+ return dataPackagesIds.map(dataFeedId => {
206
+ const signedDataPackages = packagesByDataFeedId[dataFeedId];
207
+ if (!signedDataPackages) {
208
+ throw new Error(`cannot find data packages for ${dataFeedId}`);
209
+ }
210
+ if (signedDataPackages.length !== uniqueSignersCount) {
211
+ throw new Error(
212
+ `got ${signedDataPackages.length} data packages for ${dataFeedId}, but expected ${uniqueSignersCount}`,
213
+ );
214
+ }
215
+ return getCalldataWithTimestamp(
216
+ dataFeedId,
217
+ signedDataPackages,
218
+ wrapper.getUnsignedMetadata(),
219
+ );
220
+ });
221
+ }
222
+ }
223
+
224
+ function cacheKey(
225
+ dataServiceId: string,
226
+ dataFeedId: string,
227
+ uniqueSignersCount: number,
228
+ historicalTimestamp = 0,
229
+ ): string {
230
+ return `${dataServiceId}:${dataFeedId}:${uniqueSignersCount}:${historicalTimestamp}`;
231
+ }
232
+
233
+ /**
234
+ * Groups SignedDataPackages by dataFeedId
235
+ * @param signedDataPackages
236
+ * @returns
237
+ */
238
+ function groupDataPackages(
239
+ signedDataPackages: SignedDataPackage[],
240
+ ): Record<string, SignedDataPackage[]> {
241
+ const packagesByDataFeedId: Record<string, SignedDataPackage[]> = {};
242
+ for (const p of signedDataPackages) {
243
+ const { dataPoints } = p.dataPackage;
244
+
245
+ // Check if all data points have the same dataFeedId
246
+ const dataFeedId0 = dataPoints[0].dataFeedId;
247
+ for (const dp of dataPoints) {
248
+ if (dp.dataFeedId !== dataFeedId0) {
249
+ throw new Error(
250
+ `data package contains data points with different dataFeedIds: ${dp.dataFeedId} and ${dataFeedId0}`,
251
+ );
252
+ }
253
+ }
254
+
255
+ // Group data packages by dataFeedId
256
+ if (!packagesByDataFeedId[dataFeedId0]) {
257
+ packagesByDataFeedId[dataFeedId0] = [];
258
+ }
259
+ packagesByDataFeedId[dataFeedId0].push(p);
260
+ }
261
+
262
+ return packagesByDataFeedId;
263
+ }
264
+
265
+ function getCalldataWithTimestamp(
266
+ dataFeedId: string,
267
+ packages: SignedDataPackage[],
268
+ unsignedMetadata: string,
269
+ ): TimestampedCalldata {
270
+ const originalPayload = RedstonePayload.prepare(packages, unsignedMetadata);
271
+
272
+ // Calculating the number of bytes in the hex representation of payload
273
+ // We divide by 2, beacuse 2 symbols in a hex string represent one byte
274
+ const originalPayloadLength = originalPayload.length / 2;
275
+
276
+ // Number of bytes that we want to add to unsigned metadata so that
277
+ // payload byte size becomes a multiplicity of 32
278
+ const bytesToAdd = 32 - (originalPayloadLength % 32);
279
+
280
+ // Adding underscores to the end of the metadata string, each underscore
281
+ // uses one byte in UTF-8
282
+ const newUnsignedMetadata = unsignedMetadata + "_".repeat(bytesToAdd);
283
+
284
+ const payload = RedstonePayload.prepare(packages, newUnsignedMetadata);
285
+
286
+ let timestamp = 0;
287
+ for (const p of packages) {
288
+ const newTimestamp = p.dataPackage.timestampMilliseconds / 1000;
289
+ if (timestamp === 0) {
290
+ timestamp = newTimestamp;
291
+ } else if (timestamp !== newTimestamp) {
292
+ throw new Error("Timestamps are not equal");
293
+ }
294
+ }
295
+
296
+ return {
297
+ dataFeedId,
298
+ data: encodeAbiParameters(
299
+ [{ type: "uint256" }, { type: "bytes" }],
300
+ [BigInt(timestamp), `0x${payload}`],
301
+ ),
302
+ timestamp,
303
+ };
304
+ }
@@ -0,0 +1,24 @@
1
+ import { iwstEthAbi, wstEthPriceFeedAbi } from "../../abi";
2
+ import type { GearboxSDK } from "../../GearboxSDK";
3
+ import { AbstractLPPriceFeedContract } from "./AbstractLPPriceFeed";
4
+ import type { PartialPriceFeedTreeNode } from "./AbstractPriceFeed";
5
+
6
+ type abi = typeof wstEthPriceFeedAbi;
7
+
8
+ export class WstETHPriceFeedContract extends AbstractLPPriceFeedContract<abi> {
9
+ constructor(sdk: GearboxSDK, args: PartialPriceFeedTreeNode) {
10
+ super(sdk, {
11
+ ...args,
12
+ name: "WstETHPriceFeed",
13
+ abi: wstEthPriceFeedAbi,
14
+ });
15
+ }
16
+
17
+ public override async getValue(): Promise<bigint> {
18
+ return await this.sdk.provider.publicClient.readContract({
19
+ abi: iwstEthAbi,
20
+ address: this.lpContract,
21
+ functionName: "stEthPerToken",
22
+ });
23
+ }
24
+ }