@evaafi/sdk 0.5.4 → 0.5.6

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.
Files changed (48) hide show
  1. package/dist/api/helpers.js +2 -3
  2. package/dist/api/math.d.ts +24 -2
  3. package/dist/api/math.js +189 -62
  4. package/dist/api/parser.d.ts +3 -3
  5. package/dist/api/parser.js +37 -25
  6. package/dist/api/prices.d.ts +1 -1
  7. package/dist/api/prices.js +3 -3
  8. package/dist/config.d.ts +2 -0
  9. package/dist/config.js +5 -0
  10. package/dist/constants/assets.d.ts +2 -3
  11. package/dist/constants/assets.js +10 -2
  12. package/dist/constants/general.d.ts +3 -2
  13. package/dist/constants/general.js +6 -5
  14. package/dist/constants/pools.d.ts +0 -1
  15. package/dist/constants/pools.js +1 -14
  16. package/dist/constants.d.ts +5 -34
  17. package/dist/constants.js +90 -37
  18. package/dist/contracts/MasterContract.d.ts +13 -45
  19. package/dist/contracts/MasterContract.js +10 -12
  20. package/dist/contracts/UserContract.js +7 -7
  21. package/dist/index.d.ts +6 -5
  22. package/dist/index.js +5 -3
  23. package/dist/types/Master.d.ts +8 -7
  24. package/dist/types/User.d.ts +5 -5
  25. package/dist/utils/merkleProof.d.ts +4 -0
  26. package/dist/utils/merkleProof.js +107 -0
  27. package/dist/utils/priceUtils.d.ts +55 -0
  28. package/dist/utils/priceUtils.js +117 -0
  29. package/dist/utils/sha256BigInt.js +1 -2
  30. package/dist/utils/tonConnectSender.js +2 -3
  31. package/dist/utils/userJettonWallet.d.ts +2 -2
  32. package/dist/utils/userJettonWallet.js +5 -2
  33. package/dist/utils/utils.d.ts +2 -0
  34. package/dist/utils/utils.js +6 -0
  35. package/package.json +2 -2
  36. package/src/api/math.ts +229 -50
  37. package/src/api/parser.ts +52 -37
  38. package/src/api/prices.ts +2 -1
  39. package/src/constants/assets.ts +11 -3
  40. package/src/constants/general.ts +6 -4
  41. package/src/constants/pools.ts +1 -15
  42. package/src/contracts/MasterContract.ts +25 -67
  43. package/src/contracts/UserContract.ts +8 -10
  44. package/src/index.ts +4 -7
  45. package/src/types/Master.ts +9 -8
  46. package/src/types/User.ts +5 -5
  47. package/src/utils/userJettonWallet.ts +6 -2
  48. package/src/utils/utils.ts +6 -0
@@ -5,16 +5,13 @@ export type MasterConstants = {
5
5
  ASSET_PRICE_SCALE: bigint;
6
6
  ASSET_RESERVE_FACTOR_SCALE: bigint;
7
7
  ASSET_LIQUIDATION_RESERVE_FACTOR_SCALE: bigint;
8
+ ASSET_LIQUIDATION_THRESHOLD_SCALE: bigint;
9
+ ASSET_LIQUIDATION_BONUS_SCALE: bigint;
8
10
  ASSET_ORIGINATION_FEE_SCALE: bigint;
9
11
  };
10
- export type PoolAssetConfig = (PoolTonAssetConfig | PoolJettonAssetConfig) & {
11
- name: string;
12
- };
13
12
  export type PoolAssetsConfig = PoolAssetConfig[];
14
- export type PoolTonAssetConfig = {
15
- assetId: bigint;
16
- };
17
- export type PoolJettonAssetConfig = {
13
+ export type PoolAssetConfig = {
14
+ name: string;
18
15
  assetId: bigint;
19
16
  jettonMasterAddress: Address;
20
17
  jettonWalletCode: Cell;
@@ -94,3 +91,7 @@ export type MasterData = {
94
91
  borrow: Dictionary<bigint, number>;
95
92
  };
96
93
  };
94
+ export type AgregatedBalances = {
95
+ totalBorrow: bigint;
96
+ totalSupply: bigint;
97
+ };
@@ -1,5 +1,5 @@
1
1
  import { Address, Cell, Dictionary } from '@ton/core';
2
- import { ExtendedAssetsConfig, ExtendedAssetsData, MasterConstants } from './Master';
2
+ import { ExtendedAssetsConfig, ExtendedAssetsData, PoolAssetConfig, PoolConfig } from './Master';
3
3
  export declare enum BalanceType {
4
4
  supply = "supply",
5
5
  borrow = "borrow"
@@ -10,9 +10,9 @@ export type UserBalance = {
10
10
  };
11
11
  export type UserLiqudationData = {
12
12
  greatestCollateralValue: bigint;
13
- greatestCollateralAsset: bigint;
13
+ greatestCollateralAsset: PoolAssetConfig;
14
14
  greatestLoanValue: bigint;
15
- greatestLoanAsset: bigint;
15
+ greatestLoanAsset: PoolAssetConfig;
16
16
  totalDebt: bigint;
17
17
  totalLimit: bigint;
18
18
  };
@@ -68,9 +68,9 @@ export type PredictHealthFactorArgs = {
68
68
  balanceChangeType: BalanceChangeType;
69
69
  amount: bigint;
70
70
  tokenSymbol: string;
71
- balances: Dictionary<bigint, bigint>;
71
+ principals: Dictionary<bigint, bigint>;
72
72
  prices: Dictionary<bigint, bigint>;
73
73
  assetsData: ExtendedAssetsData;
74
74
  assetsConfig: ExtendedAssetsConfig;
75
- masterConstants: MasterConstants;
75
+ poolConfig: PoolConfig;
76
76
  };
@@ -0,0 +1,4 @@
1
+ import { Cell, Dictionary, DictionaryKey, DictionaryKeyTypes } from "@ton/core";
2
+ export declare function convertToMerkleProof(c: Cell): Cell;
3
+ export declare function generateMerkleProofDirect<K extends DictionaryKeyTypes, V>(dict: Dictionary<K, V>, keys: K[], keyObject: DictionaryKey<K>): Cell;
4
+ export declare function generateMerkleProof<K extends DictionaryKeyTypes, V>(dict: Dictionary<K, V>, keys: K[], keyObject: DictionaryKey<K>): Cell;
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.convertToMerkleProof = convertToMerkleProof;
4
+ exports.generateMerkleProofDirect = generateMerkleProofDirect;
5
+ exports.generateMerkleProof = generateMerkleProof;
6
+ const core_1 = require("@ton/core");
7
+ function readUnaryLength(slice) {
8
+ let res = 0;
9
+ while (slice.loadBit()) {
10
+ res++;
11
+ }
12
+ return res;
13
+ }
14
+ function endExoticCell(b) {
15
+ let c = b.endCell();
16
+ return new core_1.Cell({ exotic: true, bits: c.bits, refs: c.refs });
17
+ }
18
+ function convertToMerkleProof(c) {
19
+ return endExoticCell((0, core_1.beginCell)()
20
+ .storeUint(3, 8)
21
+ .storeBuffer(c.hash(0))
22
+ .storeUint(c.depth(0), 16)
23
+ .storeRef(c));
24
+ }
25
+ function convertToPrunedBranch(c) {
26
+ return endExoticCell((0, core_1.beginCell)()
27
+ .storeUint(1, 8)
28
+ .storeUint(1, 8)
29
+ .storeBuffer(c.hash(0))
30
+ .storeUint(c.depth(0), 16));
31
+ }
32
+ function doGenerateMerkleProof(prefix, slice, n, keys) {
33
+ // Reading label
34
+ const originalCell = slice.asCell();
35
+ if (keys.length == 0) {
36
+ // no keys to prove, prune the whole subdict
37
+ return convertToPrunedBranch(originalCell);
38
+ }
39
+ let lb0 = slice.loadBit() ? 1 : 0;
40
+ let prefixLength = 0;
41
+ let pp = prefix;
42
+ if (lb0 === 0) {
43
+ // Short label detected
44
+ // Read
45
+ prefixLength = readUnaryLength(slice);
46
+ // Read prefix
47
+ for (let i = 0; i < prefixLength; i++) {
48
+ pp += slice.loadBit() ? '1' : '0';
49
+ }
50
+ }
51
+ else {
52
+ let lb1 = slice.loadBit() ? 1 : 0;
53
+ if (lb1 === 0) {
54
+ // Long label detected
55
+ prefixLength = slice.loadUint(Math.ceil(Math.log2(n + 1)));
56
+ for (let i = 0; i < prefixLength; i++) {
57
+ pp += slice.loadBit() ? '1' : '0';
58
+ }
59
+ }
60
+ else {
61
+ // Same label detected
62
+ let bit = slice.loadBit() ? '1' : '0';
63
+ prefixLength = slice.loadUint(Math.ceil(Math.log2(n + 1)));
64
+ for (let i = 0; i < prefixLength; i++) {
65
+ pp += bit;
66
+ }
67
+ }
68
+ }
69
+ if (n - prefixLength === 0) {
70
+ return originalCell;
71
+ }
72
+ else {
73
+ let sl = originalCell.beginParse();
74
+ let left = sl.loadRef();
75
+ let right = sl.loadRef();
76
+ // NOTE: Left and right branches are implicitly contain prefixes '0' and '1'
77
+ if (!left.isExotic) {
78
+ const leftKeys = keys.filter((key) => {
79
+ return pp + '0' === key.slice(0, pp.length + 1);
80
+ });
81
+ left = doGenerateMerkleProof(pp + '0', left.beginParse(), n - prefixLength - 1, leftKeys);
82
+ }
83
+ if (!right.isExotic) {
84
+ const rightKeys = keys.filter((key) => {
85
+ return pp + '1' === key.slice(0, pp.length + 1);
86
+ });
87
+ right = doGenerateMerkleProof(pp + '1', right.beginParse(), n - prefixLength - 1, rightKeys);
88
+ }
89
+ return (0, core_1.beginCell)()
90
+ .storeSlice(sl)
91
+ .storeRef(left)
92
+ .storeRef(right)
93
+ .endCell();
94
+ }
95
+ }
96
+ function generateMerkleProofDirect(dict, keys, keyObject) {
97
+ keys.forEach((key) => {
98
+ if (!dict.has(key)) {
99
+ throw new Error(`Trying to generate merkle proof for a missing key "${key}"`);
100
+ }
101
+ });
102
+ const s = (0, core_1.beginCell)().storeDictDirect(dict).asSlice();
103
+ return doGenerateMerkleProof('', s, keyObject.bits, keys.map((key) => keyObject.serialize(key).toString(2).padStart(keyObject.bits, '0')));
104
+ }
105
+ function generateMerkleProof(dict, keys, keyObject) {
106
+ return convertToMerkleProof(generateMerkleProofDirect(dict, keys, keyObject));
107
+ }
@@ -0,0 +1,55 @@
1
+ import { Cell, Dictionary, Slice } from "@ton/core";
2
+ import { PriceData, RawPriceData } from "../types/Common";
3
+ import { Oracle, PoolAssetsConfig } from "../types/Master";
4
+ import 'promise.any';
5
+ type OutputData = {
6
+ metadata: {
7
+ blockId: string;
8
+ transactionId: string;
9
+ outputIndex: number;
10
+ isSpent: boolean;
11
+ milestoneIndexSpent: number;
12
+ milestoneTimestampSpent: number;
13
+ transactionIdSpent: string;
14
+ milestoneIndexBooked: number;
15
+ milestoneTimestampBooked: number;
16
+ ledgerIndex: number;
17
+ };
18
+ output: {
19
+ type: number;
20
+ amount: string;
21
+ nftId: string;
22
+ unlockConditions: {
23
+ type: number;
24
+ address: {
25
+ type: number;
26
+ pubKeyHash: string;
27
+ };
28
+ }[];
29
+ features: {
30
+ type: number;
31
+ data: string;
32
+ }[];
33
+ };
34
+ };
35
+ export type OraclePricesData = {
36
+ timestamp: number;
37
+ prices: Dictionary<bigint, bigint>;
38
+ };
39
+ export declare function loadPrices(oracleNftId: String, endpoints: String[], timeout: number): Promise<OutputData>;
40
+ export declare function parsePrices(outputData: OutputData, oracleId: number): Promise<RawPriceData>;
41
+ export declare function verifyPrices(assets: PoolAssetsConfig): (priceData: RawPriceData) => boolean;
42
+ export declare function getMedianPrice(pricesData: PriceData[], asset: bigint): bigint;
43
+ export declare function packAssetsData(assetsData: {
44
+ assetId: bigint;
45
+ medianPrice: bigint;
46
+ }[]): Cell;
47
+ export declare function packPrices(assetsDataCell: Cell, oraclesDataCell: Cell): Cell;
48
+ export declare function createOracleDataProof(oracle: Oracle, data: OraclePricesData, signature: Buffer, assets: Array<bigint>): Slice;
49
+ export declare function packOraclesData(oraclesData: {
50
+ oracle: Oracle;
51
+ data: OraclePricesData;
52
+ signature: Buffer;
53
+ }[], assets: Array<bigint>): Cell;
54
+ export declare function sumDicts(result: Dictionary<bigint, bigint>, addendum: Dictionary<bigint, bigint>): void;
55
+ export {};
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loadPrices = loadPrices;
4
+ exports.parsePrices = parsePrices;
5
+ exports.verifyPrices = verifyPrices;
6
+ exports.getMedianPrice = getMedianPrice;
7
+ exports.packAssetsData = packAssetsData;
8
+ exports.packPrices = packPrices;
9
+ exports.createOracleDataProof = createOracleDataProof;
10
+ exports.packOraclesData = packOraclesData;
11
+ exports.sumDicts = sumDicts;
12
+ const core_1 = require("@ton/core");
13
+ const config_1 = require("../config");
14
+ const merkleProof_1 = require("./merkleProof");
15
+ require("promise.any");
16
+ async function loadPrices(oracleNftId, endpoints, timeout) {
17
+ return await Promise.any(endpoints.map(x => loadOracleData(oracleNftId, x, timeout)));
18
+ }
19
+ async function loadOracleData(oracleNftId, endpoint, timeout) {
20
+ let result = await fetch(`https://${endpoint}/api/indexer/v1/outputs/nft/${oracleNftId}`, {
21
+ headers: { accept: 'application/json' },
22
+ signal: AbortSignal.timeout(timeout)
23
+ });
24
+ let outputId = (await result.json());
25
+ result = await fetch(`https://${endpoint}/api/core/v2/outputs/${outputId.items[0]}`, {
26
+ headers: { accept: 'application/json' },
27
+ signal: AbortSignal.timeout(timeout)
28
+ });
29
+ return await result.json();
30
+ }
31
+ async function parsePrices(outputData, oracleId) {
32
+ const data = JSON.parse(decodeURIComponent(outputData.output.features[0].data.replace('0x', '').replace(/[0-9a-f]{2}/g, '%$&')));
33
+ try {
34
+ const pricesCell = core_1.Cell.fromBoc(Buffer.from(data['packedPrices'], 'hex'))[0];
35
+ const signature = Buffer.from(data['signature'], 'hex');
36
+ const publicKey = Buffer.from(data['publicKey'], 'hex');
37
+ const timestamp = Number(data['timestamp']);
38
+ return {
39
+ dict: pricesCell.beginParse().loadRef().beginParse().loadDictDirect(core_1.Dictionary.Keys.BigUint(256), core_1.Dictionary.Values.BigVarUint(4)),
40
+ dataCell: (0, core_1.beginCell)().storeRef(pricesCell).storeBuffer(signature).endCell(),
41
+ oracleId: oracleId,
42
+ signature: signature,
43
+ pubkey: publicKey,
44
+ timestamp: timestamp,
45
+ };
46
+ }
47
+ catch (error) {
48
+ console.log(oracleId, data, error);
49
+ throw Error();
50
+ }
51
+ }
52
+ function verifyPrices(assets) {
53
+ return function (priceData) {
54
+ const timestamp = Date.now() / 1000;
55
+ const pricesTime = priceData.timestamp;
56
+ for (const [key, asset] of Object.entries(assets)) {
57
+ if (!priceData.dict.has(asset.assetId)) {
58
+ return false;
59
+ }
60
+ }
61
+ // console.log('timestamp', timestamp, 'pricestime', pricesTime, timestamp - pricesTime);
62
+ return timestamp - pricesTime < config_1.TTL_ORACLE_DATA_SEC;
63
+ };
64
+ }
65
+ function getMedianPrice(pricesData, asset) {
66
+ const sorted = pricesData.map(x => x.dict.get(asset)).sort((a, b) => Number(a) - Number(b));
67
+ const mid = Math.floor(sorted.length / 2);
68
+ if (sorted.length % 2 === 0) {
69
+ return (sorted[mid - 1] + sorted[mid]) / 2n;
70
+ }
71
+ else {
72
+ return sorted[mid];
73
+ }
74
+ }
75
+ function packAssetsData(assetsData) {
76
+ if (assetsData.length == 0) {
77
+ throw new Error("No assets data to pack");
78
+ }
79
+ return assetsData.reduceRight((acc, { assetId, medianPrice }) => (0, core_1.beginCell)()
80
+ .storeUint(assetId, 256)
81
+ .storeCoins(medianPrice)
82
+ .storeMaybeRef(acc)
83
+ .endCell(), null);
84
+ }
85
+ function packPrices(assetsDataCell, oraclesDataCell) {
86
+ let pricesCell = (0, core_1.beginCell)()
87
+ .storeRef(assetsDataCell)
88
+ .storeRef(oraclesDataCell)
89
+ .endCell();
90
+ return pricesCell;
91
+ }
92
+ function createOracleDataProof(oracle, data, signature, assets) {
93
+ let prunedDict = (0, merkleProof_1.generateMerkleProofDirect)(data.prices, assets, core_1.Dictionary.Keys.BigUint(256));
94
+ let prunedData = (0, core_1.beginCell)().storeUint(data.timestamp, 32).storeMaybeRef(prunedDict).endCell();
95
+ let merkleProof = (0, merkleProof_1.convertToMerkleProof)(prunedData);
96
+ let oracleDataProof = (0, core_1.beginCell)().storeUint(oracle.id, 32).storeRef(merkleProof).storeBuffer(signature).asSlice();
97
+ return oracleDataProof;
98
+ }
99
+ function packOraclesData(oraclesData, assets) {
100
+ if (oraclesData.length == 0) {
101
+ throw new Error("no oracles data to pack");
102
+ }
103
+ let proofs = oraclesData.sort((d1, d2) => d1.oracle.id - d2.oracle.id).map(({ oracle, data, signature }) => createOracleDataProof(oracle, data, signature, assets));
104
+ return proofs.reduceRight((acc, val) => (0, core_1.beginCell)().storeSlice(val).storeMaybeRef(acc).endCell(), null);
105
+ }
106
+ // : String = "api.stardust-mainnet.iotaledger.net"
107
+ function sumDicts(result, addendum) {
108
+ for (const key of addendum.keys()) {
109
+ const current = result.get(key);
110
+ const value = addendum.get(key);
111
+ if (current === undefined) {
112
+ result.set(key, value);
113
+ continue;
114
+ }
115
+ result.set(key, current + value);
116
+ }
117
+ }
@@ -3,11 +3,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.sha256Hash = void 0;
6
+ exports.sha256Hash = sha256Hash;
7
7
  const sha256_1 = __importDefault(require("crypto-js/sha256"));
8
8
  function sha256Hash(input) {
9
9
  const hash = (0, sha256_1.default)(input);
10
10
  const hashHex = hash.toString();
11
11
  return BigInt('0x' + hashHex);
12
12
  }
13
- exports.sha256Hash = sha256Hash;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getTonConnectSender = exports.getLastSentBoc = void 0;
3
+ exports.getLastSentBoc = getLastSentBoc;
4
+ exports.getTonConnectSender = getTonConnectSender;
4
5
  const core_1 = require("@ton/core");
5
6
  /*
6
7
  This is not the best solution to get the BOC of the sent external message, however the Sender
@@ -11,7 +12,6 @@ let lastSentBoc;
11
12
  function getLastSentBoc() {
12
13
  return lastSentBoc;
13
14
  }
14
- exports.getLastSentBoc = getLastSentBoc;
15
15
  function getTonConnectSender(connector) {
16
16
  return {
17
17
  get address() {
@@ -34,4 +34,3 @@ function getTonConnectSender(connector) {
34
34
  },
35
35
  };
36
36
  }
37
- exports.getTonConnectSender = getTonConnectSender;
@@ -1,3 +1,3 @@
1
1
  import { Address } from '@ton/core';
2
- import { PoolAssetConfig, PoolJettonAssetConfig } from '../types/Master';
3
- export declare function getUserJettonWallet(ownerAddress: Address, poolAssetConfig: PoolAssetConfig & PoolJettonAssetConfig): Address;
2
+ import { PoolAssetConfig } from '../types/Master';
3
+ export declare function getUserJettonWallet(ownerAddress: Address, poolAssetConfig: PoolAssetConfig): Address;
@@ -1,8 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getUserJettonWallet = void 0;
3
+ exports.getUserJettonWallet = getUserJettonWallet;
4
4
  const core_1 = require("@ton/core");
5
+ const assets_1 = require("../constants/assets");
5
6
  function getUserJettonWallet(ownerAddress, poolAssetConfig) {
7
+ if (poolAssetConfig.name == 'TON' || poolAssetConfig.assetId === assets_1.UNDEFINED_ASSET.assetId) {
8
+ throw new Error(`Cant getUserJettonWallet for ${poolAssetConfig.name} asset`);
9
+ }
6
10
  const jettonMasterAddress = poolAssetConfig.jettonMasterAddress;
7
11
  const jettonWalletCode = poolAssetConfig.jettonWalletCode;
8
12
  if (poolAssetConfig.name === 'USDT') {
@@ -55,4 +59,3 @@ function getUserJettonWallet(ownerAddress, poolAssetConfig) {
55
59
  .endCell();
56
60
  return new core_1.Address(0, stateInit.hash());
57
61
  }
58
- exports.getUserJettonWallet = getUserJettonWallet;
@@ -0,0 +1,2 @@
1
+ import { PoolAssetConfig } from "../types/Master";
2
+ export declare function isTonAsset(asset: PoolAssetConfig): boolean;
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isTonAsset = isTonAsset;
4
+ function isTonAsset(asset) {
5
+ return asset.name === 'TON';
6
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evaafi/sdk",
3
- "version": "0.5.4",
3
+ "version": "0.5.6",
4
4
  "description": "SDK for EVAA contracts",
5
5
  "main": "dist/index.js",
6
6
  "files": [
@@ -20,7 +20,7 @@
20
20
  "devDependencies": {
21
21
  "@orbs-network/ton-access": "^2.3.3",
22
22
  "@ton/core": "0.56.0",
23
- "@tonconnect/sdk": "^3.0.0",
23
+ "@tonconnect/sdk": "^3.0.5",
24
24
  "@types/jest": "^29.5.12",
25
25
  "@types/node": "^20.10.4",
26
26
  "crypto-js": "^4.2.0",