@gearbox-protocol/sdk 14.12.0-next.48 → 14.12.0-next.49
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/abi/ILiquidationCompressorV313.js +103 -0
- package/dist/cjs/sdk/accounts/liquidations/LiquidationsService.js +81 -58
- package/dist/cjs/sdk/accounts/liquidations/MultichainLiquidationsService.js +6 -0
- package/dist/cjs/sdk/accounts/liquidations/constants.js +29 -0
- package/dist/cjs/sdk/accounts/liquidations/helpers.js +49 -2
- package/dist/cjs/sdk/accounts/liquidations/index.js +2 -2
- package/dist/esm/abi/ILiquidationCompressorV313.js +79 -0
- package/dist/esm/sdk/accounts/liquidations/LiquidationsService.js +87 -61
- package/dist/esm/sdk/accounts/liquidations/MultichainLiquidationsService.js +6 -0
- package/dist/esm/sdk/accounts/liquidations/constants.js +5 -0
- package/dist/esm/sdk/accounts/liquidations/helpers.js +46 -2
- package/dist/esm/sdk/accounts/liquidations/index.js +1 -1
- package/dist/types/abi/ILiquidationCompressorV313.d.ts +107 -0
- package/dist/types/rewards/rewards/merkl-api.d.ts +1 -1
- package/dist/types/sdk/MultichainSDK.d.ts +1 -1
- package/dist/types/sdk/accounts/liquidations/LiquidationsService.d.ts +6 -1
- package/dist/types/sdk/accounts/liquidations/MultichainLiquidationsService.d.ts +11 -6
- package/dist/types/sdk/accounts/liquidations/constants.d.ts +6 -0
- package/dist/types/sdk/accounts/liquidations/helpers.d.ts +73 -2
- package/dist/types/sdk/accounts/liquidations/index.d.ts +1 -1
- package/dist/types/sdk/accounts/liquidations/types.d.ts +142 -30
- package/package.json +9 -9
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var ILiquidationCompressorV313_exports = {};
|
|
20
|
+
__export(ILiquidationCompressorV313_exports, {
|
|
21
|
+
iLiquidationCompressorV313Abi: () => iLiquidationCompressorV313Abi
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(ILiquidationCompressorV313_exports);
|
|
24
|
+
const iLiquidationCompressorV313Abi = [
|
|
25
|
+
{
|
|
26
|
+
type: "function",
|
|
27
|
+
name: "contractType",
|
|
28
|
+
inputs: [],
|
|
29
|
+
outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }],
|
|
30
|
+
stateMutability: "view"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
type: "function",
|
|
34
|
+
name: "getLiquidationData",
|
|
35
|
+
inputs: [
|
|
36
|
+
{ name: "liquidator", type: "address", internalType: "address" },
|
|
37
|
+
{ name: "creditAccount", type: "address", internalType: "address" },
|
|
38
|
+
{
|
|
39
|
+
name: "priceUpdates",
|
|
40
|
+
type: "tuple[]",
|
|
41
|
+
internalType: "struct PriceUpdate[]",
|
|
42
|
+
components: [
|
|
43
|
+
{ name: "priceFeed", type: "address", internalType: "address" },
|
|
44
|
+
{ name: "data", type: "bytes", internalType: "bytes" }
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
],
|
|
48
|
+
outputs: [
|
|
49
|
+
{
|
|
50
|
+
name: "",
|
|
51
|
+
type: "tuple",
|
|
52
|
+
internalType: "struct LiquidationData",
|
|
53
|
+
components: [
|
|
54
|
+
{
|
|
55
|
+
name: "requiredUnderlyingAmount",
|
|
56
|
+
type: "uint256",
|
|
57
|
+
internalType: "uint256"
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: "expectedOutputs",
|
|
61
|
+
type: "tuple[]",
|
|
62
|
+
internalType: "struct LiquidationOutput[]",
|
|
63
|
+
components: [
|
|
64
|
+
{ name: "token", type: "address", internalType: "address" },
|
|
65
|
+
{ name: "amount", type: "uint256", internalType: "uint256" },
|
|
66
|
+
{ name: "delayed", type: "bool", internalType: "bool" },
|
|
67
|
+
{
|
|
68
|
+
name: "redeemerAddress",
|
|
69
|
+
type: "address",
|
|
70
|
+
internalType: "address"
|
|
71
|
+
},
|
|
72
|
+
{ name: "claimableAt", type: "uint256", internalType: "uint256" }
|
|
73
|
+
]
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: "liquidationCall",
|
|
77
|
+
type: "tuple",
|
|
78
|
+
internalType: "struct MultiCall",
|
|
79
|
+
components: [
|
|
80
|
+
{ name: "target", type: "address", internalType: "address" },
|
|
81
|
+
{ name: "callData", type: "bytes", internalType: "bytes" }
|
|
82
|
+
]
|
|
83
|
+
},
|
|
84
|
+
{ name: "isLiquidatorEligible", type: "bool", internalType: "bool" },
|
|
85
|
+
{ name: "kycProtocol", type: "string", internalType: "string" },
|
|
86
|
+
{ name: "kycToken", type: "address", internalType: "address" }
|
|
87
|
+
]
|
|
88
|
+
}
|
|
89
|
+
],
|
|
90
|
+
stateMutability: "nonpayable"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
type: "function",
|
|
94
|
+
name: "version",
|
|
95
|
+
inputs: [],
|
|
96
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
97
|
+
stateMutability: "view"
|
|
98
|
+
}
|
|
99
|
+
];
|
|
100
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
101
|
+
0 && (module.exports = {
|
|
102
|
+
iLiquidationCompressorV313Abi
|
|
103
|
+
});
|
|
@@ -21,18 +21,17 @@ __export(LiquidationsService_exports, {
|
|
|
21
21
|
LiquidationsService: () => LiquidationsService
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(LiquidationsService_exports);
|
|
24
|
+
var import_ILiquidationCompressorV313 = require("../../../abi/ILiquidationCompressorV313.js");
|
|
24
25
|
var import_base = require("../../base/index.js");
|
|
25
26
|
var import_constants = require("../../constants/index.js");
|
|
26
27
|
var import_utils = require("../../utils/index.js");
|
|
28
|
+
var import_constants2 = require("./constants.js");
|
|
27
29
|
var import_helpers = require("./helpers.js");
|
|
28
30
|
class LiquidationsService extends import_base.SDKConstruct {
|
|
29
31
|
/**
|
|
30
32
|
* {@inheritDoc ILiquidationsService.getLiquidatableAccounts}
|
|
31
33
|
**/
|
|
32
34
|
async getLiquidatableAccounts(props) {
|
|
33
|
-
if (props?.networks && !props.networks.includes(this.sdk.networkType)) {
|
|
34
|
-
return [];
|
|
35
|
-
}
|
|
36
35
|
await this.sdk.withdrawalCompressor?.loadWithdrawableAssets();
|
|
37
36
|
const accounts = await this.sdk.accounts.getCreditAccounts({
|
|
38
37
|
maxHealthFactor: import_constants.WAD - 1n,
|
|
@@ -67,67 +66,58 @@ class LiquidationsService extends import_base.SDKConstruct {
|
|
|
67
66
|
* {@inheritDoc ILiquidationsService.getLiquidationDetails}
|
|
68
67
|
**/
|
|
69
68
|
async getLiquidationDetails(props) {
|
|
70
|
-
const {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
`network mismatch: this SDK is attached to ${this.sdk.networkType}, requested ${network}`
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
const ca = await this.sdk.accounts.getCreditAccountData(creditAccount);
|
|
77
|
-
if (!ca) {
|
|
78
|
-
throw new Error(`credit account ${creditAccount} not found`);
|
|
79
|
-
}
|
|
80
|
-
if (!ca.success) {
|
|
81
|
-
throw new Error(
|
|
82
|
-
`cannot compute liquidation details for ${creditAccount}: collateral computation failed`
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
const compressor = this.sdk.withdrawalCompressor;
|
|
86
|
-
await compressor?.loadWithdrawableAssets();
|
|
69
|
+
const { creditAccount, liquidator, ignoreReservePrices } = props;
|
|
70
|
+
const ca = await this.#getCreditAccountData(creditAccount);
|
|
71
|
+
await this.sdk.withdrawalCompressor?.loadWithdrawableAssets();
|
|
87
72
|
const account = this.#buildAccount(ca);
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
73
|
+
const data = await this.#getLiquidationData(
|
|
74
|
+
ca,
|
|
75
|
+
liquidator,
|
|
76
|
+
ignoreReservePrices
|
|
77
|
+
);
|
|
78
|
+
const suite = this.sdk.marketRegister.findCreditManager(ca.creditManager);
|
|
79
|
+
return {
|
|
80
|
+
...account,
|
|
81
|
+
// the compressor reports the exact amounts of the liquidation path it
|
|
82
|
+
// selected, which supersede the estimates of the list row
|
|
83
|
+
repaymentAmount: {
|
|
84
|
+
token: account.totalValue.token,
|
|
85
|
+
balance: data.requiredUnderlyingAmount
|
|
86
|
+
},
|
|
87
|
+
isDelayed: data.expectedOutputs.some((o) => o.delayed),
|
|
88
|
+
receivedAssets: (0, import_helpers.toReceivedAssets)(data.expectedOutputs),
|
|
89
|
+
isLiquidatorEligible: data.isLiquidatorEligible,
|
|
90
|
+
kycProtocol: data.kycProtocol || void 0,
|
|
91
|
+
kycToken: (0, import_utils.hexEq)(data.kycToken, import_constants.ADDRESS_0X0) ? void 0 : data.kycToken,
|
|
92
|
+
approve: (0, import_helpers.toLiquidationApproval)({
|
|
93
|
+
target: data.liquidationCall.target,
|
|
94
|
+
creditFacade: suite.creditFacade.address,
|
|
95
|
+
creditManager: ca.creditManager,
|
|
96
|
+
token: suite.underlying,
|
|
97
|
+
amount: data.requiredUnderlyingAmount
|
|
98
|
+
})
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* {@inheritDoc ILiquidationsService.buildLiquidationTx}
|
|
103
|
+
**/
|
|
104
|
+
async buildLiquidationTx(props) {
|
|
105
|
+
const { creditAccount, liquidator, ignoreReservePrices } = props;
|
|
106
|
+
const ca = await this.#getCreditAccountData(creditAccount);
|
|
107
|
+
const data = await this.#getLiquidationData(
|
|
108
|
+
ca,
|
|
109
|
+
liquidator,
|
|
110
|
+
ignoreReservePrices
|
|
111
|
+
);
|
|
112
|
+
return (0, import_helpers.liquidationCallToRawTx)(
|
|
113
|
+
data.liquidationCall,
|
|
114
|
+
`liquidate credit account ${this.labelAddress(creditAccount)} to ${this.labelAddress(liquidator)}`
|
|
115
|
+
);
|
|
123
116
|
}
|
|
124
117
|
/**
|
|
125
118
|
* {@inheritDoc ILiquidationsService.getLiquidatorWithdrawals}
|
|
126
119
|
**/
|
|
127
120
|
async getLiquidatorWithdrawals(props) {
|
|
128
|
-
if (props.networks && !props.networks.includes(this.sdk.networkType)) {
|
|
129
|
-
return [];
|
|
130
|
-
}
|
|
131
121
|
const compressor = this.sdk.withdrawalCompressor;
|
|
132
122
|
if (!compressor) {
|
|
133
123
|
return [];
|
|
@@ -142,6 +132,39 @@ class LiquidationsService extends import_base.SDKConstruct {
|
|
|
142
132
|
);
|
|
143
133
|
return (0, import_helpers.toLiquidatorWithdrawals)(current, this.sdk.networkType);
|
|
144
134
|
}
|
|
135
|
+
async #getCreditAccountData(creditAccount) {
|
|
136
|
+
const ca = await this.sdk.accounts.getCreditAccountData(creditAccount);
|
|
137
|
+
if (!ca) {
|
|
138
|
+
throw new Error(`credit account ${creditAccount} not found`);
|
|
139
|
+
}
|
|
140
|
+
if (!ca.success) {
|
|
141
|
+
throw new Error(
|
|
142
|
+
`cannot compute liquidation details for ${creditAccount}: collateral computation failed`
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
return ca;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Previews the liquidation via the liquidation compressor.
|
|
149
|
+
*
|
|
150
|
+
* @param ca - Credit account to liquidate
|
|
151
|
+
* @param liquidator - Liquidator wallet, zero address when not known: it only
|
|
152
|
+
* affects the KYC eligibility fields and the receiver encoded into the calls
|
|
153
|
+
* @param ignoreReservePrices - Exclude reserve price feeds from the updates
|
|
154
|
+
**/
|
|
155
|
+
async #getLiquidationData(ca, liquidator = import_constants.ADDRESS_0X0, ignoreReservePrices) {
|
|
156
|
+
const priceUpdates = await this.sdk.accounts.getOnDemandPriceUpdates(
|
|
157
|
+
ca,
|
|
158
|
+
ignoreReservePrices
|
|
159
|
+
);
|
|
160
|
+
const { result } = await this.client.simulateContract({
|
|
161
|
+
address: import_constants2.LIQUIDATION_COMPRESSOR_V313_ADDRESS,
|
|
162
|
+
abi: import_ILiquidationCompressorV313.iLiquidationCompressorV313Abi,
|
|
163
|
+
functionName: "getLiquidationData",
|
|
164
|
+
args: [liquidator, ca.creditAccount, priceUpdates]
|
|
165
|
+
});
|
|
166
|
+
return result;
|
|
167
|
+
}
|
|
145
168
|
/**
|
|
146
169
|
* Accounts of expired credit managers with outstanding debt are liquidatable
|
|
147
170
|
* regardless of their health factor.
|
|
@@ -58,6 +58,12 @@ class MultichainLiquidationsService {
|
|
|
58
58
|
async getLiquidationDetails(props) {
|
|
59
59
|
return this.#sdk.chain(props.network).liquidations.getLiquidationDetails(props);
|
|
60
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* {@inheritDoc ILiquidationsService.buildLiquidationTx}
|
|
63
|
+
**/
|
|
64
|
+
async buildLiquidationTx(props) {
|
|
65
|
+
return this.#sdk.chain(props.network).liquidations.buildLiquidationTx(props);
|
|
66
|
+
}
|
|
61
67
|
/**
|
|
62
68
|
* {@inheritDoc ILiquidationsService.getLiquidatorWithdrawals}
|
|
63
69
|
**/
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var constants_exports = {};
|
|
20
|
+
__export(constants_exports, {
|
|
21
|
+
LIQUIDATION_COMPRESSOR_V313_ADDRESS: () => LIQUIDATION_COMPRESSOR_V313_ADDRESS
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(constants_exports);
|
|
24
|
+
var import_constants = require("../../constants/index.js");
|
|
25
|
+
const LIQUIDATION_COMPRESSOR_V313_ADDRESS = import_constants.ADDRESS_0X0;
|
|
26
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
27
|
+
0 && (module.exports = {
|
|
28
|
+
LIQUIDATION_COMPRESSOR_V313_ADDRESS
|
|
29
|
+
});
|
|
@@ -21,10 +21,14 @@ __export(helpers_exports, {
|
|
|
21
21
|
DUST_THRESHOLD: () => DUST_THRESHOLD,
|
|
22
22
|
calcEstimatedProfit: () => calcEstimatedProfit,
|
|
23
23
|
calcRepaymentAmount: () => calcRepaymentAmount,
|
|
24
|
+
liquidationCallToRawTx: () => liquidationCallToRawTx,
|
|
24
25
|
pickMainAsset: () => pickMainAsset,
|
|
25
|
-
|
|
26
|
+
toLiquidationApproval: () => toLiquidationApproval,
|
|
27
|
+
toLiquidatorWithdrawals: () => toLiquidatorWithdrawals,
|
|
28
|
+
toReceivedAssets: () => toReceivedAssets
|
|
26
29
|
});
|
|
27
30
|
module.exports = __toCommonJS(helpers_exports);
|
|
31
|
+
var import_viem = require("viem");
|
|
28
32
|
var import_constants = require("../../constants/index.js");
|
|
29
33
|
var import_utils = require("../../utils/index.js");
|
|
30
34
|
const DUST_THRESHOLD = 10n;
|
|
@@ -80,11 +84,54 @@ function toLiquidatorWithdrawals(current, network) {
|
|
|
80
84
|
}
|
|
81
85
|
return rows;
|
|
82
86
|
}
|
|
87
|
+
function toReceivedAssets(outputs) {
|
|
88
|
+
return outputs.map((o) => {
|
|
89
|
+
if (!o.delayed) {
|
|
90
|
+
return { isDelayed: false, token: o.token, amount: o.amount };
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
isDelayed: true,
|
|
94
|
+
token: o.token,
|
|
95
|
+
amount: o.amount,
|
|
96
|
+
redeemerAddress: (0, import_utils.hexEq)(o.redeemerAddress, import_constants.ADDRESS_0X0) ? void 0 : o.redeemerAddress,
|
|
97
|
+
claimableAt: o.claimableAt === 0n ? void 0 : o.claimableAt
|
|
98
|
+
};
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
function toLiquidationApproval(props) {
|
|
102
|
+
const { target, creditFacade, creditManager, token, amount } = props;
|
|
103
|
+
if (amount === 0n) {
|
|
104
|
+
return void 0;
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
spender: (0, import_utils.hexEq)(target, creditFacade) ? creditManager : target,
|
|
108
|
+
token,
|
|
109
|
+
amount
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function liquidationCallToRawTx(call, description) {
|
|
113
|
+
return {
|
|
114
|
+
to: call.target,
|
|
115
|
+
value: "0",
|
|
116
|
+
signature: "",
|
|
117
|
+
callData: call.callData,
|
|
118
|
+
contractMethod: {
|
|
119
|
+
name: (0, import_viem.slice)(call.callData, 0, 4),
|
|
120
|
+
inputs: [],
|
|
121
|
+
payable: false
|
|
122
|
+
},
|
|
123
|
+
contractInputsValues: {},
|
|
124
|
+
description
|
|
125
|
+
};
|
|
126
|
+
}
|
|
83
127
|
// Annotate the CommonJS export names for ESM import in node:
|
|
84
128
|
0 && (module.exports = {
|
|
85
129
|
DUST_THRESHOLD,
|
|
86
130
|
calcEstimatedProfit,
|
|
87
131
|
calcRepaymentAmount,
|
|
132
|
+
liquidationCallToRawTx,
|
|
88
133
|
pickMainAsset,
|
|
89
|
-
|
|
134
|
+
toLiquidationApproval,
|
|
135
|
+
toLiquidatorWithdrawals,
|
|
136
|
+
toReceivedAssets
|
|
90
137
|
});
|
|
@@ -15,13 +15,13 @@ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "defau
|
|
|
15
15
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
16
16
|
var liquidations_exports = {};
|
|
17
17
|
module.exports = __toCommonJS(liquidations_exports);
|
|
18
|
-
__reExport(liquidations_exports, require("./
|
|
18
|
+
__reExport(liquidations_exports, require("./constants.js"), module.exports);
|
|
19
19
|
__reExport(liquidations_exports, require("./LiquidationsService.js"), module.exports);
|
|
20
20
|
__reExport(liquidations_exports, require("./MultichainLiquidationsService.js"), module.exports);
|
|
21
21
|
__reExport(liquidations_exports, require("./types.js"), module.exports);
|
|
22
22
|
// Annotate the CommonJS export names for ESM import in node:
|
|
23
23
|
0 && (module.exports = {
|
|
24
|
-
...require("./
|
|
24
|
+
...require("./constants.js"),
|
|
25
25
|
...require("./LiquidationsService.js"),
|
|
26
26
|
...require("./MultichainLiquidationsService.js"),
|
|
27
27
|
...require("./types.js")
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
const iLiquidationCompressorV313Abi = [
|
|
2
|
+
{
|
|
3
|
+
type: "function",
|
|
4
|
+
name: "contractType",
|
|
5
|
+
inputs: [],
|
|
6
|
+
outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }],
|
|
7
|
+
stateMutability: "view"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
type: "function",
|
|
11
|
+
name: "getLiquidationData",
|
|
12
|
+
inputs: [
|
|
13
|
+
{ name: "liquidator", type: "address", internalType: "address" },
|
|
14
|
+
{ name: "creditAccount", type: "address", internalType: "address" },
|
|
15
|
+
{
|
|
16
|
+
name: "priceUpdates",
|
|
17
|
+
type: "tuple[]",
|
|
18
|
+
internalType: "struct PriceUpdate[]",
|
|
19
|
+
components: [
|
|
20
|
+
{ name: "priceFeed", type: "address", internalType: "address" },
|
|
21
|
+
{ name: "data", type: "bytes", internalType: "bytes" }
|
|
22
|
+
]
|
|
23
|
+
}
|
|
24
|
+
],
|
|
25
|
+
outputs: [
|
|
26
|
+
{
|
|
27
|
+
name: "",
|
|
28
|
+
type: "tuple",
|
|
29
|
+
internalType: "struct LiquidationData",
|
|
30
|
+
components: [
|
|
31
|
+
{
|
|
32
|
+
name: "requiredUnderlyingAmount",
|
|
33
|
+
type: "uint256",
|
|
34
|
+
internalType: "uint256"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: "expectedOutputs",
|
|
38
|
+
type: "tuple[]",
|
|
39
|
+
internalType: "struct LiquidationOutput[]",
|
|
40
|
+
components: [
|
|
41
|
+
{ name: "token", type: "address", internalType: "address" },
|
|
42
|
+
{ name: "amount", type: "uint256", internalType: "uint256" },
|
|
43
|
+
{ name: "delayed", type: "bool", internalType: "bool" },
|
|
44
|
+
{
|
|
45
|
+
name: "redeemerAddress",
|
|
46
|
+
type: "address",
|
|
47
|
+
internalType: "address"
|
|
48
|
+
},
|
|
49
|
+
{ name: "claimableAt", type: "uint256", internalType: "uint256" }
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: "liquidationCall",
|
|
54
|
+
type: "tuple",
|
|
55
|
+
internalType: "struct MultiCall",
|
|
56
|
+
components: [
|
|
57
|
+
{ name: "target", type: "address", internalType: "address" },
|
|
58
|
+
{ name: "callData", type: "bytes", internalType: "bytes" }
|
|
59
|
+
]
|
|
60
|
+
},
|
|
61
|
+
{ name: "isLiquidatorEligible", type: "bool", internalType: "bool" },
|
|
62
|
+
{ name: "kycProtocol", type: "string", internalType: "string" },
|
|
63
|
+
{ name: "kycToken", type: "address", internalType: "address" }
|
|
64
|
+
]
|
|
65
|
+
}
|
|
66
|
+
],
|
|
67
|
+
stateMutability: "nonpayable"
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
type: "function",
|
|
71
|
+
name: "version",
|
|
72
|
+
inputs: [],
|
|
73
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
74
|
+
stateMutability: "view"
|
|
75
|
+
}
|
|
76
|
+
];
|
|
77
|
+
export {
|
|
78
|
+
iLiquidationCompressorV313Abi
|
|
79
|
+
};
|
|
@@ -1,21 +1,23 @@
|
|
|
1
|
+
import { iLiquidationCompressorV313Abi } from "../../../abi/ILiquidationCompressorV313.js";
|
|
1
2
|
import { SDKConstruct } from "../../base/index.js";
|
|
2
|
-
import { WAD } from "../../constants/index.js";
|
|
3
|
-
import { AddressSet } from "../../utils/index.js";
|
|
3
|
+
import { ADDRESS_0X0, WAD } from "../../constants/index.js";
|
|
4
|
+
import { AddressSet, hexEq } from "../../utils/index.js";
|
|
5
|
+
import { LIQUIDATION_COMPRESSOR_V313_ADDRESS } from "./constants.js";
|
|
4
6
|
import {
|
|
5
7
|
calcEstimatedProfit,
|
|
6
8
|
calcRepaymentAmount,
|
|
7
9
|
DUST_THRESHOLD,
|
|
10
|
+
liquidationCallToRawTx,
|
|
8
11
|
pickMainAsset,
|
|
9
|
-
|
|
12
|
+
toLiquidationApproval,
|
|
13
|
+
toLiquidatorWithdrawals,
|
|
14
|
+
toReceivedAssets
|
|
10
15
|
} from "./helpers.js";
|
|
11
16
|
class LiquidationsService extends SDKConstruct {
|
|
12
17
|
/**
|
|
13
18
|
* {@inheritDoc ILiquidationsService.getLiquidatableAccounts}
|
|
14
19
|
**/
|
|
15
20
|
async getLiquidatableAccounts(props) {
|
|
16
|
-
if (props?.networks && !props.networks.includes(this.sdk.networkType)) {
|
|
17
|
-
return [];
|
|
18
|
-
}
|
|
19
21
|
await this.sdk.withdrawalCompressor?.loadWithdrawableAssets();
|
|
20
22
|
const accounts = await this.sdk.accounts.getCreditAccounts({
|
|
21
23
|
maxHealthFactor: WAD - 1n,
|
|
@@ -50,67 +52,58 @@ class LiquidationsService extends SDKConstruct {
|
|
|
50
52
|
* {@inheritDoc ILiquidationsService.getLiquidationDetails}
|
|
51
53
|
**/
|
|
52
54
|
async getLiquidationDetails(props) {
|
|
53
|
-
const {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
`network mismatch: this SDK is attached to ${this.sdk.networkType}, requested ${network}`
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
const ca = await this.sdk.accounts.getCreditAccountData(creditAccount);
|
|
60
|
-
if (!ca) {
|
|
61
|
-
throw new Error(`credit account ${creditAccount} not found`);
|
|
62
|
-
}
|
|
63
|
-
if (!ca.success) {
|
|
64
|
-
throw new Error(
|
|
65
|
-
`cannot compute liquidation details for ${creditAccount}: collateral computation failed`
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
const compressor = this.sdk.withdrawalCompressor;
|
|
69
|
-
await compressor?.loadWithdrawableAssets();
|
|
55
|
+
const { creditAccount, liquidator, ignoreReservePrices } = props;
|
|
56
|
+
const ca = await this.#getCreditAccountData(creditAccount);
|
|
57
|
+
await this.sdk.withdrawalCompressor?.loadWithdrawableAssets();
|
|
70
58
|
const account = this.#buildAccount(ca);
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
59
|
+
const data = await this.#getLiquidationData(
|
|
60
|
+
ca,
|
|
61
|
+
liquidator,
|
|
62
|
+
ignoreReservePrices
|
|
63
|
+
);
|
|
64
|
+
const suite = this.sdk.marketRegister.findCreditManager(ca.creditManager);
|
|
65
|
+
return {
|
|
66
|
+
...account,
|
|
67
|
+
// the compressor reports the exact amounts of the liquidation path it
|
|
68
|
+
// selected, which supersede the estimates of the list row
|
|
69
|
+
repaymentAmount: {
|
|
70
|
+
token: account.totalValue.token,
|
|
71
|
+
balance: data.requiredUnderlyingAmount
|
|
72
|
+
},
|
|
73
|
+
isDelayed: data.expectedOutputs.some((o) => o.delayed),
|
|
74
|
+
receivedAssets: toReceivedAssets(data.expectedOutputs),
|
|
75
|
+
isLiquidatorEligible: data.isLiquidatorEligible,
|
|
76
|
+
kycProtocol: data.kycProtocol || void 0,
|
|
77
|
+
kycToken: hexEq(data.kycToken, ADDRESS_0X0) ? void 0 : data.kycToken,
|
|
78
|
+
approve: toLiquidationApproval({
|
|
79
|
+
target: data.liquidationCall.target,
|
|
80
|
+
creditFacade: suite.creditFacade.address,
|
|
81
|
+
creditManager: ca.creditManager,
|
|
82
|
+
token: suite.underlying,
|
|
83
|
+
amount: data.requiredUnderlyingAmount
|
|
84
|
+
})
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* {@inheritDoc ILiquidationsService.buildLiquidationTx}
|
|
89
|
+
**/
|
|
90
|
+
async buildLiquidationTx(props) {
|
|
91
|
+
const { creditAccount, liquidator, ignoreReservePrices } = props;
|
|
92
|
+
const ca = await this.#getCreditAccountData(creditAccount);
|
|
93
|
+
const data = await this.#getLiquidationData(
|
|
94
|
+
ca,
|
|
95
|
+
liquidator,
|
|
96
|
+
ignoreReservePrices
|
|
97
|
+
);
|
|
98
|
+
return liquidationCallToRawTx(
|
|
99
|
+
data.liquidationCall,
|
|
100
|
+
`liquidate credit account ${this.labelAddress(creditAccount)} to ${this.labelAddress(liquidator)}`
|
|
101
|
+
);
|
|
106
102
|
}
|
|
107
103
|
/**
|
|
108
104
|
* {@inheritDoc ILiquidationsService.getLiquidatorWithdrawals}
|
|
109
105
|
**/
|
|
110
106
|
async getLiquidatorWithdrawals(props) {
|
|
111
|
-
if (props.networks && !props.networks.includes(this.sdk.networkType)) {
|
|
112
|
-
return [];
|
|
113
|
-
}
|
|
114
107
|
const compressor = this.sdk.withdrawalCompressor;
|
|
115
108
|
if (!compressor) {
|
|
116
109
|
return [];
|
|
@@ -125,6 +118,39 @@ class LiquidationsService extends SDKConstruct {
|
|
|
125
118
|
);
|
|
126
119
|
return toLiquidatorWithdrawals(current, this.sdk.networkType);
|
|
127
120
|
}
|
|
121
|
+
async #getCreditAccountData(creditAccount) {
|
|
122
|
+
const ca = await this.sdk.accounts.getCreditAccountData(creditAccount);
|
|
123
|
+
if (!ca) {
|
|
124
|
+
throw new Error(`credit account ${creditAccount} not found`);
|
|
125
|
+
}
|
|
126
|
+
if (!ca.success) {
|
|
127
|
+
throw new Error(
|
|
128
|
+
`cannot compute liquidation details for ${creditAccount}: collateral computation failed`
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
return ca;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Previews the liquidation via the liquidation compressor.
|
|
135
|
+
*
|
|
136
|
+
* @param ca - Credit account to liquidate
|
|
137
|
+
* @param liquidator - Liquidator wallet, zero address when not known: it only
|
|
138
|
+
* affects the KYC eligibility fields and the receiver encoded into the calls
|
|
139
|
+
* @param ignoreReservePrices - Exclude reserve price feeds from the updates
|
|
140
|
+
**/
|
|
141
|
+
async #getLiquidationData(ca, liquidator = ADDRESS_0X0, ignoreReservePrices) {
|
|
142
|
+
const priceUpdates = await this.sdk.accounts.getOnDemandPriceUpdates(
|
|
143
|
+
ca,
|
|
144
|
+
ignoreReservePrices
|
|
145
|
+
);
|
|
146
|
+
const { result } = await this.client.simulateContract({
|
|
147
|
+
address: LIQUIDATION_COMPRESSOR_V313_ADDRESS,
|
|
148
|
+
abi: iLiquidationCompressorV313Abi,
|
|
149
|
+
functionName: "getLiquidationData",
|
|
150
|
+
args: [liquidator, ca.creditAccount, priceUpdates]
|
|
151
|
+
});
|
|
152
|
+
return result;
|
|
153
|
+
}
|
|
128
154
|
/**
|
|
129
155
|
* Accounts of expired credit managers with outstanding debt are liquidatable
|
|
130
156
|
* regardless of their health factor.
|