@varla/sdk 2.17.0 → 2.18.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/AGENTS.md +7 -7
- package/CHANGELOG.md +21 -0
- package/dist/views/core.d.ts +24 -0
- package/dist/views/core.d.ts.map +1 -1
- package/dist/views/core.js +135 -0
- package/dist/views/core.js.map +1 -1
- package/dist/views/liquidators.d.ts +26 -0
- package/dist/views/liquidators.d.ts.map +1 -1
- package/dist/views/liquidators.js +80 -14
- package/dist/views/liquidators.js.map +1 -1
- package/dist/views/oracle.d.ts +106 -0
- package/dist/views/oracle.d.ts.map +1 -1
- package/dist/views/oracle.js +305 -1
- package/dist/views/oracle.js.map +1 -1
- package/dist/views/pool.d.ts +24 -0
- package/dist/views/pool.d.ts.map +1 -1
- package/dist/views/pool.js +127 -0
- package/dist/views/pool.js.map +1 -1
- package/dist/views/system.d.ts +20 -1
- package/dist/views/system.d.ts.map +1 -1
- package/dist/views/system.js +32 -2
- package/dist/views/system.js.map +1 -1
- package/package.json +1 -1
- package/src/views/core.ts +161 -0
- package/src/views/liquidators.ts +104 -21
- package/src/views/oracle.ts +388 -1
- package/src/views/pool.ts +153 -0
- package/src/views/system.ts +51 -3
package/src/views/liquidators.ts
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import type { Address, PublicClient } from "viem";
|
|
4
4
|
|
|
5
|
+
import { multicallChunks } from "../batch.js";
|
|
6
|
+
import { abis } from "../generated.js";
|
|
5
7
|
import { readAccountPositionsFull } from "./core.js";
|
|
6
8
|
import { type ReadPositionSnapshot, readManyPositionSnapshots } from "./oracle.js";
|
|
7
9
|
|
|
@@ -51,17 +53,8 @@ export type ReadCanLiquidate = {
|
|
|
51
53
|
currentBonus: bigint;
|
|
52
54
|
};
|
|
53
55
|
|
|
54
|
-
|
|
55
|
-
* Normalized wrapper over `*.canLiquidate(user)`.
|
|
56
|
-
*/
|
|
57
|
-
// wraps: VarlaLiquidator.canLiquidate,VarlaMergeLiquidator.canLiquidate,VarlaConvertLiquidator.canLiquidate
|
|
58
|
-
export async function readCanLiquidate(params: {
|
|
59
|
-
liquidator: CanLiquidateLike;
|
|
60
|
-
user: Address;
|
|
61
|
-
}): Promise<ReadCanLiquidate> {
|
|
62
|
-
const raw = await params.liquidator.read.canLiquidate([params.user]);
|
|
56
|
+
function normalizeCanLiquidate(raw: unknown, user: Address): ReadCanLiquidate {
|
|
63
57
|
const r: any = raw as any;
|
|
64
|
-
|
|
65
58
|
const canLiquidate = r.canLiquidate_ ?? r.canLiquidate ?? r[0];
|
|
66
59
|
const healthFactor = r.healthFactor ?? r[1];
|
|
67
60
|
const currentBonus = r.currentBonus ?? r[2];
|
|
@@ -74,7 +67,56 @@ export async function readCanLiquidate(params: {
|
|
|
74
67
|
throw new Error("Unexpected canLiquidate() return shape");
|
|
75
68
|
}
|
|
76
69
|
|
|
77
|
-
return { user
|
|
70
|
+
return { user, canLiquidate, healthFactor, currentBonus };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Normalized wrapper over `*.canLiquidate(user)`.
|
|
75
|
+
*/
|
|
76
|
+
// wraps: VarlaLiquidator.canLiquidate,VarlaMergeLiquidator.canLiquidate,VarlaConvertLiquidator.canLiquidate
|
|
77
|
+
export async function readCanLiquidate(params: {
|
|
78
|
+
liquidator: CanLiquidateLike;
|
|
79
|
+
user: Address;
|
|
80
|
+
}): Promise<ReadCanLiquidate> {
|
|
81
|
+
const raw = await params.liquidator.read.canLiquidate([params.user]);
|
|
82
|
+
return normalizeCanLiquidate(raw, params.user);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Multicall-chunked version of `readCanLiquidate`.
|
|
87
|
+
*/
|
|
88
|
+
// wraps: VarlaLiquidator.canLiquidate,VarlaMergeLiquidator.canLiquidate,VarlaConvertLiquidator.canLiquidate
|
|
89
|
+
export async function readManyCanLiquidate(params: {
|
|
90
|
+
liquidator: { address: Address };
|
|
91
|
+
client: { multicall: (args: any) => Promise<any> };
|
|
92
|
+
users: readonly Address[];
|
|
93
|
+
chunkSize?: number;
|
|
94
|
+
}): Promise<ReadCanLiquidate[]> {
|
|
95
|
+
const chunkSize = params.chunkSize ?? 256;
|
|
96
|
+
if (params.users.length === 0) return [];
|
|
97
|
+
|
|
98
|
+
const calls = params.users.map((user) => ({
|
|
99
|
+
address: params.liquidator.address,
|
|
100
|
+
abi: abis.VARLALIQUIDATOR_ABI,
|
|
101
|
+
functionName: "canLiquidate" as const,
|
|
102
|
+
args: [user] as const,
|
|
103
|
+
}));
|
|
104
|
+
|
|
105
|
+
const res = await multicallChunks({
|
|
106
|
+
client: params.client as any,
|
|
107
|
+
contracts: calls as any,
|
|
108
|
+
chunkSize,
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
const out: ReadCanLiquidate[] = [];
|
|
112
|
+
for (let i = 0; i < res.length; i++) {
|
|
113
|
+
const r: any = (res as any[])[i];
|
|
114
|
+
if (r.status !== "success") {
|
|
115
|
+
throw new Error(`Liquidator canLiquidate multicall failed: ${String(r.error ?? "unknown")}`);
|
|
116
|
+
}
|
|
117
|
+
out.push(normalizeCanLiquidate(r.result, params.users[i]!));
|
|
118
|
+
}
|
|
119
|
+
return out;
|
|
78
120
|
}
|
|
79
121
|
|
|
80
122
|
type PreviewLiquidationLike = {
|
|
@@ -171,15 +213,7 @@ export type ReadBadDebtStatus = {
|
|
|
171
213
|
shortfall: bigint;
|
|
172
214
|
};
|
|
173
215
|
|
|
174
|
-
|
|
175
|
-
* Normalized wrapper over `VarlaLiquidator.checkBadDebt(user)`.
|
|
176
|
-
*/
|
|
177
|
-
// wraps: VarlaLiquidator.checkBadDebt
|
|
178
|
-
export async function readBadDebtStatus(params: {
|
|
179
|
-
liquidator: CheckBadDebtLike;
|
|
180
|
-
user: Address;
|
|
181
|
-
}): Promise<ReadBadDebtStatus> {
|
|
182
|
-
const raw = await params.liquidator.read.checkBadDebt([params.user]);
|
|
216
|
+
function normalizeBadDebtStatus(raw: unknown, user: Address): ReadBadDebtStatus {
|
|
183
217
|
const r: any = raw as any;
|
|
184
218
|
|
|
185
219
|
const hasBadDebt = r.hasBadDebt ?? r[0];
|
|
@@ -196,7 +230,56 @@ export async function readBadDebtStatus(params: {
|
|
|
196
230
|
throw new Error("Unexpected checkBadDebt() return shape");
|
|
197
231
|
}
|
|
198
232
|
|
|
199
|
-
return { user
|
|
233
|
+
return { user, hasBadDebt, collateralValue, debtValue, shortfall };
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Normalized wrapper over `VarlaLiquidator.checkBadDebt(user)`.
|
|
238
|
+
*/
|
|
239
|
+
// wraps: VarlaLiquidator.checkBadDebt
|
|
240
|
+
export async function readBadDebtStatus(params: {
|
|
241
|
+
liquidator: CheckBadDebtLike;
|
|
242
|
+
user: Address;
|
|
243
|
+
}): Promise<ReadBadDebtStatus> {
|
|
244
|
+
const raw = await params.liquidator.read.checkBadDebt([params.user]);
|
|
245
|
+
return normalizeBadDebtStatus(raw, params.user);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Multicall-chunked version of `readBadDebtStatus`.
|
|
250
|
+
*/
|
|
251
|
+
// wraps: VarlaLiquidator.checkBadDebt
|
|
252
|
+
export async function readManyBadDebtStatus(params: {
|
|
253
|
+
liquidator: { address: Address };
|
|
254
|
+
client: { multicall: (args: any) => Promise<any> };
|
|
255
|
+
users: readonly Address[];
|
|
256
|
+
chunkSize?: number;
|
|
257
|
+
}): Promise<ReadBadDebtStatus[]> {
|
|
258
|
+
const chunkSize = params.chunkSize ?? 256;
|
|
259
|
+
if (params.users.length === 0) return [];
|
|
260
|
+
|
|
261
|
+
const calls = params.users.map((user) => ({
|
|
262
|
+
address: params.liquidator.address,
|
|
263
|
+
abi: abis.VARLALIQUIDATOR_ABI,
|
|
264
|
+
functionName: "checkBadDebt" as const,
|
|
265
|
+
args: [user] as const,
|
|
266
|
+
}));
|
|
267
|
+
|
|
268
|
+
const res = await multicallChunks({
|
|
269
|
+
client: params.client as any,
|
|
270
|
+
contracts: calls as any,
|
|
271
|
+
chunkSize,
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
const out: ReadBadDebtStatus[] = [];
|
|
275
|
+
for (let i = 0; i < res.length; i++) {
|
|
276
|
+
const r: any = (res as any[])[i];
|
|
277
|
+
if (r.status !== "success") {
|
|
278
|
+
throw new Error(`Liquidator checkBadDebt multicall failed: ${String(r.error ?? "unknown")}`);
|
|
279
|
+
}
|
|
280
|
+
out.push(normalizeBadDebtStatus(r.result, params.users[i]!));
|
|
281
|
+
}
|
|
282
|
+
return out;
|
|
200
283
|
}
|
|
201
284
|
|
|
202
285
|
type MergeLiquidatorLike = LiquidatorLike & {
|
package/src/views/oracle.ts
CHANGED
|
@@ -275,6 +275,22 @@ export type ReadOracleTiming = {
|
|
|
275
275
|
lastUpdated: bigint;
|
|
276
276
|
};
|
|
277
277
|
|
|
278
|
+
export type ReadOracleDashboardRow = {
|
|
279
|
+
positionId: bigint;
|
|
280
|
+
snapshot: ReadPositionSnapshot;
|
|
281
|
+
meta: ReadOraclePositionMeta;
|
|
282
|
+
resolvedStatus: { positionId: bigint; isResolved: boolean };
|
|
283
|
+
staleStatus: { positionId: bigint; isPriceStale: boolean };
|
|
284
|
+
priceData: ReadOraclePriceData;
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
export type ReadOracleDashboard = {
|
|
288
|
+
config: ReadOracleConfig;
|
|
289
|
+
basics: ReadOracleBasics;
|
|
290
|
+
positionIds: bigint[];
|
|
291
|
+
rows: ReadOracleDashboardRow[];
|
|
292
|
+
};
|
|
293
|
+
|
|
278
294
|
// wraps: VarlaOracle.getPriceData
|
|
279
295
|
export async function readOraclePriceData(params: {
|
|
280
296
|
oracle: {
|
|
@@ -368,6 +384,302 @@ export async function readOracleTiming(params: {
|
|
|
368
384
|
};
|
|
369
385
|
}
|
|
370
386
|
|
|
387
|
+
/**
|
|
388
|
+
* Multicall-chunked collateral status hydration for many positions.
|
|
389
|
+
*/
|
|
390
|
+
// wraps: VarlaOracle.isConfigured,VarlaOracle.isResolved,VarlaOracle.isDepositAllowed,VarlaOracle.isValidCollateral,VarlaOracle.isPriceStale
|
|
391
|
+
export async function readManyOracleCollateralStatus(params: {
|
|
392
|
+
oracle: { address: Address };
|
|
393
|
+
client: { multicall: (args: any) => Promise<any> };
|
|
394
|
+
positionIds: readonly bigint[];
|
|
395
|
+
chunkSize?: number;
|
|
396
|
+
}): Promise<ReadOracleCollateralStatus[]> {
|
|
397
|
+
const chunkSize = params.chunkSize ?? 256;
|
|
398
|
+
if (params.positionIds.length === 0) return [];
|
|
399
|
+
|
|
400
|
+
const calls = params.positionIds.flatMap((pid) => [
|
|
401
|
+
{
|
|
402
|
+
address: params.oracle.address,
|
|
403
|
+
abi: abis.VARLAORACLE_ABI,
|
|
404
|
+
functionName: "isConfigured" as const,
|
|
405
|
+
args: [pid] as const,
|
|
406
|
+
},
|
|
407
|
+
{
|
|
408
|
+
address: params.oracle.address,
|
|
409
|
+
abi: abis.VARLAORACLE_ABI,
|
|
410
|
+
functionName: "isResolved" as const,
|
|
411
|
+
args: [pid] as const,
|
|
412
|
+
},
|
|
413
|
+
{
|
|
414
|
+
address: params.oracle.address,
|
|
415
|
+
abi: abis.VARLAORACLE_ABI,
|
|
416
|
+
functionName: "isDepositAllowed" as const,
|
|
417
|
+
args: [pid] as const,
|
|
418
|
+
},
|
|
419
|
+
{
|
|
420
|
+
address: params.oracle.address,
|
|
421
|
+
abi: abis.VARLAORACLE_ABI,
|
|
422
|
+
functionName: "isValidCollateral" as const,
|
|
423
|
+
args: [pid] as const,
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
address: params.oracle.address,
|
|
427
|
+
abi: abis.VARLAORACLE_ABI,
|
|
428
|
+
functionName: "isPriceStale" as const,
|
|
429
|
+
args: [pid] as const,
|
|
430
|
+
},
|
|
431
|
+
]);
|
|
432
|
+
|
|
433
|
+
const res = await multicallChunks({
|
|
434
|
+
client: params.client as any,
|
|
435
|
+
contracts: calls as any,
|
|
436
|
+
chunkSize,
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
const out: ReadOracleCollateralStatus[] = [];
|
|
440
|
+
const stride = 5;
|
|
441
|
+
for (let i = 0; i < params.positionIds.length; i++) {
|
|
442
|
+
const base = i * stride;
|
|
443
|
+
const r0: any = (res as any[])[base + 0];
|
|
444
|
+
const r1: any = (res as any[])[base + 1];
|
|
445
|
+
const r2: any = (res as any[])[base + 2];
|
|
446
|
+
const r3: any = (res as any[])[base + 3];
|
|
447
|
+
const r4: any = (res as any[])[base + 4];
|
|
448
|
+
if (
|
|
449
|
+
r0.status !== "success" ||
|
|
450
|
+
r1.status !== "success" ||
|
|
451
|
+
r2.status !== "success" ||
|
|
452
|
+
r3.status !== "success" ||
|
|
453
|
+
r4.status !== "success"
|
|
454
|
+
) {
|
|
455
|
+
throw new Error("Oracle collateral status multicall failed");
|
|
456
|
+
}
|
|
457
|
+
out.push({
|
|
458
|
+
positionId: params.positionIds[i]!,
|
|
459
|
+
isConfigured: r0.result as boolean,
|
|
460
|
+
isResolved: r1.result as boolean,
|
|
461
|
+
isDepositAllowed: r2.result as boolean,
|
|
462
|
+
isValidCollateral: r3.result as boolean,
|
|
463
|
+
isPriceStale: r4.result as boolean,
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
return out;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// wraps: VarlaOracle.isResolved,VarlaOracle.isPriceStale
|
|
470
|
+
export async function readManyOracleStatusFlags(params: {
|
|
471
|
+
oracle: { address: Address };
|
|
472
|
+
client: { multicall: (args: any) => Promise<any> };
|
|
473
|
+
positionIds: readonly bigint[];
|
|
474
|
+
chunkSize?: number;
|
|
475
|
+
}): Promise<Array<{ positionId: bigint; isResolved: boolean; isPriceStale: boolean }>> {
|
|
476
|
+
const chunkSize = params.chunkSize ?? 256;
|
|
477
|
+
if (params.positionIds.length === 0) return [];
|
|
478
|
+
|
|
479
|
+
const calls = params.positionIds.flatMap((pid) => [
|
|
480
|
+
{
|
|
481
|
+
address: params.oracle.address,
|
|
482
|
+
abi: abis.VARLAORACLE_ABI,
|
|
483
|
+
functionName: "isResolved" as const,
|
|
484
|
+
args: [pid] as const,
|
|
485
|
+
},
|
|
486
|
+
{
|
|
487
|
+
address: params.oracle.address,
|
|
488
|
+
abi: abis.VARLAORACLE_ABI,
|
|
489
|
+
functionName: "isPriceStale" as const,
|
|
490
|
+
args: [pid] as const,
|
|
491
|
+
},
|
|
492
|
+
]);
|
|
493
|
+
|
|
494
|
+
const res = await multicallChunks({
|
|
495
|
+
client: params.client as any,
|
|
496
|
+
contracts: calls as any,
|
|
497
|
+
chunkSize,
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
const out: Array<{ positionId: bigint; isResolved: boolean; isPriceStale: boolean }> = [];
|
|
501
|
+
const stride = 2;
|
|
502
|
+
for (let i = 0; i < params.positionIds.length; i++) {
|
|
503
|
+
const base = i * stride;
|
|
504
|
+
const r0: any = (res as any[])[base + 0];
|
|
505
|
+
const r1: any = (res as any[])[base + 1];
|
|
506
|
+
if (r0.status !== "success" || r1.status !== "success") {
|
|
507
|
+
throw new Error("Oracle status flags multicall failed");
|
|
508
|
+
}
|
|
509
|
+
out.push({
|
|
510
|
+
positionId: params.positionIds[i]!,
|
|
511
|
+
isResolved: r0.result as boolean,
|
|
512
|
+
isPriceStale: r1.result as boolean,
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
return out;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* Multicall-chunked timing hydration for many positions.
|
|
520
|
+
*/
|
|
521
|
+
// wraps: VarlaOracle.getEarlyClosureWindow,VarlaOracle.getEarlyClosureFactor,VarlaOracle.lastRecoveryFromStale,VarlaOracle.getLastUpdated
|
|
522
|
+
export async function readManyOracleTiming(params: {
|
|
523
|
+
oracle: { address: Address };
|
|
524
|
+
client: { multicall: (args: any) => Promise<any> };
|
|
525
|
+
positionIds: readonly bigint[];
|
|
526
|
+
chunkSize?: number;
|
|
527
|
+
}): Promise<ReadOracleTiming[]> {
|
|
528
|
+
const chunkSize = params.chunkSize ?? 256;
|
|
529
|
+
if (params.positionIds.length === 0) return [];
|
|
530
|
+
|
|
531
|
+
const calls = params.positionIds.flatMap((pid) => [
|
|
532
|
+
{
|
|
533
|
+
address: params.oracle.address,
|
|
534
|
+
abi: abis.VARLAORACLE_ABI,
|
|
535
|
+
functionName: "getEarlyClosureWindow" as const,
|
|
536
|
+
args: [pid] as const,
|
|
537
|
+
},
|
|
538
|
+
{
|
|
539
|
+
address: params.oracle.address,
|
|
540
|
+
abi: abis.VARLAORACLE_ABI,
|
|
541
|
+
functionName: "getEarlyClosureFactor" as const,
|
|
542
|
+
args: [pid] as const,
|
|
543
|
+
},
|
|
544
|
+
{
|
|
545
|
+
address: params.oracle.address,
|
|
546
|
+
abi: abis.VARLAORACLE_ABI,
|
|
547
|
+
functionName: "lastRecoveryFromStale" as const,
|
|
548
|
+
args: [pid] as const,
|
|
549
|
+
},
|
|
550
|
+
{
|
|
551
|
+
address: params.oracle.address,
|
|
552
|
+
abi: abis.VARLAORACLE_ABI,
|
|
553
|
+
functionName: "getLastUpdated" as const,
|
|
554
|
+
args: [pid] as const,
|
|
555
|
+
},
|
|
556
|
+
]);
|
|
557
|
+
|
|
558
|
+
const res = await multicallChunks({
|
|
559
|
+
client: params.client as any,
|
|
560
|
+
contracts: calls as any,
|
|
561
|
+
chunkSize,
|
|
562
|
+
});
|
|
563
|
+
|
|
564
|
+
const out: ReadOracleTiming[] = [];
|
|
565
|
+
const stride = 4;
|
|
566
|
+
for (let i = 0; i < params.positionIds.length; i++) {
|
|
567
|
+
const base = i * stride;
|
|
568
|
+
const r0: any = (res as any[])[base + 0];
|
|
569
|
+
const r1: any = (res as any[])[base + 1];
|
|
570
|
+
const r2: any = (res as any[])[base + 2];
|
|
571
|
+
const r3: any = (res as any[])[base + 3];
|
|
572
|
+
if (
|
|
573
|
+
r0.status !== "success" ||
|
|
574
|
+
r1.status !== "success" ||
|
|
575
|
+
r2.status !== "success" ||
|
|
576
|
+
r3.status !== "success"
|
|
577
|
+
) {
|
|
578
|
+
throw new Error("Oracle timing multicall failed");
|
|
579
|
+
}
|
|
580
|
+
out.push({
|
|
581
|
+
positionId: params.positionIds[i]!,
|
|
582
|
+
earlyClosureWindow: r0.result as bigint,
|
|
583
|
+
earlyClosureFactorWad: r1.result as bigint,
|
|
584
|
+
lastRecoveryFromStale: r2.result as bigint,
|
|
585
|
+
lastUpdated: r3.result as bigint,
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
return out;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
/**
|
|
592
|
+
* Multicall-chunked tryGetPrice hydration for many positions.
|
|
593
|
+
*/
|
|
594
|
+
// wraps: VarlaOracle.tryGetPrice
|
|
595
|
+
export async function readManyTryGetPrice(params: {
|
|
596
|
+
oracle: { address: Address };
|
|
597
|
+
client: { multicall: (args: any) => Promise<any> };
|
|
598
|
+
positionIds: readonly bigint[];
|
|
599
|
+
chunkSize?: number;
|
|
600
|
+
}): Promise<ReadTryGetPrice[]> {
|
|
601
|
+
const chunkSize = params.chunkSize ?? 256;
|
|
602
|
+
if (params.positionIds.length === 0) return [];
|
|
603
|
+
|
|
604
|
+
const calls = params.positionIds.map((pid) => ({
|
|
605
|
+
address: params.oracle.address,
|
|
606
|
+
abi: abis.VARLAORACLE_ABI,
|
|
607
|
+
functionName: "tryGetPrice" as const,
|
|
608
|
+
args: [pid] as const,
|
|
609
|
+
}));
|
|
610
|
+
|
|
611
|
+
const res = await multicallChunks({
|
|
612
|
+
client: params.client as any,
|
|
613
|
+
contracts: calls as any,
|
|
614
|
+
chunkSize,
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
const out: ReadTryGetPrice[] = [];
|
|
618
|
+
for (let i = 0; i < res.length; i++) {
|
|
619
|
+
const r: any = (res as any[])[i];
|
|
620
|
+
if (r.status !== "success") {
|
|
621
|
+
throw new Error(`Oracle tryGetPrice multicall failed: ${String(r.error ?? "unknown")}`);
|
|
622
|
+
}
|
|
623
|
+
out.push(
|
|
624
|
+
await readTryGetPrice({
|
|
625
|
+
oracle: {
|
|
626
|
+
read: {
|
|
627
|
+
tryGetPrice: async () => r.result,
|
|
628
|
+
},
|
|
629
|
+
} as any,
|
|
630
|
+
positionId: params.positionIds[i]!,
|
|
631
|
+
}),
|
|
632
|
+
);
|
|
633
|
+
}
|
|
634
|
+
return out;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
/**
|
|
638
|
+
* Multicall-chunked price data hydration for many positions.
|
|
639
|
+
*/
|
|
640
|
+
// wraps: VarlaOracle.getPriceData
|
|
641
|
+
export async function readManyOraclePriceData(params: {
|
|
642
|
+
oracle: { address: Address };
|
|
643
|
+
client: { multicall: (args: any) => Promise<any> };
|
|
644
|
+
positionIds: readonly bigint[];
|
|
645
|
+
chunkSize?: number;
|
|
646
|
+
}): Promise<ReadOraclePriceData[]> {
|
|
647
|
+
const chunkSize = params.chunkSize ?? 256;
|
|
648
|
+
if (params.positionIds.length === 0) return [];
|
|
649
|
+
|
|
650
|
+
const calls = params.positionIds.map((pid) => ({
|
|
651
|
+
address: params.oracle.address,
|
|
652
|
+
abi: abis.VARLAORACLE_ABI,
|
|
653
|
+
functionName: "getPriceData" as const,
|
|
654
|
+
args: [pid] as const,
|
|
655
|
+
}));
|
|
656
|
+
|
|
657
|
+
const res = await multicallChunks({
|
|
658
|
+
client: params.client as any,
|
|
659
|
+
contracts: calls as any,
|
|
660
|
+
chunkSize,
|
|
661
|
+
});
|
|
662
|
+
|
|
663
|
+
const out: ReadOraclePriceData[] = [];
|
|
664
|
+
for (let i = 0; i < res.length; i++) {
|
|
665
|
+
const r: any = (res as any[])[i];
|
|
666
|
+
if (r.status !== "success") {
|
|
667
|
+
throw new Error(`Oracle getPriceData multicall failed: ${String(r.error ?? "unknown")}`);
|
|
668
|
+
}
|
|
669
|
+
out.push(
|
|
670
|
+
await readOraclePriceData({
|
|
671
|
+
oracle: {
|
|
672
|
+
read: {
|
|
673
|
+
getPriceData: async () => r.result,
|
|
674
|
+
},
|
|
675
|
+
} as any,
|
|
676
|
+
positionId: params.positionIds[i]!,
|
|
677
|
+
}),
|
|
678
|
+
);
|
|
679
|
+
}
|
|
680
|
+
return out;
|
|
681
|
+
}
|
|
682
|
+
|
|
371
683
|
// wraps: VarlaOracle.getConfiguredPositions
|
|
372
684
|
export async function readConfiguredPositionIds(params: {
|
|
373
685
|
oracle: {
|
|
@@ -457,7 +769,7 @@ function normalizePositionSnapshot(raw: unknown, positionId: bigint): ReadPositi
|
|
|
457
769
|
const priceE8 = r.priceE8 ?? r[1];
|
|
458
770
|
const manuallyInvalidated = r.manuallyInvalidated ?? r[2];
|
|
459
771
|
const riskTier = r.riskTier ?? r[3];
|
|
460
|
-
const earlyClosureFactorWad = r.earlyClosureFactorWad ?? r[4];
|
|
772
|
+
const earlyClosureFactorWad = r.earlyClosureFactorWad ?? r.ltvAdjustmentFactorWad ?? r[4];
|
|
461
773
|
const lastRecoveryFromStale = r.lastRecoveryFromStale_ ?? r.lastRecoveryFromStale ?? r[5];
|
|
462
774
|
const isFinalized = r.isFinalized_ ?? r.isFinalized ?? r[6];
|
|
463
775
|
|
|
@@ -741,3 +1053,78 @@ export async function hydrateOraclePositionIds(params: {
|
|
|
741
1053
|
]);
|
|
742
1054
|
return { positionIds: [...params.positionIds], snapshots, meta };
|
|
743
1055
|
}
|
|
1056
|
+
|
|
1057
|
+
/**
|
|
1058
|
+
* Aggregate reader for the admin Oracle page.
|
|
1059
|
+
*/
|
|
1060
|
+
// wraps: VarlaOracle.maxStaleness,VarlaOracle.liquidationGracePeriod,VarlaOracle.defaultEarlyClosureWindow,VarlaOracle.updater,VarlaOracle.collateralDecimals,VarlaOracle.getConfiguredPositions,VarlaOracle.getPositionSnapshot,VarlaOracle.getConditionId,VarlaOracle.getResolutionTime,VarlaOracle.getOppositePositionId,VarlaOracle.isNegRisk,VarlaOracle.getNegRiskMarketId,VarlaOracle.isManuallyInvalidated,VarlaOracle.isConfigured,VarlaOracle.isResolved,VarlaOracle.isDepositAllowed,VarlaOracle.isValidCollateral,VarlaOracle.isPriceStale,VarlaOracle.getEarlyClosureWindow,VarlaOracle.getEarlyClosureFactor,VarlaOracle.lastRecoveryFromStale,VarlaOracle.getLastUpdated,VarlaOracle.tryGetPrice,VarlaOracle.getPriceData
|
|
1061
|
+
export async function readOracleDashboard(params: {
|
|
1062
|
+
oracle: {
|
|
1063
|
+
address: Address;
|
|
1064
|
+
read: {
|
|
1065
|
+
maxStaleness: () => Promise<bigint>;
|
|
1066
|
+
liquidationGracePeriod: () => Promise<bigint>;
|
|
1067
|
+
defaultEarlyClosureWindow: () => Promise<bigint>;
|
|
1068
|
+
updater: () => Promise<Address>;
|
|
1069
|
+
collateralDecimals: () => Promise<number | bigint>;
|
|
1070
|
+
getConfiguredPositions: () => Promise<readonly bigint[]>;
|
|
1071
|
+
};
|
|
1072
|
+
};
|
|
1073
|
+
client: { multicall: (args: any) => Promise<any> };
|
|
1074
|
+
chunkSize?: number;
|
|
1075
|
+
}): Promise<ReadOracleDashboard> {
|
|
1076
|
+
const chunkSize = params.chunkSize ?? 256;
|
|
1077
|
+
const [config, basics, positionIds] = await Promise.all([
|
|
1078
|
+
readOracleConfig({ oracle: params.oracle }),
|
|
1079
|
+
readOracleBasics({ oracle: params.oracle }),
|
|
1080
|
+
readConfiguredPositionIds({ oracle: params.oracle }),
|
|
1081
|
+
]);
|
|
1082
|
+
|
|
1083
|
+
if (positionIds.length === 0) {
|
|
1084
|
+
return { config, basics, positionIds: [], rows: [] };
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
const [snapshots, meta, statusFlags, priceData] = await Promise.all([
|
|
1088
|
+
readManyPositionSnapshots({
|
|
1089
|
+
oracle: { address: params.oracle.address },
|
|
1090
|
+
client: params.client,
|
|
1091
|
+
positionIds,
|
|
1092
|
+
chunkSize,
|
|
1093
|
+
}),
|
|
1094
|
+
readManyOraclePositionMeta({
|
|
1095
|
+
oracle: { address: params.oracle.address },
|
|
1096
|
+
client: params.client,
|
|
1097
|
+
positionIds,
|
|
1098
|
+
chunkSize,
|
|
1099
|
+
}),
|
|
1100
|
+
readManyOracleStatusFlags({
|
|
1101
|
+
oracle: { address: params.oracle.address },
|
|
1102
|
+
client: params.client,
|
|
1103
|
+
positionIds,
|
|
1104
|
+
chunkSize,
|
|
1105
|
+
}),
|
|
1106
|
+
readManyOraclePriceData({
|
|
1107
|
+
oracle: { address: params.oracle.address },
|
|
1108
|
+
client: params.client,
|
|
1109
|
+
positionIds,
|
|
1110
|
+
chunkSize,
|
|
1111
|
+
}),
|
|
1112
|
+
]);
|
|
1113
|
+
|
|
1114
|
+
const rows = positionIds.map((positionId, i) => ({
|
|
1115
|
+
positionId,
|
|
1116
|
+
snapshot: snapshots[i]!,
|
|
1117
|
+
meta: meta[i]!,
|
|
1118
|
+
resolvedStatus: {
|
|
1119
|
+
positionId,
|
|
1120
|
+
isResolved: statusFlags[i]!.isResolved,
|
|
1121
|
+
},
|
|
1122
|
+
staleStatus: {
|
|
1123
|
+
positionId,
|
|
1124
|
+
isPriceStale: statusFlags[i]!.isPriceStale,
|
|
1125
|
+
},
|
|
1126
|
+
priceData: priceData[i]!,
|
|
1127
|
+
}));
|
|
1128
|
+
|
|
1129
|
+
return { config, basics, positionIds, rows };
|
|
1130
|
+
}
|