@gearbox-protocol/sdk 14.12.0-next.11 → 14.12.0-next.13
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/preview/parse/parseRWAFactoryOperationCalldata.js +13 -12
- package/dist/cjs/preview/parse/types.js +1 -1
- package/dist/cjs/preview/prerequisites/AllowancePrerequisite.js +10 -16
- package/dist/cjs/preview/prerequisites/BalancePrerequisite.js +17 -33
- package/dist/cjs/preview/prerequisites/Prerequisite.js +13 -18
- package/dist/cjs/preview/prerequisites/RWAOpenRequirementsPrerequisite.js +36 -15
- package/dist/cjs/preview/prerequisites/buildCollateralPrerequisites.js +57 -0
- package/dist/cjs/preview/prerequisites/{prepareAction.js → buildPartialLiquidationPrerequisites.js} +18 -24
- package/dist/cjs/preview/prerequisites/buildPoolPrerequisites.js +125 -0
- package/dist/cjs/preview/prerequisites/buildRWAPrerequisites.js +57 -0
- package/dist/cjs/preview/prerequisites/checkPrerequisites.js +85 -0
- package/dist/cjs/preview/prerequisites/helpers.js +47 -0
- package/dist/cjs/preview/prerequisites/index.js +2 -6
- package/dist/cjs/preview/preview/detectCloseOrRepay.js +51 -0
- package/dist/cjs/preview/preview/index.js +4 -0
- package/dist/cjs/preview/preview/previewCloseOrRepay.js +94 -0
- package/dist/cjs/preview/preview/previewOperation.js +10 -2
- package/dist/cjs/sdk/accounts/CreditAccountsServiceV310.js +104 -49
- package/dist/cjs/sdk/market/rwa/securitize/SecuritizeRWAFactory.js +26 -4
- package/dist/cjs/sdk/utils/AddressSet.js +7 -0
- package/dist/esm/preview/parse/parseRWAFactoryOperationCalldata.js +13 -12
- package/dist/esm/preview/parse/types.js +1 -1
- package/dist/esm/preview/prerequisites/AllowancePrerequisite.js +11 -20
- package/dist/esm/preview/prerequisites/BalancePrerequisite.js +18 -37
- package/dist/esm/preview/prerequisites/Prerequisite.js +13 -20
- package/dist/esm/preview/prerequisites/RWAOpenRequirementsPrerequisite.js +36 -15
- package/dist/esm/preview/prerequisites/buildCollateralPrerequisites.js +35 -0
- package/dist/esm/preview/prerequisites/buildPartialLiquidationPrerequisites.js +18 -0
- package/dist/esm/preview/prerequisites/buildPoolPrerequisites.js +101 -0
- package/dist/esm/preview/prerequisites/buildRWAPrerequisites.js +33 -0
- package/dist/esm/preview/prerequisites/checkPrerequisites.js +63 -0
- package/dist/esm/preview/prerequisites/helpers.js +23 -0
- package/dist/esm/preview/prerequisites/index.js +1 -3
- package/dist/esm/preview/preview/detectCloseOrRepay.js +26 -0
- package/dist/esm/preview/preview/index.js +2 -0
- package/dist/esm/preview/preview/previewCloseOrRepay.js +76 -0
- package/dist/esm/preview/preview/previewOperation.js +10 -2
- package/dist/esm/sdk/accounts/CreditAccountsServiceV310.js +104 -49
- package/dist/esm/sdk/market/rwa/securitize/SecuritizeRWAFactory.js +26 -4
- package/dist/esm/sdk/utils/AddressSet.js +7 -0
- package/dist/types/preview/parse/parseRWAFactoryOperationCalldata.d.ts +1 -1
- package/dist/types/preview/parse/types-rwa.d.ts +11 -23
- package/dist/types/preview/prerequisites/AllowancePrerequisite.d.ts +4 -5
- package/dist/types/preview/prerequisites/BalancePrerequisite.d.ts +4 -6
- package/dist/types/preview/prerequisites/Prerequisite.d.ts +16 -40
- package/dist/types/preview/prerequisites/RWAOpenRequirementsPrerequisite.d.ts +22 -16
- package/dist/types/preview/prerequisites/buildCollateralPrerequisites.d.ts +14 -0
- package/dist/types/preview/prerequisites/buildPartialLiquidationPrerequisites.d.ts +8 -0
- package/dist/types/preview/prerequisites/buildPoolPrerequisites.d.ts +8 -0
- package/dist/types/preview/prerequisites/buildRWAPrerequisites.d.ts +21 -0
- package/dist/types/preview/prerequisites/checkPrerequisites.d.ts +27 -0
- package/dist/types/preview/prerequisites/helpers.d.ts +15 -0
- package/dist/types/preview/prerequisites/index.d.ts +1 -3
- package/dist/types/preview/prerequisites/types.d.ts +21 -2
- package/dist/types/preview/preview/detectCloseOrRepay.d.ts +18 -0
- package/dist/types/preview/preview/index.d.ts +2 -0
- package/dist/types/preview/preview/previewAdjustCreditAccount.d.ts +2 -2
- package/dist/types/preview/preview/previewCloseOrRepay.d.ts +10 -0
- package/dist/types/preview/preview/previewOpenCreditAccount.d.ts +2 -2
- package/dist/types/preview/preview/types.d.ts +60 -3
- package/dist/types/sdk/accounts/CreditAccountsServiceV310.d.ts +6 -1
- package/dist/types/sdk/accounts/types.d.ts +66 -3
- package/dist/types/sdk/market/rwa/securitize/SecuritizeRWAFactory.d.ts +11 -3
- package/dist/types/sdk/market/rwa/securitize/types.d.ts +18 -2
- package/dist/types/sdk/market/rwa/types.d.ts +26 -9
- package/dist/types/sdk/utils/AddressSet.d.ts +1 -0
- package/package.json +1 -1
- package/dist/cjs/preview/prerequisites/buildPrerequisites.js +0 -297
- package/dist/cjs/preview/prerequisites/runPrerequisites.js +0 -71
- package/dist/esm/preview/prerequisites/buildPrerequisites.js +0 -279
- package/dist/esm/preview/prerequisites/prepareAction.js +0 -23
- package/dist/esm/preview/prerequisites/runPrerequisites.js +0 -47
- package/dist/types/preview/prerequisites/buildPrerequisites.d.ts +0 -25
- package/dist/types/preview/prerequisites/prepareAction.d.ts +0 -52
- package/dist/types/preview/prerequisites/runPrerequisites.d.ts +0 -12
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import { erc20Abi } from "viem";
|
|
2
|
-
import { iMulticall3Abi } from "../../abi/iMulticall3.js";
|
|
3
2
|
import { hexEq, NATIVE_ADDRESS } from "../../sdk/index.js";
|
|
4
|
-
import {
|
|
5
|
-
Prerequisite,
|
|
6
|
-
toPrerequisiteError
|
|
7
|
-
} from "./Prerequisite.js";
|
|
3
|
+
import { Prerequisite } from "./Prerequisite.js";
|
|
8
4
|
class BalancePrerequisite extends Prerequisite {
|
|
9
5
|
#id;
|
|
10
6
|
#title;
|
|
@@ -31,43 +27,28 @@ class BalancePrerequisite extends Prerequisite {
|
|
|
31
27
|
get detail() {
|
|
32
28
|
return this.#detail;
|
|
33
29
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const multicall3 = ctx.sdk.client.chain.contracts?.multicall3?.address;
|
|
37
|
-
if (!multicall3) {
|
|
38
|
-
throw new Error(
|
|
39
|
-
"multicall3 is not configured for this chain, cannot read native balance"
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
|
-
return [
|
|
43
|
-
{
|
|
44
|
-
address: multicall3,
|
|
45
|
-
abi: iMulticall3Abi,
|
|
46
|
-
functionName: "getEthBalance",
|
|
47
|
-
args: [this.#detail.owner]
|
|
48
|
-
}
|
|
49
|
-
];
|
|
50
|
-
}
|
|
51
|
-
return [
|
|
52
|
-
{
|
|
53
|
-
address: this.#detail.token,
|
|
54
|
-
abi: erc20Abi,
|
|
55
|
-
functionName: "balanceOf",
|
|
56
|
-
args: [this.#detail.owner]
|
|
57
|
-
}
|
|
58
|
-
];
|
|
59
|
-
}
|
|
60
|
-
resolve(slice) {
|
|
61
|
-
const res = slice[0];
|
|
62
|
-
if (!res || res.status === "failure") {
|
|
63
|
-
return this.errorResult(toPrerequisiteError(res?.error));
|
|
64
|
-
}
|
|
65
|
-
const actual = res.result;
|
|
30
|
+
async check(ctx) {
|
|
31
|
+
const actual = await this.#readBalance(ctx);
|
|
66
32
|
return this.satisfiedResult(actual >= this.#detail.required, {
|
|
67
33
|
...this.#detail,
|
|
68
34
|
actual
|
|
69
35
|
});
|
|
70
36
|
}
|
|
37
|
+
async #readBalance(ctx) {
|
|
38
|
+
if (hexEq(this.#detail.token, NATIVE_ADDRESS)) {
|
|
39
|
+
return ctx.sdk.client.getBalance({
|
|
40
|
+
address: this.#detail.owner,
|
|
41
|
+
blockNumber: ctx.blockNumber
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return ctx.sdk.client.readContract({
|
|
45
|
+
address: this.#detail.token,
|
|
46
|
+
abi: erc20Abi,
|
|
47
|
+
functionName: "balanceOf",
|
|
48
|
+
args: [this.#detail.owner],
|
|
49
|
+
blockNumber: ctx.blockNumber
|
|
50
|
+
});
|
|
51
|
+
}
|
|
71
52
|
}
|
|
72
53
|
export {
|
|
73
54
|
BalancePrerequisite
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
BaseError,
|
|
3
|
-
ContractFunctionRevertedError
|
|
4
|
-
} from "viem";
|
|
1
|
+
import { BaseError, ContractFunctionRevertedError } from "viem";
|
|
5
2
|
function toPrerequisiteError(cause) {
|
|
6
3
|
if (cause instanceof BaseError) {
|
|
7
4
|
const reverted = cause.walk(
|
|
@@ -22,19 +19,16 @@ function toPrerequisiteError(cause) {
|
|
|
22
19
|
}
|
|
23
20
|
class Prerequisite {
|
|
24
21
|
/**
|
|
25
|
-
* Verifies this prerequisite
|
|
26
|
-
*
|
|
22
|
+
* Verifies this prerequisite. Never rejects: any error thrown by
|
|
23
|
+
* {@link check} (revert, RPC/network failure, compressor error) is
|
|
24
|
+
* normalized into an `error` result.
|
|
27
25
|
*/
|
|
28
26
|
async verify(ctx) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
// testnet forks pinned to a specific block.
|
|
35
|
-
blockNumber: ctx.blockNumber
|
|
36
|
-
});
|
|
37
|
-
return this.resolve(results);
|
|
27
|
+
try {
|
|
28
|
+
return await this.check(ctx);
|
|
29
|
+
} catch (cause) {
|
|
30
|
+
return this.errorResult(cause);
|
|
31
|
+
}
|
|
38
32
|
}
|
|
39
33
|
/** Builds a successful result; `detail` carries the on-chain `actual`. */
|
|
40
34
|
satisfiedResult(satisfied, detail) {
|
|
@@ -46,18 +40,17 @@ class Prerequisite {
|
|
|
46
40
|
satisfied
|
|
47
41
|
};
|
|
48
42
|
}
|
|
49
|
-
/** Builds a failed result from a
|
|
50
|
-
errorResult(
|
|
43
|
+
/** Builds a failed result from a raw read error (normalized internally). */
|
|
44
|
+
errorResult(cause) {
|
|
51
45
|
return {
|
|
52
46
|
id: this.id,
|
|
53
47
|
kind: this.kind,
|
|
54
48
|
title: this.title,
|
|
55
49
|
detail: this.detail,
|
|
56
|
-
error
|
|
50
|
+
error: toPrerequisiteError(cause)
|
|
57
51
|
};
|
|
58
52
|
}
|
|
59
53
|
}
|
|
60
54
|
export {
|
|
61
|
-
Prerequisite
|
|
62
|
-
toPrerequisiteError
|
|
55
|
+
Prerequisite
|
|
63
56
|
};
|
|
@@ -3,11 +3,17 @@ class RWAOpenRequirementsPrerequisite extends Prerequisite {
|
|
|
3
3
|
#id;
|
|
4
4
|
#title;
|
|
5
5
|
#detail;
|
|
6
|
+
#providedArgs;
|
|
6
7
|
constructor(props) {
|
|
7
8
|
super();
|
|
8
9
|
this.#id = props.id ?? `rwaOpenRequirements:${props.factory}:${props.token}`;
|
|
9
10
|
this.#title = props.title ?? "RWA account requirements fulfilled";
|
|
10
|
-
this.#detail =
|
|
11
|
+
this.#detail = {
|
|
12
|
+
token: props.token,
|
|
13
|
+
creditManager: props.creditManager,
|
|
14
|
+
factory: props.factory
|
|
15
|
+
};
|
|
16
|
+
this.#providedArgs = props.providedArgs;
|
|
11
17
|
}
|
|
12
18
|
get id() {
|
|
13
19
|
return this.#id;
|
|
@@ -21,20 +27,35 @@ class RWAOpenRequirementsPrerequisite extends Prerequisite {
|
|
|
21
27
|
get detail() {
|
|
22
28
|
return this.#detail;
|
|
23
29
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
async check(ctx) {
|
|
31
|
+
const requirements = await ctx.sdk.accounts.getOpenAccountRequirements(
|
|
32
|
+
ctx.wallet,
|
|
33
|
+
this.#detail.creditManager,
|
|
34
|
+
{ tokenOutAddress: this.#detail.token }
|
|
35
|
+
);
|
|
36
|
+
if (!requirements) {
|
|
37
|
+
return this.satisfiedResult(true, this.#detail);
|
|
38
|
+
}
|
|
39
|
+
const { rwaFactory } = ctx.sdk.marketRegister.findByCreditManager(
|
|
40
|
+
this.#detail.creditManager
|
|
41
|
+
);
|
|
42
|
+
if (!rwaFactory) {
|
|
43
|
+
throw new Error(
|
|
44
|
+
`no RWA factory found for credit manager ${this.#detail.creditManager}`
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
const missing = rwaFactory.getMissingRequirements(
|
|
48
|
+
requirements,
|
|
49
|
+
this.#providedArgs
|
|
50
|
+
);
|
|
51
|
+
return this.satisfiedResult(
|
|
52
|
+
!missing && requirements.securitizeTokensToRegister.length === 0,
|
|
53
|
+
{
|
|
54
|
+
...this.#detail,
|
|
55
|
+
requirements,
|
|
56
|
+
missing
|
|
57
|
+
}
|
|
58
|
+
);
|
|
38
59
|
}
|
|
39
60
|
}
|
|
40
61
|
export {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AssetsMap
|
|
3
|
+
} from "../../sdk/index.js";
|
|
4
|
+
import { allowanceAndBalance } from "./helpers.js";
|
|
5
|
+
async function buildCollateralPrerequisites(spenderOptions, multicall, ctx) {
|
|
6
|
+
const { sdk, wallet } = ctx;
|
|
7
|
+
const required = new AssetsMap();
|
|
8
|
+
for (const op of multicall) {
|
|
9
|
+
if (op.operation !== "AddCollateral" || op.amount === 0n) {
|
|
10
|
+
continue;
|
|
11
|
+
}
|
|
12
|
+
required.inc(op.token, op.amount);
|
|
13
|
+
}
|
|
14
|
+
if (required.size === 0) {
|
|
15
|
+
return [];
|
|
16
|
+
}
|
|
17
|
+
const spender = await sdk.accounts.getApprovalAddress(spenderOptions);
|
|
18
|
+
const prereqs = [];
|
|
19
|
+
for (const [token, amount] of required.entries()) {
|
|
20
|
+
prereqs.push(
|
|
21
|
+
...allowanceAndBalance({
|
|
22
|
+
token,
|
|
23
|
+
owner: wallet,
|
|
24
|
+
spender,
|
|
25
|
+
required: amount,
|
|
26
|
+
allowanceTitle: "Collateral approved",
|
|
27
|
+
balanceTitle: "Sufficient collateral balance"
|
|
28
|
+
})
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
return prereqs;
|
|
32
|
+
}
|
|
33
|
+
export {
|
|
34
|
+
buildCollateralPrerequisites
|
|
35
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { allowanceAndBalance } from "./helpers.js";
|
|
2
|
+
function buildPartialLiquidationPrerequisites(tx, ctx) {
|
|
3
|
+
if (tx.repaidAmount === 0n) {
|
|
4
|
+
return [];
|
|
5
|
+
}
|
|
6
|
+
const suite = ctx.sdk.marketRegister.findByCreditManager(tx.creditManager);
|
|
7
|
+
return allowanceAndBalance({
|
|
8
|
+
token: suite.underlying,
|
|
9
|
+
owner: ctx.wallet,
|
|
10
|
+
spender: tx.creditManager,
|
|
11
|
+
required: tx.repaidAmount,
|
|
12
|
+
allowanceTitle: "Underlying approved to credit manager",
|
|
13
|
+
balanceTitle: "Sufficient underlying balance"
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
export {
|
|
17
|
+
buildPartialLiquidationPrerequisites
|
|
18
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { isAddressEqual } from "viem";
|
|
2
|
+
import { NATIVE_ADDRESS } from "../../sdk/index.js";
|
|
3
|
+
import { AllowancePrerequisite } from "./AllowancePrerequisite.js";
|
|
4
|
+
import { BalancePrerequisite } from "./BalancePrerequisite.js";
|
|
5
|
+
import { allowanceAndBalance } from "./helpers.js";
|
|
6
|
+
function buildPoolPrerequisites(tx, wallet) {
|
|
7
|
+
switch (tx.operation) {
|
|
8
|
+
// Deposit and Mint both pull the underlying from the caller into the pool;
|
|
9
|
+
// they only differ in which side (assets vs shares) the caller specifies.
|
|
10
|
+
// The exact underlying amount for Mint is resolved by the pool, so we can
|
|
11
|
+
// only require an allowance/balance against the known specified amount —
|
|
12
|
+
// here we approximate Mint by its shares amount (a lower bound on assets is
|
|
13
|
+
// not knowable from calldata alone).
|
|
14
|
+
case "Deposit":
|
|
15
|
+
if (tx.zapper) {
|
|
16
|
+
if (isAddressEqual(tx.tokenIn, NATIVE_ADDRESS)) {
|
|
17
|
+
return [
|
|
18
|
+
new BalancePrerequisite({
|
|
19
|
+
token: tx.tokenIn,
|
|
20
|
+
owner: wallet,
|
|
21
|
+
required: tx.assets,
|
|
22
|
+
title: "Sufficient token balance"
|
|
23
|
+
})
|
|
24
|
+
];
|
|
25
|
+
}
|
|
26
|
+
return allowanceAndBalance({
|
|
27
|
+
token: tx.tokenIn,
|
|
28
|
+
owner: wallet,
|
|
29
|
+
spender: tx.zapper,
|
|
30
|
+
required: tx.assets,
|
|
31
|
+
allowanceTitle: "Token approved to zapper",
|
|
32
|
+
balanceTitle: "Sufficient token balance"
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return allowanceAndBalance({
|
|
36
|
+
token: tx.underlying,
|
|
37
|
+
owner: wallet,
|
|
38
|
+
spender: tx.pool,
|
|
39
|
+
required: tx.assets,
|
|
40
|
+
allowanceTitle: "Token approved to pool",
|
|
41
|
+
balanceTitle: "Sufficient token balance"
|
|
42
|
+
});
|
|
43
|
+
case "Mint":
|
|
44
|
+
return allowanceAndBalance({
|
|
45
|
+
token: tx.underlying,
|
|
46
|
+
owner: wallet,
|
|
47
|
+
spender: tx.pool,
|
|
48
|
+
required: tx.shares,
|
|
49
|
+
allowanceTitle: "Token approved to pool",
|
|
50
|
+
balanceTitle: "Sufficient token balance"
|
|
51
|
+
});
|
|
52
|
+
// Redeem and Withdraw both burn LP shares from `owner`; they only differ in
|
|
53
|
+
// which side (shares vs assets) the caller specifies.
|
|
54
|
+
case "Redeem":
|
|
55
|
+
if (tx.zapper) {
|
|
56
|
+
return [
|
|
57
|
+
new BalancePrerequisite({
|
|
58
|
+
token: tx.tokenIn,
|
|
59
|
+
owner: wallet,
|
|
60
|
+
required: tx.shares,
|
|
61
|
+
title: "Sufficient share token balance"
|
|
62
|
+
}),
|
|
63
|
+
new AllowancePrerequisite({
|
|
64
|
+
token: tx.tokenIn,
|
|
65
|
+
owner: wallet,
|
|
66
|
+
spender: tx.zapper,
|
|
67
|
+
required: tx.shares,
|
|
68
|
+
title: "Share token approved to zapper"
|
|
69
|
+
})
|
|
70
|
+
];
|
|
71
|
+
}
|
|
72
|
+
return lpSharePrerequisites(tx.pool, tx.owner, tx.shares, wallet);
|
|
73
|
+
case "Withdraw":
|
|
74
|
+
return lpSharePrerequisites(tx.pool, tx.owner, tx.assets, wallet);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function lpSharePrerequisites(pool, owner, required, wallet) {
|
|
78
|
+
const prereqs = [
|
|
79
|
+
new BalancePrerequisite({
|
|
80
|
+
token: pool,
|
|
81
|
+
owner,
|
|
82
|
+
required,
|
|
83
|
+
title: "Sufficient LP token balance"
|
|
84
|
+
})
|
|
85
|
+
];
|
|
86
|
+
if (!isAddressEqual(owner, wallet)) {
|
|
87
|
+
prereqs.push(
|
|
88
|
+
new AllowancePrerequisite({
|
|
89
|
+
token: pool,
|
|
90
|
+
owner,
|
|
91
|
+
spender: wallet,
|
|
92
|
+
required,
|
|
93
|
+
title: "LP token approved to caller"
|
|
94
|
+
})
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
return prereqs;
|
|
98
|
+
}
|
|
99
|
+
export {
|
|
100
|
+
buildPoolPrerequisites
|
|
101
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { AddressSet } from "../../sdk/index.js";
|
|
2
|
+
import { RWAOpenRequirementsPrerequisite } from "./RWAOpenRequirementsPrerequisite.js";
|
|
3
|
+
function buildRWAPrerequisites(multicall, creditManager, providedArgs, ctx) {
|
|
4
|
+
const { rwaFactory } = ctx.sdk.marketRegister.findByCreditManager(creditManager);
|
|
5
|
+
if (!rwaFactory) {
|
|
6
|
+
return [];
|
|
7
|
+
}
|
|
8
|
+
const rwaTokens = new AddressSet(rwaFactory.getTokens());
|
|
9
|
+
const candidates = new AddressSet();
|
|
10
|
+
for (const op of multicall) {
|
|
11
|
+
if (op.operation === "AddCollateral" || op.operation === "UpdateQuota") {
|
|
12
|
+
candidates.add(op.token);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
const prereqs = [];
|
|
16
|
+
for (const token of candidates) {
|
|
17
|
+
if (!rwaTokens.has(token)) {
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
prereqs.push(
|
|
21
|
+
new RWAOpenRequirementsPrerequisite({
|
|
22
|
+
token,
|
|
23
|
+
creditManager,
|
|
24
|
+
factory: rwaFactory.address,
|
|
25
|
+
providedArgs
|
|
26
|
+
})
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
return prereqs;
|
|
30
|
+
}
|
|
31
|
+
export {
|
|
32
|
+
buildRWAPrerequisites
|
|
33
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import {
|
|
2
|
+
parseOperationCalldata
|
|
3
|
+
} from "../parse/parseOperationCalldata.js";
|
|
4
|
+
import { buildCollateralPrerequisites } from "./buildCollateralPrerequisites.js";
|
|
5
|
+
import { buildPartialLiquidationPrerequisites } from "./buildPartialLiquidationPrerequisites.js";
|
|
6
|
+
import { buildPoolPrerequisites } from "./buildPoolPrerequisites.js";
|
|
7
|
+
import { buildRWAPrerequisites } from "./buildRWAPrerequisites.js";
|
|
8
|
+
async function checkPrerequisites(input) {
|
|
9
|
+
const { sdk, sender: wallet, blockNumber } = input;
|
|
10
|
+
const tx = parseOperationCalldata(input);
|
|
11
|
+
const ctx = { sdk, wallet, blockNumber };
|
|
12
|
+
const prereqs = await buildPrerequisites(tx, ctx);
|
|
13
|
+
return Promise.all(
|
|
14
|
+
// Each prereq pairs its own kind with its detail, so the widened
|
|
15
|
+
// `verify` return is safe to narrow back to the discriminated union.
|
|
16
|
+
prereqs.map((p) => p.verify(ctx))
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
async function buildPrerequisites(tx, ctx) {
|
|
20
|
+
const { wallet } = ctx;
|
|
21
|
+
switch (tx.operation) {
|
|
22
|
+
case "Deposit":
|
|
23
|
+
case "Mint":
|
|
24
|
+
case "Redeem":
|
|
25
|
+
case "Withdraw":
|
|
26
|
+
return buildPoolPrerequisites(tx, wallet);
|
|
27
|
+
case "MultiCall":
|
|
28
|
+
case "BotMulticall":
|
|
29
|
+
case "OpenCreditAccount":
|
|
30
|
+
case "CloseCreditAccount":
|
|
31
|
+
case "LiquidateCreditAccount":
|
|
32
|
+
return buildCollateralPrerequisites(
|
|
33
|
+
tx.operation === "OpenCreditAccount" ? { creditManager: tx.creditManager, borrower: wallet } : {
|
|
34
|
+
creditManager: tx.creditManager,
|
|
35
|
+
creditAccount: tx.creditAccount
|
|
36
|
+
},
|
|
37
|
+
tx.multicall,
|
|
38
|
+
ctx
|
|
39
|
+
);
|
|
40
|
+
case "RWAOpenCreditAccount":
|
|
41
|
+
return [
|
|
42
|
+
...await buildCollateralPrerequisites(
|
|
43
|
+
{ creditManager: tx.creditManager, borrower: wallet },
|
|
44
|
+
tx.multicall,
|
|
45
|
+
ctx
|
|
46
|
+
),
|
|
47
|
+
...buildRWAPrerequisites(tx.multicall, tx.creditManager, tx.args, ctx)
|
|
48
|
+
];
|
|
49
|
+
case "RWAMulticall":
|
|
50
|
+
return buildCollateralPrerequisites(
|
|
51
|
+
{ creditManager: tx.creditManager, creditAccount: tx.creditAccount },
|
|
52
|
+
tx.multicall,
|
|
53
|
+
ctx
|
|
54
|
+
);
|
|
55
|
+
case "PartiallyLiquidateCreditAccount":
|
|
56
|
+
return buildPartialLiquidationPrerequisites(tx, ctx);
|
|
57
|
+
default:
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
export {
|
|
62
|
+
checkPrerequisites
|
|
63
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { AllowancePrerequisite } from "./AllowancePrerequisite.js";
|
|
2
|
+
import { BalancePrerequisite } from "./BalancePrerequisite.js";
|
|
3
|
+
function allowanceAndBalance(props) {
|
|
4
|
+
const { token, owner, spender, required } = props;
|
|
5
|
+
return [
|
|
6
|
+
new AllowancePrerequisite({
|
|
7
|
+
token,
|
|
8
|
+
owner,
|
|
9
|
+
spender,
|
|
10
|
+
required,
|
|
11
|
+
title: props.allowanceTitle
|
|
12
|
+
}),
|
|
13
|
+
new BalancePrerequisite({
|
|
14
|
+
token,
|
|
15
|
+
owner,
|
|
16
|
+
required,
|
|
17
|
+
title: props.balanceTitle
|
|
18
|
+
})
|
|
19
|
+
];
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
allowanceAndBalance
|
|
23
|
+
};
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
export * from "./AllowancePrerequisite.js";
|
|
2
2
|
export * from "./BalancePrerequisite.js";
|
|
3
|
-
export * from "./
|
|
3
|
+
export * from "./checkPrerequisites.js";
|
|
4
4
|
export * from "./Prerequisite.js";
|
|
5
|
-
export * from "./prepareAction.js";
|
|
6
5
|
export * from "./RWAOpenRequirementsPrerequisite.js";
|
|
7
|
-
export * from "./runPrerequisites.js";
|
|
8
6
|
export * from "./types.js";
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { isAddressEqual } from "viem";
|
|
2
|
+
import { MAX_UINT256 } from "../../sdk/index.js";
|
|
3
|
+
function isCloseOrRepay(multicall) {
|
|
4
|
+
const repaysFullDebt = multicall.some(
|
|
5
|
+
(op) => op.operation === "DecreaseBorrowedAmount" && op.amount === MAX_UINT256
|
|
6
|
+
);
|
|
7
|
+
const withdrawsEverything = multicall.some(
|
|
8
|
+
(op) => op.operation === "WithdrawCollateral" && op.amount === MAX_UINT256
|
|
9
|
+
);
|
|
10
|
+
return repaysFullDebt && withdrawsEverything;
|
|
11
|
+
}
|
|
12
|
+
function classifyCloseOrRepay(multicall, underlying) {
|
|
13
|
+
for (const op of multicall) {
|
|
14
|
+
if (op.operation === "AddCollateral") {
|
|
15
|
+
return "repay";
|
|
16
|
+
}
|
|
17
|
+
if (op.operation === "WithdrawCollateral" && !isAddressEqual(op.token, underlying)) {
|
|
18
|
+
return "repay";
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return "close";
|
|
22
|
+
}
|
|
23
|
+
export {
|
|
24
|
+
classifyCloseOrRepay,
|
|
25
|
+
isCloseOrRepay
|
|
26
|
+
};
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export * from "./applyInnerOperations.js";
|
|
2
|
+
export * from "./detectCloseOrRepay.js";
|
|
2
3
|
export * from "./errors.js";
|
|
3
4
|
export * from "./previewAdjustCreditAccount.js";
|
|
5
|
+
export * from "./previewCloseOrRepay.js";
|
|
4
6
|
export * from "./previewOperation.js";
|
|
5
7
|
export * from "./types.js";
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AP_WETH_TOKEN,
|
|
3
|
+
NO_VERSION
|
|
4
|
+
} from "../../sdk/index.js";
|
|
5
|
+
import {
|
|
6
|
+
applyInnerOperations,
|
|
7
|
+
makeInnerOperationsState
|
|
8
|
+
} from "./applyInnerOperations.js";
|
|
9
|
+
import { classifyCloseOrRepay } from "./detectCloseOrRepay.js";
|
|
10
|
+
import { unwrapNativeCollateral } from "./unwrapNativeCollateral.js";
|
|
11
|
+
async function previewCloseOrRepay(input, operation, permanent, options) {
|
|
12
|
+
const { sdk } = input;
|
|
13
|
+
const market = sdk.marketRegister.findByCreditManager(
|
|
14
|
+
operation.creditManager
|
|
15
|
+
);
|
|
16
|
+
const kind = classifyCloseOrRepay(operation.multicall, market.underlying);
|
|
17
|
+
return kind === "close" ? previewCloseCreditAccount(input, operation, permanent, options) : previewRepayCreditAccount(input, operation, permanent, options);
|
|
18
|
+
}
|
|
19
|
+
async function previewCloseCreditAccount(input, operation, permanent, options) {
|
|
20
|
+
const { sdk } = input;
|
|
21
|
+
const market = sdk.marketRegister.findByCreditManager(
|
|
22
|
+
operation.creditManager
|
|
23
|
+
);
|
|
24
|
+
const { state } = await replayMulticall(sdk, operation, options);
|
|
25
|
+
return {
|
|
26
|
+
operation: "CloseCreditAccount",
|
|
27
|
+
permanent,
|
|
28
|
+
creditManager: operation.creditManager,
|
|
29
|
+
creditAccount: operation.creditAccount,
|
|
30
|
+
receivedAmount: state.collateralWithdrawn.getOrZero(market.underlying)
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
async function previewRepayCreditAccount(input, operation, permanent, options) {
|
|
34
|
+
const { sdk, value = 0n } = input;
|
|
35
|
+
const { ca, state } = await replayMulticall(sdk, operation, options);
|
|
36
|
+
const collateralAdded = unwrapNativeCollateral(
|
|
37
|
+
state.collateralAdded.toAssets(),
|
|
38
|
+
value,
|
|
39
|
+
sdk.addressProvider.getAddress(AP_WETH_TOKEN, NO_VERSION)
|
|
40
|
+
);
|
|
41
|
+
const initialTotalDebt = ca.debt + ca.accruedInterest + ca.accruedFees;
|
|
42
|
+
return {
|
|
43
|
+
operation: "RepayCreditAccount",
|
|
44
|
+
permanent,
|
|
45
|
+
creditManager: operation.creditManager,
|
|
46
|
+
creditAccount: operation.creditAccount,
|
|
47
|
+
collateralAdded,
|
|
48
|
+
debtRepaid: initialTotalDebt - state.totalDebt,
|
|
49
|
+
collateralWithdrawn: state.collateralWithdrawn.toAssets()
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
async function replayMulticall(sdk, operation, options) {
|
|
53
|
+
let ca = options?.creditAccount;
|
|
54
|
+
if (!ca) {
|
|
55
|
+
ca = await sdk.accounts.getCreditAccountData(
|
|
56
|
+
operation.creditAccount,
|
|
57
|
+
options?.blockNumber
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
if (!ca) {
|
|
61
|
+
throw new Error(`credit account ${operation.creditAccount} not found`);
|
|
62
|
+
}
|
|
63
|
+
const state = makeInnerOperationsState();
|
|
64
|
+
for (const t of ca.tokens) {
|
|
65
|
+
if (t.balance > 1n) {
|
|
66
|
+
state.balances.upsert(t.token, t.balance);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
state.debt = ca.debt;
|
|
70
|
+
state.totalDebt = ca.debt + ca.accruedInterest + ca.accruedFees;
|
|
71
|
+
applyInnerOperations(sdk, operation.multicall, state);
|
|
72
|
+
return { ca, state };
|
|
73
|
+
}
|
|
74
|
+
export {
|
|
75
|
+
previewCloseOrRepay
|
|
76
|
+
};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { isPoolOperation, parseOperationCalldata } from "../parse/index.js";
|
|
2
|
+
import { isCloseOrRepay } from "./detectCloseOrRepay.js";
|
|
2
3
|
import { UnsupportedOperationError } from "./errors.js";
|
|
3
4
|
import { previewAdjustCreditAccount } from "./previewAdjustCreditAccount.js";
|
|
5
|
+
import { previewCloseOrRepay } from "./previewCloseOrRepay.js";
|
|
4
6
|
import { previewOpenCreditAccount } from "./previewOpenCreditAccount.js";
|
|
5
7
|
import { previewPoolOperation } from "./previewPoolOperation.js";
|
|
6
8
|
async function previewOperation(input, options) {
|
|
@@ -8,10 +10,16 @@ async function previewOperation(input, options) {
|
|
|
8
10
|
if (isPoolOperation(operation)) {
|
|
9
11
|
return previewPoolOperation(input, operation, options);
|
|
10
12
|
}
|
|
11
|
-
if (operation.operation === "OpenCreditAccount" || operation.operation === "
|
|
13
|
+
if (operation.operation === "OpenCreditAccount" || operation.operation === "RWAOpenCreditAccount") {
|
|
12
14
|
return previewOpenCreditAccount(input, operation);
|
|
13
15
|
}
|
|
14
|
-
if (operation.operation === "
|
|
16
|
+
if (operation.operation === "CloseCreditAccount") {
|
|
17
|
+
return previewCloseOrRepay(input, operation, true, options);
|
|
18
|
+
}
|
|
19
|
+
if (operation.operation === "MultiCall" || operation.operation === "BotMulticall" || operation.operation === "RWAMulticall") {
|
|
20
|
+
if (isCloseOrRepay(operation.multicall)) {
|
|
21
|
+
return previewCloseOrRepay(input, operation, false, options);
|
|
22
|
+
}
|
|
15
23
|
return previewAdjustCreditAccount(input, operation, options);
|
|
16
24
|
}
|
|
17
25
|
throw new UnsupportedOperationError(operation.operation);
|