@evaafi/sdk 0.2.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/README.md +7 -0
- package/dist/api/helpers.d.ts +8 -0
- package/dist/api/helpers.js +33 -0
- package/dist/api/math.d.ts +20 -0
- package/dist/api/math.js +214 -0
- package/dist/api/parser.d.ts +8 -0
- package/dist/api/parser.js +227 -0
- package/dist/api/prices.d.ts +9 -0
- package/dist/api/prices.js +104 -0
- package/dist/constants.d.ts +38 -0
- package/dist/constants.js +42 -0
- package/dist/contracts/JettonWallet.d.ts +7 -0
- package/dist/contracts/JettonWallet.js +20 -0
- package/dist/contracts/MasterContract.d.ts +166 -0
- package/dist/contracts/MasterContract.js +217 -0
- package/dist/contracts/UserContract.d.ts +49 -0
- package/dist/contracts/UserContract.js +99 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +53 -0
- package/dist/types/Common.d.ts +5 -0
- package/dist/types/Common.js +2 -0
- package/dist/types/Master.d.ts +63 -0
- package/dist/types/Master.js +2 -0
- package/dist/types/Redstone.d.ts +15 -0
- package/dist/types/Redstone.js +2 -0
- package/dist/types/User.d.ts +55 -0
- package/dist/types/User.js +8 -0
- package/dist/utils/sha256BigInt.d.ts +1 -0
- package/dist/utils/sha256BigInt.js +13 -0
- package/dist/utils/tonConnectSender.d.ts +4 -0
- package/dist/utils/tonConnectSender.js +37 -0
- package/dist/utils/userJettonWallet.d.ts +2 -0
- package/dist/utils/userJettonWallet.js +37 -0
- package/package.json +38 -0
- package/src/api/helpers.ts +32 -0
- package/src/api/math.ts +252 -0
- package/src/api/parser.ts +277 -0
- package/src/api/prices.ts +127 -0
- package/src/constants.ts +53 -0
- package/src/contracts/JettonWallet.ts +20 -0
- package/src/contracts/MasterContract.ts +387 -0
- package/src/contracts/UserContract.ts +125 -0
- package/src/index.ts +78 -0
- package/src/types/Common.ts +6 -0
- package/src/types/Master.ts +70 -0
- package/src/types/Redstone.ts +15 -0
- package/src/types/User.ts +66 -0
- package/src/utils/sha256BigInt.ts +7 -0
- package/src/utils/tonConnectSender.ts +37 -0
- package/src/utils/userJettonWallet.ts +34 -0
package/README.md
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Cell, Slice } from '@ton/core';
|
|
2
|
+
declare class MyCell extends Cell {
|
|
3
|
+
toString(): string;
|
|
4
|
+
hashBigInt(): bigint;
|
|
5
|
+
}
|
|
6
|
+
export declare function loadMyRef(slice: Slice): MyCell;
|
|
7
|
+
export declare function loadMaybeMyRef(slice: Slice): Cell | null;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.loadMaybeMyRef = exports.loadMyRef = void 0;
|
|
4
|
+
const core_1 = require("@ton/core");
|
|
5
|
+
class MyCell extends core_1.Cell {
|
|
6
|
+
toString() {
|
|
7
|
+
return this.hashBigInt().toString();
|
|
8
|
+
}
|
|
9
|
+
hashBigInt() {
|
|
10
|
+
return BigInt('0x' + this.hash().toString('hex'));
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function loadMyRef(slice) {
|
|
14
|
+
const cell = slice.loadRef();
|
|
15
|
+
return new MyCell({
|
|
16
|
+
exotic: cell.isExotic,
|
|
17
|
+
bits: cell.bits,
|
|
18
|
+
refs: cell.refs,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
exports.loadMyRef = loadMyRef;
|
|
22
|
+
function loadMaybeMyRef(slice) {
|
|
23
|
+
const cell = slice.loadMaybeRef();
|
|
24
|
+
if (cell === null) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
return new MyCell({
|
|
28
|
+
exotic: cell.isExotic,
|
|
29
|
+
bits: cell.bits,
|
|
30
|
+
refs: cell.refs,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
exports.loadMaybeMyRef = loadMaybeMyRef;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { AssetConfig, AssetData, AssetInterest, ExtendedAssetData } from '../types/Master';
|
|
2
|
+
import { Dictionary } from '@ton/core';
|
|
3
|
+
import { LiquidationData, UserBalance } from '../types/User';
|
|
4
|
+
export declare function mulFactor(decimal: bigint, a: bigint, b: bigint): bigint;
|
|
5
|
+
export declare function mulDiv(x: bigint, y: bigint, z: bigint): bigint;
|
|
6
|
+
export declare function bigIntMax(...args: bigint[]): bigint;
|
|
7
|
+
export declare function bigIntMin(...args: bigint[]): bigint;
|
|
8
|
+
export declare function calculatePresentValue(index: bigint, principalValue: bigint): bigint;
|
|
9
|
+
export declare function calculateCurrentRates(assetConfig: AssetConfig, assetData: AssetData): {
|
|
10
|
+
sRate: bigint;
|
|
11
|
+
bRate: bigint;
|
|
12
|
+
supplyInterest: bigint;
|
|
13
|
+
borrowInterest: bigint;
|
|
14
|
+
now: bigint;
|
|
15
|
+
};
|
|
16
|
+
export declare function calculateAssetData(assetsConfigDict: Dictionary<bigint, AssetConfig>, assetsDataDict: Dictionary<bigint, AssetData>, assetId: bigint): ExtendedAssetData;
|
|
17
|
+
export declare function calculateAssetInterest(assetConfig: AssetConfig, assetData: AssetData): AssetInterest;
|
|
18
|
+
export declare function getAvailableToBorrow(assetsConfig: Dictionary<bigint, AssetConfig>, assetsData: Dictionary<bigint, ExtendedAssetData>, principals: Dictionary<bigint, bigint>, prices: Dictionary<bigint, bigint>): bigint;
|
|
19
|
+
export declare function presentValue(sRate: bigint, bRate: bigint, principalValue: bigint): UserBalance;
|
|
20
|
+
export declare function calculateLiquidationData(assetsConfig: Dictionary<bigint, AssetConfig>, assetsData: Dictionary<bigint, ExtendedAssetData>, principals: Dictionary<bigint, bigint>, prices: Dictionary<bigint, bigint>): LiquidationData;
|
package/dist/api/math.js
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.calculateLiquidationData = exports.presentValue = exports.getAvailableToBorrow = exports.calculateAssetInterest = exports.calculateAssetData = exports.calculateCurrentRates = exports.calculatePresentValue = exports.bigIntMin = exports.bigIntMax = exports.mulDiv = exports.mulFactor = void 0;
|
|
4
|
+
const constants_1 = require("../constants");
|
|
5
|
+
const User_1 = require("../types/User");
|
|
6
|
+
function mulFactor(decimal, a, b) {
|
|
7
|
+
return (a * b) / decimal;
|
|
8
|
+
}
|
|
9
|
+
exports.mulFactor = mulFactor;
|
|
10
|
+
function mulDiv(x, y, z) {
|
|
11
|
+
return (x * y) / z;
|
|
12
|
+
}
|
|
13
|
+
exports.mulDiv = mulDiv;
|
|
14
|
+
function bigIntMax(...args) {
|
|
15
|
+
return args.reduce((m, e) => (e > m ? e : m));
|
|
16
|
+
}
|
|
17
|
+
exports.bigIntMax = bigIntMax;
|
|
18
|
+
function bigIntMin(...args) {
|
|
19
|
+
return args.reduce((m, e) => (e < m ? e : m));
|
|
20
|
+
}
|
|
21
|
+
exports.bigIntMin = bigIntMin;
|
|
22
|
+
function calculatePresentValue(index, principalValue) {
|
|
23
|
+
return (principalValue * index) / constants_1.MASTER_CONSTANTS.FACTOR_SCALE;
|
|
24
|
+
}
|
|
25
|
+
exports.calculatePresentValue = calculatePresentValue;
|
|
26
|
+
function calculateCurrentRates(assetConfig, assetData) {
|
|
27
|
+
const now = BigInt(Math.floor(Date.now() / 1000));
|
|
28
|
+
const timeElapsed = now - assetData.lastAccural;
|
|
29
|
+
const { supplyInterest, borrowInterest } = calculateAssetInterest(assetConfig, assetData);
|
|
30
|
+
if (timeElapsed > 0) {
|
|
31
|
+
const updatedSRate = assetData.sRate + mulFactor(constants_1.MASTER_CONSTANTS.FACTOR_SCALE, assetData.sRate, supplyInterest * timeElapsed);
|
|
32
|
+
const updatedBRate = assetData.bRate + mulFactor(constants_1.MASTER_CONSTANTS.FACTOR_SCALE, assetData.bRate, borrowInterest * timeElapsed);
|
|
33
|
+
return {
|
|
34
|
+
sRate: updatedSRate,
|
|
35
|
+
bRate: updatedBRate,
|
|
36
|
+
supplyInterest,
|
|
37
|
+
borrowInterest,
|
|
38
|
+
now,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
sRate: assetData.sRate,
|
|
43
|
+
bRate: assetData.bRate,
|
|
44
|
+
supplyInterest,
|
|
45
|
+
borrowInterest,
|
|
46
|
+
now,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
exports.calculateCurrentRates = calculateCurrentRates;
|
|
50
|
+
function calculateAssetData(assetsConfigDict, assetsDataDict, assetId) {
|
|
51
|
+
const config = assetsConfigDict.get(assetId); // maybe it's a huge mistake could be
|
|
52
|
+
const data = assetsDataDict.get(assetId);
|
|
53
|
+
if (!data || !config) {
|
|
54
|
+
throw new Error('Asset Data or Config is not accessible');
|
|
55
|
+
}
|
|
56
|
+
const { sRate, bRate, supplyInterest, borrowInterest, now } = calculateCurrentRates(config, data);
|
|
57
|
+
data.sRate = sRate || 0n;
|
|
58
|
+
data.bRate = bRate || 0n;
|
|
59
|
+
data.lastAccural = now;
|
|
60
|
+
const supplyApy = (1 + (Number(supplyInterest) / 1e12) * 24 * 3600) ** 365 - 1;
|
|
61
|
+
const borrowApy = (1 + (Number(borrowInterest) / 1e12) * 24 * 3600) ** 365 - 1;
|
|
62
|
+
return {
|
|
63
|
+
...data,
|
|
64
|
+
...{ supplyInterest, borrowInterest },
|
|
65
|
+
...{ supplyApy, borrowApy },
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
exports.calculateAssetData = calculateAssetData;
|
|
69
|
+
function calculateAssetInterest(assetConfig, assetData) {
|
|
70
|
+
const totalSupply = calculatePresentValue(assetData.sRate, assetData.totalSupply);
|
|
71
|
+
const totalBorrow = calculatePresentValue(assetData.bRate, assetData.totalBorrow);
|
|
72
|
+
let utilization = 0n;
|
|
73
|
+
let supplyInterest = 0n;
|
|
74
|
+
let borrowInterest = 0n;
|
|
75
|
+
if (totalSupply !== 0n) {
|
|
76
|
+
utilization = (totalBorrow * constants_1.MASTER_CONSTANTS.FACTOR_SCALE) / totalSupply;
|
|
77
|
+
}
|
|
78
|
+
if (utilization <= assetConfig.targetUtilization) {
|
|
79
|
+
borrowInterest =
|
|
80
|
+
assetConfig.baseBorrowRate +
|
|
81
|
+
mulFactor(constants_1.MASTER_CONSTANTS.FACTOR_SCALE, assetConfig.borrowRateSlopeLow, utilization);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
borrowInterest =
|
|
85
|
+
assetConfig.baseBorrowRate +
|
|
86
|
+
mulFactor(constants_1.MASTER_CONSTANTS.FACTOR_SCALE, assetConfig.borrowRateSlopeLow, assetConfig.targetUtilization) +
|
|
87
|
+
mulFactor(constants_1.MASTER_CONSTANTS.FACTOR_SCALE, assetConfig.borrowRateSlopeHigh, utilization - assetConfig.targetUtilization);
|
|
88
|
+
}
|
|
89
|
+
const reserveFactor = 10n;
|
|
90
|
+
const reserveScale = 100n;
|
|
91
|
+
supplyInterest = mulDiv(mulDiv(borrowInterest, utilization, constants_1.MASTER_CONSTANTS.FACTOR_SCALE), reserveScale - reserveFactor, reserveScale);
|
|
92
|
+
return {
|
|
93
|
+
supplyInterest,
|
|
94
|
+
borrowInterest,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
exports.calculateAssetInterest = calculateAssetInterest;
|
|
98
|
+
function getAvailableToBorrow(assetsConfig, assetsData, principals, prices) {
|
|
99
|
+
let borrowLimit = 0n;
|
|
100
|
+
let borrowAmount = 0n;
|
|
101
|
+
for (const assetID of principals.keys()) {
|
|
102
|
+
const assetConfig = assetsConfig.get(assetID);
|
|
103
|
+
const assetData = assetsData.get(assetID);
|
|
104
|
+
const price = prices.get(assetID);
|
|
105
|
+
const principal = principals.get(assetID);
|
|
106
|
+
if (principal < 0) {
|
|
107
|
+
borrowAmount += (calculatePresentValue(assetData.bRate, -principal) * price) / 10n ** assetConfig.decimals;
|
|
108
|
+
}
|
|
109
|
+
else if (principal > 0) {
|
|
110
|
+
borrowLimit +=
|
|
111
|
+
(calculatePresentValue(assetData.sRate, principal) * price * assetConfig.collateralFactor) /
|
|
112
|
+
10n ** assetConfig.decimals /
|
|
113
|
+
constants_1.MASTER_CONSTANTS.ASSET_COEFFICIENT_SCALE;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return borrowLimit - borrowAmount;
|
|
117
|
+
}
|
|
118
|
+
exports.getAvailableToBorrow = getAvailableToBorrow;
|
|
119
|
+
function presentValue(sRate, bRate, principalValue) {
|
|
120
|
+
if (principalValue > 0) {
|
|
121
|
+
return {
|
|
122
|
+
amount: calculatePresentValue(sRate, principalValue),
|
|
123
|
+
type: User_1.BalanceType.supply,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
else if (principalValue < 0) {
|
|
127
|
+
return {
|
|
128
|
+
amount: calculatePresentValue(bRate, -principalValue),
|
|
129
|
+
type: User_1.BalanceType.borrow,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
return {
|
|
134
|
+
amount: 0n,
|
|
135
|
+
type: undefined,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
exports.presentValue = presentValue;
|
|
140
|
+
function calculateLiquidationData(assetsConfig, assetsData, principals, prices) {
|
|
141
|
+
let gCollateralValue = 0n;
|
|
142
|
+
let gCollateralAsset = 0n;
|
|
143
|
+
let gLoanValue = 0n;
|
|
144
|
+
let gLoanAsset = 0n;
|
|
145
|
+
let totalDebt = 0n;
|
|
146
|
+
let totalLimit = 0n;
|
|
147
|
+
for (const key of principals.keys()) {
|
|
148
|
+
const principal = principals.get(key);
|
|
149
|
+
const assetConfig = assetsConfig.get(key);
|
|
150
|
+
const assetData = assetsData.get(key);
|
|
151
|
+
const balance = principal > 0 ? (principal * assetData.sRate) / BigInt(1e12) : (principal * assetData.bRate) / BigInt(1e12);
|
|
152
|
+
if (balance > 0) {
|
|
153
|
+
const assetWorth = (balance * prices.get(key)) / 10n ** assetConfig.decimals;
|
|
154
|
+
totalLimit += (assetWorth * assetConfig.liquidationThreshold) / constants_1.MASTER_CONSTANTS.ASSET_COEFFICIENT_SCALE;
|
|
155
|
+
if (assetWorth > gCollateralValue) {
|
|
156
|
+
gCollateralValue = assetWorth;
|
|
157
|
+
gCollateralAsset = key;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
else if (balance < 0) {
|
|
161
|
+
const assetWorth = (-balance * prices.get(key)) / 10n ** assetConfig.decimals;
|
|
162
|
+
totalDebt += assetWorth;
|
|
163
|
+
if (assetWorth > gLoanValue) {
|
|
164
|
+
gLoanValue = assetWorth;
|
|
165
|
+
gLoanAsset = key;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
if (totalLimit < totalDebt) {
|
|
170
|
+
const gLoanAssetPrice = prices.get(gLoanAsset);
|
|
171
|
+
const values = [];
|
|
172
|
+
const gCollateralAssetConfig = assetsConfig.get(gCollateralAsset);
|
|
173
|
+
const gLoanAssetConfig = assetsConfig.get(gLoanAsset);
|
|
174
|
+
const liquidationBonus = gLoanAssetConfig.liquidationBonus;
|
|
175
|
+
const loanDecimal = 10n ** gLoanAssetConfig.decimals;
|
|
176
|
+
values.push((bigIntMax(gCollateralValue / 2n, bigIntMin(gCollateralValue, 10000000000n)) *
|
|
177
|
+
loanDecimal *
|
|
178
|
+
constants_1.MASTER_CONSTANTS.ASSET_COEFFICIENT_SCALE) /
|
|
179
|
+
liquidationBonus /
|
|
180
|
+
gLoanAssetPrice);
|
|
181
|
+
values.push((gLoanValue * loanDecimal) / gLoanAssetPrice);
|
|
182
|
+
const liquidationAmount = bigIntMin(...values) - 5n;
|
|
183
|
+
const gCollateralAssetPrice = prices.get(gCollateralAsset);
|
|
184
|
+
const collateralDecimal = 10n ** gCollateralAssetConfig.decimals;
|
|
185
|
+
let minCollateralAmount = (((liquidationAmount * gLoanAssetPrice * liquidationBonus) / 10000n) * collateralDecimal) /
|
|
186
|
+
gCollateralAssetPrice /
|
|
187
|
+
loanDecimal -
|
|
188
|
+
10n;
|
|
189
|
+
minCollateralAmount = (minCollateralAmount * 97n) / 100n;
|
|
190
|
+
if (minCollateralAmount / collateralDecimal >= 1n) {
|
|
191
|
+
return {
|
|
192
|
+
greatestCollateralAsset: gCollateralAsset,
|
|
193
|
+
greatestCollateralValue: gCollateralValue,
|
|
194
|
+
greatestLoanAsset: gLoanAsset,
|
|
195
|
+
greatestLoanValue: gLoanValue,
|
|
196
|
+
totalDebt,
|
|
197
|
+
totalLimit,
|
|
198
|
+
liquidable: true,
|
|
199
|
+
liquidationAmount,
|
|
200
|
+
minCollateralAmount,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return {
|
|
205
|
+
greatestCollateralAsset: gCollateralAsset,
|
|
206
|
+
greatestCollateralValue: gCollateralValue,
|
|
207
|
+
greatestLoanAsset: gLoanAsset,
|
|
208
|
+
greatestLoanValue: gLoanValue,
|
|
209
|
+
totalDebt,
|
|
210
|
+
totalLimit,
|
|
211
|
+
liquidable: false,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
exports.calculateLiquidationData = calculateLiquidationData;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Dictionary, DictionaryValue } from '@ton/core';
|
|
2
|
+
import { AssetConfig, AssetData, ExtendedAssetData, MasterData } from '../types/Master';
|
|
3
|
+
import { UserData, UserLiteData } from '../types/User';
|
|
4
|
+
export declare function createAssetData(): DictionaryValue<AssetData>;
|
|
5
|
+
export declare function createAssetConfig(): DictionaryValue<AssetConfig>;
|
|
6
|
+
export declare function parseMasterData(masterDataBOC: string): MasterData;
|
|
7
|
+
export declare function parseUserLiteData(userDataBOC: string, assetsData: Dictionary<bigint, ExtendedAssetData>, assetsConfig: Dictionary<bigint, AssetConfig>): UserLiteData;
|
|
8
|
+
export declare function parseUserData(userLiteData: UserLiteData, assetsData: Dictionary<bigint, ExtendedAssetData>, assetsConfig: Dictionary<bigint, AssetConfig>, prices: Dictionary<bigint, bigint>): UserData;
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseUserData = exports.parseUserLiteData = exports.parseMasterData = exports.createAssetConfig = exports.createAssetData = void 0;
|
|
4
|
+
const core_1 = require("@ton/core");
|
|
5
|
+
const constants_1 = require("../constants");
|
|
6
|
+
const math_1 = require("./math");
|
|
7
|
+
const helpers_1 = require("./helpers");
|
|
8
|
+
const User_1 = require("../types/User");
|
|
9
|
+
function createAssetData() {
|
|
10
|
+
return {
|
|
11
|
+
serialize: (src, buidler) => {
|
|
12
|
+
buidler.storeUint(src.s_rate, 64);
|
|
13
|
+
buidler.storeUint(src.b_rate, 64);
|
|
14
|
+
buidler.storeUint(src.totalSupply, 64);
|
|
15
|
+
buidler.storeUint(src.totalBorrow, 64);
|
|
16
|
+
buidler.storeUint(src.lastAccural, 32);
|
|
17
|
+
buidler.storeUint(src.balance, 64);
|
|
18
|
+
},
|
|
19
|
+
parse: (src) => {
|
|
20
|
+
const sRate = BigInt(src.loadInt(64));
|
|
21
|
+
const bRate = BigInt(src.loadInt(64));
|
|
22
|
+
const totalSupply = BigInt(src.loadInt(64));
|
|
23
|
+
const totalBorrow = BigInt(src.loadInt(64));
|
|
24
|
+
const lastAccural = BigInt(src.loadInt(32));
|
|
25
|
+
const balance = BigInt(src.loadInt(64));
|
|
26
|
+
return { sRate, bRate, totalSupply, totalBorrow, lastAccural, balance };
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
exports.createAssetData = createAssetData;
|
|
31
|
+
function createAssetConfig() {
|
|
32
|
+
return {
|
|
33
|
+
serialize: (src, builder) => {
|
|
34
|
+
builder.storeUint(src.oracle, 256);
|
|
35
|
+
builder.storeUint(src.decimals, 8);
|
|
36
|
+
const refBuild = (0, core_1.beginCell)();
|
|
37
|
+
refBuild.storeUint(src.collateralFactor, 16);
|
|
38
|
+
refBuild.storeUint(src.liquidationThreshold, 16);
|
|
39
|
+
refBuild.storeUint(src.liquidationPenalty, 16);
|
|
40
|
+
refBuild.storeUint(src.baseBorrowRate, 64);
|
|
41
|
+
refBuild.storeUint(src.borrowRateSlopeLow, 64);
|
|
42
|
+
refBuild.storeUint(src.borrowRateSlopeHigh, 64);
|
|
43
|
+
refBuild.storeUint(src.supplyRateSlopeLow, 64);
|
|
44
|
+
refBuild.storeUint(src.supplyRateSlopeHigh, 64);
|
|
45
|
+
refBuild.storeUint(src.targetUtilization, 64);
|
|
46
|
+
refBuild.storeUint(src.originationFee, 64);
|
|
47
|
+
builder.storeRef(refBuild.endCell());
|
|
48
|
+
},
|
|
49
|
+
parse: (src) => {
|
|
50
|
+
const oracle = src.loadUintBig(256);
|
|
51
|
+
const decimals = BigInt(src.loadUint(8));
|
|
52
|
+
const ref = src.loadRef().beginParse();
|
|
53
|
+
const collateralFactor = BigInt(ref.loadUint(16));
|
|
54
|
+
const liquidationThreshold = BigInt(ref.loadUint(16));
|
|
55
|
+
const liquidationBonus = BigInt(ref.loadUint(16));
|
|
56
|
+
const baseBorrowRate = BigInt(ref.loadUint(64));
|
|
57
|
+
const borrowRateSlopeLow = BigInt(ref.loadUint(64));
|
|
58
|
+
const borrowRateSlopeHigh = BigInt(ref.loadUint(64));
|
|
59
|
+
const supplyRateSlopeLow = BigInt(ref.loadUint(64));
|
|
60
|
+
const supplyRateSlopeHigh = BigInt(ref.loadUint(64));
|
|
61
|
+
const targetUtilization = BigInt(ref.loadUint(64));
|
|
62
|
+
const originationFee = BigInt(ref.loadUint(64));
|
|
63
|
+
return {
|
|
64
|
+
oracle,
|
|
65
|
+
decimals,
|
|
66
|
+
collateralFactor,
|
|
67
|
+
liquidationThreshold,
|
|
68
|
+
liquidationBonus,
|
|
69
|
+
baseBorrowRate,
|
|
70
|
+
borrowRateSlopeLow,
|
|
71
|
+
borrowRateSlopeHigh,
|
|
72
|
+
supplyRateSlopeLow,
|
|
73
|
+
supplyRateSlopeHigh,
|
|
74
|
+
targetUtilization,
|
|
75
|
+
originationFee,
|
|
76
|
+
};
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
exports.createAssetConfig = createAssetConfig;
|
|
81
|
+
function parseMasterData(masterDataBOC) {
|
|
82
|
+
const masterSlice = core_1.Cell.fromBase64(masterDataBOC).beginParse();
|
|
83
|
+
const meta = masterSlice.loadRef().beginParse().loadStringTail();
|
|
84
|
+
const upgradeConfigParser = masterSlice.loadRef().beginParse();
|
|
85
|
+
const upgradeConfig = {
|
|
86
|
+
masterCodeVersion: Number(upgradeConfigParser.loadCoins()),
|
|
87
|
+
userCodeVersion: Number(upgradeConfigParser.loadCoins()),
|
|
88
|
+
timeout: upgradeConfigParser.loadUint(32),
|
|
89
|
+
updateTime: upgradeConfigParser.loadUint(64),
|
|
90
|
+
freezeTime: upgradeConfigParser.loadUint(64),
|
|
91
|
+
userCode: (0, helpers_1.loadMyRef)(upgradeConfigParser),
|
|
92
|
+
blankCode: (0, helpers_1.loadMyRef)(upgradeConfigParser),
|
|
93
|
+
newMasterCode: (0, helpers_1.loadMaybeMyRef)(upgradeConfigParser),
|
|
94
|
+
newUserCode: (0, helpers_1.loadMaybeMyRef)(upgradeConfigParser),
|
|
95
|
+
};
|
|
96
|
+
upgradeConfigParser.endParse();
|
|
97
|
+
const masterConfigSlice = masterSlice.loadRef().beginParse();
|
|
98
|
+
const assetsConfigDict = masterConfigSlice.loadDict(core_1.Dictionary.Keys.BigUint(256), createAssetConfig());
|
|
99
|
+
const assetsDataDict = masterSlice.loadDict(core_1.Dictionary.Keys.BigUint(256), createAssetData());
|
|
100
|
+
const assetsExtendedData = core_1.Dictionary.empty();
|
|
101
|
+
const assetsReserves = core_1.Dictionary.empty();
|
|
102
|
+
const apy = {
|
|
103
|
+
supply: core_1.Dictionary.empty(),
|
|
104
|
+
borrow: core_1.Dictionary.empty(),
|
|
105
|
+
};
|
|
106
|
+
for (const [tokenSymbol, assetID] of Object.entries(constants_1.ASSET_ID)) {
|
|
107
|
+
const assetData = (0, math_1.calculateAssetData)(assetsConfigDict, assetsDataDict, assetID);
|
|
108
|
+
assetsExtendedData.set(assetID, assetData);
|
|
109
|
+
}
|
|
110
|
+
const masterConfig = {
|
|
111
|
+
ifActive: masterConfigSlice.loadInt(8),
|
|
112
|
+
admin: masterConfigSlice.loadAddress(),
|
|
113
|
+
adminPK: masterConfigSlice.loadBuffer(64),
|
|
114
|
+
tokenKeys: (0, helpers_1.loadMaybeMyRef)(masterConfigSlice),
|
|
115
|
+
walletToMaster: (0, helpers_1.loadMaybeMyRef)(masterConfigSlice),
|
|
116
|
+
};
|
|
117
|
+
masterConfigSlice.endParse();
|
|
118
|
+
for (const [_, assetID] of Object.entries(constants_1.ASSET_ID)) {
|
|
119
|
+
const assetData = assetsExtendedData.get(assetID);
|
|
120
|
+
const totalSupply = (0, math_1.calculatePresentValue)(assetData.sRate, assetData.totalSupply);
|
|
121
|
+
const totalBorrow = (0, math_1.calculatePresentValue)(assetData.bRate, assetData.totalBorrow);
|
|
122
|
+
assetsReserves.set(assetID, assetData.balance - totalSupply + totalBorrow);
|
|
123
|
+
apy.supply.set(assetID, (1 + (Number(assetData.supplyInterest) / 1e12) * 24 * 3600) ** 365 - 1);
|
|
124
|
+
apy.borrow.set(assetID, (1 + (Number(assetData.borrowInterest) / 1e12) * 24 * 3600) ** 365 - 1);
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
meta: meta,
|
|
128
|
+
upgradeConfig: upgradeConfig,
|
|
129
|
+
masterConfig: masterConfig,
|
|
130
|
+
assetsConfig: assetsConfigDict,
|
|
131
|
+
assetsData: assetsExtendedData,
|
|
132
|
+
assetsReserves: assetsReserves,
|
|
133
|
+
apy: apy,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
exports.parseMasterData = parseMasterData;
|
|
137
|
+
function parseUserLiteData(userDataBOC, assetsData, assetsConfig) {
|
|
138
|
+
const userSlice = core_1.Cell.fromBase64(userDataBOC).beginParse();
|
|
139
|
+
const codeVersion = userSlice.loadCoins();
|
|
140
|
+
const masterAddress = userSlice.loadAddress();
|
|
141
|
+
const userAddress = userSlice.loadAddress();
|
|
142
|
+
const principalsDict = userSlice.loadDict(core_1.Dictionary.Keys.BigUint(256), core_1.Dictionary.Values.BigInt(64));
|
|
143
|
+
const userState = userSlice.loadInt(64);
|
|
144
|
+
const trackingSupplyIndex = userSlice.loadUintBig(64);
|
|
145
|
+
const trackingBorrowIndex = userSlice.loadUintBig(64);
|
|
146
|
+
const dutchAuctionStart = userSlice.loadUint(32);
|
|
147
|
+
const backupCell = (0, helpers_1.loadMyRef)(userSlice);
|
|
148
|
+
userSlice.endParse();
|
|
149
|
+
const userBalances = core_1.Dictionary.empty();
|
|
150
|
+
for (const [_, assetID] of Object.entries(constants_1.ASSET_ID)) {
|
|
151
|
+
const assetData = assetsData.get(assetID);
|
|
152
|
+
const assetConfig = assetsConfig.get(assetID);
|
|
153
|
+
const balance = (0, math_1.presentValue)(assetData.sRate, assetData.bRate, principalsDict.get(assetID) || 0n);
|
|
154
|
+
userBalances.set(assetID, balance);
|
|
155
|
+
}
|
|
156
|
+
return {
|
|
157
|
+
type: 'active',
|
|
158
|
+
codeVersion: Number(codeVersion),
|
|
159
|
+
masterAddress: masterAddress,
|
|
160
|
+
ownerAddress: userAddress,
|
|
161
|
+
principals: principalsDict,
|
|
162
|
+
state: userState,
|
|
163
|
+
balances: userBalances,
|
|
164
|
+
trackingSupplyIndex: trackingSupplyIndex,
|
|
165
|
+
trackingBorrowIndex: trackingBorrowIndex,
|
|
166
|
+
dutchAuctionStart: dutchAuctionStart,
|
|
167
|
+
backupCell: backupCell,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
exports.parseUserLiteData = parseUserLiteData;
|
|
171
|
+
function parseUserData(userLiteData, assetsData, assetsConfig, prices) {
|
|
172
|
+
const withdrawalLimits = core_1.Dictionary.empty();
|
|
173
|
+
const borrowLimits = core_1.Dictionary.empty();
|
|
174
|
+
let supplyBalance = 0n;
|
|
175
|
+
let borrowBalance = 0n;
|
|
176
|
+
for (const [_, assetID] of Object.entries(constants_1.ASSET_ID)) {
|
|
177
|
+
const assetData = assetsData.get(assetID);
|
|
178
|
+
const assetConfig = assetsConfig.get(assetID);
|
|
179
|
+
const balance = (0, math_1.presentValue)(assetData.sRate, assetData.bRate, userLiteData.principals.get(assetID) || 0n);
|
|
180
|
+
userLiteData.balances.set(assetID, balance);
|
|
181
|
+
}
|
|
182
|
+
for (const [_, assetID] of Object.entries(constants_1.ASSET_ID)) {
|
|
183
|
+
const assetConfig = assetsConfig.get(assetID);
|
|
184
|
+
const balance = userLiteData.balances.get(assetID);
|
|
185
|
+
if (balance.type === User_1.BalanceType.supply) {
|
|
186
|
+
supplyBalance += (balance.amount * prices.get(assetID)) / 10n ** assetConfig.decimals;
|
|
187
|
+
}
|
|
188
|
+
if (balance.type === User_1.BalanceType.borrow) {
|
|
189
|
+
borrowBalance += (balance.amount * prices.get(assetID)) / 10n ** assetConfig.decimals;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
const availableToBorrow = (0, math_1.getAvailableToBorrow)(assetsConfig, assetsData, userLiteData.principals, prices);
|
|
193
|
+
for (const [_, assetID] of Object.entries(constants_1.ASSET_ID)) {
|
|
194
|
+
const assetConfig = assetsConfig.get(assetID);
|
|
195
|
+
const assetData = assetsData.get(assetID);
|
|
196
|
+
const balance = userLiteData.balances.get(assetID);
|
|
197
|
+
if (balance.type === User_1.BalanceType.supply) {
|
|
198
|
+
withdrawalLimits.set(assetID, (0, math_1.bigIntMax)((0, math_1.bigIntMin)(assetData.balance, ((supplyBalance -
|
|
199
|
+
(borrowBalance * constants_1.MASTER_CONSTANTS.ASSET_COEFFICIENT_SCALE) / assetConfig.collateralFactor) *
|
|
200
|
+
10n ** assetConfig.decimals) /
|
|
201
|
+
prices.get(assetID) -
|
|
202
|
+
5n, balance.amount), 0n));
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
borrowLimits.set(assetID, (0, math_1.bigIntMin)((availableToBorrow * 10n ** assetConfig.decimals) / prices.get(assetID), assetData.balance));
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
const limitUsed = borrowBalance + availableToBorrow;
|
|
209
|
+
const limitUsedPercent = limitUsed === 0n
|
|
210
|
+
? 0
|
|
211
|
+
: Number(BigInt(1e9) - (availableToBorrow * BigInt(1e9)) / (borrowBalance + availableToBorrow)) / 1e7;
|
|
212
|
+
const liquidationData = (0, math_1.calculateLiquidationData)(assetsConfig, assetsData, userLiteData.principals, prices);
|
|
213
|
+
const healthFactor = 1 - Number(liquidationData.totalDebt) / Number(liquidationData.totalLimit);
|
|
214
|
+
return {
|
|
215
|
+
...userLiteData,
|
|
216
|
+
withdrawalLimits: withdrawalLimits,
|
|
217
|
+
borrowLimits: borrowLimits,
|
|
218
|
+
supplyBalance: supplyBalance,
|
|
219
|
+
borrowBalance: borrowBalance,
|
|
220
|
+
availableToBorrow: availableToBorrow,
|
|
221
|
+
limitUsedPercent: limitUsedPercent,
|
|
222
|
+
limitUsed: limitUsed,
|
|
223
|
+
liquidationData: liquidationData,
|
|
224
|
+
healthFactor: healthFactor,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
exports.parseUserData = parseUserData;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { PriceData } from '../types/Common';
|
|
2
|
+
type SerializedPrice = {
|
|
3
|
+
symbol: string;
|
|
4
|
+
value: number;
|
|
5
|
+
timestamp: number;
|
|
6
|
+
};
|
|
7
|
+
export declare function getLiteDataBytesString(priceData: SerializedPrice): string;
|
|
8
|
+
export declare function getPrices(): Promise<PriceData | undefined>;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getPrices = exports.getLiteDataBytesString = void 0;
|
|
4
|
+
const core_1 = require("@ton/core");
|
|
5
|
+
const ethers_1 = require("ethers");
|
|
6
|
+
const constants_1 = require("../constants");
|
|
7
|
+
function hexToArrayBuffer(input) {
|
|
8
|
+
if (typeof input !== 'string') {
|
|
9
|
+
throw new TypeError('Expected input to be a string');
|
|
10
|
+
}
|
|
11
|
+
if (input.length % 2 !== 0) {
|
|
12
|
+
throw new RangeError('Expected string to be an even number of characters');
|
|
13
|
+
}
|
|
14
|
+
if (input.startsWith('0x')) {
|
|
15
|
+
input = input.slice(2);
|
|
16
|
+
}
|
|
17
|
+
const view = new Uint8Array(input.length / 2);
|
|
18
|
+
for (let i = 0; i < input.length; i += 2) {
|
|
19
|
+
view[i / 2] = parseInt(input.substring(i, i + 2), 16);
|
|
20
|
+
}
|
|
21
|
+
return Buffer.from(view.buffer);
|
|
22
|
+
}
|
|
23
|
+
function convertStringToBytes32String(str) {
|
|
24
|
+
if (str.length > 31) {
|
|
25
|
+
const bytes32StringLength = 32 * 2 + 2; // 32 bytes (each byte uses 2 symbols) + 0x
|
|
26
|
+
if (str.length === bytes32StringLength && str.startsWith('0x')) {
|
|
27
|
+
return str;
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
return ethers_1.ethers.utils.id(str);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
return ethers_1.ethers.utils.formatBytes32String(str);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function getLiteDataBytesString(priceData) {
|
|
38
|
+
let data = priceData.symbol.substr(2) + priceData.value.toString(16).padStart(64, '0');
|
|
39
|
+
data += Math.ceil(priceData.timestamp / 1000)
|
|
40
|
+
.toString(16)
|
|
41
|
+
.padStart(64, '0');
|
|
42
|
+
return data;
|
|
43
|
+
}
|
|
44
|
+
exports.getLiteDataBytesString = getLiteDataBytesString;
|
|
45
|
+
async function getPrice(symbol) {
|
|
46
|
+
const res = await fetch(`https://api.redstone.finance/prices?symbol=${symbol}&provider=redstone&limit=1`);
|
|
47
|
+
const data = (await res.json());
|
|
48
|
+
const price = data[0];
|
|
49
|
+
const message = {
|
|
50
|
+
symbol: convertStringToBytes32String(price.symbol),
|
|
51
|
+
value: Math.round(price.value * 10 ** 8),
|
|
52
|
+
timestamp: price.timestamp,
|
|
53
|
+
};
|
|
54
|
+
let dictKey;
|
|
55
|
+
const dictValue = BigInt(message.value) * 10n;
|
|
56
|
+
switch (message.symbol) {
|
|
57
|
+
case '0x544f4e0000000000000000000000000000000000000000000000000000000000':
|
|
58
|
+
dictKey = constants_1.ASSET_ID.TON;
|
|
59
|
+
break;
|
|
60
|
+
case '0x5553445400000000000000000000000000000000000000000000000000000000':
|
|
61
|
+
dictKey = constants_1.ASSET_ID.jUSDT;
|
|
62
|
+
break;
|
|
63
|
+
case '0x5553444300000000000000000000000000000000000000000000000000000000':
|
|
64
|
+
dictKey = constants_1.ASSET_ID.jUSDC;
|
|
65
|
+
break;
|
|
66
|
+
default:
|
|
67
|
+
throw new Error('Unknown symbol');
|
|
68
|
+
}
|
|
69
|
+
const signature = hexToArrayBuffer(price.liteEvmSignature);
|
|
70
|
+
return {
|
|
71
|
+
data: Buffer.from(getLiteDataBytesString(message), 'hex'),
|
|
72
|
+
signature: signature,
|
|
73
|
+
dictKey: dictKey,
|
|
74
|
+
dictValue: dictValue,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
async function getPrices() {
|
|
78
|
+
try {
|
|
79
|
+
const symbols = ['TON', 'USDT', 'USDC'];
|
|
80
|
+
const rawPriceData = [];
|
|
81
|
+
const priceDict = core_1.Dictionary.empty(core_1.Dictionary.Keys.BigUint(256), core_1.Dictionary.Values.BigUint(64));
|
|
82
|
+
const pricePromises = symbols.map(async (symbol) => {
|
|
83
|
+
const price = await getPrice(symbol);
|
|
84
|
+
priceDict.set(price.dictKey, price.dictValue);
|
|
85
|
+
rawPriceData.push(price);
|
|
86
|
+
});
|
|
87
|
+
await Promise.all(pricePromises);
|
|
88
|
+
const rawPricesDict = core_1.Dictionary.empty();
|
|
89
|
+
for (const data of rawPriceData) {
|
|
90
|
+
rawPricesDict.set(data.signature, (0, core_1.beginCell)().storeBuffer(data.data).endCell());
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
dict: priceDict,
|
|
94
|
+
dataCell: (0, core_1.beginCell)()
|
|
95
|
+
.storeDictDirect(rawPricesDict, core_1.Dictionary.Keys.Buffer(65), core_1.Dictionary.Values.Cell())
|
|
96
|
+
.endCell(),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
console.error(error);
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
exports.getPrices = getPrices;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Address, Cell } from '@ton/core';
|
|
2
|
+
export declare const EVAA_MASTER_MAINNET: Address;
|
|
3
|
+
export declare const MAINNET_VERSION = 2;
|
|
4
|
+
export declare const EVAA_MASTER_TESTNET: Address;
|
|
5
|
+
export declare const TESTNET_VERSION = 1;
|
|
6
|
+
export declare const ASSET_ID: {
|
|
7
|
+
TON: bigint;
|
|
8
|
+
jUSDT: bigint;
|
|
9
|
+
jUSDC: bigint;
|
|
10
|
+
};
|
|
11
|
+
export declare const JETTON_MASTER_ADDRESSES: {
|
|
12
|
+
jUSDT_MAINNET: Address;
|
|
13
|
+
jUSDT_TESTNET: Address;
|
|
14
|
+
jUSDC_MAINNET: Address;
|
|
15
|
+
jUSDC_TESTNET: Address;
|
|
16
|
+
};
|
|
17
|
+
export declare const MASTER_CONSTANTS: {
|
|
18
|
+
FACTOR_SCALE: bigint;
|
|
19
|
+
ASSET_COEFFICIENT_SCALE: bigint;
|
|
20
|
+
ASSET_PRICE_SCALE: bigint;
|
|
21
|
+
};
|
|
22
|
+
export declare const LENDING_CODE: Cell;
|
|
23
|
+
export declare const JETTON_WALLET_CODE: Cell;
|
|
24
|
+
export declare const OPCODES: {
|
|
25
|
+
SUPPLY: number;
|
|
26
|
+
WITHDRAW: number;
|
|
27
|
+
LIQUIDATE: number;
|
|
28
|
+
JETTON_TRANSFER: number;
|
|
29
|
+
};
|
|
30
|
+
export declare const FEES: {
|
|
31
|
+
SUPPLY: bigint;
|
|
32
|
+
WITHDRAW: bigint;
|
|
33
|
+
SUPPLY_JETTON: bigint;
|
|
34
|
+
SUPPLY_JETTON_FWD: bigint;
|
|
35
|
+
LIQUIDATION: bigint;
|
|
36
|
+
LIQUIDATION_JETTON: bigint;
|
|
37
|
+
LIQUIDATION_JETTON_FWD: bigint;
|
|
38
|
+
};
|