@jup-ag/lend 0.0.106 → 0.0.107-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/borrow/index.d.mts +6 -4209
- package/dist/borrow/index.d.ts +6 -4209
- package/dist/borrow/index.mjs +9 -2297
- package/dist/index.mjs +2 -2
- package/dist/refinance/index.d.mts +58 -0
- package/dist/refinance/index.d.ts +58 -0
- package/dist/refinance/index.mjs +270 -0
- package/dist/shared/{lend.BGZ9rdrj.mjs → lend.C2-jCLFw.mjs} +2 -2
- package/dist/shared/lend.DNFQlLzM.d.mts +4211 -0
- package/dist/shared/lend.DNFQlLzM.d.ts +4211 -0
- package/dist/shared/lend.yP9-PjAh.mjs +2299 -0
- package/package.json +5 -1
package/dist/borrow/index.mjs
CHANGED
|
@@ -1,2300 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { g as getLiquidateIx, a as getVaultsProgram } from '../shared/lend.yP9-PjAh.mjs';
|
|
2
|
+
export { I as INIT_TICK, p as MAX_TICK, M as MIN_TICK, q as TICKS_PER_TICK_HAS_DEBT, T as TICK_HAS_DEBT_ARRAY_SIZE, s as TICK_HAS_DEBT_CHILDREN_SIZE, t as TICK_HAS_DEBT_CHILDREN_SIZE_IN_BITS, u as TOTAL_INDICES_NEEDED, Z as ZERO_TICK_SCALED_RATIO, A as findNextTickWithDebt, h as getAccountOwner, i as getCurrentPosition, j as getCurrentPositionState, k as getFinalPosition, x as getFirstTickForIndex, d as getInitPositionContext, c as getInitPositionIx, f as getLiquidateContext, b as getOperateContext, e as getOperateIx, v as getRatioAtTick, w as getTickAtRatio, y as getTickIndices, l as loadRelevantBranches, o as loadRelevantBranchesForLiquidate, m as loadRelevantTicksHasDebtArrays, n as loadRelevantTicksHasDebtArraysLiquidate, r as readOraclePrice, z as readTickHasDebtArray } from '../shared/lend.yP9-PjAh.mjs';
|
|
3
|
+
import { PublicKey, TransactionMessage, ComputeBudgetProgram, VersionedTransaction } from '@solana/web3.js';
|
|
2
4
|
import BN from 'bn.js';
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
const address = "jupnw4B6Eqs7ft6rxpzYLJZYSnrpRgPcr589n5Kv4oc";
|
|
10
|
-
const metadata = {
|
|
11
|
-
name: "oracle",
|
|
12
|
-
version: "0.1.0",
|
|
13
|
-
spec: "0.1.0",
|
|
14
|
-
description: "Created with Anchor"
|
|
15
|
-
};
|
|
16
|
-
const instructions = [
|
|
17
|
-
{
|
|
18
|
-
name: "get_both_exchange_rate",
|
|
19
|
-
discriminator: [
|
|
20
|
-
92,
|
|
21
|
-
88,
|
|
22
|
-
161,
|
|
23
|
-
46,
|
|
24
|
-
230,
|
|
25
|
-
193,
|
|
26
|
-
46,
|
|
27
|
-
237
|
|
28
|
-
],
|
|
29
|
-
accounts: [
|
|
30
|
-
{
|
|
31
|
-
name: "oracle"
|
|
32
|
-
}
|
|
33
|
-
],
|
|
34
|
-
args: [
|
|
35
|
-
{
|
|
36
|
-
name: "_nonce",
|
|
37
|
-
type: "u16"
|
|
38
|
-
}
|
|
39
|
-
]
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
name: "get_exchange_rate",
|
|
43
|
-
discriminator: [
|
|
44
|
-
153,
|
|
45
|
-
76,
|
|
46
|
-
17,
|
|
47
|
-
194,
|
|
48
|
-
170,
|
|
49
|
-
215,
|
|
50
|
-
89,
|
|
51
|
-
142
|
|
52
|
-
],
|
|
53
|
-
accounts: [
|
|
54
|
-
{
|
|
55
|
-
name: "oracle"
|
|
56
|
-
}
|
|
57
|
-
],
|
|
58
|
-
args: [
|
|
59
|
-
{
|
|
60
|
-
name: "_nonce",
|
|
61
|
-
type: "u16"
|
|
62
|
-
}
|
|
63
|
-
],
|
|
64
|
-
returns: "u128"
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
name: "get_exchange_rate_liquidate",
|
|
68
|
-
discriminator: [
|
|
69
|
-
228,
|
|
70
|
-
169,
|
|
71
|
-
73,
|
|
72
|
-
39,
|
|
73
|
-
91,
|
|
74
|
-
82,
|
|
75
|
-
27,
|
|
76
|
-
5
|
|
77
|
-
],
|
|
78
|
-
accounts: [
|
|
79
|
-
{
|
|
80
|
-
name: "oracle"
|
|
81
|
-
}
|
|
82
|
-
],
|
|
83
|
-
args: [
|
|
84
|
-
{
|
|
85
|
-
name: "_nonce",
|
|
86
|
-
type: "u16"
|
|
87
|
-
}
|
|
88
|
-
],
|
|
89
|
-
returns: "u128"
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
name: "get_exchange_rate_operate",
|
|
93
|
-
discriminator: [
|
|
94
|
-
174,
|
|
95
|
-
166,
|
|
96
|
-
126,
|
|
97
|
-
10,
|
|
98
|
-
122,
|
|
99
|
-
153,
|
|
100
|
-
94,
|
|
101
|
-
203
|
|
102
|
-
],
|
|
103
|
-
accounts: [
|
|
104
|
-
{
|
|
105
|
-
name: "oracle"
|
|
106
|
-
}
|
|
107
|
-
],
|
|
108
|
-
args: [
|
|
109
|
-
{
|
|
110
|
-
name: "_nonce",
|
|
111
|
-
type: "u16"
|
|
112
|
-
}
|
|
113
|
-
],
|
|
114
|
-
returns: "u128"
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
name: "init_admin",
|
|
118
|
-
discriminator: [
|
|
119
|
-
97,
|
|
120
|
-
65,
|
|
121
|
-
97,
|
|
122
|
-
27,
|
|
123
|
-
200,
|
|
124
|
-
206,
|
|
125
|
-
72,
|
|
126
|
-
219
|
|
127
|
-
],
|
|
128
|
-
accounts: [
|
|
129
|
-
{
|
|
130
|
-
name: "signer",
|
|
131
|
-
writable: true,
|
|
132
|
-
signer: true
|
|
133
|
-
},
|
|
134
|
-
{
|
|
135
|
-
name: "oracle_admin",
|
|
136
|
-
writable: true,
|
|
137
|
-
pda: {
|
|
138
|
-
seeds: [
|
|
139
|
-
{
|
|
140
|
-
kind: "const",
|
|
141
|
-
value: [
|
|
142
|
-
111,
|
|
143
|
-
114,
|
|
144
|
-
97,
|
|
145
|
-
99,
|
|
146
|
-
108,
|
|
147
|
-
101,
|
|
148
|
-
95,
|
|
149
|
-
97,
|
|
150
|
-
100,
|
|
151
|
-
109,
|
|
152
|
-
105,
|
|
153
|
-
110
|
|
154
|
-
]
|
|
155
|
-
}
|
|
156
|
-
]
|
|
157
|
-
}
|
|
158
|
-
},
|
|
159
|
-
{
|
|
160
|
-
name: "system_program",
|
|
161
|
-
address: "11111111111111111111111111111111"
|
|
162
|
-
}
|
|
163
|
-
],
|
|
164
|
-
args: [
|
|
165
|
-
{
|
|
166
|
-
name: "authority",
|
|
167
|
-
type: "pubkey"
|
|
168
|
-
}
|
|
169
|
-
]
|
|
170
|
-
},
|
|
171
|
-
{
|
|
172
|
-
name: "init_oracle_config",
|
|
173
|
-
discriminator: [
|
|
174
|
-
77,
|
|
175
|
-
144,
|
|
176
|
-
180,
|
|
177
|
-
246,
|
|
178
|
-
217,
|
|
179
|
-
15,
|
|
180
|
-
118,
|
|
181
|
-
92
|
|
182
|
-
],
|
|
183
|
-
accounts: [
|
|
184
|
-
{
|
|
185
|
-
name: "signer",
|
|
186
|
-
writable: true,
|
|
187
|
-
signer: true
|
|
188
|
-
},
|
|
189
|
-
{
|
|
190
|
-
name: "oracle_admin"
|
|
191
|
-
},
|
|
192
|
-
{
|
|
193
|
-
name: "oracle",
|
|
194
|
-
writable: true,
|
|
195
|
-
pda: {
|
|
196
|
-
seeds: [
|
|
197
|
-
{
|
|
198
|
-
kind: "const",
|
|
199
|
-
value: [
|
|
200
|
-
111,
|
|
201
|
-
114,
|
|
202
|
-
97,
|
|
203
|
-
99,
|
|
204
|
-
108,
|
|
205
|
-
101
|
|
206
|
-
]
|
|
207
|
-
},
|
|
208
|
-
{
|
|
209
|
-
kind: "arg",
|
|
210
|
-
path: "nonce"
|
|
211
|
-
}
|
|
212
|
-
]
|
|
213
|
-
}
|
|
214
|
-
},
|
|
215
|
-
{
|
|
216
|
-
name: "system_program",
|
|
217
|
-
address: "11111111111111111111111111111111"
|
|
218
|
-
}
|
|
219
|
-
],
|
|
220
|
-
args: [
|
|
221
|
-
{
|
|
222
|
-
name: "sources",
|
|
223
|
-
type: {
|
|
224
|
-
vec: {
|
|
225
|
-
defined: {
|
|
226
|
-
name: "Sources"
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
},
|
|
231
|
-
{
|
|
232
|
-
name: "nonce",
|
|
233
|
-
type: "u16"
|
|
234
|
-
}
|
|
235
|
-
]
|
|
236
|
-
},
|
|
237
|
-
{
|
|
238
|
-
name: "update_authority",
|
|
239
|
-
discriminator: [
|
|
240
|
-
32,
|
|
241
|
-
46,
|
|
242
|
-
64,
|
|
243
|
-
28,
|
|
244
|
-
149,
|
|
245
|
-
75,
|
|
246
|
-
243,
|
|
247
|
-
88
|
|
248
|
-
],
|
|
249
|
-
accounts: [
|
|
250
|
-
{
|
|
251
|
-
name: "authority",
|
|
252
|
-
signer: true
|
|
253
|
-
},
|
|
254
|
-
{
|
|
255
|
-
name: "oracle_admin",
|
|
256
|
-
writable: true
|
|
257
|
-
}
|
|
258
|
-
],
|
|
259
|
-
args: [
|
|
260
|
-
{
|
|
261
|
-
name: "new_authority",
|
|
262
|
-
type: "pubkey"
|
|
263
|
-
}
|
|
264
|
-
]
|
|
265
|
-
},
|
|
266
|
-
{
|
|
267
|
-
name: "update_auths",
|
|
268
|
-
discriminator: [
|
|
269
|
-
93,
|
|
270
|
-
96,
|
|
271
|
-
178,
|
|
272
|
-
156,
|
|
273
|
-
57,
|
|
274
|
-
117,
|
|
275
|
-
253,
|
|
276
|
-
209
|
|
277
|
-
],
|
|
278
|
-
accounts: [
|
|
279
|
-
{
|
|
280
|
-
name: "authority",
|
|
281
|
-
signer: true
|
|
282
|
-
},
|
|
283
|
-
{
|
|
284
|
-
name: "oracle_admin",
|
|
285
|
-
writable: true
|
|
286
|
-
}
|
|
287
|
-
],
|
|
288
|
-
args: [
|
|
289
|
-
{
|
|
290
|
-
name: "auth_status",
|
|
291
|
-
type: {
|
|
292
|
-
vec: {
|
|
293
|
-
defined: {
|
|
294
|
-
name: "AddressBool"
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
]
|
|
300
|
-
}
|
|
301
|
-
];
|
|
302
|
-
const accounts = [
|
|
303
|
-
{
|
|
304
|
-
name: "Oracle",
|
|
305
|
-
discriminator: [
|
|
306
|
-
139,
|
|
307
|
-
194,
|
|
308
|
-
131,
|
|
309
|
-
179,
|
|
310
|
-
140,
|
|
311
|
-
179,
|
|
312
|
-
229,
|
|
313
|
-
244
|
|
314
|
-
]
|
|
315
|
-
},
|
|
316
|
-
{
|
|
317
|
-
name: "OracleAdmin",
|
|
318
|
-
discriminator: [
|
|
319
|
-
239,
|
|
320
|
-
232,
|
|
321
|
-
8,
|
|
322
|
-
20,
|
|
323
|
-
254,
|
|
324
|
-
63,
|
|
325
|
-
25,
|
|
326
|
-
246
|
|
327
|
-
]
|
|
328
|
-
}
|
|
329
|
-
];
|
|
330
|
-
const events = [
|
|
331
|
-
{
|
|
332
|
-
name: "LogStakePoolHighFeeDetected",
|
|
333
|
-
discriminator: [
|
|
334
|
-
198,
|
|
335
|
-
106,
|
|
336
|
-
149,
|
|
337
|
-
7,
|
|
338
|
-
25,
|
|
339
|
-
83,
|
|
340
|
-
39,
|
|
341
|
-
155
|
|
342
|
-
]
|
|
343
|
-
},
|
|
344
|
-
{
|
|
345
|
-
name: "LogUpdateAuthority",
|
|
346
|
-
discriminator: [
|
|
347
|
-
150,
|
|
348
|
-
152,
|
|
349
|
-
157,
|
|
350
|
-
143,
|
|
351
|
-
6,
|
|
352
|
-
135,
|
|
353
|
-
193,
|
|
354
|
-
101
|
|
355
|
-
]
|
|
356
|
-
},
|
|
357
|
-
{
|
|
358
|
-
name: "LogUpdateAuths",
|
|
359
|
-
discriminator: [
|
|
360
|
-
88,
|
|
361
|
-
80,
|
|
362
|
-
109,
|
|
363
|
-
48,
|
|
364
|
-
111,
|
|
365
|
-
203,
|
|
366
|
-
76,
|
|
367
|
-
251
|
|
368
|
-
]
|
|
369
|
-
}
|
|
370
|
-
];
|
|
371
|
-
const errors = [
|
|
372
|
-
{
|
|
373
|
-
code: 6000,
|
|
374
|
-
name: "PriceNotValid",
|
|
375
|
-
msg: "PRICE_NOT_VALID"
|
|
376
|
-
},
|
|
377
|
-
{
|
|
378
|
-
code: 6001,
|
|
379
|
-
name: "PriceTooOld",
|
|
380
|
-
msg: "PRICE_TOO_OLD"
|
|
381
|
-
},
|
|
382
|
-
{
|
|
383
|
-
code: 6002,
|
|
384
|
-
name: "RateZero",
|
|
385
|
-
msg: "RATE_ZERO"
|
|
386
|
-
},
|
|
387
|
-
{
|
|
388
|
-
code: 6003,
|
|
389
|
-
name: "InvalidParams",
|
|
390
|
-
msg: "INVALID_PARAMS"
|
|
391
|
-
},
|
|
392
|
-
{
|
|
393
|
-
code: 6004,
|
|
394
|
-
name: "InvalidPythSourceMultiplierAndDivisor",
|
|
395
|
-
msg: "INVALID_PYTH_SOURCE_MULTIPLIER_AND_DIVISOR"
|
|
396
|
-
},
|
|
397
|
-
{
|
|
398
|
-
code: 6005,
|
|
399
|
-
name: "InvalidSource",
|
|
400
|
-
msg: "INVALID_SOURCE"
|
|
401
|
-
},
|
|
402
|
-
{
|
|
403
|
-
code: 6006,
|
|
404
|
-
name: "InvalidSourcesLength",
|
|
405
|
-
msg: "INVALID_SOURCES_LENGTH"
|
|
406
|
-
},
|
|
407
|
-
{
|
|
408
|
-
code: 6007,
|
|
409
|
-
name: "OracleAdminOnlyAuthority",
|
|
410
|
-
msg: "ORACLE_ADMIN_ONLY_AUTHORITY"
|
|
411
|
-
},
|
|
412
|
-
{
|
|
413
|
-
code: 6008,
|
|
414
|
-
name: "OracleAdminOnlyAuth",
|
|
415
|
-
msg: "ORACLE_ADMIN_ONLY_AUTH"
|
|
416
|
-
},
|
|
417
|
-
{
|
|
418
|
-
code: 6009,
|
|
419
|
-
name: "OracleAdminMaxAuthCountReached",
|
|
420
|
-
msg: "ORACLE_ADMIN_MAX_AUTH_COUNT_REACHED"
|
|
421
|
-
},
|
|
422
|
-
{
|
|
423
|
-
code: 6010,
|
|
424
|
-
name: "OracleAdminInvalidParams",
|
|
425
|
-
msg: "ORACLE_ADMIN_INVALID_PARAMS"
|
|
426
|
-
},
|
|
427
|
-
{
|
|
428
|
-
code: 6011,
|
|
429
|
-
name: "OracleNonceMismatch",
|
|
430
|
-
msg: "ORACLE_NONCE_MISMATCH"
|
|
431
|
-
},
|
|
432
|
-
{
|
|
433
|
-
code: 6012,
|
|
434
|
-
name: "PriceConfidenceNotSufficient",
|
|
435
|
-
msg: "PRICE_CONFIDENCE_NOT_SUFFICIENT"
|
|
436
|
-
},
|
|
437
|
-
{
|
|
438
|
-
code: 6013,
|
|
439
|
-
name: "StakePoolNotRefreshed",
|
|
440
|
-
msg: "STAKE_POOL_NOT_REFRESHED"
|
|
441
|
-
},
|
|
442
|
-
{
|
|
443
|
-
code: 6014,
|
|
444
|
-
name: "InvalidPrice",
|
|
445
|
-
msg: "INVALID_PRICE"
|
|
446
|
-
},
|
|
447
|
-
{
|
|
448
|
-
code: 6015,
|
|
449
|
-
name: "FeeTooHigh",
|
|
450
|
-
msg: "FEE_TOO_HIGH"
|
|
451
|
-
},
|
|
452
|
-
{
|
|
453
|
-
code: 6016,
|
|
454
|
-
name: "RedstonePriceOverflow",
|
|
455
|
-
msg: "REDSTONE_PRICE_OVERFLOW"
|
|
456
|
-
},
|
|
457
|
-
{
|
|
458
|
-
code: 6017,
|
|
459
|
-
name: "TimestampExpected",
|
|
460
|
-
msg: "TIMESTAMP_EXPECTED"
|
|
461
|
-
},
|
|
462
|
-
{
|
|
463
|
-
code: 6018,
|
|
464
|
-
name: "CpiToStakeProgramFailed",
|
|
465
|
-
msg: "CPI_TO_STAKE_PROGRAM_FAILED"
|
|
466
|
-
},
|
|
467
|
-
{
|
|
468
|
-
code: 6019,
|
|
469
|
-
name: "InvalidStakePoolReturnParams",
|
|
470
|
-
msg: "INVALID_STAKE_POOL_RETURN_PARAMS"
|
|
471
|
-
},
|
|
472
|
-
{
|
|
473
|
-
code: 6020,
|
|
474
|
-
name: "ChainlinkPriceReadError",
|
|
475
|
-
msg: "CHAINLINK_PRICE_READ_ERROR"
|
|
476
|
-
},
|
|
477
|
-
{
|
|
478
|
-
code: 6021,
|
|
479
|
-
name: "SinglePoolTokenSupplyZero",
|
|
480
|
-
msg: "SINGLE_POOL_TOKEN_SUPPLY_ZERO"
|
|
481
|
-
},
|
|
482
|
-
{
|
|
483
|
-
code: 6022,
|
|
484
|
-
name: "SinglePoolInvalidStakeAccount",
|
|
485
|
-
msg: "SINGLE_POOL_INVALID_STAKE_ACCOUNT"
|
|
486
|
-
},
|
|
487
|
-
{
|
|
488
|
-
code: 6023,
|
|
489
|
-
name: "SinglePoolInvalidMint",
|
|
490
|
-
msg: "SINGLE_POOL_INVALID_MINT"
|
|
491
|
-
}
|
|
492
|
-
];
|
|
493
|
-
const types = [
|
|
494
|
-
{
|
|
495
|
-
name: "AddressBool",
|
|
496
|
-
type: {
|
|
497
|
-
kind: "struct",
|
|
498
|
-
fields: [
|
|
499
|
-
{
|
|
500
|
-
name: "addr",
|
|
501
|
-
type: "pubkey"
|
|
502
|
-
},
|
|
503
|
-
{
|
|
504
|
-
name: "value",
|
|
505
|
-
type: "bool"
|
|
506
|
-
}
|
|
507
|
-
]
|
|
508
|
-
}
|
|
509
|
-
},
|
|
510
|
-
{
|
|
511
|
-
name: "LogStakePoolHighFeeDetected",
|
|
512
|
-
type: {
|
|
513
|
-
kind: "struct",
|
|
514
|
-
fields: [
|
|
515
|
-
{
|
|
516
|
-
name: "stake_pool",
|
|
517
|
-
type: "pubkey"
|
|
518
|
-
},
|
|
519
|
-
{
|
|
520
|
-
name: "epoch",
|
|
521
|
-
type: "u64"
|
|
522
|
-
}
|
|
523
|
-
]
|
|
524
|
-
}
|
|
525
|
-
},
|
|
526
|
-
{
|
|
527
|
-
name: "LogUpdateAuthority",
|
|
528
|
-
type: {
|
|
529
|
-
kind: "struct",
|
|
530
|
-
fields: [
|
|
531
|
-
{
|
|
532
|
-
name: "new_authority",
|
|
533
|
-
type: "pubkey"
|
|
534
|
-
}
|
|
535
|
-
]
|
|
536
|
-
}
|
|
537
|
-
},
|
|
538
|
-
{
|
|
539
|
-
name: "LogUpdateAuths",
|
|
540
|
-
type: {
|
|
541
|
-
kind: "struct",
|
|
542
|
-
fields: [
|
|
543
|
-
{
|
|
544
|
-
name: "auth_status",
|
|
545
|
-
type: {
|
|
546
|
-
vec: {
|
|
547
|
-
defined: {
|
|
548
|
-
name: "AddressBool"
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
]
|
|
554
|
-
}
|
|
555
|
-
},
|
|
556
|
-
{
|
|
557
|
-
name: "Oracle",
|
|
558
|
-
type: {
|
|
559
|
-
kind: "struct",
|
|
560
|
-
fields: [
|
|
561
|
-
{
|
|
562
|
-
name: "nonce",
|
|
563
|
-
type: "u16"
|
|
564
|
-
},
|
|
565
|
-
{
|
|
566
|
-
name: "sources",
|
|
567
|
-
type: {
|
|
568
|
-
vec: {
|
|
569
|
-
defined: {
|
|
570
|
-
name: "Sources"
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
},
|
|
575
|
-
{
|
|
576
|
-
name: "bump",
|
|
577
|
-
type: "u8"
|
|
578
|
-
}
|
|
579
|
-
]
|
|
580
|
-
}
|
|
581
|
-
},
|
|
582
|
-
{
|
|
583
|
-
name: "OracleAdmin",
|
|
584
|
-
type: {
|
|
585
|
-
kind: "struct",
|
|
586
|
-
fields: [
|
|
587
|
-
{
|
|
588
|
-
name: "authority",
|
|
589
|
-
type: "pubkey"
|
|
590
|
-
},
|
|
591
|
-
{
|
|
592
|
-
name: "auths",
|
|
593
|
-
type: {
|
|
594
|
-
vec: "pubkey"
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
]
|
|
598
|
-
}
|
|
599
|
-
},
|
|
600
|
-
{
|
|
601
|
-
name: "SourceType",
|
|
602
|
-
type: {
|
|
603
|
-
kind: "enum",
|
|
604
|
-
variants: [
|
|
605
|
-
{
|
|
606
|
-
name: "Pyth"
|
|
607
|
-
},
|
|
608
|
-
{
|
|
609
|
-
name: "StakePool"
|
|
610
|
-
},
|
|
611
|
-
{
|
|
612
|
-
name: "MsolPool"
|
|
613
|
-
},
|
|
614
|
-
{
|
|
615
|
-
name: "Redstone"
|
|
616
|
-
},
|
|
617
|
-
{
|
|
618
|
-
name: "Chainlink"
|
|
619
|
-
},
|
|
620
|
-
{
|
|
621
|
-
name: "SinglePool"
|
|
622
|
-
}
|
|
623
|
-
]
|
|
624
|
-
}
|
|
625
|
-
},
|
|
626
|
-
{
|
|
627
|
-
name: "Sources",
|
|
628
|
-
type: {
|
|
629
|
-
kind: "struct",
|
|
630
|
-
fields: [
|
|
631
|
-
{
|
|
632
|
-
name: "source",
|
|
633
|
-
type: "pubkey"
|
|
634
|
-
},
|
|
635
|
-
{
|
|
636
|
-
name: "invert",
|
|
637
|
-
type: "bool"
|
|
638
|
-
},
|
|
639
|
-
{
|
|
640
|
-
name: "multiplier",
|
|
641
|
-
type: "u128"
|
|
642
|
-
},
|
|
643
|
-
{
|
|
644
|
-
name: "divisor",
|
|
645
|
-
type: "u128"
|
|
646
|
-
},
|
|
647
|
-
{
|
|
648
|
-
name: "source_type",
|
|
649
|
-
type: {
|
|
650
|
-
defined: {
|
|
651
|
-
name: "SourceType"
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
]
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
];
|
|
659
|
-
const oracle = {
|
|
660
|
-
address: address,
|
|
661
|
-
metadata: metadata,
|
|
662
|
-
instructions: instructions,
|
|
663
|
-
accounts: accounts,
|
|
664
|
-
events: events,
|
|
665
|
-
errors: errors,
|
|
666
|
-
types: types
|
|
667
|
-
};
|
|
668
|
-
|
|
669
|
-
const MIN_TICK$1 = -16383;
|
|
670
|
-
const MAX_TICK$1 = 16383;
|
|
671
|
-
const ZERO_TICK_SCALED_RATIO$1 = new BN(281474976710656);
|
|
672
|
-
const TICK_HAS_DEBT_ARRAY_SIZE = 8;
|
|
673
|
-
const TICKS_PER_TICK_HAS_DEBT = TICK_HAS_DEBT_ARRAY_SIZE * 256;
|
|
674
|
-
const TICK_HAS_DEBT_CHILDREN_SIZE = 32;
|
|
675
|
-
const TICK_HAS_DEBT_CHILDREN_SIZE_IN_BITS = 256;
|
|
676
|
-
const TOTAL_INDICES_NEEDED = 16;
|
|
677
|
-
function getRatioAtTick(tick) {
|
|
678
|
-
if (tick < MIN_TICK$1 || tick > MAX_TICK$1) {
|
|
679
|
-
throw new Error(`Tick ${tick} out of range [${MIN_TICK$1}, ${MAX_TICK$1}]`);
|
|
680
|
-
}
|
|
681
|
-
const FACTOR00 = new BN("18446744073709551616");
|
|
682
|
-
const FACTOR01 = new BN("18419115400608638658");
|
|
683
|
-
const FACTOR02 = new BN("18391528108445969703");
|
|
684
|
-
const FACTOR03 = new BN("18336477419114433396");
|
|
685
|
-
const FACTOR04 = new BN("18226869890870665593");
|
|
686
|
-
const FACTOR05 = new BN("18009616477100071088");
|
|
687
|
-
const FACTOR06 = new BN("17582847377087825313");
|
|
688
|
-
const FACTOR07 = new BN("16759408633341240198");
|
|
689
|
-
const FACTOR08 = new BN("15226414841393184936");
|
|
690
|
-
const FACTOR09 = new BN("12568272644527235157");
|
|
691
|
-
const FACTOR10 = new BN("8563108841104354677");
|
|
692
|
-
const FACTOR11 = new BN("3975055583337633975");
|
|
693
|
-
const FACTOR12 = new BN("856577552520149366");
|
|
694
|
-
const FACTOR13 = new BN("39775317560084773");
|
|
695
|
-
const FACTOR14 = new BN("85764505686420");
|
|
696
|
-
const FACTOR15 = new BN("398745188");
|
|
697
|
-
const absTick = Math.abs(tick);
|
|
698
|
-
let factor = FACTOR00;
|
|
699
|
-
if (absTick & 1) factor = FACTOR01;
|
|
700
|
-
if (absTick & 2) factor = mulShift64(factor, FACTOR02);
|
|
701
|
-
if (absTick & 4) factor = mulShift64(factor, FACTOR03);
|
|
702
|
-
if (absTick & 8) factor = mulShift64(factor, FACTOR04);
|
|
703
|
-
if (absTick & 16) factor = mulShift64(factor, FACTOR05);
|
|
704
|
-
if (absTick & 32) factor = mulShift64(factor, FACTOR06);
|
|
705
|
-
if (absTick & 64) factor = mulShift64(factor, FACTOR07);
|
|
706
|
-
if (absTick & 128) factor = mulShift64(factor, FACTOR08);
|
|
707
|
-
if (absTick & 256) factor = mulShift64(factor, FACTOR09);
|
|
708
|
-
if (absTick & 512) factor = mulShift64(factor, FACTOR10);
|
|
709
|
-
if (absTick & 1024) factor = mulShift64(factor, FACTOR11);
|
|
710
|
-
if (absTick & 2048) factor = mulShift64(factor, FACTOR12);
|
|
711
|
-
if (absTick & 4096) factor = mulShift64(factor, FACTOR13);
|
|
712
|
-
if (absTick & 8192) factor = mulShift64(factor, FACTOR14);
|
|
713
|
-
if (absTick & 16384) factor = mulShift64(factor, FACTOR15);
|
|
714
|
-
let precision = new BN(0);
|
|
715
|
-
if (tick > 0) {
|
|
716
|
-
const maxU128 = new BN(2).pow(new BN(128)).sub(new BN(1));
|
|
717
|
-
factor = maxU128.div(factor);
|
|
718
|
-
if (!factor.mod(new BN(65536)).isZero()) {
|
|
719
|
-
precision = new BN(1);
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
const ratioX48 = factor.shrn(16).add(precision);
|
|
723
|
-
return ratioX48;
|
|
724
|
-
}
|
|
725
|
-
function mulShift64(n0, n1) {
|
|
726
|
-
try {
|
|
727
|
-
return n0.mul(n1).shrn(64);
|
|
728
|
-
} catch {
|
|
729
|
-
const product = n0.mul(n1);
|
|
730
|
-
return product.div(new BN(2).pow(new BN(64)));
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
function getTickAtRatio(ratioX48) {
|
|
734
|
-
const MIN_RATIOX48 = new BN(6093);
|
|
735
|
-
const MAX_RATIOX48 = new BN("13002088133096036565414295");
|
|
736
|
-
const _1E13 = new BN("10000000000000");
|
|
737
|
-
if (ratioX48.lt(MIN_RATIOX48) || ratioX48.gt(MAX_RATIOX48)) {
|
|
738
|
-
throw new Error(`Ratio ${ratioX48.toString()} out of bounds`);
|
|
739
|
-
}
|
|
740
|
-
const isNegative = ratioX48.lt(ZERO_TICK_SCALED_RATIO$1);
|
|
741
|
-
let factor;
|
|
742
|
-
factor = isNegative ? ZERO_TICK_SCALED_RATIO$1.mul(_1E13).div(ratioX48) : ratioX48.mul(_1E13).div(ZERO_TICK_SCALED_RATIO$1);
|
|
743
|
-
let tick = 0;
|
|
744
|
-
if (factor.gte(new BN("2150859953785115391"))) {
|
|
745
|
-
tick |= 8192;
|
|
746
|
-
factor = factor.mul(_1E13).div(new BN("2150859953785115391"));
|
|
747
|
-
}
|
|
748
|
-
if (factor.gte(new BN("4637736467054931"))) {
|
|
749
|
-
tick |= 4096;
|
|
750
|
-
factor = factor.mul(_1E13).div(new BN("4637736467054931"));
|
|
751
|
-
}
|
|
752
|
-
if (factor.gte(new BN("215354044936586"))) {
|
|
753
|
-
tick |= 2048;
|
|
754
|
-
factor = factor.mul(_1E13).div(new BN("215354044936586"));
|
|
755
|
-
}
|
|
756
|
-
if (factor.gte(new BN("46406254420777"))) {
|
|
757
|
-
tick |= 1024;
|
|
758
|
-
factor = factor.mul(_1E13).div(new BN("46406254420777"));
|
|
759
|
-
}
|
|
760
|
-
if (factor.gte(new BN("21542110950596"))) {
|
|
761
|
-
tick |= 512;
|
|
762
|
-
factor = factor.mul(_1E13).div(new BN("21542110950596"));
|
|
763
|
-
}
|
|
764
|
-
if (factor.gte(new BN("14677230989051"))) {
|
|
765
|
-
tick |= 256;
|
|
766
|
-
factor = factor.mul(_1E13).div(new BN("14677230989051"));
|
|
767
|
-
}
|
|
768
|
-
if (factor.gte(new BN("12114962232319"))) {
|
|
769
|
-
tick |= 128;
|
|
770
|
-
factor = factor.mul(_1E13).div(new BN("12114962232319"));
|
|
771
|
-
}
|
|
772
|
-
if (factor.gte(new BN("11006798913544"))) {
|
|
773
|
-
tick |= 64;
|
|
774
|
-
factor = factor.mul(_1E13).div(new BN("11006798913544"));
|
|
775
|
-
}
|
|
776
|
-
if (factor.gte(new BN("10491329235871"))) {
|
|
777
|
-
tick |= 32;
|
|
778
|
-
factor = factor.mul(_1E13).div(new BN("10491329235871"));
|
|
779
|
-
}
|
|
780
|
-
if (factor.gte(new BN("10242718992470"))) {
|
|
781
|
-
tick |= 16;
|
|
782
|
-
factor = factor.mul(_1E13).div(new BN("10242718992470"));
|
|
783
|
-
}
|
|
784
|
-
if (factor.gte(new BN("10120631893548"))) {
|
|
785
|
-
tick |= 8;
|
|
786
|
-
factor = factor.mul(_1E13).div(new BN("10120631893548"));
|
|
787
|
-
}
|
|
788
|
-
if (factor.gte(new BN("10060135135051"))) {
|
|
789
|
-
tick |= 4;
|
|
790
|
-
factor = factor.mul(_1E13).div(new BN("10060135135051"));
|
|
791
|
-
}
|
|
792
|
-
if (factor.gte(new BN("10030022500000"))) {
|
|
793
|
-
tick |= 2;
|
|
794
|
-
factor = factor.mul(_1E13).div(new BN("10030022500000"));
|
|
795
|
-
}
|
|
796
|
-
if (factor.gte(new BN("10015000000000"))) {
|
|
797
|
-
tick |= 1;
|
|
798
|
-
}
|
|
799
|
-
if (isNegative) {
|
|
800
|
-
tick = ~tick;
|
|
801
|
-
}
|
|
802
|
-
return tick;
|
|
803
|
-
}
|
|
804
|
-
function getFirstTickForIndex(index) {
|
|
805
|
-
if (index >= TOTAL_INDICES_NEEDED) {
|
|
806
|
-
throw new Error(
|
|
807
|
-
`Invalid index: ${index}. Must be between 0 and ${TOTAL_INDICES_NEEDED - 1}`
|
|
808
|
-
);
|
|
809
|
-
}
|
|
810
|
-
return MIN_TICK$1 + index * TICKS_PER_TICK_HAS_DEBT;
|
|
811
|
-
}
|
|
812
|
-
function getTickIndices(tick) {
|
|
813
|
-
if (tick < MIN_TICK$1 || tick > MAX_TICK$1) {
|
|
814
|
-
throw new Error("Tick out of range");
|
|
815
|
-
}
|
|
816
|
-
const tickOffset = tick - MIN_TICK$1;
|
|
817
|
-
const arrayIndex = Math.floor(tickOffset / TICKS_PER_TICK_HAS_DEBT);
|
|
818
|
-
const firstTickForIndex = getFirstTickForIndex(arrayIndex);
|
|
819
|
-
const tickWithinArray = tick - firstTickForIndex;
|
|
820
|
-
const mapIndex = Math.floor(
|
|
821
|
-
tickWithinArray / TICK_HAS_DEBT_CHILDREN_SIZE_IN_BITS
|
|
822
|
-
);
|
|
823
|
-
const tickWithinMap = tickWithinArray % TICK_HAS_DEBT_CHILDREN_SIZE_IN_BITS;
|
|
824
|
-
const byteIndex = Math.floor(tickWithinMap / 8);
|
|
825
|
-
const bitIndex = tickWithinMap % 8;
|
|
826
|
-
return { arrayIndex, mapIndex, byteIndex, bitIndex };
|
|
827
|
-
}
|
|
828
|
-
async function readTickHasDebtArray({
|
|
829
|
-
vaultId,
|
|
830
|
-
index,
|
|
831
|
-
program
|
|
832
|
-
}) {
|
|
833
|
-
const tickPda = getTickHasDebt(vaultId, index);
|
|
834
|
-
return await program.account.tickHasDebtArray.fetch(tickPda);
|
|
835
|
-
}
|
|
836
|
-
async function findNextTickWithDebt(vaultId, startTick, program) {
|
|
837
|
-
try {
|
|
838
|
-
const { arrayIndex, mapIndex, byteIndex, bitIndex } = getTickIndices(startTick);
|
|
839
|
-
let currentArrayIndex = arrayIndex;
|
|
840
|
-
let currentMapIndex = mapIndex;
|
|
841
|
-
let tickHasDebtData = await readTickHasDebtArray({
|
|
842
|
-
vaultId,
|
|
843
|
-
index: currentArrayIndex,
|
|
844
|
-
program
|
|
845
|
-
});
|
|
846
|
-
if (!tickHasDebtData) {
|
|
847
|
-
return MIN_TICK$1;
|
|
848
|
-
}
|
|
849
|
-
clearBitsInBitmap(tickHasDebtData, mapIndex, byteIndex, bitIndex);
|
|
850
|
-
while (true) {
|
|
851
|
-
const { nextTick, hasNextTick } = fetchNextTopTickFromBitmap(
|
|
852
|
-
tickHasDebtData,
|
|
853
|
-
currentMapIndex
|
|
854
|
-
);
|
|
855
|
-
if (hasNextTick && nextTick !== MIN_TICK$1) {
|
|
856
|
-
return nextTick;
|
|
857
|
-
}
|
|
858
|
-
if (currentArrayIndex === 0) {
|
|
859
|
-
return MIN_TICK$1;
|
|
860
|
-
}
|
|
861
|
-
currentArrayIndex -= 1;
|
|
862
|
-
currentMapIndex = TICK_HAS_DEBT_ARRAY_SIZE - 1;
|
|
863
|
-
tickHasDebtData = await readTickHasDebtArray({
|
|
864
|
-
vaultId,
|
|
865
|
-
index: currentArrayIndex,
|
|
866
|
-
program
|
|
867
|
-
});
|
|
868
|
-
if (!tickHasDebtData) {
|
|
869
|
-
return MIN_TICK$1;
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
} catch (error) {
|
|
873
|
-
console.warn(`Error finding next tick with debt:`, error);
|
|
874
|
-
return MIN_TICK$1;
|
|
875
|
-
}
|
|
876
|
-
}
|
|
877
|
-
function clearBitsInBitmap(tickHasDebtData, mapIndex, byteIndex, bitIndex) {
|
|
878
|
-
const bitmap = [...tickHasDebtData.tickHasDebt[mapIndex].childrenBits];
|
|
879
|
-
if (bitIndex > 0) {
|
|
880
|
-
const mask = (1 << bitIndex) - 1;
|
|
881
|
-
bitmap[byteIndex] &= mask;
|
|
882
|
-
} else {
|
|
883
|
-
bitmap[byteIndex] = 0;
|
|
884
|
-
}
|
|
885
|
-
for (let i = byteIndex + 1; i < TICK_HAS_DEBT_CHILDREN_SIZE; i++) {
|
|
886
|
-
bitmap[i] = 0;
|
|
887
|
-
}
|
|
888
|
-
tickHasDebtData.tickHasDebt[mapIndex].childrenBits = bitmap;
|
|
889
|
-
}
|
|
890
|
-
function fetchNextTopTickFromBitmap(tickHasDebtData, startMapIndex) {
|
|
891
|
-
let mapIndex = startMapIndex;
|
|
892
|
-
while (mapIndex >= 0) {
|
|
893
|
-
if (hasBitsInMap(tickHasDebtData, mapIndex)) {
|
|
894
|
-
const { nextTick, hasNextTick } = getNextTickFromMap(
|
|
895
|
-
tickHasDebtData,
|
|
896
|
-
mapIndex
|
|
897
|
-
);
|
|
898
|
-
if (hasNextTick) {
|
|
899
|
-
return { nextTick, hasNextTick: true };
|
|
900
|
-
}
|
|
901
|
-
}
|
|
902
|
-
mapIndex--;
|
|
903
|
-
}
|
|
904
|
-
return { nextTick: MIN_TICK$1, hasNextTick: false };
|
|
905
|
-
}
|
|
906
|
-
function hasBitsInMap(tickHasDebtData, mapIndex) {
|
|
907
|
-
const childrenBits = tickHasDebtData.tickHasDebt[mapIndex].childrenBits;
|
|
908
|
-
return childrenBits.some((byte) => byte !== 0);
|
|
909
|
-
}
|
|
910
|
-
function getNextTickFromMap(tickHasDebtData, mapIndex) {
|
|
911
|
-
const childrenBits = tickHasDebtData.tickHasDebt[mapIndex].childrenBits;
|
|
912
|
-
for (let byteIdx = TICK_HAS_DEBT_CHILDREN_SIZE - 1; byteIdx >= 0; byteIdx--) {
|
|
913
|
-
if (childrenBits[byteIdx] !== 0) {
|
|
914
|
-
const leadingZeros = getMostSignificantBit(childrenBits[byteIdx]);
|
|
915
|
-
const bitPos = 7 - leadingZeros;
|
|
916
|
-
const tickWithinMap = byteIdx * 8 + bitPos;
|
|
917
|
-
const mapFirstTick = getFirstTickForMapIndex(
|
|
918
|
-
tickHasDebtData.index,
|
|
919
|
-
mapIndex
|
|
920
|
-
);
|
|
921
|
-
return {
|
|
922
|
-
nextTick: mapFirstTick + tickWithinMap,
|
|
923
|
-
hasNextTick: true
|
|
924
|
-
};
|
|
925
|
-
}
|
|
926
|
-
}
|
|
927
|
-
return { nextTick: MIN_TICK$1, hasNextTick: false };
|
|
928
|
-
}
|
|
929
|
-
function getMostSignificantBit(byte) {
|
|
930
|
-
if (byte === 0) return 8;
|
|
931
|
-
let leadingZeros = 0;
|
|
932
|
-
let mask = 128;
|
|
933
|
-
while ((byte & mask) === 0 && leadingZeros < 8) {
|
|
934
|
-
leadingZeros++;
|
|
935
|
-
mask >>>= 1;
|
|
936
|
-
}
|
|
937
|
-
return leadingZeros;
|
|
938
|
-
}
|
|
939
|
-
function getFirstTickForMapIndex(arrayIndex, mapIndex) {
|
|
940
|
-
const arrayFirstTick = getFirstTickForIndex(arrayIndex);
|
|
941
|
-
return arrayFirstTick + mapIndex * TICK_HAS_DEBT_CHILDREN_SIZE_IN_BITS;
|
|
942
|
-
}
|
|
943
|
-
|
|
944
|
-
const COEFFICIENT_SIZE_DEBT_FACTOR = 35;
|
|
945
|
-
const EXPONENT_SIZE_DEBT_FACTOR = 15;
|
|
946
|
-
const EXPONENT_MAX_DEBT_FACTOR = new BN(1).shln(EXPONENT_SIZE_DEBT_FACTOR).subn(1);
|
|
947
|
-
const DECIMALS_DEBT_FACTOR = new BN(16384);
|
|
948
|
-
const MAX_MASK_DEBT_FACTOR$1 = new BN(1).shln(COEFFICIENT_SIZE_DEBT_FACTOR + EXPONENT_SIZE_DEBT_FACTOR).subn(1);
|
|
949
|
-
const PRECISION = 64;
|
|
950
|
-
const TWO_POWER_64 = new BN("18446744073709551615");
|
|
951
|
-
const TWO_POWER_69_MINUS_1 = new BN(1).shln(69).subn(1);
|
|
952
|
-
const COEFFICIENT_PLUS_PRECISION = COEFFICIENT_SIZE_DEBT_FACTOR + PRECISION;
|
|
953
|
-
const COEFFICIENT_PLUS_PRECISION_MINUS_1 = COEFFICIENT_PLUS_PRECISION - 1;
|
|
954
|
-
new BN(1).shln(COEFFICIENT_PLUS_PRECISION_MINUS_1).subn(1);
|
|
955
|
-
new BN(1).shln(COEFFICIENT_PLUS_PRECISION_MINUS_1 - 1).subn(1);
|
|
956
|
-
function mulDivNormal(normal, bigNumber1, bigNumber2) {
|
|
957
|
-
if (bigNumber1.isZero() || bigNumber2.isZero()) {
|
|
958
|
-
return new BN(0);
|
|
959
|
-
}
|
|
960
|
-
const exponent1 = bigNumber1.and(EXPONENT_MAX_DEBT_FACTOR);
|
|
961
|
-
const exponent2 = bigNumber2.and(EXPONENT_MAX_DEBT_FACTOR);
|
|
962
|
-
if (exponent2.lt(exponent1)) {
|
|
963
|
-
throw new Error("LibraryBnError: exponent2 should be >= exponent1");
|
|
964
|
-
}
|
|
965
|
-
const netExponent = exponent2.sub(exponent1);
|
|
966
|
-
if (netExponent.lt(new BN(129))) {
|
|
967
|
-
const coefficient1 = bigNumber1.shrn(EXPONENT_SIZE_DEBT_FACTOR);
|
|
968
|
-
const coefficient2 = bigNumber2.shrn(EXPONENT_SIZE_DEBT_FACTOR);
|
|
969
|
-
const numerator = normal.mul(coefficient1);
|
|
970
|
-
const denominator = coefficient2.shln(netExponent.toNumber());
|
|
971
|
-
if (denominator.isZero()) {
|
|
972
|
-
throw new Error("LibraryDivisionByZero");
|
|
973
|
-
}
|
|
974
|
-
const result = numerator.div(denominator);
|
|
975
|
-
if (result.gt(TWO_POWER_64)) {
|
|
976
|
-
throw new Error("LibraryBnError: result overflow");
|
|
977
|
-
}
|
|
978
|
-
return result;
|
|
979
|
-
} else {
|
|
980
|
-
return new BN(0);
|
|
981
|
-
}
|
|
982
|
-
}
|
|
983
|
-
function mulBigNumber(bigNumber1, bigNumber2) {
|
|
984
|
-
const coefficient1 = bigNumber1.shrn(EXPONENT_SIZE_DEBT_FACTOR);
|
|
985
|
-
const coefficient2 = bigNumber2.shrn(EXPONENT_SIZE_DEBT_FACTOR);
|
|
986
|
-
const exponent1 = bigNumber1.and(EXPONENT_MAX_DEBT_FACTOR);
|
|
987
|
-
const exponent2 = bigNumber2.and(EXPONENT_MAX_DEBT_FACTOR);
|
|
988
|
-
const resCoefficient = coefficient1.mul(coefficient2);
|
|
989
|
-
const overflowLen = resCoefficient.gt(TWO_POWER_69_MINUS_1) ? COEFFICIENT_SIZE_DEBT_FACTOR : COEFFICIENT_SIZE_DEBT_FACTOR - 1;
|
|
990
|
-
const adjustedCoefficient = resCoefficient.shrn(overflowLen);
|
|
991
|
-
const resExponent = exponent1.add(exponent2).add(new BN(overflowLen));
|
|
992
|
-
if (resExponent.lt(DECIMALS_DEBT_FACTOR)) {
|
|
993
|
-
throw new Error("LibraryBnError: exponent underflow");
|
|
994
|
-
}
|
|
995
|
-
const finalExponent = resExponent.sub(DECIMALS_DEBT_FACTOR);
|
|
996
|
-
if (finalExponent.gt(EXPONENT_MAX_DEBT_FACTOR)) {
|
|
997
|
-
return MAX_MASK_DEBT_FACTOR$1;
|
|
998
|
-
}
|
|
999
|
-
return adjustedCoefficient.shln(EXPONENT_SIZE_DEBT_FACTOR).or(finalExponent);
|
|
1000
|
-
}
|
|
1001
|
-
|
|
1002
|
-
const getVaultsProgram = ({
|
|
1003
|
-
connection,
|
|
1004
|
-
signer
|
|
1005
|
-
}) => new Program(vaults, {
|
|
1006
|
-
connection,
|
|
1007
|
-
publicKey: signer
|
|
1008
|
-
});
|
|
1009
|
-
const INIT_TICK = -2147483648;
|
|
1010
|
-
const MIN_TICK = -16383;
|
|
1011
|
-
const MAX_TICK = 16383;
|
|
1012
|
-
const MAX_MASK_DEBT_FACTOR = new BN("1125899906842623");
|
|
1013
|
-
const EXCHANGE_PRICES_PRECISION = new BN(10).pow(new BN(12));
|
|
1014
|
-
const ZERO_TICK_SCALED_RATIO = new BN(281474976710656);
|
|
1015
|
-
const TICK_SPACING = new BN(10015);
|
|
1016
|
-
const X30 = new BN(1073741823);
|
|
1017
|
-
const MIN_I128$1 = new BN("170141183460469231731687303715884105728").neg();
|
|
1018
|
-
const getAccountOwner = async (account, connection) => {
|
|
1019
|
-
const info = await connection.getAccountInfo(account);
|
|
1020
|
-
if (!info)
|
|
1021
|
-
throw new Error(`Account info not found for ${account.toString()}`);
|
|
1022
|
-
return info.owner;
|
|
1023
|
-
};
|
|
1024
|
-
const getCurrentPosition = async ({
|
|
1025
|
-
vaultId,
|
|
1026
|
-
positionId,
|
|
1027
|
-
connection
|
|
1028
|
-
}) => {
|
|
1029
|
-
const program = new Program(vaults, { connection });
|
|
1030
|
-
const position = await program.account.position.fetch(
|
|
1031
|
-
getPosition(vaultId, positionId)
|
|
1032
|
-
);
|
|
1033
|
-
return await getCurrentPositionState({
|
|
1034
|
-
vaultId,
|
|
1035
|
-
position,
|
|
1036
|
-
program
|
|
1037
|
-
});
|
|
1038
|
-
};
|
|
1039
|
-
const getCurrentPositionState = async ({
|
|
1040
|
-
vaultId,
|
|
1041
|
-
position,
|
|
1042
|
-
program
|
|
1043
|
-
}) => {
|
|
1044
|
-
let positionTick = position.tick;
|
|
1045
|
-
if (positionTick === INIT_TICK) {
|
|
1046
|
-
positionTick = MIN_TICK;
|
|
1047
|
-
}
|
|
1048
|
-
if (position.isSupplyOnlyPosition) {
|
|
1049
|
-
return {
|
|
1050
|
-
tick: MIN_TICK,
|
|
1051
|
-
tickId: 0,
|
|
1052
|
-
colRaw: new BN(position.supplyAmount.toString()),
|
|
1053
|
-
finalAmount: new BN(position.supplyAmount.toString()),
|
|
1054
|
-
debtRaw: new BN(0),
|
|
1055
|
-
dustDebtRaw: new BN(0),
|
|
1056
|
-
isSupplyOnlyPosition: true,
|
|
1057
|
-
userLiquidationStatus: false,
|
|
1058
|
-
postLiquidationBranchId: 0
|
|
1059
|
-
};
|
|
1060
|
-
}
|
|
1061
|
-
const colRaw = new BN(position.supplyAmount.toString());
|
|
1062
|
-
const dustDebtRaw = new BN(position.dustDebtAmount.toString());
|
|
1063
|
-
let debtRaw = new BN(0);
|
|
1064
|
-
if (positionTick > MIN_TICK) {
|
|
1065
|
-
const collateralForDebtCalc = colRaw.add(new BN(1));
|
|
1066
|
-
const ratio = getRatioAtTick(positionTick);
|
|
1067
|
-
debtRaw = ratio.mul(collateralForDebtCalc).shrn(48).add(new BN(1));
|
|
1068
|
-
} else {
|
|
1069
|
-
debtRaw = new BN(0);
|
|
1070
|
-
}
|
|
1071
|
-
let userLiquidationStatus = false;
|
|
1072
|
-
let postLiquidationBranchId = 0;
|
|
1073
|
-
if (positionTick > MIN_TICK) {
|
|
1074
|
-
const tickData = await program.account.tick.fetch(
|
|
1075
|
-
getTick(vaultId, positionTick)
|
|
1076
|
-
);
|
|
1077
|
-
if (tickData.isLiquidated || tickData.totalIds > position.tickId) {
|
|
1078
|
-
userLiquidationStatus = true;
|
|
1079
|
-
let [tickIdData, branches] = await Promise.all([
|
|
1080
|
-
program.account.tickIdLiquidation.fetch(
|
|
1081
|
-
getTickIdLiquidation(
|
|
1082
|
-
vaultId,
|
|
1083
|
-
positionTick,
|
|
1084
|
-
position.tickId
|
|
1085
|
-
)
|
|
1086
|
-
).catch(() => null),
|
|
1087
|
-
getAllBranches({ vaultId, program })
|
|
1088
|
-
]);
|
|
1089
|
-
if (!tickIdData) {
|
|
1090
|
-
tickIdData = {
|
|
1091
|
-
vaultId,
|
|
1092
|
-
tick: positionTick,
|
|
1093
|
-
tickMap: position.tickId,
|
|
1094
|
-
isFullyLiquidated1: 0,
|
|
1095
|
-
liquidationBranchId1: 0,
|
|
1096
|
-
debtFactor1: new BN(0),
|
|
1097
|
-
isFullyLiquidated2: 0,
|
|
1098
|
-
liquidationBranchId2: 0,
|
|
1099
|
-
debtFactor2: new BN(0),
|
|
1100
|
-
isFullyLiquidated3: 0,
|
|
1101
|
-
liquidationBranchId3: 0,
|
|
1102
|
-
debtFactor3: new BN(0)
|
|
1103
|
-
};
|
|
1104
|
-
}
|
|
1105
|
-
const { isFullyLiquidated, branchId, connectionFactor } = getLiquidationStatus(position.tickId, tickData, tickIdData);
|
|
1106
|
-
postLiquidationBranchId = branchId;
|
|
1107
|
-
if (isFullyLiquidated) {
|
|
1108
|
-
return {
|
|
1109
|
-
tick: MIN_TICK,
|
|
1110
|
-
tickId: 0,
|
|
1111
|
-
colRaw: new BN(0),
|
|
1112
|
-
debtRaw: new BN(0),
|
|
1113
|
-
dustDebtRaw: new BN(0),
|
|
1114
|
-
finalAmount: new BN(0),
|
|
1115
|
-
isSupplyOnlyPosition: true,
|
|
1116
|
-
userLiquidationStatus: true,
|
|
1117
|
-
postLiquidationBranchId: 0
|
|
1118
|
-
};
|
|
1119
|
-
}
|
|
1120
|
-
const { finalTick, finalColRaw, finalDebtRaw } = processLiquidatedPosition({
|
|
1121
|
-
branches,
|
|
1122
|
-
branchId: postLiquidationBranchId,
|
|
1123
|
-
initialConnectionFactor: connectionFactor,
|
|
1124
|
-
initialDebtRaw: debtRaw
|
|
1125
|
-
});
|
|
1126
|
-
const netDebtRaw2 = finalDebtRaw.gt(dustDebtRaw) ? finalDebtRaw.sub(dustDebtRaw) : new BN(0);
|
|
1127
|
-
return {
|
|
1128
|
-
tick: finalTick,
|
|
1129
|
-
tickId: position.tickId,
|
|
1130
|
-
colRaw: finalColRaw,
|
|
1131
|
-
debtRaw: finalDebtRaw,
|
|
1132
|
-
dustDebtRaw,
|
|
1133
|
-
finalAmount: netDebtRaw2.gt(new BN(0)) ? finalColRaw : new BN(0),
|
|
1134
|
-
isSupplyOnlyPosition: finalTick === MIN_TICK,
|
|
1135
|
-
userLiquidationStatus,
|
|
1136
|
-
postLiquidationBranchId
|
|
1137
|
-
};
|
|
1138
|
-
}
|
|
1139
|
-
}
|
|
1140
|
-
const netDebtRaw = debtRaw.gt(dustDebtRaw) ? debtRaw.sub(dustDebtRaw) : new BN(0);
|
|
1141
|
-
return {
|
|
1142
|
-
tick: positionTick,
|
|
1143
|
-
tickId: position.tickId,
|
|
1144
|
-
colRaw,
|
|
1145
|
-
debtRaw,
|
|
1146
|
-
dustDebtRaw,
|
|
1147
|
-
finalAmount: netDebtRaw.gt(new BN(0)) ? colRaw : new BN(0),
|
|
1148
|
-
isSupplyOnlyPosition: positionTick === MIN_TICK,
|
|
1149
|
-
userLiquidationStatus,
|
|
1150
|
-
postLiquidationBranchId
|
|
1151
|
-
};
|
|
1152
|
-
};
|
|
1153
|
-
async function getAllBranches({
|
|
1154
|
-
vaultId,
|
|
1155
|
-
program
|
|
1156
|
-
}) {
|
|
1157
|
-
const vaultState = await program.account.vaultState.fetch(
|
|
1158
|
-
getVaultState(vaultId)
|
|
1159
|
-
);
|
|
1160
|
-
const branchPromises = [];
|
|
1161
|
-
for (let i = 0; i <= vaultState.totalBranchId; i++) {
|
|
1162
|
-
branchPromises.push(
|
|
1163
|
-
program.account.branch.fetch(getBranch(vaultId, i)).catch(() => null)
|
|
1164
|
-
);
|
|
1165
|
-
}
|
|
1166
|
-
const branchResults = await Promise.all(branchPromises);
|
|
1167
|
-
const branches = branchResults.filter((branch) => branch !== null);
|
|
1168
|
-
return branches;
|
|
1169
|
-
}
|
|
1170
|
-
function getLiquidationStatus(positionTickId, tickData, tickIdData) {
|
|
1171
|
-
let isFullyLiquidated;
|
|
1172
|
-
let branchId;
|
|
1173
|
-
let connectionFactor;
|
|
1174
|
-
if (tickData.totalIds === positionTickId) {
|
|
1175
|
-
isFullyLiquidated = tickData.isFullyLiquidated === 1;
|
|
1176
|
-
branchId = tickData.liquidationBranchId;
|
|
1177
|
-
connectionFactor = tickData.debtFactor;
|
|
1178
|
-
} else {
|
|
1179
|
-
const setIndex = (positionTickId + 2) % 3;
|
|
1180
|
-
switch (setIndex) {
|
|
1181
|
-
case 0: {
|
|
1182
|
-
isFullyLiquidated = tickIdData.isFullyLiquidated1 === 1;
|
|
1183
|
-
branchId = tickIdData.liquidationBranchId1;
|
|
1184
|
-
connectionFactor = tickIdData.debtFactor1;
|
|
1185
|
-
break;
|
|
1186
|
-
}
|
|
1187
|
-
case 1: {
|
|
1188
|
-
isFullyLiquidated = tickIdData.isFullyLiquidated2 === 1;
|
|
1189
|
-
branchId = tickIdData.liquidationBranchId2;
|
|
1190
|
-
connectionFactor = tickIdData.debtFactor2;
|
|
1191
|
-
break;
|
|
1192
|
-
}
|
|
1193
|
-
default: {
|
|
1194
|
-
isFullyLiquidated = tickIdData.isFullyLiquidated3 === 1;
|
|
1195
|
-
branchId = tickIdData.liquidationBranchId3;
|
|
1196
|
-
connectionFactor = tickIdData.debtFactor3;
|
|
1197
|
-
}
|
|
1198
|
-
}
|
|
1199
|
-
}
|
|
1200
|
-
return { isFullyLiquidated, branchId, connectionFactor };
|
|
1201
|
-
}
|
|
1202
|
-
function processLiquidatedPosition({
|
|
1203
|
-
branches,
|
|
1204
|
-
branchId,
|
|
1205
|
-
initialConnectionFactor,
|
|
1206
|
-
initialDebtRaw
|
|
1207
|
-
}) {
|
|
1208
|
-
let finalColRaw = new BN(0);
|
|
1209
|
-
let finalTick;
|
|
1210
|
-
const branchMap = new Map(
|
|
1211
|
-
branches.map((branch) => [branch.branchId, branch])
|
|
1212
|
-
);
|
|
1213
|
-
let currentBranchId = branchId;
|
|
1214
|
-
let currentConnectionFactor = initialConnectionFactor;
|
|
1215
|
-
let currentBranch = branchMap.get(currentBranchId);
|
|
1216
|
-
if (!currentBranch) {
|
|
1217
|
-
throw new Error(`Branch ${currentBranchId} not found`);
|
|
1218
|
-
}
|
|
1219
|
-
while (currentBranch.status === 2) {
|
|
1220
|
-
currentConnectionFactor = mulBigNumber(
|
|
1221
|
-
currentConnectionFactor,
|
|
1222
|
-
new BN(currentBranch.debtFactor.toString())
|
|
1223
|
-
);
|
|
1224
|
-
if (currentConnectionFactor.eq(MAX_MASK_DEBT_FACTOR)) {
|
|
1225
|
-
break;
|
|
1226
|
-
}
|
|
1227
|
-
currentBranchId = currentBranch.connectedBranchId;
|
|
1228
|
-
currentBranch = branchMap.get(currentBranchId);
|
|
1229
|
-
if (!currentBranch) {
|
|
1230
|
-
throw new Error(`Connected branch ${currentBranchId} not found`);
|
|
1231
|
-
}
|
|
1232
|
-
}
|
|
1233
|
-
let positionDebtRaw = new BN(0);
|
|
1234
|
-
if (currentBranch.status === 3 || currentConnectionFactor.eq(MAX_MASK_DEBT_FACTOR)) {
|
|
1235
|
-
positionDebtRaw = new BN(0);
|
|
1236
|
-
finalTick = MIN_TICK;
|
|
1237
|
-
} else {
|
|
1238
|
-
positionDebtRaw = mulDivNormal(
|
|
1239
|
-
initialDebtRaw,
|
|
1240
|
-
currentBranch.debtFactor,
|
|
1241
|
-
currentConnectionFactor
|
|
1242
|
-
);
|
|
1243
|
-
positionDebtRaw = positionDebtRaw.gt(initialDebtRaw.div(new BN(100))) ? positionDebtRaw.mul(new BN(9999)).div(new BN(1e4)) : new BN(0);
|
|
1244
|
-
if (positionDebtRaw.gt(new BN(0))) {
|
|
1245
|
-
finalTick = currentBranch.minimaTick;
|
|
1246
|
-
const ratioAtTick = getRatioAtTick(finalTick);
|
|
1247
|
-
const ratioOneLess = ratioAtTick.mul(new BN(1e4)).div(TICK_SPACING);
|
|
1248
|
-
const ratioLength = ratioAtTick.sub(ratioOneLess);
|
|
1249
|
-
const finalRatio = ratioOneLess.add(
|
|
1250
|
-
ratioLength.mul(new BN(currentBranch.minimaTickPartials)).div(X30)
|
|
1251
|
-
);
|
|
1252
|
-
finalColRaw = positionDebtRaw.mul(ZERO_TICK_SCALED_RATIO).div(finalRatio);
|
|
1253
|
-
} else finalTick = MIN_TICK;
|
|
1254
|
-
}
|
|
1255
|
-
return {
|
|
1256
|
-
finalTick,
|
|
1257
|
-
finalColRaw,
|
|
1258
|
-
finalDebtRaw: positionDebtRaw
|
|
1259
|
-
};
|
|
1260
|
-
}
|
|
1261
|
-
const getFinalPosition = async ({
|
|
1262
|
-
vaultId,
|
|
1263
|
-
currentPosition,
|
|
1264
|
-
newColAmount,
|
|
1265
|
-
newDebtAmount,
|
|
1266
|
-
program,
|
|
1267
|
-
connection,
|
|
1268
|
-
signer
|
|
1269
|
-
}) => {
|
|
1270
|
-
program = program ?? getVaultsProgram({ connection, signer });
|
|
1271
|
-
const vaultConfig = await program.account.vaultConfig.fetch(
|
|
1272
|
-
getVaultConfig(vaultId)
|
|
1273
|
-
);
|
|
1274
|
-
const {
|
|
1275
|
-
vaultSupplyExchangePrice: supplyExPrice,
|
|
1276
|
-
vaultBorrowExchangePrice: borrowExPrice
|
|
1277
|
-
} = await getExchangePrices({
|
|
1278
|
-
vaultId,
|
|
1279
|
-
vaultConfig,
|
|
1280
|
-
connection,
|
|
1281
|
-
signer
|
|
1282
|
-
});
|
|
1283
|
-
const borrowFee = vaultConfig.borrowFee;
|
|
1284
|
-
let { colRaw, debtRaw, dustDebtRaw } = currentPosition;
|
|
1285
|
-
if (newColAmount.gt(new BN(0))) {
|
|
1286
|
-
const supplyRaw = newColAmount.mul(EXCHANGE_PRICES_PRECISION).div(supplyExPrice);
|
|
1287
|
-
colRaw = colRaw.add(supplyRaw);
|
|
1288
|
-
} else if (newColAmount.lt(new BN(0))) {
|
|
1289
|
-
let withdrawRaw = new BN(0);
|
|
1290
|
-
if (newColAmount.gt(MIN_I128$1)) {
|
|
1291
|
-
withdrawRaw = newColAmount.abs().mul(EXCHANGE_PRICES_PRECISION).div(supplyExPrice).sub(new BN(1));
|
|
1292
|
-
colRaw = colRaw.sub(withdrawRaw);
|
|
1293
|
-
} else if (newColAmount.eq(MIN_I128$1)) {
|
|
1294
|
-
withdrawRaw = colRaw.mul(supplyExPrice).div(EXCHANGE_PRICES_PRECISION).mul(new BN(-1)).add(new BN(1));
|
|
1295
|
-
colRaw = new BN(0);
|
|
1296
|
-
} else {
|
|
1297
|
-
throw new Error("Invalid newColAmount");
|
|
1298
|
-
}
|
|
1299
|
-
}
|
|
1300
|
-
if (newDebtAmount.gt(new BN(0))) {
|
|
1301
|
-
const borrowRaw = newDebtAmount.mul(EXCHANGE_PRICES_PRECISION).div(borrowExPrice).add(new BN(1));
|
|
1302
|
-
const feeAmount = borrowRaw.mul(new BN(borrowFee)).div(new BN(1e4));
|
|
1303
|
-
const borrowAmountWithFee = borrowRaw.add(feeAmount);
|
|
1304
|
-
debtRaw = debtRaw.add(borrowAmountWithFee);
|
|
1305
|
-
} else if (newDebtAmount.lt(new BN(0))) {
|
|
1306
|
-
if (newDebtAmount.gt(MIN_I128$1)) {
|
|
1307
|
-
const payback_amount = newDebtAmount.abs().mul(EXCHANGE_PRICES_PRECISION).div(borrowExPrice).add(new BN(1));
|
|
1308
|
-
debtRaw = debtRaw.sub(payback_amount);
|
|
1309
|
-
} else if (newDebtAmount.eq(MIN_I128$1)) {
|
|
1310
|
-
debtRaw = new BN(0);
|
|
1311
|
-
} else {
|
|
1312
|
-
throw new Error("Invalid newDebtAmount");
|
|
1313
|
-
}
|
|
1314
|
-
}
|
|
1315
|
-
const netDebtRaw = debtRaw.gt(dustDebtRaw) ? debtRaw.sub(dustDebtRaw) : new BN(0);
|
|
1316
|
-
let finalTick;
|
|
1317
|
-
let isSupplyOnlyPosition;
|
|
1318
|
-
if (netDebtRaw.eq(new BN(0)) || colRaw.eq(new BN(0))) {
|
|
1319
|
-
finalTick = MIN_TICK;
|
|
1320
|
-
isSupplyOnlyPosition = true;
|
|
1321
|
-
} else {
|
|
1322
|
-
const marginAdjustedDebt = netDebtRaw.mul(new BN(1000000001)).div(new BN(1e9)).add(new BN(1));
|
|
1323
|
-
const ratio = marginAdjustedDebt.mul(ZERO_TICK_SCALED_RATIO).div(colRaw);
|
|
1324
|
-
const baseTickAtRatio = getTickAtRatio(ratio);
|
|
1325
|
-
finalTick = baseTickAtRatio + 1;
|
|
1326
|
-
if (finalTick < MIN_TICK) {
|
|
1327
|
-
finalTick = MIN_TICK;
|
|
1328
|
-
} else if (finalTick > MAX_TICK) {
|
|
1329
|
-
finalTick = MAX_TICK;
|
|
1330
|
-
}
|
|
1331
|
-
isSupplyOnlyPosition = false;
|
|
1332
|
-
}
|
|
1333
|
-
return {
|
|
1334
|
-
tick: finalTick,
|
|
1335
|
-
tickId: currentPosition.tickId,
|
|
1336
|
-
colRaw,
|
|
1337
|
-
debtRaw,
|
|
1338
|
-
dustDebtRaw,
|
|
1339
|
-
finalAmount: netDebtRaw.gt(new BN(0)) ? colRaw : new BN(0),
|
|
1340
|
-
isSupplyOnlyPosition
|
|
1341
|
-
};
|
|
1342
|
-
};
|
|
1343
|
-
async function loadRelevantBranches(vaultId, vaultState, liquidationStatus, postLiquidationBranchId, program) {
|
|
1344
|
-
const addedBranchIds = /* @__PURE__ */ new Set();
|
|
1345
|
-
const currentBranchId = postLiquidationBranchId > 0 ? postLiquidationBranchId : vaultState.currentBranchId;
|
|
1346
|
-
let connectedBranchId = 0;
|
|
1347
|
-
if (currentBranchId > 0) {
|
|
1348
|
-
try {
|
|
1349
|
-
const currentBranch = await program.account.branch.fetch(
|
|
1350
|
-
getBranch(vaultId, currentBranchId)
|
|
1351
|
-
);
|
|
1352
|
-
if (currentBranch) {
|
|
1353
|
-
addedBranchIds.add(currentBranch.branchId);
|
|
1354
|
-
connectedBranchId = currentBranch.connectedBranchId;
|
|
1355
|
-
}
|
|
1356
|
-
} catch (error) {
|
|
1357
|
-
console.warn(`Failed to fetch current branch ${currentBranchId}:`, error);
|
|
1358
|
-
}
|
|
1359
|
-
}
|
|
1360
|
-
if (liquidationStatus) {
|
|
1361
|
-
while (connectedBranchId > 0) {
|
|
1362
|
-
try {
|
|
1363
|
-
const connectedBranch = await program.account.branch.fetch(
|
|
1364
|
-
getBranch(vaultId, connectedBranchId)
|
|
1365
|
-
);
|
|
1366
|
-
if (connectedBranch) {
|
|
1367
|
-
if (!addedBranchIds.has(connectedBranch.branchId))
|
|
1368
|
-
addedBranchIds.add(connectedBranch.branchId);
|
|
1369
|
-
connectedBranchId = connectedBranch.connectedBranchId;
|
|
1370
|
-
} else break;
|
|
1371
|
-
} catch (error) {
|
|
1372
|
-
console.warn(
|
|
1373
|
-
`Failed to fetch connected branch ${connectedBranchId}:`,
|
|
1374
|
-
error
|
|
1375
|
-
);
|
|
1376
|
-
break;
|
|
1377
|
-
}
|
|
1378
|
-
}
|
|
1379
|
-
if (!addedBranchIds.has(0)) addedBranchIds.add(0);
|
|
1380
|
-
}
|
|
1381
|
-
return [...addedBranchIds];
|
|
1382
|
-
}
|
|
1383
|
-
async function loadRelevantTicksHasDebtArrays(vaultId, topTick, existingPositionTick, finalTick, program) {
|
|
1384
|
-
const tickHasDebtArrays = /* @__PURE__ */ new Set();
|
|
1385
|
-
if (existingPositionTick == topTick) {
|
|
1386
|
-
let nextTickWithDebt = await findNextTickWithDebt(
|
|
1387
|
-
vaultId,
|
|
1388
|
-
topTick,
|
|
1389
|
-
program
|
|
1390
|
-
);
|
|
1391
|
-
let { arrayIndex: startIndex } = getTickIndices(nextTickWithDebt);
|
|
1392
|
-
let { arrayIndex: endIndex } = getTickIndices(topTick);
|
|
1393
|
-
let { arrayIndex: finalTickIndex } = getTickIndices(finalTick);
|
|
1394
|
-
let finalTickHasDebtPda = getTickHasDebt(vaultId, finalTickIndex);
|
|
1395
|
-
tickHasDebtArrays.add(finalTickHasDebtPda);
|
|
1396
|
-
if (endIndex < 15) endIndex++;
|
|
1397
|
-
try {
|
|
1398
|
-
for (let arrIdx = startIndex; arrIdx <= endIndex; arrIdx++)
|
|
1399
|
-
tickHasDebtArrays.add(getTickHasDebt(vaultId, arrIdx));
|
|
1400
|
-
} catch (error) {
|
|
1401
|
-
console.warn(`Error finding next tick with debt:`, error);
|
|
1402
|
-
}
|
|
1403
|
-
} else {
|
|
1404
|
-
let { arrayIndex: finalTickIndex } = getTickIndices(finalTick);
|
|
1405
|
-
let { arrayIndex: existingPositionTickIndex } = getTickIndices(existingPositionTick);
|
|
1406
|
-
tickHasDebtArrays.add(getTickHasDebt(vaultId, finalTickIndex));
|
|
1407
|
-
tickHasDebtArrays.add(
|
|
1408
|
-
getTickHasDebt(vaultId, existingPositionTickIndex)
|
|
1409
|
-
);
|
|
1410
|
-
}
|
|
1411
|
-
return [...tickHasDebtArrays];
|
|
1412
|
-
}
|
|
1413
|
-
async function getExchangePrices({
|
|
1414
|
-
vaultId,
|
|
1415
|
-
vaultConfig,
|
|
1416
|
-
connection,
|
|
1417
|
-
signer
|
|
1418
|
-
}) {
|
|
1419
|
-
const program = new Program(vaults, { connection });
|
|
1420
|
-
const ix = await program.methods.getExchangePrices().accounts({
|
|
1421
|
-
vaultState: getVaultState(vaultId),
|
|
1422
|
-
vaultConfig: getVaultConfig(vaultId),
|
|
1423
|
-
supplyTokenReserves: getReserve(vaultConfig.supplyToken),
|
|
1424
|
-
borrowTokenReserves: getReserve(vaultConfig.borrowToken)
|
|
1425
|
-
}).instruction();
|
|
1426
|
-
const transaction = new Transaction().add(ix);
|
|
1427
|
-
const latestBlockHash = await connection.getLatestBlockhash();
|
|
1428
|
-
transaction.recentBlockhash = latestBlockHash.blockhash;
|
|
1429
|
-
transaction.feePayer = signer;
|
|
1430
|
-
const raw = await connection.simulateTransaction(transaction);
|
|
1431
|
-
if (raw.value.err && raw.value.err === "InvalidAccountForFee" && signer.toBase58() !== "HEyJLdMfZhhQ7FHCtjD5DWDFNFQhaeAVAsHeWqoY6dSD") {
|
|
1432
|
-
return await getExchangePrices({
|
|
1433
|
-
vaultId,
|
|
1434
|
-
vaultConfig,
|
|
1435
|
-
connection,
|
|
1436
|
-
signer: new PublicKey("HEyJLdMfZhhQ7FHCtjD5DWDFNFQhaeAVAsHeWqoY6dSD")
|
|
1437
|
-
});
|
|
1438
|
-
}
|
|
1439
|
-
const returnLog = raw.value.logs?.find(
|
|
1440
|
-
(log) => log.startsWith("Program return:")
|
|
1441
|
-
);
|
|
1442
|
-
if (!returnLog) {
|
|
1443
|
-
let error = new Error("No return data found in logs");
|
|
1444
|
-
error.simulation = raw.value;
|
|
1445
|
-
throw error;
|
|
1446
|
-
}
|
|
1447
|
-
const base64Data = returnLog.split(" ")[3];
|
|
1448
|
-
const buffer = Buffer.from(base64Data, "base64");
|
|
1449
|
-
const liquiditySupplyExchangePrice = new BN(buffer.subarray(0, 16), "le");
|
|
1450
|
-
const liquidityBorrowExchangePrice = new BN(buffer.subarray(16, 32), "le");
|
|
1451
|
-
const vaultSupplyExchangePrice = new BN(buffer.subarray(32, 48), "le");
|
|
1452
|
-
const vaultBorrowExchangePrice = new BN(buffer.subarray(48, 64), "le");
|
|
1453
|
-
return {
|
|
1454
|
-
liquiditySupplyExchangePrice,
|
|
1455
|
-
liquidityBorrowExchangePrice,
|
|
1456
|
-
vaultSupplyExchangePrice,
|
|
1457
|
-
vaultBorrowExchangePrice
|
|
1458
|
-
};
|
|
1459
|
-
}
|
|
1460
|
-
async function loadRelevantTicksHasDebtArraysLiquidate(vaultId, topTick, nextTick, program) {
|
|
1461
|
-
const { arrayIndex: topTickIndex } = getTickIndices(topTick);
|
|
1462
|
-
const { arrayIndex: nextTickIndex } = getTickIndices(nextTick);
|
|
1463
|
-
const promises = [];
|
|
1464
|
-
for (let arrIdx = topTickIndex; arrIdx >= nextTickIndex; arrIdx--) {
|
|
1465
|
-
promises.push(
|
|
1466
|
-
program.account.tickHasDebtArray.fetch(
|
|
1467
|
-
getTickHasDebt(vaultId, arrIdx)
|
|
1468
|
-
)
|
|
1469
|
-
);
|
|
1470
|
-
}
|
|
1471
|
-
const results = await Promise.allSettled(promises);
|
|
1472
|
-
const tickHasDebtArrays = results.filter((result) => result.status === "fulfilled").map(
|
|
1473
|
-
(result) => result.value
|
|
1474
|
-
);
|
|
1475
|
-
return tickHasDebtArrays;
|
|
1476
|
-
}
|
|
1477
|
-
async function loadRelevantBranchesForLiquidate(vaultId, vaultState, program) {
|
|
1478
|
-
const branches = [];
|
|
1479
|
-
const currentBranchId = vaultState.currentBranchId;
|
|
1480
|
-
if (currentBranchId > 0) {
|
|
1481
|
-
try {
|
|
1482
|
-
const currentBranch = await program.account.branch.fetch(
|
|
1483
|
-
getBranch(vaultId, currentBranchId)
|
|
1484
|
-
);
|
|
1485
|
-
if (currentBranch) branches.push(currentBranch);
|
|
1486
|
-
} catch (error) {
|
|
1487
|
-
console.warn(`Failed to fetch current branch ${currentBranchId}:`, error);
|
|
1488
|
-
}
|
|
1489
|
-
}
|
|
1490
|
-
let connectedBranchId = branches[0].connectedBranchId;
|
|
1491
|
-
const doesBranchExist = (branchId) => branches.some((b) => b.branchId === branchId);
|
|
1492
|
-
while (!doesBranchExist(connectedBranchId)) {
|
|
1493
|
-
try {
|
|
1494
|
-
const connectedBranch = await program.account.branch.fetch(
|
|
1495
|
-
getBranch(vaultId, connectedBranchId)
|
|
1496
|
-
);
|
|
1497
|
-
connectedBranchId = connectedBranch.connectedBranchId;
|
|
1498
|
-
if (connectedBranch) branches.push(connectedBranch);
|
|
1499
|
-
} catch (error) {
|
|
1500
|
-
console.warn(`Failed to fetch connected branch ${connectedBranchId}:`, error);
|
|
1501
|
-
}
|
|
1502
|
-
}
|
|
1503
|
-
if (!doesBranchExist(0)) branches.push({ branchId: 0 });
|
|
1504
|
-
return branches;
|
|
1505
|
-
}
|
|
1506
|
-
async function readOraclePrice({
|
|
1507
|
-
connection,
|
|
1508
|
-
signer,
|
|
1509
|
-
oracle: oracle$1
|
|
1510
|
-
}) {
|
|
1511
|
-
const program = new Program(
|
|
1512
|
-
oracle,
|
|
1513
|
-
new AnchorProvider(connection, {
|
|
1514
|
-
signTransaction() {
|
|
1515
|
-
throw new Error("Not implemented");
|
|
1516
|
-
},
|
|
1517
|
-
signAllTransactions() {
|
|
1518
|
-
throw new Error("Not implemented");
|
|
1519
|
-
},
|
|
1520
|
-
publicKey: signer ?? new PublicKey("HEyJLdMfZhhQ7FHCtjD5DWDFNFQhaeAVAsHeWqoY6dSD")
|
|
1521
|
-
})
|
|
1522
|
-
);
|
|
1523
|
-
const oracleData = await program.account.oracle.fetch(oracle$1);
|
|
1524
|
-
let remainingAccounts = [];
|
|
1525
|
-
for (const source of oracleData.sources) {
|
|
1526
|
-
remainingAccounts.push({
|
|
1527
|
-
pubkey: source.source,
|
|
1528
|
-
isWritable: false,
|
|
1529
|
-
isSigner: false
|
|
1530
|
-
});
|
|
1531
|
-
}
|
|
1532
|
-
const [oraclePriceOperate, oraclePriceLiquidate] = await Promise.all([
|
|
1533
|
-
program.methods.getExchangeRateOperate(oracleData.nonce).accounts({ oracle: oracle$1 }).remainingAccounts(remainingAccounts).view(),
|
|
1534
|
-
program.methods.getExchangeRateLiquidate(oracleData.nonce).accounts({ oracle: oracle$1 }).remainingAccounts(remainingAccounts).view()
|
|
1535
|
-
]);
|
|
1536
|
-
return {
|
|
1537
|
-
oraclePriceOperate,
|
|
1538
|
-
oraclePriceLiquidate,
|
|
1539
|
-
oracleSources: oracleData.sources
|
|
1540
|
-
};
|
|
1541
|
-
}
|
|
1542
|
-
|
|
1543
|
-
const MPL_TOKEN_METADATA_PROGRAM_ID = new PublicKey(
|
|
1544
|
-
"metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"
|
|
1545
|
-
);
|
|
1546
|
-
const LIQUIDITY_PROGRAM_ID = new PublicKey(liquidity.address);
|
|
1547
|
-
const MIN_I128 = new BN("170141183460469231731687303715884105728").neg();
|
|
1548
|
-
async function getOtherInstructionsOperate(vaultId, vaultState, currentPosition, finalPosition, currentTick, program, signer) {
|
|
1549
|
-
const otherIxs = [];
|
|
1550
|
-
const tickToRead = [currentTick];
|
|
1551
|
-
let currentTickData;
|
|
1552
|
-
let finalTickData;
|
|
1553
|
-
tickToRead.push(currentPosition.tick);
|
|
1554
|
-
tickToRead.push(finalPosition.tick);
|
|
1555
|
-
if (tickToRead.length > 0) {
|
|
1556
|
-
const tickData = await program.account.tick.fetchMultiple(
|
|
1557
|
-
tickToRead.map((tick) => getTick(vaultId, tick))
|
|
1558
|
-
);
|
|
1559
|
-
currentTickData = tickData[0];
|
|
1560
|
-
finalTickData = tickData[2];
|
|
1561
|
-
for (const [i, tickDatum] of tickData.entries()) {
|
|
1562
|
-
if (!tickDatum) {
|
|
1563
|
-
const ix = await program.methods.initTick(vaultId, tickToRead[i]).accounts(getInitTickContext(vaultId, tickToRead[i], signer)).instruction();
|
|
1564
|
-
otherIxs.push(ix);
|
|
1565
|
-
}
|
|
1566
|
-
}
|
|
1567
|
-
}
|
|
1568
|
-
let newBranchId;
|
|
1569
|
-
if (vaultState.branchLiquidated) {
|
|
1570
|
-
newBranchId = vaultState.totalBranchId + 1;
|
|
1571
|
-
const newBranchData = await program.account.branch.fetch(
|
|
1572
|
-
getBranch(vaultId, newBranchId)
|
|
1573
|
-
);
|
|
1574
|
-
if (!newBranchData) {
|
|
1575
|
-
const ix = await program.methods.initBranch(vaultId, newBranchId).accounts(getInitBranchContext(vaultId, newBranchId, signer)).instruction();
|
|
1576
|
-
otherIxs.push(ix);
|
|
1577
|
-
}
|
|
1578
|
-
} else {
|
|
1579
|
-
newBranchId = vaultState.currentBranchId;
|
|
1580
|
-
}
|
|
1581
|
-
const newBranchPda = getBranch(vaultId, newBranchId);
|
|
1582
|
-
const currentTickIdDataPda = getTickIdLiquidation(
|
|
1583
|
-
vaultId,
|
|
1584
|
-
currentTick,
|
|
1585
|
-
currentTickData ? currentTickData.totalIds : 0
|
|
1586
|
-
);
|
|
1587
|
-
const tickIdsToRead = [
|
|
1588
|
-
{
|
|
1589
|
-
tick: currentTick,
|
|
1590
|
-
totalIds: currentTickData ? currentTickData.totalIds : 0
|
|
1591
|
-
}
|
|
1592
|
-
];
|
|
1593
|
-
const finalTickIdDataPda = getTickIdLiquidation(
|
|
1594
|
-
vaultId,
|
|
1595
|
-
finalPosition.tick,
|
|
1596
|
-
finalTickData ? finalTickData.totalIds : 0
|
|
1597
|
-
);
|
|
1598
|
-
if (finalPosition.tick !== currentTick)
|
|
1599
|
-
if (finalTickData) {
|
|
1600
|
-
tickIdsToRead.push({
|
|
1601
|
-
tick: finalPosition.tick,
|
|
1602
|
-
totalIds: finalTickData.totalIds
|
|
1603
|
-
});
|
|
1604
|
-
} else {
|
|
1605
|
-
const context = await getInitTickIdLiquidationContext(
|
|
1606
|
-
vaultId,
|
|
1607
|
-
finalPosition.tick,
|
|
1608
|
-
signer,
|
|
1609
|
-
program
|
|
1610
|
-
);
|
|
1611
|
-
const ix = await program.methods.initTickIdLiquidation(vaultId, finalPosition.tick, 0).accounts(context).instruction();
|
|
1612
|
-
otherIxs.push(ix);
|
|
1613
|
-
}
|
|
1614
|
-
const tickIdData = await program.account.tickIdLiquidation.fetchMultiple(
|
|
1615
|
-
tickIdsToRead.map(
|
|
1616
|
-
({ tick, totalIds }) => getTickIdLiquidation(vaultId, tick, totalIds)
|
|
1617
|
-
)
|
|
1618
|
-
);
|
|
1619
|
-
if (tickIdData.length > 0) {
|
|
1620
|
-
for (const [i, tickIdDatum] of tickIdData.entries()) {
|
|
1621
|
-
if (!tickIdDatum) {
|
|
1622
|
-
const ix = await program.methods.initTickIdLiquidation(
|
|
1623
|
-
vaultId,
|
|
1624
|
-
tickIdsToRead[i].tick,
|
|
1625
|
-
tickIdsToRead[i].totalIds
|
|
1626
|
-
).accounts(
|
|
1627
|
-
await getInitTickIdLiquidationContext(
|
|
1628
|
-
vaultId,
|
|
1629
|
-
tickIdsToRead[i].tick,
|
|
1630
|
-
signer,
|
|
1631
|
-
program
|
|
1632
|
-
)
|
|
1633
|
-
).instruction();
|
|
1634
|
-
otherIxs.push(ix);
|
|
1635
|
-
}
|
|
1636
|
-
}
|
|
1637
|
-
}
|
|
1638
|
-
return {
|
|
1639
|
-
otherIxs,
|
|
1640
|
-
newBranchPda,
|
|
1641
|
-
currentTickIdDataPda,
|
|
1642
|
-
finalTickIdDataPda
|
|
1643
|
-
};
|
|
1644
|
-
}
|
|
1645
|
-
const tickHelper = (tickValue) => {
|
|
1646
|
-
return tickValue === 0 ? INIT_TICK : tickValue;
|
|
1647
|
-
};
|
|
1648
|
-
async function getRemainingAccountsOperate(vaultId, vaultState, vaultConfig, finalPositionTick, existingPositionTick, liquidationStatus, postLiquidationBranchId, program) {
|
|
1649
|
-
const remainingAccounts = [];
|
|
1650
|
-
const oracleProgram = new Program(oracle, program.provider);
|
|
1651
|
-
const [oracleData, branches, tickHasDebt] = await Promise.all([
|
|
1652
|
-
oracleProgram.account.oracle.fetch(new PublicKey(vaultConfig.oracle)),
|
|
1653
|
-
// Add branch accounts (next 10 remaining accounts)
|
|
1654
|
-
loadRelevantBranches(
|
|
1655
|
-
vaultId,
|
|
1656
|
-
vaultState,
|
|
1657
|
-
liquidationStatus,
|
|
1658
|
-
postLiquidationBranchId,
|
|
1659
|
-
program
|
|
1660
|
-
),
|
|
1661
|
-
loadRelevantTicksHasDebtArrays(
|
|
1662
|
-
vaultId,
|
|
1663
|
-
tickHelper(vaultState.topmostTick),
|
|
1664
|
-
existingPositionTick,
|
|
1665
|
-
finalPositionTick,
|
|
1666
|
-
program
|
|
1667
|
-
)
|
|
1668
|
-
]);
|
|
1669
|
-
const sourceLength = oracleData.sources.length;
|
|
1670
|
-
for (const source of oracleData.sources)
|
|
1671
|
-
remainingAccounts.push({
|
|
1672
|
-
pubkey: new PublicKey(source.source),
|
|
1673
|
-
isWritable: false,
|
|
1674
|
-
isSigner: false
|
|
1675
|
-
});
|
|
1676
|
-
const branchLength = branches.length;
|
|
1677
|
-
for (const branch of branches) {
|
|
1678
|
-
remainingAccounts.push({
|
|
1679
|
-
pubkey: getBranch(vaultId, branch),
|
|
1680
|
-
isWritable: true,
|
|
1681
|
-
isSigner: false
|
|
1682
|
-
});
|
|
1683
|
-
}
|
|
1684
|
-
const tickHasDebtLength = tickHasDebt.length;
|
|
1685
|
-
for (const tickHasDebtArray of tickHasDebt)
|
|
1686
|
-
remainingAccounts.push({
|
|
1687
|
-
pubkey: tickHasDebtArray,
|
|
1688
|
-
isWritable: true,
|
|
1689
|
-
isSigner: false
|
|
1690
|
-
});
|
|
1691
|
-
const remainingAccountsIndices = [
|
|
1692
|
-
sourceLength,
|
|
1693
|
-
branchLength,
|
|
1694
|
-
tickHasDebtLength
|
|
1695
|
-
];
|
|
1696
|
-
return {
|
|
1697
|
-
remainingAccounts,
|
|
1698
|
-
remainingAccountsIndices
|
|
1699
|
-
};
|
|
1700
|
-
}
|
|
1701
|
-
async function getOperateContext({
|
|
1702
|
-
vaultId,
|
|
1703
|
-
positionId,
|
|
1704
|
-
program,
|
|
1705
|
-
connection,
|
|
1706
|
-
signer,
|
|
1707
|
-
positionOwner = signer,
|
|
1708
|
-
colAmount: newCol,
|
|
1709
|
-
debtAmount: newDebt,
|
|
1710
|
-
recipient
|
|
1711
|
-
}) {
|
|
1712
|
-
program = program ?? getVaultsProgram({ connection, signer });
|
|
1713
|
-
const [vaultState, vaultConfig, vaultMetadata] = await Promise.all([
|
|
1714
|
-
program.account.vaultState.fetch(getVaultState(vaultId)),
|
|
1715
|
-
program.account.vaultConfig.fetch(getVaultConfig(vaultId)),
|
|
1716
|
-
program.account.vaultMetadata.fetch(getVaultMetadata(vaultId))
|
|
1717
|
-
]);
|
|
1718
|
-
const [supplyTokenProgram, borrowTokenProgram] = await Promise.all([
|
|
1719
|
-
getAccountOwner(vaultConfig.supplyToken, connection),
|
|
1720
|
-
getAccountOwner(vaultConfig.borrowToken, connection)
|
|
1721
|
-
]);
|
|
1722
|
-
const vaultSupplyDecimals = vaultMetadata.supplyMintDecimals;
|
|
1723
|
-
const vaultBorrowDecimals = vaultMetadata.borrowMintDecimals;
|
|
1724
|
-
if (newCol.gt(MIN_I128)) {
|
|
1725
|
-
const decimalsDelta = vaultSupplyDecimals < 9 ? 9 - vaultSupplyDecimals : 0;
|
|
1726
|
-
newCol = newCol.mul(new BN(10).pow(new BN(decimalsDelta)));
|
|
1727
|
-
}
|
|
1728
|
-
if (newDebt.gt(MIN_I128)) {
|
|
1729
|
-
const decimalsDelta = vaultBorrowDecimals < 9 ? 9 - vaultBorrowDecimals : 0;
|
|
1730
|
-
newDebt = newDebt.mul(new BN(10).pow(new BN(decimalsDelta)));
|
|
1731
|
-
}
|
|
1732
|
-
const positionData = positionId === 0 ? {
|
|
1733
|
-
nftId: vaultState.nextPositionId,
|
|
1734
|
-
positionMint: new PublicKey(0),
|
|
1735
|
-
isSupplyOnlyPosition: 1,
|
|
1736
|
-
tick: -2147483648,
|
|
1737
|
-
tickId: 0,
|
|
1738
|
-
lastUpdateTimestamp: new BN(0),
|
|
1739
|
-
supplyAmount: new BN(0),
|
|
1740
|
-
dustDebtAmount: new BN(0)} : await program.account.position.fetch(
|
|
1741
|
-
getPosition(vaultId, positionId)
|
|
1742
|
-
);
|
|
1743
|
-
let existingPositionTick = positionData.tick;
|
|
1744
|
-
const currentPosition = await getCurrentPositionState({
|
|
1745
|
-
vaultId,
|
|
1746
|
-
position: positionData,
|
|
1747
|
-
program
|
|
1748
|
-
});
|
|
1749
|
-
if (existingPositionTick === -2147483648) {
|
|
1750
|
-
existingPositionTick = currentPosition.tick;
|
|
1751
|
-
}
|
|
1752
|
-
const currentPositionTickPda = getTick(
|
|
1753
|
-
vaultId,
|
|
1754
|
-
existingPositionTick
|
|
1755
|
-
);
|
|
1756
|
-
const finalPosition = await getFinalPosition({
|
|
1757
|
-
vaultId,
|
|
1758
|
-
currentPosition,
|
|
1759
|
-
newColAmount: newCol,
|
|
1760
|
-
newDebtAmount: newDebt,
|
|
1761
|
-
program,
|
|
1762
|
-
connection,
|
|
1763
|
-
signer
|
|
1764
|
-
});
|
|
1765
|
-
const { otherIxs, newBranchPda, currentTickIdDataPda, finalTickIdDataPda } = await getOtherInstructionsOperate(
|
|
1766
|
-
vaultId,
|
|
1767
|
-
vaultState,
|
|
1768
|
-
currentPosition,
|
|
1769
|
-
finalPosition,
|
|
1770
|
-
existingPositionTick,
|
|
1771
|
-
program,
|
|
1772
|
-
signer
|
|
1773
|
-
);
|
|
1774
|
-
const { remainingAccounts, remainingAccountsIndices } = await getRemainingAccountsOperate(
|
|
1775
|
-
vaultId,
|
|
1776
|
-
vaultState,
|
|
1777
|
-
vaultConfig,
|
|
1778
|
-
finalPosition.tick,
|
|
1779
|
-
existingPositionTick,
|
|
1780
|
-
currentPosition.userLiquidationStatus,
|
|
1781
|
-
currentPosition.postLiquidationBranchId,
|
|
1782
|
-
program
|
|
1783
|
-
);
|
|
1784
|
-
const accounts = {
|
|
1785
|
-
signer,
|
|
1786
|
-
signerSupplyTokenAccount: getAssociatedTokenAddressSync(
|
|
1787
|
-
vaultConfig.supplyToken,
|
|
1788
|
-
signer,
|
|
1789
|
-
false,
|
|
1790
|
-
supplyTokenProgram
|
|
1791
|
-
),
|
|
1792
|
-
signerBorrowTokenAccount: getAssociatedTokenAddressSync(
|
|
1793
|
-
vaultConfig.borrowToken,
|
|
1794
|
-
signer,
|
|
1795
|
-
false,
|
|
1796
|
-
borrowTokenProgram
|
|
1797
|
-
),
|
|
1798
|
-
recipient: recipient ?? null,
|
|
1799
|
-
recipientSupplyTokenAccount: recipient ? getAssociatedTokenAddressSync(
|
|
1800
|
-
vaultConfig.supplyToken,
|
|
1801
|
-
recipient,
|
|
1802
|
-
false,
|
|
1803
|
-
supplyTokenProgram
|
|
1804
|
-
) : null,
|
|
1805
|
-
recipientBorrowTokenAccount: recipient ? getAssociatedTokenAddressSync(
|
|
1806
|
-
vaultConfig.borrowToken,
|
|
1807
|
-
recipient,
|
|
1808
|
-
false,
|
|
1809
|
-
borrowTokenProgram
|
|
1810
|
-
) : null,
|
|
1811
|
-
vaultConfig: getVaultConfig(vaultId),
|
|
1812
|
-
vaultState: getVaultState(vaultId),
|
|
1813
|
-
supplyToken: vaultConfig.supplyToken,
|
|
1814
|
-
borrowToken: vaultConfig.borrowToken,
|
|
1815
|
-
oracle: new PublicKey(vaultConfig.oracle),
|
|
1816
|
-
position: getPosition(vaultId, positionData.nftId),
|
|
1817
|
-
positionTokenAccount: getPositionTokenAccount(
|
|
1818
|
-
vaultId,
|
|
1819
|
-
positionData.nftId,
|
|
1820
|
-
positionOwner
|
|
1821
|
-
),
|
|
1822
|
-
currentPositionTick: currentPositionTickPda,
|
|
1823
|
-
finalPositionTick: getTick(vaultId, finalPosition.tick),
|
|
1824
|
-
currentPositionTickId: currentTickIdDataPda,
|
|
1825
|
-
finalPositionTickId: finalTickIdDataPda,
|
|
1826
|
-
newBranch: newBranchPda,
|
|
1827
|
-
supplyTokenReservesLiquidity: getLiquidityReserve(
|
|
1828
|
-
vaultConfig.supplyToken
|
|
1829
|
-
),
|
|
1830
|
-
borrowTokenReservesLiquidity: getLiquidityReserve(
|
|
1831
|
-
vaultConfig.borrowToken
|
|
1832
|
-
),
|
|
1833
|
-
vaultSupplyPositionOnLiquidity: getUserSupplyPosition(
|
|
1834
|
-
vaultConfig.supplyToken,
|
|
1835
|
-
getVaultConfig(vaultId)
|
|
1836
|
-
),
|
|
1837
|
-
vaultBorrowPositionOnLiquidity: getUserBorrowPosition(
|
|
1838
|
-
vaultConfig.borrowToken,
|
|
1839
|
-
getVaultConfig(vaultId)
|
|
1840
|
-
),
|
|
1841
|
-
supplyRateModel: getRateModel(vaultConfig.supplyToken),
|
|
1842
|
-
borrowRateModel: getRateModel(vaultConfig.borrowToken),
|
|
1843
|
-
supplyTokenClaimAccount: null,
|
|
1844
|
-
borrowTokenClaimAccount: null,
|
|
1845
|
-
liquidity: getLiquidity(),
|
|
1846
|
-
liquidityProgram: LIQUIDITY_PROGRAM_ID,
|
|
1847
|
-
vaultSupplyTokenAccount: getAssociatedTokenAddressSync(
|
|
1848
|
-
vaultConfig.supplyToken,
|
|
1849
|
-
getLiquidity(),
|
|
1850
|
-
true,
|
|
1851
|
-
supplyTokenProgram
|
|
1852
|
-
),
|
|
1853
|
-
vaultBorrowTokenAccount: getAssociatedTokenAddressSync(
|
|
1854
|
-
vaultConfig.borrowToken,
|
|
1855
|
-
getLiquidity(),
|
|
1856
|
-
true,
|
|
1857
|
-
borrowTokenProgram
|
|
1858
|
-
),
|
|
1859
|
-
oracleProgram: new PublicKey(vaultConfig.oracleProgram),
|
|
1860
|
-
supplyTokenProgram,
|
|
1861
|
-
borrowTokenProgram,
|
|
1862
|
-
associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
1863
|
-
systemProgram: SystemProgram.programId
|
|
1864
|
-
};
|
|
1865
|
-
return {
|
|
1866
|
-
nftId: positionData.nftId,
|
|
1867
|
-
accounts,
|
|
1868
|
-
remainingAccounts,
|
|
1869
|
-
initPositionIx: positionId === 0 ? await program.methods.initPosition(vaultId, positionData.nftId).accounts(
|
|
1870
|
-
getInitPositionContext(vaultId, positionData.nftId, signer)
|
|
1871
|
-
).instruction() : null,
|
|
1872
|
-
otherIxs,
|
|
1873
|
-
remainingAccountsIndices,
|
|
1874
|
-
lookupTable: vaultMetadata.lookupTable
|
|
1875
|
-
};
|
|
1876
|
-
}
|
|
1877
|
-
async function getInitPositionIx({
|
|
1878
|
-
vaultId,
|
|
1879
|
-
connection,
|
|
1880
|
-
signer
|
|
1881
|
-
}) {
|
|
1882
|
-
const program = getVaultsProgram({ connection, signer });
|
|
1883
|
-
const vaultState = await program.account.vaultState.fetch(
|
|
1884
|
-
getVaultState(vaultId)
|
|
1885
|
-
);
|
|
1886
|
-
return {
|
|
1887
|
-
ix: await program.methods.initPosition(vaultId, vaultState.nextPositionId).accounts(
|
|
1888
|
-
getInitPositionContext(vaultId, vaultState.nextPositionId, signer)
|
|
1889
|
-
).instruction(),
|
|
1890
|
-
nftId: vaultState.nextPositionId
|
|
1891
|
-
};
|
|
1892
|
-
}
|
|
1893
|
-
function getInitPositionContext(vaultId, positionId, signer) {
|
|
1894
|
-
return {
|
|
1895
|
-
signer,
|
|
1896
|
-
vaultAdmin: getVaultAdmin(),
|
|
1897
|
-
vaultState: getVaultState(vaultId),
|
|
1898
|
-
position: getPosition(vaultId, positionId),
|
|
1899
|
-
positionMint: getPositionMint(vaultId, positionId),
|
|
1900
|
-
positionTokenAccount: getPositionTokenAccount(
|
|
1901
|
-
vaultId,
|
|
1902
|
-
positionId,
|
|
1903
|
-
signer
|
|
1904
|
-
),
|
|
1905
|
-
tokenProgram: TOKEN_PROGRAM_ID,
|
|
1906
|
-
metadataAccount: getPositionMetadata(vaultId, positionId),
|
|
1907
|
-
associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
1908
|
-
systemProgram: SystemProgram.programId,
|
|
1909
|
-
sysvarInstruction: SYSVAR_INSTRUCTIONS_PUBKEY,
|
|
1910
|
-
metadataProgram: MPL_TOKEN_METADATA_PROGRAM_ID,
|
|
1911
|
-
rent: SYSVAR_RENT_PUBKEY
|
|
1912
|
-
};
|
|
1913
|
-
}
|
|
1914
|
-
const getOperateIx = async ({
|
|
1915
|
-
vaultId,
|
|
1916
|
-
positionId,
|
|
1917
|
-
colAmount,
|
|
1918
|
-
debtAmount,
|
|
1919
|
-
connection,
|
|
1920
|
-
signer,
|
|
1921
|
-
recipient,
|
|
1922
|
-
positionOwner
|
|
1923
|
-
}) => {
|
|
1924
|
-
const program = getVaultsProgram({ connection, signer });
|
|
1925
|
-
const {
|
|
1926
|
-
accounts,
|
|
1927
|
-
remainingAccounts,
|
|
1928
|
-
remainingAccountsIndices,
|
|
1929
|
-
initPositionIx,
|
|
1930
|
-
otherIxs,
|
|
1931
|
-
lookupTable,
|
|
1932
|
-
nftId
|
|
1933
|
-
} = await getOperateContext({
|
|
1934
|
-
vaultId,
|
|
1935
|
-
positionId,
|
|
1936
|
-
colAmount,
|
|
1937
|
-
debtAmount,
|
|
1938
|
-
signer,
|
|
1939
|
-
positionOwner,
|
|
1940
|
-
connection,
|
|
1941
|
-
recipient,
|
|
1942
|
-
program
|
|
1943
|
-
});
|
|
1944
|
-
const [operateIx, addressLookupTable] = await Promise.all([
|
|
1945
|
-
program.methods.operate(
|
|
1946
|
-
colAmount,
|
|
1947
|
-
debtAmount,
|
|
1948
|
-
{ direct: {} },
|
|
1949
|
-
Buffer.from(remainingAccountsIndices)
|
|
1950
|
-
).accounts(accounts).remainingAccounts(remainingAccounts).instruction(),
|
|
1951
|
-
connection.getAddressLookupTable(lookupTable)
|
|
1952
|
-
]);
|
|
1953
|
-
return {
|
|
1954
|
-
nftId,
|
|
1955
|
-
accounts,
|
|
1956
|
-
remainingAccounts,
|
|
1957
|
-
remainingAccountsIndices,
|
|
1958
|
-
addressLookupTableAddresses: lookupTable ? [lookupTable] : [],
|
|
1959
|
-
addressLookupTableAccounts: addressLookupTable.value ? [addressLookupTable.value] : [],
|
|
1960
|
-
ixs: initPositionIx ? [initPositionIx, ...otherIxs, operateIx] : [...otherIxs, operateIx]
|
|
1961
|
-
};
|
|
1962
|
-
};
|
|
1963
|
-
function getInitBranchContext(vaultId, branchId, signer) {
|
|
1964
|
-
return {
|
|
1965
|
-
signer,
|
|
1966
|
-
vaultConfig: getVaultConfig(vaultId),
|
|
1967
|
-
branch: getBranch(vaultId, branchId),
|
|
1968
|
-
systemProgram: SystemProgram.programId
|
|
1969
|
-
};
|
|
1970
|
-
}
|
|
1971
|
-
function getInitTickContext(vaultId, tick, signer) {
|
|
1972
|
-
return {
|
|
1973
|
-
signer,
|
|
1974
|
-
vaultConfig: getVaultConfig(vaultId),
|
|
1975
|
-
tickData: getTick(vaultId, tick),
|
|
1976
|
-
systemProgram: SystemProgram.programId
|
|
1977
|
-
};
|
|
1978
|
-
}
|
|
1979
|
-
async function getInitTickIdLiquidationContext(vaultId, tick, signer, program) {
|
|
1980
|
-
const tickData = await program.account.tick.fetch(getTick(vaultId, tick)).catch(() => null);
|
|
1981
|
-
if (!tickData) {
|
|
1982
|
-
return {
|
|
1983
|
-
signer,
|
|
1984
|
-
vaultConfig: getVaultConfig(vaultId),
|
|
1985
|
-
tickIdLiquidation: getTickIdLiquidation(vaultId, tick, 0),
|
|
1986
|
-
tickData: getTick(vaultId, tick),
|
|
1987
|
-
systemProgram: SystemProgram.programId
|
|
1988
|
-
};
|
|
1989
|
-
}
|
|
1990
|
-
return {
|
|
1991
|
-
signer,
|
|
1992
|
-
vaultConfig: getVaultConfig(vaultId),
|
|
1993
|
-
tickIdLiquidation: getTickIdLiquidation(
|
|
1994
|
-
vaultId,
|
|
1995
|
-
tick,
|
|
1996
|
-
tickData.totalIds
|
|
1997
|
-
),
|
|
1998
|
-
tickData: getTick(vaultId, tick),
|
|
1999
|
-
systemProgram: SystemProgram.programId
|
|
2000
|
-
};
|
|
2001
|
-
}
|
|
2002
|
-
async function getLiquidateContext({
|
|
2003
|
-
vaultId,
|
|
2004
|
-
to,
|
|
2005
|
-
program,
|
|
2006
|
-
connection,
|
|
2007
|
-
signer
|
|
2008
|
-
}) {
|
|
2009
|
-
program = program ?? getVaultsProgram({ connection, signer });
|
|
2010
|
-
const [vaultState, vaultConfig, vaultMetadata] = await Promise.all([
|
|
2011
|
-
program.account.vaultState.fetch(getVaultState(vaultId)),
|
|
2012
|
-
program.account.vaultConfig.fetch(getVaultConfig(vaultId)),
|
|
2013
|
-
program.account.vaultMetadata.fetch(getVaultMetadata(vaultId))
|
|
2014
|
-
]);
|
|
2015
|
-
const [supplyTokenProgram, borrowTokenProgram] = await Promise.all([
|
|
2016
|
-
getAccountOwner(vaultConfig.supplyToken, connection),
|
|
2017
|
-
getAccountOwner(vaultConfig.borrowToken, connection)
|
|
2018
|
-
]);
|
|
2019
|
-
const { arrayIndex } = getTickIndices(vaultState.topmostTick);
|
|
2020
|
-
let { otherIxs, newBranchPda } = await getOtherInstructionsLiquidate(
|
|
2021
|
-
vaultId,
|
|
2022
|
-
vaultState,
|
|
2023
|
-
program,
|
|
2024
|
-
signer
|
|
2025
|
-
);
|
|
2026
|
-
const {
|
|
2027
|
-
remainingAccounts,
|
|
2028
|
-
remainingAccountsIndices,
|
|
2029
|
-
otherIxs: finalOtherIxs
|
|
2030
|
-
} = await getRemainingAccountsLiquidate(
|
|
2031
|
-
vaultId,
|
|
2032
|
-
vaultState,
|
|
2033
|
-
vaultConfig,
|
|
2034
|
-
otherIxs,
|
|
2035
|
-
program,
|
|
2036
|
-
connection,
|
|
2037
|
-
signer
|
|
2038
|
-
);
|
|
2039
|
-
return {
|
|
2040
|
-
accounts: {
|
|
2041
|
-
signer,
|
|
2042
|
-
signerTokenAccount: getAssociatedTokenAddressSync(
|
|
2043
|
-
vaultConfig.borrowToken,
|
|
2044
|
-
signer,
|
|
2045
|
-
false,
|
|
2046
|
-
borrowTokenProgram
|
|
2047
|
-
),
|
|
2048
|
-
to,
|
|
2049
|
-
toTokenAccount: getAssociatedTokenAddressSync(
|
|
2050
|
-
vaultConfig.supplyToken,
|
|
2051
|
-
to,
|
|
2052
|
-
false,
|
|
2053
|
-
supplyTokenProgram
|
|
2054
|
-
),
|
|
2055
|
-
vaultAdmin: getVaultAdmin(),
|
|
2056
|
-
vaultConfig: getVaultConfig(vaultId),
|
|
2057
|
-
vaultState: getVaultState(vaultId),
|
|
2058
|
-
supplyToken: vaultConfig.supplyToken,
|
|
2059
|
-
borrowToken: vaultConfig.borrowToken,
|
|
2060
|
-
oracle: new PublicKey(vaultConfig.oracle),
|
|
2061
|
-
tickHasDebt: getTickHasDebt(vaultId, arrayIndex),
|
|
2062
|
-
newBranch: newBranchPda,
|
|
2063
|
-
supplyTokenReservesLiquidity: getLiquidityReserve(
|
|
2064
|
-
vaultConfig.supplyToken
|
|
2065
|
-
),
|
|
2066
|
-
borrowTokenReservesLiquidity: getLiquidityReserve(
|
|
2067
|
-
vaultConfig.borrowToken
|
|
2068
|
-
),
|
|
2069
|
-
vaultSupplyPositionOnLiquidity: getUserSupplyPosition(
|
|
2070
|
-
vaultConfig.supplyToken,
|
|
2071
|
-
getVaultConfig(vaultId)
|
|
2072
|
-
),
|
|
2073
|
-
vaultBorrowPositionOnLiquidity: getUserBorrowPosition(
|
|
2074
|
-
vaultConfig.borrowToken,
|
|
2075
|
-
getVaultConfig(vaultId)
|
|
2076
|
-
),
|
|
2077
|
-
supplyRateModel: getRateModel(vaultConfig.supplyToken),
|
|
2078
|
-
borrowRateModel: getRateModel(vaultConfig.borrowToken),
|
|
2079
|
-
supplyTokenClaimAccount: getClaimAccount(
|
|
2080
|
-
vaultConfig.supplyToken,
|
|
2081
|
-
getVaultConfig(vaultId)
|
|
2082
|
-
),
|
|
2083
|
-
borrowTokenClaimAccount: getClaimAccount(
|
|
2084
|
-
vaultConfig.borrowToken,
|
|
2085
|
-
getVaultConfig(vaultId)
|
|
2086
|
-
),
|
|
2087
|
-
liquidity: getLiquidity(),
|
|
2088
|
-
liquidityProgram: LIQUIDITY_PROGRAM_ID,
|
|
2089
|
-
vaultSupplyTokenAccount: getAssociatedTokenAddressSync(
|
|
2090
|
-
vaultConfig.supplyToken,
|
|
2091
|
-
getLiquidity(),
|
|
2092
|
-
true,
|
|
2093
|
-
supplyTokenProgram
|
|
2094
|
-
),
|
|
2095
|
-
vaultBorrowTokenAccount: getAssociatedTokenAddressSync(
|
|
2096
|
-
vaultConfig.borrowToken,
|
|
2097
|
-
getLiquidity(),
|
|
2098
|
-
true,
|
|
2099
|
-
borrowTokenProgram
|
|
2100
|
-
),
|
|
2101
|
-
oracleProgram: new PublicKey(vaultConfig.oracleProgram),
|
|
2102
|
-
supplyTokenProgram,
|
|
2103
|
-
borrowTokenProgram,
|
|
2104
|
-
systemProgram: SystemProgram.programId,
|
|
2105
|
-
associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID
|
|
2106
|
-
},
|
|
2107
|
-
remainingAccounts,
|
|
2108
|
-
otherIxs: finalOtherIxs,
|
|
2109
|
-
remainingAccountsIndices,
|
|
2110
|
-
lookupTable: vaultMetadata.lookupTable
|
|
2111
|
-
};
|
|
2112
|
-
}
|
|
2113
|
-
const getLiquidateIx = async ({
|
|
2114
|
-
vaultId,
|
|
2115
|
-
debtAmount,
|
|
2116
|
-
colPerUnitDebt = new BN(0),
|
|
2117
|
-
absorb = false,
|
|
2118
|
-
signer,
|
|
2119
|
-
to = signer,
|
|
2120
|
-
connection
|
|
2121
|
-
}) => {
|
|
2122
|
-
const program = getVaultsProgram({ connection, signer });
|
|
2123
|
-
const {
|
|
2124
|
-
accounts,
|
|
2125
|
-
remainingAccounts,
|
|
2126
|
-
remainingAccountsIndices,
|
|
2127
|
-
otherIxs,
|
|
2128
|
-
lookupTable
|
|
2129
|
-
} = await getLiquidateContext({
|
|
2130
|
-
vaultId,
|
|
2131
|
-
to,
|
|
2132
|
-
program,
|
|
2133
|
-
signer,
|
|
2134
|
-
connection
|
|
2135
|
-
});
|
|
2136
|
-
const ixs = [];
|
|
2137
|
-
if (otherIxs.length > 0) {
|
|
2138
|
-
ixs.push(...otherIxs);
|
|
2139
|
-
}
|
|
2140
|
-
const [ix, addressLookupTable] = await Promise.all([
|
|
2141
|
-
program.methods.liquidate(
|
|
2142
|
-
debtAmount,
|
|
2143
|
-
colPerUnitDebt,
|
|
2144
|
-
absorb,
|
|
2145
|
-
{ direct: {} },
|
|
2146
|
-
Buffer.from(remainingAccountsIndices)
|
|
2147
|
-
).accounts(accounts).remainingAccounts(remainingAccounts).instruction(),
|
|
2148
|
-
connection.getAddressLookupTable(lookupTable)
|
|
2149
|
-
]);
|
|
2150
|
-
ixs.push(ix);
|
|
2151
|
-
return {
|
|
2152
|
-
accounts,
|
|
2153
|
-
remainingAccounts,
|
|
2154
|
-
remainingAccountsIndices,
|
|
2155
|
-
ixs,
|
|
2156
|
-
addressLookupTableAddresses: lookupTable ? [lookupTable] : [],
|
|
2157
|
-
addressLookupTableAccounts: addressLookupTable.value ? [addressLookupTable.value] : []
|
|
2158
|
-
};
|
|
2159
|
-
};
|
|
2160
|
-
async function getOtherInstructionsLiquidate(vaultId, vaultState, program, signer) {
|
|
2161
|
-
const otherIxs = [];
|
|
2162
|
-
let newBranchId = vaultState.branchLiquidated === 1 ? vaultState.totalBranchId + 1 : vaultState.currentBranchId;
|
|
2163
|
-
let newBranchPda = getBranch(vaultId, newBranchId);
|
|
2164
|
-
const [newBranchData, tickData] = await Promise.all([
|
|
2165
|
-
program.account.branch.fetch(newBranchPda).catch(() => null),
|
|
2166
|
-
// might be possible that liquidation ends on a tick that is not initialized
|
|
2167
|
-
program.account.tick.fetch(getTick(vaultId, vaultState.topmostTick)).catch(() => null)
|
|
2168
|
-
]);
|
|
2169
|
-
if (!newBranchData) {
|
|
2170
|
-
const ix = await program.methods.initBranch(vaultId, newBranchId).accounts(getInitBranchContext(vaultId, newBranchId, signer)).instruction();
|
|
2171
|
-
otherIxs.push(ix);
|
|
2172
|
-
}
|
|
2173
|
-
if (!tickData) {
|
|
2174
|
-
const ix = await program.methods.initTick(vaultId, vaultState.topmostTick).accounts(getInitTickContext(vaultId, vaultState.topmostTick, signer)).instruction();
|
|
2175
|
-
otherIxs.push(ix);
|
|
2176
|
-
}
|
|
2177
|
-
return {
|
|
2178
|
-
otherIxs,
|
|
2179
|
-
newBranchPda
|
|
2180
|
-
};
|
|
2181
|
-
}
|
|
2182
|
-
async function loadRelevantTicksForLiquidate(vaultId, vaultState, liquidationTick, program) {
|
|
2183
|
-
const ticks = [];
|
|
2184
|
-
let topTick = vaultState.topmostTick;
|
|
2185
|
-
if (topTick > liquidationTick)
|
|
2186
|
-
try {
|
|
2187
|
-
const topTickData = await program.account.tick.fetch(
|
|
2188
|
-
getTick(vaultId, topTick)
|
|
2189
|
-
);
|
|
2190
|
-
if (topTickData) ticks.push({ ...topTickData, tick: topTick });
|
|
2191
|
-
} catch {
|
|
2192
|
-
}
|
|
2193
|
-
let nextTick = MIN_TICK$1;
|
|
2194
|
-
try {
|
|
2195
|
-
nextTick = await findNextTickWithDebt(vaultId, topTick, program);
|
|
2196
|
-
} catch {
|
|
2197
|
-
}
|
|
2198
|
-
const doesTickExist = (tick) => ticks.some((t) => t.tick === tick);
|
|
2199
|
-
while (nextTick > liquidationTick && !doesTickExist(nextTick)) {
|
|
2200
|
-
try {
|
|
2201
|
-
const nextTickData = await program.account.tick.fetch(
|
|
2202
|
-
getTick(vaultId, nextTick)
|
|
2203
|
-
);
|
|
2204
|
-
if (nextTickData) ticks.push({ ...nextTickData, tick: nextTick });
|
|
2205
|
-
else throw new Error("Tick not found to load");
|
|
2206
|
-
nextTick = await findNextTickWithDebt(vaultId, nextTick, program);
|
|
2207
|
-
} catch {
|
|
2208
|
-
}
|
|
2209
|
-
}
|
|
2210
|
-
return { ticks, nextTick };
|
|
2211
|
-
}
|
|
2212
|
-
async function getRemainingAccountsLiquidate(vaultId, vaultState, vaultConfig, otherIxs, program, connection, signer) {
|
|
2213
|
-
const remainingAccounts = [];
|
|
2214
|
-
const { oraclePriceLiquidate, oracleSources } = await readOraclePrice({
|
|
2215
|
-
oracle: vaultConfig.oracle,
|
|
2216
|
-
connection
|
|
2217
|
-
// signer,
|
|
2218
|
-
});
|
|
2219
|
-
const liquidationRatio = new BN(oraclePriceLiquidate).mul(new BN(281474976710656)).div(new BN(10).pow(new BN(15)));
|
|
2220
|
-
const liquidationThresholdRatio = liquidationRatio.mul(new BN(vaultConfig.liquidationThreshold)).div(new BN(10).pow(new BN(3)));
|
|
2221
|
-
const liquidationTick = getTickAtRatio(liquidationThresholdRatio);
|
|
2222
|
-
for (const source of oracleSources) {
|
|
2223
|
-
remainingAccounts.push({
|
|
2224
|
-
pubkey: source.source,
|
|
2225
|
-
isWritable: false,
|
|
2226
|
-
isSigner: false
|
|
2227
|
-
});
|
|
2228
|
-
}
|
|
2229
|
-
const [branches, { ticks: tickAccounts, nextTick }] = await Promise.all([
|
|
2230
|
-
loadRelevantBranchesForLiquidate(vaultId, vaultState, program),
|
|
2231
|
-
loadRelevantTicksForLiquidate(
|
|
2232
|
-
vaultId,
|
|
2233
|
-
vaultState,
|
|
2234
|
-
liquidationTick,
|
|
2235
|
-
program
|
|
2236
|
-
)
|
|
2237
|
-
]);
|
|
2238
|
-
const tickHasDebt = await loadRelevantTicksHasDebtArraysLiquidate(
|
|
2239
|
-
vaultId,
|
|
2240
|
-
vaultState.topmostTick,
|
|
2241
|
-
nextTick,
|
|
2242
|
-
program
|
|
2243
|
-
);
|
|
2244
|
-
for (const branch of branches) {
|
|
2245
|
-
remainingAccounts.push({
|
|
2246
|
-
pubkey: getBranch(vaultId, branch.branchId),
|
|
2247
|
-
isWritable: true,
|
|
2248
|
-
isSigner: false
|
|
2249
|
-
});
|
|
2250
|
-
}
|
|
2251
|
-
const tickToInit = [];
|
|
2252
|
-
const existingTicks = await Promise.all(
|
|
2253
|
-
tickAccounts.map(
|
|
2254
|
-
(tickData) => program.account.tick.fetch(getTick(vaultId, tickData.tick)).catch(() => null)
|
|
2255
|
-
)
|
|
2256
|
-
);
|
|
2257
|
-
const initInstructions = await Promise.all(
|
|
2258
|
-
tickAccounts.map(async (tickData, index) => {
|
|
2259
|
-
const existingTick = existingTicks[index];
|
|
2260
|
-
if (!existingTick && !tickToInit.includes(tickData.tick)) {
|
|
2261
|
-
tickToInit.push(tickData.tick);
|
|
2262
|
-
return program.methods.initTick(vaultId, tickData.tick).accounts(getInitTickContext(vaultId, tickData.tick, signer)).instruction();
|
|
2263
|
-
}
|
|
2264
|
-
return null;
|
|
2265
|
-
})
|
|
2266
|
-
);
|
|
2267
|
-
for (const ix of initInstructions) {
|
|
2268
|
-
if (ix) {
|
|
2269
|
-
otherIxs.push(ix);
|
|
2270
|
-
}
|
|
2271
|
-
}
|
|
2272
|
-
for (const tickData of tickAccounts) {
|
|
2273
|
-
remainingAccounts.push({
|
|
2274
|
-
pubkey: getTick(vaultId, tickData.tick),
|
|
2275
|
-
isWritable: true,
|
|
2276
|
-
isSigner: false
|
|
2277
|
-
});
|
|
2278
|
-
}
|
|
2279
|
-
for (const tickHasDebtArray of tickHasDebt) {
|
|
2280
|
-
remainingAccounts.push({
|
|
2281
|
-
pubkey: getTickHasDebt(vaultId, tickHasDebtArray.index),
|
|
2282
|
-
isWritable: true,
|
|
2283
|
-
isSigner: false
|
|
2284
|
-
});
|
|
2285
|
-
}
|
|
2286
|
-
const remainingAccountsIndices = [
|
|
2287
|
-
oracleSources.length,
|
|
2288
|
-
branches.length,
|
|
2289
|
-
tickAccounts.length,
|
|
2290
|
-
tickHasDebt.length
|
|
2291
|
-
];
|
|
2292
|
-
return {
|
|
2293
|
-
remainingAccounts,
|
|
2294
|
-
otherIxs,
|
|
2295
|
-
remainingAccountsIndices
|
|
2296
|
-
};
|
|
2297
|
-
}
|
|
5
|
+
import { g as getVaultAdmin } from '../shared/lend.C2-jCLFw.mjs';
|
|
6
|
+
import '@coral-xyz/anchor';
|
|
7
|
+
import '../shared/lend.CioR9-te.mjs';
|
|
8
|
+
import '@solana/spl-token';
|
|
9
|
+
import '../shared/lend.BzG5ldOV.mjs';
|
|
2298
10
|
|
|
2299
11
|
const simulateLiquidate = async (params) => {
|
|
2300
12
|
const { connection, signer } = params;
|
|
@@ -2363,4 +75,4 @@ function parseVaultLiquidations(logs) {
|
|
|
2363
75
|
return results;
|
|
2364
76
|
}
|
|
2365
77
|
|
|
2366
|
-
export {
|
|
78
|
+
export { getAllLiquidations, getLiquidateIx, getLiquidations, getVaultsProgram, simulateLiquidate };
|