@evaafi/sdk 0.7.0 → 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/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 +2 -2
- package/dist/constants/general.js +4 -4
- 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 +7 -7
- 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 -1
- 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 -8
- package/dist/prices/utils.js +32 -46
- package/dist/types/Master.d.ts +10 -30
- package/dist/types/Master.js +3 -0
- 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 +3 -2
- 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} +3 -96
- 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 -177
- package/src/contracts/MasterContract.ts +0 -410
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
import { Dictionary } from "@ton/core";
|
|
2
|
-
import { PoolAssetConfig, PoolAssetsConfig
|
|
2
|
+
import { ExtendedEvaaOracle, PoolAssetConfig, PoolAssetsConfig } from "../types/Master";
|
|
3
|
+
import { FetchConfig } from '../utils/utils';
|
|
4
|
+
import { Oracle } from "./Oracle.interface";
|
|
5
|
+
import { Prices } from "./Prices";
|
|
3
6
|
import { PriceSource } from "./sources";
|
|
4
7
|
import { PriceSourcesConfig } from "./Types";
|
|
5
|
-
|
|
6
|
-
|
|
8
|
+
export type PricesCollectorConfig = {
|
|
9
|
+
poolAssetsConfig: PoolAssetsConfig;
|
|
10
|
+
minimalOracles: number;
|
|
11
|
+
evaaOracles: ExtendedEvaaOracle[];
|
|
12
|
+
sourcesConfig?: PriceSourcesConfig;
|
|
13
|
+
additionalPriceSources?: PriceSource[];
|
|
14
|
+
};
|
|
15
|
+
export declare class PricesCollector implements Oracle {
|
|
7
16
|
#private;
|
|
8
|
-
constructor(
|
|
9
|
-
getPricesForLiquidate(realPrincipals: Dictionary<bigint, bigint>,
|
|
10
|
-
getPricesForWithdraw(realPrincipals: Dictionary<bigint, bigint>, withdrawAsset: PoolAssetConfig, collateralToDebt?: boolean,
|
|
11
|
-
|
|
17
|
+
constructor(config: PricesCollectorConfig);
|
|
18
|
+
getPricesForLiquidate(realPrincipals: Dictionary<bigint, bigint>, fetchConfig?: FetchConfig): Promise<Prices>;
|
|
19
|
+
getPricesForWithdraw(realPrincipals: Dictionary<bigint, bigint>, withdrawAsset: PoolAssetConfig, collateralToDebt?: boolean, fetchConfig?: FetchConfig): Promise<Prices>;
|
|
20
|
+
getPricesForSupplyWithdraw(realPrincipals: Dictionary<bigint, bigint>, supplyAsset: PoolAssetConfig | undefined, withdrawAsset: PoolAssetConfig | undefined, collateralToDebt: boolean, fetchConfig?: FetchConfig): Promise<Prices>;
|
|
21
|
+
getPrices(assets?: PoolAssetsConfig, fetchConfig?: FetchConfig): Promise<Prices>;
|
|
12
22
|
}
|
|
@@ -10,40 +10,40 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
10
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
11
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
12
|
};
|
|
13
|
-
var _PricesCollector_instances, _PricesCollector_prices,
|
|
13
|
+
var _PricesCollector_instances, _PricesCollector_prices, _PricesCollector_poolAssetsConfig, _PricesCollector_sourcesConfig, _PricesCollector_priceSources, _PricesCollector_minimalOracles, _PricesCollector_getPricesByAssetList, _PricesCollector_collectPrices, _PricesCollector_collectPricesWithValidation, _PricesCollector_filterPrices, _PricesCollector_filterEmptyPrincipalsAndAssets;
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.PricesCollector = void 0;
|
|
16
16
|
const core_1 = require("@ton/core");
|
|
17
|
-
const pools_1 = require("../constants/pools");
|
|
18
|
-
const Types_1 = require("./Types");
|
|
19
|
-
const utils_1 = require("./utils");
|
|
20
|
-
const utils_2 = require("../utils/utils");
|
|
21
|
-
const Prices_1 = require("./Prices");
|
|
22
17
|
const math_1 = require("../api/math");
|
|
18
|
+
const utils_1 = require("../utils/utils");
|
|
19
|
+
const Prices_1 = require("./Prices");
|
|
20
|
+
const Types_1 = require("./Types");
|
|
21
|
+
const utils_2 = require("./utils");
|
|
23
22
|
class PricesCollector {
|
|
24
|
-
constructor(
|
|
23
|
+
constructor(config) {
|
|
25
24
|
_PricesCollector_instances.add(this);
|
|
26
25
|
_PricesCollector_prices.set(this, void 0);
|
|
27
|
-
|
|
26
|
+
_PricesCollector_poolAssetsConfig.set(this, void 0);
|
|
28
27
|
_PricesCollector_sourcesConfig.set(this, void 0);
|
|
29
28
|
_PricesCollector_priceSources.set(this, void 0);
|
|
30
|
-
|
|
31
|
-
__classPrivateFieldSet(this,
|
|
32
|
-
__classPrivateFieldSet(this,
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
_PricesCollector_minimalOracles.set(this, void 0);
|
|
30
|
+
__classPrivateFieldSet(this, _PricesCollector_poolAssetsConfig, config.poolAssetsConfig, "f");
|
|
31
|
+
__classPrivateFieldSet(this, _PricesCollector_sourcesConfig, config.sourcesConfig ?? Types_1.DefaultPriceSourcesConfig, "f");
|
|
32
|
+
__classPrivateFieldSet(this, _PricesCollector_priceSources, (0, utils_2.generatePriceSources)(__classPrivateFieldGet(this, _PricesCollector_sourcesConfig, "f"), config.evaaOracles), "f");
|
|
33
|
+
__classPrivateFieldSet(this, _PricesCollector_minimalOracles, config.minimalOracles, "f");
|
|
34
|
+
if (config.additionalPriceSources) {
|
|
35
|
+
__classPrivateFieldGet(this, _PricesCollector_priceSources, "f").push(...config.additionalPriceSources);
|
|
35
36
|
}
|
|
36
37
|
__classPrivateFieldSet(this, _PricesCollector_prices, [], "f");
|
|
37
38
|
}
|
|
38
|
-
|
|
39
|
-
async getPricesForLiquidate(realPrincipals, retries = 1, timeout = 3000) {
|
|
39
|
+
async getPricesForLiquidate(realPrincipals, fetchConfig) {
|
|
40
40
|
const assets = __classPrivateFieldGet(this, _PricesCollector_instances, "m", _PricesCollector_filterEmptyPrincipalsAndAssets).call(this, realPrincipals);
|
|
41
41
|
if (assets.includes(undefined)) {
|
|
42
42
|
throw new Error("User from another pool");
|
|
43
43
|
}
|
|
44
|
-
return await this.getPrices(assets.map(x => x),
|
|
44
|
+
return await this.getPrices(assets.map(x => x), fetchConfig);
|
|
45
45
|
}
|
|
46
|
-
async getPricesForWithdraw(realPrincipals, withdrawAsset, collateralToDebt = false,
|
|
46
|
+
async getPricesForWithdraw(realPrincipals, withdrawAsset, collateralToDebt = false, fetchConfig) {
|
|
47
47
|
let assets = __classPrivateFieldGet(this, _PricesCollector_instances, "m", _PricesCollector_filterEmptyPrincipalsAndAssets).call(this, realPrincipals);
|
|
48
48
|
if ((0, math_1.checkNotInDebtAtAll)(realPrincipals) && (realPrincipals.get(withdrawAsset.assetId) ?? 0n) > 0n && !collateralToDebt) {
|
|
49
49
|
return new Prices_1.Prices(core_1.Dictionary.empty(), core_1.Cell.EMPTY);
|
|
@@ -57,74 +57,90 @@ class PricesCollector {
|
|
|
57
57
|
if (collateralToDebt && assets.length == 1) {
|
|
58
58
|
throw new Error("Cannot debt only one supplied asset");
|
|
59
59
|
}
|
|
60
|
-
return await this.getPrices(assets.map(x => x),
|
|
60
|
+
return await this.getPrices(assets.map(x => x), fetchConfig);
|
|
61
61
|
}
|
|
62
|
-
async
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
async getPricesForSupplyWithdraw(realPrincipals, supplyAsset, withdrawAsset, collateralToDebt, fetchConfig) {
|
|
63
|
+
// Используем ту же логику, что и getPricesForWithdraw, но supplyAsset не используется
|
|
64
|
+
let assets = __classPrivateFieldGet(this, _PricesCollector_instances, "m", _PricesCollector_filterEmptyPrincipalsAndAssets).call(this, realPrincipals);
|
|
65
|
+
if ((0, math_1.checkNotInDebtAtAll)(realPrincipals) && withdrawAsset && (realPrincipals.get(withdrawAsset.assetId) ?? 0n) > 0n && !collateralToDebt) {
|
|
65
66
|
return new Prices_1.Prices(core_1.Dictionary.empty(), core_1.Cell.EMPTY);
|
|
66
67
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
//console.debug('[getPrices] Load prices attemp', i + 1)
|
|
70
|
-
if (i > 0) {
|
|
71
|
-
await (0, utils_2.delay)(timeout);
|
|
72
|
-
}
|
|
73
|
-
await __classPrivateFieldGet(this, _PricesCollector_instances, "m", _PricesCollector_collectPrices).call(this);
|
|
74
|
-
}
|
|
75
|
-
else {
|
|
76
|
-
break;
|
|
77
|
-
}
|
|
68
|
+
if (assets.includes(undefined)) {
|
|
69
|
+
throw new Error("User from another pool");
|
|
78
70
|
}
|
|
79
|
-
if (
|
|
80
|
-
|
|
71
|
+
if (withdrawAsset && !assets.includes(withdrawAsset)) {
|
|
72
|
+
assets.push(withdrawAsset);
|
|
73
|
+
}
|
|
74
|
+
if (collateralToDebt && assets.length == 1) {
|
|
75
|
+
throw new Error("Cannot debt only one supplied asset");
|
|
76
|
+
}
|
|
77
|
+
return await this.getPrices(assets.map(x => x), fetchConfig);
|
|
78
|
+
}
|
|
79
|
+
async getPrices(assets = __classPrivateFieldGet(this, _PricesCollector_poolAssetsConfig, "f"), fetchConfig) {
|
|
80
|
+
if (assets.length == 0) {
|
|
81
|
+
return new Prices_1.Prices(core_1.Dictionary.empty(), core_1.Cell.EMPTY);
|
|
82
|
+
}
|
|
83
|
+
await __classPrivateFieldGet(this, _PricesCollector_instances, "m", _PricesCollector_collectPricesWithValidation).call(this, fetchConfig);
|
|
84
|
+
if (__classPrivateFieldGet(this, _PricesCollector_prices, "f").length < __classPrivateFieldGet(this, _PricesCollector_minimalOracles, "f")) {
|
|
85
|
+
throw new Error(`Error per updating prices, valid ${__classPrivateFieldGet(this, _PricesCollector_prices, "f").length} of ${__classPrivateFieldGet(this, _PricesCollector_minimalOracles, "f")}`);
|
|
81
86
|
}
|
|
82
87
|
const prices = __classPrivateFieldGet(this, _PricesCollector_instances, "m", _PricesCollector_getPricesByAssetList).call(this, assets);
|
|
83
88
|
return new Prices_1.Prices(prices.dict, prices.dataCell);
|
|
84
89
|
}
|
|
85
90
|
}
|
|
86
91
|
exports.PricesCollector = PricesCollector;
|
|
87
|
-
_PricesCollector_prices = new WeakMap(),
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
if (pricesFiltered.length < __classPrivateFieldGet(this, _PricesCollector_poolConfig, "f").minimalOracles) {
|
|
92
|
+
_PricesCollector_prices = new WeakMap(), _PricesCollector_poolAssetsConfig = new WeakMap(), _PricesCollector_sourcesConfig = new WeakMap(), _PricesCollector_priceSources = new WeakMap(), _PricesCollector_minimalOracles = new WeakMap(), _PricesCollector_instances = new WeakSet(), _PricesCollector_getPricesByAssetList = function _PricesCollector_getPricesByAssetList(assets) {
|
|
93
|
+
let pricesFiltered = __classPrivateFieldGet(this, _PricesCollector_prices, "f");
|
|
94
|
+
if (pricesFiltered.length < __classPrivateFieldGet(this, _PricesCollector_minimalOracles, "f")) {
|
|
91
95
|
throw new Error("Not enough price data");
|
|
92
96
|
}
|
|
93
|
-
if (pricesFiltered.length > __classPrivateFieldGet(this,
|
|
97
|
+
if (pricesFiltered.length > __classPrivateFieldGet(this, _PricesCollector_minimalOracles, "f")) {
|
|
94
98
|
const sortedByTimestamp = pricesFiltered.slice().sort((a, b) => b.timestamp - a.timestamp);
|
|
95
|
-
const newerPrices = sortedByTimestamp.slice(0, __classPrivateFieldGet(this,
|
|
99
|
+
const newerPrices = sortedByTimestamp.slice(0, __classPrivateFieldGet(this, _PricesCollector_minimalOracles, "f"));
|
|
96
100
|
pricesFiltered = newerPrices.sort((a, b) => a.oracleId - b.oracleId);
|
|
97
101
|
}
|
|
98
102
|
const medianData = assets.map((asset) => ({
|
|
99
103
|
assetId: asset.assetId,
|
|
100
|
-
medianPrice: (0,
|
|
104
|
+
medianPrice: (0, utils_2.getMedianPrice)(pricesFiltered, asset.assetId),
|
|
101
105
|
}));
|
|
102
106
|
const nonEmptymedianData = medianData.filter(x => x.medianPrice != null);
|
|
103
|
-
const packedMedianData = (0,
|
|
107
|
+
const packedMedianData = (0, utils_2.packAssetsData)(nonEmptymedianData);
|
|
104
108
|
const oraclesData = pricesFiltered.map((x) => ({
|
|
105
109
|
oracle: { id: x.oracleId, pubkey: x.pubkey },
|
|
106
110
|
data: { timestamp: x.timestamp, prices: x.dict },
|
|
107
111
|
signature: x.signature,
|
|
108
112
|
}));
|
|
109
|
-
const packedOracleData = (0,
|
|
113
|
+
const packedOracleData = (0, utils_2.packOraclesData)(oraclesData, nonEmptymedianData.map(x => x.assetId));
|
|
110
114
|
const dict = core_1.Dictionary.empty();
|
|
111
115
|
for (const medianDataAsset of nonEmptymedianData) {
|
|
112
116
|
dict.set(medianDataAsset.assetId, medianDataAsset.medianPrice);
|
|
113
117
|
}
|
|
114
118
|
return {
|
|
115
119
|
dict: dict,
|
|
116
|
-
dataCell: (0,
|
|
120
|
+
dataCell: (0, utils_2.packPrices)(packedMedianData, packedOracleData)
|
|
117
121
|
};
|
|
118
|
-
}, _PricesCollector_collectPrices = async function _PricesCollector_collectPrices() {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
+
}, _PricesCollector_collectPrices = async function _PricesCollector_collectPrices(fetchConfig) {
|
|
123
|
+
for (const priceSource of __classPrivateFieldGet(this, _PricesCollector_priceSources, "f")) {
|
|
124
|
+
try {
|
|
125
|
+
__classPrivateFieldSet(this, _PricesCollector_prices, await (0, utils_1.proxyFetchRetries)((0, utils_2.collectAndFilterPrices)(priceSource, __classPrivateFieldGet(this, _PricesCollector_minimalOracles, "f"), fetchConfig), fetchConfig), "f");
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
// Try next source
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
122
132
|
}
|
|
123
|
-
catch { }
|
|
124
133
|
return false;
|
|
134
|
+
}, _PricesCollector_collectPricesWithValidation = async function _PricesCollector_collectPricesWithValidation(fetchConfig) {
|
|
135
|
+
if (!__classPrivateFieldGet(this, _PricesCollector_prices, "f") || __classPrivateFieldGet(this, _PricesCollector_instances, "m", _PricesCollector_filterPrices).call(this) < __classPrivateFieldGet(this, _PricesCollector_minimalOracles, "f")) {
|
|
136
|
+
const success = await __classPrivateFieldGet(this, _PricesCollector_instances, "m", _PricesCollector_collectPrices).call(this, fetchConfig);
|
|
137
|
+
if (!success || __classPrivateFieldGet(this, _PricesCollector_prices, "f").length < __classPrivateFieldGet(this, _PricesCollector_minimalOracles, "f")) {
|
|
138
|
+
throw new Error(`Failed to collect sufficient prices: ${__classPrivateFieldGet(this, _PricesCollector_prices, "f")?.length || 0} of ${__classPrivateFieldGet(this, _PricesCollector_minimalOracles, "f")}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
125
141
|
}, _PricesCollector_filterPrices = function _PricesCollector_filterPrices() {
|
|
126
|
-
__classPrivateFieldSet(this, _PricesCollector_prices, __classPrivateFieldGet(this, _PricesCollector_prices, "f").filter((0,
|
|
142
|
+
__classPrivateFieldSet(this, _PricesCollector_prices, __classPrivateFieldGet(this, _PricesCollector_prices, "f").filter((0, utils_2.verifyPricesTimestamp)()), "f");
|
|
127
143
|
return __classPrivateFieldGet(this, _PricesCollector_prices, "f").length;
|
|
128
144
|
}, _PricesCollector_filterEmptyPrincipalsAndAssets = function _PricesCollector_filterEmptyPrincipalsAndAssets(principals) {
|
|
129
|
-
return principals.keys().filter(x => principals.get(x) != 0n).map(x => __classPrivateFieldGet(this,
|
|
145
|
+
return principals.keys().filter(x => principals.get(x) != 0n).map(x => __classPrivateFieldGet(this, _PricesCollector_poolAssetsConfig, "f").find(asset => asset.assetId == x));
|
|
130
146
|
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { HexString } from '@pythnetwork/hermes-client';
|
|
2
|
+
import { Dictionary } from '@ton/core';
|
|
3
|
+
import { OracleConfig } from '../api/parsers/PythOracleParser';
|
|
4
|
+
import { PoolAssetConfig, PoolAssetsConfig } from '../types/Master';
|
|
5
|
+
import { FetchConfig } from '../utils/utils';
|
|
6
|
+
import { Oracle } from './Oracle.interface';
|
|
7
|
+
import { Prices } from './Prices';
|
|
8
|
+
import { PythPriceSourcesConfig } from './Types';
|
|
9
|
+
export type PythCollectorConfig = {
|
|
10
|
+
poolAssetsConfig: PoolAssetsConfig;
|
|
11
|
+
pythOracle: OracleConfig;
|
|
12
|
+
pythConfig: PythPriceSourcesConfig;
|
|
13
|
+
};
|
|
14
|
+
export declare class PythCollector implements Oracle {
|
|
15
|
+
#private;
|
|
16
|
+
constructor(config: PythCollectorConfig);
|
|
17
|
+
getPricesForLiquidate(realPrincipals: Dictionary<bigint, bigint>, fetchConfig?: FetchConfig): Promise<Prices>;
|
|
18
|
+
getPricesForSupplyWithdraw(realPrincipals: Dictionary<bigint, bigint>, supplyAsset: PoolAssetConfig | undefined, withdrawAsset: PoolAssetConfig | undefined, collateralToDebt: boolean, fetchConfig?: FetchConfig): Promise<Prices>;
|
|
19
|
+
getPrices(assets?: PoolAssetsConfig, fetchConfig?: FetchConfig): Promise<Prices>;
|
|
20
|
+
getPricesForWithdraw(realPrincipals: Dictionary<bigint, bigint>, withdrawAsset: PoolAssetConfig, collateralToDebt?: boolean, fetchConfig?: FetchConfig): Promise<Prices>;
|
|
21
|
+
createRequiredFeedsList(evaaIds: bigint[]): HexString[];
|
|
22
|
+
}
|
|
@@ -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,5 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
-
import {
|
|
2
|
+
import type { PriceUpdate } from '@pythnetwork/hermes-client';
|
|
3
|
+
import type { Cell, Dictionary } from '@ton/core';
|
|
3
4
|
/**
|
|
4
5
|
* Configuration for price source endpoints.
|
|
5
6
|
*/
|
|
@@ -9,10 +10,21 @@ export type PriceSourcesConfig = {
|
|
|
9
10
|
/** Endpoints for ICP price data */
|
|
10
11
|
icpEndpoints: string[];
|
|
11
12
|
};
|
|
13
|
+
/**
|
|
14
|
+
* Configuration for pyth prices.
|
|
15
|
+
*/
|
|
16
|
+
export type PythPriceSourcesConfig = {
|
|
17
|
+
/** Endpoints for pyth price data */
|
|
18
|
+
pythEndpoints: string[];
|
|
19
|
+
};
|
|
12
20
|
/**
|
|
13
21
|
* Default configuration for price source endpoints.
|
|
14
22
|
*/
|
|
15
23
|
export declare const DefaultPriceSourcesConfig: PriceSourcesConfig;
|
|
24
|
+
/**
|
|
25
|
+
* Configuration for pyth price sources.
|
|
26
|
+
*/
|
|
27
|
+
export declare const DefaultPythPriceSourcesConfig: PythPriceSourcesConfig;
|
|
16
28
|
export type RawPriceData = {
|
|
17
29
|
dict: Dictionary<bigint, bigint>;
|
|
18
30
|
dataCell: Cell;
|
|
@@ -21,6 +33,10 @@ export type RawPriceData = {
|
|
|
21
33
|
pubkey: Buffer;
|
|
22
34
|
timestamp: number;
|
|
23
35
|
};
|
|
36
|
+
export type PythFeedUpdateType = {
|
|
37
|
+
parsed: PriceUpdate['parsed'];
|
|
38
|
+
binary: Buffer;
|
|
39
|
+
};
|
|
24
40
|
export type PriceData = {
|
|
25
41
|
dict: Dictionary<bigint, bigint>;
|
|
26
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;
|