|
1 | 1 | import type { Address, Hex } from "viem"; |
2 | 2 | import { decodeFunctionData } from "viem"; |
3 | 3 |
|
4 | | -import { iUpdatablePriceFeedAbi, priceOracleV3Abi } from "../abi"; |
5 | | -import type { PriceFeedTreeNode, PriceOracleData } from "../base"; |
| 4 | +import { |
| 5 | + iPriceFeedCompressorAbi, |
| 6 | + iUpdatablePriceFeedAbi, |
| 7 | + priceOracleV3Abi, |
| 8 | +} from "../abi"; |
| 9 | +import type { |
| 10 | + PriceFeedMapEntry, |
| 11 | + PriceFeedTreeNode, |
| 12 | + PriceOracleData, |
| 13 | +} from "../base"; |
6 | 14 | import { BaseContract } from "../base"; |
| 15 | +import { AP_PRICE_FEED_COMPRESSOR } from "../constants"; |
7 | 16 | import type { GearboxSDK } from "../GearboxSDK"; |
8 | 17 | import type { PriceOracleState } from "../state"; |
9 | 18 | import { AddressMap } from "../utils"; |
| 19 | +import { simulateMulticall } from "../utils/viem"; |
10 | 20 | import type { |
11 | 21 | IPriceFeedContract, |
12 | 22 | PriceFeedUsageType, |
13 | 23 | UpdatePriceFeedsResult, |
14 | 24 | } from "./pricefeeds"; |
15 | | -import { PriceFeedRef } from "./pricefeeds"; |
| 25 | +import { PriceFeedRef, rawTxToMulticallPriceUpdate } from "./pricefeeds"; |
16 | 26 |
|
17 | 27 | type abi = typeof priceOracleV3Abi; |
18 | 28 |
|
@@ -104,8 +114,8 @@ export class PriceOracleContract extends BaseContract<abi> { |
104 | 114 | const reserve = opts?.reserve ?? true; |
105 | 115 | return tokens |
106 | 116 | .flatMap(t => [ |
107 | | - main ? this.mainPriceFeeds[t].priceFeed : undefined, |
108 | | - reserve ? this.reservePriceFeeds[t].priceFeed : undefined, |
| 117 | + main ? this.mainPriceFeeds[t]?.priceFeed : undefined, |
| 118 | + reserve ? this.reservePriceFeeds[t]?.priceFeed : undefined, |
109 | 119 | ]) |
110 | 120 | .filter((f): f is IPriceFeedContract => !!f); |
111 | 121 | } |
@@ -205,83 +215,43 @@ export class PriceOracleContract extends BaseContract<abi> { |
205 | 215 | return (amount * fromPrice * toScale) / (toPrice * fromScale); |
206 | 216 | } |
207 | 217 |
|
208 | | - // async loadPrices( |
209 | | - // priceUpdatesTxs: Array<RawTx>, |
210 | | - // block: bigint, |
211 | | - // ): Promise<{ |
212 | | - // mainPrices: Record<Address, bigint>; |
213 | | - // reservePrices: Record<Address, bigint>; |
214 | | - // }> { |
215 | | - // const priceUpdateCalls: Array<MultiCallStruct> = priceUpdatesTxs.map( |
216 | | - // tx => ({ |
217 | | - // target: tx.to, |
218 | | - // callData: tx.callData, |
219 | | - // allowFailure: false, |
220 | | - // }), |
221 | | - // ); |
222 | | - |
223 | | - // const getPricesRawCalls = (reserve: boolean): Array<MultiCallStruct> => { |
224 | | - // return Object.keys( |
225 | | - // reserve ? this.reservePriceFeeds : this.mainPriceFeeds, |
226 | | - // ).map(token => ({ |
227 | | - // target: this.address, |
228 | | - // callData: encodeFunctionData({ |
229 | | - // functionName: "getPriceRaw", |
230 | | - // args: [token as Address, reserve], |
231 | | - // abi: this.abi, |
232 | | - // }), |
233 | | - // allowFailure: true, |
234 | | - // })); |
235 | | - // }; |
236 | | - |
237 | | - // const { result } = await this.v3.publicClient.simulateContract({ |
238 | | - // address: MULTICALL_ADDRESS, |
239 | | - // abi: multicall3Abi, |
240 | | - // functionName: "aggregate3", |
241 | | - // args: [ |
242 | | - // [ |
243 | | - // ...priceUpdateCalls, |
244 | | - // ...getPricesRawCalls(false), |
245 | | - // ...getPricesRawCalls(true), |
246 | | - // ], |
247 | | - // ], |
248 | | - // chain: this.v3.publicClient.chain!, |
249 | | - // account: this.v3.walletClient.account!, |
250 | | - // gas: 550_000_000n, |
251 | | - // // blockNumber: BigInt(block), |
252 | | - // }); |
253 | | - |
254 | | - // const returnRawPrices = ( |
255 | | - // result as Array<{ success: boolean; returnData: Hex }> |
256 | | - // ).slice(priceUpdateCalls.length); |
257 | | - |
258 | | - // const prices = returnRawPrices.map(callReturn => |
259 | | - // callReturn.success |
260 | | - // ? decodeFunctionResult({ |
261 | | - // functionName: "getPrice", |
262 | | - // abi: this.abi, |
263 | | - // data: callReturn.returnData! as Hex, |
264 | | - // }) |
265 | | - // : 0n, |
266 | | - // ) as Array<bigint>; |
267 | | - |
268 | | - // const mainPrices: Record<Address, bigint> = {}; |
269 | | - // const reservePrices: Record<Address, bigint> = {}; |
270 | | - |
271 | | - // const mainPFlength = Object.keys(this.mainPriceFeeds).length; |
272 | | - |
273 | | - // prices.forEach((price, i) => { |
274 | | - // if (i < mainPFlength) { |
275 | | - // mainPrices[Object.keys(this.mainPriceFeeds)[i] as Address] = price; |
276 | | - // } else { |
277 | | - // reservePrices[ |
278 | | - // Object.keys(this.reservePriceFeeds)[i - mainPFlength] as Address |
279 | | - // ] = price; |
280 | | - // } |
281 | | - // }); |
| 218 | + /** |
| 219 | + * Loads new prices for this oracle from PriceFeedCompressor |
| 220 | + * Does not update price feeds, only updates prices |
| 221 | + */ |
| 222 | + public async updatePrices(): Promise<void> { |
| 223 | + const { txs } = await this.updatePriceFeeds(); |
| 224 | + const resp = await simulateMulticall(this.provider.publicClient, { |
| 225 | + contracts: [ |
| 226 | + ...txs.map(rawTxToMulticallPriceUpdate), |
| 227 | + { |
| 228 | + abi: iPriceFeedCompressorAbi, |
| 229 | + address: this.sdk.addressProvider.getLatestVersion( |
| 230 | + AP_PRICE_FEED_COMPRESSOR, |
| 231 | + ), |
| 232 | + functionName: "getPriceFeeds", |
| 233 | + args: [this.address], |
| 234 | + }, |
| 235 | + ], |
| 236 | + allowFailure: false, |
| 237 | + gas: 550_000_000n, |
| 238 | + batchSize: 0, // we cannot have price updates and compressor request in different batches |
| 239 | + }); |
| 240 | + const [entries, tree] = resp.pop() as [ |
| 241 | + PriceFeedMapEntry[], |
| 242 | + PriceFeedTreeNode[], |
| 243 | + ]; |
282 | 244 |
|
283 | | - // return { mainPrices, reservePrices }; |
284 | | - // } |
| 245 | + entries.forEach(({ token, priceFeed, reserve }) => { |
| 246 | + const price = tree.find(n => n.baseParams.addr === priceFeed)?.answer |
| 247 | + ?.price; |
| 248 | + if (reserve && price) { |
| 249 | + this.reservePrices.upsert(token, price); |
| 250 | + } else if (price) { |
| 251 | + this.mainPrices.upsert(token, price); |
| 252 | + } |
| 253 | + }); |
| 254 | + } |
285 | 255 |
|
286 | 256 | #labelPriceFeed( |
287 | 257 | address: Address, |
|
0 commit comments