@gearbox-protocol/sdk 14.11.20 → 14.11.21

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 (27) hide show
  1. package/dist/cjs/permissionless/bindings/instance-manager.js +1 -1
  2. package/dist/cjs/permissionless/utils/price-update/get-updatable-feeds.js +2 -23
  3. package/dist/cjs/sdk/OnchainSDK.js +0 -15
  4. package/dist/cjs/sdk/market/pricefeeds/PriceFeedsRegister.js +4 -6
  5. package/dist/cjs/sdk/market/pricefeeds/PythPriceFeed.js +1 -0
  6. package/dist/cjs/sdk/market/pricefeeds/RedstonePriceFeed.js +1 -0
  7. package/dist/cjs/sdk/market/pricefeeds/updates/PythUpdater.js +4 -122
  8. package/dist/cjs/sdk/market/pricefeeds/updates/RedstoneUpdater.js +4 -196
  9. package/dist/cjs/sdk/market/pricefeeds/updates/fetchPythPayloads.js +3 -105
  10. package/dist/cjs/sdk/market/pricefeeds/updates/fetchRedstonePayloads.js +4 -126
  11. package/dist/esm/permissionless/bindings/instance-manager.js +1 -1
  12. package/dist/esm/permissionless/utils/price-update/get-updatable-feeds.js +2 -27
  13. package/dist/esm/sdk/OnchainSDK.js +0 -15
  14. package/dist/esm/sdk/market/pricefeeds/PriceFeedsRegister.js +4 -6
  15. package/dist/esm/sdk/market/pricefeeds/PythPriceFeed.js +1 -0
  16. package/dist/esm/sdk/market/pricefeeds/RedstonePriceFeed.js +1 -0
  17. package/dist/esm/sdk/market/pricefeeds/updates/PythUpdater.js +4 -122
  18. package/dist/esm/sdk/market/pricefeeds/updates/RedstoneUpdater.js +4 -196
  19. package/dist/esm/sdk/market/pricefeeds/updates/fetchPythPayloads.js +3 -109
  20. package/dist/esm/sdk/market/pricefeeds/updates/fetchRedstonePayloads.js +4 -130
  21. package/dist/types/permissionless/utils/price-update/get-updatable-feeds.d.ts +4 -3
  22. package/dist/types/sdk/market/pricefeeds/PriceFeedsRegister.d.ts +4 -5
  23. package/dist/types/sdk/market/pricefeeds/updates/PythUpdater.d.ts +5 -7
  24. package/dist/types/sdk/market/pricefeeds/updates/RedstoneUpdater.d.ts +5 -8
  25. package/dist/types/sdk/market/pricefeeds/updates/fetchPythPayloads.d.ts +2 -6
  26. package/dist/types/sdk/market/pricefeeds/updates/fetchRedstonePayloads.d.ts +2 -6
  27. package/package.json +1 -5
@@ -21,135 +21,13 @@ __export(fetchRedstonePayloads_exports, {
21
21
  fetchRedstonePayloads: () => fetchRedstonePayloads
22
22
  });
23
23
  module.exports = __toCommonJS(fetchRedstonePayloads_exports);
24
- var import_evm_connector = require("@redstone-finance/evm-connector");
25
- var import_protocol = require("@redstone-finance/protocol");
26
- var import_sdk = require("@redstone-finance/sdk");
27
- var import_utils = require("@redstone-finance/utils");
28
- var import_viem = require("viem");
29
- var import_utils2 = require("../../../utils/index.js");
30
24
  async function fetchRedstonePayloads(options) {
31
- const {
32
- dataServiceId,
33
- dataFeedsIds,
34
- uniqueSignersCount,
35
- historicalTimestampMs,
36
- gateways,
37
- failOnMissingFeeds,
38
- enableLogging,
39
- logger,
40
- returnPrices
41
- } = options;
42
- const metadataTimestampMs = historicalTimestampMs ?? options.metadataTimestampMs;
43
- const dataPackagesIds = Array.from(new Set(dataFeedsIds));
44
- if (dataPackagesIds.length === 0) {
45
- return [];
46
- }
47
- const wrapper = new import_evm_connector.DataServiceWrapper({
48
- dataServiceId,
49
- dataPackagesIds,
50
- uniqueSignersCount,
51
- authorizedSigners: (0, import_sdk.getSignersForDataServiceId)(
52
- dataServiceId
53
- ),
54
- historicalTimestamp: historicalTimestampMs,
55
- urls: gateways,
56
- ignoreMissingFeed: !failOnMissingFeeds,
57
- enableEnhancedLogs: enableLogging
58
- });
59
- if (metadataTimestampMs) {
60
- wrapper.setMetadataTimestamp(metadataTimestampMs);
61
- }
62
- const dataPayload = await (0, import_utils2.retry)(() => wrapper.prepareRedstonePayload(true), {
63
- attempts: 5,
64
- interval: historicalTimestampMs ? 30500 : 250
65
- });
66
- const parsed = import_protocol.RedstonePayload.parse((0, import_viem.toBytes)(`0x${dataPayload}`));
67
- const packagesByDataFeedId = groupDataPackages(parsed.signedDataPackages);
68
- const result = [];
69
- for (const dataFeedId of dataFeedsIds) {
70
- const signedDataPackages = packagesByDataFeedId[dataFeedId];
71
- if (!signedDataPackages) {
72
- if (failOnMissingFeeds) {
73
- throw new Error(`cannot find data packages for ${dataFeedId}`);
74
- }
75
- logger?.warn(`cannot find data packages for ${dataFeedId}`);
76
- continue;
77
- }
78
- if (signedDataPackages.length !== uniqueSignersCount) {
79
- if (failOnMissingFeeds) {
80
- throw new Error(
81
- `got ${signedDataPackages.length} data packages for ${dataFeedId}, but expected ${uniqueSignersCount}`
82
- );
83
- }
84
- logger?.warn(
85
- `got ${signedDataPackages.length} data packages for ${dataFeedId}, but expected ${uniqueSignersCount}`
86
- );
87
- continue;
88
- }
89
- result.push(
90
- getCalldataWithTimestamp(
91
- dataFeedId,
92
- signedDataPackages,
93
- wrapper.getUnsignedMetadata(),
94
- returnPrices
95
- )
25
+ for (const _feed of options.dataFeedsIds) {
26
+ throw new Error(
27
+ "RedStone price updates are no longer supported by this SDK"
96
28
  );
97
29
  }
98
- return result;
99
- }
100
- function groupDataPackages(signedDataPackages) {
101
- const packagesByDataFeedId = {};
102
- for (const p of signedDataPackages) {
103
- const { dataPoints } = p.dataPackage;
104
- const dataFeedId0 = dataPoints[0].dataFeedId;
105
- for (const dp of dataPoints) {
106
- if (dp.dataFeedId !== dataFeedId0) {
107
- throw new Error(
108
- `data package contains data points with different dataFeedIds: ${dp.dataFeedId} and ${dataFeedId0}`
109
- );
110
- }
111
- }
112
- if (!packagesByDataFeedId[dataFeedId0]) {
113
- packagesByDataFeedId[dataFeedId0] = [];
114
- }
115
- packagesByDataFeedId[dataFeedId0].push(p);
116
- }
117
- return packagesByDataFeedId;
118
- }
119
- function getCalldataWithTimestamp(dataFeedId, packages, unsignedMetadata, returnPrices) {
120
- const originalPayload = import_protocol.RedstonePayload.prepare(packages, unsignedMetadata);
121
- const originalPayloadLength = originalPayload.length / 2;
122
- const bytesToAdd = 32 - originalPayloadLength % 32;
123
- const newUnsignedMetadata = unsignedMetadata + "_".repeat(bytesToAdd);
124
- const payload = import_protocol.RedstonePayload.prepare(packages, newUnsignedMetadata);
125
- let timestamp = 0;
126
- for (const p of packages) {
127
- const newTimestamp = p.dataPackage.timestampMilliseconds / 1e3;
128
- if (timestamp === 0) {
129
- timestamp = newTimestamp;
130
- } else if (timestamp !== newTimestamp) {
131
- throw new Error("Timestamps are not equal");
132
- }
133
- }
134
- const base = {
135
- dataFeedId,
136
- data: (0, import_viem.encodeAbiParameters)(
137
- [{ type: "uint256" }, { type: "bytes" }],
138
- [BigInt(timestamp), `0x${payload}`]
139
- ),
140
- timestamp,
141
- cached: false
142
- };
143
- if (returnPrices) {
144
- const prices = packages.flatMap((p) => p.dataPackage.dataPoints).map((dp) => BigInt(`0x${Buffer.from(dp.value).toString("hex")}`));
145
- const medianPrice = BigInt(import_utils.MathUtils.getMedianOfBigNumbers(prices));
146
- return {
147
- ...base,
148
- price: medianPrice,
149
- decimals: 8
150
- };
151
- }
152
- return base;
30
+ return [];
153
31
  }
154
32
  // Annotate the CommonJS export names for ESM import in node:
155
33
  0 && (module.exports = {
@@ -16,11 +16,11 @@ import {
16
16
  json_stringify
17
17
  } from "../../sdk/index.js";
18
18
  import { Addresses } from "../deployment/addresses.js";
19
+ import { BytecodeRepositoryContract } from "./bytecode-repository.js";
19
20
  import { WithdrawalCompressorContract } from "./compressors/index.js";
20
21
  import { PriceFeedStoreContract } from "./price-feed-store.js";
21
22
  import { RoutingManagerContract } from "./router/index.js";
22
23
  import { TreasurySplitterContract } from "./treasury-splitter.js";
23
- import { BytecodeRepositoryContract } from "./bytecode-repository.js";
24
24
  const abi = instanceManagerAbi;
25
25
  class InstanceManagerContract extends BaseContract {
26
26
  constructor(addr, register) {
@@ -1,30 +1,5 @@
1
- import { getContract } from "viem";
2
- import { priceFeedCompressorAbi } from "../../../abi/compressors/priceFeedCompressor.js";
3
- import {
4
- bytes32ToString,
5
- PythPriceFeed,
6
- RedstonePriceFeedContract
7
- } from "../../../sdk/index.js";
8
- async function getUpdatablePriceFeeds(args) {
9
- const { sdk, client, pfCompressor, priceFeeds } = args;
10
- const priceFeedCompressor = getContract({
11
- address: pfCompressor,
12
- abi: priceFeedCompressorAbi,
13
- client
14
- });
15
- const updatablePriceFeeds = (await priceFeedCompressor.read.loadPriceFeedTree([
16
- priceFeeds
17
- ])).filter(
18
- (data) => ["PRICE_FEED::PYTH", "PRICE_FEED::REDSTONE"].includes(
19
- bytes32ToString(data.baseParams.contractType)
20
- )
21
- ).map((data) => {
22
- if (bytes32ToString(data.baseParams.contractType) === "PRICE_FEED::PYTH") {
23
- return new PythPriceFeed(sdk, data);
24
- }
25
- return new RedstonePriceFeedContract(sdk, data);
26
- });
27
- return updatablePriceFeeds;
1
+ async function getUpdatablePriceFeeds(_args) {
2
+ return [];
28
3
  }
29
4
  export {
30
5
  getUpdatablePriceFeeds
@@ -149,16 +149,6 @@ class OnchainSDK extends ChainContractsRegister {
149
149
  );
150
150
  this.#currentBlock = block.number;
151
151
  this.#timestamp = block.timestamp;
152
- if (blockNumber && !redstone?.historicTimestamp && time - Number(block.timestamp) * 1e3 > 60 * 1e3) {
153
- this.logger?.warn(
154
- "attaching to fixed block number, but redstone historicTimestamp is not set. price updates might fail"
155
- );
156
- }
157
- if (blockNumber && !pyth?.historicTimestamp && time - Number(block.timestamp) * 1e3 > 60 * 1e3) {
158
- this.logger?.warn(
159
- "attaching to fixed block number, but pyth historicTimestamp is not set. price updates might fail"
160
- );
161
- }
162
152
  this.#priceFeeds = new PriceFeedRegister(this, { redstone, pyth });
163
153
  this.logger?.debug(
164
154
  `attach block number ${this.currentBlock} timestamp ${this.timestamp}`
@@ -330,11 +320,6 @@ class OnchainSDK extends ChainContractsRegister {
330
320
  */
331
321
  async syncState(opts) {
332
322
  let { blockNumber, timestamp, ignoreUpdateablePrices } = opts ?? {};
333
- if (this.priceFeeds.historical && !ignoreUpdateablePrices) {
334
- this.logger?.warn(
335
- "syncState is not supported with redstone or pyth historicTimestamp"
336
- );
337
- }
338
323
  if (!blockNumber || !timestamp) {
339
324
  const block = await this.client.getBlock({
340
325
  blockTag: "latest"
@@ -27,7 +27,6 @@ import { MellowLRTPriceFeedContract } from "./MellowLRTPriceFeed.js";
27
27
  import { PendleTWAPPTPriceFeed } from "./PendleTWAPPTPriceFeed.js";
28
28
  import { PythPriceFeed } from "./PythPriceFeed.js";
29
29
  import { RedstonePriceFeedContract } from "./RedstonePriceFeed.js";
30
- import { PythUpdater, RedstoneUpdater } from "./updates/index.js";
31
30
  import { WstETHPriceFeedContract } from "./WstETHPriceFeed.js";
32
31
  import { YearnPriceFeedContract } from "./YearnPriceFeed.js";
33
32
  import { ZeroPriceFeedContract } from "./ZeroPriceFeed.js";
@@ -36,12 +35,9 @@ class PriceFeedRegister extends SDKConstruct {
36
35
  #updaters;
37
36
  #feeds = new AddressMap(void 0, "priceFeeds");
38
37
  #latestUpdate;
39
- constructor(sdk, opts = {}) {
38
+ constructor(sdk, _opts = {}) {
40
39
  super(sdk);
41
- this.#updaters = [
42
- new PythUpdater(sdk, opts?.pyth),
43
- new RedstoneUpdater(sdk, opts?.redstone)
44
- ];
40
+ this.#updaters = [];
45
41
  }
46
42
  /**
47
43
  * @internal
@@ -151,6 +147,7 @@ class PriceFeedRegister extends SDKConstruct {
151
147
  * @returns
152
148
  */
153
149
  async generateExternalPriceFeedsUpdateTxs(feeds, block) {
150
+ if (this.#updaters.length === 0) return { txs: [], timestamp: 0 };
154
151
  const [priceFeedCompressorAddress] = this.sdk.addressProvider.mustGetLatest(
155
152
  AP_PRICE_FEED_COMPRESSOR,
156
153
  VERSION_RANGE_310
@@ -225,6 +222,7 @@ class PriceFeedRegister extends SDKConstruct {
225
222
  * Discovered price feeds are not saved anywhere in PriceFeedRegister, and can later be used to load price feed updates
226
223
  */
227
224
  async getPartialUpdatablePriceFeeds(configurators) {
225
+ if (this.#updaters.length === 0) return [];
228
226
  const [priceFeedCompressorAddress] = this.sdk.addressProvider.mustGetLatest(
229
227
  AP_PRICE_FEED_COMPRESSOR,
230
228
  VERSION_RANGE_310
@@ -13,6 +13,7 @@ class PythPriceFeed extends AbstractPriceFeedContract {
13
13
  constructor(options, args) {
14
14
  super(options, {
15
15
  ...args,
16
+ updatable: false,
16
17
  name: "PythPriceFeed",
17
18
  abi
18
19
  });
@@ -13,6 +13,7 @@ class RedstonePriceFeedContract extends AbstractPriceFeedContract {
13
13
  constructor(options, args) {
14
14
  super(options, {
15
15
  ...args,
16
+ updatable: false,
16
17
  name: "RedstonePriceFeed",
17
18
  abi: redstonePriceFeedAbi
18
19
  });
@@ -1,7 +1,5 @@
1
1
  import { z } from "zod/v4";
2
2
  import { SDKConstruct } from "../../../base/index.js";
3
- import { fetchPythPayloads } from "./fetchPythPayloads.js";
4
- import { PriceUpdatesCache } from "./PriceUpdatesCache.js";
5
3
  import { PriceUpdateTx } from "./PriceUpdateTx.js";
6
4
  class PythUpdateTx extends PriceUpdateTx {
7
5
  name = "pyth";
@@ -29,131 +27,15 @@ const PythOptions = z.object({
29
27
  failOnMissingFeeds: z.boolean().optional()
30
28
  });
31
29
  class PythUpdater extends SDKConstruct {
32
- #cache;
33
- /**
34
- * Fixed pyth historic timestamp in seconds
35
- */
36
- #historicalTimestamp;
37
- #apiProxy;
38
- #failOnMissingFeeds;
39
- constructor(sdk, opts = {}) {
30
+ constructor(sdk, _opts = {}) {
40
31
  super(sdk);
41
- const { apiProxy, cacheTTL, failOnMissingFeeds, historicTimestamp } = opts;
42
- this.#failOnMissingFeeds = failOnMissingFeeds;
43
- this.#apiProxy = apiProxy;
44
- if (historicTimestamp) {
45
- this.#historicalTimestamp = historicTimestamp === true ? Number(this.sdk.timestamp) : historicTimestamp;
46
- this.logger?.debug(
47
- `using historical timestamp ${this.#historicalTimestamp}`
48
- );
49
- }
50
- this.#cache = opts.cache ?? new PriceUpdatesCache({
51
- ttl: cacheTTL ?? 225 * 1e3,
52
- historical: !!historicTimestamp
53
- });
54
32
  }
55
- async getUpdateTxs(feeds) {
56
- if (feeds.length === 0) {
57
- return [];
58
- }
59
- this.logger?.debug(
60
- `generating update transactions for ${feeds.length} pyth price feeds`
61
- );
62
- const pythFeeds = new Map(
63
- feeds.filter(isPyth).map((f) => [f.priceFeedId, f])
64
- );
65
- const payloads = await this.#getPayloads(new Set(pythFeeds.keys()));
66
- let [minTimestamp, maxTimestamp] = [Number.POSITIVE_INFINITY, 0];
67
- const results = [];
68
- for (const p of payloads) {
69
- const priceFeed = pythFeeds.get(p.dataFeedId);
70
- if (!priceFeed) {
71
- throw new Error(`cannot find price feed for ${p.dataFeedId}`);
72
- }
73
- const { dataFeedId, timestamp, cached, data } = p;
74
- minTimestamp = Math.min(minTimestamp, timestamp);
75
- maxTimestamp = Math.max(maxTimestamp, timestamp);
76
- results.push(
77
- new PythUpdateTx(priceFeed.createPriceUpdateTx(data), {
78
- dataFeedId,
79
- priceFeed: priceFeed.address,
80
- timestamp,
81
- cached
82
- })
83
- );
84
- }
85
- let tsRange = "";
86
- if (results.length) {
87
- const minDelta = BigInt(minTimestamp) - this.sdk.timestamp;
88
- tsRange = `, timestamps ${minTimestamp} (${minDelta})`;
89
- if (minTimestamp !== maxTimestamp) {
90
- const maxDelta = BigInt(maxTimestamp) - this.sdk.timestamp;
91
- tsRange = `${tsRange} - ${maxTimestamp} (${maxDelta})`;
92
- }
93
- }
94
- this.logger?.debug(
95
- `generated ${results.length} update transactions for pyth price feeds: ${Array.from(pythFeeds.keys()).join(", ")}${tsRange}`
96
- );
97
- return results;
33
+ async getUpdateTxs(_feeds) {
34
+ return [];
98
35
  }
99
36
  get historical() {
100
- return !!this.#historicalTimestamp;
101
- }
102
- /**
103
- * Gets pyth payloads
104
- * @param dataFeedsIds
105
- * @returns
106
- */
107
- async #getPayloads(dataFeedsIds) {
108
- this.logger?.debug(
109
- `getting pyth payloads for ${dataFeedsIds.size} price feeds: ${Array.from(dataFeedsIds).join(", ")}`
110
- );
111
- const fromCache = [];
112
- const uncached = [];
113
- for (const priceFeedsId of dataFeedsIds) {
114
- const cached = this.#cache.get(priceFeedsId);
115
- if (cached) {
116
- fromCache.push({ ...cached, cached: true });
117
- } else {
118
- uncached.push(priceFeedsId);
119
- }
120
- }
121
- const fromPyth = await this.#fetchPayloads(
122
- new Set(uncached)
123
- );
124
- for (const resp of fromPyth) {
125
- this.#cache.set(resp, resp.dataFeedId);
126
- }
127
- this.logger?.debug(
128
- `got ${fromPyth.length} new pyth updates and ${fromCache.length} from cache`
129
- );
130
- return [...fromCache, ...fromPyth];
37
+ return false;
131
38
  }
132
- /**
133
- * Fetches pyth payloads from Hermes API
134
- * @param dataFeedsIds
135
- * @returns
136
- */
137
- async #fetchPayloads(dataFeedsIds) {
138
- if (dataFeedsIds.size === 0) {
139
- return [];
140
- }
141
- const ids = Array.from(dataFeedsIds);
142
- const tsStr = this.#historicalTimestamp ? ` with historical timestamp ${this.#historicalTimestamp}` : "";
143
- this.logger?.debug(
144
- `fetching pyth payloads for ${dataFeedsIds.size} price feeds: ${ids.join(", ")}${tsStr}`
145
- );
146
- return fetchPythPayloads({
147
- dataFeedsIds,
148
- historicalTimestampSeconds: this.#historicalTimestamp,
149
- apiProxy: this.#apiProxy,
150
- failOnMissingFeeds: this.#failOnMissingFeeds,
151
- logger: this.logger
152
- });
153
- }
154
- }
155
- function isPyth(pf) {
156
- return pf.contractType === "PRICE_FEED::PYTH";
157
39
  }
158
40
  export {
159
41
  PythOptions,
@@ -1,8 +1,5 @@
1
1
  import { z } from "zod/v4";
2
2
  import { SDKConstruct } from "../../../base/index.js";
3
- import { AddressMap } from "../../../utils/index.js";
4
- import { fetchRedstonePayloads } from "./fetchRedstonePayloads.js";
5
- import { PriceUpdatesCache } from "./PriceUpdatesCache.js";
6
3
  import { PriceUpdateTx } from "./PriceUpdateTx.js";
7
4
  class RedstoneUpdateTx extends PriceUpdateTx {
8
5
  name = "redstone";
@@ -34,204 +31,15 @@ const RedstoneOptions = z.object({
34
31
  enableLogging: z.boolean().optional()
35
32
  });
36
33
  class RedstoneUpdater extends SDKConstruct {
37
- #cache;
38
- #historicalTimestampMs;
39
- #gateways;
40
- #failOnMissingFeeds;
41
- #enableLogging;
42
- constructor(sdk, opts = {}) {
34
+ constructor(sdk, _opts = {}) {
43
35
  super(sdk);
44
- this.#failOnMissingFeeds = opts.failOnMissingFeeds;
45
- this.#enableLogging = opts.enableLogging;
46
- this.#gateways = opts.gateways?.length ? opts.gateways : void 0;
47
- let ts = opts.historicTimestamp;
48
- if (ts) {
49
- ts = ts === true ? Number(this.sdk.timestamp) * 1e3 : ts;
50
- this.#historicalTimestampMs = 6e4 * Math.floor(ts / 6e4);
51
- this.logger?.debug(
52
- `using historical timestamp ${this.#historicalTimestampMs}`
53
- );
54
- }
55
- this.#cache = opts.cache ?? new PriceUpdatesCache({
56
- ttl: opts.cacheTTL ?? 225 * 1e3,
57
- historical: !!ts
58
- });
59
36
  }
60
- async getUpdateTxs(feeds) {
61
- if (feeds.length === 0) {
62
- return [];
63
- }
64
- this.logger?.debug(
65
- `generating update transactions for ${feeds.length} redstone price feeds`
66
- );
67
- const groupedFeeds = {};
68
- const priceFeeds = /* @__PURE__ */ new Map();
69
- for (const feed of feeds) {
70
- if (!isRedstone(feed)) {
71
- continue;
72
- }
73
- const key = `${feed.dataServiceId}:${feed.signersThreshold}`;
74
- if (!groupedFeeds[key]) {
75
- groupedFeeds[key] = /* @__PURE__ */ new Set();
76
- }
77
- groupedFeeds[key].add(feed.dataId);
78
- const pfsForDataId = priceFeeds.get(feed.dataId) ?? new AddressMap();
79
- pfsForDataId.upsert(feed.address, feed);
80
- priceFeeds.set(feed.dataId, pfsForDataId);
81
- }
82
- const results = [];
83
- let [minTimestamp, maxTimestamp] = [Number.POSITIVE_INFINITY, 0];
84
- for (const [key, group] of Object.entries(groupedFeeds)) {
85
- const [dataServiceId, signersStr] = key.split(":");
86
- const uniqueSignersCount = parseInt(signersStr, 10);
87
- const payloads = await this.#safeGetPayloads(
88
- dataServiceId,
89
- group,
90
- uniqueSignersCount
91
- );
92
- for (const { dataFeedId, data, timestamp, cached } of payloads) {
93
- const pfsForDataId = priceFeeds.get(dataFeedId);
94
- if (!pfsForDataId) {
95
- throw new Error(`cannot get price feed addresses for ${dataFeedId}`);
96
- }
97
- for (const priceFeed of pfsForDataId.values()) {
98
- minTimestamp = Math.min(minTimestamp, timestamp);
99
- maxTimestamp = Math.max(maxTimestamp, timestamp);
100
- results.push(
101
- new RedstoneUpdateTx(priceFeed.createPriceUpdateTx(data), {
102
- dataFeedId,
103
- dataServiceId,
104
- priceFeed: priceFeed.address,
105
- timestamp,
106
- cached
107
- })
108
- );
109
- }
110
- }
111
- }
112
- let tsRange = "";
113
- if (results.length) {
114
- const minDelta = BigInt(minTimestamp) - this.sdk.timestamp;
115
- tsRange = `, timestamps ${minTimestamp} (${minDelta})`;
116
- if (minTimestamp !== maxTimestamp) {
117
- const maxDelta = BigInt(maxTimestamp) - this.sdk.timestamp;
118
- tsRange = `${tsRange} - ${maxTimestamp} (${maxDelta})`;
119
- }
120
- }
121
- this.logger?.debug(
122
- `generated ${results.length} update transactions for redstone price feeds: ${Array.from(priceFeeds.keys()).join(", ")}${tsRange}`
123
- );
124
- return results;
37
+ async getUpdateTxs(_feeds) {
38
+ return [];
125
39
  }
126
40
  get historical() {
127
- return !!this.#historicalTimestampMs;
41
+ return false;
128
42
  }
129
- /**
130
- * Gets payloads, retries once if it has expired while inflight
131
- * @param dataServiceId
132
- * @param dataFeedsIds
133
- * @param uniqueSignersCount
134
- * @returns
135
- */
136
- async #safeGetPayloads(dataServiceId, dataFeedsIds, uniqueSignersCount) {
137
- let result = await this.#getPayloads(
138
- dataServiceId,
139
- dataFeedsIds,
140
- uniqueSignersCount
141
- );
142
- if (this.#historicalTimestampMs) {
143
- return result;
144
- }
145
- let expired = false;
146
- for (const { timestamp, dataFeedId } of result) {
147
- const delta = Number(this.sdk.timestamp) - timestamp;
148
- if (delta >= 240 && delta < 255) {
149
- this.logger?.warn(
150
- `payload for ${dataFeedId} has expired by ${delta} seconds`
151
- );
152
- expired = true;
153
- }
154
- }
155
- if (expired) {
156
- result = await this.#getPayloads(
157
- dataServiceId,
158
- dataFeedsIds,
159
- uniqueSignersCount
160
- );
161
- }
162
- return result;
163
- }
164
- /**
165
- * Gets redstone payloads in one request for multiple feeds with the same dataServiceId and uniqueSignersCount
166
- * If historicalTimestamp is set, responses will be cached
167
- * @param dataServiceId
168
- * @param dataFeedsIds
169
- * @param uniqueSignersCount
170
- * @returns
171
- */
172
- async #getPayloads(dataServiceId, dataFeedsIds, uniqueSignersCount) {
173
- this.logger?.debug(
174
- `getting redstone payloads for ${dataFeedsIds.size} data feeds in ${dataServiceId} with ${uniqueSignersCount} signers: ${Array.from(dataFeedsIds).join(", ")}`
175
- );
176
- const fromCache = [];
177
- const uncached = [];
178
- for (const dataFeedId of dataFeedsIds) {
179
- const cached = this.#cache.get(
180
- dataServiceId,
181
- dataFeedId,
182
- uniqueSignersCount
183
- );
184
- if (cached) {
185
- fromCache.push({ ...cached, cached: true });
186
- } else {
187
- uncached.push(dataFeedId);
188
- }
189
- }
190
- const fromRedstone = await this.#fetchPayloads(
191
- dataServiceId,
192
- new Set(uncached),
193
- uniqueSignersCount
194
- );
195
- for (const resp of fromRedstone) {
196
- this.#cache.set(resp, dataServiceId, resp.dataFeedId, uniqueSignersCount);
197
- }
198
- this.logger?.debug(
199
- `got ${fromRedstone.length} new redstone updates and ${fromCache.length} from cache`
200
- );
201
- return [...fromCache, ...fromRedstone];
202
- }
203
- /**
204
- * Fetches redstone payloads in one request for multiple feeds with the same dataServiceId and uniqueSignersCount
205
- * Payloads are loaded in one request to avoid redstone rate limit
206
- * @param dataServiceId
207
- * @param dataFeedsIds
208
- * @param uniqueSignersCount
209
- * @returns
210
- */
211
- async #fetchPayloads(dataServiceId, dataFeedsIds, uniqueSignersCount) {
212
- if (dataFeedsIds.size === 0) {
213
- return [];
214
- }
215
- const dataPackagesIds = Array.from(dataFeedsIds);
216
- const tsStr = this.#historicalTimestampMs ? ` with historical timestamp ${this.#historicalTimestampMs}` : "";
217
- this.logger?.debug(
218
- `fetching redstone payloads for ${dataFeedsIds.size} data feeds in ${dataServiceId} with ${uniqueSignersCount} signers: ${dataPackagesIds.join(", ")}${tsStr}`
219
- );
220
- return fetchRedstonePayloads({
221
- dataServiceId,
222
- dataFeedsIds,
223
- uniqueSignersCount,
224
- historicalTimestampMs: this.#historicalTimestampMs,
225
- gateways: this.#gateways,
226
- failOnMissingFeeds: this.#failOnMissingFeeds,
227
- enableLogging: this.#enableLogging,
228
- logger: this.logger,
229
- metadataTimestampMs: Number(this.sdk.timestamp) * 1e3
230
- });
231
- }
232
- }
233
- function isRedstone(pf) {
234
- return pf.contractType === "PRICE_FEED::REDSTONE";
235
43
  }
236
44
  export {
237
45
  RedstoneOptions,