@gearbox-protocol/sdk 14.11.19 → 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.
- package/dist/cjs/permissionless/bindings/instance-manager.js +1 -1
- package/dist/cjs/permissionless/bindings/market-configurator.js +2 -1
- package/dist/cjs/permissionless/utils/price-update/get-updatable-feeds.js +2 -23
- package/dist/cjs/sdk/OnchainSDK.js +0 -15
- package/dist/cjs/sdk/market/pricefeeds/PriceFeedsRegister.js +4 -6
- package/dist/cjs/sdk/market/pricefeeds/PythPriceFeed.js +1 -0
- package/dist/cjs/sdk/market/pricefeeds/RedstonePriceFeed.js +1 -0
- package/dist/cjs/sdk/market/pricefeeds/updates/PythUpdater.js +4 -122
- package/dist/cjs/sdk/market/pricefeeds/updates/RedstoneUpdater.js +4 -196
- package/dist/cjs/sdk/market/pricefeeds/updates/fetchPythPayloads.js +3 -105
- package/dist/cjs/sdk/market/pricefeeds/updates/fetchRedstonePayloads.js +4 -126
- package/dist/esm/permissionless/bindings/instance-manager.js +1 -1
- package/dist/esm/permissionless/bindings/market-configurator.js +2 -1
- package/dist/esm/permissionless/utils/price-update/get-updatable-feeds.js +2 -27
- package/dist/esm/sdk/OnchainSDK.js +0 -15
- package/dist/esm/sdk/market/pricefeeds/PriceFeedsRegister.js +4 -6
- package/dist/esm/sdk/market/pricefeeds/PythPriceFeed.js +1 -0
- package/dist/esm/sdk/market/pricefeeds/RedstonePriceFeed.js +1 -0
- package/dist/esm/sdk/market/pricefeeds/updates/PythUpdater.js +4 -122
- package/dist/esm/sdk/market/pricefeeds/updates/RedstoneUpdater.js +4 -196
- package/dist/esm/sdk/market/pricefeeds/updates/fetchPythPayloads.js +3 -109
- package/dist/esm/sdk/market/pricefeeds/updates/fetchRedstonePayloads.js +4 -130
- package/dist/types/permissionless/utils/price-update/get-updatable-feeds.d.ts +4 -3
- package/dist/types/sdk/market/pricefeeds/PriceFeedsRegister.d.ts +4 -5
- package/dist/types/sdk/market/pricefeeds/updates/PythUpdater.d.ts +5 -7
- package/dist/types/sdk/market/pricefeeds/updates/RedstoneUpdater.d.ts +5 -8
- package/dist/types/sdk/market/pricefeeds/updates/fetchPythPayloads.d.ts +2 -6
- package/dist/types/sdk/market/pricefeeds/updates/fetchRedstonePayloads.d.ts +2 -6
- package/package.json +1 -5
|
@@ -32,11 +32,11 @@ var import_uniswapV3Worker = require("../../abi/router/uniswapV3Worker.js");
|
|
|
32
32
|
var import_uniswapV4Worker = require("../../abi/router/uniswapV4Worker.js");
|
|
33
33
|
var import_sdk = require("../../sdk/index.js");
|
|
34
34
|
var import_addresses = require("../deployment/addresses.js");
|
|
35
|
+
var import_bytecode_repository = require("./bytecode-repository.js");
|
|
35
36
|
var import_compressors = require("./compressors/index.js");
|
|
36
37
|
var import_price_feed_store = require("./price-feed-store.js");
|
|
37
38
|
var import_router = require("./router/index.js");
|
|
38
39
|
var import_treasury_splitter = require("./treasury-splitter.js");
|
|
39
|
-
var import_bytecode_repository = require("./bytecode-repository.js");
|
|
40
40
|
const abi = import_instanceManager.instanceManagerAbi;
|
|
41
41
|
class InstanceManagerContract extends import_sdk.BaseContract {
|
|
42
42
|
constructor(addr, register) {
|
|
@@ -21,29 +21,8 @@ __export(get_updatable_feeds_exports, {
|
|
|
21
21
|
getUpdatablePriceFeeds: () => getUpdatablePriceFeeds
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(get_updatable_feeds_exports);
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
var import_sdk = require("../../../sdk/index.js");
|
|
27
|
-
async function getUpdatablePriceFeeds(args) {
|
|
28
|
-
const { sdk, client, pfCompressor, priceFeeds } = args;
|
|
29
|
-
const priceFeedCompressor = (0, import_viem.getContract)({
|
|
30
|
-
address: pfCompressor,
|
|
31
|
-
abi: import_priceFeedCompressor.priceFeedCompressorAbi,
|
|
32
|
-
client
|
|
33
|
-
});
|
|
34
|
-
const updatablePriceFeeds = (await priceFeedCompressor.read.loadPriceFeedTree([
|
|
35
|
-
priceFeeds
|
|
36
|
-
])).filter(
|
|
37
|
-
(data) => ["PRICE_FEED::PYTH", "PRICE_FEED::REDSTONE"].includes(
|
|
38
|
-
(0, import_sdk.bytes32ToString)(data.baseParams.contractType)
|
|
39
|
-
)
|
|
40
|
-
).map((data) => {
|
|
41
|
-
if ((0, import_sdk.bytes32ToString)(data.baseParams.contractType) === "PRICE_FEED::PYTH") {
|
|
42
|
-
return new import_sdk.PythPriceFeed(sdk, data);
|
|
43
|
-
}
|
|
44
|
-
return new import_sdk.RedstonePriceFeedContract(sdk, data);
|
|
45
|
-
});
|
|
46
|
-
return updatablePriceFeeds;
|
|
24
|
+
async function getUpdatablePriceFeeds(_args) {
|
|
25
|
+
return [];
|
|
47
26
|
}
|
|
48
27
|
// Annotate the CommonJS export names for ESM import in node:
|
|
49
28
|
0 && (module.exports = {
|
|
@@ -150,16 +150,6 @@ class OnchainSDK extends import_base.ChainContractsRegister {
|
|
|
150
150
|
);
|
|
151
151
|
this.#currentBlock = block.number;
|
|
152
152
|
this.#timestamp = block.timestamp;
|
|
153
|
-
if (blockNumber && !redstone?.historicTimestamp && time - Number(block.timestamp) * 1e3 > 60 * 1e3) {
|
|
154
|
-
this.logger?.warn(
|
|
155
|
-
"attaching to fixed block number, but redstone historicTimestamp is not set. price updates might fail"
|
|
156
|
-
);
|
|
157
|
-
}
|
|
158
|
-
if (blockNumber && !pyth?.historicTimestamp && time - Number(block.timestamp) * 1e3 > 60 * 1e3) {
|
|
159
|
-
this.logger?.warn(
|
|
160
|
-
"attaching to fixed block number, but pyth historicTimestamp is not set. price updates might fail"
|
|
161
|
-
);
|
|
162
|
-
}
|
|
163
153
|
this.#priceFeeds = new import_pricefeeds.PriceFeedRegister(this, { redstone, pyth });
|
|
164
154
|
this.logger?.debug(
|
|
165
155
|
`attach block number ${this.currentBlock} timestamp ${this.timestamp}`
|
|
@@ -331,11 +321,6 @@ class OnchainSDK extends import_base.ChainContractsRegister {
|
|
|
331
321
|
*/
|
|
332
322
|
async syncState(opts) {
|
|
333
323
|
let { blockNumber, timestamp, ignoreUpdateablePrices } = opts ?? {};
|
|
334
|
-
if (this.priceFeeds.historical && !ignoreUpdateablePrices) {
|
|
335
|
-
this.logger?.warn(
|
|
336
|
-
"syncState is not supported with redstone or pyth historicTimestamp"
|
|
337
|
-
);
|
|
338
|
-
}
|
|
339
324
|
if (!blockNumber || !timestamp) {
|
|
340
325
|
const block = await this.client.getBlock({
|
|
341
326
|
blockTag: "latest"
|
|
@@ -43,7 +43,6 @@ var import_MellowLRTPriceFeed = require("./MellowLRTPriceFeed.js");
|
|
|
43
43
|
var import_PendleTWAPPTPriceFeed = require("./PendleTWAPPTPriceFeed.js");
|
|
44
44
|
var import_PythPriceFeed = require("./PythPriceFeed.js");
|
|
45
45
|
var import_RedstonePriceFeed = require("./RedstonePriceFeed.js");
|
|
46
|
-
var import_updates = require("./updates/index.js");
|
|
47
46
|
var import_WstETHPriceFeed = require("./WstETHPriceFeed.js");
|
|
48
47
|
var import_YearnPriceFeed = require("./YearnPriceFeed.js");
|
|
49
48
|
var import_ZeroPriceFeed = require("./ZeroPriceFeed.js");
|
|
@@ -52,12 +51,9 @@ class PriceFeedRegister extends import_base.SDKConstruct {
|
|
|
52
51
|
#updaters;
|
|
53
52
|
#feeds = new import_utils.AddressMap(void 0, "priceFeeds");
|
|
54
53
|
#latestUpdate;
|
|
55
|
-
constructor(sdk,
|
|
54
|
+
constructor(sdk, _opts = {}) {
|
|
56
55
|
super(sdk);
|
|
57
|
-
this.#updaters = [
|
|
58
|
-
new import_updates.PythUpdater(sdk, opts?.pyth),
|
|
59
|
-
new import_updates.RedstoneUpdater(sdk, opts?.redstone)
|
|
60
|
-
];
|
|
56
|
+
this.#updaters = [];
|
|
61
57
|
}
|
|
62
58
|
/**
|
|
63
59
|
* @internal
|
|
@@ -167,6 +163,7 @@ class PriceFeedRegister extends import_base.SDKConstruct {
|
|
|
167
163
|
* @returns
|
|
168
164
|
*/
|
|
169
165
|
async generateExternalPriceFeedsUpdateTxs(feeds, block) {
|
|
166
|
+
if (this.#updaters.length === 0) return { txs: [], timestamp: 0 };
|
|
170
167
|
const [priceFeedCompressorAddress] = this.sdk.addressProvider.mustGetLatest(
|
|
171
168
|
import_constants.AP_PRICE_FEED_COMPRESSOR,
|
|
172
169
|
import_constants.VERSION_RANGE_310
|
|
@@ -241,6 +238,7 @@ class PriceFeedRegister extends import_base.SDKConstruct {
|
|
|
241
238
|
* Discovered price feeds are not saved anywhere in PriceFeedRegister, and can later be used to load price feed updates
|
|
242
239
|
*/
|
|
243
240
|
async getPartialUpdatablePriceFeeds(configurators) {
|
|
241
|
+
if (this.#updaters.length === 0) return [];
|
|
244
242
|
const [priceFeedCompressorAddress] = this.sdk.addressProvider.mustGetLatest(
|
|
245
243
|
import_constants.AP_PRICE_FEED_COMPRESSOR,
|
|
246
244
|
import_constants.VERSION_RANGE_310
|
|
@@ -24,8 +24,6 @@ __export(PythUpdater_exports, {
|
|
|
24
24
|
module.exports = __toCommonJS(PythUpdater_exports);
|
|
25
25
|
var import_v4 = require("zod/v4");
|
|
26
26
|
var import_base = require("../../../base/index.js");
|
|
27
|
-
var import_fetchPythPayloads = require("./fetchPythPayloads.js");
|
|
28
|
-
var import_PriceUpdatesCache = require("./PriceUpdatesCache.js");
|
|
29
27
|
var import_PriceUpdateTx = require("./PriceUpdateTx.js");
|
|
30
28
|
class PythUpdateTx extends import_PriceUpdateTx.PriceUpdateTx {
|
|
31
29
|
name = "pyth";
|
|
@@ -53,131 +51,15 @@ const PythOptions = import_v4.z.object({
|
|
|
53
51
|
failOnMissingFeeds: import_v4.z.boolean().optional()
|
|
54
52
|
});
|
|
55
53
|
class PythUpdater extends import_base.SDKConstruct {
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Fixed pyth historic timestamp in seconds
|
|
59
|
-
*/
|
|
60
|
-
#historicalTimestamp;
|
|
61
|
-
#apiProxy;
|
|
62
|
-
#failOnMissingFeeds;
|
|
63
|
-
constructor(sdk, opts = {}) {
|
|
54
|
+
constructor(sdk, _opts = {}) {
|
|
64
55
|
super(sdk);
|
|
65
|
-
const { apiProxy, cacheTTL, failOnMissingFeeds, historicTimestamp } = opts;
|
|
66
|
-
this.#failOnMissingFeeds = failOnMissingFeeds;
|
|
67
|
-
this.#apiProxy = apiProxy;
|
|
68
|
-
if (historicTimestamp) {
|
|
69
|
-
this.#historicalTimestamp = historicTimestamp === true ? Number(this.sdk.timestamp) : historicTimestamp;
|
|
70
|
-
this.logger?.debug(
|
|
71
|
-
`using historical timestamp ${this.#historicalTimestamp}`
|
|
72
|
-
);
|
|
73
|
-
}
|
|
74
|
-
this.#cache = opts.cache ?? new import_PriceUpdatesCache.PriceUpdatesCache({
|
|
75
|
-
ttl: cacheTTL ?? 225 * 1e3,
|
|
76
|
-
historical: !!historicTimestamp
|
|
77
|
-
});
|
|
78
56
|
}
|
|
79
|
-
async getUpdateTxs(
|
|
80
|
-
|
|
81
|
-
return [];
|
|
82
|
-
}
|
|
83
|
-
this.logger?.debug(
|
|
84
|
-
`generating update transactions for ${feeds.length} pyth price feeds`
|
|
85
|
-
);
|
|
86
|
-
const pythFeeds = new Map(
|
|
87
|
-
feeds.filter(isPyth).map((f) => [f.priceFeedId, f])
|
|
88
|
-
);
|
|
89
|
-
const payloads = await this.#getPayloads(new Set(pythFeeds.keys()));
|
|
90
|
-
let [minTimestamp, maxTimestamp] = [Number.POSITIVE_INFINITY, 0];
|
|
91
|
-
const results = [];
|
|
92
|
-
for (const p of payloads) {
|
|
93
|
-
const priceFeed = pythFeeds.get(p.dataFeedId);
|
|
94
|
-
if (!priceFeed) {
|
|
95
|
-
throw new Error(`cannot find price feed for ${p.dataFeedId}`);
|
|
96
|
-
}
|
|
97
|
-
const { dataFeedId, timestamp, cached, data } = p;
|
|
98
|
-
minTimestamp = Math.min(minTimestamp, timestamp);
|
|
99
|
-
maxTimestamp = Math.max(maxTimestamp, timestamp);
|
|
100
|
-
results.push(
|
|
101
|
-
new PythUpdateTx(priceFeed.createPriceUpdateTx(data), {
|
|
102
|
-
dataFeedId,
|
|
103
|
-
priceFeed: priceFeed.address,
|
|
104
|
-
timestamp,
|
|
105
|
-
cached
|
|
106
|
-
})
|
|
107
|
-
);
|
|
108
|
-
}
|
|
109
|
-
let tsRange = "";
|
|
110
|
-
if (results.length) {
|
|
111
|
-
const minDelta = BigInt(minTimestamp) - this.sdk.timestamp;
|
|
112
|
-
tsRange = `, timestamps ${minTimestamp} (${minDelta})`;
|
|
113
|
-
if (minTimestamp !== maxTimestamp) {
|
|
114
|
-
const maxDelta = BigInt(maxTimestamp) - this.sdk.timestamp;
|
|
115
|
-
tsRange = `${tsRange} - ${maxTimestamp} (${maxDelta})`;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
this.logger?.debug(
|
|
119
|
-
`generated ${results.length} update transactions for pyth price feeds: ${Array.from(pythFeeds.keys()).join(", ")}${tsRange}`
|
|
120
|
-
);
|
|
121
|
-
return results;
|
|
57
|
+
async getUpdateTxs(_feeds) {
|
|
58
|
+
return [];
|
|
122
59
|
}
|
|
123
60
|
get historical() {
|
|
124
|
-
return
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Gets pyth payloads
|
|
128
|
-
* @param dataFeedsIds
|
|
129
|
-
* @returns
|
|
130
|
-
*/
|
|
131
|
-
async #getPayloads(dataFeedsIds) {
|
|
132
|
-
this.logger?.debug(
|
|
133
|
-
`getting pyth payloads for ${dataFeedsIds.size} price feeds: ${Array.from(dataFeedsIds).join(", ")}`
|
|
134
|
-
);
|
|
135
|
-
const fromCache = [];
|
|
136
|
-
const uncached = [];
|
|
137
|
-
for (const priceFeedsId of dataFeedsIds) {
|
|
138
|
-
const cached = this.#cache.get(priceFeedsId);
|
|
139
|
-
if (cached) {
|
|
140
|
-
fromCache.push({ ...cached, cached: true });
|
|
141
|
-
} else {
|
|
142
|
-
uncached.push(priceFeedsId);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
const fromPyth = await this.#fetchPayloads(
|
|
146
|
-
new Set(uncached)
|
|
147
|
-
);
|
|
148
|
-
for (const resp of fromPyth) {
|
|
149
|
-
this.#cache.set(resp, resp.dataFeedId);
|
|
150
|
-
}
|
|
151
|
-
this.logger?.debug(
|
|
152
|
-
`got ${fromPyth.length} new pyth updates and ${fromCache.length} from cache`
|
|
153
|
-
);
|
|
154
|
-
return [...fromCache, ...fromPyth];
|
|
61
|
+
return false;
|
|
155
62
|
}
|
|
156
|
-
/**
|
|
157
|
-
* Fetches pyth payloads from Hermes API
|
|
158
|
-
* @param dataFeedsIds
|
|
159
|
-
* @returns
|
|
160
|
-
*/
|
|
161
|
-
async #fetchPayloads(dataFeedsIds) {
|
|
162
|
-
if (dataFeedsIds.size === 0) {
|
|
163
|
-
return [];
|
|
164
|
-
}
|
|
165
|
-
const ids = Array.from(dataFeedsIds);
|
|
166
|
-
const tsStr = this.#historicalTimestamp ? ` with historical timestamp ${this.#historicalTimestamp}` : "";
|
|
167
|
-
this.logger?.debug(
|
|
168
|
-
`fetching pyth payloads for ${dataFeedsIds.size} price feeds: ${ids.join(", ")}${tsStr}`
|
|
169
|
-
);
|
|
170
|
-
return (0, import_fetchPythPayloads.fetchPythPayloads)({
|
|
171
|
-
dataFeedsIds,
|
|
172
|
-
historicalTimestampSeconds: this.#historicalTimestamp,
|
|
173
|
-
apiProxy: this.#apiProxy,
|
|
174
|
-
failOnMissingFeeds: this.#failOnMissingFeeds,
|
|
175
|
-
logger: this.logger
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
function isPyth(pf) {
|
|
180
|
-
return pf.contractType === "PRICE_FEED::PYTH";
|
|
181
63
|
}
|
|
182
64
|
// Annotate the CommonJS export names for ESM import in node:
|
|
183
65
|
0 && (module.exports = {
|
|
@@ -24,9 +24,6 @@ __export(RedstoneUpdater_exports, {
|
|
|
24
24
|
module.exports = __toCommonJS(RedstoneUpdater_exports);
|
|
25
25
|
var import_v4 = require("zod/v4");
|
|
26
26
|
var import_base = require("../../../base/index.js");
|
|
27
|
-
var import_utils = require("../../../utils/index.js");
|
|
28
|
-
var import_fetchRedstonePayloads = require("./fetchRedstonePayloads.js");
|
|
29
|
-
var import_PriceUpdatesCache = require("./PriceUpdatesCache.js");
|
|
30
27
|
var import_PriceUpdateTx = require("./PriceUpdateTx.js");
|
|
31
28
|
class RedstoneUpdateTx extends import_PriceUpdateTx.PriceUpdateTx {
|
|
32
29
|
name = "redstone";
|
|
@@ -58,204 +55,15 @@ const RedstoneOptions = import_v4.z.object({
|
|
|
58
55
|
enableLogging: import_v4.z.boolean().optional()
|
|
59
56
|
});
|
|
60
57
|
class RedstoneUpdater extends import_base.SDKConstruct {
|
|
61
|
-
|
|
62
|
-
#historicalTimestampMs;
|
|
63
|
-
#gateways;
|
|
64
|
-
#failOnMissingFeeds;
|
|
65
|
-
#enableLogging;
|
|
66
|
-
constructor(sdk, opts = {}) {
|
|
58
|
+
constructor(sdk, _opts = {}) {
|
|
67
59
|
super(sdk);
|
|
68
|
-
this.#failOnMissingFeeds = opts.failOnMissingFeeds;
|
|
69
|
-
this.#enableLogging = opts.enableLogging;
|
|
70
|
-
this.#gateways = opts.gateways?.length ? opts.gateways : void 0;
|
|
71
|
-
let ts = opts.historicTimestamp;
|
|
72
|
-
if (ts) {
|
|
73
|
-
ts = ts === true ? Number(this.sdk.timestamp) * 1e3 : ts;
|
|
74
|
-
this.#historicalTimestampMs = 6e4 * Math.floor(ts / 6e4);
|
|
75
|
-
this.logger?.debug(
|
|
76
|
-
`using historical timestamp ${this.#historicalTimestampMs}`
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
this.#cache = opts.cache ?? new import_PriceUpdatesCache.PriceUpdatesCache({
|
|
80
|
-
ttl: opts.cacheTTL ?? 225 * 1e3,
|
|
81
|
-
historical: !!ts
|
|
82
|
-
});
|
|
83
60
|
}
|
|
84
|
-
async getUpdateTxs(
|
|
85
|
-
|
|
86
|
-
return [];
|
|
87
|
-
}
|
|
88
|
-
this.logger?.debug(
|
|
89
|
-
`generating update transactions for ${feeds.length} redstone price feeds`
|
|
90
|
-
);
|
|
91
|
-
const groupedFeeds = {};
|
|
92
|
-
const priceFeeds = /* @__PURE__ */ new Map();
|
|
93
|
-
for (const feed of feeds) {
|
|
94
|
-
if (!isRedstone(feed)) {
|
|
95
|
-
continue;
|
|
96
|
-
}
|
|
97
|
-
const key = `${feed.dataServiceId}:${feed.signersThreshold}`;
|
|
98
|
-
if (!groupedFeeds[key]) {
|
|
99
|
-
groupedFeeds[key] = /* @__PURE__ */ new Set();
|
|
100
|
-
}
|
|
101
|
-
groupedFeeds[key].add(feed.dataId);
|
|
102
|
-
const pfsForDataId = priceFeeds.get(feed.dataId) ?? new import_utils.AddressMap();
|
|
103
|
-
pfsForDataId.upsert(feed.address, feed);
|
|
104
|
-
priceFeeds.set(feed.dataId, pfsForDataId);
|
|
105
|
-
}
|
|
106
|
-
const results = [];
|
|
107
|
-
let [minTimestamp, maxTimestamp] = [Number.POSITIVE_INFINITY, 0];
|
|
108
|
-
for (const [key, group] of Object.entries(groupedFeeds)) {
|
|
109
|
-
const [dataServiceId, signersStr] = key.split(":");
|
|
110
|
-
const uniqueSignersCount = parseInt(signersStr, 10);
|
|
111
|
-
const payloads = await this.#safeGetPayloads(
|
|
112
|
-
dataServiceId,
|
|
113
|
-
group,
|
|
114
|
-
uniqueSignersCount
|
|
115
|
-
);
|
|
116
|
-
for (const { dataFeedId, data, timestamp, cached } of payloads) {
|
|
117
|
-
const pfsForDataId = priceFeeds.get(dataFeedId);
|
|
118
|
-
if (!pfsForDataId) {
|
|
119
|
-
throw new Error(`cannot get price feed addresses for ${dataFeedId}`);
|
|
120
|
-
}
|
|
121
|
-
for (const priceFeed of pfsForDataId.values()) {
|
|
122
|
-
minTimestamp = Math.min(minTimestamp, timestamp);
|
|
123
|
-
maxTimestamp = Math.max(maxTimestamp, timestamp);
|
|
124
|
-
results.push(
|
|
125
|
-
new RedstoneUpdateTx(priceFeed.createPriceUpdateTx(data), {
|
|
126
|
-
dataFeedId,
|
|
127
|
-
dataServiceId,
|
|
128
|
-
priceFeed: priceFeed.address,
|
|
129
|
-
timestamp,
|
|
130
|
-
cached
|
|
131
|
-
})
|
|
132
|
-
);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
let tsRange = "";
|
|
137
|
-
if (results.length) {
|
|
138
|
-
const minDelta = BigInt(minTimestamp) - this.sdk.timestamp;
|
|
139
|
-
tsRange = `, timestamps ${minTimestamp} (${minDelta})`;
|
|
140
|
-
if (minTimestamp !== maxTimestamp) {
|
|
141
|
-
const maxDelta = BigInt(maxTimestamp) - this.sdk.timestamp;
|
|
142
|
-
tsRange = `${tsRange} - ${maxTimestamp} (${maxDelta})`;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
this.logger?.debug(
|
|
146
|
-
`generated ${results.length} update transactions for redstone price feeds: ${Array.from(priceFeeds.keys()).join(", ")}${tsRange}`
|
|
147
|
-
);
|
|
148
|
-
return results;
|
|
61
|
+
async getUpdateTxs(_feeds) {
|
|
62
|
+
return [];
|
|
149
63
|
}
|
|
150
64
|
get historical() {
|
|
151
|
-
return
|
|
65
|
+
return false;
|
|
152
66
|
}
|
|
153
|
-
/**
|
|
154
|
-
* Gets payloads, retries once if it has expired while inflight
|
|
155
|
-
* @param dataServiceId
|
|
156
|
-
* @param dataFeedsIds
|
|
157
|
-
* @param uniqueSignersCount
|
|
158
|
-
* @returns
|
|
159
|
-
*/
|
|
160
|
-
async #safeGetPayloads(dataServiceId, dataFeedsIds, uniqueSignersCount) {
|
|
161
|
-
let result = await this.#getPayloads(
|
|
162
|
-
dataServiceId,
|
|
163
|
-
dataFeedsIds,
|
|
164
|
-
uniqueSignersCount
|
|
165
|
-
);
|
|
166
|
-
if (this.#historicalTimestampMs) {
|
|
167
|
-
return result;
|
|
168
|
-
}
|
|
169
|
-
let expired = false;
|
|
170
|
-
for (const { timestamp, dataFeedId } of result) {
|
|
171
|
-
const delta = Number(this.sdk.timestamp) - timestamp;
|
|
172
|
-
if (delta >= 240 && delta < 255) {
|
|
173
|
-
this.logger?.warn(
|
|
174
|
-
`payload for ${dataFeedId} has expired by ${delta} seconds`
|
|
175
|
-
);
|
|
176
|
-
expired = true;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
if (expired) {
|
|
180
|
-
result = await this.#getPayloads(
|
|
181
|
-
dataServiceId,
|
|
182
|
-
dataFeedsIds,
|
|
183
|
-
uniqueSignersCount
|
|
184
|
-
);
|
|
185
|
-
}
|
|
186
|
-
return result;
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* Gets redstone payloads in one request for multiple feeds with the same dataServiceId and uniqueSignersCount
|
|
190
|
-
* If historicalTimestamp is set, responses will be cached
|
|
191
|
-
* @param dataServiceId
|
|
192
|
-
* @param dataFeedsIds
|
|
193
|
-
* @param uniqueSignersCount
|
|
194
|
-
* @returns
|
|
195
|
-
*/
|
|
196
|
-
async #getPayloads(dataServiceId, dataFeedsIds, uniqueSignersCount) {
|
|
197
|
-
this.logger?.debug(
|
|
198
|
-
`getting redstone payloads for ${dataFeedsIds.size} data feeds in ${dataServiceId} with ${uniqueSignersCount} signers: ${Array.from(dataFeedsIds).join(", ")}`
|
|
199
|
-
);
|
|
200
|
-
const fromCache = [];
|
|
201
|
-
const uncached = [];
|
|
202
|
-
for (const dataFeedId of dataFeedsIds) {
|
|
203
|
-
const cached = this.#cache.get(
|
|
204
|
-
dataServiceId,
|
|
205
|
-
dataFeedId,
|
|
206
|
-
uniqueSignersCount
|
|
207
|
-
);
|
|
208
|
-
if (cached) {
|
|
209
|
-
fromCache.push({ ...cached, cached: true });
|
|
210
|
-
} else {
|
|
211
|
-
uncached.push(dataFeedId);
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
const fromRedstone = await this.#fetchPayloads(
|
|
215
|
-
dataServiceId,
|
|
216
|
-
new Set(uncached),
|
|
217
|
-
uniqueSignersCount
|
|
218
|
-
);
|
|
219
|
-
for (const resp of fromRedstone) {
|
|
220
|
-
this.#cache.set(resp, dataServiceId, resp.dataFeedId, uniqueSignersCount);
|
|
221
|
-
}
|
|
222
|
-
this.logger?.debug(
|
|
223
|
-
`got ${fromRedstone.length} new redstone updates and ${fromCache.length} from cache`
|
|
224
|
-
);
|
|
225
|
-
return [...fromCache, ...fromRedstone];
|
|
226
|
-
}
|
|
227
|
-
/**
|
|
228
|
-
* Fetches redstone payloads in one request for multiple feeds with the same dataServiceId and uniqueSignersCount
|
|
229
|
-
* Payloads are loaded in one request to avoid redstone rate limit
|
|
230
|
-
* @param dataServiceId
|
|
231
|
-
* @param dataFeedsIds
|
|
232
|
-
* @param uniqueSignersCount
|
|
233
|
-
* @returns
|
|
234
|
-
*/
|
|
235
|
-
async #fetchPayloads(dataServiceId, dataFeedsIds, uniqueSignersCount) {
|
|
236
|
-
if (dataFeedsIds.size === 0) {
|
|
237
|
-
return [];
|
|
238
|
-
}
|
|
239
|
-
const dataPackagesIds = Array.from(dataFeedsIds);
|
|
240
|
-
const tsStr = this.#historicalTimestampMs ? ` with historical timestamp ${this.#historicalTimestampMs}` : "";
|
|
241
|
-
this.logger?.debug(
|
|
242
|
-
`fetching redstone payloads for ${dataFeedsIds.size} data feeds in ${dataServiceId} with ${uniqueSignersCount} signers: ${dataPackagesIds.join(", ")}${tsStr}`
|
|
243
|
-
);
|
|
244
|
-
return (0, import_fetchRedstonePayloads.fetchRedstonePayloads)({
|
|
245
|
-
dataServiceId,
|
|
246
|
-
dataFeedsIds,
|
|
247
|
-
uniqueSignersCount,
|
|
248
|
-
historicalTimestampMs: this.#historicalTimestampMs,
|
|
249
|
-
gateways: this.#gateways,
|
|
250
|
-
failOnMissingFeeds: this.#failOnMissingFeeds,
|
|
251
|
-
enableLogging: this.#enableLogging,
|
|
252
|
-
logger: this.logger,
|
|
253
|
-
metadataTimestampMs: Number(this.sdk.timestamp) * 1e3
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
function isRedstone(pf) {
|
|
258
|
-
return pf.contractType === "PRICE_FEED::REDSTONE";
|
|
259
67
|
}
|
|
260
68
|
// Annotate the CommonJS export names for ESM import in node:
|
|
261
69
|
0 && (module.exports = {
|
|
@@ -21,113 +21,11 @@ __export(fetchPythPayloads_exports, {
|
|
|
21
21
|
fetchPythPayloads: () => fetchPythPayloads
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(fetchPythPayloads_exports);
|
|
24
|
-
var import_buffer = require("buffer");
|
|
25
|
-
var import_viem = require("viem");
|
|
26
|
-
var import_utils = require("../../../utils/index.js");
|
|
27
|
-
var import_PythAccumulatorUpdateData = require("./PythAccumulatorUpdateData.js");
|
|
28
24
|
async function fetchPythPayloads(options) {
|
|
29
|
-
const {
|
|
30
|
-
|
|
31
|
-
failOnMissingFeeds,
|
|
32
|
-
historicalTimestampSeconds,
|
|
33
|
-
logger,
|
|
34
|
-
apiProxy,
|
|
35
|
-
customFetch = fetch,
|
|
36
|
-
returnPrices
|
|
37
|
-
} = options;
|
|
38
|
-
const ids = Array.from(new Set(dataFeedsIds)).sort();
|
|
39
|
-
if (ids.length === 0) {
|
|
40
|
-
return [];
|
|
25
|
+
for (const _feed of options.dataFeedsIds) {
|
|
26
|
+
throw new Error("Pyth price updates are no longer supported by this SDK");
|
|
41
27
|
}
|
|
42
|
-
|
|
43
|
-
api = api.endsWith("/") ? api : `${api}/`;
|
|
44
|
-
const url = new URL(api + (historicalTimestampSeconds ?? "latest"));
|
|
45
|
-
url.searchParams.append("parsed", returnPrices ? "true" : "false");
|
|
46
|
-
if (!failOnMissingFeeds) {
|
|
47
|
-
url.searchParams.append("ignore_invalid_price_ids", "true");
|
|
48
|
-
}
|
|
49
|
-
for (const id of ids) {
|
|
50
|
-
url.searchParams.append("ids[]", id);
|
|
51
|
-
}
|
|
52
|
-
const resp = await (0, import_utils.retry)(
|
|
53
|
-
async () => {
|
|
54
|
-
const resp2 = await customFetch(url.toString());
|
|
55
|
-
if (!resp2.ok) {
|
|
56
|
-
const body = await resp2.text();
|
|
57
|
-
throw new Error(
|
|
58
|
-
`failed to fetch pyth payloads: ${resp2.statusText}: ${body}`
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
const data = await resp2.json();
|
|
62
|
-
return data;
|
|
63
|
-
},
|
|
64
|
-
{ attempts: 3, exponent: 2, interval: 200 }
|
|
65
|
-
);
|
|
66
|
-
const result = respToCalldata(resp, returnPrices);
|
|
67
|
-
if (result.length !== ids.length) {
|
|
68
|
-
if (failOnMissingFeeds) {
|
|
69
|
-
throw new Error(
|
|
70
|
-
`expected ${ids.length} price feeds, got ${result.length}`
|
|
71
|
-
);
|
|
72
|
-
} else {
|
|
73
|
-
logger?.warn(`expected ${ids.length} price feeds, got ${result.length}`);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
return result;
|
|
77
|
-
}
|
|
78
|
-
function respToCalldata(resp, returnPrices) {
|
|
79
|
-
if (resp.binary.data.length === 0) {
|
|
80
|
-
return [];
|
|
81
|
-
}
|
|
82
|
-
const updates = splitAccumulatorUpdates(resp.binary.data[0]);
|
|
83
|
-
const priceMap = /* @__PURE__ */ new Map();
|
|
84
|
-
if (returnPrices && resp.parsed) {
|
|
85
|
-
for (const feed of resp.parsed) {
|
|
86
|
-
const feedId = feed.id.startsWith("0x") ? feed.id : `0x${feed.id}`;
|
|
87
|
-
priceMap.set(feedId.toLowerCase(), {
|
|
88
|
-
price: BigInt(feed.price.price),
|
|
89
|
-
decimals: Math.abs(feed.price.expo)
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
return updates.map(({ data, dataFeedId, timestamp }) => {
|
|
94
|
-
const base = {
|
|
95
|
-
dataFeedId,
|
|
96
|
-
data: (0, import_viem.encodeAbiParameters)(
|
|
97
|
-
[{ type: "uint256" }, { type: "bytes[]" }],
|
|
98
|
-
[BigInt(timestamp), [data]]
|
|
99
|
-
),
|
|
100
|
-
timestamp,
|
|
101
|
-
cached: false
|
|
102
|
-
};
|
|
103
|
-
if (returnPrices) {
|
|
104
|
-
const priceInfo = priceMap.get(dataFeedId.toLowerCase());
|
|
105
|
-
if (!priceInfo) {
|
|
106
|
-
throw new Error(`Price info not found for feed ${dataFeedId}`);
|
|
107
|
-
}
|
|
108
|
-
return {
|
|
109
|
-
...base,
|
|
110
|
-
price: priceInfo.price,
|
|
111
|
-
decimals: priceInfo.decimals
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
return base;
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
function splitAccumulatorUpdates(binary) {
|
|
118
|
-
const data = import_buffer.Buffer.from(binary, "hex");
|
|
119
|
-
const parsed = (0, import_PythAccumulatorUpdateData.parseAccumulatorUpdateData)(data);
|
|
120
|
-
const results = [];
|
|
121
|
-
for (let i = 0; i < parsed.updates.length; i++) {
|
|
122
|
-
const upd = parsed.updates[i].message;
|
|
123
|
-
const msg = (0, import_PythAccumulatorUpdateData.parsePriceFeedMessage)(upd);
|
|
124
|
-
results.push({
|
|
125
|
-
dataFeedId: (0, import_viem.toHex)(msg.feedId),
|
|
126
|
-
timestamp: Number(msg.publishTime),
|
|
127
|
-
data: (0, import_viem.toHex)((0, import_PythAccumulatorUpdateData.sliceAccumulatorUpdateData)(data, i, i + 1))
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
return results;
|
|
28
|
+
return [];
|
|
131
29
|
}
|
|
132
30
|
// Annotate the CommonJS export names for ESM import in node:
|
|
133
31
|
0 && (module.exports = {
|