@gearbox-protocol/sdk 14.12.0-next.12 → 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/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/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/types.d.ts +3 -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
|
@@ -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);
|
|
@@ -170,8 +170,8 @@ class SecuritizeRWAFactory extends BaseContract {
|
|
|
170
170
|
/**
|
|
171
171
|
* {@inheritDoc IRWAFactory.multicall}
|
|
172
172
|
*/
|
|
173
|
-
multicall(creditAccount, calls,
|
|
174
|
-
const { tokensToRegister = [], signaturesToCache = [] } =
|
|
173
|
+
multicall(creditAccount, calls, args) {
|
|
174
|
+
const { tokensToRegister = [], signaturesToCache = [] } = args ?? {};
|
|
175
175
|
return this.createRawTx({
|
|
176
176
|
functionName: "multicall",
|
|
177
177
|
args: [creditAccount, calls, tokensToRegister, signaturesToCache]
|
|
@@ -201,11 +201,33 @@ class SecuritizeRWAFactory extends BaseContract {
|
|
|
201
201
|
requiredSignatures
|
|
202
202
|
};
|
|
203
203
|
}
|
|
204
|
+
/**
|
|
205
|
+
* {@inheritDoc IRWAFactory.getMissingRequirements}
|
|
206
|
+
*
|
|
207
|
+
* A required signature is omitted when `providedArgs.signaturesToCache`
|
|
208
|
+
* already carries a signature for the same token: the transaction caches it
|
|
209
|
+
* on-chain as part of the operation.
|
|
210
|
+
*/
|
|
211
|
+
getMissingRequirements(requirements, providedArgs) {
|
|
212
|
+
const providedTokens = new AddressSet(
|
|
213
|
+
(providedArgs?.signaturesToCache ?? []).map((s) => s.token)
|
|
214
|
+
);
|
|
215
|
+
const requiredSignatures = requirements.requiredSignatures.filter(
|
|
216
|
+
(message) => !providedTokens.has(message.message.token)
|
|
217
|
+
);
|
|
218
|
+
if (requiredSignatures.length === 0) {
|
|
219
|
+
return void 0;
|
|
220
|
+
}
|
|
221
|
+
return {
|
|
222
|
+
type: RWA_FACTORY_SECURITIZE,
|
|
223
|
+
requiredSignatures
|
|
224
|
+
};
|
|
225
|
+
}
|
|
204
226
|
/**
|
|
205
227
|
* {@inheritDoc IRWAFactory.openCreditAccount}
|
|
206
228
|
*/
|
|
207
|
-
openCreditAccount(creditManager, calls,
|
|
208
|
-
const { tokensToRegister = [], signaturesToCache = [] } =
|
|
229
|
+
openCreditAccount(creditManager, calls, args) {
|
|
230
|
+
const { tokensToRegister = [], signaturesToCache = [] } = args ?? {};
|
|
209
231
|
return this.createRawTx({
|
|
210
232
|
functionName: "openCreditAccount",
|
|
211
233
|
args: [creditManager, calls, tokensToRegister, signaturesToCache]
|
|
@@ -15,6 +15,13 @@ class AddressSet extends Set {
|
|
|
15
15
|
has(value) {
|
|
16
16
|
return super.has(getAddress(value));
|
|
17
17
|
}
|
|
18
|
+
difference(other) {
|
|
19
|
+
const result = new AddressSet(this.keys());
|
|
20
|
+
for (const key of other) {
|
|
21
|
+
result.delete(getAddress(key));
|
|
22
|
+
}
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
18
25
|
/**
|
|
19
26
|
* Returns all addresses as an array.
|
|
20
27
|
**/
|
|
@@ -17,6 +17,6 @@ export interface ParseRWAFactoryOperationCalldataProps {
|
|
|
17
17
|
* identical to {@link parseFacadeOperationCalldata}.
|
|
18
18
|
*
|
|
19
19
|
* Dispatches on the factory's contract type; supporting a new factory type
|
|
20
|
-
* requires a new branch here
|
|
20
|
+
* requires a new branch here.
|
|
21
21
|
*/
|
|
22
22
|
export declare function parseRWAFactoryOperationCalldata(props: ParseRWAFactoryOperationCalldataProps): RWAOperation;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Address } from "viem";
|
|
2
|
-
import type {
|
|
2
|
+
import type { RWAOperationArgs } from "../../sdk/index.js";
|
|
3
3
|
import type { InnerOperation } from "./types-facades.js";
|
|
4
4
|
/**
|
|
5
5
|
* Metadata shared by all RWA factory operations. RWA credit accounts are
|
|
@@ -13,36 +13,24 @@ export interface RWAOperationMetadata {
|
|
|
13
13
|
creditManager: Address;
|
|
14
14
|
creditFacade: Address;
|
|
15
15
|
}
|
|
16
|
-
export interface
|
|
17
|
-
operation: "
|
|
16
|
+
export interface RWAOpenCreditAccountOperation<Ext extends object = {}> extends RWAOperationMetadata {
|
|
17
|
+
operation: "RWAOpenCreditAccount";
|
|
18
18
|
multicall: InnerOperation<Ext>[];
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* requirements.
|
|
20
|
+
* Factory-specific registration args decoded from calldata (for
|
|
21
|
+
* Securitize: `tokensToRegister`/`signaturesToCache`).
|
|
23
22
|
*/
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* EIP-712 registration signatures to store on-chain, decoded from calldata.
|
|
27
|
-
* Empty in the template flow.
|
|
28
|
-
*/
|
|
29
|
-
signaturesToCache: SecuritizeRegisterMessage[];
|
|
23
|
+
args: RWAOperationArgs;
|
|
30
24
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
* the factory-specific registration args.
|
|
34
|
-
*/
|
|
35
|
-
export interface SecuritizeMulticallOperation<Ext extends object = {}> extends RWAOperationMetadata {
|
|
36
|
-
operation: "SecuritizeMulticall";
|
|
25
|
+
export interface RWAMulticallOperation<Ext extends object = {}> extends RWAOperationMetadata {
|
|
26
|
+
operation: "RWAMulticall";
|
|
37
27
|
creditAccount: Address;
|
|
38
28
|
multicall: InnerOperation<Ext>[];
|
|
39
|
-
/**
|
|
40
|
-
|
|
41
|
-
/** EIP-712 registration signatures to store on-chain, decoded from calldata. */
|
|
42
|
-
signaturesToCache: SecuritizeRegisterMessage[];
|
|
29
|
+
/** Factory-specific registration args decoded from calldata. */
|
|
30
|
+
args: RWAOperationArgs;
|
|
43
31
|
}
|
|
44
32
|
/**
|
|
45
33
|
* Discriminated union of all RWA factory operation types. Extend it when
|
|
46
34
|
* adding support for a new RWA factory type.
|
|
47
35
|
*/
|
|
48
|
-
export type RWAOperation<Ext extends object = {}> =
|
|
36
|
+
export type RWAOperation<Ext extends object = {}> = RWAOpenCreditAccountOperation<Ext> | RWAMulticallOperation<Ext>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { type Address
|
|
2
|
-
import {
|
|
3
|
-
import type { PrerequisiteDetail, PrerequisiteResult } from "./types.js";
|
|
1
|
+
import { type Address } from "viem";
|
|
2
|
+
import { Prerequisite } from "./Prerequisite.js";
|
|
3
|
+
import type { PrerequisiteContext, PrerequisiteDetail, PrerequisiteResult } from "./types.js";
|
|
4
4
|
export interface AllowancePrerequisiteProps {
|
|
5
5
|
token: Address;
|
|
6
6
|
owner: Address;
|
|
@@ -17,6 +17,5 @@ export declare class AllowancePrerequisite extends Prerequisite<"allowance"> {
|
|
|
17
17
|
get kind(): "allowance";
|
|
18
18
|
get title(): string;
|
|
19
19
|
get detail(): PrerequisiteDetail<"allowance">;
|
|
20
|
-
|
|
21
|
-
resolve(slice: MulticallCallResult[]): PrerequisiteResult<"allowance">;
|
|
20
|
+
protected check(ctx: PrerequisiteContext): Promise<PrerequisiteResult<"allowance">>;
|
|
22
21
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type Address
|
|
2
|
-
import {
|
|
1
|
+
import { type Address } from "viem";
|
|
2
|
+
import { Prerequisite } from "./Prerequisite.js";
|
|
3
3
|
import type { PrerequisiteContext, PrerequisiteDetail, PrerequisiteResult } from "./types.js";
|
|
4
4
|
export interface BalancePrerequisiteProps {
|
|
5
5
|
token: Address;
|
|
@@ -11,8 +11,7 @@ export interface BalancePrerequisiteProps {
|
|
|
11
11
|
/**
|
|
12
12
|
* Checks that `owner` holds a token balance >= `required`. The token is read
|
|
13
13
|
* as an ERC-20, except for the native pseudo-address ({@link NATIVE_ADDRESS},
|
|
14
|
-
* e.g. ETH-zapper deposits) whose balance is read via
|
|
15
|
-
* `getEthBalance`.
|
|
14
|
+
* e.g. ETH-zapper deposits) whose balance is read via `getBalance`.
|
|
16
15
|
*/
|
|
17
16
|
export declare class BalancePrerequisite extends Prerequisite<"balance"> {
|
|
18
17
|
#private;
|
|
@@ -21,6 +20,5 @@ export declare class BalancePrerequisite extends Prerequisite<"balance"> {
|
|
|
21
20
|
get kind(): "balance";
|
|
22
21
|
get title(): string;
|
|
23
22
|
get detail(): PrerequisiteDetail<"balance">;
|
|
24
|
-
|
|
25
|
-
resolve(slice: MulticallCallResult[]): PrerequisiteResult<"balance">;
|
|
23
|
+
protected check(ctx: PrerequisiteContext): Promise<PrerequisiteResult<"balance">>;
|
|
26
24
|
}
|
|
@@ -1,37 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { PrerequisiteContext, PrerequisiteDetail, PrerequisiteError, PrerequisiteKind, PrerequisiteResult } from "./types.js";
|
|
1
|
+
import type { PrerequisiteContext, PrerequisiteDetail, PrerequisiteKind, PrerequisiteResult } from "./types.js";
|
|
3
2
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
status: "success";
|
|
9
|
-
result: unknown;
|
|
10
|
-
error?: undefined;
|
|
11
|
-
} | {
|
|
12
|
-
status: "failure";
|
|
13
|
-
result?: undefined;
|
|
14
|
-
error: Error;
|
|
15
|
-
};
|
|
16
|
-
/**
|
|
17
|
-
* Decodes an unknown error into a {@link PrerequisiteError} with a
|
|
18
|
-
* human-readable revert reason. Mirrors the SDK's `extractCallError`: walk the
|
|
19
|
-
* viem error chain for a {@link ContractFunctionRevertedError} and use its
|
|
20
|
-
* `errorName`, otherwise fall back to the error's short message / name.
|
|
21
|
-
*/
|
|
22
|
-
export declare function toPrerequisiteError(cause: unknown): PrerequisiteError;
|
|
23
|
-
/**
|
|
24
|
-
* A single verifiable prerequisite for a transaction. Subclasses describe the
|
|
25
|
-
* on-chain reads they need ({@link calls}) and how to turn the multicall slice
|
|
26
|
-
* into a {@link PrerequisiteResult} ({@link resolve}).
|
|
3
|
+
* A single verifiable prerequisite for a transaction. Subclasses implement
|
|
4
|
+
* {@link check} to perform whatever async reads they need (an ERC-20
|
|
5
|
+
* `readContract`, a compressor call, ...) and map the outcome into a
|
|
6
|
+
* {@link PrerequisiteResult}.
|
|
27
7
|
*
|
|
28
|
-
* Identity (`id`, `kind`, `title`) and build-time `detail` are exposed as
|
|
29
|
-
* read-only accessors; subclasses back them with private fields. The shared
|
|
30
|
-
* {@link satisfiedResult}/{@link errorResult} helpers are `protected` so each
|
|
31
|
-
* subclass builds results consistently.
|
|
32
|
-
*
|
|
33
|
-
* The same instance can be verified standalone via {@link verify} or batched
|
|
34
|
-
* together with others by `verifyPrerequisites`.
|
|
35
8
|
*/
|
|
36
9
|
export declare abstract class Prerequisite<K extends PrerequisiteKind> {
|
|
37
10
|
/** Stable identifier, used as a React key and for deduplication. */
|
|
@@ -42,19 +15,22 @@ export declare abstract class Prerequisite<K extends PrerequisiteKind> {
|
|
|
42
15
|
abstract get title(): string;
|
|
43
16
|
/** Inputs known before reading the chain (no `actual` yet). */
|
|
44
17
|
abstract get detail(): PrerequisiteDetail<K>;
|
|
45
|
-
/** Contract reads this check needs (usually one). */
|
|
46
|
-
abstract calls(ctx: PrerequisiteContext): ContractFunctionParameters[];
|
|
47
|
-
/** Maps this check's slice of the multicall response into a result. */
|
|
48
|
-
abstract resolve(slice: MulticallCallResult[]): PrerequisiteResult<K>;
|
|
49
18
|
/**
|
|
50
|
-
* Verifies this prerequisite
|
|
51
|
-
*
|
|
19
|
+
* Verifies this prerequisite. Never rejects: any error thrown by
|
|
20
|
+
* {@link check} (revert, RPC/network failure, compressor error) is
|
|
21
|
+
* normalized into an `error` result.
|
|
52
22
|
*/
|
|
53
23
|
verify(ctx: PrerequisiteContext): Promise<PrerequisiteResult<K>>;
|
|
24
|
+
/**
|
|
25
|
+
* Performs the reads this prerequisite needs and maps them into a result.
|
|
26
|
+
* May throw on read failure; {@link verify} converts throws into `error`
|
|
27
|
+
* results.
|
|
28
|
+
*/
|
|
29
|
+
protected abstract check(ctx: PrerequisiteContext): Promise<PrerequisiteResult<K>>;
|
|
54
30
|
/** Builds a successful result; `detail` carries the on-chain `actual`. */
|
|
55
31
|
protected satisfiedResult(satisfied: boolean, detail: PrerequisiteDetail<K>): PrerequisiteResult<K>;
|
|
56
|
-
/** Builds a failed result from a
|
|
57
|
-
protected errorResult(
|
|
32
|
+
/** Builds a failed result from a raw read error (normalized internally). */
|
|
33
|
+
protected errorResult(cause: unknown): PrerequisiteResult<K>;
|
|
58
34
|
}
|
|
59
35
|
/** Any prerequisite regardless of its kind, used for heterogeneous lists. */
|
|
60
36
|
export type AnyPrerequisite = Prerequisite<PrerequisiteKind>;
|