@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.
Files changed (75) hide show
  1. package/dist/cjs/preview/parse/parseRWAFactoryOperationCalldata.js +13 -12
  2. package/dist/cjs/preview/parse/types.js +1 -1
  3. package/dist/cjs/preview/prerequisites/AllowancePrerequisite.js +10 -16
  4. package/dist/cjs/preview/prerequisites/BalancePrerequisite.js +17 -33
  5. package/dist/cjs/preview/prerequisites/Prerequisite.js +13 -18
  6. package/dist/cjs/preview/prerequisites/RWAOpenRequirementsPrerequisite.js +36 -15
  7. package/dist/cjs/preview/prerequisites/buildCollateralPrerequisites.js +57 -0
  8. package/dist/cjs/preview/prerequisites/{prepareAction.js → buildPartialLiquidationPrerequisites.js} +18 -24
  9. package/dist/cjs/preview/prerequisites/buildPoolPrerequisites.js +125 -0
  10. package/dist/cjs/preview/prerequisites/buildRWAPrerequisites.js +57 -0
  11. package/dist/cjs/preview/prerequisites/checkPrerequisites.js +85 -0
  12. package/dist/cjs/preview/prerequisites/helpers.js +47 -0
  13. package/dist/cjs/preview/prerequisites/index.js +2 -6
  14. package/dist/cjs/preview/preview/detectCloseOrRepay.js +51 -0
  15. package/dist/cjs/preview/preview/index.js +4 -0
  16. package/dist/cjs/preview/preview/previewCloseOrRepay.js +94 -0
  17. package/dist/cjs/preview/preview/previewOperation.js +10 -2
  18. package/dist/cjs/sdk/accounts/CreditAccountsServiceV310.js +104 -49
  19. package/dist/cjs/sdk/market/rwa/securitize/SecuritizeRWAFactory.js +26 -4
  20. package/dist/cjs/sdk/utils/AddressSet.js +7 -0
  21. package/dist/esm/preview/parse/parseRWAFactoryOperationCalldata.js +13 -12
  22. package/dist/esm/preview/parse/types.js +1 -1
  23. package/dist/esm/preview/prerequisites/AllowancePrerequisite.js +11 -20
  24. package/dist/esm/preview/prerequisites/BalancePrerequisite.js +18 -37
  25. package/dist/esm/preview/prerequisites/Prerequisite.js +13 -20
  26. package/dist/esm/preview/prerequisites/RWAOpenRequirementsPrerequisite.js +36 -15
  27. package/dist/esm/preview/prerequisites/buildCollateralPrerequisites.js +35 -0
  28. package/dist/esm/preview/prerequisites/buildPartialLiquidationPrerequisites.js +18 -0
  29. package/dist/esm/preview/prerequisites/buildPoolPrerequisites.js +101 -0
  30. package/dist/esm/preview/prerequisites/buildRWAPrerequisites.js +33 -0
  31. package/dist/esm/preview/prerequisites/checkPrerequisites.js +63 -0
  32. package/dist/esm/preview/prerequisites/helpers.js +23 -0
  33. package/dist/esm/preview/prerequisites/index.js +1 -3
  34. package/dist/esm/preview/preview/detectCloseOrRepay.js +26 -0
  35. package/dist/esm/preview/preview/index.js +2 -0
  36. package/dist/esm/preview/preview/previewCloseOrRepay.js +76 -0
  37. package/dist/esm/preview/preview/previewOperation.js +10 -2
  38. package/dist/esm/sdk/accounts/CreditAccountsServiceV310.js +104 -49
  39. package/dist/esm/sdk/market/rwa/securitize/SecuritizeRWAFactory.js +26 -4
  40. package/dist/esm/sdk/utils/AddressSet.js +7 -0
  41. package/dist/types/preview/parse/parseRWAFactoryOperationCalldata.d.ts +1 -1
  42. package/dist/types/preview/parse/types-rwa.d.ts +11 -23
  43. package/dist/types/preview/prerequisites/AllowancePrerequisite.d.ts +4 -5
  44. package/dist/types/preview/prerequisites/BalancePrerequisite.d.ts +4 -6
  45. package/dist/types/preview/prerequisites/Prerequisite.d.ts +16 -40
  46. package/dist/types/preview/prerequisites/RWAOpenRequirementsPrerequisite.d.ts +22 -16
  47. package/dist/types/preview/prerequisites/buildCollateralPrerequisites.d.ts +14 -0
  48. package/dist/types/preview/prerequisites/buildPartialLiquidationPrerequisites.d.ts +8 -0
  49. package/dist/types/preview/prerequisites/buildPoolPrerequisites.d.ts +8 -0
  50. package/dist/types/preview/prerequisites/buildRWAPrerequisites.d.ts +21 -0
  51. package/dist/types/preview/prerequisites/checkPrerequisites.d.ts +27 -0
  52. package/dist/types/preview/prerequisites/helpers.d.ts +15 -0
  53. package/dist/types/preview/prerequisites/index.d.ts +1 -3
  54. package/dist/types/preview/prerequisites/types.d.ts +21 -2
  55. package/dist/types/preview/preview/detectCloseOrRepay.d.ts +18 -0
  56. package/dist/types/preview/preview/index.d.ts +2 -0
  57. package/dist/types/preview/preview/previewAdjustCreditAccount.d.ts +2 -2
  58. package/dist/types/preview/preview/previewCloseOrRepay.d.ts +10 -0
  59. package/dist/types/preview/preview/previewOpenCreditAccount.d.ts +2 -2
  60. package/dist/types/preview/preview/types.d.ts +60 -3
  61. package/dist/types/sdk/accounts/CreditAccountsServiceV310.d.ts +6 -1
  62. package/dist/types/sdk/accounts/types.d.ts +66 -3
  63. package/dist/types/sdk/market/rwa/securitize/SecuritizeRWAFactory.d.ts +11 -3
  64. package/dist/types/sdk/market/rwa/securitize/types.d.ts +18 -2
  65. package/dist/types/sdk/market/rwa/types.d.ts +26 -9
  66. package/dist/types/sdk/utils/AddressSet.d.ts +1 -0
  67. package/package.json +1 -1
  68. package/dist/cjs/preview/prerequisites/buildPrerequisites.js +0 -297
  69. package/dist/cjs/preview/prerequisites/runPrerequisites.js +0 -71
  70. package/dist/esm/preview/prerequisites/buildPrerequisites.js +0 -279
  71. package/dist/esm/preview/prerequisites/prepareAction.js +0 -23
  72. package/dist/esm/preview/prerequisites/runPrerequisites.js +0 -47
  73. package/dist/types/preview/prerequisites/buildPrerequisites.d.ts +0 -25
  74. package/dist/types/preview/prerequisites/prepareAction.d.ts +0 -52
  75. 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
- calls(ctx) {
35
- if (hexEq(this.#detail.token, NATIVE_ADDRESS)) {
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 on its own using an `allowFailure` multicall.
26
- * Prefer `verifyPrerequisites` to batch several checks into one round-trip.
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
- const calls = this.calls(ctx);
30
- const results = await ctx.sdk.client.multicall({
31
- allowFailure: true,
32
- contracts: calls,
33
- // `undefined` lets viem read at `latest`; `blockNumber` is only set for
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 decoded read error. */
50
- errorResult(error) {
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 = props.requirements;
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
- /** Pre-resolved: no on-chain reads to contribute. */
25
- calls() {
26
- return [];
27
- }
28
- resolve() {
29
- return this.satisfiedResult(this.#satisfied(), this.#detail);
30
- }
31
- /**
32
- * Satisfied when the borrower has nothing left to do: no tokens pending
33
- * issuer-side registration and no messages left to sign.
34
- */
35
- #satisfied() {
36
- const { securitizeTokensToRegister, requiredSignatures } = this.#detail;
37
- return securitizeTokensToRegister.length === 0 && requiredSignatures.length === 0;
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 "./buildPrerequisites.js";
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 === "SecuritizeOpenCreditAccount") {
13
+ if (operation.operation === "OpenCreditAccount" || operation.operation === "RWAOpenCreditAccount") {
12
14
  return previewOpenCreditAccount(input, operation);
13
15
  }
14
- if (operation.operation === "MultiCall" || operation.operation === "BotMulticall" || operation.operation === "SecuritizeMulticall") {
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);