@gearbox-protocol/sdk 3.0.0-vfour.334 → 3.0.0-vfour.336
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/dev/PriceFeedStore.js +15 -13
- package/dist/cjs/sdk/accounts/CreditAccountsService.js +20 -28
- package/dist/cjs/sdk/market/MarketRegister.js +22 -28
- package/dist/cjs/sdk/market/oracle/PriceOracleBaseContract.js +1 -1
- package/dist/cjs/sdk/market/pricefeeds/PriceFeedsRegister.js +37 -38
- package/dist/cjs/sdk/market/pricefeeds/RedstoneUpdater.js +30 -12
- package/dist/cjs/sdk/market/pricefeeds/index.js +0 -2
- package/dist/cjs/sdk/utils/viem/index.js +3 -1
- package/dist/cjs/sdk/utils/viem/simulateWithPriceUpdates.js +134 -0
- package/dist/esm/dev/PriceFeedStore.js +17 -15
- package/dist/esm/sdk/accounts/CreditAccountsService.js +21 -29
- package/dist/esm/sdk/market/MarketRegister.js +23 -29
- package/dist/esm/sdk/market/oracle/PriceOracleBaseContract.js +1 -1
- package/dist/esm/sdk/market/pricefeeds/PriceFeedsRegister.js +37 -38
- package/dist/esm/sdk/market/pricefeeds/RedstoneUpdater.js +29 -12
- package/dist/esm/sdk/market/pricefeeds/index.js +0 -1
- package/dist/esm/sdk/utils/viem/index.js +1 -0
- package/dist/esm/sdk/utils/viem/simulateWithPriceUpdates.js +114 -0
- package/dist/types/abi/errors.d.ts +1 -0
- package/dist/types/sdk/chain/chains.d.ts +1 -2
- package/dist/types/sdk/market/pricefeeds/PriceFeedsRegister.d.ts +1 -1
- package/dist/types/sdk/market/pricefeeds/RedstoneUpdater.d.ts +8 -3
- package/dist/types/sdk/market/pricefeeds/index.d.ts +0 -1
- package/dist/types/sdk/market/pricefeeds/types.d.ts +2 -2
- package/dist/types/sdk/types/transactions.d.ts +14 -0
- package/dist/types/sdk/utils/viem/index.d.ts +1 -0
- package/dist/types/sdk/utils/viem/simulateWithPriceUpdates.d.ts +28 -0
- package/package.json +1 -1
- package/dist/cjs/sdk/market/pricefeeds/utils.js +0 -42
- package/dist/esm/sdk/market/pricefeeds/utils.js +0 -18
- package/dist/types/sdk/market/pricefeeds/utils.d.ts +0 -33
|
@@ -65,19 +65,21 @@ class PriceFeedStore extends import_sdk.SDKConstruct {
|
|
|
65
65
|
if (update) {
|
|
66
66
|
const feeds = result.map((f) => this.sdk.priceFeeds.create(f));
|
|
67
67
|
const { txs } = await this.sdk.priceFeeds.generatePriceFeedsUpdateTxs(feeds);
|
|
68
|
-
const resp = await
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
68
|
+
const [resp] = await (0, import_sdk.simulateWithPriceUpdates)(
|
|
69
|
+
this.provider.publicClient,
|
|
70
|
+
{
|
|
71
|
+
priceUpdates: txs,
|
|
72
|
+
contracts: [
|
|
73
|
+
{
|
|
74
|
+
address: this.#compressor,
|
|
75
|
+
abi: import_compressors.iPriceFeedCompressorAbi,
|
|
76
|
+
functionName: "loadPriceFeedTree",
|
|
77
|
+
args: [priceFeeds]
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
);
|
|
82
|
+
return resp;
|
|
81
83
|
}
|
|
82
84
|
this.#logger?.debug(
|
|
83
85
|
`loaded ${result.length} price feed nodes from compressor`
|
|
@@ -28,7 +28,6 @@ var import_v300 = require("../../abi/v300.js");
|
|
|
28
28
|
var import_adapters = require("../../adapters/abi/adapters.js");
|
|
29
29
|
var import_base = require("../base/index.js");
|
|
30
30
|
var import_constants = require("../constants/index.js");
|
|
31
|
-
var import_market = require("../market/index.js");
|
|
32
31
|
var import_router = require("../router/index.js");
|
|
33
32
|
var import_sdk_gov_legacy = require("../sdk-gov-legacy/index.js");
|
|
34
33
|
var import_utils = require("../utils/index.js");
|
|
@@ -69,12 +68,12 @@ class CreditAccountsService extends import_base.SDKConstruct {
|
|
|
69
68
|
if (raw.success) {
|
|
70
69
|
return raw;
|
|
71
70
|
}
|
|
72
|
-
const { txs: priceUpdateTxs
|
|
71
|
+
const { txs: priceUpdateTxs } = await this.sdk.priceFeeds.generatePriceFeedsUpdateTxs(void 0, {
|
|
73
72
|
account
|
|
74
73
|
});
|
|
75
|
-
const
|
|
74
|
+
const [cad] = await (0, import_viem2.simulateWithPriceUpdates)(this.provider.publicClient, {
|
|
75
|
+
priceUpdates: priceUpdateTxs,
|
|
76
76
|
contracts: [
|
|
77
|
-
...priceUpdateTxs.map(import_market.rawTxToMulticallPriceUpdate),
|
|
78
77
|
{
|
|
79
78
|
abi: import_compressors.iCreditAccountCompressorAbi,
|
|
80
79
|
address: this.#compressor,
|
|
@@ -82,13 +81,8 @@ class CreditAccountsService extends import_base.SDKConstruct {
|
|
|
82
81
|
args: [account]
|
|
83
82
|
}
|
|
84
83
|
],
|
|
85
|
-
allowFailure: false,
|
|
86
|
-
// gas: 550_000_000n,
|
|
87
|
-
batchSize: 0,
|
|
88
|
-
// we cannot have price updates and compressor request in different batches
|
|
89
84
|
blockNumber
|
|
90
85
|
});
|
|
91
|
-
const cad = resp.pop();
|
|
92
86
|
return cad;
|
|
93
87
|
}
|
|
94
88
|
/**
|
|
@@ -122,7 +116,7 @@ class CreditAccountsService extends import_base.SDKConstruct {
|
|
|
122
116
|
minHealthFactor,
|
|
123
117
|
maxHealthFactor
|
|
124
118
|
};
|
|
125
|
-
const { txs: priceUpdateTxs
|
|
119
|
+
const { txs: priceUpdateTxs } = await this.sdk.priceFeeds.generatePriceFeedsUpdateTxs();
|
|
126
120
|
const allCAs = [];
|
|
127
121
|
for (const reverting of [false, true]) {
|
|
128
122
|
let offset = 0n;
|
|
@@ -703,24 +697,22 @@ class CreditAccountsService extends import_base.SDKConstruct {
|
|
|
703
697
|
async #getCreditAccounts(args, priceUpdateTxs, options) {
|
|
704
698
|
const blockNumber = options?.blockNumber;
|
|
705
699
|
if (priceUpdateTxs?.length) {
|
|
706
|
-
const resp = await (0, import_viem2.
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
const getCreditAccountsResp = resp.pop();
|
|
723
|
-
return getCreditAccountsResp;
|
|
700
|
+
const [resp] = await (0, import_viem2.simulateWithPriceUpdates)(
|
|
701
|
+
this.provider.publicClient,
|
|
702
|
+
{
|
|
703
|
+
priceUpdates: priceUpdateTxs,
|
|
704
|
+
contracts: [
|
|
705
|
+
{
|
|
706
|
+
abi: import_compressors.iCreditAccountCompressorAbi,
|
|
707
|
+
address: this.#compressor,
|
|
708
|
+
functionName: "getCreditAccounts",
|
|
709
|
+
args
|
|
710
|
+
}
|
|
711
|
+
],
|
|
712
|
+
blockNumber
|
|
713
|
+
}
|
|
714
|
+
);
|
|
715
|
+
return resp;
|
|
724
716
|
}
|
|
725
717
|
return this.provider.publicClient.readContract({
|
|
726
718
|
abi: import_compressors.iCreditAccountCompressorAbi,
|
|
@@ -27,7 +27,6 @@ var import_constants = require("../constants/index.js");
|
|
|
27
27
|
var import_utils = require("../utils/index.js");
|
|
28
28
|
var import_viem = require("../utils/viem/index.js");
|
|
29
29
|
var import_MarketSuite = require("./MarketSuite.js");
|
|
30
|
-
var import_pricefeeds = require("./pricefeeds/index.js");
|
|
31
30
|
class MarketRegister extends import_base.SDKConstruct {
|
|
32
31
|
#logger;
|
|
33
32
|
/**
|
|
@@ -102,22 +101,21 @@ class MarketRegister extends import_base.SDKConstruct {
|
|
|
102
101
|
);
|
|
103
102
|
let markets = [];
|
|
104
103
|
if (txs.length) {
|
|
105
|
-
const resp = await (0, import_viem.
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
markets = resp.pop();
|
|
104
|
+
const [resp] = await (0, import_viem.simulateWithPriceUpdates)(
|
|
105
|
+
this.provider.publicClient,
|
|
106
|
+
{
|
|
107
|
+
priceUpdates: txs,
|
|
108
|
+
contracts: [
|
|
109
|
+
{
|
|
110
|
+
abi: import_compressors.iMarketCompressorAbi,
|
|
111
|
+
address: marketCompressorAddress,
|
|
112
|
+
functionName: "getMarkets",
|
|
113
|
+
args: [this.#marketFilter]
|
|
114
|
+
}
|
|
115
|
+
]
|
|
116
|
+
}
|
|
117
|
+
);
|
|
118
|
+
markets = resp;
|
|
121
119
|
} else {
|
|
122
120
|
markets = await this.provider.publicClient.readContract({
|
|
123
121
|
abi: import_compressors.iMarketCompressorAbi,
|
|
@@ -145,17 +143,13 @@ class MarketRegister extends import_base.SDKConstruct {
|
|
|
145
143
|
return;
|
|
146
144
|
}
|
|
147
145
|
const { txs } = await this.sdk.priceFeeds.generatePriceFeedsUpdateTxs();
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
batchSize: 0
|
|
156
|
-
// we cannot have price updates and compressor request in different batches
|
|
157
|
-
});
|
|
158
|
-
const oraclesStates = resp.slice(txs.length);
|
|
146
|
+
const oraclesStates = await (0, import_viem.simulateWithPriceUpdates)(
|
|
147
|
+
this.provider.publicClient,
|
|
148
|
+
{
|
|
149
|
+
priceUpdates: txs,
|
|
150
|
+
contracts: multicalls.map((mc) => mc.call)
|
|
151
|
+
}
|
|
152
|
+
);
|
|
159
153
|
for (let i = 0; i < multicalls.length; i++) {
|
|
160
154
|
const handler = multicalls[i].onResult;
|
|
161
155
|
const result = oraclesStates[i];
|
|
@@ -107,7 +107,7 @@ class PriceOracleBaseContract extends import_base.BaseContract {
|
|
|
107
107
|
}
|
|
108
108
|
const { txs } = updates;
|
|
109
109
|
for (const tx of txs) {
|
|
110
|
-
const { to: priceFeed, callData, description } = tx;
|
|
110
|
+
const { to: priceFeed, callData, description } = tx.raw;
|
|
111
111
|
const [token, reserve] = this.findTokenForPriceFeed(priceFeed);
|
|
112
112
|
if (!token) {
|
|
113
113
|
this.logger?.debug(
|
|
@@ -65,7 +65,43 @@ class PriceFeedRegister extends import_base.SDKConstruct {
|
|
|
65
65
|
*/
|
|
66
66
|
async generatePriceFeedsUpdateTxs(priceFeeds, logContext = {}) {
|
|
67
67
|
const updateables = priceFeeds ? priceFeeds.flatMap((pf) => pf.updatableDependencies()) : this.#feeds.values();
|
|
68
|
-
|
|
68
|
+
const txs = [];
|
|
69
|
+
const redstonePFs = [];
|
|
70
|
+
const latestUpdate = {
|
|
71
|
+
redstone: [],
|
|
72
|
+
timestamp: Math.floor(Date.now() / 1e3)
|
|
73
|
+
};
|
|
74
|
+
for (const pf of updateables) {
|
|
75
|
+
if ((0, import_RedstonePriceFeed.isRedstone)(pf)) {
|
|
76
|
+
redstonePFs.push(pf);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
let maxTimestamp = 0;
|
|
80
|
+
if (redstonePFs.length > 0) {
|
|
81
|
+
const redstoneUpdates = await this.redstoneUpdater.getUpdateTxs(
|
|
82
|
+
redstonePFs,
|
|
83
|
+
logContext
|
|
84
|
+
);
|
|
85
|
+
for (const tx of redstoneUpdates) {
|
|
86
|
+
const { data } = tx;
|
|
87
|
+
const { timestamp } = data;
|
|
88
|
+
if (timestamp > maxTimestamp) {
|
|
89
|
+
maxTimestamp = timestamp;
|
|
90
|
+
}
|
|
91
|
+
txs.push(tx);
|
|
92
|
+
latestUpdate.redstone.push(data);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const result = { txs, timestamp: maxTimestamp };
|
|
96
|
+
this.logger?.debug(
|
|
97
|
+
logContext,
|
|
98
|
+
`generated ${txs.length} price feed update transactions, timestamp: ${maxTimestamp}`
|
|
99
|
+
);
|
|
100
|
+
if (txs.length) {
|
|
101
|
+
await this.#hooks.triggerHooks("updatesGenerated", result);
|
|
102
|
+
}
|
|
103
|
+
this.#latestUpdate = latestUpdate;
|
|
104
|
+
return result;
|
|
69
105
|
}
|
|
70
106
|
has(address) {
|
|
71
107
|
return this.#feeds.has(address);
|
|
@@ -114,43 +150,6 @@ class PriceFeedRegister extends import_base.SDKConstruct {
|
|
|
114
150
|
this.logger?.debug(`loaded ${result.length} partial updatable price feeds`);
|
|
115
151
|
return result.map((baseParams) => this.#createUpdatableProxy({ baseParams }));
|
|
116
152
|
}
|
|
117
|
-
async #generatePriceFeedsUpdateTxs(updateables, logContext = {}) {
|
|
118
|
-
const txs = [];
|
|
119
|
-
const redstonePFs = [];
|
|
120
|
-
const latestUpdate = {
|
|
121
|
-
redstone: [],
|
|
122
|
-
timestamp: Math.floor(Date.now() / 1e3)
|
|
123
|
-
};
|
|
124
|
-
for (const pf of updateables) {
|
|
125
|
-
if ((0, import_RedstonePriceFeed.isRedstone)(pf)) {
|
|
126
|
-
redstonePFs.push(pf);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
let maxTimestamp = 0;
|
|
130
|
-
if (redstonePFs.length > 0) {
|
|
131
|
-
const redstoneUpdates = await this.redstoneUpdater.getUpdateTxs(
|
|
132
|
-
redstonePFs,
|
|
133
|
-
logContext
|
|
134
|
-
);
|
|
135
|
-
for (const { tx, timestamp, ...rest } of redstoneUpdates) {
|
|
136
|
-
if (timestamp > maxTimestamp) {
|
|
137
|
-
maxTimestamp = timestamp;
|
|
138
|
-
}
|
|
139
|
-
txs.push(tx);
|
|
140
|
-
latestUpdate.redstone.push({ ...rest, timestamp });
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
const result = { txs, timestamp: maxTimestamp };
|
|
144
|
-
this.logger?.debug(
|
|
145
|
-
logContext,
|
|
146
|
-
`generated ${txs.length} price feed update transactions, timestamp: ${maxTimestamp}`
|
|
147
|
-
);
|
|
148
|
-
if (txs.length) {
|
|
149
|
-
await this.#hooks.triggerHooks("updatesGenerated", result);
|
|
150
|
-
}
|
|
151
|
-
this.#latestUpdate = latestUpdate;
|
|
152
|
-
return result;
|
|
153
|
-
}
|
|
154
153
|
create(data) {
|
|
155
154
|
const contractType = (0, import_utils.bytes32ToString)(
|
|
156
155
|
data.baseParams.contractType
|
|
@@ -18,6 +18,7 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var RedstoneUpdater_exports = {};
|
|
20
20
|
__export(RedstoneUpdater_exports, {
|
|
21
|
+
RedstoneUpdateTx: () => RedstoneUpdateTx,
|
|
21
22
|
RedstoneUpdater: () => RedstoneUpdater
|
|
22
23
|
});
|
|
23
24
|
module.exports = __toCommonJS(RedstoneUpdater_exports);
|
|
@@ -26,6 +27,18 @@ var import_protocol = require("@redstone-finance/protocol");
|
|
|
26
27
|
var import_viem = require("viem");
|
|
27
28
|
var import_base = require("../../base/index.js");
|
|
28
29
|
var import_utils = require("../../utils/index.js");
|
|
30
|
+
class RedstoneUpdateTx {
|
|
31
|
+
raw;
|
|
32
|
+
data;
|
|
33
|
+
constructor(raw, data) {
|
|
34
|
+
this.raw = raw;
|
|
35
|
+
this.data = data;
|
|
36
|
+
}
|
|
37
|
+
get pretty() {
|
|
38
|
+
const cached = this.data.cached ? " (cached)" : "";
|
|
39
|
+
return `redstone feed ${this.data.dataFeedId} at ${this.data.priceFeed} with timestamp ${this.data.timestamp}${cached}`;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
29
42
|
class RedstoneUpdater extends import_base.SDKConstruct {
|
|
30
43
|
#logger;
|
|
31
44
|
#cache = /* @__PURE__ */ new Map();
|
|
@@ -76,18 +89,22 @@ class RedstoneUpdater extends import_base.SDKConstruct {
|
|
|
76
89
|
if (!priceFeed) {
|
|
77
90
|
throw new Error(`cannot get price feed address for ${dataFeedId}`);
|
|
78
91
|
}
|
|
79
|
-
results.push(
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
92
|
+
results.push(
|
|
93
|
+
new RedstoneUpdateTx(
|
|
94
|
+
priceFeed.createRawTx({
|
|
95
|
+
functionName: "updatePrice",
|
|
96
|
+
args: [data],
|
|
97
|
+
description: `updating price for ${dataFeedId} [${this.sdk.provider.addressLabels.get(priceFeed.address)}]`
|
|
98
|
+
}),
|
|
99
|
+
{
|
|
100
|
+
dataFeedId,
|
|
101
|
+
dataServiceId,
|
|
102
|
+
priceFeed: priceFeed.address.toLowerCase(),
|
|
103
|
+
timestamp,
|
|
104
|
+
cached
|
|
105
|
+
}
|
|
106
|
+
)
|
|
107
|
+
);
|
|
91
108
|
}
|
|
92
109
|
}
|
|
93
110
|
this.#logger?.debug(
|
|
@@ -242,5 +259,6 @@ function getCalldataWithTimestamp(dataFeedId, packages, unsignedMetadata) {
|
|
|
242
259
|
}
|
|
243
260
|
// Annotate the CommonJS export names for ESM import in node:
|
|
244
261
|
0 && (module.exports = {
|
|
262
|
+
RedstoneUpdateTx,
|
|
245
263
|
RedstoneUpdater
|
|
246
264
|
});
|
|
@@ -32,7 +32,6 @@ __reExport(pricefeeds_exports, require("./PriceFeedsRegister.js"), module.export
|
|
|
32
32
|
__reExport(pricefeeds_exports, require("./PythPriceFeed.js"), module.exports);
|
|
33
33
|
__reExport(pricefeeds_exports, require("./RedstonePriceFeed.js"), module.exports);
|
|
34
34
|
__reExport(pricefeeds_exports, require("./types.js"), module.exports);
|
|
35
|
-
__reExport(pricefeeds_exports, require("./utils.js"), module.exports);
|
|
36
35
|
__reExport(pricefeeds_exports, require("./WstETHPriceFeed.js"), module.exports);
|
|
37
36
|
__reExport(pricefeeds_exports, require("./YearnPriceFeed.js"), module.exports);
|
|
38
37
|
__reExport(pricefeeds_exports, require("./ZeroPriceFeed.js"), module.exports);
|
|
@@ -55,7 +54,6 @@ __reExport(pricefeeds_exports, require("./ZeroPriceFeed.js"), module.exports);
|
|
|
55
54
|
...require("./PythPriceFeed.js"),
|
|
56
55
|
...require("./RedstonePriceFeed.js"),
|
|
57
56
|
...require("./types.js"),
|
|
58
|
-
...require("./utils.js"),
|
|
59
57
|
...require("./WstETHPriceFeed.js"),
|
|
60
58
|
...require("./YearnPriceFeed.js"),
|
|
61
59
|
...require("./ZeroPriceFeed.js")
|
|
@@ -18,9 +18,11 @@ module.exports = __toCommonJS(viem_exports);
|
|
|
18
18
|
__reExport(viem_exports, require("./detectNetwork.js"), module.exports);
|
|
19
19
|
__reExport(viem_exports, require("./sendRawTx.js"), module.exports);
|
|
20
20
|
__reExport(viem_exports, require("./simulateMulticall.js"), module.exports);
|
|
21
|
+
__reExport(viem_exports, require("./simulateWithPriceUpdates.js"), module.exports);
|
|
21
22
|
// Annotate the CommonJS export names for ESM import in node:
|
|
22
23
|
0 && (module.exports = {
|
|
23
24
|
...require("./detectNetwork.js"),
|
|
24
25
|
...require("./sendRawTx.js"),
|
|
25
|
-
...require("./simulateMulticall.js")
|
|
26
|
+
...require("./simulateMulticall.js"),
|
|
27
|
+
...require("./simulateWithPriceUpdates.js")
|
|
26
28
|
});
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var simulateWithPriceUpdates_exports = {};
|
|
20
|
+
__export(simulateWithPriceUpdates_exports, {
|
|
21
|
+
SimulateWithPriceUpdatesError: () => SimulateWithPriceUpdatesError,
|
|
22
|
+
simulateWithPriceUpdates: () => simulateWithPriceUpdates
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(simulateWithPriceUpdates_exports);
|
|
25
|
+
var import_viem = require("viem");
|
|
26
|
+
var import_abi = require("../../../abi/index.js");
|
|
27
|
+
var import_hex = require("../hex.js");
|
|
28
|
+
var import_simulateMulticall = require("./simulateMulticall.js");
|
|
29
|
+
const updatePriceFeedAbi = [...import_abi.iUpdatablePriceFeedAbi, ...import_abi.errorAbis];
|
|
30
|
+
async function simulateWithPriceUpdates(client, parameters) {
|
|
31
|
+
const { contracts: restContracts, priceUpdates, ...rest } = parameters;
|
|
32
|
+
if (restContracts.length === 0) {
|
|
33
|
+
throw new SimulateWithPriceUpdatesError(
|
|
34
|
+
new import_viem.BaseError("no contracts calls provided"),
|
|
35
|
+
priceUpdates,
|
|
36
|
+
restContracts
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
const contracts = [
|
|
41
|
+
...priceUpdates.map(rawTxToMulticallPriceUpdate),
|
|
42
|
+
...restContracts
|
|
43
|
+
];
|
|
44
|
+
const resp = await (0, import_simulateMulticall.simulateMulticall)(client, {
|
|
45
|
+
contracts,
|
|
46
|
+
...rest,
|
|
47
|
+
allowFailure: false,
|
|
48
|
+
batchSize: 0
|
|
49
|
+
// we cannot have price updates and compressor request in different batches
|
|
50
|
+
});
|
|
51
|
+
const restResults = resp.slice(priceUpdates.length);
|
|
52
|
+
return restResults;
|
|
53
|
+
} catch (e) {
|
|
54
|
+
throw new SimulateWithPriceUpdatesError(
|
|
55
|
+
e,
|
|
56
|
+
priceUpdates,
|
|
57
|
+
restContracts
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function rawTxToMulticallPriceUpdate({
|
|
62
|
+
raw
|
|
63
|
+
}) {
|
|
64
|
+
const { to, callData } = raw;
|
|
65
|
+
const { args, functionName } = (0, import_viem.decodeFunctionData)({
|
|
66
|
+
abi: updatePriceFeedAbi,
|
|
67
|
+
data: callData
|
|
68
|
+
});
|
|
69
|
+
if (functionName !== "updatePrice") {
|
|
70
|
+
throw new Error(
|
|
71
|
+
`call to function ${functionName} cannot be converted to a price update`
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
abi: updatePriceFeedAbi,
|
|
76
|
+
address: to,
|
|
77
|
+
functionName,
|
|
78
|
+
args
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
class SimulateWithPriceUpdatesError extends import_viem.BaseError {
|
|
82
|
+
cause;
|
|
83
|
+
priceUpdates;
|
|
84
|
+
calls;
|
|
85
|
+
constructor(cause, priceUpdates, calls) {
|
|
86
|
+
let failedPriceFeed = "0x0";
|
|
87
|
+
const base = cause instanceof import_viem.BaseError ? cause : {};
|
|
88
|
+
let causeMeta = base.metaMessages ? [...base.metaMessages, " "] : [];
|
|
89
|
+
if (base instanceof import_viem.ContractFunctionExecutionError && base.functionName === "updatePrice") {
|
|
90
|
+
failedPriceFeed = base.contractAddress ?? "0x0";
|
|
91
|
+
causeMeta = [
|
|
92
|
+
`simulate multicall with ${priceUpdates.length} price updates failed`,
|
|
93
|
+
" "
|
|
94
|
+
];
|
|
95
|
+
const updateRevert = cause instanceof import_viem.BaseError ? cause.walk(
|
|
96
|
+
(err) => err instanceof import_viem.ContractFunctionRevertedError
|
|
97
|
+
) : void 0;
|
|
98
|
+
if (updateRevert) {
|
|
99
|
+
causeMeta = [
|
|
100
|
+
`simulate multicall with ${priceUpdates.length} price updates failed: ${updateRevert.metaMessages?.[0]}`,
|
|
101
|
+
" "
|
|
102
|
+
];
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
const priceUpdatesMeta = [
|
|
106
|
+
"Price Updates:",
|
|
107
|
+
...priceUpdates.map(
|
|
108
|
+
(u) => `${(0, import_hex.hexEq)(u.data.priceFeed, failedPriceFeed) ? "[FAILED] " : ""}${u.pretty}`
|
|
109
|
+
)
|
|
110
|
+
];
|
|
111
|
+
const callsMeta = [
|
|
112
|
+
"Calls:",
|
|
113
|
+
...calls.map((c) => `${c.address}.${c.functionName}`)
|
|
114
|
+
];
|
|
115
|
+
super(
|
|
116
|
+
`simulate multicall with ${priceUpdates.length} price updates failed`,
|
|
117
|
+
{
|
|
118
|
+
cause: base,
|
|
119
|
+
metaMessages: [...causeMeta, ...priceUpdatesMeta, ...callsMeta].filter(
|
|
120
|
+
Boolean
|
|
121
|
+
),
|
|
122
|
+
name: "SimulateWithPriceUpdatesError"
|
|
123
|
+
}
|
|
124
|
+
);
|
|
125
|
+
this.cause = cause;
|
|
126
|
+
this.priceUpdates = priceUpdates;
|
|
127
|
+
this.calls = calls;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
131
|
+
0 && (module.exports = {
|
|
132
|
+
SimulateWithPriceUpdatesError,
|
|
133
|
+
simulateWithPriceUpdates
|
|
134
|
+
});
|
|
@@ -3,8 +3,8 @@ import { iPriceFeedStoreAbi } from "../abi/iPriceFeedStore.js";
|
|
|
3
3
|
import {
|
|
4
4
|
AddressMap,
|
|
5
5
|
AP_PRICE_FEED_COMPRESSOR,
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
SDKConstruct,
|
|
7
|
+
simulateWithPriceUpdates
|
|
8
8
|
} from "../sdk/index.js";
|
|
9
9
|
class PriceFeedStore extends SDKConstruct {
|
|
10
10
|
#store;
|
|
@@ -47,19 +47,21 @@ class PriceFeedStore extends SDKConstruct {
|
|
|
47
47
|
if (update) {
|
|
48
48
|
const feeds = result.map((f) => this.sdk.priceFeeds.create(f));
|
|
49
49
|
const { txs } = await this.sdk.priceFeeds.generatePriceFeedsUpdateTxs(feeds);
|
|
50
|
-
const resp = await
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
50
|
+
const [resp] = await simulateWithPriceUpdates(
|
|
51
|
+
this.provider.publicClient,
|
|
52
|
+
{
|
|
53
|
+
priceUpdates: txs,
|
|
54
|
+
contracts: [
|
|
55
|
+
{
|
|
56
|
+
address: this.#compressor,
|
|
57
|
+
abi: iPriceFeedCompressorAbi,
|
|
58
|
+
functionName: "loadPriceFeedTree",
|
|
59
|
+
args: [priceFeeds]
|
|
60
|
+
}
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
);
|
|
64
|
+
return resp;
|
|
63
65
|
}
|
|
64
66
|
this.#logger?.debug(
|
|
65
67
|
`loaded ${result.length} price feed nodes from compressor`
|
|
@@ -20,7 +20,6 @@ import {
|
|
|
20
20
|
MIN_INT96,
|
|
21
21
|
NOT_DEPLOYED
|
|
22
22
|
} from "../constants/index.js";
|
|
23
|
-
import { rawTxToMulticallPriceUpdate } from "../market/index.js";
|
|
24
23
|
import {
|
|
25
24
|
assetsMap
|
|
26
25
|
} from "../router/index.js";
|
|
@@ -38,7 +37,7 @@ import {
|
|
|
38
37
|
tokenSymbolByAddress
|
|
39
38
|
} from "../sdk-gov-legacy/index.js";
|
|
40
39
|
import { childLogger } from "../utils/index.js";
|
|
41
|
-
import {
|
|
40
|
+
import { simulateWithPriceUpdates } from "../utils/viem/index.js";
|
|
42
41
|
class CreditAccountsService extends SDKConstruct {
|
|
43
42
|
#compressor;
|
|
44
43
|
#batchSize;
|
|
@@ -75,12 +74,12 @@ class CreditAccountsService extends SDKConstruct {
|
|
|
75
74
|
if (raw.success) {
|
|
76
75
|
return raw;
|
|
77
76
|
}
|
|
78
|
-
const { txs: priceUpdateTxs
|
|
77
|
+
const { txs: priceUpdateTxs } = await this.sdk.priceFeeds.generatePriceFeedsUpdateTxs(void 0, {
|
|
79
78
|
account
|
|
80
79
|
});
|
|
81
|
-
const
|
|
80
|
+
const [cad] = await simulateWithPriceUpdates(this.provider.publicClient, {
|
|
81
|
+
priceUpdates: priceUpdateTxs,
|
|
82
82
|
contracts: [
|
|
83
|
-
...priceUpdateTxs.map(rawTxToMulticallPriceUpdate),
|
|
84
83
|
{
|
|
85
84
|
abi: iCreditAccountCompressorAbi,
|
|
86
85
|
address: this.#compressor,
|
|
@@ -88,13 +87,8 @@ class CreditAccountsService extends SDKConstruct {
|
|
|
88
87
|
args: [account]
|
|
89
88
|
}
|
|
90
89
|
],
|
|
91
|
-
allowFailure: false,
|
|
92
|
-
// gas: 550_000_000n,
|
|
93
|
-
batchSize: 0,
|
|
94
|
-
// we cannot have price updates and compressor request in different batches
|
|
95
90
|
blockNumber
|
|
96
91
|
});
|
|
97
|
-
const cad = resp.pop();
|
|
98
92
|
return cad;
|
|
99
93
|
}
|
|
100
94
|
/**
|
|
@@ -128,7 +122,7 @@ class CreditAccountsService extends SDKConstruct {
|
|
|
128
122
|
minHealthFactor,
|
|
129
123
|
maxHealthFactor
|
|
130
124
|
};
|
|
131
|
-
const { txs: priceUpdateTxs
|
|
125
|
+
const { txs: priceUpdateTxs } = await this.sdk.priceFeeds.generatePriceFeedsUpdateTxs();
|
|
132
126
|
const allCAs = [];
|
|
133
127
|
for (const reverting of [false, true]) {
|
|
134
128
|
let offset = 0n;
|
|
@@ -709,24 +703,22 @@ class CreditAccountsService extends SDKConstruct {
|
|
|
709
703
|
async #getCreditAccounts(args, priceUpdateTxs, options) {
|
|
710
704
|
const blockNumber = options?.blockNumber;
|
|
711
705
|
if (priceUpdateTxs?.length) {
|
|
712
|
-
const resp = await
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
const getCreditAccountsResp = resp.pop();
|
|
729
|
-
return getCreditAccountsResp;
|
|
706
|
+
const [resp] = await simulateWithPriceUpdates(
|
|
707
|
+
this.provider.publicClient,
|
|
708
|
+
{
|
|
709
|
+
priceUpdates: priceUpdateTxs,
|
|
710
|
+
contracts: [
|
|
711
|
+
{
|
|
712
|
+
abi: iCreditAccountCompressorAbi,
|
|
713
|
+
address: this.#compressor,
|
|
714
|
+
functionName: "getCreditAccounts",
|
|
715
|
+
args
|
|
716
|
+
}
|
|
717
|
+
],
|
|
718
|
+
blockNumber
|
|
719
|
+
}
|
|
720
|
+
);
|
|
721
|
+
return resp;
|
|
730
722
|
}
|
|
731
723
|
return this.provider.publicClient.readContract({
|
|
732
724
|
abi: iCreditAccountCompressorAbi,
|
|
@@ -2,9 +2,8 @@ import { iMarketCompressorAbi } from "../../abi/compressors.js";
|
|
|
2
2
|
import { SDKConstruct } from "../base/index.js";
|
|
3
3
|
import { ADDRESS_0X0, AP_MARKET_COMPRESSOR } from "../constants/index.js";
|
|
4
4
|
import { AddressMap, childLogger } from "../utils/index.js";
|
|
5
|
-
import {
|
|
5
|
+
import { simulateWithPriceUpdates } from "../utils/viem/index.js";
|
|
6
6
|
import { MarketSuite } from "./MarketSuite.js";
|
|
7
|
-
import { rawTxToMulticallPriceUpdate } from "./pricefeeds/index.js";
|
|
8
7
|
class MarketRegister extends SDKConstruct {
|
|
9
8
|
#logger;
|
|
10
9
|
/**
|
|
@@ -79,22 +78,21 @@ class MarketRegister extends SDKConstruct {
|
|
|
79
78
|
);
|
|
80
79
|
let markets = [];
|
|
81
80
|
if (txs.length) {
|
|
82
|
-
const resp = await
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
markets = resp.pop();
|
|
81
|
+
const [resp] = await simulateWithPriceUpdates(
|
|
82
|
+
this.provider.publicClient,
|
|
83
|
+
{
|
|
84
|
+
priceUpdates: txs,
|
|
85
|
+
contracts: [
|
|
86
|
+
{
|
|
87
|
+
abi: iMarketCompressorAbi,
|
|
88
|
+
address: marketCompressorAddress,
|
|
89
|
+
functionName: "getMarkets",
|
|
90
|
+
args: [this.#marketFilter]
|
|
91
|
+
}
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
markets = resp;
|
|
98
96
|
} else {
|
|
99
97
|
markets = await this.provider.publicClient.readContract({
|
|
100
98
|
abi: iMarketCompressorAbi,
|
|
@@ -122,17 +120,13 @@ class MarketRegister extends SDKConstruct {
|
|
|
122
120
|
return;
|
|
123
121
|
}
|
|
124
122
|
const { txs } = await this.sdk.priceFeeds.generatePriceFeedsUpdateTxs();
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
batchSize: 0
|
|
133
|
-
// we cannot have price updates and compressor request in different batches
|
|
134
|
-
});
|
|
135
|
-
const oraclesStates = resp.slice(txs.length);
|
|
123
|
+
const oraclesStates = await simulateWithPriceUpdates(
|
|
124
|
+
this.provider.publicClient,
|
|
125
|
+
{
|
|
126
|
+
priceUpdates: txs,
|
|
127
|
+
contracts: multicalls.map((mc) => mc.call)
|
|
128
|
+
}
|
|
129
|
+
);
|
|
136
130
|
for (let i = 0; i < multicalls.length; i++) {
|
|
137
131
|
const handler = multicalls[i].onResult;
|
|
138
132
|
const result = oraclesStates[i];
|
|
@@ -84,7 +84,7 @@ class PriceOracleBaseContract extends BaseContract {
|
|
|
84
84
|
}
|
|
85
85
|
const { txs } = updates;
|
|
86
86
|
for (const tx of txs) {
|
|
87
|
-
const { to: priceFeed, callData, description } = tx;
|
|
87
|
+
const { to: priceFeed, callData, description } = tx.raw;
|
|
88
88
|
const [token, reserve] = this.findTokenForPriceFeed(priceFeed);
|
|
89
89
|
if (!token) {
|
|
90
90
|
this.logger?.debug(
|
|
@@ -44,7 +44,43 @@ class PriceFeedRegister extends SDKConstruct {
|
|
|
44
44
|
*/
|
|
45
45
|
async generatePriceFeedsUpdateTxs(priceFeeds, logContext = {}) {
|
|
46
46
|
const updateables = priceFeeds ? priceFeeds.flatMap((pf) => pf.updatableDependencies()) : this.#feeds.values();
|
|
47
|
-
|
|
47
|
+
const txs = [];
|
|
48
|
+
const redstonePFs = [];
|
|
49
|
+
const latestUpdate = {
|
|
50
|
+
redstone: [],
|
|
51
|
+
timestamp: Math.floor(Date.now() / 1e3)
|
|
52
|
+
};
|
|
53
|
+
for (const pf of updateables) {
|
|
54
|
+
if (isRedstone(pf)) {
|
|
55
|
+
redstonePFs.push(pf);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
let maxTimestamp = 0;
|
|
59
|
+
if (redstonePFs.length > 0) {
|
|
60
|
+
const redstoneUpdates = await this.redstoneUpdater.getUpdateTxs(
|
|
61
|
+
redstonePFs,
|
|
62
|
+
logContext
|
|
63
|
+
);
|
|
64
|
+
for (const tx of redstoneUpdates) {
|
|
65
|
+
const { data } = tx;
|
|
66
|
+
const { timestamp } = data;
|
|
67
|
+
if (timestamp > maxTimestamp) {
|
|
68
|
+
maxTimestamp = timestamp;
|
|
69
|
+
}
|
|
70
|
+
txs.push(tx);
|
|
71
|
+
latestUpdate.redstone.push(data);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const result = { txs, timestamp: maxTimestamp };
|
|
75
|
+
this.logger?.debug(
|
|
76
|
+
logContext,
|
|
77
|
+
`generated ${txs.length} price feed update transactions, timestamp: ${maxTimestamp}`
|
|
78
|
+
);
|
|
79
|
+
if (txs.length) {
|
|
80
|
+
await this.#hooks.triggerHooks("updatesGenerated", result);
|
|
81
|
+
}
|
|
82
|
+
this.#latestUpdate = latestUpdate;
|
|
83
|
+
return result;
|
|
48
84
|
}
|
|
49
85
|
has(address) {
|
|
50
86
|
return this.#feeds.has(address);
|
|
@@ -93,43 +129,6 @@ class PriceFeedRegister extends SDKConstruct {
|
|
|
93
129
|
this.logger?.debug(`loaded ${result.length} partial updatable price feeds`);
|
|
94
130
|
return result.map((baseParams) => this.#createUpdatableProxy({ baseParams }));
|
|
95
131
|
}
|
|
96
|
-
async #generatePriceFeedsUpdateTxs(updateables, logContext = {}) {
|
|
97
|
-
const txs = [];
|
|
98
|
-
const redstonePFs = [];
|
|
99
|
-
const latestUpdate = {
|
|
100
|
-
redstone: [],
|
|
101
|
-
timestamp: Math.floor(Date.now() / 1e3)
|
|
102
|
-
};
|
|
103
|
-
for (const pf of updateables) {
|
|
104
|
-
if (isRedstone(pf)) {
|
|
105
|
-
redstonePFs.push(pf);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
let maxTimestamp = 0;
|
|
109
|
-
if (redstonePFs.length > 0) {
|
|
110
|
-
const redstoneUpdates = await this.redstoneUpdater.getUpdateTxs(
|
|
111
|
-
redstonePFs,
|
|
112
|
-
logContext
|
|
113
|
-
);
|
|
114
|
-
for (const { tx, timestamp, ...rest } of redstoneUpdates) {
|
|
115
|
-
if (timestamp > maxTimestamp) {
|
|
116
|
-
maxTimestamp = timestamp;
|
|
117
|
-
}
|
|
118
|
-
txs.push(tx);
|
|
119
|
-
latestUpdate.redstone.push({ ...rest, timestamp });
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
const result = { txs, timestamp: maxTimestamp };
|
|
123
|
-
this.logger?.debug(
|
|
124
|
-
logContext,
|
|
125
|
-
`generated ${txs.length} price feed update transactions, timestamp: ${maxTimestamp}`
|
|
126
|
-
);
|
|
127
|
-
if (txs.length) {
|
|
128
|
-
await this.#hooks.triggerHooks("updatesGenerated", result);
|
|
129
|
-
}
|
|
130
|
-
this.#latestUpdate = latestUpdate;
|
|
131
|
-
return result;
|
|
132
|
-
}
|
|
133
132
|
create(data) {
|
|
134
133
|
const contractType = bytes32ToString(
|
|
135
134
|
data.baseParams.contractType
|
|
@@ -3,6 +3,18 @@ import { RedstonePayload } from "@redstone-finance/protocol";
|
|
|
3
3
|
import { encodeAbiParameters, toBytes } from "viem";
|
|
4
4
|
import { SDKConstruct } from "../../base/index.js";
|
|
5
5
|
import { childLogger, retry } from "../../utils/index.js";
|
|
6
|
+
class RedstoneUpdateTx {
|
|
7
|
+
raw;
|
|
8
|
+
data;
|
|
9
|
+
constructor(raw, data) {
|
|
10
|
+
this.raw = raw;
|
|
11
|
+
this.data = data;
|
|
12
|
+
}
|
|
13
|
+
get pretty() {
|
|
14
|
+
const cached = this.data.cached ? " (cached)" : "";
|
|
15
|
+
return `redstone feed ${this.data.dataFeedId} at ${this.data.priceFeed} with timestamp ${this.data.timestamp}${cached}`;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
6
18
|
class RedstoneUpdater extends SDKConstruct {
|
|
7
19
|
#logger;
|
|
8
20
|
#cache = /* @__PURE__ */ new Map();
|
|
@@ -53,18 +65,22 @@ class RedstoneUpdater extends SDKConstruct {
|
|
|
53
65
|
if (!priceFeed) {
|
|
54
66
|
throw new Error(`cannot get price feed address for ${dataFeedId}`);
|
|
55
67
|
}
|
|
56
|
-
results.push(
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
+
results.push(
|
|
69
|
+
new RedstoneUpdateTx(
|
|
70
|
+
priceFeed.createRawTx({
|
|
71
|
+
functionName: "updatePrice",
|
|
72
|
+
args: [data],
|
|
73
|
+
description: `updating price for ${dataFeedId} [${this.sdk.provider.addressLabels.get(priceFeed.address)}]`
|
|
74
|
+
}),
|
|
75
|
+
{
|
|
76
|
+
dataFeedId,
|
|
77
|
+
dataServiceId,
|
|
78
|
+
priceFeed: priceFeed.address.toLowerCase(),
|
|
79
|
+
timestamp,
|
|
80
|
+
cached
|
|
81
|
+
}
|
|
82
|
+
)
|
|
83
|
+
);
|
|
68
84
|
}
|
|
69
85
|
}
|
|
70
86
|
this.#logger?.debug(
|
|
@@ -218,5 +234,6 @@ function getCalldataWithTimestamp(dataFeedId, packages, unsignedMetadata) {
|
|
|
218
234
|
};
|
|
219
235
|
}
|
|
220
236
|
export {
|
|
237
|
+
RedstoneUpdateTx,
|
|
221
238
|
RedstoneUpdater
|
|
222
239
|
};
|
|
@@ -15,7 +15,6 @@ export * from "./PriceFeedsRegister.js";
|
|
|
15
15
|
export * from "./PythPriceFeed.js";
|
|
16
16
|
export * from "./RedstonePriceFeed.js";
|
|
17
17
|
export * from "./types.js";
|
|
18
|
-
export * from "./utils.js";
|
|
19
18
|
export * from "./WstETHPriceFeed.js";
|
|
20
19
|
export * from "./YearnPriceFeed.js";
|
|
21
20
|
export * from "./ZeroPriceFeed.js";
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BaseError,
|
|
3
|
+
ContractFunctionExecutionError,
|
|
4
|
+
ContractFunctionRevertedError,
|
|
5
|
+
decodeFunctionData
|
|
6
|
+
} from "viem";
|
|
7
|
+
import { errorAbis, iUpdatablePriceFeedAbi } from "../../../abi/index.js";
|
|
8
|
+
import { hexEq } from "../hex.js";
|
|
9
|
+
import { simulateMulticall } from "./simulateMulticall.js";
|
|
10
|
+
const updatePriceFeedAbi = [...iUpdatablePriceFeedAbi, ...errorAbis];
|
|
11
|
+
async function simulateWithPriceUpdates(client, parameters) {
|
|
12
|
+
const { contracts: restContracts, priceUpdates, ...rest } = parameters;
|
|
13
|
+
if (restContracts.length === 0) {
|
|
14
|
+
throw new SimulateWithPriceUpdatesError(
|
|
15
|
+
new BaseError("no contracts calls provided"),
|
|
16
|
+
priceUpdates,
|
|
17
|
+
restContracts
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
const contracts = [
|
|
22
|
+
...priceUpdates.map(rawTxToMulticallPriceUpdate),
|
|
23
|
+
...restContracts
|
|
24
|
+
];
|
|
25
|
+
const resp = await simulateMulticall(client, {
|
|
26
|
+
contracts,
|
|
27
|
+
...rest,
|
|
28
|
+
allowFailure: false,
|
|
29
|
+
batchSize: 0
|
|
30
|
+
// we cannot have price updates and compressor request in different batches
|
|
31
|
+
});
|
|
32
|
+
const restResults = resp.slice(priceUpdates.length);
|
|
33
|
+
return restResults;
|
|
34
|
+
} catch (e) {
|
|
35
|
+
throw new SimulateWithPriceUpdatesError(
|
|
36
|
+
e,
|
|
37
|
+
priceUpdates,
|
|
38
|
+
restContracts
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function rawTxToMulticallPriceUpdate({
|
|
43
|
+
raw
|
|
44
|
+
}) {
|
|
45
|
+
const { to, callData } = raw;
|
|
46
|
+
const { args, functionName } = decodeFunctionData({
|
|
47
|
+
abi: updatePriceFeedAbi,
|
|
48
|
+
data: callData
|
|
49
|
+
});
|
|
50
|
+
if (functionName !== "updatePrice") {
|
|
51
|
+
throw new Error(
|
|
52
|
+
`call to function ${functionName} cannot be converted to a price update`
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
abi: updatePriceFeedAbi,
|
|
57
|
+
address: to,
|
|
58
|
+
functionName,
|
|
59
|
+
args
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
class SimulateWithPriceUpdatesError extends BaseError {
|
|
63
|
+
cause;
|
|
64
|
+
priceUpdates;
|
|
65
|
+
calls;
|
|
66
|
+
constructor(cause, priceUpdates, calls) {
|
|
67
|
+
let failedPriceFeed = "0x0";
|
|
68
|
+
const base = cause instanceof BaseError ? cause : {};
|
|
69
|
+
let causeMeta = base.metaMessages ? [...base.metaMessages, " "] : [];
|
|
70
|
+
if (base instanceof ContractFunctionExecutionError && base.functionName === "updatePrice") {
|
|
71
|
+
failedPriceFeed = base.contractAddress ?? "0x0";
|
|
72
|
+
causeMeta = [
|
|
73
|
+
`simulate multicall with ${priceUpdates.length} price updates failed`,
|
|
74
|
+
" "
|
|
75
|
+
];
|
|
76
|
+
const updateRevert = cause instanceof BaseError ? cause.walk(
|
|
77
|
+
(err) => err instanceof ContractFunctionRevertedError
|
|
78
|
+
) : void 0;
|
|
79
|
+
if (updateRevert) {
|
|
80
|
+
causeMeta = [
|
|
81
|
+
`simulate multicall with ${priceUpdates.length} price updates failed: ${updateRevert.metaMessages?.[0]}`,
|
|
82
|
+
" "
|
|
83
|
+
];
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const priceUpdatesMeta = [
|
|
87
|
+
"Price Updates:",
|
|
88
|
+
...priceUpdates.map(
|
|
89
|
+
(u) => `${hexEq(u.data.priceFeed, failedPriceFeed) ? "[FAILED] " : ""}${u.pretty}`
|
|
90
|
+
)
|
|
91
|
+
];
|
|
92
|
+
const callsMeta = [
|
|
93
|
+
"Calls:",
|
|
94
|
+
...calls.map((c) => `${c.address}.${c.functionName}`)
|
|
95
|
+
];
|
|
96
|
+
super(
|
|
97
|
+
`simulate multicall with ${priceUpdates.length} price updates failed`,
|
|
98
|
+
{
|
|
99
|
+
cause: base,
|
|
100
|
+
metaMessages: [...causeMeta, ...priceUpdatesMeta, ...callsMeta].filter(
|
|
101
|
+
Boolean
|
|
102
|
+
),
|
|
103
|
+
name: "SimulateWithPriceUpdatesError"
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
this.cause = cause;
|
|
107
|
+
this.priceUpdates = priceUpdates;
|
|
108
|
+
this.calls = calls;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
export {
|
|
112
|
+
SimulateWithPriceUpdatesError,
|
|
113
|
+
simulateWithPriceUpdates
|
|
114
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Address, Chain } from "viem";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
type Curator = "Chaos Labs" | "K3";
|
|
3
|
+
export type Curator = "Chaos Labs" | "K3";
|
|
4
4
|
export interface GearboxChain extends Chain {
|
|
5
5
|
network: NetworkType;
|
|
6
6
|
defaultMarketConfigurators: Record<Address, Curator>;
|
|
@@ -15,4 +15,3 @@ export declare function getChain(chainIdOrNetworkType: number | bigint | Network
|
|
|
15
15
|
export declare function getNetworkType(chainId: number | bigint): NetworkType;
|
|
16
16
|
export declare function isSupportedNetwork(chainId: number | undefined): chainId is number;
|
|
17
17
|
export declare function isPublicNetwork(networkOrChainId: NetworkType | number | bigint): boolean;
|
|
18
|
-
export {};
|
|
@@ -16,7 +16,7 @@ export type PriceFeedRegisterHooks = {
|
|
|
16
16
|
};
|
|
17
17
|
export interface LatestUpdate {
|
|
18
18
|
timestamp: number;
|
|
19
|
-
redstone:
|
|
19
|
+
redstone: RedstoneUpdateTask[];
|
|
20
20
|
}
|
|
21
21
|
/**
|
|
22
22
|
* PriceFeedRegister acts as a chain-level cache to avoid creating multiple contract instances.
|
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
import type { Address } from "viem";
|
|
2
2
|
import { SDKConstruct } from "../../base/index.js";
|
|
3
3
|
import type { GearboxSDK } from "../../GearboxSDK.js";
|
|
4
|
-
import type { RawTx } from "../../types/index.js";
|
|
4
|
+
import type { IPriceUpdateTx, RawTx } from "../../types/index.js";
|
|
5
5
|
import type { RedstonePriceFeedContract } from "./RedstonePriceFeed.js";
|
|
6
6
|
export interface RedstoneUpdateTask {
|
|
7
7
|
dataFeedId: string;
|
|
8
8
|
dataServiceId: string;
|
|
9
9
|
priceFeed: Address;
|
|
10
|
-
tx: RawTx;
|
|
11
10
|
timestamp: number;
|
|
12
11
|
cached: boolean;
|
|
13
12
|
}
|
|
13
|
+
export declare class RedstoneUpdateTx implements IPriceUpdateTx<RedstoneUpdateTask> {
|
|
14
|
+
readonly raw: RawTx;
|
|
15
|
+
readonly data: RedstoneUpdateTask;
|
|
16
|
+
constructor(raw: RawTx, data: RedstoneUpdateTask);
|
|
17
|
+
get pretty(): string;
|
|
18
|
+
}
|
|
14
19
|
/**
|
|
15
20
|
* Class to update multiple redstone price feeds at once
|
|
16
21
|
*/
|
|
@@ -25,5 +30,5 @@ export declare class RedstoneUpdater extends SDKConstruct {
|
|
|
25
30
|
* Set redstone gateways
|
|
26
31
|
*/
|
|
27
32
|
set gateways(gateways: string[]);
|
|
28
|
-
getUpdateTxs(feeds: RedstonePriceFeedContract[], logContext?: Record<string, any>): Promise<
|
|
33
|
+
getUpdateTxs(feeds: RedstonePriceFeedContract[], logContext?: Record<string, any>): Promise<RedstoneUpdateTx[]>;
|
|
29
34
|
}
|
|
@@ -15,7 +15,6 @@ export * from "./PriceFeedsRegister.js";
|
|
|
15
15
|
export * from "./PythPriceFeed.js";
|
|
16
16
|
export * from "./RedstonePriceFeed.js";
|
|
17
17
|
export * from "./types.js";
|
|
18
|
-
export * from "./utils.js";
|
|
19
18
|
export * from "./WstETHPriceFeed.js";
|
|
20
19
|
export * from "./YearnPriceFeed.js";
|
|
21
20
|
export * from "./ZeroPriceFeed.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { UnionOmit } from "viem";
|
|
2
2
|
import type { IBaseContract } from "../../base/index.js";
|
|
3
|
-
import type {
|
|
3
|
+
import type { IPriceUpdateTx, PriceFeedStateHuman } from "../../types/index.js";
|
|
4
4
|
import type { PriceFeedRef } from "./PriceFeedRef.js";
|
|
5
5
|
export type PriceFeedUsageType = "Main" | "Reserve";
|
|
6
6
|
export type PriceFeedContractTypeLegacy = "PF_BALANCER_STABLE_LP_ORACLE" | "PF_BALANCER_WEIGHTED_LP_ORACLE" | "PF_BOUNDED_ORACLE" | "PF_CHAINLINK_ORACLE" | "PF_COMPOSITE_ORACLE" | "PF_CURVE_CRYPTO_LP_ORACLE" | "PF_CURVE_STABLE_LP_ORACLE" | "PF_CURVE_USD_ORACLE" | "PF_ERC4626_ORACLE" | "PF_MELLOW_LRT_ORACLE" | "PF_PENDLE_PT_TWAP_ORACLE" | "PF_PYTH_ORACLE" | "PF_REDSTONE_ORACLE" | "PF_WSTETH_ORACLE" | "PF_YEARN_ORACLE" | "PF_ZERO_ORACLE";
|
|
@@ -35,6 +35,6 @@ export interface ILPPriceFeedContract extends IPriceFeedContract {
|
|
|
35
35
|
currentLowerBound: () => Promise<bigint>;
|
|
36
36
|
}
|
|
37
37
|
export interface UpdatePriceFeedsResult {
|
|
38
|
-
txs:
|
|
38
|
+
txs: IPriceUpdateTx[];
|
|
39
39
|
timestamp: number;
|
|
40
40
|
}
|
|
@@ -13,6 +13,20 @@ export interface RawTx {
|
|
|
13
13
|
contractInputsValues: Record<string, any>;
|
|
14
14
|
description?: string;
|
|
15
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* Wrapper interface for RawTx with diagnostic data
|
|
18
|
+
*/
|
|
19
|
+
export interface IPriceUpdateTx<Data extends {
|
|
20
|
+
timestamp: number;
|
|
21
|
+
priceFeed: Address;
|
|
22
|
+
} = {
|
|
23
|
+
priceFeed: Address;
|
|
24
|
+
timestamp: number;
|
|
25
|
+
}> {
|
|
26
|
+
raw: RawTx;
|
|
27
|
+
data: Data;
|
|
28
|
+
pretty: string;
|
|
29
|
+
}
|
|
16
30
|
export interface MultiCall {
|
|
17
31
|
target: Address;
|
|
18
32
|
callData: Hex;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { AbiStateMutability, Narrow } from "abitype";
|
|
2
|
+
import type { Chain, Client, ContractFunctionParameters, MulticallContracts, MulticallParameters, MulticallReturnType, Transport } from "viem";
|
|
3
|
+
import { BaseError } from "viem";
|
|
4
|
+
import type { IPriceUpdateTx } from "../../types/index.js";
|
|
5
|
+
export type SimulateWithPriceUpdatesParameters<contracts extends readonly unknown[] = readonly ContractFunctionParameters[], options extends {
|
|
6
|
+
optional?: boolean;
|
|
7
|
+
properties?: Record<string, any>;
|
|
8
|
+
} = {}> = MulticallParameters<contracts, false, options> & {
|
|
9
|
+
priceUpdates: IPriceUpdateTx[];
|
|
10
|
+
contracts: MulticallContracts<Narrow<contracts>, {
|
|
11
|
+
mutability: AbiStateMutability;
|
|
12
|
+
}>;
|
|
13
|
+
};
|
|
14
|
+
export type SimulateWithPriceUpdatesReturnType<contracts extends readonly unknown[] = readonly ContractFunctionParameters[], options extends {
|
|
15
|
+
error?: Error;
|
|
16
|
+
} = {
|
|
17
|
+
error: Error;
|
|
18
|
+
}> = MulticallReturnType<contracts, false, options>;
|
|
19
|
+
export declare function simulateWithPriceUpdates<const contracts extends readonly unknown[], chain extends Chain | undefined>(client: Client<Transport, chain>, parameters: SimulateWithPriceUpdatesParameters<contracts>): Promise<SimulateWithPriceUpdatesReturnType<contracts>>;
|
|
20
|
+
export type SimulateWithPriceUpdatesErrorType<contracts extends readonly unknown[]> = SimulateWithPriceUpdatesError<contracts> & {
|
|
21
|
+
name: "SimulateWithPriceUpdatesError";
|
|
22
|
+
};
|
|
23
|
+
export declare class SimulateWithPriceUpdatesError<contracts extends readonly unknown[]> extends BaseError {
|
|
24
|
+
cause: Error;
|
|
25
|
+
readonly priceUpdates: IPriceUpdateTx[];
|
|
26
|
+
readonly calls: MulticallContracts<Narrow<contracts>>;
|
|
27
|
+
constructor(cause: Error, priceUpdates: IPriceUpdateTx[], calls: MulticallContracts<Narrow<contracts>>);
|
|
28
|
+
}
|
package/package.json
CHANGED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
var utils_exports = {};
|
|
20
|
-
__export(utils_exports, {
|
|
21
|
-
rawTxToMulticallPriceUpdate: () => rawTxToMulticallPriceUpdate
|
|
22
|
-
});
|
|
23
|
-
module.exports = __toCommonJS(utils_exports);
|
|
24
|
-
var import_viem = require("viem");
|
|
25
|
-
var import_iUpdatablePriceFeed = require("../../../abi/iUpdatablePriceFeed.js");
|
|
26
|
-
function rawTxToMulticallPriceUpdate(tx) {
|
|
27
|
-
const { to, callData } = tx;
|
|
28
|
-
const { args, functionName } = (0, import_viem.decodeFunctionData)({
|
|
29
|
-
abi: import_iUpdatablePriceFeed.iUpdatablePriceFeedAbi,
|
|
30
|
-
data: callData
|
|
31
|
-
});
|
|
32
|
-
return {
|
|
33
|
-
abi: import_iUpdatablePriceFeed.iUpdatablePriceFeedAbi,
|
|
34
|
-
address: to,
|
|
35
|
-
functionName,
|
|
36
|
-
args
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
40
|
-
0 && (module.exports = {
|
|
41
|
-
rawTxToMulticallPriceUpdate
|
|
42
|
-
});
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { decodeFunctionData } from "viem";
|
|
2
|
-
import { iUpdatablePriceFeedAbi } from "../../../abi/iUpdatablePriceFeed.js";
|
|
3
|
-
function rawTxToMulticallPriceUpdate(tx) {
|
|
4
|
-
const { to, callData } = tx;
|
|
5
|
-
const { args, functionName } = decodeFunctionData({
|
|
6
|
-
abi: iUpdatablePriceFeedAbi,
|
|
7
|
-
data: callData
|
|
8
|
-
});
|
|
9
|
-
return {
|
|
10
|
-
abi: iUpdatablePriceFeedAbi,
|
|
11
|
-
address: to,
|
|
12
|
-
functionName,
|
|
13
|
-
args
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
export {
|
|
17
|
-
rawTxToMulticallPriceUpdate
|
|
18
|
-
};
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import type { RawTx } from "../../types/index.js";
|
|
2
|
-
/**
|
|
3
|
-
* Helper method to convert our RawTx into viem's multicall format
|
|
4
|
-
* Involves decoding what was previously encoded, but it's better than adding another method to PriceOracle
|
|
5
|
-
* @param tx
|
|
6
|
-
* @returns
|
|
7
|
-
*/
|
|
8
|
-
export declare function rawTxToMulticallPriceUpdate(tx: RawTx): {
|
|
9
|
-
abi: readonly [{
|
|
10
|
-
readonly type: "function";
|
|
11
|
-
readonly name: "updatable";
|
|
12
|
-
readonly inputs: readonly [];
|
|
13
|
-
readonly outputs: readonly [{
|
|
14
|
-
readonly name: "";
|
|
15
|
-
readonly type: "bool";
|
|
16
|
-
readonly internalType: "bool";
|
|
17
|
-
}];
|
|
18
|
-
readonly stateMutability: "view";
|
|
19
|
-
}, {
|
|
20
|
-
readonly type: "function";
|
|
21
|
-
readonly name: "updatePrice";
|
|
22
|
-
readonly inputs: readonly [{
|
|
23
|
-
readonly name: "data";
|
|
24
|
-
readonly type: "bytes";
|
|
25
|
-
readonly internalType: "bytes";
|
|
26
|
-
}];
|
|
27
|
-
readonly outputs: readonly [];
|
|
28
|
-
readonly stateMutability: "nonpayable";
|
|
29
|
-
}];
|
|
30
|
-
address: `0x${string}`;
|
|
31
|
-
functionName: "updatable" | "updatePrice";
|
|
32
|
-
args: readonly [] | readonly [`0x${string}`];
|
|
33
|
-
};
|