@evaafi/sdk 0.3.0 → 0.3.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/dist/api/math.js +1 -1
- package/dist/api/parser.js +13 -11
- package/dist/api/prices.d.ts +0 -7
- package/dist/api/prices.js +13 -88
- package/dist/constants.d.ts +12 -2
- package/dist/constants.js +16 -6
- package/dist/types/Master.d.ts +2 -2
- package/dist/utils/userJettonWallet.js +24 -0
- package/package.json +1 -1
- package/src/api/math.ts +252 -252
- package/src/constants.ts +64 -58
- package/src/utils/userJettonWallet.ts +55 -41
- package/dist/types/Redstone.d.ts +0 -15
- package/dist/types/Redstone.js +0 -2
package/dist/api/math.js
CHANGED
|
@@ -48,7 +48,7 @@ function calculateCurrentRates(assetConfig, assetData) {
|
|
|
48
48
|
}
|
|
49
49
|
exports.calculateCurrentRates = calculateCurrentRates;
|
|
50
50
|
function calculateAssetData(assetsConfigDict, assetsDataDict, assetId) {
|
|
51
|
-
const config = assetsConfigDict.get(assetId);
|
|
51
|
+
const config = assetsConfigDict.get(assetId);
|
|
52
52
|
const data = assetsDataDict.get(assetId);
|
|
53
53
|
if (!data || !config) {
|
|
54
54
|
throw new Error('Asset Data or Config is not accessible');
|
package/dist/api/parser.js
CHANGED
|
@@ -50,16 +50,17 @@ function createAssetConfig() {
|
|
|
50
50
|
const oracle = src.loadUintBig(256);
|
|
51
51
|
const decimals = BigInt(src.loadUint(8));
|
|
52
52
|
const ref = src.loadRef().beginParse();
|
|
53
|
-
const collateralFactor =
|
|
54
|
-
const liquidationThreshold =
|
|
55
|
-
const liquidationBonus =
|
|
56
|
-
const baseBorrowRate =
|
|
57
|
-
const borrowRateSlopeLow =
|
|
58
|
-
const borrowRateSlopeHigh =
|
|
59
|
-
const supplyRateSlopeLow =
|
|
60
|
-
const supplyRateSlopeHigh =
|
|
61
|
-
const targetUtilization =
|
|
62
|
-
const originationFee =
|
|
53
|
+
const collateralFactor = ref.loadUintBig(16);
|
|
54
|
+
const liquidationThreshold = ref.loadUintBig(16);
|
|
55
|
+
const liquidationBonus = ref.loadUintBig(16);
|
|
56
|
+
const baseBorrowRate = ref.loadUintBig(64);
|
|
57
|
+
const borrowRateSlopeLow = ref.loadUintBig(64);
|
|
58
|
+
const borrowRateSlopeHigh = ref.loadUintBig(64);
|
|
59
|
+
const supplyRateSlopeLow = ref.loadUintBig(64);
|
|
60
|
+
const supplyRateSlopeHigh = ref.loadUintBig(64);
|
|
61
|
+
const targetUtilization = ref.loadUintBig(64);
|
|
62
|
+
const originationFee = ref.loadUintBig(64);
|
|
63
|
+
const dust = ref.loadUintBig(64);
|
|
63
64
|
return {
|
|
64
65
|
oracle,
|
|
65
66
|
decimals,
|
|
@@ -73,6 +74,7 @@ function createAssetConfig() {
|
|
|
73
74
|
supplyRateSlopeHigh,
|
|
74
75
|
targetUtilization,
|
|
75
76
|
originationFee,
|
|
77
|
+
dust,
|
|
76
78
|
};
|
|
77
79
|
},
|
|
78
80
|
};
|
|
@@ -110,7 +112,7 @@ function parseMasterData(masterDataBOC) {
|
|
|
110
112
|
const masterConfig = {
|
|
111
113
|
ifActive: masterConfigSlice.loadInt(8),
|
|
112
114
|
admin: masterConfigSlice.loadAddress(),
|
|
113
|
-
adminPK: masterConfigSlice.
|
|
115
|
+
adminPK: masterConfigSlice.loadUintBig(256),
|
|
114
116
|
tokenKeys: (0, helpers_1.loadMaybeMyRef)(masterConfigSlice),
|
|
115
117
|
walletToMaster: (0, helpers_1.loadMaybeMyRef)(masterConfigSlice),
|
|
116
118
|
};
|
package/dist/api/prices.d.ts
CHANGED
|
@@ -1,9 +1,2 @@
|
|
|
1
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
2
|
export declare function getPrices(): Promise<PriceData | undefined>;
|
|
9
|
-
export {};
|
package/dist/api/prices.js
CHANGED
|
@@ -1,99 +1,24 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getPrices =
|
|
3
|
+
exports.getPrices = void 0;
|
|
4
4
|
const core_1 = require("@ton/core");
|
|
5
|
-
const ethers_1 = require("ethers");
|
|
6
5
|
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
6
|
async function getPrices() {
|
|
78
7
|
try {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
rawPriceData.push(price);
|
|
8
|
+
let result = await fetch('https://api.stardust-mainnet.iotaledger.net/api/indexer/v1/outputs/nft/' + constants_1.NFT_ID, {
|
|
9
|
+
headers: { accept: 'application/json' },
|
|
10
|
+
});
|
|
11
|
+
let outputId = (await result.json());
|
|
12
|
+
result = await fetch('https://api.stardust-mainnet.iotaledger.net/api/core/v2/outputs/' + outputId.items[0], {
|
|
13
|
+
headers: { accept: 'application/json' },
|
|
86
14
|
});
|
|
87
|
-
await
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
15
|
+
let resData = (await result.json());
|
|
16
|
+
const data = JSON.parse(decodeURIComponent(resData.output.features[0].data.replace('0x', '').replace(/[0-9a-f]{2}/g, '%$&')));
|
|
17
|
+
const pricesCell = core_1.Cell.fromBoc(Buffer.from(data['packedPrices'], 'hex'))[0];
|
|
18
|
+
const signature = Buffer.from(data['signature'], 'hex');
|
|
92
19
|
return {
|
|
93
|
-
dict:
|
|
94
|
-
dataCell: (0, core_1.beginCell)()
|
|
95
|
-
.storeDictDirect(rawPricesDict, core_1.Dictionary.Keys.Buffer(65), core_1.Dictionary.Values.Cell())
|
|
96
|
-
.endCell(),
|
|
20
|
+
dict: pricesCell.beginParse().loadDictDirect(core_1.Dictionary.Keys.BigUint(256), core_1.Dictionary.Values.BigUint(64)),
|
|
21
|
+
dataCell: (0, core_1.beginCell)().storeRef(pricesCell).storeBuffer(signature).endCell(),
|
|
97
22
|
};
|
|
98
23
|
}
|
|
99
24
|
catch (error) {
|
package/dist/constants.d.ts
CHANGED
|
@@ -1,18 +1,28 @@
|
|
|
1
1
|
import { Address, Cell } from '@ton/core';
|
|
2
2
|
export declare const EVAA_MASTER_MAINNET: Address;
|
|
3
|
-
export declare const MAINNET_VERSION =
|
|
3
|
+
export declare const MAINNET_VERSION = 3;
|
|
4
4
|
export declare const EVAA_MASTER_TESTNET: Address;
|
|
5
|
-
export declare const TESTNET_VERSION =
|
|
5
|
+
export declare const TESTNET_VERSION = 3;
|
|
6
|
+
export declare const NFT_ID = "0xfb9874544d76ca49c5db9cc3e5121e4c018bc8a2fb2bfe8f2a38c5b9963492f5";
|
|
6
7
|
export declare const ASSET_ID: {
|
|
7
8
|
TON: bigint;
|
|
8
9
|
jUSDT: bigint;
|
|
9
10
|
jUSDC: bigint;
|
|
11
|
+
stTON: bigint;
|
|
12
|
+
tsTON: bigint;
|
|
13
|
+
USDT: bigint;
|
|
10
14
|
};
|
|
11
15
|
export declare const JETTON_MASTER_ADDRESSES: {
|
|
12
16
|
jUSDT_MAINNET: Address;
|
|
13
17
|
jUSDT_TESTNET: Address;
|
|
14
18
|
jUSDC_MAINNET: Address;
|
|
15
19
|
jUSDC_TESTNET: Address;
|
|
20
|
+
stTON_MAINNET: Address;
|
|
21
|
+
stTON_TESTNET: Address;
|
|
22
|
+
tsTON_MAINNET: Address;
|
|
23
|
+
tsTON_TESTNET: null;
|
|
24
|
+
USDT_MAINNET: Address;
|
|
25
|
+
USDT_TESTNET: null;
|
|
16
26
|
};
|
|
17
27
|
export declare const MASTER_CONSTANTS: {
|
|
18
28
|
FACTOR_SCALE: bigint;
|
package/dist/constants.js
CHANGED
|
@@ -1,22 +1,32 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.FEES = exports.OPCODES = exports.JETTON_WALLET_CODE = exports.LENDING_CODE = exports.MASTER_CONSTANTS = exports.JETTON_MASTER_ADDRESSES = exports.ASSET_ID = exports.TESTNET_VERSION = exports.EVAA_MASTER_TESTNET = exports.MAINNET_VERSION = exports.EVAA_MASTER_MAINNET = void 0;
|
|
3
|
+
exports.FEES = exports.OPCODES = exports.JETTON_WALLET_CODE = exports.LENDING_CODE = exports.MASTER_CONSTANTS = exports.JETTON_MASTER_ADDRESSES = exports.ASSET_ID = exports.NFT_ID = exports.TESTNET_VERSION = exports.EVAA_MASTER_TESTNET = exports.MAINNET_VERSION = exports.EVAA_MASTER_MAINNET = void 0;
|
|
4
4
|
const core_1 = require("@ton/core");
|
|
5
5
|
const sha256BigInt_1 = require("./utils/sha256BigInt");
|
|
6
6
|
exports.EVAA_MASTER_MAINNET = core_1.Address.parse('EQC8rUZqR_pWV1BylWUlPNBzyiTYVoBEmQkMIQDZXICfnuRr');
|
|
7
|
-
exports.MAINNET_VERSION =
|
|
8
|
-
exports.EVAA_MASTER_TESTNET = core_1.Address.parse('
|
|
9
|
-
exports.TESTNET_VERSION =
|
|
7
|
+
exports.MAINNET_VERSION = 3;
|
|
8
|
+
exports.EVAA_MASTER_TESTNET = core_1.Address.parse('kQClWdMebpK90b6imEUreQJ4M3oz8Gqwd3xkVIowR8LDX98-');
|
|
9
|
+
exports.TESTNET_VERSION = 3;
|
|
10
|
+
exports.NFT_ID = '0xfb9874544d76ca49c5db9cc3e5121e4c018bc8a2fb2bfe8f2a38c5b9963492f5';
|
|
10
11
|
exports.ASSET_ID = {
|
|
11
12
|
TON: (0, sha256BigInt_1.sha256Hash)('TON'),
|
|
12
13
|
jUSDT: (0, sha256BigInt_1.sha256Hash)('jUSDT'),
|
|
13
14
|
jUSDC: (0, sha256BigInt_1.sha256Hash)('jUSDC'),
|
|
15
|
+
stTON: (0, sha256BigInt_1.sha256Hash)('stTON'),
|
|
16
|
+
tsTON: (0, sha256BigInt_1.sha256Hash)('tsTON'),
|
|
17
|
+
USDT: (0, sha256BigInt_1.sha256Hash)('USDT'),
|
|
14
18
|
};
|
|
15
19
|
exports.JETTON_MASTER_ADDRESSES = {
|
|
16
20
|
jUSDT_MAINNET: core_1.Address.parse('EQBwbF0otxLyA3VrRjjC1q7i3G7LtoEpdyBjZEuNtrhC4drm'),
|
|
17
|
-
jUSDT_TESTNET: core_1.Address.parse('
|
|
21
|
+
jUSDT_TESTNET: core_1.Address.parse('kQBtFVedUkg9Q7M5eMx_gxAdP5R7QCLR-3RCYQNrm_DZYr6Z'),
|
|
18
22
|
jUSDC_MAINNET: core_1.Address.parse('EQCEHZi-CLX2ghdsNbY35umR1OFODG5ySHrtK6GItMdWv7dS'),
|
|
19
|
-
jUSDC_TESTNET: core_1.Address.parse('
|
|
23
|
+
jUSDC_TESTNET: core_1.Address.parse('kQCZWZD_rBZ1vrqF22aX4AZrU1a1q-YKZH_R2VlALoVNCvXd'),
|
|
24
|
+
stTON_MAINNET: core_1.Address.parse('EQBOn-1b-315ogeCl5lfPYW0ut6sjA2eq4LTdRv5vJJ1SsxX'),
|
|
25
|
+
stTON_TESTNET: core_1.Address.parse('kQCpm8ixF6STW7aidxn_Qkp4sR73msPlrduCeRZfo-Zu7dxt'),
|
|
26
|
+
tsTON_MAINNET: core_1.Address.parse('EQCRC0telhv1QESvTx24nNqUWB72zCysXQ0Bx97lVzucQ3Gr'),
|
|
27
|
+
tsTON_TESTNET: null,
|
|
28
|
+
USDT_MAINNET: core_1.Address.parse('EQD_kMQkK-A9-CQu3CdOnQUDZ2_8bY8Zrh1PvtE3hZpxvdRH'),
|
|
29
|
+
USDT_TESTNET: null,
|
|
20
30
|
};
|
|
21
31
|
exports.MASTER_CONSTANTS = {
|
|
22
32
|
FACTOR_SCALE: BigInt(1e12),
|
package/dist/types/Master.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
1
|
import { Address, Cell, Dictionary } from '@ton/core';
|
|
3
2
|
export type UpgradeConfig = {
|
|
4
3
|
masterCodeVersion: number;
|
|
@@ -24,11 +23,12 @@ export type AssetConfig = {
|
|
|
24
23
|
supplyRateSlopeHigh: bigint;
|
|
25
24
|
targetUtilization: bigint;
|
|
26
25
|
originationFee: bigint;
|
|
26
|
+
dust: bigint;
|
|
27
27
|
};
|
|
28
28
|
export type MasterConfig = {
|
|
29
29
|
ifActive: number;
|
|
30
30
|
admin: Address;
|
|
31
|
-
adminPK:
|
|
31
|
+
adminPK: bigint;
|
|
32
32
|
tokenKeys: Cell | null;
|
|
33
33
|
walletToMaster: Cell | null;
|
|
34
34
|
};
|
|
@@ -22,6 +22,30 @@ function getUserJettonWallet(ownerAddress, assetID, network) {
|
|
|
22
22
|
builder.storeAddress(constants_1.JETTON_MASTER_ADDRESSES.jUSDC_TESTNET);
|
|
23
23
|
}
|
|
24
24
|
break;
|
|
25
|
+
case constants_1.ASSET_ID.stTON:
|
|
26
|
+
if (network === 'mainnet') {
|
|
27
|
+
builder.storeAddress(constants_1.JETTON_MASTER_ADDRESSES.stTON_MAINNET);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
builder.storeAddress(constants_1.JETTON_MASTER_ADDRESSES.stTON_TESTNET);
|
|
31
|
+
}
|
|
32
|
+
break;
|
|
33
|
+
case constants_1.ASSET_ID.tsTON:
|
|
34
|
+
if (network === 'mainnet') {
|
|
35
|
+
builder.storeAddress(constants_1.JETTON_MASTER_ADDRESSES.tsTON_MAINNET);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
builder.storeAddress(constants_1.JETTON_MASTER_ADDRESSES.tsTON_TESTNET);
|
|
39
|
+
}
|
|
40
|
+
break;
|
|
41
|
+
case constants_1.ASSET_ID.USDT:
|
|
42
|
+
if (network === 'mainnet') {
|
|
43
|
+
builder.storeAddress(constants_1.JETTON_MASTER_ADDRESSES.USDT_MAINNET);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
builder.storeAddress(constants_1.JETTON_MASTER_ADDRESSES.USDT_TESTNET);
|
|
47
|
+
}
|
|
48
|
+
break;
|
|
25
49
|
default:
|
|
26
50
|
throw new Error('Unsupported asset');
|
|
27
51
|
}
|
package/package.json
CHANGED
package/src/api/math.ts
CHANGED
|
@@ -1,252 +1,252 @@
|
|
|
1
|
-
import { AssetConfig, AssetData, AssetInterest, ExtendedAssetData } from '../types/Master';
|
|
2
|
-
import { MASTER_CONSTANTS } from '../constants';
|
|
3
|
-
import { Dictionary } from '@ton/core';
|
|
4
|
-
import { BalanceType, LiquidationData, UserBalance } from '../types/User';
|
|
5
|
-
|
|
6
|
-
export function mulFactor(decimal: bigint, a: bigint, b: bigint): bigint {
|
|
7
|
-
return (a * b) / decimal;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export function mulDiv(x: bigint, y: bigint, z: bigint): bigint {
|
|
11
|
-
return (x * y) / z;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export function bigIntMax(...args: bigint[]): bigint {
|
|
15
|
-
return args.reduce((m, e) => (e > m ? e : m));
|
|
16
|
-
}
|
|
17
|
-
export function bigIntMin(...args: bigint[]): bigint {
|
|
18
|
-
return args.reduce((m, e) => (e < m ? e : m));
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function calculatePresentValue(index: bigint, principalValue: bigint): bigint {
|
|
22
|
-
return (principalValue * index) / MASTER_CONSTANTS.FACTOR_SCALE;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function calculateCurrentRates(assetConfig: AssetConfig, assetData: AssetData) {
|
|
26
|
-
const now = BigInt(Math.floor(Date.now() / 1000));
|
|
27
|
-
const timeElapsed = now - assetData.lastAccural;
|
|
28
|
-
const { supplyInterest, borrowInterest } = calculateAssetInterest(assetConfig, assetData);
|
|
29
|
-
|
|
30
|
-
if (timeElapsed > 0) {
|
|
31
|
-
const updatedSRate =
|
|
32
|
-
assetData.sRate + mulFactor(MASTER_CONSTANTS.FACTOR_SCALE, assetData.sRate, supplyInterest * timeElapsed);
|
|
33
|
-
const updatedBRate =
|
|
34
|
-
assetData.bRate + mulFactor(MASTER_CONSTANTS.FACTOR_SCALE, assetData.bRate, borrowInterest * timeElapsed);
|
|
35
|
-
return {
|
|
36
|
-
sRate: updatedSRate,
|
|
37
|
-
bRate: updatedBRate,
|
|
38
|
-
supplyInterest,
|
|
39
|
-
borrowInterest,
|
|
40
|
-
now,
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return {
|
|
45
|
-
sRate: assetData.sRate,
|
|
46
|
-
bRate: assetData.bRate,
|
|
47
|
-
supplyInterest,
|
|
48
|
-
borrowInterest,
|
|
49
|
-
now,
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export function calculateAssetData(
|
|
54
|
-
assetsConfigDict: Dictionary<bigint, AssetConfig>,
|
|
55
|
-
assetsDataDict: Dictionary<bigint, AssetData>,
|
|
56
|
-
assetId: bigint,
|
|
57
|
-
): ExtendedAssetData {
|
|
58
|
-
const config = assetsConfigDict.get(assetId);
|
|
59
|
-
const data = assetsDataDict.get(assetId);
|
|
60
|
-
|
|
61
|
-
if (!data || !config) {
|
|
62
|
-
throw new Error('Asset Data or Config is not accessible');
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const { sRate, bRate, supplyInterest, borrowInterest, now } = calculateCurrentRates(config, data);
|
|
66
|
-
data.sRate = sRate || 0n;
|
|
67
|
-
data.bRate = bRate || 0n;
|
|
68
|
-
data.lastAccural = now;
|
|
69
|
-
|
|
70
|
-
const supplyApy = (1 + (Number(supplyInterest) / 1e12) * 24 * 3600) ** 365 - 1;
|
|
71
|
-
const borrowApy = (1 + (Number(borrowInterest) / 1e12) * 24 * 3600) ** 365 - 1;
|
|
72
|
-
|
|
73
|
-
return {
|
|
74
|
-
...data,
|
|
75
|
-
...{ supplyInterest, borrowInterest },
|
|
76
|
-
...{ supplyApy, borrowApy },
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export function calculateAssetInterest(assetConfig: AssetConfig, assetData: AssetData): AssetInterest {
|
|
81
|
-
const totalSupply = calculatePresentValue(assetData.sRate, assetData.totalSupply);
|
|
82
|
-
const totalBorrow = calculatePresentValue(assetData.bRate, assetData.totalBorrow);
|
|
83
|
-
let utilization = 0n;
|
|
84
|
-
let supplyInterest = 0n;
|
|
85
|
-
let borrowInterest = 0n;
|
|
86
|
-
|
|
87
|
-
if (totalSupply !== 0n) {
|
|
88
|
-
utilization = (totalBorrow * MASTER_CONSTANTS.FACTOR_SCALE) / totalSupply;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (utilization <= assetConfig.targetUtilization) {
|
|
92
|
-
borrowInterest =
|
|
93
|
-
assetConfig.baseBorrowRate +
|
|
94
|
-
mulFactor(MASTER_CONSTANTS.FACTOR_SCALE, assetConfig.borrowRateSlopeLow, utilization);
|
|
95
|
-
} else {
|
|
96
|
-
borrowInterest =
|
|
97
|
-
assetConfig.baseBorrowRate +
|
|
98
|
-
mulFactor(MASTER_CONSTANTS.FACTOR_SCALE, assetConfig.borrowRateSlopeLow, assetConfig.targetUtilization) +
|
|
99
|
-
mulFactor(
|
|
100
|
-
MASTER_CONSTANTS.FACTOR_SCALE,
|
|
101
|
-
assetConfig.borrowRateSlopeHigh,
|
|
102
|
-
utilization - assetConfig.targetUtilization,
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const reserveFactor = 10n;
|
|
107
|
-
const reserveScale = 100n;
|
|
108
|
-
supplyInterest = mulDiv(
|
|
109
|
-
mulDiv(borrowInterest, utilization, MASTER_CONSTANTS.FACTOR_SCALE),
|
|
110
|
-
reserveScale - reserveFactor,
|
|
111
|
-
reserveScale,
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
return {
|
|
115
|
-
supplyInterest,
|
|
116
|
-
borrowInterest,
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
export function getAvailableToBorrow(
|
|
121
|
-
assetsConfig: Dictionary<bigint, AssetConfig>,
|
|
122
|
-
assetsData: Dictionary<bigint, ExtendedAssetData>,
|
|
123
|
-
principals: Dictionary<bigint, bigint>,
|
|
124
|
-
prices: Dictionary<bigint, bigint>,
|
|
125
|
-
): bigint {
|
|
126
|
-
let borrowLimit = 0n;
|
|
127
|
-
let borrowAmount = 0n;
|
|
128
|
-
|
|
129
|
-
for (const assetID of principals.keys()) {
|
|
130
|
-
const assetConfig = assetsConfig.get(assetID) as AssetConfig;
|
|
131
|
-
const assetData = assetsData.get(assetID) as ExtendedAssetData;
|
|
132
|
-
const price = prices.get(assetID) as bigint;
|
|
133
|
-
const principal = principals.get(assetID) as bigint;
|
|
134
|
-
|
|
135
|
-
if (principal < 0) {
|
|
136
|
-
borrowAmount += (calculatePresentValue(assetData.bRate, -principal) * price) / 10n ** assetConfig.decimals;
|
|
137
|
-
} else if (principal > 0) {
|
|
138
|
-
borrowLimit +=
|
|
139
|
-
(calculatePresentValue(assetData.sRate, principal) * price * assetConfig.collateralFactor) /
|
|
140
|
-
10n ** assetConfig.decimals /
|
|
141
|
-
MASTER_CONSTANTS.ASSET_COEFFICIENT_SCALE;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
return borrowLimit - borrowAmount;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
export function presentValue(sRate: bigint, bRate: bigint, principalValue: bigint): UserBalance {
|
|
149
|
-
if (principalValue > 0) {
|
|
150
|
-
return {
|
|
151
|
-
amount: calculatePresentValue(sRate, principalValue),
|
|
152
|
-
type: BalanceType.supply,
|
|
153
|
-
};
|
|
154
|
-
} else if (principalValue < 0) {
|
|
155
|
-
return {
|
|
156
|
-
amount: calculatePresentValue(bRate, -principalValue),
|
|
157
|
-
type: BalanceType.borrow,
|
|
158
|
-
};
|
|
159
|
-
} else {
|
|
160
|
-
return {
|
|
161
|
-
amount: 0n,
|
|
162
|
-
type: undefined,
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
export function calculateLiquidationData(
|
|
168
|
-
assetsConfig: Dictionary<bigint, AssetConfig>,
|
|
169
|
-
assetsData: Dictionary<bigint, ExtendedAssetData>,
|
|
170
|
-
principals: Dictionary<bigint, bigint>,
|
|
171
|
-
prices: Dictionary<bigint, bigint>,
|
|
172
|
-
): LiquidationData {
|
|
173
|
-
let gCollateralValue = 0n;
|
|
174
|
-
let gCollateralAsset = 0n;
|
|
175
|
-
let gLoanValue = 0n;
|
|
176
|
-
let gLoanAsset = 0n;
|
|
177
|
-
let totalDebt = 0n;
|
|
178
|
-
let totalLimit = 0n;
|
|
179
|
-
|
|
180
|
-
for (const key of principals.keys()) {
|
|
181
|
-
const principal = principals.get(key)!;
|
|
182
|
-
const assetConfig = assetsConfig.get(key)!;
|
|
183
|
-
const assetData = assetsData.get(key)!;
|
|
184
|
-
const balance =
|
|
185
|
-
principal > 0 ? (principal * assetData.sRate) / BigInt(1e12) : (principal * assetData.bRate) / BigInt(1e12);
|
|
186
|
-
if (balance > 0) {
|
|
187
|
-
const assetWorth = (balance * prices.get(key)!) / 10n ** assetConfig.decimals;
|
|
188
|
-
totalLimit += (assetWorth * assetConfig.liquidationThreshold) / MASTER_CONSTANTS.ASSET_COEFFICIENT_SCALE;
|
|
189
|
-
if (assetWorth > gCollateralValue) {
|
|
190
|
-
gCollateralValue = assetWorth;
|
|
191
|
-
gCollateralAsset = key;
|
|
192
|
-
}
|
|
193
|
-
} else if (balance < 0) {
|
|
194
|
-
const assetWorth = (-balance * prices.get(key)!) / 10n ** assetConfig.decimals;
|
|
195
|
-
totalDebt += assetWorth;
|
|
196
|
-
if (assetWorth > gLoanValue) {
|
|
197
|
-
gLoanValue = assetWorth;
|
|
198
|
-
gLoanAsset = key;
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
if (totalLimit < totalDebt) {
|
|
204
|
-
const gLoanAssetPrice = prices.get(gLoanAsset)!;
|
|
205
|
-
const values: bigint[] = [];
|
|
206
|
-
const gCollateralAssetConfig = assetsConfig.get(gCollateralAsset)!;
|
|
207
|
-
const gLoanAssetConfig = assetsConfig.get(gLoanAsset)!;
|
|
208
|
-
const liquidationBonus = gLoanAssetConfig.liquidationBonus;
|
|
209
|
-
const loanDecimal = 10n ** gLoanAssetConfig.decimals;
|
|
210
|
-
values.push(
|
|
211
|
-
(bigIntMax(gCollateralValue / 2n, bigIntMin(gCollateralValue, 10_000_000_000n)) *
|
|
212
|
-
loanDecimal *
|
|
213
|
-
MASTER_CONSTANTS.ASSET_COEFFICIENT_SCALE) /
|
|
214
|
-
liquidationBonus /
|
|
215
|
-
gLoanAssetPrice,
|
|
216
|
-
);
|
|
217
|
-
values.push((gLoanValue * loanDecimal) / gLoanAssetPrice);
|
|
218
|
-
|
|
219
|
-
const liquidationAmount = (bigIntMin(...values) as bigint) - 5n;
|
|
220
|
-
const gCollateralAssetPrice: bigint = prices.get(gCollateralAsset)!;
|
|
221
|
-
const collateralDecimal = 10n ** gCollateralAssetConfig.decimals;
|
|
222
|
-
let minCollateralAmount =
|
|
223
|
-
(((liquidationAmount * gLoanAssetPrice * liquidationBonus) / 10000n) * collateralDecimal) /
|
|
224
|
-
gCollateralAssetPrice /
|
|
225
|
-
loanDecimal -
|
|
226
|
-
10n;
|
|
227
|
-
minCollateralAmount = (minCollateralAmount * 97n) / 100n;
|
|
228
|
-
if (minCollateralAmount / collateralDecimal >= 1n) {
|
|
229
|
-
return {
|
|
230
|
-
greatestCollateralAsset: gCollateralAsset,
|
|
231
|
-
greatestCollateralValue: gCollateralValue,
|
|
232
|
-
greatestLoanAsset: gLoanAsset,
|
|
233
|
-
greatestLoanValue: gLoanValue,
|
|
234
|
-
totalDebt,
|
|
235
|
-
totalLimit,
|
|
236
|
-
liquidable: true,
|
|
237
|
-
liquidationAmount,
|
|
238
|
-
minCollateralAmount,
|
|
239
|
-
};
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
return {
|
|
244
|
-
greatestCollateralAsset: gCollateralAsset,
|
|
245
|
-
greatestCollateralValue: gCollateralValue,
|
|
246
|
-
greatestLoanAsset: gLoanAsset,
|
|
247
|
-
greatestLoanValue: gLoanValue,
|
|
248
|
-
totalDebt,
|
|
249
|
-
totalLimit,
|
|
250
|
-
liquidable: false,
|
|
251
|
-
};
|
|
252
|
-
}
|
|
1
|
+
import { AssetConfig, AssetData, AssetInterest, ExtendedAssetData } from '../types/Master';
|
|
2
|
+
import { MASTER_CONSTANTS } from '../constants';
|
|
3
|
+
import { Dictionary } from '@ton/core';
|
|
4
|
+
import { BalanceType, LiquidationData, UserBalance } from '../types/User';
|
|
5
|
+
|
|
6
|
+
export function mulFactor(decimal: bigint, a: bigint, b: bigint): bigint {
|
|
7
|
+
return (a * b) / decimal;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function mulDiv(x: bigint, y: bigint, z: bigint): bigint {
|
|
11
|
+
return (x * y) / z;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function bigIntMax(...args: bigint[]): bigint {
|
|
15
|
+
return args.reduce((m, e) => (e > m ? e : m));
|
|
16
|
+
}
|
|
17
|
+
export function bigIntMin(...args: bigint[]): bigint {
|
|
18
|
+
return args.reduce((m, e) => (e < m ? e : m));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function calculatePresentValue(index: bigint, principalValue: bigint): bigint {
|
|
22
|
+
return (principalValue * index) / MASTER_CONSTANTS.FACTOR_SCALE;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function calculateCurrentRates(assetConfig: AssetConfig, assetData: AssetData) {
|
|
26
|
+
const now = BigInt(Math.floor(Date.now() / 1000));
|
|
27
|
+
const timeElapsed = now - assetData.lastAccural;
|
|
28
|
+
const { supplyInterest, borrowInterest } = calculateAssetInterest(assetConfig, assetData);
|
|
29
|
+
|
|
30
|
+
if (timeElapsed > 0) {
|
|
31
|
+
const updatedSRate =
|
|
32
|
+
assetData.sRate + mulFactor(MASTER_CONSTANTS.FACTOR_SCALE, assetData.sRate, supplyInterest * timeElapsed);
|
|
33
|
+
const updatedBRate =
|
|
34
|
+
assetData.bRate + mulFactor(MASTER_CONSTANTS.FACTOR_SCALE, assetData.bRate, borrowInterest * timeElapsed);
|
|
35
|
+
return {
|
|
36
|
+
sRate: updatedSRate,
|
|
37
|
+
bRate: updatedBRate,
|
|
38
|
+
supplyInterest,
|
|
39
|
+
borrowInterest,
|
|
40
|
+
now,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
sRate: assetData.sRate,
|
|
46
|
+
bRate: assetData.bRate,
|
|
47
|
+
supplyInterest,
|
|
48
|
+
borrowInterest,
|
|
49
|
+
now,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function calculateAssetData(
|
|
54
|
+
assetsConfigDict: Dictionary<bigint, AssetConfig>,
|
|
55
|
+
assetsDataDict: Dictionary<bigint, AssetData>,
|
|
56
|
+
assetId: bigint,
|
|
57
|
+
): ExtendedAssetData {
|
|
58
|
+
const config = assetsConfigDict.get(assetId);
|
|
59
|
+
const data = assetsDataDict.get(assetId);
|
|
60
|
+
|
|
61
|
+
if (!data || !config) {
|
|
62
|
+
throw new Error('Asset Data or Config is not accessible');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const { sRate, bRate, supplyInterest, borrowInterest, now } = calculateCurrentRates(config, data);
|
|
66
|
+
data.sRate = sRate || 0n;
|
|
67
|
+
data.bRate = bRate || 0n;
|
|
68
|
+
data.lastAccural = now;
|
|
69
|
+
|
|
70
|
+
const supplyApy = (1 + (Number(supplyInterest) / 1e12) * 24 * 3600) ** 365 - 1;
|
|
71
|
+
const borrowApy = (1 + (Number(borrowInterest) / 1e12) * 24 * 3600) ** 365 - 1;
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
...data,
|
|
75
|
+
...{ supplyInterest, borrowInterest },
|
|
76
|
+
...{ supplyApy, borrowApy },
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function calculateAssetInterest(assetConfig: AssetConfig, assetData: AssetData): AssetInterest {
|
|
81
|
+
const totalSupply = calculatePresentValue(assetData.sRate, assetData.totalSupply);
|
|
82
|
+
const totalBorrow = calculatePresentValue(assetData.bRate, assetData.totalBorrow);
|
|
83
|
+
let utilization = 0n;
|
|
84
|
+
let supplyInterest = 0n;
|
|
85
|
+
let borrowInterest = 0n;
|
|
86
|
+
|
|
87
|
+
if (totalSupply !== 0n) {
|
|
88
|
+
utilization = (totalBorrow * MASTER_CONSTANTS.FACTOR_SCALE) / totalSupply;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (utilization <= assetConfig.targetUtilization) {
|
|
92
|
+
borrowInterest =
|
|
93
|
+
assetConfig.baseBorrowRate +
|
|
94
|
+
mulFactor(MASTER_CONSTANTS.FACTOR_SCALE, assetConfig.borrowRateSlopeLow, utilization);
|
|
95
|
+
} else {
|
|
96
|
+
borrowInterest =
|
|
97
|
+
assetConfig.baseBorrowRate +
|
|
98
|
+
mulFactor(MASTER_CONSTANTS.FACTOR_SCALE, assetConfig.borrowRateSlopeLow, assetConfig.targetUtilization) +
|
|
99
|
+
mulFactor(
|
|
100
|
+
MASTER_CONSTANTS.FACTOR_SCALE,
|
|
101
|
+
assetConfig.borrowRateSlopeHigh,
|
|
102
|
+
utilization - assetConfig.targetUtilization,
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const reserveFactor = 10n;
|
|
107
|
+
const reserveScale = 100n;
|
|
108
|
+
supplyInterest = mulDiv(
|
|
109
|
+
mulDiv(borrowInterest, utilization, MASTER_CONSTANTS.FACTOR_SCALE),
|
|
110
|
+
reserveScale - reserveFactor,
|
|
111
|
+
reserveScale,
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
supplyInterest,
|
|
116
|
+
borrowInterest,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function getAvailableToBorrow(
|
|
121
|
+
assetsConfig: Dictionary<bigint, AssetConfig>,
|
|
122
|
+
assetsData: Dictionary<bigint, ExtendedAssetData>,
|
|
123
|
+
principals: Dictionary<bigint, bigint>,
|
|
124
|
+
prices: Dictionary<bigint, bigint>,
|
|
125
|
+
): bigint {
|
|
126
|
+
let borrowLimit = 0n;
|
|
127
|
+
let borrowAmount = 0n;
|
|
128
|
+
|
|
129
|
+
for (const assetID of principals.keys()) {
|
|
130
|
+
const assetConfig = assetsConfig.get(assetID) as AssetConfig;
|
|
131
|
+
const assetData = assetsData.get(assetID) as ExtendedAssetData;
|
|
132
|
+
const price = prices.get(assetID) as bigint;
|
|
133
|
+
const principal = principals.get(assetID) as bigint;
|
|
134
|
+
|
|
135
|
+
if (principal < 0) {
|
|
136
|
+
borrowAmount += (calculatePresentValue(assetData.bRate, -principal) * price) / 10n ** assetConfig.decimals;
|
|
137
|
+
} else if (principal > 0) {
|
|
138
|
+
borrowLimit +=
|
|
139
|
+
(calculatePresentValue(assetData.sRate, principal) * price * assetConfig.collateralFactor) /
|
|
140
|
+
10n ** assetConfig.decimals /
|
|
141
|
+
MASTER_CONSTANTS.ASSET_COEFFICIENT_SCALE;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return borrowLimit - borrowAmount;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export function presentValue(sRate: bigint, bRate: bigint, principalValue: bigint): UserBalance {
|
|
149
|
+
if (principalValue > 0) {
|
|
150
|
+
return {
|
|
151
|
+
amount: calculatePresentValue(sRate, principalValue),
|
|
152
|
+
type: BalanceType.supply,
|
|
153
|
+
};
|
|
154
|
+
} else if (principalValue < 0) {
|
|
155
|
+
return {
|
|
156
|
+
amount: calculatePresentValue(bRate, -principalValue),
|
|
157
|
+
type: BalanceType.borrow,
|
|
158
|
+
};
|
|
159
|
+
} else {
|
|
160
|
+
return {
|
|
161
|
+
amount: 0n,
|
|
162
|
+
type: undefined,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export function calculateLiquidationData(
|
|
168
|
+
assetsConfig: Dictionary<bigint, AssetConfig>,
|
|
169
|
+
assetsData: Dictionary<bigint, ExtendedAssetData>,
|
|
170
|
+
principals: Dictionary<bigint, bigint>,
|
|
171
|
+
prices: Dictionary<bigint, bigint>,
|
|
172
|
+
): LiquidationData {
|
|
173
|
+
let gCollateralValue = 0n;
|
|
174
|
+
let gCollateralAsset = 0n;
|
|
175
|
+
let gLoanValue = 0n;
|
|
176
|
+
let gLoanAsset = 0n;
|
|
177
|
+
let totalDebt = 0n;
|
|
178
|
+
let totalLimit = 0n;
|
|
179
|
+
|
|
180
|
+
for (const key of principals.keys()) {
|
|
181
|
+
const principal = principals.get(key)!;
|
|
182
|
+
const assetConfig = assetsConfig.get(key)!;
|
|
183
|
+
const assetData = assetsData.get(key)!;
|
|
184
|
+
const balance =
|
|
185
|
+
principal > 0 ? (principal * assetData.sRate) / BigInt(1e12) : (principal * assetData.bRate) / BigInt(1e12);
|
|
186
|
+
if (balance > 0) {
|
|
187
|
+
const assetWorth = (balance * prices.get(key)!) / 10n ** assetConfig.decimals;
|
|
188
|
+
totalLimit += (assetWorth * assetConfig.liquidationThreshold) / MASTER_CONSTANTS.ASSET_COEFFICIENT_SCALE;
|
|
189
|
+
if (assetWorth > gCollateralValue) {
|
|
190
|
+
gCollateralValue = assetWorth;
|
|
191
|
+
gCollateralAsset = key;
|
|
192
|
+
}
|
|
193
|
+
} else if (balance < 0) {
|
|
194
|
+
const assetWorth = (-balance * prices.get(key)!) / 10n ** assetConfig.decimals;
|
|
195
|
+
totalDebt += assetWorth;
|
|
196
|
+
if (assetWorth > gLoanValue) {
|
|
197
|
+
gLoanValue = assetWorth;
|
|
198
|
+
gLoanAsset = key;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if (totalLimit < totalDebt) {
|
|
204
|
+
const gLoanAssetPrice = prices.get(gLoanAsset)!;
|
|
205
|
+
const values: bigint[] = [];
|
|
206
|
+
const gCollateralAssetConfig = assetsConfig.get(gCollateralAsset)!;
|
|
207
|
+
const gLoanAssetConfig = assetsConfig.get(gLoanAsset)!;
|
|
208
|
+
const liquidationBonus = gLoanAssetConfig.liquidationBonus;
|
|
209
|
+
const loanDecimal = 10n ** gLoanAssetConfig.decimals;
|
|
210
|
+
values.push(
|
|
211
|
+
(bigIntMax(gCollateralValue / 2n, bigIntMin(gCollateralValue, 10_000_000_000n)) *
|
|
212
|
+
loanDecimal *
|
|
213
|
+
MASTER_CONSTANTS.ASSET_COEFFICIENT_SCALE) /
|
|
214
|
+
liquidationBonus /
|
|
215
|
+
gLoanAssetPrice,
|
|
216
|
+
);
|
|
217
|
+
values.push((gLoanValue * loanDecimal) / gLoanAssetPrice);
|
|
218
|
+
|
|
219
|
+
const liquidationAmount = (bigIntMin(...values) as bigint) - 5n;
|
|
220
|
+
const gCollateralAssetPrice: bigint = prices.get(gCollateralAsset)!;
|
|
221
|
+
const collateralDecimal = 10n ** gCollateralAssetConfig.decimals;
|
|
222
|
+
let minCollateralAmount =
|
|
223
|
+
(((liquidationAmount * gLoanAssetPrice * liquidationBonus) / 10000n) * collateralDecimal) /
|
|
224
|
+
gCollateralAssetPrice /
|
|
225
|
+
loanDecimal -
|
|
226
|
+
10n;
|
|
227
|
+
minCollateralAmount = (minCollateralAmount * 97n) / 100n;
|
|
228
|
+
if (minCollateralAmount / collateralDecimal >= 1n) {
|
|
229
|
+
return {
|
|
230
|
+
greatestCollateralAsset: gCollateralAsset,
|
|
231
|
+
greatestCollateralValue: gCollateralValue,
|
|
232
|
+
greatestLoanAsset: gLoanAsset,
|
|
233
|
+
greatestLoanValue: gLoanValue,
|
|
234
|
+
totalDebt,
|
|
235
|
+
totalLimit,
|
|
236
|
+
liquidable: true,
|
|
237
|
+
liquidationAmount,
|
|
238
|
+
minCollateralAmount,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return {
|
|
244
|
+
greatestCollateralAsset: gCollateralAsset,
|
|
245
|
+
greatestCollateralValue: gCollateralValue,
|
|
246
|
+
greatestLoanAsset: gLoanAsset,
|
|
247
|
+
greatestLoanValue: gLoanValue,
|
|
248
|
+
totalDebt,
|
|
249
|
+
totalLimit,
|
|
250
|
+
liquidable: false,
|
|
251
|
+
};
|
|
252
|
+
}
|
package/src/constants.ts
CHANGED
|
@@ -1,58 +1,64 @@
|
|
|
1
|
-
import { Address, Cell, toNano } from '@ton/core';
|
|
2
|
-
import { sha256Hash } from './utils/sha256BigInt';
|
|
3
|
-
|
|
4
|
-
export const EVAA_MASTER_MAINNET = Address.parse('EQC8rUZqR_pWV1BylWUlPNBzyiTYVoBEmQkMIQDZXICfnuRr');
|
|
5
|
-
export const MAINNET_VERSION = 3;
|
|
6
|
-
export const EVAA_MASTER_TESTNET = Address.parse('kQClWdMebpK90b6imEUreQJ4M3oz8Gqwd3xkVIowR8LDX98-');
|
|
7
|
-
export const TESTNET_VERSION = 3;
|
|
8
|
-
|
|
9
|
-
export const NFT_ID = '0xfb9874544d76ca49c5db9cc3e5121e4c018bc8a2fb2bfe8f2a38c5b9963492f5';
|
|
10
|
-
|
|
11
|
-
export const ASSET_ID = {
|
|
12
|
-
TON: sha256Hash('TON'),
|
|
13
|
-
jUSDT: sha256Hash('jUSDT'),
|
|
14
|
-
jUSDC: sha256Hash('jUSDC'),
|
|
15
|
-
stTON: sha256Hash('stTON'),
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
export const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
export const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
1
|
+
import { Address, Cell, toNano } from '@ton/core';
|
|
2
|
+
import { sha256Hash } from './utils/sha256BigInt';
|
|
3
|
+
|
|
4
|
+
export const EVAA_MASTER_MAINNET = Address.parse('EQC8rUZqR_pWV1BylWUlPNBzyiTYVoBEmQkMIQDZXICfnuRr');
|
|
5
|
+
export const MAINNET_VERSION = 3;
|
|
6
|
+
export const EVAA_MASTER_TESTNET = Address.parse('kQClWdMebpK90b6imEUreQJ4M3oz8Gqwd3xkVIowR8LDX98-');
|
|
7
|
+
export const TESTNET_VERSION = 3;
|
|
8
|
+
|
|
9
|
+
export const NFT_ID = '0xfb9874544d76ca49c5db9cc3e5121e4c018bc8a2fb2bfe8f2a38c5b9963492f5';
|
|
10
|
+
|
|
11
|
+
export const ASSET_ID = {
|
|
12
|
+
TON: sha256Hash('TON'),
|
|
13
|
+
jUSDT: sha256Hash('jUSDT'),
|
|
14
|
+
jUSDC: sha256Hash('jUSDC'),
|
|
15
|
+
stTON: sha256Hash('stTON'),
|
|
16
|
+
tsTON: sha256Hash('tsTON'),
|
|
17
|
+
USDT: sha256Hash('USDT'),
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const JETTON_MASTER_ADDRESSES = {
|
|
21
|
+
jUSDT_MAINNET: Address.parse('EQBwbF0otxLyA3VrRjjC1q7i3G7LtoEpdyBjZEuNtrhC4drm'),
|
|
22
|
+
jUSDT_TESTNET: Address.parse('kQBtFVedUkg9Q7M5eMx_gxAdP5R7QCLR-3RCYQNrm_DZYr6Z'),
|
|
23
|
+
jUSDC_MAINNET: Address.parse('EQCEHZi-CLX2ghdsNbY35umR1OFODG5ySHrtK6GItMdWv7dS'),
|
|
24
|
+
jUSDC_TESTNET: Address.parse('kQCZWZD_rBZ1vrqF22aX4AZrU1a1q-YKZH_R2VlALoVNCvXd'),
|
|
25
|
+
stTON_MAINNET: Address.parse('EQBOn-1b-315ogeCl5lfPYW0ut6sjA2eq4LTdRv5vJJ1SsxX'),
|
|
26
|
+
stTON_TESTNET: Address.parse('kQCpm8ixF6STW7aidxn_Qkp4sR73msPlrduCeRZfo-Zu7dxt'),
|
|
27
|
+
tsTON_MAINNET: Address.parse('EQCRC0telhv1QESvTx24nNqUWB72zCysXQ0Bx97lVzucQ3Gr'),
|
|
28
|
+
tsTON_TESTNET: null,
|
|
29
|
+
USDT_MAINNET: Address.parse('EQD_kMQkK-A9-CQu3CdOnQUDZ2_8bY8Zrh1PvtE3hZpxvdRH'),
|
|
30
|
+
USDT_TESTNET: null,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const MASTER_CONSTANTS = {
|
|
34
|
+
FACTOR_SCALE: BigInt(1e12),
|
|
35
|
+
ASSET_COEFFICIENT_SCALE: 10000n,
|
|
36
|
+
ASSET_PRICE_SCALE: BigInt(1e8),
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const LENDING_CODE = Cell.fromBoc(
|
|
40
|
+
Buffer.from(
|
|
41
|
+
'b5ee9c72c1010e0100fd000d12182a555a6065717691969efd0114ff00f4a413f4bcf2c80b010202c8050202039f740403001ff2f8276a2687d2018fd201800f883b840051d38642c678b64e4400780e58fc10802faf07f80e59fa801e78b096664c02078067c07c100627a7978402014807060007a0ddb0c60201c709080013a0fd007a026900aa90400201200b0a0031b8e1002191960aa00b9e2ca007f4042796d225e8019203f6010201200d0c000bf7c147d2218400b9d10e86981fd201840b07f8138d809797976a2687d2029116382f970fd9178089910374daf81b619fd20182c7883b8701981684100627910eba56001797a6a6ba610fd8200e8768f76a9f6aa00cc2a32a8292878809bef2f1889f883bbcdeb86f01',
|
|
42
|
+
'hex',
|
|
43
|
+
),
|
|
44
|
+
)[0];
|
|
45
|
+
export const JETTON_WALLET_CODE = Cell.fromBase64(
|
|
46
|
+
'te6cckECEQEAAyMAART/APSkE/S88sgLAQIBYgIDAgLMBAUAG6D2BdqJofQB9IH0gahhAgHUBgcCASAICQDDCDHAJJfBOAB0NMDAXGwlRNfA/AM4PpA+kAx+gAxcdch+gAx+gAwc6m0AALTH4IQD4p+pVIgupUxNFnwCeCCEBeNRRlSILqWMUREA/AK4DWCEFlfB7y6k1nwC+BfBIQP8vCAAET6RDBwuvLhTYAIBIAoLAIPUAQa5D2omh9AH0gfSBqGAJpj8EIC8aijKkQXUEIPe7L7wndCVj5cWLpn5j9ABgJ0CgR5CgCfQEsZ4sA54tmZPaqQB8VA9M/+gD6QCHwAe1E0PoA+kD6QNQwUTahUirHBfLiwSjC//LiwlQ0QnBUIBNUFAPIUAT6AljPFgHPFszJIsjLARL0APQAywDJIPkAcHTIywLKB8v/ydAE+kD0BDH6ACDXScIA8uLEd4AYyMsFUAjPFnD6AhfLaxPMgMAgEgDQ4AnoIQF41FGcjLHxnLP1AH+gIizxZQBs8WJfoCUAPPFslQBcwjkXKRceJQCKgToIIJycOAoBS88uLFBMmAQPsAECPIUAT6AljPFgHPFszJ7VQC9ztRND6APpA+kDUMAjTP/oAUVGgBfpA+kBTW8cFVHNtcFQgE1QUA8hQBPoCWM8WAc8WzMkiyMsBEvQA9ADLAMn5AHB0yMsCygfL/8nQUA3HBRyx8uLDCvoAUaihggiYloBmtgihggiYloCgGKEnlxBJEDg3XwTjDSXXCwGAPEADXO1E0PoA+kD6QNQwB9M/+gD6QDBRUaFSSccF8uLBJ8L/8uLCBYIJMS0AoBa88uLDghB73ZfeyMsfFcs/UAP6AiLPFgHPFslxgBjIywUkzxZw+gLLaszJgED7AEATyFAE+gJYzxYBzxbMye1UgAHBSeaAYoYIQc2LQnMjLH1Iwyz9Y+gJQB88WUAfPFslxgBDIywUkzxZQBvoCFctqFMzJcfsAECQQIwB8wwAjwgCwjiGCENUydttwgBDIywVQCM8WUAT6AhbLahLLHxLLP8ly+wCTNWwh4gPIUAT6AljPFgHPFszJ7VSV6u3X',
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
export const OPCODES = {
|
|
50
|
+
SUPPLY: 0x1,
|
|
51
|
+
WITHDRAW: 0x2,
|
|
52
|
+
LIQUIDATE: 0x3,
|
|
53
|
+
JETTON_TRANSFER: 0xf8a7ea5,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const FEES = {
|
|
57
|
+
SUPPLY: toNano('0.3'),
|
|
58
|
+
WITHDRAW: toNano('0.5'),
|
|
59
|
+
SUPPLY_JETTON: toNano('0.8'),
|
|
60
|
+
SUPPLY_JETTON_FWD: toNano('0.5'),
|
|
61
|
+
LIQUIDATION: toNano('0.8'),
|
|
62
|
+
LIQUIDATION_JETTON: toNano('1'),
|
|
63
|
+
LIQUIDATION_JETTON_FWD: toNano('0.8'),
|
|
64
|
+
};
|
|
@@ -1,41 +1,55 @@
|
|
|
1
|
-
import { Address, beginCell, storeStateInit } from '@ton/core';
|
|
2
|
-
import { ASSET_ID, JETTON_MASTER_ADDRESSES, JETTON_WALLET_CODE } from '../constants';
|
|
3
|
-
|
|
4
|
-
export function getUserJettonWallet(ownerAddress: Address, assetID: bigint, network: 'mainnet' | 'testnet'): Address {
|
|
5
|
-
const builder = beginCell().storeCoins(0).storeAddress(ownerAddress);
|
|
6
|
-
switch (assetID) {
|
|
7
|
-
case ASSET_ID.jUSDT:
|
|
8
|
-
if (network === 'mainnet') {
|
|
9
|
-
builder.storeAddress(JETTON_MASTER_ADDRESSES.jUSDT_MAINNET);
|
|
10
|
-
} else {
|
|
11
|
-
builder.storeAddress(JETTON_MASTER_ADDRESSES.jUSDT_TESTNET);
|
|
12
|
-
}
|
|
13
|
-
break;
|
|
14
|
-
case ASSET_ID.jUSDC:
|
|
15
|
-
if (network === 'mainnet') {
|
|
16
|
-
builder.storeAddress(JETTON_MASTER_ADDRESSES.jUSDC_MAINNET);
|
|
17
|
-
} else {
|
|
18
|
-
builder.storeAddress(JETTON_MASTER_ADDRESSES.jUSDC_TESTNET);
|
|
19
|
-
}
|
|
20
|
-
break;
|
|
21
|
-
case ASSET_ID.stTON:
|
|
22
|
-
if (network === 'mainnet') {
|
|
23
|
-
builder.storeAddress(JETTON_MASTER_ADDRESSES.stTON_MAINNET);
|
|
24
|
-
} else {
|
|
25
|
-
builder.storeAddress(JETTON_MASTER_ADDRESSES.stTON_TESTNET);
|
|
26
|
-
}
|
|
27
|
-
break;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
1
|
+
import { Address, beginCell, storeStateInit } from '@ton/core';
|
|
2
|
+
import { ASSET_ID, JETTON_MASTER_ADDRESSES, JETTON_WALLET_CODE } from '../constants';
|
|
3
|
+
|
|
4
|
+
export function getUserJettonWallet(ownerAddress: Address, assetID: bigint, network: 'mainnet' | 'testnet'): Address {
|
|
5
|
+
const builder = beginCell().storeCoins(0).storeAddress(ownerAddress);
|
|
6
|
+
switch (assetID) {
|
|
7
|
+
case ASSET_ID.jUSDT:
|
|
8
|
+
if (network === 'mainnet') {
|
|
9
|
+
builder.storeAddress(JETTON_MASTER_ADDRESSES.jUSDT_MAINNET);
|
|
10
|
+
} else {
|
|
11
|
+
builder.storeAddress(JETTON_MASTER_ADDRESSES.jUSDT_TESTNET);
|
|
12
|
+
}
|
|
13
|
+
break;
|
|
14
|
+
case ASSET_ID.jUSDC:
|
|
15
|
+
if (network === 'mainnet') {
|
|
16
|
+
builder.storeAddress(JETTON_MASTER_ADDRESSES.jUSDC_MAINNET);
|
|
17
|
+
} else {
|
|
18
|
+
builder.storeAddress(JETTON_MASTER_ADDRESSES.jUSDC_TESTNET);
|
|
19
|
+
}
|
|
20
|
+
break;
|
|
21
|
+
case ASSET_ID.stTON:
|
|
22
|
+
if (network === 'mainnet') {
|
|
23
|
+
builder.storeAddress(JETTON_MASTER_ADDRESSES.stTON_MAINNET);
|
|
24
|
+
} else {
|
|
25
|
+
builder.storeAddress(JETTON_MASTER_ADDRESSES.stTON_TESTNET);
|
|
26
|
+
}
|
|
27
|
+
break;
|
|
28
|
+
case ASSET_ID.tsTON:
|
|
29
|
+
if (network === 'mainnet') {
|
|
30
|
+
builder.storeAddress(JETTON_MASTER_ADDRESSES.tsTON_MAINNET);
|
|
31
|
+
} else {
|
|
32
|
+
builder.storeAddress(JETTON_MASTER_ADDRESSES.tsTON_TESTNET);
|
|
33
|
+
}
|
|
34
|
+
break;
|
|
35
|
+
case ASSET_ID.USDT:
|
|
36
|
+
if (network === 'mainnet') {
|
|
37
|
+
builder.storeAddress(JETTON_MASTER_ADDRESSES.USDT_MAINNET);
|
|
38
|
+
} else {
|
|
39
|
+
builder.storeAddress(JETTON_MASTER_ADDRESSES.USDT_TESTNET);
|
|
40
|
+
}
|
|
41
|
+
break;
|
|
42
|
+
default:
|
|
43
|
+
throw new Error('Unsupported asset');
|
|
44
|
+
}
|
|
45
|
+
const data = builder.storeRef(JETTON_WALLET_CODE).endCell();
|
|
46
|
+
const stateInit = beginCell()
|
|
47
|
+
.store(
|
|
48
|
+
storeStateInit({
|
|
49
|
+
code: JETTON_WALLET_CODE,
|
|
50
|
+
data: data,
|
|
51
|
+
}),
|
|
52
|
+
)
|
|
53
|
+
.endCell();
|
|
54
|
+
return new Address(0, stateInit.hash());
|
|
55
|
+
}
|
package/dist/types/Redstone.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export type CoinData = {
|
|
2
|
-
id: string;
|
|
3
|
-
symbol: string;
|
|
4
|
-
provider: string;
|
|
5
|
-
value: number;
|
|
6
|
-
liteEvmSignature: string;
|
|
7
|
-
permawebTx: string;
|
|
8
|
-
version: string;
|
|
9
|
-
source: {
|
|
10
|
-
coingecko: number;
|
|
11
|
-
};
|
|
12
|
-
timestamp: number;
|
|
13
|
-
minutes: number;
|
|
14
|
-
providerPublicKey: string;
|
|
15
|
-
};
|
package/dist/types/Redstone.js
DELETED