@evaafi/sdk 0.6.1 → 0.6.2-b

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 (73) hide show
  1. package/LICENSE.md +7 -0
  2. package/README.md +2 -1
  3. package/dist/api/liquidation.js +1 -3
  4. package/dist/api/math.d.ts +10 -1
  5. package/dist/api/math.js +45 -6
  6. package/dist/api/parser.js +49 -27
  7. package/dist/api/prices.d.ts +5 -2
  8. package/dist/api/prices.js +35 -13
  9. package/dist/constants/assets.d.ts +8 -0
  10. package/dist/constants/assets.js +31 -1
  11. package/dist/constants/general.d.ts +5 -2
  12. package/dist/constants/general.js +12 -22
  13. package/dist/constants/pools.d.ts +1 -0
  14. package/dist/constants/pools.js +19 -3
  15. package/dist/contracts/MasterContract.d.ts +5 -0
  16. package/dist/contracts/MasterContract.js +6 -0
  17. package/dist/index.d.ts +4 -4
  18. package/dist/index.js +10 -2
  19. package/dist/prices/Prices.d.ts +9 -0
  20. package/dist/prices/Prices.js +43 -0
  21. package/dist/prices/PricesCollector.d.ts +12 -0
  22. package/dist/prices/PricesCollector.js +123 -0
  23. package/dist/prices/Types.d.ts +33 -0
  24. package/dist/prices/Types.js +11 -0
  25. package/dist/prices/constants.d.ts +1 -0
  26. package/dist/prices/constants.js +4 -0
  27. package/dist/prices/index.d.ts +6 -0
  28. package/dist/prices/index.js +22 -0
  29. package/dist/prices/sources/Backend.d.ts +13 -0
  30. package/dist/prices/sources/Backend.js +52 -0
  31. package/dist/prices/sources/Icp.d.ts +10 -0
  32. package/dist/prices/sources/Icp.js +23 -0
  33. package/dist/prices/sources/Iota.d.ts +39 -0
  34. package/dist/prices/sources/Iota.js +49 -0
  35. package/dist/prices/sources/PriceSource.d.ts +14 -0
  36. package/dist/prices/sources/PriceSource.js +26 -0
  37. package/dist/prices/sources/index.d.ts +4 -0
  38. package/dist/prices/sources/index.js +20 -0
  39. package/dist/prices/utils.d.ts +23 -0
  40. package/dist/prices/utils.js +148 -0
  41. package/dist/types/Master.d.ts +2 -1
  42. package/dist/types/User.d.ts +11 -1
  43. package/dist/utils/userJettonWallet.js +42 -43
  44. package/dist/utils/utils.d.ts +1 -0
  45. package/dist/utils/utils.js +5 -1
  46. package/package.json +11 -9
  47. package/src/api/liquidation.ts +0 -1
  48. package/src/api/math.ts +66 -5
  49. package/src/api/parser.ts +56 -31
  50. package/src/api/prices.ts +20 -7
  51. package/src/constants/assets.ts +57 -0
  52. package/src/constants/general.ts +11 -23
  53. package/src/constants/pools.ts +21 -5
  54. package/src/contracts/MasterContract.ts +8 -1
  55. package/src/index.ts +9 -2
  56. package/src/prices/Prices.ts +32 -0
  57. package/src/prices/PricesCollector.ts +139 -0
  58. package/src/prices/Types.ts +44 -0
  59. package/src/prices/constants.ts +1 -0
  60. package/src/prices/index.ts +6 -0
  61. package/src/prices/sources/Backend.ts +62 -0
  62. package/src/prices/sources/Icp.ts +27 -0
  63. package/src/prices/sources/Iota.ts +90 -0
  64. package/src/prices/sources/PriceSource.ts +35 -0
  65. package/src/prices/sources/index.ts +4 -0
  66. package/src/prices/utils.ts +170 -0
  67. package/src/types/Master.ts +3 -2
  68. package/src/types/User.ts +13 -3
  69. package/src/utils/userJettonWallet.ts +43 -53
  70. package/src/utils/utils.ts +5 -1
  71. package/src/config.ts +0 -1
  72. package/src/types/Common.ts +0 -16
  73. package/src/utils/priceUtils.ts +0 -177
@@ -0,0 +1,44 @@
1
+ import { Cell, Dictionary } from '@ton/core';
2
+
3
+ /**
4
+ * Configuration for price source endpoints.
5
+ */
6
+ export type PriceSourcesConfig = {
7
+ /** Endpoints for backend price data */
8
+ backendEndpoints: string[];
9
+
10
+ /** Endpoints for IOTA price data */
11
+ iotaEndpoints: string[];
12
+
13
+ /** Endpoints for ICP price data */
14
+ icpEndpoints: string[];
15
+ };
16
+
17
+ /**
18
+ * Default configuration for price source endpoints.
19
+ */
20
+ export const DefaultPriceSourcesConfig: PriceSourcesConfig = {
21
+ backendEndpoints: ['evaa.space'],
22
+ iotaEndpoints: ['api.stardust-mainnet.iotaledger.net'],
23
+ icpEndpoints: ['6khmc-aiaaa-aaaap-ansfq-cai.raw.icp0.io'],
24
+ }
25
+
26
+ export type RawPriceData = {
27
+ dict: Dictionary<bigint, bigint>;
28
+ dataCell: Cell;
29
+ oracleId: number;
30
+ signature: Buffer;
31
+ pubkey: Buffer;
32
+ timestamp: number;
33
+ };
34
+
35
+
36
+ export type PriceData = {
37
+ dict: Dictionary<bigint, bigint>;
38
+ dataCell: Cell;
39
+ };
40
+
41
+ export type OraclePricesData = {
42
+ timestamp: number,
43
+ prices: Dictionary<bigint, bigint>
44
+ }
@@ -0,0 +1 @@
1
+ export const TTL_ORACLE_DATA_SEC = 120;
@@ -0,0 +1,6 @@
1
+ export * from './sources';
2
+ export * from './Types';
3
+ export * from './constants';
4
+ export * from './utils';
5
+ export * from './Prices';
6
+ export * from './PricesCollector';
@@ -0,0 +1,62 @@
1
+ import { beginCell, Cell, Dictionary } from "@ton/core";
2
+ import { RawPriceData } from "..";
3
+ import { PriceSource } from "./PriceSource";
4
+
5
+ export class BackendPriceSource extends PriceSource {
6
+ protected priceSourceName: string = 'BackendPriceSource';
7
+
8
+ async getPrices(): Promise<RawPriceData[]> {
9
+ const data = await this.loadOracleData();
10
+ return data.map(outputData => this.parsePrices(outputData));
11
+ }
12
+
13
+ async loadOracleData(): Promise<OutputData[]> {
14
+ let response = await fetch(`https://${this._endpoint}/api/prices`, {
15
+ headers: { accept: 'application/json' },
16
+ signal: AbortSignal.timeout(5000)
17
+ });
18
+
19
+ const resp = (await response.json());
20
+ const data = resp as Record<string, string>;
21
+ let outputData: OutputData[] = [];
22
+
23
+ for (const nft of this._nfts) {
24
+ outputData.push({ oracleId: nft.id, data: data[nft.address] })
25
+ }
26
+
27
+ return outputData;
28
+ }
29
+
30
+
31
+ parsePrices(outputData: OutputData): RawPriceData {
32
+ try {
33
+ //console.debug('outputData', outputData);
34
+ //console.debug(outputData.data.replace('0x', '').replace(/[0-9a-f]{2}/g, '%$&'))
35
+ const data = JSON.parse(
36
+ decodeURIComponent(outputData.data.replace('0x', '').replace(/[0-9a-f]{2}/g, '%$&')),
37
+ );
38
+ const pricesCell = Cell.fromBoc(Buffer.from(data['packedPrices'], 'hex'))[0];
39
+ const signature = Buffer.from(data['signature'], 'hex');
40
+ const publicKey = Buffer.from(data['publicKey'], 'hex');
41
+ const timestamp = Number(data['timestamp']);
42
+
43
+ return {
44
+ dict: pricesCell.beginParse().loadRef().beginParse().loadDictDirect(Dictionary.Keys.BigUint(256), Dictionary.Values.BigVarUint(4)),
45
+ dataCell: beginCell().storeRef(pricesCell).storeBuffer(signature).endCell(),
46
+ oracleId: outputData.oracleId,
47
+ signature: signature,
48
+ pubkey: publicKey,
49
+ timestamp: timestamp,
50
+ };
51
+ }
52
+ catch (error) {
53
+ //console.debug(`Price source error ${this.priceSourceName} ${outputData.oracleId} ${outputData.data} ${error}`);
54
+ throw error;
55
+ }
56
+ }
57
+ }
58
+
59
+ type OutputData = {
60
+ oracleId: number,
61
+ data: string
62
+ };
@@ -0,0 +1,27 @@
1
+ import { BackendPriceSource } from ".";
2
+
3
+ export class IcpPriceSource extends BackendPriceSource {
4
+ protected priceSourceName: string = 'IcpPriceSource';
5
+
6
+ async loadOracleData(): Promise<OutputData[]> {
7
+ let response = await fetch(`https://${this._endpoint}/prices`, {
8
+ headers: { accept: 'application/json' },
9
+ signal: AbortSignal.timeout(5000)
10
+ });
11
+
12
+ const data = (await response.json()) as Record<string, string>;
13
+
14
+ let outputData: OutputData[] = [];
15
+
16
+ for (const nft of this._nfts) {
17
+ outputData.push({oracleId: nft.id, data: data[nft.address] })
18
+ }
19
+
20
+ return outputData;
21
+ }
22
+ }
23
+
24
+ type OutputData = {
25
+ oracleId: number,
26
+ data: string
27
+ };
@@ -0,0 +1,90 @@
1
+ import { beginCell, Cell, Dictionary } from "@ton/core";
2
+ import { PriceSource } from "./PriceSource";
3
+ import { RawPriceData } from "..";
4
+
5
+ export class IotaPriceSource extends PriceSource {
6
+ protected priceSourceName: string = 'IotaPriceSource';
7
+
8
+ async getPrices(): Promise<RawPriceData[]> {
9
+ return await Promise.all(this.nfts.map(nft => this.loadOracleData(nft.address)
10
+ .then(x => this.parsePrices(x, nft.id))));
11
+ }
12
+
13
+ async loadOracleData(oracleNftId: String): Promise<OutputData> {
14
+ let result = await fetch(`https://${this._endpoint}/api/indexer/v1/outputs/nft/${oracleNftId}`, {
15
+ headers: { accept: 'application/json' },
16
+ signal: AbortSignal.timeout(5000)
17
+ });
18
+ let outputId = (await result.json()) as NftData;
19
+
20
+ result = await fetch(`https://${this._endpoint}/api/core/v2/outputs/${outputId.items[0]}`, {
21
+ headers: { accept: 'application/json' },
22
+ signal: AbortSignal.timeout(5000)
23
+ });
24
+ return (await result.json() as OutputData);
25
+ }
26
+
27
+
28
+ parsePrices(outputData: OutputData, oracleId: number): RawPriceData {
29
+ const data = JSON.parse(
30
+ decodeURIComponent(outputData.output.features[0].data.replace('0x', '').replace(/[0-9a-f]{2}/g, '%$&')),
31
+ );
32
+
33
+ try {
34
+ const pricesCell = 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
+
39
+ return {
40
+ dict: pricesCell.beginParse().loadRef().beginParse().loadDictDirect(Dictionary.Keys.BigUint(256), Dictionary.Values.BigVarUint(4)),
41
+ dataCell: beginCell().storeRef(pricesCell).storeBuffer(signature).endCell(),
42
+ oracleId: oracleId,
43
+ signature: signature,
44
+ pubkey: publicKey,
45
+ timestamp: timestamp,
46
+ };
47
+ }
48
+ catch (error) {
49
+ //console.debug(`Price source error ${this.priceSourceName} ${outputData} ${error}`);
50
+ throw error;
51
+ }
52
+ }
53
+ }
54
+
55
+ type NftData = {
56
+ ledgerIndex: number;
57
+ pageSize: number;
58
+ items: string[];
59
+ };
60
+
61
+ type OutputData = {
62
+ metadata: {
63
+ blockId: string;
64
+ transactionId: string;
65
+ outputIndex: number;
66
+ isSpent: boolean;
67
+ milestoneIndexSpent: number;
68
+ milestoneTimestampSpent: number;
69
+ transactionIdSpent: string;
70
+ milestoneIndexBooked: number;
71
+ milestoneTimestampBooked: number;
72
+ ledgerIndex: number;
73
+ };
74
+ output: {
75
+ type: number;
76
+ amount: string;
77
+ nftId: string;
78
+ unlockConditions: {
79
+ type: number;
80
+ address: {
81
+ type: number;
82
+ pubKeyHash: string;
83
+ };
84
+ }[];
85
+ features: {
86
+ type: number;
87
+ data: string;
88
+ }[];
89
+ };
90
+ };
@@ -0,0 +1,35 @@
1
+ import { RawPriceData } from "..";
2
+ import { OracleNFT } from "../../types/Master";
3
+
4
+ export abstract class PriceSource {
5
+ protected priceSourceName: string = 'BackendPriceSource';
6
+ protected _endpoint: string;
7
+ protected _nfts: OracleNFT[];
8
+
9
+ constructor(endpoint: string, nfts: OracleNFT[]) {
10
+ this._endpoint = endpoint;
11
+ this._nfts = nfts;
12
+ }
13
+
14
+ get sourceName() {
15
+ return this.priceSourceName;
16
+ }
17
+
18
+ get endpoint() {
19
+ return this._endpoint;
20
+ }
21
+
22
+ get nfts() {
23
+ return this._nfts;
24
+ }
25
+
26
+ set endpoint(endpoint: string) {
27
+ this._endpoint = endpoint;
28
+ }
29
+
30
+ set nfts(nfts: OracleNFT[]) {
31
+ this._nfts = nfts;
32
+ }
33
+
34
+ abstract getPrices(): Promise<RawPriceData[]>;
35
+ }
@@ -0,0 +1,4 @@
1
+ export * from './Backend';
2
+ export * from './Iota';
3
+ export * from './Icp';
4
+ export * from './PriceSource';
@@ -0,0 +1,170 @@
1
+ import { beginCell, Cell, Dictionary, Slice } from "@ton/core";
2
+ import { BackendPriceSource, DefaultPriceSourcesConfig, IcpPriceSource, IotaPriceSource, MAINNET_POOL_CONFIG, OraclePricesData, PriceData, PriceSource, PriceSourcesConfig, RawPriceData, TTL_ORACLE_DATA_SEC } from "..";
3
+ import { Oracle, OracleNFT, PoolConfig } from "../types/Master";
4
+ import { convertToMerkleProof, generateMerkleProofDirect } from "../utils/merkleProof";
5
+ import { signVerify } from "@ton/crypto";
6
+
7
+ export function verifyPricesTimestamp() {
8
+ return function(priceData: RawPriceData): boolean {
9
+ const timestamp = Date.now() / 1000;
10
+ const pricesTime = priceData.timestamp;
11
+
12
+ //console.debug('timestamp - pricesTime, pricesTime', timestamp - pricesTime, pricesTime);
13
+ return timestamp - pricesTime < TTL_ORACLE_DATA_SEC;
14
+ }
15
+ }
16
+
17
+ export function verifyPricesSign(nfts: OracleNFT[]) {
18
+ return function(priceData: RawPriceData): boolean {
19
+ if (nfts.findIndex(x => x.pubkey.equals(priceData.pubkey)) == -1) {
20
+ //console.debug('[verifyPricesSign] nft not found');
21
+ return false;
22
+ }
23
+
24
+ return verifyRawPriceDataSign(priceData)
25
+ }
26
+ }
27
+
28
+ /* export function verifyPricesAssets(assets: PoolAssetsConfig) {
29
+ return function(priceData: RawPriceData): boolean {
30
+ for (const asset of assets) {
31
+ if(!priceData.dict.has(asset.assetId)) {
32
+ return false;
33
+ }
34
+ }
35
+ return true;
36
+ }
37
+ } */
38
+
39
+ export function getMedianPrice(pricesData: PriceData[], asset: bigint): bigint | null {
40
+ try {
41
+ const usingPrices = pricesData.filter(x => x.dict.has(asset));
42
+ const sorted = usingPrices.map(x => x.dict.get(asset)!).sort((a, b) => Number(a) - Number(b));
43
+
44
+ if (sorted.length == 0) {
45
+ return null;
46
+ }
47
+
48
+ const mid = Math.floor(sorted.length / 2);
49
+ if (sorted.length % 2 === 0) {
50
+ return (sorted[mid - 1] + sorted[mid]) / 2n;
51
+ } else {
52
+ return sorted[mid];
53
+ }
54
+ }
55
+ catch {
56
+ return null;
57
+ }
58
+ }
59
+
60
+ export function packAssetsData(assetsData: {assetId: bigint, medianPrice: bigint}[]): Cell {
61
+ if (assetsData.length == 0) {
62
+ throw new Error("No assets data to pack");
63
+ }
64
+ return assetsData.reduceRight(
65
+ (acc: Cell | null, {assetId, medianPrice}) => beginCell()
66
+ .storeUint(assetId, 256)
67
+ .storeCoins(medianPrice)
68
+ .storeMaybeRef(acc)
69
+ .endCell(),
70
+ null
71
+ )!;
72
+ }
73
+
74
+ export function packPrices(assetsDataCell: Cell, oraclesDataCell: Cell): Cell {
75
+ let pricesCell = beginCell()
76
+ .storeRef(assetsDataCell)
77
+ .storeRef(oraclesDataCell)
78
+ .endCell();
79
+ return pricesCell;
80
+ }
81
+
82
+ export function createOracleDataProof(oracle: Oracle,
83
+ data: OraclePricesData,
84
+ signature: Buffer,
85
+ assets: Array<bigint>): Slice {
86
+ let prunedDict = generateMerkleProofDirect(data.prices, assets, Dictionary.Keys.BigUint(256));
87
+ let prunedData = beginCell().storeUint(data.timestamp, 32).storeMaybeRef(prunedDict).endCell();
88
+ let merkleProof = convertToMerkleProof(prunedData);
89
+ let oracleDataProof = beginCell().storeUint(oracle.id, 32).storeRef(merkleProof).storeBuffer(signature).asSlice();
90
+ return oracleDataProof;
91
+ }
92
+
93
+ export function packOraclesData(oraclesData: {oracle: Oracle, data: OraclePricesData, signature: Buffer}[],
94
+ assets: Array<bigint>): Cell {
95
+ if (oraclesData.length == 0) {
96
+ throw new Error("no oracles data to pack");
97
+ }
98
+ let proofs = oraclesData.sort((d1, d2) => d1.oracle.id - d2.oracle.id).map(
99
+ ({oracle, data, signature}) => createOracleDataProof(oracle, data, signature, assets)
100
+ );
101
+ return proofs.reduceRight((acc: Cell | null, val) => beginCell().storeSlice(val).storeMaybeRef(acc).endCell(), null)!;
102
+ }
103
+
104
+ export function sumDicts(result: Dictionary<bigint, bigint>, addendum: Dictionary<bigint, bigint>) {
105
+ for (const key of addendum.keys()) {
106
+ const current = result.get(key)!;
107
+ const value = addendum.get(key)!;
108
+
109
+ if (current === undefined) {
110
+ result.set(key, value);
111
+ continue;
112
+ }
113
+
114
+ result.set(key, current + value);
115
+ }
116
+ }
117
+
118
+ export function generatePriceSources(config: PriceSourcesConfig = DefaultPriceSourcesConfig, nfts: OracleNFT[] = MAINNET_POOL_CONFIG.oracles) {
119
+ let result: PriceSource[] = config.backendEndpoints.map(x => new BackendPriceSource(x, nfts));
120
+
121
+ result.push(...config.icpEndpoints.map(x => new IcpPriceSource(x, nfts)));
122
+ result.push(...config.iotaEndpoints.map(x => new IotaPriceSource(x, nfts)));
123
+
124
+ return result;
125
+ }
126
+
127
+ export async function collectAndFilterPrices(priceSource: PriceSource, poolConfig: PoolConfig): Promise<RawPriceData[]> {
128
+ const prices = await priceSource.getPrices();
129
+
130
+ //console.debug('[FILTERING] before filtering prices len ', priceSource.sourceName, prices.length);
131
+ return await (async () => {
132
+ const acceptedPrices: RawPriceData[] = prices.filter(
133
+ price => verifyPricesTimestamp()(price) && verifyPricesSign(poolConfig.oracles)(price)
134
+ );
135
+
136
+ //console.debug('[FILTERING] after filtering prices len ', priceSource.sourceName, acceptedPrices.length);
137
+
138
+ if (acceptedPrices.length < poolConfig.minimalOracles) {
139
+ throw new Error("Prices are outdated");
140
+ }
141
+
142
+ return acceptedPrices;
143
+ })();
144
+ }
145
+
146
+ export function unpackMedianPrices(pricesCell: Cell): Dictionary<bigint, bigint> | undefined {
147
+ if (!pricesCell) return undefined;
148
+ const slice = pricesCell.beginParse();
149
+ let assetCell: Cell | null = slice.loadRef();
150
+ const res = Dictionary.empty<bigint, bigint>();
151
+ while (assetCell != Cell.EMPTY && assetCell !== null) {
152
+ const slice = assetCell.beginParse();
153
+ const assetId = slice.loadUintBig(256);
154
+ const medianPrice = slice.loadCoins();
155
+ res.set(assetId, medianPrice);
156
+ assetCell = slice.loadMaybeRef();
157
+ }
158
+ return res;
159
+ }
160
+
161
+ export function verifyRawPriceDataSign(priceData: RawPriceData): boolean {
162
+ const message = priceData.dataCell.refs[0].hash()
163
+ const signature = priceData.signature;
164
+ const publicKey = priceData.pubkey;
165
+
166
+ const valid: boolean = signVerify(message, signature, publicKey);
167
+ //console.debug('[verifyRawPriceDataSign] sign is valid:', valid);
168
+
169
+ return valid;
170
+ }
@@ -89,7 +89,7 @@ export type AssetData = {
89
89
  balance: bigint;
90
90
  trackingSupplyIndex: bigint;
91
91
  trackingBorrowIndex: bigint;
92
- awaitedSupply?: bigint;
92
+ awaitedSupply: bigint;
93
93
  };
94
94
 
95
95
  export type AssetInterest = {
@@ -126,7 +126,8 @@ export type AgregatedBalances = {
126
126
 
127
127
  export type OracleNFT = {
128
128
  id: number,
129
- address: string
129
+ address: string,
130
+ pubkey: Buffer
130
131
  }
131
132
 
132
133
  export type Oracle = {
package/src/types/User.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { Address, Cell, Dictionary } from '@ton/core';
2
- import { AssetConfig, ExtendedAssetData, ExtendedAssetsConfig, ExtendedAssetsData, MasterConfig, MasterConstants, PoolAssetConfig, PoolConfig } from './Master';
1
+ import { Address, BitBuilder, Cell, Dictionary } from '@ton/core';
2
+ import { AssetConfig, AssetData, ExtendedAssetData, ExtendedAssetsConfig, ExtendedAssetsData, MasterConfig, MasterConstants, PoolAssetConfig, PoolConfig } from './Master';
3
3
 
4
4
  export enum BalanceType {
5
5
  supply = 'supply',
@@ -38,6 +38,7 @@ export type UserLiteData = {
38
38
  masterAddress: Address;
39
39
  ownerAddress: Address;
40
40
  principals: Dictionary<bigint, bigint>;
41
+ realPrincipals: Dictionary<bigint, bigint>; // principals before applying dusts
41
42
  state: number;
42
43
  balances: Dictionary<bigint, UserBalance>;
43
44
  trackingSupplyIndex: bigint;
@@ -47,6 +48,7 @@ export type UserLiteData = {
47
48
  rewards: Dictionary<bigint, UserRewards>;
48
49
  backupCell1: Cell | null;
49
50
  backupCell2: Cell | null;
51
+ fullyParsed: boolean;
50
52
  };
51
53
 
52
54
  export type UserDataActive = UserLiteData & {
@@ -59,8 +61,8 @@ export type UserDataActive = UserLiteData & {
59
61
  limitUsedPercent: number;
60
62
  limitUsed: bigint;
61
63
  healthFactor: number;
62
-
63
64
  liquidationData: LiquidationData;
65
+ havePrincipalWithoutPrice: boolean;
64
66
  };
65
67
 
66
68
  export type UserDataInactive = {
@@ -99,3 +101,11 @@ export type PredictHealthFactorArgs = {
99
101
  assetsConfig: ExtendedAssetsConfig;
100
102
  poolConfig: PoolConfig;
101
103
  };
104
+
105
+ export type PredictAPYArgs = {
106
+ balanceChangeType: BalanceChangeType;
107
+ amount: bigint; // always positive
108
+ assetData: AssetData;
109
+ assetConfig: AssetConfig;
110
+ masterConstants: MasterConstants;
111
+ };
@@ -2,66 +2,56 @@ import { Address, beginCell, Cell, storeStateInit } from '@ton/core';
2
2
  import { PoolAssetConfig } from '../types/Master';
3
3
  import { UNDEFINED_ASSET } from '../constants/assets';
4
4
 
5
+ function getUserJettonData(ownerAddress: Address, assetName: string, jettonWalletCode: Cell, jettonMasterAddress: Address) {
6
+ switch (assetName) {
7
+ case 'uTON':
8
+ return beginCell()
9
+ .storeCoins(0)
10
+ .storeUint(0, 64)
11
+ .storeAddress(ownerAddress)
12
+ .storeAddress(jettonMasterAddress)
13
+ .storeRef(jettonWalletCode)
14
+ .endCell();
15
+ case 'DOGS':
16
+ case 'NOT':
17
+ case 'USDT':
18
+ return beginCell()
19
+ .storeUint(0, 4)
20
+ .storeCoins(0)
21
+ .storeAddress(ownerAddress)
22
+ .storeAddress(jettonMasterAddress)
23
+ .endCell();
24
+ case 'tsTON':
25
+ return beginCell()
26
+ .storeCoins(0)
27
+ .storeAddress(ownerAddress)
28
+ .storeAddress(jettonMasterAddress)
29
+ .storeRef(jettonWalletCode)
30
+ .storeCoins(0)
31
+ .storeUint(0, 48)
32
+ .endCell();
33
+ default:
34
+ return beginCell().storeCoins(0)
35
+ .storeAddress(ownerAddress)
36
+ .storeAddress(jettonMasterAddress)
37
+ .storeRef(jettonWalletCode)
38
+ .endCell();
39
+
40
+ }
41
+ }
5
42
  export function getUserJettonWallet(ownerAddress: Address, poolAssetConfig: PoolAssetConfig) {
6
- if (poolAssetConfig.name == 'TON' || poolAssetConfig.assetId === UNDEFINED_ASSET.assetId) {
43
+ const assetName = poolAssetConfig.name;
44
+ if (assetName == 'TON' || poolAssetConfig.assetId === UNDEFINED_ASSET.assetId) {
7
45
  throw new Error(`Cant getUserJettonWallet for ${poolAssetConfig.name} asset`)
8
46
  }
9
- const jettonMasterAddress = poolAssetConfig.jettonMasterAddress;
10
- const jettonWalletCode = poolAssetConfig.jettonWalletCode;
11
-
12
- if (poolAssetConfig.name === 'USDT') {
13
- const lib_prep = beginCell().storeUint(2, 8).storeBuffer(jettonWalletCode.hash()).endCell();
14
- const jwallet_code = new Cell({ exotic: true, bits: lib_prep.bits, refs: lib_prep.refs });
15
-
16
- const jettonData = beginCell()
17
- .storeUint(0, 4)
18
- .storeCoins(0)
19
- .storeAddress(ownerAddress)
20
- .storeAddress(jettonMasterAddress)
21
- .endCell();
22
-
23
- const stateInit = beginCell()
24
- .store(
25
- storeStateInit({
26
- code: jwallet_code,
27
- data: jettonData
28
- })
29
- )
30
- .endCell();
31
- return new Address(0, stateInit.hash());
32
- }
47
+ let jettonWalletCode = poolAssetConfig.jettonWalletCode;
33
48
 
34
- if (poolAssetConfig.name === 'tsTON') {
49
+ if (assetName === 'USDT' || assetName === 'tsTON') {
35
50
  const lib_prep = beginCell().storeUint(2, 8).storeBuffer(jettonWalletCode.hash()).endCell();
36
- const jwallet_code = new Cell({ exotic: true, bits: lib_prep.bits, refs: lib_prep.refs });
37
-
38
- const jettonData = beginCell()
39
- .storeCoins(0)
40
- .storeAddress(ownerAddress)
41
- .storeAddress(jettonMasterAddress)
42
- .storeRef(jwallet_code)
43
- .storeCoins(0)
44
- .storeUint(0, 48)
45
- .endCell();
46
-
47
- const stateInit = beginCell()
48
- .store(
49
- storeStateInit({
50
- code: jwallet_code,
51
- data: jettonData
52
- })
53
- )
54
- .endCell();
55
-
56
- return new Address(0, stateInit.hash());
51
+ jettonWalletCode = new Cell({ exotic: true, bits: lib_prep.bits, refs: lib_prep.refs });
57
52
  }
58
53
 
59
- const jettonData = beginCell()
60
- .storeCoins(0)
61
- .storeAddress(ownerAddress)
62
- .storeAddress(jettonMasterAddress)
63
- .storeRef(jettonWalletCode)
64
- .endCell();
54
+ const jettonData = getUserJettonData(ownerAddress, assetName, jettonWalletCode, poolAssetConfig.jettonMasterAddress);
65
55
 
66
56
  const stateInit = beginCell()
67
57
  .store(
@@ -7,4 +7,8 @@ export function isTonAsset(asset: PoolAssetConfig) {
7
7
 
8
8
  export function isTonAssetId(assetId: bigint) {
9
9
  return assetId === ASSET_ID.TON;
10
- }
10
+ }
11
+
12
+ export function delay(ms: number) {
13
+ return new Promise(resolve => setTimeout(resolve, ms));
14
+ }
package/src/config.ts DELETED
@@ -1 +0,0 @@
1
- export const TTL_ORACLE_DATA_SEC = 120; // todo back to 120
@@ -1,16 +0,0 @@
1
- import { Cell, Dictionary } from '@ton/core';
2
-
3
- export type RawPriceData = {
4
- dict: Dictionary<bigint, bigint>;
5
- dataCell: Cell;
6
- oracleId: number;
7
- signature: Buffer;
8
- pubkey: Buffer;
9
- timestamp: number;
10
- };
11
-
12
-
13
- export type PriceData = {
14
- dict: Dictionary<bigint, bigint>;
15
- dataCell: Cell;
16
- };