@evaafi/sdk 0.6.4 → 0.9.0-a

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 (122) hide show
  1. package/dist/api/feeds.d.ts +31 -0
  2. package/dist/api/feeds.js +73 -0
  3. package/dist/api/liquidation.js +1 -1
  4. package/dist/api/math.js +1 -1
  5. package/dist/api/parser.d.ts +4 -2
  6. package/dist/api/parser.js +39 -18
  7. package/dist/api/parsers/AbstractOracleParser.d.ts +11 -0
  8. package/dist/api/parsers/AbstractOracleParser.js +9 -0
  9. package/dist/api/parsers/ClassicOracleParser.d.ts +10 -0
  10. package/dist/api/parsers/ClassicOracleParser.js +16 -0
  11. package/dist/api/parsers/PythOracleParser.d.ts +18 -0
  12. package/dist/api/parsers/PythOracleParser.js +22 -0
  13. package/dist/api/parsers/index.d.ts +3 -0
  14. package/dist/api/parsers/index.js +19 -0
  15. package/dist/api/prices.d.ts +7 -6
  16. package/dist/api/prices.js +37 -46
  17. package/dist/constants/assets/assetId.d.ts +22 -0
  18. package/dist/constants/assets/assetId.js +29 -0
  19. package/dist/constants/assets/index.d.ts +3 -0
  20. package/dist/constants/assets/index.js +19 -0
  21. package/dist/constants/{assets.d.ts → assets/mainnet.d.ts} +3 -29
  22. package/dist/constants/{assets.js → assets/mainnet.js} +30 -79
  23. package/dist/constants/assets/testnet.d.ts +14 -0
  24. package/dist/constants/assets/testnet.js +54 -0
  25. package/dist/constants/general/index.d.ts +65 -0
  26. package/dist/constants/general/index.js +93 -0
  27. package/dist/constants/general/mainnet.d.ts +24 -0
  28. package/dist/constants/{general.js → general/mainnet.js} +38 -60
  29. package/dist/constants/general/testnet.d.ts +12 -0
  30. package/dist/constants/general/testnet.js +15 -0
  31. package/dist/constants/index.d.ts +3 -0
  32. package/dist/constants/index.js +19 -0
  33. package/dist/constants/pools/index.d.ts +2 -0
  34. package/dist/constants/pools/index.js +18 -0
  35. package/dist/constants/pools/mainnet.d.ts +14 -0
  36. package/dist/constants/pools/mainnet.js +145 -0
  37. package/dist/constants/pools/testnet.d.ts +9 -0
  38. package/dist/constants/pools/testnet.js +57 -0
  39. package/dist/contracts/AbstractMaster.d.ts +185 -0
  40. package/dist/contracts/AbstractMaster.js +179 -0
  41. package/dist/contracts/ClassicMaster.d.ts +34 -0
  42. package/dist/contracts/ClassicMaster.js +87 -0
  43. package/dist/contracts/PythMaster.d.ts +62 -0
  44. package/dist/contracts/PythMaster.js +179 -0
  45. package/dist/contracts/UserContract.d.ts +1 -7
  46. package/dist/contracts/UserContract.js +1 -19
  47. package/dist/contracts/index.d.ts +5 -0
  48. package/dist/contracts/index.js +21 -0
  49. package/dist/index.d.ts +14 -14
  50. package/dist/index.js +20 -60
  51. package/dist/prices/Oracle.interface.d.ts +9 -0
  52. package/dist/prices/Oracle.interface.js +2 -0
  53. package/dist/prices/Prices.d.ts +5 -3
  54. package/dist/prices/Prices.js +13 -3
  55. package/dist/prices/PricesCollector.d.ts +17 -7
  56. package/dist/prices/PricesCollector.js +67 -51
  57. package/dist/prices/PythCollector.d.ts +22 -0
  58. package/dist/prices/PythCollector.js +217 -0
  59. package/dist/prices/Types.d.ts +17 -1
  60. package/dist/prices/Types.js +8 -1
  61. package/dist/prices/index.d.ts +4 -3
  62. package/dist/prices/index.js +4 -3
  63. package/dist/prices/sources/Backend.d.ts +5 -4
  64. package/dist/prices/sources/Backend.js +16 -13
  65. package/dist/prices/sources/Icp.d.ts +2 -1
  66. package/dist/prices/sources/Icp.js +12 -9
  67. package/dist/prices/sources/PriceSource.d.ts +7 -6
  68. package/dist/prices/utils.d.ts +10 -8
  69. package/dist/prices/utils.js +32 -46
  70. package/dist/types/Master.d.ts +10 -30
  71. package/dist/types/Master.js +3 -0
  72. package/dist/utils/userJettonWallet.js +0 -8
  73. package/dist/utils/utils.d.ts +8 -1
  74. package/dist/utils/utils.js +31 -2
  75. package/package.json +4 -3
  76. package/src/api/feeds.ts +90 -0
  77. package/src/api/liquidation.ts +1 -1
  78. package/src/api/math.ts +1 -1
  79. package/src/api/parser.ts +100 -38
  80. package/src/api/parsers/AbstractOracleParser.ts +16 -0
  81. package/src/api/parsers/ClassicOracleParser.ts +20 -0
  82. package/src/api/parsers/PythOracleParser.ts +34 -0
  83. package/src/api/parsers/index.ts +3 -0
  84. package/src/api/prices.ts +32 -41
  85. package/src/constants/assets/assetId.ts +30 -0
  86. package/src/constants/assets/index.ts +3 -0
  87. package/src/constants/{assets.ts → assets/mainnet.ts} +27 -94
  88. package/src/constants/assets/testnet.ts +74 -0
  89. package/src/constants/general/index.ts +91 -0
  90. package/src/constants/{general.ts → general/mainnet.ts} +48 -72
  91. package/src/constants/general/testnet.ts +25 -0
  92. package/src/constants/index.ts +3 -0
  93. package/src/constants/pools/index.ts +2 -0
  94. package/src/constants/pools/mainnet.ts +218 -0
  95. package/src/constants/pools/testnet.ts +75 -0
  96. package/src/contracts/AbstractMaster.ts +450 -0
  97. package/src/contracts/ClassicMaster.ts +149 -0
  98. package/src/contracts/PythMaster.ts +313 -0
  99. package/src/contracts/UserContract.ts +7 -28
  100. package/src/contracts/index.ts +7 -0
  101. package/src/index.ts +18 -85
  102. package/src/prices/Oracle.interface.ts +18 -0
  103. package/src/prices/Prices.ts +17 -4
  104. package/src/prices/PricesCollector.ts +91 -68
  105. package/src/prices/PythCollector.ts +294 -0
  106. package/src/prices/Types.ts +28 -6
  107. package/src/prices/index.ts +4 -3
  108. package/src/prices/sources/Backend.ts +21 -19
  109. package/src/prices/sources/Icp.ts +13 -10
  110. package/src/prices/sources/PriceSource.ts +6 -5
  111. package/src/prices/utils.ts +65 -68
  112. package/src/types/Master.ts +29 -52
  113. package/src/types/User.ts +15 -7
  114. package/src/utils/userJettonWallet.ts +0 -8
  115. package/src/utils/utils.ts +41 -2
  116. package/dist/constants/general.d.ts +0 -67
  117. package/dist/constants/pools.d.ts +0 -13
  118. package/dist/constants/pools.js +0 -120
  119. package/dist/contracts/MasterContract.d.ts +0 -156
  120. package/dist/contracts/MasterContract.js +0 -260
  121. package/src/constants/pools.ts +0 -175
  122. package/src/contracts/MasterContract.ts +0 -410
@@ -0,0 +1,450 @@
1
+ import {
2
+ Address,
3
+ beginCell,
4
+ Builder,
5
+ Cell,
6
+ Contract,
7
+ ContractProvider,
8
+ Dictionary,
9
+ OpenedContract,
10
+ Sender,
11
+ SendMode,
12
+ storeStateInit,
13
+ } from '@ton/core';
14
+ import { isTonAsset, isValidSubaccountId } from '..';
15
+ import { parseMasterData } from '../api/parser';
16
+ import { OracleParser } from '../api/parsers/AbstractOracleParser';
17
+ import { ClassicOracleInfo } from '../api/parsers/ClassicOracleParser';
18
+ import { PythOracleInfo } from '../api/parsers/PythOracleParser';
19
+ import { FEES, OPCODES } from '../constants/general';
20
+ import { ExtendedAssetsConfig, ExtendedAssetsData, PoolAssetConfig, PoolConfig, UpgradeConfig } from '../types/Master';
21
+ import { getUserJettonWallet } from '../utils/userJettonWallet';
22
+ import {
23
+ ClassicLiquidationOperationParameters,
24
+ ClassicLiquidationParameters,
25
+ ClassicSupplyWithdrawParameters,
26
+ ClassicWithdrawParameters,
27
+ } from './ClassicMaster';
28
+ import { JettonWallet } from './JettonWallet';
29
+ import {
30
+ PythLiquidationOperationParameters,
31
+ PythLiquidationParameters,
32
+ PythSupplyWithdrawParameters,
33
+ PythWithdrawParameters,
34
+ } from './PythMaster';
35
+ import { EvaaUser } from './UserContract';
36
+
37
+ // Internal
38
+ type JettonParams = {
39
+ queryID: bigint;
40
+ amount?: bigint;
41
+ liquidationAmount?: bigint;
42
+ supplyAmount?: bigint;
43
+ responseAddress?: Address;
44
+ userAddress?: Address;
45
+ liquidatorAddress?: Address;
46
+ forwardAmount?: bigint;
47
+ destinationAddress?: Address;
48
+ };
49
+
50
+ /**
51
+ * Parameters for the Evaa contract
52
+ * @property testnet - true for testnet, false for mainnet
53
+ * @property debug - true to enable debug mode (optional)
54
+ */
55
+ export type EvaaParameters = {
56
+ poolConfig: PoolConfig;
57
+ debug?: boolean;
58
+ };
59
+
60
+ /**
61
+ * Base parameters for supply
62
+ * @property queryID - unique query ID
63
+ * @property includeUserCode - true to include user code for update (needed when user contract code version is outdated)
64
+ * @property amount - amount to supply
65
+ * @property userAddress - user address
66
+ * @property asset
67
+ */
68
+ export type SupplyParameters = {
69
+ asset: PoolAssetConfig;
70
+ queryID: bigint;
71
+ includeUserCode: boolean;
72
+ amount: bigint;
73
+ userAddress: Address;
74
+ responseAddress?: Address;
75
+ forwardAmount?: bigint;
76
+ payload: Cell;
77
+ subaccountId?: number;
78
+ returnRepayRemainingsFlag?: boolean;
79
+ customPayloadRecipient?: Address;
80
+ customPayloadSaturationFlag?: boolean;
81
+ };
82
+
83
+ /**
84
+ * Parameters for the withdraw message
85
+ * @property queryID - unique query ID
86
+ * @property asset - asset config
87
+ * @property amount - amount to withdraw
88
+ * @property userAddress - user address
89
+ * @property includeUserCode - true to include user code for update (needed when user contract code version is outdated)
90
+ */
91
+ export type WithdrawParameters = {
92
+ queryID: bigint;
93
+ amount: bigint;
94
+ userAddress: Address;
95
+ includeUserCode: boolean;
96
+ asset: PoolAssetConfig;
97
+ payload: Cell;
98
+ subaccountId?: number;
99
+ forwardAmount?: bigint;
100
+ amountToTransfer: bigint;
101
+ customPayloadSaturationFlag: boolean;
102
+ returnRepayRemainingsFlag: boolean;
103
+ };
104
+
105
+ /**
106
+ * Parameters for liquidation inner operations
107
+ * @interface LiquidationInnerParameters
108
+ */
109
+ export type LiquidationInnerParameters = {
110
+ /** Liquidation operation payload cell */
111
+ payload: Cell;
112
+ subaccountId: number;
113
+ customPayloadRecipient: Address;
114
+ customPayloadSaturationFlag: boolean;
115
+ };
116
+
117
+ /**
118
+ * Base data for liquidation. Can be obtained from the user contract liquidationParameters getter
119
+ * @property loanAsset - loan asset ID
120
+ * @property queryID - unique query ID
121
+ * @property liquidatorAddress - liquidator address, where and collateral will be sent
122
+ */
123
+ export type LiquidationParameters = {
124
+ loanAsset: bigint;
125
+ queryID: bigint;
126
+ liquidatorAddress: Address;
127
+ };
128
+
129
+ /**
130
+ * @property asset - asset config
131
+ * @property borrowerAddress - borrower address (user address that is being liquidated)
132
+ * @property collateralAsset - collateral asset ID
133
+ * @property minCollateralAmount - minimal amount to receive from the liquidation
134
+ * @property liquidationAmount - amount to liquidate
135
+ * @property includeUserCode - true to include user code for update (needed when user contract code version is outdated)
136
+ */
137
+ export type LiquidationOperationBuilderParameters = {
138
+ asset: PoolAssetConfig;
139
+ borrowerAddress: Address;
140
+ collateralAsset: bigint;
141
+ minCollateralAmount: bigint;
142
+ liquidationAmount: bigint;
143
+ includeUserCode: boolean;
144
+ };
145
+
146
+ export type SupplyWithdrawParameters = {
147
+ queryID: bigint;
148
+ supplyAmount: bigint;
149
+ supplyAsset: PoolAssetConfig;
150
+ withdrawAmount: bigint;
151
+ withdrawAsset: PoolAssetConfig;
152
+ withdrawRecipient: Address;
153
+ includeUserCode: boolean;
154
+ tonForRepayRemainings?: bigint;
155
+ payload: Cell;
156
+ subaccountId?: number;
157
+ returnRepayRemainingsFlag?: boolean;
158
+ customPayloadSaturationFlag?: boolean;
159
+ forwardAmount?: bigint;
160
+ responseAddress?: Address;
161
+ };
162
+
163
+ // Base shared configuration for all master types
164
+ export type BaseMasterConfig = {
165
+ ifActive: number;
166
+ admin: Address;
167
+ tokenKeys: Cell | null;
168
+ supervisor: Address | null;
169
+ };
170
+
171
+ export type OracleInfo = PythOracleInfo | ClassicOracleInfo;
172
+
173
+ // Generic master configuration with oracle info
174
+ export type MasterConfig<T extends OracleInfo> = BaseMasterConfig & {
175
+ oraclesInfo: T;
176
+ };
177
+
178
+ // Base shared data for all master types
179
+ export type BaseMasterData = {
180
+ meta: string;
181
+ upgradeConfig: UpgradeConfig;
182
+ assetsConfig: ExtendedAssetsConfig;
183
+ assetsData: ExtendedAssetsData;
184
+ assetsReserves: Dictionary<bigint, bigint>;
185
+ apy: {
186
+ supply: Dictionary<bigint, number>;
187
+ borrow: Dictionary<bigint, number>;
188
+ };
189
+ };
190
+
191
+ // Generic master data with config
192
+ export type MasterData<T extends MasterConfig<OracleInfo>> = BaseMasterData & {
193
+ masterConfig: T;
194
+ };
195
+
196
+ /**
197
+ * Abstract EVAA Master base that encapsulates shared logic and structure.
198
+ * Concrete implementations (Classic/Pyth) should override message creation for
199
+ * withdraw/liquidation and supply-withdraw wrapping.
200
+ */
201
+ export abstract class AbstractEvaaMaster<T extends MasterData<MasterConfig<OracleInfo>>> implements Contract {
202
+ readonly address: Address;
203
+ protected _poolConfig: PoolConfig;
204
+ protected readonly debug?: boolean;
205
+ protected _data?: T;
206
+ protected lastSync = 0;
207
+
208
+ constructor(parameters: EvaaParameters) {
209
+ this._poolConfig = parameters.poolConfig;
210
+ this.address = this._poolConfig.masterAddress;
211
+ this.debug = parameters?.debug;
212
+ }
213
+
214
+ get poolConfig(): PoolConfig {
215
+ return this._poolConfig;
216
+ }
217
+
218
+ get data(): T | undefined {
219
+ return this._data;
220
+ }
221
+
222
+ // ---------- Common helpers ----------
223
+ protected createJettonTransferMessage(parameters: JettonParams, defaultFees: bigint, message: Cell): Cell {
224
+ if (
225
+ parameters.amount == undefined &&
226
+ parameters.liquidationAmount == undefined &&
227
+ parameters.supplyAmount == undefined
228
+ ) {
229
+ throw new Error('Either amount or liquidationAmount or supplyAmount must be provided');
230
+ }
231
+ return beginCell()
232
+ .storeUint(OPCODES.JETTON_TRANSFER, 32)
233
+ .storeUint(parameters.queryID, 64)
234
+ .storeCoins(parameters.amount ?? parameters.liquidationAmount ?? parameters.supplyAmount ?? 0n)
235
+ .storeAddress(parameters.destinationAddress ?? this.address)
236
+ .storeAddress(parameters.responseAddress ?? parameters.userAddress ?? parameters.liquidatorAddress)
237
+ .storeBit(0)
238
+ .storeCoins(parameters.forwardAmount ?? defaultFees)
239
+ .storeBit(1)
240
+ .storeRef(message)
241
+ .endCell();
242
+ }
243
+
244
+ abstract buildGeneralDataPayload(parameters: PythSupplyWithdrawParameters | ClassicSupplyWithdrawParameters): Cell;
245
+
246
+ protected buildSupplyWithdrawOperationPayload(
247
+ parameters: PythSupplyWithdrawParameters | ClassicSupplyWithdrawParameters,
248
+ ): Cell {
249
+ const isTon = isTonAsset(parameters.supplyAsset);
250
+
251
+ const supplyData = beginCell();
252
+ if (isTon) {
253
+ supplyData.storeUint(parameters.supplyAmount, 64);
254
+ }
255
+
256
+ const withdrawData = beginCell()
257
+ .storeUint(parameters.withdrawAmount, 64)
258
+ .storeUint(parameters.withdrawAsset.assetId, 256)
259
+ .storeAddress(parameters.withdrawRecipient);
260
+
261
+ const generalData = this.buildGeneralDataPayload(parameters);
262
+ return beginCell().storeRef(supplyData).storeRef(withdrawData).storeRef(generalData).endCell();
263
+ }
264
+
265
+ // ---------- Public message builders (shared) ----------
266
+ createSupplyMessage(parameters: SupplyParameters): Cell {
267
+ const subaccountId = parameters.subaccountId ?? 0;
268
+ const isTon = isTonAsset(parameters.asset);
269
+
270
+ const operationPayload = beginCell()
271
+ .storeUint(OPCODES.SUPPLY_MASTER, 32)
272
+ .storeBuilder(isTon ? beginCell().storeUint(parameters.queryID, 64) : beginCell())
273
+ .storeInt(parameters.includeUserCode ? -1 : 0, 2)
274
+ .storeBuilder(isTon ? beginCell().storeUint(parameters.amount, 64) : beginCell())
275
+ .storeAddress(parameters.userAddress)
276
+ .storeRef(parameters.payload)
277
+ .storeInt(subaccountId, 16)
278
+ .storeInt(parameters.returnRepayRemainingsFlag ? -1 : 0, 2)
279
+ .storeAddress(parameters.customPayloadRecipient)
280
+ .storeInt(parameters.customPayloadSaturationFlag ? -1 : 0, 2)
281
+ .endCell();
282
+
283
+ if (!isTon) {
284
+ return this.createJettonTransferMessage(parameters, FEES.SUPPLY, operationPayload);
285
+ } else {
286
+ return operationPayload;
287
+ }
288
+ }
289
+
290
+ // Concrete classes must wrap the operation payload correctly for their oracle
291
+ abstract createSupplyWithdrawMessage(
292
+ parameters: ClassicSupplyWithdrawParameters | PythSupplyWithdrawParameters,
293
+ ): Cell;
294
+
295
+ // ---------- Sending operations ----------
296
+ async sendSupply(provider: ContractProvider, via: Sender, value: bigint, parameters: SupplyParameters) {
297
+ const message = this.createSupplyMessage(parameters);
298
+
299
+ await this.sendTx(provider, via, value, message, parameters.asset);
300
+ }
301
+
302
+ async sendSupplyWithdraw(
303
+ provider: ContractProvider,
304
+ via: Sender,
305
+ value: bigint,
306
+ parameters: ClassicSupplyWithdrawParameters | PythSupplyWithdrawParameters,
307
+ ) {
308
+ const message = this.createSupplyWithdrawMessage(parameters);
309
+
310
+ await this.sendTx(provider, via, value, message, parameters.supplyAsset);
311
+ }
312
+
313
+ // Abstract where oracle path differs
314
+ abstract sendWithdraw(
315
+ provider: ContractProvider,
316
+ via: Sender,
317
+ value: bigint,
318
+ parameters: ClassicWithdrawParameters | PythWithdrawParameters,
319
+ ): Promise<void>;
320
+
321
+ abstract createLiquidationMessage(parameters: ClassicLiquidationParameters | PythLiquidationParameters): Cell;
322
+
323
+ protected buildLiquidationInnerBuilder(parameters: LiquidationInnerParameters): Builder {
324
+ const subaccountId = parameters.subaccountId ?? 0;
325
+
326
+ return beginCell()
327
+ .storeRef(parameters.payload)
328
+ .storeInt(subaccountId, 16)
329
+ .storeAddress(parameters.customPayloadRecipient)
330
+ .storeInt(parameters.customPayloadSaturationFlag ? -1 : 0, 2);
331
+ }
332
+
333
+ protected abstract buildLiquidationOperationPayload(
334
+ parameters: PythLiquidationOperationParameters | ClassicLiquidationOperationParameters,
335
+ ): Cell | Builder;
336
+
337
+ protected buildLiquidationOperationPayloadBuilder(parameters: LiquidationOperationBuilderParameters): Builder {
338
+ return beginCell()
339
+ .storeAddress(parameters.borrowerAddress)
340
+ .storeUint(parameters.collateralAsset, 256)
341
+ .storeUint(parameters.minCollateralAmount, 64)
342
+ .storeInt(parameters.includeUserCode ? -1 : 0, 2)
343
+ .storeUint(isTonAsset(parameters.asset) ? parameters.liquidationAmount : 0, 64);
344
+ }
345
+
346
+ abstract sendLiquidation(
347
+ provider: ContractProvider,
348
+ via: Sender,
349
+ value: bigint,
350
+ parameters: ClassicLiquidationParameters | PythLiquidationParameters,
351
+ ): Promise<void>;
352
+
353
+ // ---------- Read helpers ----------
354
+ calculateUserSCAddr(userAddress: Address, lendingCode: Cell, subaccountId: number = 0): Address {
355
+ const subaccount = beginCell();
356
+ if (subaccountId !== 0) {
357
+ if (!isValidSubaccountId(subaccountId)) throw new Error('Invalid subaccount id');
358
+ subaccount.storeInt(subaccountId, 16);
359
+ }
360
+
361
+ const lendingData = beginCell()
362
+ .storeAddress(this.address)
363
+ .storeAddress(userAddress)
364
+ .storeUint(0, 8)
365
+ .storeBit(0)
366
+ .storeBuilder(subaccount)
367
+ .endCell();
368
+
369
+ const stateInit = beginCell()
370
+ .store(
371
+ storeStateInit({
372
+ code: lendingCode,
373
+ data: lendingData,
374
+ }),
375
+ )
376
+ .endCell();
377
+
378
+ return new Address(0, stateInit.hash());
379
+ }
380
+
381
+ openUserContract(userAddress: Address, subaccountId: number = 0): EvaaUser {
382
+ return EvaaUser.createFromAddress(
383
+ this.calculateUserSCAddr(userAddress, this._poolConfig.lendingCode, subaccountId),
384
+ this._poolConfig,
385
+ );
386
+ }
387
+
388
+ getOpenedUserContract(
389
+ provider: ContractProvider,
390
+ userAddress: Address,
391
+ subaccountId: number = 0,
392
+ ): OpenedContract<EvaaUser> {
393
+ return provider.open(this.openUserContract(userAddress, subaccountId));
394
+ }
395
+
396
+ async sendOnchainGetter(
397
+ provider: ContractProvider,
398
+ via: Sender,
399
+ value: bigint,
400
+ queryID: bigint,
401
+ forwardPayload: Cell,
402
+ ) {
403
+ await provider.internal(via, {
404
+ value,
405
+ sendMode: SendMode.PAY_GAS_SEPARATELY + SendMode.IGNORE_ERRORS,
406
+ body: beginCell()
407
+ .storeUint(OPCODES.ONCHAIN_GETTER, 32)
408
+ .storeUint(queryID, 64)
409
+ .storeRef(forwardPayload)
410
+ .endCell(),
411
+ });
412
+ }
413
+
414
+ async sendTx(provider: ContractProvider, via: Sender, value: bigint, message: Cell, asset: PoolAssetConfig) {
415
+ if (!isTonAsset(asset)) {
416
+ if (!via.address) throw new Error('Via address is required for jetton supply');
417
+ const jettonWallet = provider.open(JettonWallet.createFromAddress(getUserJettonWallet(via.address, asset)));
418
+ await jettonWallet.sendTransfer(via, value, message);
419
+ } else {
420
+ await provider.internal(via, {
421
+ value,
422
+ sendMode: SendMode.PAY_GAS_SEPARATELY + SendMode.IGNORE_ERRORS,
423
+ body: message,
424
+ });
425
+ }
426
+ }
427
+
428
+ // Centralized sync logic used by concrete masters (Classic/Pyth)
429
+ protected async syncMasterData(provider: ContractProvider, oracleParser: OracleParser): Promise<void> {
430
+ const state = (await provider.getState()).state;
431
+ if (state.type === 'active') {
432
+ this._data = parseMasterData(
433
+ state.data!.toString('base64'),
434
+ this._poolConfig.poolAssetsConfig,
435
+ this._poolConfig.masterConstants,
436
+ oracleParser,
437
+ ) as T;
438
+ if (this._data.upgradeConfig.masterCodeVersion !== this._poolConfig.masterVersion) {
439
+ throw Error(
440
+ `Outdated SDK pool version. It supports only master code version ${this._poolConfig.masterVersion}, but the current master code version is ${this._data.upgradeConfig.masterCodeVersion}`,
441
+ );
442
+ }
443
+ this.lastSync = Math.floor(Date.now() / 1000);
444
+ } else {
445
+ throw Error('Master contract is not active');
446
+ }
447
+ }
448
+
449
+ protected abstract getSync(provider: ContractProvider): Promise<void>;
450
+ }
@@ -0,0 +1,149 @@
1
+ import { beginCell, Builder, Cell, ContractProvider, Sender } from '@ton/core';
2
+ import { isTonAsset, LiquidationParameters, TON_MAINNET } from '..';
3
+ import { ClassicOracleInfo, ClassicOracleParser } from '../api/parsers/ClassicOracleParser';
4
+ import { FEES, OPCODES } from '../constants/general';
5
+ import {
6
+ AbstractEvaaMaster,
7
+ BaseMasterConfig,
8
+ BaseMasterData,
9
+ EvaaParameters,
10
+ LiquidationInnerParameters,
11
+ LiquidationOperationBuilderParameters,
12
+ SupplyWithdrawParameters,
13
+ WithdrawParameters,
14
+ } from './AbstractMaster';
15
+
16
+ export type ClassicSupplyWithdrawParameters = SupplyWithdrawParameters & {
17
+ priceData?: Cell;
18
+ };
19
+
20
+ /**
21
+ * Parameters for the withdraw message
22
+ * @property priceData - price data cell. Can be obtained from the getPrices function
23
+ */
24
+ export type ClassicWithdrawParameters = WithdrawParameters & {
25
+ priceData: Cell;
26
+ };
27
+
28
+ export type ClassicLiquidationOperationParameters = LiquidationOperationBuilderParameters &
29
+ LiquidationInnerParameters & {
30
+ priceData: Cell;
31
+ };
32
+
33
+ export type ClassicLiquidationParameters = LiquidationParameters & ClassicLiquidationOperationParameters;
34
+
35
+ export type ClassicMasterConfig = BaseMasterConfig & {
36
+ oraclesInfo: ClassicOracleInfo;
37
+ };
38
+
39
+ export type ClassicMasterData = BaseMasterData & {
40
+ masterConfig: ClassicMasterConfig;
41
+ };
42
+
43
+ export class EvaaMasterClassic extends AbstractEvaaMaster<ClassicMasterData> {
44
+ constructor(parameters: EvaaParameters) {
45
+ super(parameters);
46
+ }
47
+
48
+ buildGeneralDataPayload(parameters: ClassicSupplyWithdrawParameters): Cell {
49
+ return beginCell()
50
+ .storeInt(parameters.includeUserCode ? -1 : 0, 2)
51
+ .storeMaybeRef(parameters.priceData)
52
+ .storeUint(parameters.tonForRepayRemainings ?? 0n, 64)
53
+ .storeRef(parameters.payload)
54
+ .storeInt(parameters.subaccountId ?? 0, 16)
55
+ .storeInt(parameters.returnRepayRemainingsFlag ? -1 : 0, 2)
56
+ .storeInt(parameters.customPayloadSaturationFlag ? -1 : 0, 2)
57
+ .endCell();
58
+ }
59
+
60
+ createSupplyWithdrawMessage(parameters: ClassicSupplyWithdrawParameters): Cell {
61
+ const isTon = isTonAsset(parameters.supplyAsset);
62
+
63
+ const operationPayload = this.buildSupplyWithdrawOperationPayload(parameters);
64
+
65
+ const refOpCode = parameters.priceData
66
+ ? OPCODES.SUPPLY_WITHDRAW_MASTER
67
+ : OPCODES.SUPPLY_WITHDRAW_MASTER_WITHOUT_PRICES;
68
+
69
+ if (!isTon) {
70
+ return this.createJettonTransferMessage(
71
+ parameters,
72
+ FEES.SUPPLY_WITHDRAW,
73
+ beginCell().storeUint(refOpCode, 32).storeSlice(operationPayload.beginParse()).endCell(),
74
+ );
75
+ } else {
76
+ return beginCell()
77
+ .storeUint(refOpCode, 32)
78
+ .storeUint(parameters.queryID, 64)
79
+ .storeSlice(operationPayload.beginParse())
80
+ .endCell();
81
+ }
82
+ }
83
+
84
+ async sendWithdraw(
85
+ provider: ContractProvider,
86
+ via: Sender,
87
+ value: bigint,
88
+ parameters: ClassicWithdrawParameters,
89
+ ): Promise<void> {
90
+ // Compatibility layer using supply-withdraw with TON zero supply
91
+ await this.sendSupplyWithdraw(provider, via, value, {
92
+ supplyAsset: TON_MAINNET,
93
+ supplyAmount: 0n,
94
+ queryID: parameters.queryID,
95
+ withdrawAsset: parameters.asset,
96
+ withdrawAmount: parameters.amount,
97
+ withdrawRecipient: parameters.userAddress,
98
+ includeUserCode: parameters.includeUserCode,
99
+ forwardAmount: parameters.forwardAmount,
100
+ payload: parameters.payload,
101
+ subaccountId: parameters.subaccountId ?? 0,
102
+ customPayloadSaturationFlag: parameters.customPayloadSaturationFlag ?? false,
103
+ returnRepayRemainingsFlag: parameters.returnRepayRemainingsFlag ?? false,
104
+ tonForRepayRemainings: 0n,
105
+ priceData: parameters.priceData,
106
+ });
107
+ }
108
+
109
+ protected buildLiquidationOperationPayload(parameters: ClassicLiquidationOperationParameters): Builder {
110
+ const operationPayloadBuilder = this.buildLiquidationOperationPayloadBuilder(parameters);
111
+ const innerBuilder = this.buildLiquidationInnerBuilder(parameters);
112
+
113
+ return operationPayloadBuilder.storeRef(innerBuilder).storeRef(parameters.priceData);
114
+ }
115
+
116
+ createLiquidationMessage(parameters: ClassicLiquidationParameters): Cell {
117
+ const isTon = isTonAsset(parameters.asset);
118
+ const operationPayload = this.buildLiquidationOperationPayload(parameters);
119
+
120
+ if (!isTon) {
121
+ return this.createJettonTransferMessage(
122
+ parameters,
123
+ FEES.LIQUIDATION_JETTON_FWD,
124
+ beginCell().storeUint(OPCODES.LIQUIDATE_MASTER, 32).storeBuilder(operationPayload).endCell(),
125
+ );
126
+ } else {
127
+ return beginCell()
128
+ .storeUint(OPCODES.LIQUIDATE_MASTER, 32)
129
+ .storeUint(parameters.queryID, 64)
130
+ .storeBuilder(operationPayload)
131
+ .endCell();
132
+ }
133
+ }
134
+
135
+ async sendLiquidation(
136
+ provider: ContractProvider,
137
+ via: Sender,
138
+ value: bigint,
139
+ parameters: ClassicLiquidationParameters,
140
+ ): Promise<void> {
141
+ const message = this.createLiquidationMessage(parameters);
142
+
143
+ await this.sendTx(provider, via, value, message, parameters.asset);
144
+ }
145
+
146
+ async getSync(provider: ContractProvider) {
147
+ await this.syncMasterData(provider, new ClassicOracleParser());
148
+ }
149
+ }