@evaafi/sdk 0.6.1-a → 0.6.2
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/CHANGELOG.md +240 -0
- package/LICENSE.md +7 -0
- package/dist/api/liquidation.js +1 -3
- package/dist/api/math.js +0 -2
- package/dist/api/prices.d.ts +5 -2
- package/dist/api/prices.js +35 -13
- package/dist/constants/assets.d.ts +8 -0
- package/dist/constants/assets.js +31 -1
- package/dist/constants/general.d.ts +3 -0
- package/dist/constants/general.js +10 -17
- package/dist/constants/pools.d.ts +1 -0
- package/dist/constants/pools.js +18 -2
- package/dist/contracts/MasterContract.d.ts +5 -0
- package/dist/contracts/MasterContract.js +6 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +7 -1
- package/dist/prices/Prices.d.ts +9 -0
- package/dist/prices/Prices.js +43 -0
- package/dist/prices/PricesCollector.d.ts +12 -0
- package/dist/prices/PricesCollector.js +121 -0
- package/dist/prices/Types.d.ts +33 -0
- package/dist/prices/Types.js +11 -0
- package/dist/prices/constants.d.ts +1 -0
- package/dist/prices/constants.js +4 -0
- package/dist/prices/index.d.ts +6 -0
- package/dist/prices/index.js +22 -0
- package/dist/prices/sources/Backend.d.ts +13 -0
- package/dist/prices/sources/Backend.js +52 -0
- package/dist/prices/sources/Icp.d.ts +10 -0
- package/dist/prices/sources/Icp.js +23 -0
- package/dist/prices/sources/Iota.d.ts +39 -0
- package/dist/prices/sources/Iota.js +49 -0
- package/dist/prices/sources/PriceSource.d.ts +14 -0
- package/dist/prices/sources/PriceSource.js +26 -0
- package/dist/prices/sources/index.d.ts +4 -0
- package/dist/prices/sources/index.js +20 -0
- package/dist/prices/utils.d.ts +23 -0
- package/dist/prices/utils.js +148 -0
- package/dist/types/Master.d.ts +1 -0
- package/dist/utils/userJettonWallet.js +42 -43
- package/dist/utils/utils.d.ts +1 -0
- package/dist/utils/utils.js +5 -1
- package/package.json +4 -2
- package/src/api/liquidation.ts +0 -1
- package/src/api/math.ts +1 -2
- package/src/api/parser.ts +0 -2
- package/src/api/prices.ts +20 -7
- package/src/constants/assets.ts +57 -0
- package/src/constants/general.ts +9 -18
- package/src/constants/pools.ts +20 -4
- package/src/contracts/MasterContract.ts +8 -1
- package/src/index.ts +7 -2
- package/src/prices/Prices.ts +32 -0
- package/src/prices/PricesCollector.ts +135 -0
- package/src/prices/Types.ts +44 -0
- package/src/prices/constants.ts +1 -0
- package/src/prices/index.ts +6 -0
- package/src/prices/sources/Backend.ts +62 -0
- package/src/prices/sources/Icp.ts +27 -0
- package/src/prices/sources/Iota.ts +90 -0
- package/src/prices/sources/PriceSource.ts +35 -0
- package/src/prices/sources/index.ts +4 -0
- package/src/prices/utils.ts +170 -0
- package/src/types/Master.ts +2 -1
- package/src/utils/userJettonWallet.ts +43 -53
- package/src/utils/utils.ts +5 -1
- package/src/config.ts +0 -1
- package/src/types/Common.ts +0 -16
- package/src/utils/priceUtils.ts +0 -177
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
exports.TESTNET_POOL_CONFIG = exports.MAINNET_POOL_CONFIG = exports.MASTER_CONSTANTS = exports.FEES = exports.OPCODES = exports.LENDING_CODE = exports.TESTNET_VERSION = exports.EVAA_MASTER_TESTNET = exports.MAINNET_VERSION = exports.EVAA_MASTER_MAINNET = exports.BalanceChangeType = exports.BalanceType = exports.EvaaUser = exports.Evaa = exports.JettonWallet = exports.getPrices = exports.parseUserLiteData = exports.parseUserData = exports.parseMasterData = exports.createAssetConfig = exports.createAssetData = exports.calculateAssetsValues = exports.selectGreatestAssets = exports.findAssetById = exports.prepareAssetInfo = exports.toAssetWorth = exports.toAssetAmount = exports.deductLiquidationBonus = exports.addLiquidationBonus = exports.deductReserve = exports.addReserve = exports.isBadDebt = exports.isLiquidatable = exports.calculateMinCollateralByTransferredAmount = exports.calculateLiquidationAmounts = exports.BigMath = exports.calculateHealthParams = exports.predictHealthFactor = exports.calculateLiquidationData = exports.presentValue = exports.calculateMaximumWithdrawAmount = exports.getAvailableToBorrow = exports.calculateAssetInterest = exports.calculateAssetData = exports.calculateCurrentRates = exports.calculatePresentValue = exports.bigIntMax = exports.bigIntMin = exports.mulDiv = exports.mulFactor = void 0;
|
|
18
|
-
exports.getUserJettonWallet = exports.getTonConnectSender = exports.getLastSentBoc = exports.STTON_TESTNET = exports.JUSDC_TESTNET = exports.JUSDT_TESTNET = exports.TSTON_MAINNET = exports.STTON_MAINNET = exports.JUSDC_MAINNET = exports.JUSDT_MAINNET = exports.USDT_STORM_MAINNET = exports.TON_STORM_MAINNET = exports.TONUSDT_DEDUST_MAINNET = exports.USDT_MAINNET = exports.TON_MAINNET = exports.UNDEFINED_ASSET = exports.ASSET_ID = exports.MAINNET_LP_POOL_CONFIG = void 0;
|
|
18
|
+
exports.getUserJettonWallet = exports.getTonConnectSender = exports.getLastSentBoc = exports.STTON_TESTNET = exports.JUSDC_TESTNET = exports.JUSDT_TESTNET = exports.TSTON_MAINNET = exports.STTON_MAINNET = exports.JUSDC_MAINNET = exports.JUSDT_MAINNET = exports.NOT_MAINNET = exports.UTON_MAINNET = exports.CATI_MAINNET = exports.DOGS_MAINNET = exports.USDT_STORM_MAINNET = exports.TON_STORM_MAINNET = exports.TONUSDT_DEDUST_MAINNET = exports.USDT_MAINNET = exports.TON_MAINNET = exports.UNDEFINED_ASSET = exports.ASSET_ID = exports.MAINNET_ALTS_POOL_CONFIG = exports.MAINNET_LP_POOL_CONFIG = void 0;
|
|
19
19
|
// Math
|
|
20
20
|
var math_1 = require("./api/math");
|
|
21
21
|
Object.defineProperty(exports, "mulFactor", { enumerable: true, get: function () { return math_1.mulFactor; } });
|
|
@@ -82,6 +82,7 @@ var pools_1 = require("./constants/pools");
|
|
|
82
82
|
Object.defineProperty(exports, "MAINNET_POOL_CONFIG", { enumerable: true, get: function () { return pools_1.MAINNET_POOL_CONFIG; } });
|
|
83
83
|
Object.defineProperty(exports, "TESTNET_POOL_CONFIG", { enumerable: true, get: function () { return pools_1.TESTNET_POOL_CONFIG; } });
|
|
84
84
|
Object.defineProperty(exports, "MAINNET_LP_POOL_CONFIG", { enumerable: true, get: function () { return pools_1.MAINNET_LP_POOL_CONFIG; } });
|
|
85
|
+
Object.defineProperty(exports, "MAINNET_ALTS_POOL_CONFIG", { enumerable: true, get: function () { return pools_1.MAINNET_ALTS_POOL_CONFIG; } });
|
|
85
86
|
var assets_1 = require("./constants/assets");
|
|
86
87
|
Object.defineProperty(exports, "ASSET_ID", { enumerable: true, get: function () { return assets_1.ASSET_ID; } });
|
|
87
88
|
Object.defineProperty(exports, "UNDEFINED_ASSET", { enumerable: true, get: function () { return assets_1.UNDEFINED_ASSET; } });
|
|
@@ -90,6 +91,10 @@ Object.defineProperty(exports, "USDT_MAINNET", { enumerable: true, get: function
|
|
|
90
91
|
Object.defineProperty(exports, "TONUSDT_DEDUST_MAINNET", { enumerable: true, get: function () { return assets_1.TONUSDT_DEDUST_MAINNET; } });
|
|
91
92
|
Object.defineProperty(exports, "TON_STORM_MAINNET", { enumerable: true, get: function () { return assets_1.TON_STORM_MAINNET; } });
|
|
92
93
|
Object.defineProperty(exports, "USDT_STORM_MAINNET", { enumerable: true, get: function () { return assets_1.USDT_STORM_MAINNET; } });
|
|
94
|
+
Object.defineProperty(exports, "DOGS_MAINNET", { enumerable: true, get: function () { return assets_1.DOGS_MAINNET; } });
|
|
95
|
+
Object.defineProperty(exports, "CATI_MAINNET", { enumerable: true, get: function () { return assets_1.CATI_MAINNET; } });
|
|
96
|
+
Object.defineProperty(exports, "UTON_MAINNET", { enumerable: true, get: function () { return assets_1.UTON_MAINNET; } });
|
|
97
|
+
Object.defineProperty(exports, "NOT_MAINNET", { enumerable: true, get: function () { return assets_1.NOT_MAINNET; } });
|
|
93
98
|
Object.defineProperty(exports, "JUSDT_MAINNET", { enumerable: true, get: function () { return assets_1.JUSDT_MAINNET; } });
|
|
94
99
|
Object.defineProperty(exports, "JUSDC_MAINNET", { enumerable: true, get: function () { return assets_1.JUSDC_MAINNET; } });
|
|
95
100
|
Object.defineProperty(exports, "STTON_MAINNET", { enumerable: true, get: function () { return assets_1.STTON_MAINNET; } });
|
|
@@ -99,6 +104,7 @@ Object.defineProperty(exports, "JUSDC_TESTNET", { enumerable: true, get: functio
|
|
|
99
104
|
Object.defineProperty(exports, "STTON_TESTNET", { enumerable: true, get: function () { return assets_1.STTON_TESTNET; } });
|
|
100
105
|
__exportStar(require("./constants/assets"), exports);
|
|
101
106
|
__exportStar(require("./utils/utils"), exports);
|
|
107
|
+
__exportStar(require("./prices"), exports);
|
|
102
108
|
// Utils
|
|
103
109
|
var tonConnectSender_1 = require("./utils/tonConnectSender");
|
|
104
110
|
Object.defineProperty(exports, "getLastSentBoc", { enumerable: true, get: function () { return tonConnectSender_1.getLastSentBoc; } });
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Cell, Dictionary } from "@ton/core";
|
|
2
|
+
import { PoolAssetConfig } from "../types/Master";
|
|
3
|
+
export declare class Prices {
|
|
4
|
+
#private;
|
|
5
|
+
constructor(dict: Dictionary<bigint, bigint>, dataCell: Cell);
|
|
6
|
+
get dict(): Dictionary<bigint, bigint>;
|
|
7
|
+
get dataCell(): Cell;
|
|
8
|
+
getAssetPrice<T extends bigint | PoolAssetConfig>(asset: T): bigint | undefined;
|
|
9
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
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 _Prices_instances, _Prices_dict, _Prices_dataCell, _Prices_extractAssetId;
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.Prices = void 0;
|
|
16
|
+
const core_1 = require("@ton/core");
|
|
17
|
+
class Prices {
|
|
18
|
+
constructor(dict, dataCell) {
|
|
19
|
+
_Prices_instances.add(this);
|
|
20
|
+
_Prices_dict.set(this, void 0);
|
|
21
|
+
_Prices_dataCell.set(this, void 0);
|
|
22
|
+
__classPrivateFieldSet(this, _Prices_dict, dict, "f");
|
|
23
|
+
__classPrivateFieldSet(this, _Prices_dataCell, dataCell, "f");
|
|
24
|
+
}
|
|
25
|
+
get dict() {
|
|
26
|
+
const dict = core_1.Dictionary.empty();
|
|
27
|
+
for (const [key, value] of __classPrivateFieldGet(this, _Prices_dict, "f")) {
|
|
28
|
+
dict.set(key, value);
|
|
29
|
+
}
|
|
30
|
+
return dict;
|
|
31
|
+
}
|
|
32
|
+
get dataCell() {
|
|
33
|
+
return new core_1.Cell(__classPrivateFieldGet(this, _Prices_dataCell, "f"));
|
|
34
|
+
}
|
|
35
|
+
getAssetPrice(asset) {
|
|
36
|
+
const assetId = __classPrivateFieldGet(this, _Prices_instances, "m", _Prices_extractAssetId).call(this, asset);
|
|
37
|
+
return __classPrivateFieldGet(this, _Prices_dict, "f").get(assetId);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.Prices = Prices;
|
|
41
|
+
_Prices_dict = new WeakMap(), _Prices_dataCell = new WeakMap(), _Prices_instances = new WeakSet(), _Prices_extractAssetId = function _Prices_extractAssetId(asset) {
|
|
42
|
+
return typeof asset === 'bigint' ? asset : asset.assetId;
|
|
43
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Dictionary } from "@ton/core";
|
|
2
|
+
import { PoolAssetConfig, PoolAssetsConfig, PoolConfig } from "../types/Master";
|
|
3
|
+
import { PriceSource } from "./sources";
|
|
4
|
+
import { PriceSourcesConfig } from "./Types";
|
|
5
|
+
import { Prices } from "./Prices";
|
|
6
|
+
export declare class PricesCollector {
|
|
7
|
+
#private;
|
|
8
|
+
constructor(poolConfig?: PoolConfig, sourcesConfig?: PriceSourcesConfig, additionalPriceSources?: PriceSource[]);
|
|
9
|
+
getPricesForLiquidate(userPrincipals: Dictionary<bigint, bigint>, retries?: number, timeout?: number): Promise<Prices>;
|
|
10
|
+
getPricesForWithdraw(userPrincipals: Dictionary<bigint, bigint>, withdrawAsset: PoolAssetConfig, collateralToDebt?: boolean, retries?: number, timeout?: number): Promise<Prices>;
|
|
11
|
+
getPrices(assets?: PoolAssetsConfig, retries?: number, timeout?: number): Promise<Prices>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
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 _PricesCollector_instances, _PricesCollector_prices, _PricesCollector_poolConfig, _PricesCollector_sourcesConfig, _PricesCollector_priceSources, _PricesCollector_getPricesByAssetList, _PricesCollector_collectPrices, _PricesCollector_filterPrices;
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.PricesCollector = void 0;
|
|
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
|
+
const math_1 = require("../api/math");
|
|
23
|
+
class PricesCollector {
|
|
24
|
+
constructor(poolConfig = pools_1.MAINNET_POOL_CONFIG, sourcesConfig = Types_1.DefaultPriceSourcesConfig, additionalPriceSources) {
|
|
25
|
+
_PricesCollector_instances.add(this);
|
|
26
|
+
_PricesCollector_prices.set(this, void 0);
|
|
27
|
+
_PricesCollector_poolConfig.set(this, void 0);
|
|
28
|
+
_PricesCollector_sourcesConfig.set(this, void 0);
|
|
29
|
+
_PricesCollector_priceSources.set(this, void 0);
|
|
30
|
+
__classPrivateFieldSet(this, _PricesCollector_poolConfig, poolConfig, "f");
|
|
31
|
+
__classPrivateFieldSet(this, _PricesCollector_sourcesConfig, sourcesConfig, "f");
|
|
32
|
+
__classPrivateFieldSet(this, _PricesCollector_priceSources, (0, utils_1.generatePriceSources)(__classPrivateFieldGet(this, _PricesCollector_sourcesConfig, "f"), __classPrivateFieldGet(this, _PricesCollector_poolConfig, "f").oracles), "f");
|
|
33
|
+
if (additionalPriceSources) {
|
|
34
|
+
__classPrivateFieldGet(this, _PricesCollector_priceSources, "f").push(...additionalPriceSources);
|
|
35
|
+
}
|
|
36
|
+
__classPrivateFieldSet(this, _PricesCollector_prices, [], "f");
|
|
37
|
+
}
|
|
38
|
+
// TODO Make UserData class and incapsulate raw bigintegers
|
|
39
|
+
async getPricesForLiquidate(userPrincipals, retries = 1, timeout = 3000) {
|
|
40
|
+
const assets = userPrincipals.keys().map(x => __classPrivateFieldGet(this, _PricesCollector_poolConfig, "f").poolAssetsConfig.find(asset => asset.assetId == x));
|
|
41
|
+
if (assets.includes(undefined)) {
|
|
42
|
+
throw new Error("User from another pool");
|
|
43
|
+
}
|
|
44
|
+
return await this.getPrices(assets.map(x => x), retries, timeout);
|
|
45
|
+
}
|
|
46
|
+
async getPricesForWithdraw(userPrincipals, withdrawAsset, collateralToDebt = false, retries = 1, timeout = 3000) {
|
|
47
|
+
let assets = userPrincipals.keys().map(x => __classPrivateFieldGet(this, _PricesCollector_poolConfig, "f").poolAssetsConfig.find(asset => asset.assetId == x));
|
|
48
|
+
if ((0, math_1.checkNotInDebtAtAll)(userPrincipals) && userPrincipals.has(withdrawAsset.assetId) && !collateralToDebt) {
|
|
49
|
+
return new Prices_1.Prices(core_1.Dictionary.empty(), core_1.Cell.EMPTY);
|
|
50
|
+
}
|
|
51
|
+
if (assets.includes(undefined)) {
|
|
52
|
+
throw new Error("User from another pool");
|
|
53
|
+
}
|
|
54
|
+
if (!assets.includes(withdrawAsset)) {
|
|
55
|
+
assets.push(withdrawAsset);
|
|
56
|
+
}
|
|
57
|
+
if (collateralToDebt && assets.length == 1) {
|
|
58
|
+
throw new Error("Cannot debt only one supplied asset");
|
|
59
|
+
}
|
|
60
|
+
return await this.getPrices(assets.map(x => x), retries, timeout);
|
|
61
|
+
}
|
|
62
|
+
async getPrices(assets = __classPrivateFieldGet(this, _PricesCollector_poolConfig, "f").poolAssetsConfig, retries = 1, timeout = 3000) {
|
|
63
|
+
console.debug('[getPrices] Assets length', assets.length);
|
|
64
|
+
if (assets.length == 0) {
|
|
65
|
+
return new Prices_1.Prices(core_1.Dictionary.empty(), core_1.Cell.EMPTY);
|
|
66
|
+
}
|
|
67
|
+
for (let i = 0; i <= retries; i++) { // attemts = retries + 1
|
|
68
|
+
if (!__classPrivateFieldGet(this, _PricesCollector_prices, "f") || __classPrivateFieldGet(this, _PricesCollector_instances, "m", _PricesCollector_filterPrices).call(this) < __classPrivateFieldGet(this, _PricesCollector_poolConfig, "f").minimalOracles) {
|
|
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
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (__classPrivateFieldGet(this, _PricesCollector_prices, "f").length < __classPrivateFieldGet(this, _PricesCollector_poolConfig, "f").minimalOracles) {
|
|
80
|
+
throw new Error(`Error per updating prices, valid ${__classPrivateFieldGet(this, _PricesCollector_prices, "f").length} of ${__classPrivateFieldGet(this, _PricesCollector_poolConfig, "f").minimalOracles}`); // if still not enough data after retries
|
|
81
|
+
}
|
|
82
|
+
const prices = __classPrivateFieldGet(this, _PricesCollector_instances, "m", _PricesCollector_getPricesByAssetList).call(this, assets);
|
|
83
|
+
return new Prices_1.Prices(prices.dict, prices.dataCell);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
exports.PricesCollector = PricesCollector;
|
|
87
|
+
_PricesCollector_prices = new WeakMap(), _PricesCollector_poolConfig = new WeakMap(), _PricesCollector_sourcesConfig = new WeakMap(), _PricesCollector_priceSources = new WeakMap(), _PricesCollector_instances = new WeakSet(), _PricesCollector_getPricesByAssetList = function _PricesCollector_getPricesByAssetList(assets) {
|
|
88
|
+
//console.debug('[getPricesByAssetList] start')
|
|
89
|
+
let pricesFiltered = __classPrivateFieldGet(this, _PricesCollector_prices, "f"); // for strict check this.#prices.filter(x => assets.every(asset => x.dict.has(asset.assetId)));
|
|
90
|
+
if (pricesFiltered.length < __classPrivateFieldGet(this, _PricesCollector_poolConfig, "f").minimalOracles) {
|
|
91
|
+
throw new Error("Not enough price data");
|
|
92
|
+
}
|
|
93
|
+
if (pricesFiltered.length > __classPrivateFieldGet(this, _PricesCollector_poolConfig, "f").minimalOracles) {
|
|
94
|
+
const sortedByTimestamp = pricesFiltered.slice().sort((a, b) => b.timestamp - a.timestamp);
|
|
95
|
+
const newerPrices = sortedByTimestamp.slice(0, __classPrivateFieldGet(this, _PricesCollector_poolConfig, "f").minimalOracles);
|
|
96
|
+
pricesFiltered = newerPrices.sort((a, b) => a.oracleId - b.oracleId);
|
|
97
|
+
}
|
|
98
|
+
const medianData = assets.map(asset => ({ assetId: asset.assetId, medianPrice: (0, utils_1.getMedianPrice)(__classPrivateFieldGet(this, _PricesCollector_prices, "f"), asset.assetId) }));
|
|
99
|
+
const nonEmptymedianData = medianData.filter(x => x.medianPrice != null);
|
|
100
|
+
const packedMedianData = (0, utils_1.packAssetsData)(nonEmptymedianData);
|
|
101
|
+
const oraclesData = __classPrivateFieldGet(this, _PricesCollector_prices, "f").map(x => ({ oracle: { id: x.oracleId, pubkey: x.pubkey }, data: { timestamp: x.timestamp, prices: x.dict }, signature: x.signature }));
|
|
102
|
+
const packedOracleData = (0, utils_1.packOraclesData)(oraclesData, nonEmptymedianData.map(x => x.assetId));
|
|
103
|
+
const dict = core_1.Dictionary.empty();
|
|
104
|
+
for (const medianDataAsset of nonEmptymedianData) {
|
|
105
|
+
dict.set(medianDataAsset.assetId, medianDataAsset.medianPrice);
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
dict: dict,
|
|
109
|
+
dataCell: (0, utils_1.packPrices)(packedMedianData, packedOracleData)
|
|
110
|
+
};
|
|
111
|
+
}, _PricesCollector_collectPrices = async function _PricesCollector_collectPrices() {
|
|
112
|
+
try {
|
|
113
|
+
__classPrivateFieldSet(this, _PricesCollector_prices, await Promise.any(__classPrivateFieldGet(this, _PricesCollector_priceSources, "f").map(x => (0, utils_1.collectAndFilterPrices)(x, __classPrivateFieldGet(this, _PricesCollector_poolConfig, "f")))), "f");
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
catch { }
|
|
117
|
+
return false;
|
|
118
|
+
}, _PricesCollector_filterPrices = function _PricesCollector_filterPrices() {
|
|
119
|
+
__classPrivateFieldSet(this, _PricesCollector_prices, __classPrivateFieldGet(this, _PricesCollector_prices, "f").filter((0, utils_1.verifyPricesTimestamp)()), "f");
|
|
120
|
+
return __classPrivateFieldGet(this, _PricesCollector_prices, "f").length;
|
|
121
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { Cell, Dictionary } from '@ton/core';
|
|
3
|
+
/**
|
|
4
|
+
* Configuration for price source endpoints.
|
|
5
|
+
*/
|
|
6
|
+
export type PriceSourcesConfig = {
|
|
7
|
+
/** Endpoints for backend price data */
|
|
8
|
+
backendEndpoints: string[];
|
|
9
|
+
/** Endpoints for IOTA price data */
|
|
10
|
+
iotaEndpoints: string[];
|
|
11
|
+
/** Endpoints for ICP price data */
|
|
12
|
+
icpEndpoints: string[];
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Default configuration for price source endpoints.
|
|
16
|
+
*/
|
|
17
|
+
export declare const DefaultPriceSourcesConfig: PriceSourcesConfig;
|
|
18
|
+
export type RawPriceData = {
|
|
19
|
+
dict: Dictionary<bigint, bigint>;
|
|
20
|
+
dataCell: Cell;
|
|
21
|
+
oracleId: number;
|
|
22
|
+
signature: Buffer;
|
|
23
|
+
pubkey: Buffer;
|
|
24
|
+
timestamp: number;
|
|
25
|
+
};
|
|
26
|
+
export type PriceData = {
|
|
27
|
+
dict: Dictionary<bigint, bigint>;
|
|
28
|
+
dataCell: Cell;
|
|
29
|
+
};
|
|
30
|
+
export type OraclePricesData = {
|
|
31
|
+
timestamp: number;
|
|
32
|
+
prices: Dictionary<bigint, bigint>;
|
|
33
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DefaultPriceSourcesConfig = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Default configuration for price source endpoints.
|
|
6
|
+
*/
|
|
7
|
+
exports.DefaultPriceSourcesConfig = {
|
|
8
|
+
backendEndpoints: ['evaa.space'],
|
|
9
|
+
iotaEndpoints: ['api.stardust-mainnet.iotaledger.net'],
|
|
10
|
+
icpEndpoints: ['6khmc-aiaaa-aaaap-ansfq-cai.raw.icp0.io'],
|
|
11
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const TTL_ORACLE_DATA_SEC = 120;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./sources"), exports);
|
|
18
|
+
__exportStar(require("./Types"), exports);
|
|
19
|
+
__exportStar(require("./constants"), exports);
|
|
20
|
+
__exportStar(require("./utils"), exports);
|
|
21
|
+
__exportStar(require("./Prices"), exports);
|
|
22
|
+
__exportStar(require("./PricesCollector"), exports);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { RawPriceData } from "..";
|
|
2
|
+
import { PriceSource } from "./PriceSource";
|
|
3
|
+
export declare class BackendPriceSource extends PriceSource {
|
|
4
|
+
protected priceSourceName: string;
|
|
5
|
+
getPrices(): Promise<RawPriceData[]>;
|
|
6
|
+
loadOracleData(): Promise<OutputData[]>;
|
|
7
|
+
parsePrices(outputData: OutputData): RawPriceData;
|
|
8
|
+
}
|
|
9
|
+
type OutputData = {
|
|
10
|
+
oracleId: number;
|
|
11
|
+
data: string;
|
|
12
|
+
};
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BackendPriceSource = void 0;
|
|
4
|
+
const core_1 = require("@ton/core");
|
|
5
|
+
const PriceSource_1 = require("./PriceSource");
|
|
6
|
+
class BackendPriceSource extends PriceSource_1.PriceSource {
|
|
7
|
+
constructor() {
|
|
8
|
+
super(...arguments);
|
|
9
|
+
this.priceSourceName = 'BackendPriceSource';
|
|
10
|
+
}
|
|
11
|
+
async getPrices() {
|
|
12
|
+
const data = await this.loadOracleData();
|
|
13
|
+
return data.map(outputData => this.parsePrices(outputData));
|
|
14
|
+
}
|
|
15
|
+
async loadOracleData() {
|
|
16
|
+
let response = await fetch(`https://${this._endpoint}/api/prices`, {
|
|
17
|
+
headers: { accept: 'application/json' },
|
|
18
|
+
signal: AbortSignal.timeout(5000)
|
|
19
|
+
});
|
|
20
|
+
const resp = (await response.json());
|
|
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;
|
|
27
|
+
}
|
|
28
|
+
parsePrices(outputData) {
|
|
29
|
+
try {
|
|
30
|
+
//console.debug('outputData', outputData);
|
|
31
|
+
//console.debug(outputData.data.replace('0x', '').replace(/[0-9a-f]{2}/g, '%$&'))
|
|
32
|
+
const data = JSON.parse(decodeURIComponent(outputData.data.replace('0x', '').replace(/[0-9a-f]{2}/g, '%$&')));
|
|
33
|
+
const pricesCell = core_1.Cell.fromBoc(Buffer.from(data['packedPrices'], 'hex'))[0];
|
|
34
|
+
const signature = Buffer.from(data['signature'], 'hex');
|
|
35
|
+
const publicKey = Buffer.from(data['publicKey'], 'hex');
|
|
36
|
+
const timestamp = Number(data['timestamp']);
|
|
37
|
+
return {
|
|
38
|
+
dict: pricesCell.beginParse().loadRef().beginParse().loadDictDirect(core_1.Dictionary.Keys.BigUint(256), core_1.Dictionary.Values.BigVarUint(4)),
|
|
39
|
+
dataCell: (0, core_1.beginCell)().storeRef(pricesCell).storeBuffer(signature).endCell(),
|
|
40
|
+
oracleId: outputData.oracleId,
|
|
41
|
+
signature: signature,
|
|
42
|
+
pubkey: publicKey,
|
|
43
|
+
timestamp: timestamp,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
//console.debug(`Price source error ${this.priceSourceName} ${outputData.oracleId} ${outputData.data} ${error}`);
|
|
48
|
+
throw error;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
exports.BackendPriceSource = BackendPriceSource;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { BackendPriceSource } from ".";
|
|
2
|
+
export declare class IcpPriceSource extends BackendPriceSource {
|
|
3
|
+
protected priceSourceName: string;
|
|
4
|
+
loadOracleData(): Promise<OutputData[]>;
|
|
5
|
+
}
|
|
6
|
+
type OutputData = {
|
|
7
|
+
oracleId: number;
|
|
8
|
+
data: string;
|
|
9
|
+
};
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.IcpPriceSource = void 0;
|
|
4
|
+
const _1 = require(".");
|
|
5
|
+
class IcpPriceSource extends _1.BackendPriceSource {
|
|
6
|
+
constructor() {
|
|
7
|
+
super(...arguments);
|
|
8
|
+
this.priceSourceName = 'IcpPriceSource';
|
|
9
|
+
}
|
|
10
|
+
async loadOracleData() {
|
|
11
|
+
let response = await fetch(`https://${this._endpoint}/prices`, {
|
|
12
|
+
headers: { accept: 'application/json' },
|
|
13
|
+
signal: AbortSignal.timeout(5000)
|
|
14
|
+
});
|
|
15
|
+
const data = (await response.json());
|
|
16
|
+
let outputData = [];
|
|
17
|
+
for (const nft of this._nfts) {
|
|
18
|
+
outputData.push({ oracleId: nft.id, data: data[nft.address] });
|
|
19
|
+
}
|
|
20
|
+
return outputData;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.IcpPriceSource = IcpPriceSource;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { PriceSource } from "./PriceSource";
|
|
2
|
+
import { RawPriceData } from "..";
|
|
3
|
+
export declare class IotaPriceSource extends PriceSource {
|
|
4
|
+
protected priceSourceName: string;
|
|
5
|
+
getPrices(): Promise<RawPriceData[]>;
|
|
6
|
+
loadOracleData(oracleNftId: String): Promise<OutputData>;
|
|
7
|
+
parsePrices(outputData: OutputData, oracleId: number): RawPriceData;
|
|
8
|
+
}
|
|
9
|
+
type OutputData = {
|
|
10
|
+
metadata: {
|
|
11
|
+
blockId: string;
|
|
12
|
+
transactionId: string;
|
|
13
|
+
outputIndex: number;
|
|
14
|
+
isSpent: boolean;
|
|
15
|
+
milestoneIndexSpent: number;
|
|
16
|
+
milestoneTimestampSpent: number;
|
|
17
|
+
transactionIdSpent: string;
|
|
18
|
+
milestoneIndexBooked: number;
|
|
19
|
+
milestoneTimestampBooked: number;
|
|
20
|
+
ledgerIndex: number;
|
|
21
|
+
};
|
|
22
|
+
output: {
|
|
23
|
+
type: number;
|
|
24
|
+
amount: string;
|
|
25
|
+
nftId: string;
|
|
26
|
+
unlockConditions: {
|
|
27
|
+
type: number;
|
|
28
|
+
address: {
|
|
29
|
+
type: number;
|
|
30
|
+
pubKeyHash: string;
|
|
31
|
+
};
|
|
32
|
+
}[];
|
|
33
|
+
features: {
|
|
34
|
+
type: number;
|
|
35
|
+
data: string;
|
|
36
|
+
}[];
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.IotaPriceSource = void 0;
|
|
4
|
+
const core_1 = require("@ton/core");
|
|
5
|
+
const PriceSource_1 = require("./PriceSource");
|
|
6
|
+
class IotaPriceSource extends PriceSource_1.PriceSource {
|
|
7
|
+
constructor() {
|
|
8
|
+
super(...arguments);
|
|
9
|
+
this.priceSourceName = 'IotaPriceSource';
|
|
10
|
+
}
|
|
11
|
+
async getPrices() {
|
|
12
|
+
return await Promise.all(this.nfts.map(nft => this.loadOracleData(nft.address)
|
|
13
|
+
.then(x => this.parsePrices(x, nft.id))));
|
|
14
|
+
}
|
|
15
|
+
async loadOracleData(oracleNftId) {
|
|
16
|
+
let result = await fetch(`https://${this._endpoint}/api/indexer/v1/outputs/nft/${oracleNftId}`, {
|
|
17
|
+
headers: { accept: 'application/json' },
|
|
18
|
+
signal: AbortSignal.timeout(5000)
|
|
19
|
+
});
|
|
20
|
+
let outputId = (await result.json());
|
|
21
|
+
result = await fetch(`https://${this._endpoint}/api/core/v2/outputs/${outputId.items[0]}`, {
|
|
22
|
+
headers: { accept: 'application/json' },
|
|
23
|
+
signal: AbortSignal.timeout(5000)
|
|
24
|
+
});
|
|
25
|
+
return await result.json();
|
|
26
|
+
}
|
|
27
|
+
parsePrices(outputData, oracleId) {
|
|
28
|
+
const data = JSON.parse(decodeURIComponent(outputData.output.features[0].data.replace('0x', '').replace(/[0-9a-f]{2}/g, '%$&')));
|
|
29
|
+
try {
|
|
30
|
+
const pricesCell = core_1.Cell.fromBoc(Buffer.from(data['packedPrices'], 'hex'))[0];
|
|
31
|
+
const signature = Buffer.from(data['signature'], 'hex');
|
|
32
|
+
const publicKey = Buffer.from(data['publicKey'], 'hex');
|
|
33
|
+
const timestamp = Number(data['timestamp']);
|
|
34
|
+
return {
|
|
35
|
+
dict: pricesCell.beginParse().loadRef().beginParse().loadDictDirect(core_1.Dictionary.Keys.BigUint(256), core_1.Dictionary.Values.BigVarUint(4)),
|
|
36
|
+
dataCell: (0, core_1.beginCell)().storeRef(pricesCell).storeBuffer(signature).endCell(),
|
|
37
|
+
oracleId: oracleId,
|
|
38
|
+
signature: signature,
|
|
39
|
+
pubkey: publicKey,
|
|
40
|
+
timestamp: timestamp,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
//console.debug(`Price source error ${this.priceSourceName} ${outputData} ${error}`);
|
|
45
|
+
throw error;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
exports.IotaPriceSource = IotaPriceSource;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { RawPriceData } from "..";
|
|
2
|
+
import { OracleNFT } from "../../types/Master";
|
|
3
|
+
export declare abstract class PriceSource {
|
|
4
|
+
protected priceSourceName: string;
|
|
5
|
+
protected _endpoint: string;
|
|
6
|
+
protected _nfts: OracleNFT[];
|
|
7
|
+
constructor(endpoint: string, nfts: OracleNFT[]);
|
|
8
|
+
get sourceName(): string;
|
|
9
|
+
get endpoint(): string;
|
|
10
|
+
get nfts(): OracleNFT[];
|
|
11
|
+
set endpoint(endpoint: string);
|
|
12
|
+
set nfts(nfts: OracleNFT[]);
|
|
13
|
+
abstract getPrices(): Promise<RawPriceData[]>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PriceSource = void 0;
|
|
4
|
+
class PriceSource {
|
|
5
|
+
constructor(endpoint, nfts) {
|
|
6
|
+
this.priceSourceName = 'BackendPriceSource';
|
|
7
|
+
this._endpoint = endpoint;
|
|
8
|
+
this._nfts = nfts;
|
|
9
|
+
}
|
|
10
|
+
get sourceName() {
|
|
11
|
+
return this.priceSourceName;
|
|
12
|
+
}
|
|
13
|
+
get endpoint() {
|
|
14
|
+
return this._endpoint;
|
|
15
|
+
}
|
|
16
|
+
get nfts() {
|
|
17
|
+
return this._nfts;
|
|
18
|
+
}
|
|
19
|
+
set endpoint(endpoint) {
|
|
20
|
+
this._endpoint = endpoint;
|
|
21
|
+
}
|
|
22
|
+
set nfts(nfts) {
|
|
23
|
+
this._nfts = nfts;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.PriceSource = PriceSource;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./Backend"), exports);
|
|
18
|
+
__exportStar(require("./Iota"), exports);
|
|
19
|
+
__exportStar(require("./Icp"), exports);
|
|
20
|
+
__exportStar(require("./PriceSource"), exports);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { Cell, Dictionary, Slice } from "@ton/core";
|
|
3
|
+
import { OraclePricesData, PriceData, PriceSource, PriceSourcesConfig, RawPriceData } from "..";
|
|
4
|
+
import { Oracle, OracleNFT, PoolConfig } from "../types/Master";
|
|
5
|
+
export declare function verifyPricesTimestamp(): (priceData: RawPriceData) => boolean;
|
|
6
|
+
export declare function verifyPricesSign(nfts: OracleNFT[]): (priceData: RawPriceData) => boolean;
|
|
7
|
+
export declare function getMedianPrice(pricesData: PriceData[], asset: bigint): bigint | null;
|
|
8
|
+
export declare function packAssetsData(assetsData: {
|
|
9
|
+
assetId: bigint;
|
|
10
|
+
medianPrice: bigint;
|
|
11
|
+
}[]): Cell;
|
|
12
|
+
export declare function packPrices(assetsDataCell: Cell, oraclesDataCell: Cell): Cell;
|
|
13
|
+
export declare function createOracleDataProof(oracle: Oracle, data: OraclePricesData, signature: Buffer, assets: Array<bigint>): Slice;
|
|
14
|
+
export declare function packOraclesData(oraclesData: {
|
|
15
|
+
oracle: Oracle;
|
|
16
|
+
data: OraclePricesData;
|
|
17
|
+
signature: Buffer;
|
|
18
|
+
}[], assets: Array<bigint>): Cell;
|
|
19
|
+
export declare function sumDicts(result: Dictionary<bigint, bigint>, addendum: Dictionary<bigint, bigint>): void;
|
|
20
|
+
export declare function generatePriceSources(config?: PriceSourcesConfig, nfts?: OracleNFT[]): PriceSource[];
|
|
21
|
+
export declare function collectAndFilterPrices(priceSource: PriceSource, poolConfig: PoolConfig): Promise<RawPriceData[]>;
|
|
22
|
+
export declare function unpackMedianPrices(pricesCell: Cell): Dictionary<bigint, bigint> | undefined;
|
|
23
|
+
export declare function verifyRawPriceDataSign(priceData: RawPriceData): boolean;
|