@evaafi/sdk 0.6.4 → 0.9.0
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/api/feeds.d.ts +30 -0
- package/dist/api/feeds.js +73 -0
- package/dist/api/liquidation.js +1 -1
- package/dist/api/math.js +1 -1
- package/dist/api/parser.d.ts +4 -2
- package/dist/api/parser.js +39 -18
- package/dist/api/parsers/AbstractOracleParser.d.ts +11 -0
- package/dist/api/parsers/AbstractOracleParser.js +9 -0
- package/dist/api/parsers/ClassicOracleParser.d.ts +10 -0
- package/dist/api/parsers/ClassicOracleParser.js +16 -0
- package/dist/api/parsers/PythOracleParser.d.ts +17 -0
- package/dist/api/parsers/PythOracleParser.js +22 -0
- package/dist/api/parsers/index.d.ts +3 -0
- package/dist/api/parsers/index.js +19 -0
- package/dist/api/prices.d.ts +6 -6
- package/dist/api/prices.js +37 -46
- package/dist/api/pyth.d.ts +16 -0
- package/dist/api/pyth.js +35 -0
- package/dist/constants/assets/assetId.d.ts +22 -0
- package/dist/constants/assets/assetId.js +29 -0
- package/dist/constants/assets/index.d.ts +3 -0
- package/dist/constants/assets/index.js +19 -0
- package/dist/constants/assets/mainnet.d.ts +19 -0
- package/dist/constants/assets/mainnet.js +114 -0
- package/dist/constants/assets/testnet.d.ts +14 -0
- package/dist/constants/assets/testnet.js +54 -0
- package/dist/constants/assets.d.ts +3 -0
- package/dist/constants/assets.js +14 -1
- package/dist/constants/general/index.d.ts +65 -0
- package/dist/constants/general/index.js +93 -0
- package/dist/constants/general/mainnet.d.ts +24 -0
- package/dist/constants/general/mainnet.js +53 -0
- package/dist/constants/general/testnet.d.ts +12 -0
- package/dist/constants/general/testnet.js +15 -0
- package/dist/constants/general.d.ts +4 -4
- package/dist/constants/general.js +6 -6
- package/dist/constants/index.d.ts +3 -0
- package/dist/constants/index.js +19 -0
- package/dist/constants/pools/index.d.ts +2 -0
- package/dist/constants/pools/index.js +18 -0
- package/dist/constants/pools/mainnet.d.ts +14 -0
- package/dist/constants/pools/mainnet.js +145 -0
- package/dist/constants/pools/testnet.d.ts +9 -0
- package/dist/constants/pools/testnet.js +57 -0
- package/dist/constants/pools.js +9 -9
- package/dist/contracts/AbstractMaster.d.ts +185 -0
- package/dist/contracts/AbstractMaster.js +179 -0
- package/dist/contracts/ClassicMaster.d.ts +34 -0
- package/dist/contracts/ClassicMaster.js +87 -0
- package/dist/contracts/PythMaster.d.ts +61 -0
- package/dist/contracts/PythMaster.js +179 -0
- package/dist/contracts/UserContract.d.ts +1 -7
- package/dist/contracts/UserContract.js +1 -19
- package/dist/contracts/index.d.ts +5 -0
- package/dist/contracts/index.js +21 -0
- package/dist/index.d.ts +14 -14
- package/dist/index.js +20 -60
- package/dist/prices/Oracle.interface.d.ts +9 -0
- package/dist/prices/Oracle.interface.js +2 -0
- package/dist/prices/Prices.d.ts +5 -3
- package/dist/prices/Prices.js +13 -3
- package/dist/prices/PricesCollector.d.ts +17 -7
- package/dist/prices/PricesCollector.js +67 -51
- package/dist/prices/PythCollector.d.ts +22 -0
- package/dist/prices/PythCollector.js +217 -0
- package/dist/prices/Types.d.ts +17 -2
- package/dist/prices/Types.js +8 -1
- package/dist/prices/index.d.ts +4 -3
- package/dist/prices/index.js +4 -3
- package/dist/prices/sources/Backend.d.ts +5 -4
- package/dist/prices/sources/Backend.js +16 -13
- package/dist/prices/sources/Icp.d.ts +2 -1
- package/dist/prices/sources/Icp.js +12 -9
- package/dist/prices/sources/PriceSource.d.ts +7 -6
- package/dist/prices/utils.d.ts +10 -9
- package/dist/prices/utils.js +32 -46
- package/dist/rewards/RewardMaster.d.ts +0 -1
- package/dist/rewards/RewardUser.d.ts +0 -1
- package/dist/types/Master.d.ts +10 -31
- package/dist/types/Master.js +3 -0
- package/dist/types/MasterRewards.d.ts +0 -1
- package/dist/types/UserRewards.d.ts +0 -1
- package/dist/utils/sha256BigInt.d.ts +0 -1
- package/dist/utils/userJettonWallet.js +0 -8
- package/dist/utils/utils.d.ts +8 -1
- package/dist/utils/utils.js +31 -2
- package/package.json +4 -3
- package/src/api/feeds.ts +90 -0
- package/src/api/liquidation.ts +1 -1
- package/src/api/math.ts +1 -1
- package/src/api/parser.ts +100 -38
- package/src/api/parsers/AbstractOracleParser.ts +16 -0
- package/src/api/parsers/ClassicOracleParser.ts +20 -0
- package/src/api/parsers/PythOracleParser.ts +34 -0
- package/src/api/parsers/index.ts +3 -0
- package/src/api/prices.ts +32 -41
- package/src/constants/assets/assetId.ts +30 -0
- package/src/constants/assets/index.ts +3 -0
- package/src/constants/{assets.ts → assets/mainnet.ts} +27 -94
- package/src/constants/assets/testnet.ts +74 -0
- package/src/constants/general/index.ts +91 -0
- package/src/constants/{general.ts → general/mainnet.ts} +48 -72
- package/src/constants/general/testnet.ts +25 -0
- package/src/constants/index.ts +3 -0
- package/src/constants/pools/index.ts +2 -0
- package/src/constants/pools/mainnet.ts +218 -0
- package/src/constants/pools/testnet.ts +75 -0
- package/src/contracts/AbstractMaster.ts +450 -0
- package/src/contracts/ClassicMaster.ts +149 -0
- package/src/contracts/PythMaster.ts +313 -0
- package/src/contracts/UserContract.ts +7 -28
- package/src/contracts/index.ts +7 -0
- package/src/index.ts +18 -85
- package/src/prices/Oracle.interface.ts +18 -0
- package/src/prices/Prices.ts +17 -4
- package/src/prices/PricesCollector.ts +91 -68
- package/src/prices/PythCollector.ts +294 -0
- package/src/prices/Types.ts +28 -6
- package/src/prices/index.ts +4 -3
- package/src/prices/sources/Backend.ts +21 -19
- package/src/prices/sources/Icp.ts +13 -10
- package/src/prices/sources/PriceSource.ts +6 -5
- package/src/prices/utils.ts +65 -68
- package/src/types/Master.ts +29 -52
- package/src/types/User.ts +15 -7
- package/src/utils/userJettonWallet.ts +0 -8
- package/src/utils/utils.ts +41 -2
- package/src/constants/pools.ts +0 -175
- package/src/contracts/MasterContract.ts +0 -410
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
3
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
4
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
5
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
6
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
7
|
+
};
|
|
8
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
9
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
10
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
11
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
|
+
};
|
|
13
|
+
var _PythCollector_instances, _PythCollector_oracleInfo, _PythCollector_parsedFeedsMap, _PythCollector_pythConfig, _PythCollector_poolAssetsConfig, _PythCollector_pythToEvaaDirect, _PythCollector_pythToEvaaReferred, _PythCollector_evaaToPythDirect, _PythCollector_allowedRefEvaa, _PythCollector_getPythFeedsUpdates, _PythCollector_fetchPythUpdatesWithRetry, _PythCollector_filterEmptyPrincipalsAndAssets;
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.PythCollector = void 0;
|
|
16
|
+
const hermes_client_1 = require("@pythnetwork/hermes-client");
|
|
17
|
+
const core_1 = require("@ton/core");
|
|
18
|
+
const math_1 = require("../api/math");
|
|
19
|
+
const prices_1 = require("../api/prices");
|
|
20
|
+
const constants_1 = require("../constants");
|
|
21
|
+
const Master_1 = require("../types/Master");
|
|
22
|
+
const utils_1 = require("../utils/utils");
|
|
23
|
+
const Prices_1 = require("./Prices");
|
|
24
|
+
const constants_2 = require("./constants");
|
|
25
|
+
class PythCollector {
|
|
26
|
+
constructor(config) {
|
|
27
|
+
_PythCollector_instances.add(this);
|
|
28
|
+
_PythCollector_oracleInfo.set(this, void 0);
|
|
29
|
+
_PythCollector_parsedFeedsMap.set(this, void 0);
|
|
30
|
+
_PythCollector_pythConfig.set(this, void 0);
|
|
31
|
+
_PythCollector_poolAssetsConfig.set(this, void 0);
|
|
32
|
+
_PythCollector_pythToEvaaDirect.set(this, new Map()); // pythId -> evaaId (native)
|
|
33
|
+
_PythCollector_pythToEvaaReferred.set(this, new Map()); // pythId -> Set<evaaId>,
|
|
34
|
+
_PythCollector_evaaToPythDirect.set(this, new Map()); // evaaId -> pythId (native)
|
|
35
|
+
_PythCollector_allowedRefEvaa.set(this, new Map()); // evaaId -> baseEvaaId (allowedRefTokens)
|
|
36
|
+
__classPrivateFieldSet(this, _PythCollector_oracleInfo, config.pythOracle, "f");
|
|
37
|
+
__classPrivateFieldSet(this, _PythCollector_pythConfig, config.pythConfig, "f");
|
|
38
|
+
__classPrivateFieldSet(this, _PythCollector_poolAssetsConfig, config.poolAssetsConfig, "f");
|
|
39
|
+
__classPrivateFieldSet(this, _PythCollector_parsedFeedsMap, (0, Master_1.parseFeedsMapDict)(__classPrivateFieldGet(this, _PythCollector_oracleInfo, "f").feedsMap), "f");
|
|
40
|
+
// 1) pythId -> evaaId, evaaId -> pythId
|
|
41
|
+
for (const [pythId, feedInfo] of __classPrivateFieldGet(this, _PythCollector_parsedFeedsMap, "f").entries()) {
|
|
42
|
+
__classPrivateFieldGet(this, _PythCollector_pythToEvaaDirect, "f").set(pythId, feedInfo.evaaId);
|
|
43
|
+
__classPrivateFieldGet(this, _PythCollector_evaaToPythDirect, "f").set(feedInfo.evaaId, pythId);
|
|
44
|
+
}
|
|
45
|
+
// 2) pythId (native) -> Set<evaaId>
|
|
46
|
+
for (const [pythId, feedInfo] of __classPrivateFieldGet(this, _PythCollector_parsedFeedsMap, "f").entries()) {
|
|
47
|
+
const ref = feedInfo.referredPythFeed;
|
|
48
|
+
if (ref && ref !== 0n) {
|
|
49
|
+
if (!__classPrivateFieldGet(this, _PythCollector_pythToEvaaReferred, "f").has(ref))
|
|
50
|
+
__classPrivateFieldGet(this, _PythCollector_pythToEvaaReferred, "f").set(ref, new Set());
|
|
51
|
+
__classPrivateFieldGet(this, _PythCollector_pythToEvaaReferred, "f").get(ref).add(feedInfo.evaaId);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// 3) evaaId -> baseEvaaId (allowedRefTokens)
|
|
55
|
+
for (const evaaId of __classPrivateFieldGet(this, _PythCollector_oracleInfo, "f").allowedRefTokens.keys()) {
|
|
56
|
+
const base = __classPrivateFieldGet(this, _PythCollector_oracleInfo, "f").allowedRefTokens.get(evaaId);
|
|
57
|
+
__classPrivateFieldGet(this, _PythCollector_allowedRefEvaa, "f").set(evaaId, base);
|
|
58
|
+
// If baseEvaaId have pythId. evaaId -> pyth(base)
|
|
59
|
+
const basePyth = __classPrivateFieldGet(this, _PythCollector_evaaToPythDirect, "f").get(base);
|
|
60
|
+
if (basePyth) {
|
|
61
|
+
if (!__classPrivateFieldGet(this, _PythCollector_pythToEvaaReferred, "f").has(basePyth))
|
|
62
|
+
__classPrivateFieldGet(this, _PythCollector_pythToEvaaReferred, "f").set(basePyth, new Set());
|
|
63
|
+
__classPrivateFieldGet(this, _PythCollector_pythToEvaaReferred, "f").get(basePyth).add(evaaId);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
async getPricesForLiquidate(realPrincipals, fetchConfig) {
|
|
68
|
+
const assets = __classPrivateFieldGet(this, _PythCollector_instances, "m", _PythCollector_filterEmptyPrincipalsAndAssets).call(this, realPrincipals);
|
|
69
|
+
if (assets.includes(undefined)) {
|
|
70
|
+
throw new Error('User from another pool');
|
|
71
|
+
}
|
|
72
|
+
return await this.getPrices(assets.map((x) => x), fetchConfig);
|
|
73
|
+
}
|
|
74
|
+
async getPricesForSupplyWithdraw(realPrincipals, supplyAsset, withdrawAsset, collateralToDebt, fetchConfig) {
|
|
75
|
+
let assets = __classPrivateFieldGet(this, _PythCollector_instances, "m", _PythCollector_filterEmptyPrincipalsAndAssets).call(this, realPrincipals);
|
|
76
|
+
if ((0, math_1.checkNotInDebtAtAll)(realPrincipals) &&
|
|
77
|
+
withdrawAsset &&
|
|
78
|
+
(realPrincipals.get(withdrawAsset.assetId) ?? 0n) > 0n &&
|
|
79
|
+
!collateralToDebt) {
|
|
80
|
+
return new Prices_1.Prices(core_1.Dictionary.empty(), core_1.Cell.EMPTY, undefined, undefined);
|
|
81
|
+
}
|
|
82
|
+
if (assets.includes(undefined)) {
|
|
83
|
+
throw new Error('User from another pool');
|
|
84
|
+
}
|
|
85
|
+
if (withdrawAsset && !assets.find((a) => a?.assetId === withdrawAsset.assetId)) {
|
|
86
|
+
assets.push(withdrawAsset);
|
|
87
|
+
}
|
|
88
|
+
if (collateralToDebt && assets.length == 1) {
|
|
89
|
+
throw new Error('Cannot debt only one supplied asset');
|
|
90
|
+
}
|
|
91
|
+
return await this.getPrices(assets.map((x) => x), fetchConfig);
|
|
92
|
+
}
|
|
93
|
+
async getPrices(assets = __classPrivateFieldGet(this, _PythCollector_poolAssetsConfig, "f"), fetchConfig) {
|
|
94
|
+
// Declare variables at the beginning
|
|
95
|
+
let minPublishTime;
|
|
96
|
+
let maxPublishTime;
|
|
97
|
+
if (assets.length === 0) {
|
|
98
|
+
return new Prices_1.Prices(core_1.Dictionary.empty(), core_1.Cell.EMPTY, undefined, undefined);
|
|
99
|
+
}
|
|
100
|
+
const requiredFeeds = this.createRequiredFeedsList(assets.map((a) => a.assetId));
|
|
101
|
+
const pythUpdates = await __classPrivateFieldGet(this, _PythCollector_instances, "m", _PythCollector_fetchPythUpdatesWithRetry).call(this, requiredFeeds, fetchConfig);
|
|
102
|
+
// Calculate min and max publish times for validation
|
|
103
|
+
if (pythUpdates.parsed && pythUpdates.parsed.length > 0) {
|
|
104
|
+
const publishTimes = pythUpdates.parsed.map((u) => BigInt(u.price.publish_time));
|
|
105
|
+
const tmin = publishTimes.reduce((a, b) => (a < b ? a : b));
|
|
106
|
+
const tmax = publishTimes.reduce((a, b) => (a > b ? a : b));
|
|
107
|
+
if (tmax - tmin > constants_2.TTL_ORACLE_DATA_SEC) {
|
|
108
|
+
throw new Error(`Price feeds don't fit in a single 3-minute window. Time span: ${tmax - tmin} seconds (max allowed: ${constants_2.TTL_ORACLE_DATA_SEC})`);
|
|
109
|
+
}
|
|
110
|
+
// Set boundaries using "from oldest" approach: minPublishTime = tmin, maxPublishTime = tmin + 180
|
|
111
|
+
minPublishTime = tmin;
|
|
112
|
+
maxPublishTime = tmin + BigInt(constants_2.TTL_ORACLE_DATA_SEC);
|
|
113
|
+
}
|
|
114
|
+
const pricesDict = core_1.Dictionary.empty();
|
|
115
|
+
const pythPriceUpdates = pythUpdates.parsed;
|
|
116
|
+
if (pythPriceUpdates) {
|
|
117
|
+
// Only set prices for requested assets, not all possible mapped assets
|
|
118
|
+
const requestedAssetIds = new Set(assets.map((a) => a.assetId));
|
|
119
|
+
for (const u of pythPriceUpdates) {
|
|
120
|
+
const pythId = BigInt('0x' + u.id);
|
|
121
|
+
const price = (BigInt(u.price.price) * BigInt(10 ** 9)) / BigInt(10 ** (u.price.expo * -1));
|
|
122
|
+
// Set price for direct mapping if the evaaId is requested
|
|
123
|
+
const directEvaa = __classPrivateFieldGet(this, _PythCollector_pythToEvaaDirect, "f").get(pythId);
|
|
124
|
+
if (directEvaa && requestedAssetIds.has(directEvaa)) {
|
|
125
|
+
pricesDict.set(directEvaa, price);
|
|
126
|
+
}
|
|
127
|
+
// Set price for referred assets only if they are requested
|
|
128
|
+
const referredSet = __classPrivateFieldGet(this, _PythCollector_pythToEvaaReferred, "f").get(pythId);
|
|
129
|
+
if (referredSet && referredSet.size) {
|
|
130
|
+
for (const evaaId of referredSet) {
|
|
131
|
+
if (requestedAssetIds.has(evaaId)) {
|
|
132
|
+
pricesDict.set(evaaId, price);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// TODO: fix it
|
|
138
|
+
if (pricesDict.get(constants_1.TSTON_MAINNET.assetId) && pricesDict.get(constants_1.TON_MAINNET.assetId)) {
|
|
139
|
+
pricesDict.set(constants_1.TSTON_MAINNET.assetId, (pricesDict.get(constants_1.TSTON_MAINNET.assetId) * pricesDict.get(constants_1.TON_MAINNET.assetId)) / BigInt(10 ** 9));
|
|
140
|
+
}
|
|
141
|
+
// TODO: fix it
|
|
142
|
+
if (pricesDict.get(constants_1.STTON_MAINNET.assetId) && pricesDict.get(constants_1.TON_MAINNET.assetId)) {
|
|
143
|
+
pricesDict.set(constants_1.STTON_MAINNET.assetId, (pricesDict.get(constants_1.STTON_MAINNET.assetId) * pricesDict.get(constants_1.TON_MAINNET.assetId)) / BigInt(10 ** 9));
|
|
144
|
+
}
|
|
145
|
+
// TODO: fix it
|
|
146
|
+
if (pricesDict.get(constants_1.TSUSDE_MAINNET.assetId) && pricesDict.get(constants_1.USDE_MAINNET.assetId)) {
|
|
147
|
+
pricesDict.set(constants_1.TSUSDE_MAINNET.assetId, (pricesDict.get(constants_1.TSUSDE_MAINNET.assetId) * pricesDict.get(constants_1.USDE_MAINNET.assetId)) / BigInt(10 ** 9));
|
|
148
|
+
}
|
|
149
|
+
// Check that all requested assets have prices
|
|
150
|
+
const missing = assets.map((a) => a.assetId).filter((id) => pricesDict.get(id) === undefined);
|
|
151
|
+
if (missing.length) {
|
|
152
|
+
throw new Error(`Missing prices for ${missing.length} asset(s): ${missing.map((x) => x.toString()).join(', ')}`);
|
|
153
|
+
}
|
|
154
|
+
const dataCell = (0, prices_1.packPythUpdatesData)(pythUpdates.binary);
|
|
155
|
+
return new Prices_1.Prices(pricesDict, dataCell, minPublishTime, maxPublishTime);
|
|
156
|
+
}
|
|
157
|
+
return new Prices_1.Prices(core_1.Dictionary.empty(), core_1.Cell.EMPTY, minPublishTime, maxPublishTime);
|
|
158
|
+
}
|
|
159
|
+
async getPricesForWithdraw(realPrincipals, withdrawAsset, collateralToDebt = false, fetchConfig) {
|
|
160
|
+
let assets = __classPrivateFieldGet(this, _PythCollector_instances, "m", _PythCollector_filterEmptyPrincipalsAndAssets).call(this, realPrincipals);
|
|
161
|
+
if ((0, math_1.checkNotInDebtAtAll)(realPrincipals) &&
|
|
162
|
+
(realPrincipals.get(withdrawAsset.assetId) ?? 0n) > 0n &&
|
|
163
|
+
!collateralToDebt) {
|
|
164
|
+
return new Prices_1.Prices(core_1.Dictionary.empty(), core_1.Cell.EMPTY);
|
|
165
|
+
}
|
|
166
|
+
if (assets.includes(undefined)) {
|
|
167
|
+
throw new Error('User from another pool');
|
|
168
|
+
}
|
|
169
|
+
if (!assets.includes(withdrawAsset)) {
|
|
170
|
+
assets.push(withdrawAsset);
|
|
171
|
+
}
|
|
172
|
+
if (collateralToDebt && assets.length == 1) {
|
|
173
|
+
throw new Error('Cannot debt only one supplied asset');
|
|
174
|
+
}
|
|
175
|
+
return await this.getPrices(assets.map((x) => x), fetchConfig);
|
|
176
|
+
}
|
|
177
|
+
createRequiredFeedsList(evaaIds) {
|
|
178
|
+
const requiredFeeds = new Set();
|
|
179
|
+
for (const evaaId of evaaIds) {
|
|
180
|
+
let pythId = __classPrivateFieldGet(this, _PythCollector_evaaToPythDirect, "f").get(evaaId);
|
|
181
|
+
// If evaaId no have native feed — try by allowedRefTokens (evAA->baseEvAA->pyth)
|
|
182
|
+
if (!pythId) {
|
|
183
|
+
const baseEvaa = __classPrivateFieldGet(this, _PythCollector_allowedRefEvaa, "f").get(evaaId);
|
|
184
|
+
if (baseEvaa)
|
|
185
|
+
pythId = __classPrivateFieldGet(this, _PythCollector_evaaToPythDirect, "f").get(baseEvaa) ?? null;
|
|
186
|
+
}
|
|
187
|
+
if (pythId) {
|
|
188
|
+
requiredFeeds.add(pythId);
|
|
189
|
+
const feedInfo = __classPrivateFieldGet(this, _PythCollector_parsedFeedsMap, "f").get(pythId);
|
|
190
|
+
if (feedInfo?.referredPythFeed && feedInfo.referredPythFeed !== 0n) {
|
|
191
|
+
requiredFeeds.add(feedInfo.referredPythFeed);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return Array.from(requiredFeeds).map((id) => '0x' + id.toString(16));
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
exports.PythCollector = PythCollector;
|
|
199
|
+
_PythCollector_oracleInfo = new WeakMap(), _PythCollector_parsedFeedsMap = new WeakMap(), _PythCollector_pythConfig = new WeakMap(), _PythCollector_poolAssetsConfig = new WeakMap(), _PythCollector_pythToEvaaDirect = new WeakMap(), _PythCollector_pythToEvaaReferred = new WeakMap(), _PythCollector_evaaToPythDirect = new WeakMap(), _PythCollector_allowedRefEvaa = new WeakMap(), _PythCollector_instances = new WeakSet(), _PythCollector_getPythFeedsUpdates =
|
|
200
|
+
/**
|
|
201
|
+
* Updates feeds data from specified endpoint
|
|
202
|
+
* @param feedIds list of pyth feed ids to fetch
|
|
203
|
+
* @returns binary - buffer of feeds update, parsed - json feeds data
|
|
204
|
+
*/
|
|
205
|
+
async function _PythCollector_getPythFeedsUpdates(feedIds) {
|
|
206
|
+
const latestPriceUpdates = await Promise.any(__classPrivateFieldGet(this, _PythCollector_pythConfig, "f").pythEndpoints.map((x) => new hermes_client_1.HermesClient(x).getLatestPriceUpdates(feedIds, { encoding: 'hex' })));
|
|
207
|
+
const parsed = latestPriceUpdates['parsed'];
|
|
208
|
+
const binary = Buffer.from(latestPriceUpdates.binary.data[0], 'hex');
|
|
209
|
+
return { binary, parsed };
|
|
210
|
+
}, _PythCollector_fetchPythUpdatesWithRetry = async function _PythCollector_fetchPythUpdatesWithRetry(requiredFeeds, fetchConfig) {
|
|
211
|
+
return (0, utils_1.proxyFetchRetries)(__classPrivateFieldGet(this, _PythCollector_instances, "m", _PythCollector_getPythFeedsUpdates).call(this, requiredFeeds), fetchConfig);
|
|
212
|
+
}, _PythCollector_filterEmptyPrincipalsAndAssets = function _PythCollector_filterEmptyPrincipalsAndAssets(principals) {
|
|
213
|
+
return principals
|
|
214
|
+
.keys()
|
|
215
|
+
.filter((x) => principals.get(x) != 0n)
|
|
216
|
+
.map((x) => __classPrivateFieldGet(this, _PythCollector_poolAssetsConfig, "f").find((asset) => asset.assetId == x));
|
|
217
|
+
};
|
package/dist/prices/Types.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
|
|
3
|
-
import { Cell, Dictionary } from '@ton/core';
|
|
2
|
+
import type { PriceUpdate } from '@pythnetwork/hermes-client';
|
|
3
|
+
import type { Cell, Dictionary } from '@ton/core';
|
|
4
4
|
/**
|
|
5
5
|
* Configuration for price source endpoints.
|
|
6
6
|
*/
|
|
@@ -10,10 +10,21 @@ export type PriceSourcesConfig = {
|
|
|
10
10
|
/** Endpoints for ICP price data */
|
|
11
11
|
icpEndpoints: string[];
|
|
12
12
|
};
|
|
13
|
+
/**
|
|
14
|
+
* Configuration for pyth prices.
|
|
15
|
+
*/
|
|
16
|
+
export type PythPriceSourcesConfig = {
|
|
17
|
+
/** Endpoints for pyth price data */
|
|
18
|
+
pythEndpoints: string[];
|
|
19
|
+
};
|
|
13
20
|
/**
|
|
14
21
|
* Default configuration for price source endpoints.
|
|
15
22
|
*/
|
|
16
23
|
export declare const DefaultPriceSourcesConfig: PriceSourcesConfig;
|
|
24
|
+
/**
|
|
25
|
+
* Configuration for pyth price sources.
|
|
26
|
+
*/
|
|
27
|
+
export declare const DefaultPythPriceSourcesConfig: PythPriceSourcesConfig;
|
|
17
28
|
export type RawPriceData = {
|
|
18
29
|
dict: Dictionary<bigint, bigint>;
|
|
19
30
|
dataCell: Cell;
|
|
@@ -22,6 +33,10 @@ export type RawPriceData = {
|
|
|
22
33
|
pubkey: Buffer;
|
|
23
34
|
timestamp: number;
|
|
24
35
|
};
|
|
36
|
+
export type PythFeedUpdateType = {
|
|
37
|
+
parsed: PriceUpdate['parsed'];
|
|
38
|
+
binary: Buffer;
|
|
39
|
+
};
|
|
25
40
|
export type PriceData = {
|
|
26
41
|
dict: Dictionary<bigint, bigint>;
|
|
27
42
|
dataCell: Cell;
|
package/dist/prices/Types.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DefaultPriceSourcesConfig = void 0;
|
|
3
|
+
exports.DefaultPythPriceSourcesConfig = exports.DefaultPriceSourcesConfig = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Default configuration for price source endpoints.
|
|
6
6
|
*/
|
|
@@ -8,3 +8,10 @@ exports.DefaultPriceSourcesConfig = {
|
|
|
8
8
|
backendEndpoints: ['api.evaa.space', 'evaa.space'],
|
|
9
9
|
icpEndpoints: ['6khmc-aiaaa-aaaap-ansfq-cai.raw.icp0.io'],
|
|
10
10
|
};
|
|
11
|
+
/**
|
|
12
|
+
* Configuration for pyth price sources.
|
|
13
|
+
*/
|
|
14
|
+
exports.DefaultPythPriceSourcesConfig = {
|
|
15
|
+
// FYI: 3RPS limit per IP, TODO: support Pythnet RPC
|
|
16
|
+
pythEndpoints: ['https://hermes.pyth.network'],
|
|
17
|
+
};
|
package/dist/prices/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
export * from './sources';
|
|
2
|
-
export * from './Types';
|
|
3
1
|
export * from './constants';
|
|
4
|
-
export * from './utils';
|
|
5
2
|
export * from './Prices';
|
|
6
3
|
export * from './PricesCollector';
|
|
4
|
+
export * from './PythCollector';
|
|
5
|
+
export * from './sources';
|
|
6
|
+
export * from './Types';
|
|
7
|
+
export * from './utils';
|
package/dist/prices/index.js
CHANGED
|
@@ -14,9 +14,10 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./sources"), exports);
|
|
18
|
-
__exportStar(require("./Types"), exports);
|
|
19
17
|
__exportStar(require("./constants"), exports);
|
|
20
|
-
__exportStar(require("./utils"), exports);
|
|
21
18
|
__exportStar(require("./Prices"), exports);
|
|
22
19
|
__exportStar(require("./PricesCollector"), exports);
|
|
20
|
+
__exportStar(require("./PythCollector"), exports);
|
|
21
|
+
__exportStar(require("./sources"), exports);
|
|
22
|
+
__exportStar(require("./Types"), exports);
|
|
23
|
+
__exportStar(require("./utils"), exports);
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { RawPriceData } from
|
|
2
|
-
import {
|
|
1
|
+
import { RawPriceData } from '..';
|
|
2
|
+
import { FetchConfig } from '../../utils/utils';
|
|
3
|
+
import { PriceSource } from './PriceSource';
|
|
3
4
|
export declare class BackendPriceSource extends PriceSource {
|
|
4
5
|
protected priceSourceName: string;
|
|
5
|
-
getPrices(): Promise<RawPriceData[]>;
|
|
6
|
-
loadOracleData(): Promise<OutputData[]>;
|
|
6
|
+
getPrices(fetchConfig?: FetchConfig): Promise<RawPriceData[]>;
|
|
7
|
+
loadOracleData(fetchConfig?: FetchConfig): Promise<OutputData[]>;
|
|
7
8
|
parsePrices(outputData: OutputData): RawPriceData;
|
|
8
9
|
}
|
|
9
10
|
type OutputData = {
|
|
@@ -2,28 +2,31 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.BackendPriceSource = void 0;
|
|
4
4
|
const core_1 = require("@ton/core");
|
|
5
|
+
const utils_1 = require("../../utils/utils");
|
|
5
6
|
const PriceSource_1 = require("./PriceSource");
|
|
6
7
|
class BackendPriceSource extends PriceSource_1.PriceSource {
|
|
7
8
|
constructor() {
|
|
8
9
|
super(...arguments);
|
|
9
10
|
this.priceSourceName = 'BackendPriceSource';
|
|
10
11
|
}
|
|
11
|
-
async getPrices() {
|
|
12
|
-
const data = await this.loadOracleData();
|
|
13
|
-
return data.map(outputData => this.parsePrices(outputData));
|
|
12
|
+
async getPrices(fetchConfig) {
|
|
13
|
+
const data = await this.loadOracleData(fetchConfig);
|
|
14
|
+
return data.map((outputData) => this.parsePrices(outputData));
|
|
14
15
|
}
|
|
15
|
-
async loadOracleData() {
|
|
16
|
-
|
|
16
|
+
async loadOracleData(fetchConfig = utils_1.DefaultFetchConfig) {
|
|
17
|
+
const fetchPromise = fetch(`https://${this._endpoint}/api/prices`, {
|
|
17
18
|
headers: { accept: 'application/json' },
|
|
18
|
-
signal: AbortSignal.timeout(
|
|
19
|
+
signal: AbortSignal.timeout(fetchConfig.timeout),
|
|
20
|
+
}).then(async (response) => {
|
|
21
|
+
const resp = await response.json();
|
|
22
|
+
const data = resp;
|
|
23
|
+
let outputData = [];
|
|
24
|
+
for (const nft of this._nfts) {
|
|
25
|
+
outputData.push({ oracleId: nft.id, data: data[nft.address] });
|
|
26
|
+
}
|
|
27
|
+
return outputData;
|
|
19
28
|
});
|
|
20
|
-
|
|
21
|
-
const data = resp;
|
|
22
|
-
let outputData = [];
|
|
23
|
-
for (const nft of this._nfts) {
|
|
24
|
-
outputData.push({ oracleId: nft.id, data: data[nft.address] });
|
|
25
|
-
}
|
|
26
|
-
return outputData;
|
|
29
|
+
return await (0, utils_1.proxyFetchRetries)(fetchPromise, fetchConfig);
|
|
27
30
|
}
|
|
28
31
|
parsePrices(outputData) {
|
|
29
32
|
try {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { BackendPriceSource } from ".";
|
|
2
|
+
import { FetchConfig } from "../../utils/utils";
|
|
2
3
|
export declare class IcpPriceSource extends BackendPriceSource {
|
|
3
4
|
protected priceSourceName: string;
|
|
4
|
-
loadOracleData(): Promise<OutputData[]>;
|
|
5
|
+
loadOracleData(fetchConfig?: FetchConfig): Promise<OutputData[]>;
|
|
5
6
|
}
|
|
6
7
|
type OutputData = {
|
|
7
8
|
oracleId: number;
|
|
@@ -2,22 +2,25 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.IcpPriceSource = void 0;
|
|
4
4
|
const _1 = require(".");
|
|
5
|
+
const utils_1 = require("../../utils/utils");
|
|
5
6
|
class IcpPriceSource extends _1.BackendPriceSource {
|
|
6
7
|
constructor() {
|
|
7
8
|
super(...arguments);
|
|
8
9
|
this.priceSourceName = 'IcpPriceSource';
|
|
9
10
|
}
|
|
10
|
-
async loadOracleData() {
|
|
11
|
-
|
|
11
|
+
async loadOracleData(fetchConfig = utils_1.DefaultFetchConfig) {
|
|
12
|
+
const fetchPromise = fetch(`https://${this._endpoint}/prices`, {
|
|
12
13
|
headers: { accept: 'application/json' },
|
|
13
|
-
signal: AbortSignal.timeout(
|
|
14
|
+
signal: AbortSignal.timeout(fetchConfig.timeout)
|
|
15
|
+
}).then(async (response) => {
|
|
16
|
+
const data = (await response.json());
|
|
17
|
+
let outputData = [];
|
|
18
|
+
for (const nft of this._nfts) {
|
|
19
|
+
outputData.push({ oracleId: nft.id, data: data[nft.address] });
|
|
20
|
+
}
|
|
21
|
+
return outputData;
|
|
14
22
|
});
|
|
15
|
-
|
|
16
|
-
let outputData = [];
|
|
17
|
-
for (const nft of this._nfts) {
|
|
18
|
-
outputData.push({ oracleId: nft.id, data: data[nft.address] });
|
|
19
|
-
}
|
|
20
|
-
return outputData;
|
|
23
|
+
return await (0, utils_1.proxyFetchRetries)(fetchPromise, fetchConfig);
|
|
21
24
|
}
|
|
22
25
|
}
|
|
23
26
|
exports.IcpPriceSource = IcpPriceSource;
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { RawPriceData } from "..";
|
|
2
|
-
import {
|
|
2
|
+
import { ExtendedEvaaOracle } from "../../types/Master";
|
|
3
|
+
import { FetchConfig } from "../../utils/utils";
|
|
3
4
|
export declare abstract class PriceSource {
|
|
4
5
|
protected priceSourceName: string;
|
|
5
6
|
protected _endpoint: string;
|
|
6
|
-
protected _nfts:
|
|
7
|
-
constructor(endpoint: string, nfts:
|
|
7
|
+
protected _nfts: ExtendedEvaaOracle[];
|
|
8
|
+
constructor(endpoint: string, nfts: ExtendedEvaaOracle[]);
|
|
8
9
|
get sourceName(): string;
|
|
9
10
|
get endpoint(): string;
|
|
10
|
-
get nfts():
|
|
11
|
+
get nfts(): ExtendedEvaaOracle[];
|
|
11
12
|
set endpoint(endpoint: string);
|
|
12
|
-
set nfts(nfts:
|
|
13
|
-
abstract getPrices(): Promise<RawPriceData[]>;
|
|
13
|
+
set nfts(nfts: ExtendedEvaaOracle[]);
|
|
14
|
+
abstract getPrices(fetchConfig?: FetchConfig): Promise<RawPriceData[]>;
|
|
14
15
|
}
|
package/dist/prices/utils.d.ts
CHANGED
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import { Cell, Dictionary, Slice } from '@ton/core';
|
|
3
|
+
import { EvaaOracle, ExtendedEvaaOracle } from '../types/Master';
|
|
4
|
+
import { FetchConfig } from '../utils/utils';
|
|
5
|
+
import { PriceSource } from './sources/PriceSource';
|
|
6
|
+
import { OraclePricesData, PriceData, PriceSourcesConfig, RawPriceData } from './Types';
|
|
6
7
|
export declare function verifyPricesTimestamp(): (priceData: RawPriceData) => boolean;
|
|
7
|
-
export declare function verifyPricesSign(nfts: OracleNFT[]): (priceData: RawPriceData) => boolean;
|
|
8
8
|
export declare function getMedianPrice(pricesData: PriceData[], asset: bigint): bigint | null;
|
|
9
9
|
export declare function packAssetsData(assetsData: {
|
|
10
10
|
assetId: bigint;
|
|
11
11
|
medianPrice: bigint;
|
|
12
12
|
}[]): Cell;
|
|
13
13
|
export declare function packPrices(assetsDataCell: Cell, oraclesDataCell: Cell): Cell;
|
|
14
|
-
export declare function createOracleDataProof(oracle:
|
|
14
|
+
export declare function createOracleDataProof(oracle: EvaaOracle, data: OraclePricesData, signature: Buffer, assets: Array<bigint>): Slice;
|
|
15
15
|
export declare function packOraclesData(oraclesData: {
|
|
16
|
-
oracle:
|
|
16
|
+
oracle: EvaaOracle;
|
|
17
17
|
data: OraclePricesData;
|
|
18
18
|
signature: Buffer;
|
|
19
19
|
}[], assets: Array<bigint>): Cell;
|
|
20
20
|
export declare function sumDicts(result: Dictionary<bigint, bigint>, addendum: Dictionary<bigint, bigint>): void;
|
|
21
|
-
export declare function generatePriceSources(config
|
|
22
|
-
export declare function collectAndFilterPrices(priceSource: PriceSource,
|
|
21
|
+
export declare function generatePriceSources(config: PriceSourcesConfig, nfts: ExtendedEvaaOracle[]): PriceSource[];
|
|
22
|
+
export declare function collectAndFilterPrices(priceSource: PriceSource, minimalOracles: number, fetchConfig?: FetchConfig): Promise<RawPriceData[]>;
|
|
23
23
|
export declare function unpackMedianPrices(pricesCell: Cell): Dictionary<bigint, bigint> | undefined;
|
|
24
|
+
export declare function verifyPricesSign(nfts: ExtendedEvaaOracle[]): (priceData: RawPriceData) => boolean;
|
|
24
25
|
export declare function verifyRawPriceDataSign(priceData: RawPriceData): boolean;
|
package/dist/prices/utils.js
CHANGED
|
@@ -1,43 +1,24 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.verifyRawPriceDataSign = exports.unpackMedianPrices = exports.collectAndFilterPrices = exports.generatePriceSources = exports.sumDicts = exports.packOraclesData = exports.createOracleDataProof = exports.packPrices = exports.packAssetsData = exports.getMedianPrice = exports.
|
|
3
|
+
exports.verifyRawPriceDataSign = exports.verifyPricesSign = exports.unpackMedianPrices = exports.collectAndFilterPrices = exports.generatePriceSources = exports.sumDicts = exports.packOraclesData = exports.createOracleDataProof = exports.packPrices = exports.packAssetsData = exports.getMedianPrice = exports.verifyPricesTimestamp = void 0;
|
|
4
4
|
const core_1 = require("@ton/core");
|
|
5
5
|
const crypto_1 = require("@ton/crypto");
|
|
6
|
-
const __1 = require("..");
|
|
7
6
|
const merkleProof_1 = require("../utils/merkleProof");
|
|
7
|
+
const constants_1 = require("./constants");
|
|
8
|
+
const Backend_1 = require("./sources/Backend");
|
|
9
|
+
const Icp_1 = require("./sources/Icp");
|
|
8
10
|
function verifyPricesTimestamp() {
|
|
9
11
|
return function (priceData) {
|
|
10
12
|
const timestamp = Date.now() / 1000;
|
|
11
13
|
const pricesTime = priceData.timestamp;
|
|
12
|
-
|
|
13
|
-
return timestamp - pricesTime < __1.TTL_ORACLE_DATA_SEC;
|
|
14
|
+
return timestamp - pricesTime < constants_1.TTL_ORACLE_DATA_SEC;
|
|
14
15
|
};
|
|
15
16
|
}
|
|
16
17
|
exports.verifyPricesTimestamp = verifyPricesTimestamp;
|
|
17
|
-
function verifyPricesSign(nfts) {
|
|
18
|
-
return function (priceData) {
|
|
19
|
-
if (nfts.findIndex(x => x.pubkey.equals(priceData.pubkey)) == -1) {
|
|
20
|
-
//console.debug('[verifyPricesSign] nft not found');
|
|
21
|
-
return false;
|
|
22
|
-
}
|
|
23
|
-
return verifyRawPriceDataSign(priceData);
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
exports.verifyPricesSign = verifyPricesSign;
|
|
27
|
-
/* export function verifyPricesAssets(assets: PoolAssetsConfig) {
|
|
28
|
-
return function(priceData: RawPriceData): boolean {
|
|
29
|
-
for (const asset of assets) {
|
|
30
|
-
if(!priceData.dict.has(asset.assetId)) {
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
return true;
|
|
35
|
-
}
|
|
36
|
-
} */
|
|
37
18
|
function getMedianPrice(pricesData, asset) {
|
|
38
19
|
try {
|
|
39
|
-
const usingPrices = pricesData.filter(x => x.dict.has(asset));
|
|
40
|
-
const sorted = usingPrices.map(x => x.dict.get(asset)).sort((a, b) => Number(a) - Number(b));
|
|
20
|
+
const usingPrices = pricesData.filter((x) => x.dict.has(asset));
|
|
21
|
+
const sorted = usingPrices.map((x) => x.dict.get(asset)).sort((a, b) => Number(a) - Number(b));
|
|
41
22
|
if (sorted.length == 0) {
|
|
42
23
|
return null;
|
|
43
24
|
}
|
|
@@ -56,20 +37,13 @@ function getMedianPrice(pricesData, asset) {
|
|
|
56
37
|
exports.getMedianPrice = getMedianPrice;
|
|
57
38
|
function packAssetsData(assetsData) {
|
|
58
39
|
if (assetsData.length == 0) {
|
|
59
|
-
throw new Error(
|
|
40
|
+
throw new Error('No assets data to pack');
|
|
60
41
|
}
|
|
61
|
-
return assetsData.reduceRight((acc, { assetId, medianPrice }) => (0, core_1.beginCell)()
|
|
62
|
-
.storeUint(assetId, 256)
|
|
63
|
-
.storeCoins(medianPrice)
|
|
64
|
-
.storeMaybeRef(acc)
|
|
65
|
-
.endCell(), null);
|
|
42
|
+
return assetsData.reduceRight((acc, { assetId, medianPrice }) => (0, core_1.beginCell)().storeUint(assetId, 256).storeCoins(medianPrice).storeMaybeRef(acc).endCell(), null);
|
|
66
43
|
}
|
|
67
44
|
exports.packAssetsData = packAssetsData;
|
|
68
45
|
function packPrices(assetsDataCell, oraclesDataCell) {
|
|
69
|
-
let pricesCell = (0, core_1.beginCell)()
|
|
70
|
-
.storeRef(assetsDataCell)
|
|
71
|
-
.storeRef(oraclesDataCell)
|
|
72
|
-
.endCell();
|
|
46
|
+
let pricesCell = (0, core_1.beginCell)().storeRef(assetsDataCell).storeRef(oraclesDataCell).endCell();
|
|
73
47
|
return pricesCell;
|
|
74
48
|
}
|
|
75
49
|
exports.packPrices = packPrices;
|
|
@@ -83,9 +57,11 @@ function createOracleDataProof(oracle, data, signature, assets) {
|
|
|
83
57
|
exports.createOracleDataProof = createOracleDataProof;
|
|
84
58
|
function packOraclesData(oraclesData, assets) {
|
|
85
59
|
if (oraclesData.length == 0) {
|
|
86
|
-
throw new Error(
|
|
60
|
+
throw new Error('no oracles data to pack');
|
|
87
61
|
}
|
|
88
|
-
let proofs = oraclesData
|
|
62
|
+
let proofs = oraclesData
|
|
63
|
+
.sort((d1, d2) => d1.oracle.id - d2.oracle.id)
|
|
64
|
+
.map(({ oracle, data, signature }) => createOracleDataProof(oracle, data, signature, assets));
|
|
89
65
|
return proofs.reduceRight((acc, val) => (0, core_1.beginCell)().storeSlice(val).storeMaybeRef(acc).endCell(), null);
|
|
90
66
|
}
|
|
91
67
|
exports.packOraclesData = packOraclesData;
|
|
@@ -101,20 +77,20 @@ function sumDicts(result, addendum) {
|
|
|
101
77
|
}
|
|
102
78
|
}
|
|
103
79
|
exports.sumDicts = sumDicts;
|
|
104
|
-
function generatePriceSources(config
|
|
105
|
-
let result = config.backendEndpoints.map(x => new
|
|
106
|
-
result.push(...config.icpEndpoints.map(x => new
|
|
80
|
+
function generatePriceSources(config, nfts) {
|
|
81
|
+
let result = config.backendEndpoints.map((x) => new Backend_1.BackendPriceSource(x, nfts));
|
|
82
|
+
result.push(...config.icpEndpoints.map((x) => new Icp_1.IcpPriceSource(x, nfts)));
|
|
107
83
|
return result;
|
|
108
84
|
}
|
|
109
85
|
exports.generatePriceSources = generatePriceSources;
|
|
110
|
-
async function collectAndFilterPrices(priceSource,
|
|
111
|
-
const prices = await priceSource.getPrices();
|
|
86
|
+
async function collectAndFilterPrices(priceSource, minimalOracles, fetchConfig) {
|
|
87
|
+
const prices = await priceSource.getPrices(fetchConfig);
|
|
112
88
|
//console.debug('[FILTERING] before filtering prices len ', priceSource.sourceName, prices.length);
|
|
113
89
|
return (async () => {
|
|
114
|
-
const acceptedPrices = prices.filter(price => verifyPricesTimestamp()(price) && verifyPricesSign(
|
|
90
|
+
const acceptedPrices = prices.filter((price) => verifyPricesTimestamp()(price) && verifyPricesSign(priceSource.nfts)(price));
|
|
115
91
|
//console.debug('[FILTERING] after filtering prices len ', priceSource.sourceName, acceptedPrices.length);
|
|
116
|
-
if (acceptedPrices.length <
|
|
117
|
-
throw new Error(
|
|
92
|
+
if (acceptedPrices.length < minimalOracles) {
|
|
93
|
+
throw new Error('Prices are outdated');
|
|
118
94
|
}
|
|
119
95
|
return acceptedPrices;
|
|
120
96
|
})();
|
|
@@ -136,6 +112,16 @@ function unpackMedianPrices(pricesCell) {
|
|
|
136
112
|
return res;
|
|
137
113
|
}
|
|
138
114
|
exports.unpackMedianPrices = unpackMedianPrices;
|
|
115
|
+
function verifyPricesSign(nfts) {
|
|
116
|
+
return function (priceData) {
|
|
117
|
+
if (nfts.findIndex((x) => x.pubkey.equals(priceData.pubkey)) == -1) {
|
|
118
|
+
//console.debug('[verifyPricesSign] nft not found');
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
return verifyRawPriceDataSign(priceData);
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
exports.verifyPricesSign = verifyPricesSign;
|
|
139
125
|
function verifyRawPriceDataSign(priceData) {
|
|
140
126
|
const message = priceData.dataCell.refs[0].hash();
|
|
141
127
|
const signature = priceData.signature;
|