@gearbox-protocol/sdk 14.3.1 → 14.4.1
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/cjs/dev/createAnvilClient.js +38 -5
- package/dist/cjs/sdk/accounts/CreditAccountsServiceV310.js +103 -16
- package/dist/esm/dev/createAnvilClient.js +35 -6
- package/dist/esm/sdk/accounts/CreditAccountsServiceV310.js +103 -16
- package/dist/types/dev/createAnvilClient.d.ts +28 -1
- package/dist/types/sdk/accounts/CreditAccountsServiceV310.d.ts +0 -4
- package/dist/types/sdk/accounts/types.d.ts +17 -28
- package/package.json +6 -1
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
var createAnvilClient_exports = {};
|
|
20
30
|
__export(createAnvilClient_exports, {
|
|
@@ -26,11 +36,26 @@ __export(createAnvilClient_exports, {
|
|
|
26
36
|
});
|
|
27
37
|
module.exports = __toCommonJS(createAnvilClient_exports);
|
|
28
38
|
var import_viem = require("viem");
|
|
39
|
+
let dealModulePromise;
|
|
40
|
+
async function loadDeal() {
|
|
41
|
+
dealModulePromise ??= import("viem-deal").catch(() => null);
|
|
42
|
+
const mod = await dealModulePromise;
|
|
43
|
+
if (!mod) {
|
|
44
|
+
throw new Error(
|
|
45
|
+
"createAnvilClient: deal action requires the 'viem-deal' package; install it as a dependency"
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
return mod.deal;
|
|
49
|
+
}
|
|
29
50
|
function extendAnvilClient(client) {
|
|
30
|
-
return client.extend((0, import_viem.testActions)({ mode: "anvil" })).extend(import_viem.walletActions).extend((c) => ({
|
|
51
|
+
return client.extend(() => ({ mode: "anvil" })).extend((0, import_viem.testActions)({ mode: "anvil" })).extend(import_viem.walletActions).extend((c) => ({
|
|
31
52
|
anvilNodeInfo: () => anvilNodeInfo(c),
|
|
32
53
|
isAnvil: () => isAnvil(c),
|
|
33
|
-
evmMineDetailed: (timestamp) => evmMineDetailed(c, timestamp)
|
|
54
|
+
evmMineDetailed: (timestamp) => evmMineDetailed(c, timestamp),
|
|
55
|
+
deal: async (params) => {
|
|
56
|
+
const deal = await loadDeal();
|
|
57
|
+
await deal(c, params);
|
|
58
|
+
}
|
|
34
59
|
}));
|
|
35
60
|
}
|
|
36
61
|
function createAnvilClient({
|
|
@@ -39,13 +64,21 @@ function createAnvilClient({
|
|
|
39
64
|
cacheTime = 0,
|
|
40
65
|
pollingInterval = 50
|
|
41
66
|
}) {
|
|
42
|
-
|
|
67
|
+
return (0, import_viem.createTestClient)({
|
|
68
|
+
mode: "anvil",
|
|
43
69
|
chain,
|
|
44
70
|
transport,
|
|
45
71
|
cacheTime,
|
|
46
72
|
pollingInterval
|
|
47
|
-
})
|
|
48
|
-
|
|
73
|
+
}).extend(import_viem.publicActions).extend(import_viem.walletActions).extend((c) => ({
|
|
74
|
+
anvilNodeInfo: () => anvilNodeInfo(c),
|
|
75
|
+
isAnvil: () => isAnvil(c),
|
|
76
|
+
evmMineDetailed: (timestamp) => evmMineDetailed(c, timestamp),
|
|
77
|
+
deal: async (params) => {
|
|
78
|
+
const deal = await loadDeal();
|
|
79
|
+
await deal(c, params);
|
|
80
|
+
}
|
|
81
|
+
}));
|
|
49
82
|
}
|
|
50
83
|
async function isAnvil(client) {
|
|
51
84
|
try {
|
|
@@ -454,10 +454,63 @@ class CreditAccountsServiceV310 extends import_base.SDKConstruct {
|
|
|
454
454
|
};
|
|
455
455
|
}
|
|
456
456
|
/**
|
|
457
|
-
* {@inheritDoc ICreditAccountsService.
|
|
457
|
+
* {@inheritDoc ICreditAccountsService.partiallyLiquidate}
|
|
458
458
|
*/
|
|
459
|
-
|
|
460
|
-
const { account,
|
|
459
|
+
async partiallyLiquidate(props) {
|
|
460
|
+
const { account, to } = props;
|
|
461
|
+
const tokenOut = props.tokenOut ?? this.#getBestTokenOut(account);
|
|
462
|
+
const optimalHF = props.optimalHF ?? this.getOptimalHFForPartialLiquidation(account);
|
|
463
|
+
const repaidAmount = props.repaidAmount ?? this.#calcOptimalRepaidAmount(account, tokenOut, optimalHF);
|
|
464
|
+
const minSeizedAmount = props.minSeizedAmount ?? this.#calcMinSeizedAmount(account, tokenOut, repaidAmount);
|
|
465
|
+
const cm = this.sdk.marketRegister.findCreditManager(account.creditManager);
|
|
466
|
+
const updates = await this.getOnDemandPriceUpdates(account, true);
|
|
467
|
+
const tx = cm.creditFacade.partiallyLiquidateCreditAccount(
|
|
468
|
+
account.creditAccount,
|
|
469
|
+
tokenOut,
|
|
470
|
+
repaidAmount,
|
|
471
|
+
minSeizedAmount,
|
|
472
|
+
to,
|
|
473
|
+
updates
|
|
474
|
+
);
|
|
475
|
+
return tx;
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
478
|
+
* Picks the most valuable enabled non-underlying collateral token on the
|
|
479
|
+
* credit account (by oracle value in underlying).
|
|
480
|
+
*
|
|
481
|
+
* Ported from solidity:
|
|
482
|
+
* https://github.com/Gearbox-protocol/router-v3/blob/main/contracts/liquidation/AbstractLiquidator.sol#L270
|
|
483
|
+
*/
|
|
484
|
+
#getBestTokenOut(account) {
|
|
485
|
+
const market = this.sdk.marketRegister.findByCreditManager(
|
|
486
|
+
account.creditManager
|
|
487
|
+
);
|
|
488
|
+
const underlying = market.underlying;
|
|
489
|
+
let bestVal = 0n;
|
|
490
|
+
let bestToken;
|
|
491
|
+
for (const t of account.tokens) {
|
|
492
|
+
if (t.token === underlying) continue;
|
|
493
|
+
if ((t.mask & account.enabledTokensMask) === 0n) continue;
|
|
494
|
+
if (t.balance === 0n) continue;
|
|
495
|
+
const val = market.priceOracle.convert(t.token, underlying, t.balance);
|
|
496
|
+
if (val > bestVal) {
|
|
497
|
+
bestVal = val;
|
|
498
|
+
bestToken = t.token;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
if (!bestToken) {
|
|
502
|
+
throw new Error(
|
|
503
|
+
`cannot determine tokenOut for partial liquidation of ${this.sdk.labelAddress(account.creditAccount)}: no enabled non-underlying collateral with value`
|
|
504
|
+
);
|
|
505
|
+
}
|
|
506
|
+
return bestToken;
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* Returns the minimum amount of `token` collateral that must be seized when
|
|
510
|
+
* repaying `repaidAmount` of underlying. Mirrors the on-chain liquidation
|
|
511
|
+
* discount math, expired-aware.
|
|
512
|
+
*/
|
|
513
|
+
#calcMinSeizedAmount(account, token, repaidAmount) {
|
|
461
514
|
const market = this.sdk.marketRegister.findByCreditManager(
|
|
462
515
|
account.creditManager
|
|
463
516
|
);
|
|
@@ -473,21 +526,55 @@ class CreditAccountsServiceV310 extends import_base.SDKConstruct {
|
|
|
473
526
|
return tokenAmount * 9990n / BigInt(fee);
|
|
474
527
|
}
|
|
475
528
|
/**
|
|
476
|
-
*
|
|
529
|
+
* Computes the optimal `repaidAmount` (in underlying) that brings the credit
|
|
530
|
+
* account's health factor close to `optimalHF` after partial liquidation.
|
|
531
|
+
*
|
|
532
|
+
* Ported from solidity:
|
|
533
|
+
* https://github.com/Gearbox-protocol/router-v3/blob/56e2d515ec6d9bb1e324e71c3708e59710779b24/contracts/liquidation/AbstractLiquidator.sol#L292
|
|
477
534
|
*/
|
|
478
|
-
|
|
479
|
-
const
|
|
480
|
-
|
|
481
|
-
const updates = await this.getOnDemandPriceUpdates(account, true);
|
|
482
|
-
const tx = cm.creditFacade.partiallyLiquidateCreditAccount(
|
|
483
|
-
account.creditAccount,
|
|
484
|
-
token,
|
|
485
|
-
repaidAmount,
|
|
486
|
-
minSeizedAmount,
|
|
487
|
-
to,
|
|
488
|
-
updates
|
|
535
|
+
#calcOptimalRepaidAmount(account, token, optimalHF) {
|
|
536
|
+
const suite = this.sdk.marketRegister.findCreditManager(
|
|
537
|
+
account.creditManager
|
|
489
538
|
);
|
|
490
|
-
|
|
539
|
+
const market = this.sdk.marketRegister.findByCreditManager(
|
|
540
|
+
account.creditManager
|
|
541
|
+
);
|
|
542
|
+
const cm = suite.creditManager;
|
|
543
|
+
const feeLiquidation = suite.isExpired ? cm.feeLiquidationExpired : cm.feeLiquidation;
|
|
544
|
+
const liquidationDiscount = suite.isExpired ? cm.liquidationDiscountExpired : cm.liquidationDiscount;
|
|
545
|
+
const discount = BigInt(liquidationDiscount) - BigInt(feeLiquidation);
|
|
546
|
+
const ltTokenOut = cm.liquidationThresholds.get(token);
|
|
547
|
+
if (ltTokenOut === void 0) {
|
|
548
|
+
throw new Error(
|
|
549
|
+
`token ${this.sdk.labelAddress(token)} is not a collateral token in credit manager ${this.sdk.labelAddress(account.creditManager)}`
|
|
550
|
+
);
|
|
551
|
+
}
|
|
552
|
+
const totalDebt = account.debt + account.accruedInterest + account.accruedFees;
|
|
553
|
+
const twvUnderlying = market.priceOracle.convertFromUSD(
|
|
554
|
+
market.underlying,
|
|
555
|
+
account.twvUSD
|
|
556
|
+
);
|
|
557
|
+
const denominator = discount * optimalHF / import_constants.PERCENTAGE_FACTOR - BigInt(ltTokenOut);
|
|
558
|
+
if (denominator <= 0n) {
|
|
559
|
+
throw new Error(
|
|
560
|
+
"cannot compute optimal repaid amount: invalid liquidation parameters (discount * hfOptimal <= ltTokenOut)"
|
|
561
|
+
);
|
|
562
|
+
}
|
|
563
|
+
const numerator = totalDebt * optimalHF - twvUnderlying * import_constants.PERCENTAGE_FACTOR;
|
|
564
|
+
if (numerator <= 0n) {
|
|
565
|
+
return 0n;
|
|
566
|
+
}
|
|
567
|
+
const optimalValueSeized = numerator / denominator;
|
|
568
|
+
let repaidAmount = optimalValueSeized * discount / import_constants.PERCENTAGE_FACTOR;
|
|
569
|
+
const minDebt = suite.creditFacade.minDebt;
|
|
570
|
+
if (totalDebt < minDebt) {
|
|
571
|
+
return 0n;
|
|
572
|
+
}
|
|
573
|
+
const surplusDebt = totalDebt - minDebt;
|
|
574
|
+
if (repaidAmount > surplusDebt) {
|
|
575
|
+
repaidAmount = surplusDebt * 999n / 1000n;
|
|
576
|
+
}
|
|
577
|
+
return repaidAmount;
|
|
491
578
|
}
|
|
492
579
|
/**
|
|
493
580
|
* {@inheritDoc ICreditAccountsService.closeCreditAccount}
|
|
@@ -1,9 +1,30 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
createTestClient,
|
|
3
|
+
publicActions,
|
|
4
|
+
testActions,
|
|
5
|
+
toHex,
|
|
6
|
+
walletActions
|
|
7
|
+
} from "viem";
|
|
8
|
+
let dealModulePromise;
|
|
9
|
+
async function loadDeal() {
|
|
10
|
+
dealModulePromise ??= import("viem-deal").catch(() => null);
|
|
11
|
+
const mod = await dealModulePromise;
|
|
12
|
+
if (!mod) {
|
|
13
|
+
throw new Error(
|
|
14
|
+
"createAnvilClient: deal action requires the 'viem-deal' package; install it as a dependency"
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
return mod.deal;
|
|
18
|
+
}
|
|
2
19
|
function extendAnvilClient(client) {
|
|
3
|
-
return client.extend(testActions({ mode: "anvil" })).extend(walletActions).extend((c) => ({
|
|
20
|
+
return client.extend(() => ({ mode: "anvil" })).extend(testActions({ mode: "anvil" })).extend(walletActions).extend((c) => ({
|
|
4
21
|
anvilNodeInfo: () => anvilNodeInfo(c),
|
|
5
22
|
isAnvil: () => isAnvil(c),
|
|
6
|
-
evmMineDetailed: (timestamp) => evmMineDetailed(c, timestamp)
|
|
23
|
+
evmMineDetailed: (timestamp) => evmMineDetailed(c, timestamp),
|
|
24
|
+
deal: async (params) => {
|
|
25
|
+
const deal = await loadDeal();
|
|
26
|
+
await deal(c, params);
|
|
27
|
+
}
|
|
7
28
|
}));
|
|
8
29
|
}
|
|
9
30
|
function createAnvilClient({
|
|
@@ -12,13 +33,21 @@ function createAnvilClient({
|
|
|
12
33
|
cacheTime = 0,
|
|
13
34
|
pollingInterval = 50
|
|
14
35
|
}) {
|
|
15
|
-
|
|
36
|
+
return createTestClient({
|
|
37
|
+
mode: "anvil",
|
|
16
38
|
chain,
|
|
17
39
|
transport,
|
|
18
40
|
cacheTime,
|
|
19
41
|
pollingInterval
|
|
20
|
-
})
|
|
21
|
-
|
|
42
|
+
}).extend(publicActions).extend(walletActions).extend((c) => ({
|
|
43
|
+
anvilNodeInfo: () => anvilNodeInfo(c),
|
|
44
|
+
isAnvil: () => isAnvil(c),
|
|
45
|
+
evmMineDetailed: (timestamp) => evmMineDetailed(c, timestamp),
|
|
46
|
+
deal: async (params) => {
|
|
47
|
+
const deal = await loadDeal();
|
|
48
|
+
await deal(c, params);
|
|
49
|
+
}
|
|
50
|
+
}));
|
|
22
51
|
}
|
|
23
52
|
async function isAnvil(client) {
|
|
24
53
|
try {
|
|
@@ -449,10 +449,63 @@ class CreditAccountsServiceV310 extends SDKConstruct {
|
|
|
449
449
|
};
|
|
450
450
|
}
|
|
451
451
|
/**
|
|
452
|
-
* {@inheritDoc ICreditAccountsService.
|
|
452
|
+
* {@inheritDoc ICreditAccountsService.partiallyLiquidate}
|
|
453
453
|
*/
|
|
454
|
-
|
|
455
|
-
const { account,
|
|
454
|
+
async partiallyLiquidate(props) {
|
|
455
|
+
const { account, to } = props;
|
|
456
|
+
const tokenOut = props.tokenOut ?? this.#getBestTokenOut(account);
|
|
457
|
+
const optimalHF = props.optimalHF ?? this.getOptimalHFForPartialLiquidation(account);
|
|
458
|
+
const repaidAmount = props.repaidAmount ?? this.#calcOptimalRepaidAmount(account, tokenOut, optimalHF);
|
|
459
|
+
const minSeizedAmount = props.minSeizedAmount ?? this.#calcMinSeizedAmount(account, tokenOut, repaidAmount);
|
|
460
|
+
const cm = this.sdk.marketRegister.findCreditManager(account.creditManager);
|
|
461
|
+
const updates = await this.getOnDemandPriceUpdates(account, true);
|
|
462
|
+
const tx = cm.creditFacade.partiallyLiquidateCreditAccount(
|
|
463
|
+
account.creditAccount,
|
|
464
|
+
tokenOut,
|
|
465
|
+
repaidAmount,
|
|
466
|
+
minSeizedAmount,
|
|
467
|
+
to,
|
|
468
|
+
updates
|
|
469
|
+
);
|
|
470
|
+
return tx;
|
|
471
|
+
}
|
|
472
|
+
/**
|
|
473
|
+
* Picks the most valuable enabled non-underlying collateral token on the
|
|
474
|
+
* credit account (by oracle value in underlying).
|
|
475
|
+
*
|
|
476
|
+
* Ported from solidity:
|
|
477
|
+
* https://github.com/Gearbox-protocol/router-v3/blob/main/contracts/liquidation/AbstractLiquidator.sol#L270
|
|
478
|
+
*/
|
|
479
|
+
#getBestTokenOut(account) {
|
|
480
|
+
const market = this.sdk.marketRegister.findByCreditManager(
|
|
481
|
+
account.creditManager
|
|
482
|
+
);
|
|
483
|
+
const underlying = market.underlying;
|
|
484
|
+
let bestVal = 0n;
|
|
485
|
+
let bestToken;
|
|
486
|
+
for (const t of account.tokens) {
|
|
487
|
+
if (t.token === underlying) continue;
|
|
488
|
+
if ((t.mask & account.enabledTokensMask) === 0n) continue;
|
|
489
|
+
if (t.balance === 0n) continue;
|
|
490
|
+
const val = market.priceOracle.convert(t.token, underlying, t.balance);
|
|
491
|
+
if (val > bestVal) {
|
|
492
|
+
bestVal = val;
|
|
493
|
+
bestToken = t.token;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
if (!bestToken) {
|
|
497
|
+
throw new Error(
|
|
498
|
+
`cannot determine tokenOut for partial liquidation of ${this.sdk.labelAddress(account.creditAccount)}: no enabled non-underlying collateral with value`
|
|
499
|
+
);
|
|
500
|
+
}
|
|
501
|
+
return bestToken;
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* Returns the minimum amount of `token` collateral that must be seized when
|
|
505
|
+
* repaying `repaidAmount` of underlying. Mirrors the on-chain liquidation
|
|
506
|
+
* discount math, expired-aware.
|
|
507
|
+
*/
|
|
508
|
+
#calcMinSeizedAmount(account, token, repaidAmount) {
|
|
456
509
|
const market = this.sdk.marketRegister.findByCreditManager(
|
|
457
510
|
account.creditManager
|
|
458
511
|
);
|
|
@@ -468,21 +521,55 @@ class CreditAccountsServiceV310 extends SDKConstruct {
|
|
|
468
521
|
return tokenAmount * 9990n / BigInt(fee);
|
|
469
522
|
}
|
|
470
523
|
/**
|
|
471
|
-
*
|
|
524
|
+
* Computes the optimal `repaidAmount` (in underlying) that brings the credit
|
|
525
|
+
* account's health factor close to `optimalHF` after partial liquidation.
|
|
526
|
+
*
|
|
527
|
+
* Ported from solidity:
|
|
528
|
+
* https://github.com/Gearbox-protocol/router-v3/blob/56e2d515ec6d9bb1e324e71c3708e59710779b24/contracts/liquidation/AbstractLiquidator.sol#L292
|
|
472
529
|
*/
|
|
473
|
-
|
|
474
|
-
const
|
|
475
|
-
|
|
476
|
-
const updates = await this.getOnDemandPriceUpdates(account, true);
|
|
477
|
-
const tx = cm.creditFacade.partiallyLiquidateCreditAccount(
|
|
478
|
-
account.creditAccount,
|
|
479
|
-
token,
|
|
480
|
-
repaidAmount,
|
|
481
|
-
minSeizedAmount,
|
|
482
|
-
to,
|
|
483
|
-
updates
|
|
530
|
+
#calcOptimalRepaidAmount(account, token, optimalHF) {
|
|
531
|
+
const suite = this.sdk.marketRegister.findCreditManager(
|
|
532
|
+
account.creditManager
|
|
484
533
|
);
|
|
485
|
-
|
|
534
|
+
const market = this.sdk.marketRegister.findByCreditManager(
|
|
535
|
+
account.creditManager
|
|
536
|
+
);
|
|
537
|
+
const cm = suite.creditManager;
|
|
538
|
+
const feeLiquidation = suite.isExpired ? cm.feeLiquidationExpired : cm.feeLiquidation;
|
|
539
|
+
const liquidationDiscount = suite.isExpired ? cm.liquidationDiscountExpired : cm.liquidationDiscount;
|
|
540
|
+
const discount = BigInt(liquidationDiscount) - BigInt(feeLiquidation);
|
|
541
|
+
const ltTokenOut = cm.liquidationThresholds.get(token);
|
|
542
|
+
if (ltTokenOut === void 0) {
|
|
543
|
+
throw new Error(
|
|
544
|
+
`token ${this.sdk.labelAddress(token)} is not a collateral token in credit manager ${this.sdk.labelAddress(account.creditManager)}`
|
|
545
|
+
);
|
|
546
|
+
}
|
|
547
|
+
const totalDebt = account.debt + account.accruedInterest + account.accruedFees;
|
|
548
|
+
const twvUnderlying = market.priceOracle.convertFromUSD(
|
|
549
|
+
market.underlying,
|
|
550
|
+
account.twvUSD
|
|
551
|
+
);
|
|
552
|
+
const denominator = discount * optimalHF / PERCENTAGE_FACTOR - BigInt(ltTokenOut);
|
|
553
|
+
if (denominator <= 0n) {
|
|
554
|
+
throw new Error(
|
|
555
|
+
"cannot compute optimal repaid amount: invalid liquidation parameters (discount * hfOptimal <= ltTokenOut)"
|
|
556
|
+
);
|
|
557
|
+
}
|
|
558
|
+
const numerator = totalDebt * optimalHF - twvUnderlying * PERCENTAGE_FACTOR;
|
|
559
|
+
if (numerator <= 0n) {
|
|
560
|
+
return 0n;
|
|
561
|
+
}
|
|
562
|
+
const optimalValueSeized = numerator / denominator;
|
|
563
|
+
let repaidAmount = optimalValueSeized * discount / PERCENTAGE_FACTOR;
|
|
564
|
+
const minDebt = suite.creditFacade.minDebt;
|
|
565
|
+
if (totalDebt < minDebt) {
|
|
566
|
+
return 0n;
|
|
567
|
+
}
|
|
568
|
+
const surplusDebt = totalDebt - minDebt;
|
|
569
|
+
if (repaidAmount > surplusDebt) {
|
|
570
|
+
repaidAmount = surplusDebt * 999n / 1000n;
|
|
571
|
+
}
|
|
572
|
+
return repaidAmount;
|
|
486
573
|
}
|
|
487
574
|
/**
|
|
488
575
|
* {@inheritDoc ICreditAccountsService.closeCreditAccount}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Block, Chain, Client, Hex, Prettify, PublicClient, TestActions, TestRpcSchema, Transport, WalletClient } from "viem";
|
|
1
|
+
import type { Account, Address, Block, Chain, Client, Hex, Prettify, PublicClient, TestActions, TestRpcSchema, Transport, WalletClient } from "viem";
|
|
2
2
|
export interface AnvilNodeInfo {
|
|
3
3
|
currentBlockNumber: string;
|
|
4
4
|
currentBlockTimestamp: number;
|
|
@@ -30,6 +30,20 @@ export type AnvilRPCSchema = [
|
|
|
30
30
|
ReturnType: Block<Hex>[];
|
|
31
31
|
}
|
|
32
32
|
];
|
|
33
|
+
export interface AnvilDealParameters {
|
|
34
|
+
/**
|
|
35
|
+
* ERC20 token address.
|
|
36
|
+
*/
|
|
37
|
+
erc20: Address;
|
|
38
|
+
/**
|
|
39
|
+
* Account that should receive the tokens.
|
|
40
|
+
*/
|
|
41
|
+
account: Account | Address;
|
|
42
|
+
/**
|
|
43
|
+
* Token amount in raw units (no decimals applied).
|
|
44
|
+
*/
|
|
45
|
+
amount: bigint;
|
|
46
|
+
}
|
|
33
47
|
export type AnvilActions = {
|
|
34
48
|
anvilNodeInfo: () => Promise<AnvilNodeInfo>;
|
|
35
49
|
isAnvil: () => Promise<boolean>;
|
|
@@ -38,6 +52,11 @@ export type AnvilActions = {
|
|
|
38
52
|
* Block timestamp in seconds
|
|
39
53
|
*/
|
|
40
54
|
timestamp: bigint | number) => Promise<Block<Hex> | undefined>;
|
|
55
|
+
/**
|
|
56
|
+
* Deals ERC20 tokens to an account by overriding the storage of
|
|
57
|
+
* `balanceOf(account)`. Requires `viem-deal` as a peer dependency.
|
|
58
|
+
*/
|
|
59
|
+
deal: (params: AnvilDealParameters) => Promise<void>;
|
|
41
60
|
};
|
|
42
61
|
export type AnvilClient = Prettify<{
|
|
43
62
|
mode: "anvil";
|
|
@@ -48,6 +67,14 @@ export interface AnvilClientConfig<transport extends Transport = Transport, chai
|
|
|
48
67
|
cacheTime?: number;
|
|
49
68
|
pollingInterval?: number;
|
|
50
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Extends an arbitrary viem `PublicClient` with anvil + wallet actions plus
|
|
72
|
+
* the SDK's bonus actions (`anvilNodeInfo`, `isAnvil`, `evmMineDetailed`,
|
|
73
|
+
* `deal`).
|
|
74
|
+
*
|
|
75
|
+
* Used to lift `sdk.client` into an `AnvilClient` shape on the fly when test
|
|
76
|
+
* RPCs (impersonateAccount, setBalance, setStorageAt, ...) are needed.
|
|
77
|
+
*/
|
|
51
78
|
export declare function extendAnvilClient(client: PublicClient): AnvilClient;
|
|
52
79
|
export declare function createAnvilClient({ chain, transport, cacheTime, pollingInterval, }: AnvilClientConfig): AnvilClient;
|
|
53
80
|
/**
|
|
@@ -64,10 +64,6 @@ export declare class CreditAccountsServiceV310 extends SDKConstruct implements I
|
|
|
64
64
|
* {@inheritDoc ICreditAccountsService.fullyLiquidate}
|
|
65
65
|
**/
|
|
66
66
|
fullyLiquidate(props: FullyLiquidateProps): Promise<FullyLiquidateResult>;
|
|
67
|
-
/**
|
|
68
|
-
* {@inheritDoc ICreditAccountsService.calcMinSeizedAmount}
|
|
69
|
-
*/
|
|
70
|
-
calcMinSeizedAmount(props: PartiallyLiquidateProps): bigint;
|
|
71
67
|
/**
|
|
72
68
|
* {@inheritDoc ICreditAccountsService.partiallyLiquidate}
|
|
73
69
|
*/
|
|
@@ -488,41 +488,37 @@ export interface FullyLiquidateProps {
|
|
|
488
488
|
*/
|
|
489
489
|
debtOnly?: boolean;
|
|
490
490
|
}
|
|
491
|
-
export interface CalcMinSeizedAmountProps {
|
|
492
|
-
/**
|
|
493
|
-
* Credit account to liquidate
|
|
494
|
-
*/
|
|
495
|
-
account: RouterCASlice;
|
|
496
|
-
/**
|
|
497
|
-
* Collateral token to seize
|
|
498
|
-
*/
|
|
499
|
-
token: Address;
|
|
500
|
-
/**
|
|
501
|
-
* Amount of underlying token to repay
|
|
502
|
-
*/
|
|
503
|
-
repaidAmount: bigint;
|
|
504
|
-
}
|
|
505
491
|
export interface PartiallyLiquidateProps {
|
|
506
492
|
/**
|
|
507
493
|
* Credit account to liquidate
|
|
508
494
|
*/
|
|
509
|
-
account:
|
|
495
|
+
account: CreditAccountData;
|
|
510
496
|
/**
|
|
511
497
|
* Address to transfer underlying left after liquidation
|
|
512
498
|
*/
|
|
513
499
|
to: Address;
|
|
514
500
|
/**
|
|
515
|
-
* Collateral token to seize
|
|
501
|
+
* Collateral token to seize.
|
|
502
|
+
* If omitted, the most valuable enabled non-underlying collateral token
|
|
503
|
+
* (by oracle)
|
|
516
504
|
*/
|
|
517
|
-
|
|
505
|
+
tokenOut?: Address;
|
|
518
506
|
/**
|
|
519
|
-
* Amount of underlying token to repay
|
|
507
|
+
* Amount of underlying token to repay.
|
|
508
|
+
* If omitted, computed internally
|
|
520
509
|
*/
|
|
521
|
-
repaidAmount
|
|
510
|
+
repaidAmount?: bigint;
|
|
522
511
|
/**
|
|
523
|
-
* Minimum amount of `token` to seize from `creditAccount
|
|
512
|
+
* Minimum amount of `token` to seize from `creditAccount`.
|
|
513
|
+
* If omitted, computed internally
|
|
524
514
|
*/
|
|
525
|
-
minSeizedAmount
|
|
515
|
+
minSeizedAmount?: bigint;
|
|
516
|
+
/**
|
|
517
|
+
* Target health factor for partial liquidation (4 digits precision, 10000 = 100%).
|
|
518
|
+
* If omitted, defaults to {@link ICreditAccountsService.getOptimalHFForPartialLiquidation}.
|
|
519
|
+
* Only used when `repaidAmount` is not explicitly provided.
|
|
520
|
+
*/
|
|
521
|
+
optimalHF?: bigint;
|
|
526
522
|
}
|
|
527
523
|
/**
|
|
528
524
|
* EIP-2612 permit signature data for a token, enabling gasless approval for credit account operations.
|
|
@@ -717,13 +713,6 @@ export interface ICreditAccountsService extends Construct {
|
|
|
717
713
|
* @returns Transaction data and optional loss policy data
|
|
718
714
|
*/
|
|
719
715
|
fullyLiquidate(props: FullyLiquidateProps): Promise<FullyLiquidateResult>;
|
|
720
|
-
/**
|
|
721
|
-
* Calculates minimum amount of collateral token to seize from credit account
|
|
722
|
-
* for partial liquidation, can be passed to {@link partiallyLiquidate} as `minSeizedAmount`
|
|
723
|
-
* @param props - {@link CalcMinSeizedAmountProps}
|
|
724
|
-
* @returns Minimum amount of collateral token to seize
|
|
725
|
-
*/
|
|
726
|
-
calcMinSeizedAmount(props: CalcMinSeizedAmountProps): bigint;
|
|
727
716
|
/**
|
|
728
717
|
* Generates transaction to partially liquidate credit account;
|
|
729
718
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gearbox-protocol/sdk",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.4.1",
|
|
4
4
|
"description": "Gearbox SDK",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "./dist/cjs/sdk/index.js",
|
|
@@ -109,6 +109,11 @@
|
|
|
109
109
|
"axios": "^1.0.0",
|
|
110
110
|
"viem-deal": "^2.0.4"
|
|
111
111
|
},
|
|
112
|
+
"peerDependenciesMeta": {
|
|
113
|
+
"viem-deal": {
|
|
114
|
+
"optional": true
|
|
115
|
+
}
|
|
116
|
+
},
|
|
112
117
|
"commitlint": {
|
|
113
118
|
"extends": [
|
|
114
119
|
"@commitlint/config-conventional"
|