@gearbox-protocol/sdk 17.1.0-next.2 → 17.1.0-next.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.
- package/dist/cjs/onchain/MultichainSDK.js +2 -27
- package/dist/cjs/onchain/OnchainSDK.js +5 -6
- package/dist/cjs/onchain/accounts/intents/borrow.js +47 -20
- package/dist/cjs/onchain/accounts/intents/guards.js +6 -4
- package/dist/cjs/onchain/accounts/intents/index.js +40 -9
- package/dist/cjs/onchain/accounts/intents/open-strategy.js +49 -17
- package/dist/cjs/onchain/accounts/intents/realize.js +55 -24
- package/dist/cjs/onchain/index.js +0 -5
- package/dist/cjs/onchain/market/credit/CreditSuite.js +6 -5
- package/dist/cjs/onchain/market/index.js +0 -5
- package/dist/cjs/onchain/market/pricefeeds/feeds/RedstonePriceFeed.js +1 -7
- package/dist/cjs/onchain/market/pricefeeds/index.js +0 -5
- package/dist/cjs/onchain/market/pricefeeds/updates/UpdatablePriceFeedRegistry.js +5 -5
- package/dist/cjs/onchain/market/pricefeeds/updates/index.js +0 -5
- package/dist/cjs/onchain/options.js +1 -7
- package/dist/cjs/permissionless/index.js +1 -5
- package/dist/cjs/permissionless/utils/index.js +1 -5
- package/dist/cjs/permissionless/utils/price-update/get-price-update-tx.js +5 -0
- package/dist/cjs/permissionless/utils/price-update/get-updatable-feeds.js +6 -4
- package/dist/cjs/permissionless/utils/price-update/index.js +1 -5
- package/dist/cjs/sdk/prepare/PrepareApi.js +83 -32
- package/dist/esm/onchain/MultichainSDK.js +2 -27
- package/dist/esm/onchain/OnchainSDK.js +5 -6
- package/dist/esm/onchain/accounts/intents/borrow.js +47 -20
- package/dist/esm/onchain/accounts/intents/guards.js +6 -4
- package/dist/esm/onchain/accounts/intents/index.js +40 -9
- package/dist/esm/onchain/accounts/intents/open-strategy.js +49 -17
- package/dist/esm/onchain/accounts/intents/realize.js +55 -24
- package/dist/esm/onchain/index.js +1 -3
- package/dist/esm/onchain/market/credit/CreditSuite.js +6 -5
- package/dist/esm/onchain/market/index.js +1 -3
- package/dist/esm/onchain/market/pricefeeds/feeds/RedstonePriceFeed.js +1 -7
- package/dist/esm/onchain/market/pricefeeds/index.js +1 -3
- package/dist/esm/onchain/market/pricefeeds/updates/UpdatablePriceFeedRegistry.js +5 -5
- package/dist/esm/onchain/market/pricefeeds/updates/index.js +1 -3
- package/dist/esm/onchain/options.js +1 -7
- package/dist/esm/permissionless/index.js +2 -3
- package/dist/esm/permissionless/utils/index.js +2 -3
- package/dist/esm/permissionless/utils/price-update/get-price-update-tx.js +5 -0
- package/dist/esm/permissionless/utils/price-update/get-updatable-feeds.js +6 -4
- package/dist/esm/permissionless/utils/price-update/index.js +2 -3
- package/dist/esm/sdk/prepare/PrepareApi.js +83 -32
- package/dist/types/onchain/MultichainSDK.d.ts +0 -10
- package/dist/types/onchain/OnchainSDK.d.ts +0 -10
- package/dist/types/onchain/accounts/index.d.ts +2 -2
- package/dist/types/onchain/accounts/intents/borrow.d.ts +5 -0
- package/dist/types/onchain/accounts/intents/guards.d.ts +6 -4
- package/dist/types/onchain/accounts/intents/index.d.ts +4 -4
- package/dist/types/onchain/accounts/intents/open-strategy.d.ts +5 -0
- package/dist/types/onchain/accounts/intents/realize.d.ts +5 -0
- package/dist/types/onchain/accounts/intents/types.d.ts +49 -6
- package/dist/types/onchain/index.d.ts +4 -6
- package/dist/types/onchain/market/credit/CreditSuite.d.ts +10 -0
- package/dist/types/onchain/market/index.d.ts +3 -5
- package/dist/types/onchain/market/pricefeeds/feeds/RedstonePriceFeed.d.ts +1 -4
- package/dist/types/onchain/market/pricefeeds/index.d.ts +3 -5
- package/dist/types/onchain/market/pricefeeds/updates/UpdatablePriceFeedRegistry.d.ts +4 -4
- package/dist/types/onchain/market/pricefeeds/updates/index.d.ts +3 -5
- package/dist/types/onchain/market/pricefeeds/updates/types.d.ts +2 -16
- package/dist/types/onchain/options.d.ts +0 -7
- package/dist/types/permissionless/index.d.ts +2 -3
- package/dist/types/permissionless/utils/index.d.ts +2 -3
- package/dist/types/permissionless/utils/price-update/get-price-update-tx.d.ts +5 -0
- package/dist/types/permissionless/utils/price-update/get-updatable-feeds.d.ts +9 -3
- package/dist/types/permissionless/utils/price-update/index.d.ts +2 -3
- package/dist/types/sdk/index.d.ts +2 -2
- package/dist/types/sdk/prepare/PrepareApi.d.ts +16 -14
- package/dist/types/sdk/prepare/index.d.ts +2 -2
- package/dist/types/sdk/prepare/types.d.ts +21 -14
- package/package.json +1 -5
- package/dist/cjs/onchain/market/pricefeeds/updates/RedstoneUpdater.js +0 -193
- package/dist/cjs/onchain/market/pricefeeds/updates/fetchRedstonePayloads.js +0 -95
- package/dist/cjs/permissionless/utils/price-update/get-price-feeds.js +0 -60
- package/dist/esm/onchain/market/pricefeeds/updates/RedstoneUpdater.js +0 -191
- package/dist/esm/onchain/market/pricefeeds/updates/fetchRedstonePayloads.js +0 -94
- package/dist/esm/permissionless/utils/price-update/get-price-feeds.js +0 -57
- package/dist/types/onchain/market/pricefeeds/updates/RedstoneUpdater.d.ts +0 -37
- package/dist/types/onchain/market/pricefeeds/updates/fetchRedstonePayloads.d.ts +0 -62
- package/dist/types/permissionless/utils/price-update/get-price-feeds.d.ts +0 -22
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_onchain_constants_address_provider = require("../../../onchain/constants/address-provider.js");
|
|
3
|
-
const require_onchain_OnchainSDK = require("../../../onchain/OnchainSDK.js");
|
|
4
|
-
require("../../../onchain/index.js");
|
|
5
|
-
const require_permissionless_bindings_address_provider = require("../../bindings/address-provider.js");
|
|
6
|
-
require("../../deployment/addresses.js");
|
|
7
|
-
const require_permissionless_utils_format = require("../format.js");
|
|
8
|
-
require("../../bindings/index.js");
|
|
9
|
-
const require_permissionless_utils_price_update_get_updatable_feeds = require("./get-updatable-feeds.js");
|
|
10
|
-
//#region src/permissionless/utils/price-update/get-price-feeds.ts
|
|
11
|
-
/**
|
|
12
|
-
* @deprecated This helper will be removed in the next releases.
|
|
13
|
-
*/
|
|
14
|
-
function getCallTouchedPriceFeeds(parsedCall) {
|
|
15
|
-
const priceFeeds = [];
|
|
16
|
-
const deepParsedArgs = require_permissionless_utils_format.deepJsonParse(parsedCall.args);
|
|
17
|
-
function searchForPriceFeeds(obj) {
|
|
18
|
-
if (obj === null || obj === void 0) return;
|
|
19
|
-
if (Array.isArray(obj)) {
|
|
20
|
-
obj.forEach((item) => {
|
|
21
|
-
searchForPriceFeeds(item);
|
|
22
|
-
});
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
if (typeof obj === "object") for (const [key, value] of Object.entries(obj)) {
|
|
26
|
-
if (key === "priceFeed" || key === "underlyingPriceFeed") priceFeeds.push(value);
|
|
27
|
-
searchForPriceFeeds(value);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
searchForPriceFeeds(deepParsedArgs);
|
|
31
|
-
return priceFeeds;
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* @deprecated This helper will be removed in the next releases.
|
|
35
|
-
*/
|
|
36
|
-
function getCallsTouchedPriceFeeds(parsedCalls) {
|
|
37
|
-
return parsedCalls.flatMap((call) => getCallTouchedPriceFeeds(call));
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* @deprecated This helper will be removed in the next releases.
|
|
41
|
-
*/
|
|
42
|
-
async function getCallsTouchedUpdatablePriceFeeds({ parsedCalls, client, gasLimit }) {
|
|
43
|
-
const pfCompressor = await new require_permissionless_bindings_address_provider.AddressProviderContract("0xF7f0a609BfAb9a0A98786951ef10e5FE26cC1E38", client).getAddressOrRevert(require_onchain_constants_address_provider.AP_PRICE_FEED_COMPRESSOR, 310n);
|
|
44
|
-
const gearboxClient = client;
|
|
45
|
-
const chain = gearboxClient.chain;
|
|
46
|
-
if (!chain) throw new Error("Chain not defined on client");
|
|
47
|
-
const sdk = new require_onchain_OnchainSDK.OnchainSDK(chain.network, { client: gearboxClient }, { gasLimit });
|
|
48
|
-
await sdk.attach({ marketConfigurators: [] });
|
|
49
|
-
const touchedFeeds = parsedCalls.flatMap((call) => getCallTouchedPriceFeeds(call));
|
|
50
|
-
return (await require_permissionless_utils_price_update_get_updatable_feeds.getUpdatablePriceFeeds({
|
|
51
|
-
sdk,
|
|
52
|
-
client,
|
|
53
|
-
pfCompressor,
|
|
54
|
-
priceFeeds: touchedFeeds
|
|
55
|
-
})).map((feed) => feed.address);
|
|
56
|
-
}
|
|
57
|
-
//#endregion
|
|
58
|
-
exports.getCallTouchedPriceFeeds = getCallTouchedPriceFeeds;
|
|
59
|
-
exports.getCallsTouchedPriceFeeds = getCallsTouchedPriceFeeds;
|
|
60
|
-
exports.getCallsTouchedUpdatablePriceFeeds = getCallsTouchedUpdatablePriceFeeds;
|
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
import { AddressMap } from "../../../utils/AddressMap.js";
|
|
2
|
-
import "../../../utils/index.js";
|
|
3
|
-
import { SDKConstruct } from "../../../base/SDKConstruct.js";
|
|
4
|
-
import "../../../base/index.js";
|
|
5
|
-
import { fetchRedstonePayloads } from "./fetchRedstonePayloads.js";
|
|
6
|
-
import { PriceUpdatesCache } from "./PriceUpdatesCache.js";
|
|
7
|
-
import { PriceUpdateTx } from "./PriceUpdateTx.js";
|
|
8
|
-
import { z } from "zod/v4";
|
|
9
|
-
//#region src/onchain/market/pricefeeds/updates/RedstoneUpdater.ts
|
|
10
|
-
var RedstoneUpdateTx = class extends PriceUpdateTx {
|
|
11
|
-
name = "redstone";
|
|
12
|
-
};
|
|
13
|
-
const RedstoneOptions = z.object({
|
|
14
|
-
/**
|
|
15
|
-
* Fixed redstone historic timestamp in ms
|
|
16
|
-
* Set to true to enable redstone historical mode using timestamp from attach block
|
|
17
|
-
*/
|
|
18
|
-
historicTimestamp: z.union([z.number().nonnegative(), z.literal(true)]).optional(),
|
|
19
|
-
/**
|
|
20
|
-
* Override redstone gateways. Can be used to set caching proxies, to avoid rate limiting
|
|
21
|
-
*/
|
|
22
|
-
gateways: z.array(z.url()).optional(),
|
|
23
|
-
/**
|
|
24
|
-
* TTL for redstone cache in milliseconds
|
|
25
|
-
* If 0, disables caching
|
|
26
|
-
* If not set, uses some default value
|
|
27
|
-
* Cache is always enabled in historical mode
|
|
28
|
-
*/
|
|
29
|
-
cacheTTL: z.number().nonnegative().optional(),
|
|
30
|
-
/**
|
|
31
|
-
* When true, an error will be thrown when redstone is unable to fetch data for some feeds
|
|
32
|
-
*/
|
|
33
|
-
failOnMissingFeeds: z.boolean().optional(),
|
|
34
|
-
/**
|
|
35
|
-
* Enable redstone internal logging
|
|
36
|
-
*/
|
|
37
|
-
enableLogging: z.boolean().optional()
|
|
38
|
-
});
|
|
39
|
-
/**
|
|
40
|
-
* Class to update multiple redstone price feeds at once
|
|
41
|
-
*/
|
|
42
|
-
var RedstoneUpdater = class extends SDKConstruct {
|
|
43
|
-
#cache;
|
|
44
|
-
#historicalTimestampMs;
|
|
45
|
-
#gateways;
|
|
46
|
-
#failOnMissingFeeds;
|
|
47
|
-
#enableLogging;
|
|
48
|
-
constructor(sdk, opts = {}) {
|
|
49
|
-
super(sdk);
|
|
50
|
-
this.#failOnMissingFeeds = opts.failOnMissingFeeds;
|
|
51
|
-
this.#enableLogging = opts.enableLogging;
|
|
52
|
-
this.#gateways = opts.gateways?.length ? opts.gateways : void 0;
|
|
53
|
-
let ts = opts.historicTimestamp;
|
|
54
|
-
if (ts) {
|
|
55
|
-
ts = ts === true ? Number(this.sdk.timestamp) * 1e3 : ts;
|
|
56
|
-
this.#historicalTimestampMs = 6e4 * Math.floor(ts / 6e4);
|
|
57
|
-
this.logger?.debug(`using historical timestamp ${this.#historicalTimestampMs}`);
|
|
58
|
-
}
|
|
59
|
-
this.#cache = opts.cache ?? new PriceUpdatesCache({
|
|
60
|
-
ttl: opts.cacheTTL ?? 225e3,
|
|
61
|
-
historical: !!ts
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
async getUpdateTxs(feeds) {
|
|
65
|
-
if (feeds.length === 0) return [];
|
|
66
|
-
this.logger?.debug(`generating update transactions for ${feeds.length} redstone price feeds`);
|
|
67
|
-
const groupedFeeds = {};
|
|
68
|
-
const priceFeeds = /* @__PURE__ */ new Map();
|
|
69
|
-
for (const feed of feeds) {
|
|
70
|
-
if (!isRedstone(feed)) continue;
|
|
71
|
-
const key = `${feed.dataServiceId}:${feed.signersThreshold}`;
|
|
72
|
-
if (!groupedFeeds[key]) groupedFeeds[key] = /* @__PURE__ */ new Set();
|
|
73
|
-
groupedFeeds[key].add(feed.dataId);
|
|
74
|
-
const pfsForDataId = priceFeeds.get(feed.dataId) ?? new AddressMap();
|
|
75
|
-
pfsForDataId.upsert(feed.address, feed);
|
|
76
|
-
priceFeeds.set(feed.dataId, pfsForDataId);
|
|
77
|
-
}
|
|
78
|
-
const results = [];
|
|
79
|
-
let [minTimestamp, maxTimestamp] = [Number.POSITIVE_INFINITY, 0];
|
|
80
|
-
for (const [key, group] of Object.entries(groupedFeeds)) {
|
|
81
|
-
const [dataServiceId, signersStr] = key.split(":");
|
|
82
|
-
const uniqueSignersCount = parseInt(signersStr, 10);
|
|
83
|
-
const payloads = await this.#safeGetPayloads(dataServiceId, group, uniqueSignersCount);
|
|
84
|
-
for (const { dataFeedId, data, timestamp, cached } of payloads) {
|
|
85
|
-
const pfsForDataId = priceFeeds.get(dataFeedId);
|
|
86
|
-
if (!pfsForDataId) throw new Error(`cannot get price feed addresses for ${dataFeedId}`);
|
|
87
|
-
for (const priceFeed of pfsForDataId.values()) {
|
|
88
|
-
minTimestamp = Math.min(minTimestamp, timestamp);
|
|
89
|
-
maxTimestamp = Math.max(maxTimestamp, timestamp);
|
|
90
|
-
results.push(new RedstoneUpdateTx(priceFeed.createPriceUpdateTx(data), {
|
|
91
|
-
dataFeedId,
|
|
92
|
-
dataServiceId,
|
|
93
|
-
priceFeed: priceFeed.address,
|
|
94
|
-
timestamp,
|
|
95
|
-
cached
|
|
96
|
-
}));
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
let tsRange = "";
|
|
101
|
-
if (results.length) {
|
|
102
|
-
const minDelta = BigInt(minTimestamp) - this.sdk.timestamp;
|
|
103
|
-
tsRange = `, timestamps ${minTimestamp} (${minDelta})`;
|
|
104
|
-
if (minTimestamp !== maxTimestamp) {
|
|
105
|
-
const maxDelta = BigInt(maxTimestamp) - this.sdk.timestamp;
|
|
106
|
-
tsRange = `${tsRange} - ${maxTimestamp} (${maxDelta})`;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
this.logger?.debug(`generated ${results.length} update transactions for redstone price feeds: ${Array.from(priceFeeds.keys()).join(", ")}${tsRange}`);
|
|
110
|
-
return results;
|
|
111
|
-
}
|
|
112
|
-
get historical() {
|
|
113
|
-
return !!this.#historicalTimestampMs;
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Gets payloads, retries once if it has expired while inflight
|
|
117
|
-
* @param dataServiceId
|
|
118
|
-
* @param dataFeedsIds
|
|
119
|
-
* @param uniqueSignersCount
|
|
120
|
-
* @returns
|
|
121
|
-
*/
|
|
122
|
-
async #safeGetPayloads(dataServiceId, dataFeedsIds, uniqueSignersCount) {
|
|
123
|
-
let result = await this.#getPayloads(dataServiceId, dataFeedsIds, uniqueSignersCount);
|
|
124
|
-
if (this.#historicalTimestampMs) return result;
|
|
125
|
-
let expired = false;
|
|
126
|
-
for (const { timestamp, dataFeedId } of result) {
|
|
127
|
-
const delta = Number(this.sdk.timestamp) - timestamp;
|
|
128
|
-
if (delta >= 240 && delta < 255) {
|
|
129
|
-
this.logger?.warn(`payload for ${dataFeedId} has expired by ${delta} seconds`);
|
|
130
|
-
expired = true;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
if (expired) result = await this.#getPayloads(dataServiceId, dataFeedsIds, uniqueSignersCount);
|
|
134
|
-
return result;
|
|
135
|
-
}
|
|
136
|
-
/**
|
|
137
|
-
* Gets redstone payloads in one request for multiple feeds with the same dataServiceId and uniqueSignersCount
|
|
138
|
-
* If historicalTimestamp is set, responses will be cached
|
|
139
|
-
* @param dataServiceId
|
|
140
|
-
* @param dataFeedsIds
|
|
141
|
-
* @param uniqueSignersCount
|
|
142
|
-
* @returns
|
|
143
|
-
*/
|
|
144
|
-
async #getPayloads(dataServiceId, dataFeedsIds, uniqueSignersCount) {
|
|
145
|
-
this.logger?.debug(`getting redstone payloads for ${dataFeedsIds.size} data feeds in ${dataServiceId} with ${uniqueSignersCount} signers: ${Array.from(dataFeedsIds).join(", ")}`);
|
|
146
|
-
const fromCache = [];
|
|
147
|
-
const uncached = [];
|
|
148
|
-
for (const dataFeedId of dataFeedsIds) {
|
|
149
|
-
const cached = this.#cache.get(dataServiceId, dataFeedId, uniqueSignersCount);
|
|
150
|
-
if (cached) fromCache.push({
|
|
151
|
-
...cached,
|
|
152
|
-
cached: true
|
|
153
|
-
});
|
|
154
|
-
else uncached.push(dataFeedId);
|
|
155
|
-
}
|
|
156
|
-
const fromRedstone = await this.#fetchPayloads(dataServiceId, new Set(uncached), uniqueSignersCount);
|
|
157
|
-
for (const resp of fromRedstone) this.#cache.set(resp, dataServiceId, resp.dataFeedId, uniqueSignersCount);
|
|
158
|
-
this.logger?.debug(`got ${fromRedstone.length} new redstone updates and ${fromCache.length} from cache`);
|
|
159
|
-
return [...fromCache, ...fromRedstone];
|
|
160
|
-
}
|
|
161
|
-
/**
|
|
162
|
-
* Fetches redstone payloads in one request for multiple feeds with the same dataServiceId and uniqueSignersCount
|
|
163
|
-
* Payloads are loaded in one request to avoid redstone rate limit
|
|
164
|
-
* @param dataServiceId
|
|
165
|
-
* @param dataFeedsIds
|
|
166
|
-
* @param uniqueSignersCount
|
|
167
|
-
* @returns
|
|
168
|
-
*/
|
|
169
|
-
async #fetchPayloads(dataServiceId, dataFeedsIds, uniqueSignersCount) {
|
|
170
|
-
if (dataFeedsIds.size === 0) return [];
|
|
171
|
-
const dataPackagesIds = Array.from(dataFeedsIds);
|
|
172
|
-
const tsStr = this.#historicalTimestampMs ? ` with historical timestamp ${this.#historicalTimestampMs}` : "";
|
|
173
|
-
this.logger?.debug(`fetching redstone payloads for ${dataFeedsIds.size} data feeds in ${dataServiceId} with ${uniqueSignersCount} signers: ${dataPackagesIds.join(", ")}${tsStr}`);
|
|
174
|
-
return fetchRedstonePayloads({
|
|
175
|
-
dataServiceId,
|
|
176
|
-
dataFeedsIds,
|
|
177
|
-
uniqueSignersCount,
|
|
178
|
-
historicalTimestampMs: this.#historicalTimestampMs,
|
|
179
|
-
gateways: this.#gateways,
|
|
180
|
-
failOnMissingFeeds: this.#failOnMissingFeeds,
|
|
181
|
-
enableLogging: this.#enableLogging,
|
|
182
|
-
logger: this.logger,
|
|
183
|
-
metadataTimestampMs: Number(this.sdk.timestamp) * 1e3
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
};
|
|
187
|
-
function isRedstone(pf) {
|
|
188
|
-
return pf.contractType === "PRICE_FEED::REDSTONE";
|
|
189
|
-
}
|
|
190
|
-
//#endregion
|
|
191
|
-
export { RedstoneOptions, RedstoneUpdater };
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import { retry } from "../../../utils/retry.js";
|
|
2
|
-
import "../../../utils/index.js";
|
|
3
|
-
import { encodeAbiParameters, toBytes } from "viem";
|
|
4
|
-
import { DataServiceWrapper } from "@redstone-finance/evm-connector";
|
|
5
|
-
import { RedstonePayload } from "@redstone-finance/protocol";
|
|
6
|
-
import { getSignersForDataServiceId } from "@redstone-finance/sdk";
|
|
7
|
-
import { MathUtils } from "@redstone-finance/utils";
|
|
8
|
-
//#region src/onchain/market/pricefeeds/updates/fetchRedstonePayloads.ts
|
|
9
|
-
/**
|
|
10
|
-
* Fetches redstone payloads from Redstone API
|
|
11
|
-
*/
|
|
12
|
-
async function fetchRedstonePayloads(options) {
|
|
13
|
-
const { dataServiceId, dataFeedsIds, uniqueSignersCount, historicalTimestampMs, gateways, failOnMissingFeeds, enableLogging, logger, returnPrices } = options;
|
|
14
|
-
const metadataTimestampMs = historicalTimestampMs ?? options.metadataTimestampMs;
|
|
15
|
-
const dataPackagesIds = Array.from(new Set(dataFeedsIds));
|
|
16
|
-
if (dataPackagesIds.length === 0) return [];
|
|
17
|
-
const wrapper = new DataServiceWrapper({
|
|
18
|
-
dataServiceId,
|
|
19
|
-
dataPackagesIds,
|
|
20
|
-
uniqueSignersCount,
|
|
21
|
-
authorizedSigners: getSignersForDataServiceId(dataServiceId),
|
|
22
|
-
historicalTimestamp: historicalTimestampMs,
|
|
23
|
-
urls: gateways,
|
|
24
|
-
ignoreMissingFeed: !failOnMissingFeeds,
|
|
25
|
-
enableEnhancedLogs: enableLogging
|
|
26
|
-
});
|
|
27
|
-
if (metadataTimestampMs) wrapper.setMetadataTimestamp(metadataTimestampMs);
|
|
28
|
-
const dataPayload = await retry(() => wrapper.prepareRedstonePayload(true), {
|
|
29
|
-
attempts: 5,
|
|
30
|
-
interval: historicalTimestampMs ? 30500 : 250
|
|
31
|
-
});
|
|
32
|
-
const packagesByDataFeedId = groupDataPackages(RedstonePayload.parse(toBytes(`0x${dataPayload}`)).signedDataPackages);
|
|
33
|
-
const result = [];
|
|
34
|
-
for (const dataFeedId of dataFeedsIds) {
|
|
35
|
-
const signedDataPackages = packagesByDataFeedId[dataFeedId];
|
|
36
|
-
if (!signedDataPackages) {
|
|
37
|
-
if (failOnMissingFeeds) throw new Error(`cannot find data packages for ${dataFeedId}`);
|
|
38
|
-
logger?.warn(`cannot find data packages for ${dataFeedId}`);
|
|
39
|
-
continue;
|
|
40
|
-
}
|
|
41
|
-
if (signedDataPackages.length !== uniqueSignersCount) {
|
|
42
|
-
if (failOnMissingFeeds) throw new Error(`got ${signedDataPackages.length} data packages for ${dataFeedId}, but expected ${uniqueSignersCount}`);
|
|
43
|
-
logger?.warn(`got ${signedDataPackages.length} data packages for ${dataFeedId}, but expected ${uniqueSignersCount}`);
|
|
44
|
-
continue;
|
|
45
|
-
}
|
|
46
|
-
result.push(getCalldataWithTimestamp(dataFeedId, signedDataPackages, wrapper.getUnsignedMetadata(), returnPrices));
|
|
47
|
-
}
|
|
48
|
-
return result;
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Groups SignedDataPackages by dataFeedId
|
|
52
|
-
* @param signedDataPackages
|
|
53
|
-
* @returns
|
|
54
|
-
*/
|
|
55
|
-
function groupDataPackages(signedDataPackages) {
|
|
56
|
-
const packagesByDataFeedId = {};
|
|
57
|
-
for (const p of signedDataPackages) {
|
|
58
|
-
const { dataPoints } = p.dataPackage;
|
|
59
|
-
const dataFeedId0 = dataPoints[0].dataFeedId;
|
|
60
|
-
for (const dp of dataPoints) if (dp.dataFeedId !== dataFeedId0) throw new Error(`data package contains data points with different dataFeedIds: ${dp.dataFeedId} and ${dataFeedId0}`);
|
|
61
|
-
if (!packagesByDataFeedId[dataFeedId0]) packagesByDataFeedId[dataFeedId0] = [];
|
|
62
|
-
packagesByDataFeedId[dataFeedId0].push(p);
|
|
63
|
-
}
|
|
64
|
-
return packagesByDataFeedId;
|
|
65
|
-
}
|
|
66
|
-
function getCalldataWithTimestamp(dataFeedId, packages, unsignedMetadata, returnPrices) {
|
|
67
|
-
const bytesToAdd = 32 - RedstonePayload.prepare(packages, unsignedMetadata).length / 2 % 32;
|
|
68
|
-
const newUnsignedMetadata = unsignedMetadata + "_".repeat(bytesToAdd);
|
|
69
|
-
const payload = RedstonePayload.prepare(packages, newUnsignedMetadata);
|
|
70
|
-
let timestamp = 0;
|
|
71
|
-
for (const p of packages) {
|
|
72
|
-
const newTimestamp = p.dataPackage.timestampMilliseconds / 1e3;
|
|
73
|
-
if (timestamp === 0) timestamp = newTimestamp;
|
|
74
|
-
else if (timestamp !== newTimestamp) throw new Error("Timestamps are not equal");
|
|
75
|
-
}
|
|
76
|
-
const base = {
|
|
77
|
-
dataFeedId,
|
|
78
|
-
data: encodeAbiParameters([{ type: "uint256" }, { type: "bytes" }], [BigInt(timestamp), `0x${payload}`]),
|
|
79
|
-
timestamp,
|
|
80
|
-
cached: false
|
|
81
|
-
};
|
|
82
|
-
if (returnPrices) {
|
|
83
|
-
const prices = packages.flatMap((p) => p.dataPackage.dataPoints).map((dp) => BigInt(`0x${Buffer.from(dp.value).toString("hex")}`));
|
|
84
|
-
const medianPrice = BigInt(MathUtils.getMedianOfBigNumbers(prices));
|
|
85
|
-
return {
|
|
86
|
-
...base,
|
|
87
|
-
price: medianPrice,
|
|
88
|
-
decimals: 8
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
return base;
|
|
92
|
-
}
|
|
93
|
-
//#endregion
|
|
94
|
-
export { fetchRedstonePayloads };
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { AP_PRICE_FEED_COMPRESSOR } from "../../../onchain/constants/address-provider.js";
|
|
2
|
-
import { OnchainSDK } from "../../../onchain/OnchainSDK.js";
|
|
3
|
-
import "../../../onchain/index.js";
|
|
4
|
-
import { AddressProviderContract } from "../../bindings/address-provider.js";
|
|
5
|
-
import "../../deployment/addresses.js";
|
|
6
|
-
import { deepJsonParse } from "../format.js";
|
|
7
|
-
import "../../bindings/index.js";
|
|
8
|
-
import { getUpdatablePriceFeeds } from "./get-updatable-feeds.js";
|
|
9
|
-
//#region src/permissionless/utils/price-update/get-price-feeds.ts
|
|
10
|
-
/**
|
|
11
|
-
* @deprecated This helper will be removed in the next releases.
|
|
12
|
-
*/
|
|
13
|
-
function getCallTouchedPriceFeeds(parsedCall) {
|
|
14
|
-
const priceFeeds = [];
|
|
15
|
-
const deepParsedArgs = deepJsonParse(parsedCall.args);
|
|
16
|
-
function searchForPriceFeeds(obj) {
|
|
17
|
-
if (obj === null || obj === void 0) return;
|
|
18
|
-
if (Array.isArray(obj)) {
|
|
19
|
-
obj.forEach((item) => {
|
|
20
|
-
searchForPriceFeeds(item);
|
|
21
|
-
});
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
if (typeof obj === "object") for (const [key, value] of Object.entries(obj)) {
|
|
25
|
-
if (key === "priceFeed" || key === "underlyingPriceFeed") priceFeeds.push(value);
|
|
26
|
-
searchForPriceFeeds(value);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
searchForPriceFeeds(deepParsedArgs);
|
|
30
|
-
return priceFeeds;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* @deprecated This helper will be removed in the next releases.
|
|
34
|
-
*/
|
|
35
|
-
function getCallsTouchedPriceFeeds(parsedCalls) {
|
|
36
|
-
return parsedCalls.flatMap((call) => getCallTouchedPriceFeeds(call));
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* @deprecated This helper will be removed in the next releases.
|
|
40
|
-
*/
|
|
41
|
-
async function getCallsTouchedUpdatablePriceFeeds({ parsedCalls, client, gasLimit }) {
|
|
42
|
-
const pfCompressor = await new AddressProviderContract("0xF7f0a609BfAb9a0A98786951ef10e5FE26cC1E38", client).getAddressOrRevert(AP_PRICE_FEED_COMPRESSOR, 310n);
|
|
43
|
-
const gearboxClient = client;
|
|
44
|
-
const chain = gearboxClient.chain;
|
|
45
|
-
if (!chain) throw new Error("Chain not defined on client");
|
|
46
|
-
const sdk = new OnchainSDK(chain.network, { client: gearboxClient }, { gasLimit });
|
|
47
|
-
await sdk.attach({ marketConfigurators: [] });
|
|
48
|
-
const touchedFeeds = parsedCalls.flatMap((call) => getCallTouchedPriceFeeds(call));
|
|
49
|
-
return (await getUpdatablePriceFeeds({
|
|
50
|
-
sdk,
|
|
51
|
-
client,
|
|
52
|
-
pfCompressor,
|
|
53
|
-
priceFeeds: touchedFeeds
|
|
54
|
-
})).map((feed) => feed.address);
|
|
55
|
-
}
|
|
56
|
-
//#endregion
|
|
57
|
-
export { getCallTouchedPriceFeeds, getCallsTouchedPriceFeeds, getCallsTouchedUpdatablePriceFeeds };
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { IPriceFeedContract } from "../types.js";
|
|
2
|
-
import { PriceUpdatesCache } from "./PriceUpdatesCache.js";
|
|
3
|
-
import { PriceUpdateTx } from "./PriceUpdateTx.js";
|
|
4
|
-
import { IPriceUpdateTask, IPriceUpdater } from "./types.js";
|
|
5
|
-
import { OnchainSDK } from "../../../OnchainSDK.js";
|
|
6
|
-
import { SDKConstruct } from "../../../base/SDKConstruct.js";
|
|
7
|
-
import "../../../base/index.js";
|
|
8
|
-
import { z } from "zod/v4";
|
|
9
|
-
//#region src/onchain/market/pricefeeds/updates/RedstoneUpdater.d.ts
|
|
10
|
-
interface RedstoneUpdateTask extends IPriceUpdateTask {
|
|
11
|
-
dataServiceId: string;
|
|
12
|
-
}
|
|
13
|
-
declare class RedstoneUpdateTx extends PriceUpdateTx<RedstoneUpdateTask> {
|
|
14
|
-
readonly name = "redstone";
|
|
15
|
-
}
|
|
16
|
-
declare const RedstoneOptions: z.ZodObject<{
|
|
17
|
-
historicTimestamp: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodLiteral<true>]>>;
|
|
18
|
-
gateways: z.ZodOptional<z.ZodArray<z.ZodURL>>;
|
|
19
|
-
cacheTTL: z.ZodOptional<z.ZodNumber>;
|
|
20
|
-
failOnMissingFeeds: z.ZodOptional<z.ZodBoolean>;
|
|
21
|
-
enableLogging: z.ZodOptional<z.ZodBoolean>;
|
|
22
|
-
}, z.core.$strip>;
|
|
23
|
-
type RedstoneOptions = z.infer<typeof RedstoneOptions> & {
|
|
24
|
-
/** Shared cache injected by {@link MultichainSDK} to avoid redundant fetches. */
|
|
25
|
-
cache?: PriceUpdatesCache;
|
|
26
|
-
};
|
|
27
|
-
/**
|
|
28
|
-
* Class to update multiple redstone price feeds at once
|
|
29
|
-
*/
|
|
30
|
-
declare class RedstoneUpdater extends SDKConstruct implements IPriceUpdater<RedstoneUpdateTask> {
|
|
31
|
-
#private;
|
|
32
|
-
constructor(sdk: OnchainSDK, opts?: RedstoneOptions);
|
|
33
|
-
getUpdateTxs(feeds: IPriceFeedContract[]): Promise<RedstoneUpdateTx[]>;
|
|
34
|
-
get historical(): boolean;
|
|
35
|
-
}
|
|
36
|
-
//#endregion
|
|
37
|
-
export { RedstoneOptions, RedstoneUpdater };
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { ILogger } from "../../../types/logger.js";
|
|
2
|
-
import { TimestampedCalldata, TimestampedCalldataWithPrice } from "./types.js";
|
|
3
|
-
//#region src/onchain/market/pricefeeds/updates/fetchRedstonePayloads.d.ts
|
|
4
|
-
interface FetchRedstonePayloadsOptions {
|
|
5
|
-
/**
|
|
6
|
-
* Redstone data service id
|
|
7
|
-
* Most likely "redstone-primary-prod"
|
|
8
|
-
*/
|
|
9
|
-
dataServiceId: string;
|
|
10
|
-
/**
|
|
11
|
-
* Feeds to fetch
|
|
12
|
-
*/
|
|
13
|
-
dataFeedsIds: Iterable<string>;
|
|
14
|
-
/**
|
|
15
|
-
* Ensure minimum number of signers for each feed
|
|
16
|
-
*/
|
|
17
|
-
uniqueSignersCount: number;
|
|
18
|
-
/**
|
|
19
|
-
* Historical timestamp in milliseconds
|
|
20
|
-
* Must be rounded to the nearest minute
|
|
21
|
-
*/
|
|
22
|
-
historicalTimestampMs?: number;
|
|
23
|
-
/**
|
|
24
|
-
* Metadata timestamp in milliseconds, if undefined, will be set to historical timestamp
|
|
25
|
-
* Can be used to set deterministic metadata timestamp, so requests sent by two services at the same block are identical
|
|
26
|
-
*/
|
|
27
|
-
metadataTimestampMs?: number;
|
|
28
|
-
/**
|
|
29
|
-
* Redstone gateways (put caching proxies here to avoid rate limiting)
|
|
30
|
-
*/
|
|
31
|
-
gateways?: string[];
|
|
32
|
-
/**
|
|
33
|
-
* Enable redstone internal logging
|
|
34
|
-
*/
|
|
35
|
-
enableLogging?: boolean;
|
|
36
|
-
/**
|
|
37
|
-
* When true, will throw an error if redstone is unable to fetch data for some feeds
|
|
38
|
-
*/
|
|
39
|
-
failOnMissingFeeds?: boolean;
|
|
40
|
-
/**
|
|
41
|
-
* Logger to use
|
|
42
|
-
*/
|
|
43
|
-
logger?: ILogger;
|
|
44
|
-
/**
|
|
45
|
-
* When true, returns the price data for each feed.
|
|
46
|
-
*/
|
|
47
|
-
returnPrices?: boolean;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Fetches redstone payloads with price data
|
|
51
|
-
*/
|
|
52
|
-
declare function fetchRedstonePayloads(options: FetchRedstonePayloadsOptions & {
|
|
53
|
-
returnPrices: true;
|
|
54
|
-
}): Promise<TimestampedCalldataWithPrice[]>;
|
|
55
|
-
/**
|
|
56
|
-
* Fetches redstone payloads
|
|
57
|
-
*/
|
|
58
|
-
declare function fetchRedstonePayloads(options: FetchRedstonePayloadsOptions & {
|
|
59
|
-
returnPrices?: false;
|
|
60
|
-
}): Promise<TimestampedCalldata[]>;
|
|
61
|
-
//#endregion
|
|
62
|
-
export { FetchRedstonePayloadsOptions, fetchRedstonePayloads };
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { ParsedCall } from "../../../onchain/base/types.js";
|
|
2
|
-
import "../../../onchain/index.js";
|
|
3
|
-
import { Address, Chain, PublicClient, Transport } from "viem";
|
|
4
|
-
//#region src/permissionless/utils/price-update/get-price-feeds.d.ts
|
|
5
|
-
/**
|
|
6
|
-
* @deprecated This helper will be removed in the next releases.
|
|
7
|
-
*/
|
|
8
|
-
declare function getCallTouchedPriceFeeds(parsedCall: ParsedCall): Address[];
|
|
9
|
-
/**
|
|
10
|
-
* @deprecated This helper will be removed in the next releases.
|
|
11
|
-
*/
|
|
12
|
-
declare function getCallsTouchedPriceFeeds(parsedCalls: ParsedCall[]): Address[];
|
|
13
|
-
/**
|
|
14
|
-
* @deprecated This helper will be removed in the next releases.
|
|
15
|
-
*/
|
|
16
|
-
declare function getCallsTouchedUpdatablePriceFeeds({ parsedCalls, client, gasLimit }: {
|
|
17
|
-
client: PublicClient<Transport, Chain>;
|
|
18
|
-
parsedCalls: ParsedCall[];
|
|
19
|
-
gasLimit?: bigint;
|
|
20
|
-
}): Promise<Address[]>;
|
|
21
|
-
//#endregion
|
|
22
|
-
export { getCallTouchedPriceFeeds, getCallsTouchedPriceFeeds, getCallsTouchedUpdatablePriceFeeds };
|