@gearbox-protocol/sdk 14.10.6 → 14.11.0-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/dist/cjs/abi/errors.js +42 -2
  2. package/dist/cjs/preview/index.js +26 -0
  3. package/dist/cjs/preview/package.json +1 -0
  4. package/dist/cjs/preview/parse/classifyInnerOperations.js +130 -0
  5. package/dist/cjs/preview/parse/errors.js +47 -0
  6. package/dist/cjs/preview/parse/index.js +32 -0
  7. package/dist/cjs/preview/parse/parseCreditFacadeOperation.js +111 -0
  8. package/dist/cjs/preview/parse/parsePoolOperation.js +62 -0
  9. package/dist/cjs/preview/parse/parseTransaction.js +46 -0
  10. package/dist/cjs/preview/parse/types.js +30 -0
  11. package/dist/cjs/preview/prerequisites/AllowancePrerequisite.js +78 -0
  12. package/dist/cjs/preview/prerequisites/BalancePrerequisite.js +77 -0
  13. package/dist/cjs/preview/prerequisites/Prerequisite.js +85 -0
  14. package/dist/cjs/preview/prerequisites/buildPrerequisites.js +141 -0
  15. package/dist/cjs/preview/prerequisites/index.js +32 -0
  16. package/dist/cjs/preview/prerequisites/runPrerequisites.js +71 -0
  17. package/dist/cjs/preview/prerequisites/types.js +16 -0
  18. package/dist/cjs/preview/simulate/decodeSimulationError.js +64 -0
  19. package/dist/cjs/preview/simulate/extractERC20Transfers.js +47 -0
  20. package/dist/cjs/preview/simulate/index.js +28 -0
  21. package/dist/cjs/preview/simulate/simulatePoolOperation.js +94 -0
  22. package/dist/cjs/preview/simulate/types.js +16 -0
  23. package/dist/esm/abi/errors.js +40 -1
  24. package/dist/esm/preview/index.js +3 -0
  25. package/dist/esm/preview/package.json +1 -0
  26. package/dist/esm/preview/parse/classifyInnerOperations.js +108 -0
  27. package/dist/esm/preview/parse/errors.js +22 -0
  28. package/dist/esm/preview/parse/index.js +6 -0
  29. package/dist/esm/preview/parse/parseCreditFacadeOperation.js +91 -0
  30. package/dist/esm/preview/parse/parsePoolOperation.js +38 -0
  31. package/dist/esm/preview/parse/parseTransaction.js +25 -0
  32. package/dist/esm/preview/parse/types.js +6 -0
  33. package/dist/esm/preview/prerequisites/AllowancePrerequisite.js +57 -0
  34. package/dist/esm/preview/prerequisites/BalancePrerequisite.js +56 -0
  35. package/dist/esm/preview/prerequisites/Prerequisite.js +63 -0
  36. package/dist/esm/preview/prerequisites/buildPrerequisites.js +117 -0
  37. package/dist/esm/preview/prerequisites/index.js +6 -0
  38. package/dist/esm/preview/prerequisites/runPrerequisites.js +47 -0
  39. package/dist/esm/preview/prerequisites/types.js +0 -0
  40. package/dist/esm/preview/simulate/decodeSimulationError.js +44 -0
  41. package/dist/esm/preview/simulate/extractERC20Transfers.js +23 -0
  42. package/dist/esm/preview/simulate/index.js +4 -0
  43. package/dist/esm/preview/simulate/simulatePoolOperation.js +70 -0
  44. package/dist/esm/preview/simulate/types.js +0 -0
  45. package/dist/types/abi/errors.d.ts +57 -0
  46. package/dist/types/preview/index.d.ts +3 -0
  47. package/dist/types/preview/parse/classifyInnerOperations.d.ts +21 -0
  48. package/dist/types/preview/parse/errors.d.ts +17 -0
  49. package/dist/types/preview/parse/index.d.ts +6 -0
  50. package/dist/types/preview/parse/parseCreditFacadeOperation.d.ts +18 -0
  51. package/dist/types/preview/parse/parsePoolOperation.d.ts +15 -0
  52. package/dist/types/preview/parse/parseTransaction.d.ts +23 -0
  53. package/dist/types/preview/parse/types.d.ts +78 -0
  54. package/dist/types/preview/prerequisites/AllowancePrerequisite.d.ts +24 -0
  55. package/dist/types/preview/prerequisites/BalancePrerequisite.d.ts +23 -0
  56. package/dist/types/preview/prerequisites/Prerequisite.d.ts +60 -0
  57. package/dist/types/preview/prerequisites/buildPrerequisites.d.ts +16 -0
  58. package/dist/types/preview/prerequisites/index.d.ts +6 -0
  59. package/dist/types/preview/prerequisites/runPrerequisites.d.ts +12 -0
  60. package/dist/types/preview/prerequisites/types.d.ts +78 -0
  61. package/dist/types/preview/simulate/decodeSimulationError.d.ts +18 -0
  62. package/dist/types/preview/simulate/extractERC20Transfers.d.ts +11 -0
  63. package/dist/types/preview/simulate/index.d.ts +4 -0
  64. package/dist/types/preview/simulate/simulatePoolOperation.d.ts +30 -0
  65. package/dist/types/preview/simulate/types.d.ts +43 -0
  66. package/package.json +6 -1
@@ -324,8 +324,46 @@ const iERC20ErrorsAbi = [
324
324
  ]
325
325
  }
326
326
  ];
327
+ const safeERC20ErrorsAbi = [
328
+ {
329
+ type: "error",
330
+ name: "ForceApproveFailed",
331
+ inputs: []
332
+ },
333
+ {
334
+ type: "error",
335
+ name: "Permit2TransferAmountTooHigh",
336
+ inputs: []
337
+ },
338
+ {
339
+ type: "error",
340
+ name: "SafeDecreaseAllowanceFailed",
341
+ inputs: []
342
+ },
343
+ {
344
+ type: "error",
345
+ name: "SafeIncreaseAllowanceFailed",
346
+ inputs: []
347
+ },
348
+ {
349
+ type: "error",
350
+ name: "SafePermitBadLength",
351
+ inputs: []
352
+ },
353
+ {
354
+ type: "error",
355
+ name: "SafeTransferFailed",
356
+ inputs: []
357
+ },
358
+ {
359
+ type: "error",
360
+ name: "SafeTransferFromFailed",
361
+ inputs: []
362
+ }
363
+ ];
327
364
  const errorAbis = [
328
365
  ...iERC20ErrorsAbi,
366
+ ...safeERC20ErrorsAbi,
329
367
  ...iExceptionsV310Abi,
330
368
  ...iRedstonePriceFeedExceptionsAbi,
331
369
  ...iRedstoneErrorsAbi,
@@ -341,5 +379,6 @@ export {
341
379
  iRedstoneErrorsAbi,
342
380
  iRedstonePriceFeedExceptionsAbi,
343
381
  iRouterErrorsV310Abi,
344
- ilpPriceFeedExceptionsAbi
382
+ ilpPriceFeedExceptionsAbi,
383
+ safeERC20ErrorsAbi
345
384
  };
@@ -0,0 +1,3 @@
1
+ export * from "./parse/index.js";
2
+ export * from "./prerequisites/index.js";
3
+ export * from "./simulate/index.js";
@@ -0,0 +1 @@
1
+ {"type": "module","sideEffects":false}
@@ -0,0 +1,108 @@
1
+ import { zeroAddress } from "viem";
2
+ import {
3
+ AbstractAdapterContract
4
+ } from "../../plugins/adapters/index.js";
5
+ function classifyInnerOperations(calls, props) {
6
+ const { sdk, underlying } = props;
7
+ const result = [];
8
+ for (const call of calls) {
9
+ const contract = sdk.getContract(call.target);
10
+ if (contract instanceof AbstractAdapterContract) {
11
+ result.push({
12
+ operation: "Execute",
13
+ adapter: call.target,
14
+ protocol: contract.targetContract,
15
+ adapterType: call.contractType,
16
+ version: call.version,
17
+ label: call.label,
18
+ adapterFunctionName: call.functionName,
19
+ adapterArgs: call.rawArgs,
20
+ // TODO: mirror the adapter call into the protocol fields for now. The
21
+ // real protocol-level call (adapter -> target contract) only exists in
22
+ // the execution call trace, which is not available from raw calldata.
23
+ // Recovering the actual protocol function/args requires a call trace.
24
+ protocolFunctionName: call.functionName,
25
+ protocolArgs: call.rawArgs,
26
+ transfers: [],
27
+ legacy: mockLegacyOperation()
28
+ });
29
+ continue;
30
+ }
31
+ if (contract !== void 0) {
32
+ const op = classifyFacadeInnerCall(call, underlying);
33
+ if (op) result.push(op);
34
+ continue;
35
+ }
36
+ result.push({
37
+ operation: "Execute",
38
+ adapter: call.target,
39
+ protocol: call.target,
40
+ adapterType: call.contractType,
41
+ version: call.version,
42
+ label: call.label,
43
+ adapterFunctionName: call.functionName,
44
+ adapterArgs: call.rawArgs,
45
+ // TODO: mirror the adapter call into the protocol fields for now. The
46
+ // real protocol-level call (adapter -> target contract) only exists in
47
+ // the execution call trace, which is not available from raw calldata.
48
+ // Recovering the actual protocol function/args requires a call trace.
49
+ protocolFunctionName: call.functionName,
50
+ protocolArgs: call.rawArgs,
51
+ transfers: [],
52
+ legacy: mockLegacyOperation()
53
+ });
54
+ }
55
+ return result;
56
+ }
57
+ function classifyFacadeInnerCall(call, underlying) {
58
+ const functionName = call.functionName.split("(")[0];
59
+ const { rawArgs } = call;
60
+ switch (functionName) {
61
+ case "increaseDebt":
62
+ return {
63
+ operation: "IncreaseBorrowedAmount",
64
+ token: underlying,
65
+ amount: rawArgs.amount
66
+ };
67
+ case "decreaseDebt":
68
+ return {
69
+ operation: "DecreaseBorrowedAmount",
70
+ token: underlying,
71
+ amount: rawArgs.amount
72
+ };
73
+ case "addCollateral":
74
+ case "addCollateralWithPermit":
75
+ return {
76
+ operation: "AddCollateral",
77
+ token: rawArgs.token,
78
+ amount: rawArgs.amount
79
+ };
80
+ case "withdrawCollateral":
81
+ return {
82
+ operation: "WithdrawCollateral",
83
+ token: rawArgs.token,
84
+ amount: rawArgs.amount,
85
+ to: rawArgs.to
86
+ };
87
+ case "updateQuota":
88
+ return {
89
+ operation: "UpdateQuota",
90
+ token: rawArgs.token,
91
+ change: rawArgs.quotaChange
92
+ };
93
+ default:
94
+ return null;
95
+ }
96
+ }
97
+ function mockLegacyOperation() {
98
+ return {
99
+ operation: "Swap",
100
+ from: zeroAddress,
101
+ fromAmount: "0",
102
+ to: zeroAddress,
103
+ toAmount: "0"
104
+ };
105
+ }
106
+ export {
107
+ classifyInnerOperations
108
+ };
@@ -0,0 +1,22 @@
1
+ class UnsupportedTargetError extends Error {
2
+ target;
3
+ constructor(target) {
4
+ super(`unsupported transaction target: ${target}`);
5
+ this.name = "UnsupportedTargetError";
6
+ this.target = target;
7
+ }
8
+ }
9
+ class UnsupportedPoolFunctionError extends Error {
10
+ pool;
11
+ functionName;
12
+ constructor(pool, functionName) {
13
+ super(`unsupported pool function "${functionName}" on ${pool}`);
14
+ this.name = "UnsupportedPoolFunctionError";
15
+ this.pool = pool;
16
+ this.functionName = functionName;
17
+ }
18
+ }
19
+ export {
20
+ UnsupportedPoolFunctionError,
21
+ UnsupportedTargetError
22
+ };
@@ -0,0 +1,6 @@
1
+ export * from "./classifyInnerOperations.js";
2
+ export * from "./errors.js";
3
+ export * from "./parseCreditFacadeOperation.js";
4
+ export * from "./parsePoolOperation.js";
5
+ export * from "./parseTransaction.js";
6
+ export * from "./types.js";
@@ -0,0 +1,91 @@
1
+ import {
2
+ isAddressEqual,
3
+ zeroAddress,
4
+ zeroHash
5
+ } from "viem";
6
+ import { classifyInnerOperations } from "./classifyInnerOperations.js";
7
+ function parseCreditFacadeOperation(props) {
8
+ const { sdk, facade, calldata } = props;
9
+ const parsed = sdk.parseFunctionDataV2(facade.address, calldata);
10
+ const functionName = parsed.functionName.split("(")[0];
11
+ const { rawArgs } = parsed;
12
+ const suite = sdk.marketRegister.creditManagers.find(
13
+ (cm) => isAddressEqual(cm.creditFacade.address, facade.address)
14
+ );
15
+ if (!suite) {
16
+ throw new Error(`no credit suite found for facade ${facade.address}`);
17
+ }
18
+ const metadata = {
19
+ creditManager: suite.creditManager.address,
20
+ creditFacade: facade.address,
21
+ blockNumber: Number(sdk.currentBlock),
22
+ txHash: zeroHash,
23
+ timestamp: 0
24
+ };
25
+ const innerCalls = rawArgs.calls ?? [];
26
+ const multicall = classifyInnerOperations(innerCalls, {
27
+ sdk,
28
+ underlying: suite.underlying
29
+ });
30
+ switch (functionName) {
31
+ case "multicall":
32
+ return {
33
+ ...metadata,
34
+ operation: "MultiCall",
35
+ creditAccount: rawArgs.creditAccount,
36
+ multicall
37
+ };
38
+ case "botMulticall":
39
+ return {
40
+ ...metadata,
41
+ operation: "BotMulticall",
42
+ creditAccount: rawArgs.creditAccount,
43
+ multicall
44
+ };
45
+ case "openCreditAccount":
46
+ return {
47
+ ...metadata,
48
+ operation: "OpenCreditAccount",
49
+ creditAccount: zeroAddress,
50
+ onBehalfOf: rawArgs.onBehalfOf,
51
+ referralCode: rawArgs.referralCode,
52
+ multicall
53
+ };
54
+ case "closeCreditAccount":
55
+ return {
56
+ ...metadata,
57
+ operation: "CloseCreditAccount",
58
+ creditAccount: rawArgs.creditAccount,
59
+ multicall
60
+ };
61
+ case "liquidateCreditAccount":
62
+ return {
63
+ ...metadata,
64
+ operation: "LiquidateCreditAccount",
65
+ creditAccount: rawArgs.creditAccount,
66
+ to: rawArgs.to,
67
+ // `token` and `remainingFunds` are only emitted on-chain during
68
+ // liquidation, so they are not recoverable from raw calldata.
69
+ token: zeroAddress,
70
+ remainingFunds: 0n,
71
+ multicall
72
+ };
73
+ case "partiallyLiquidateCreditAccount":
74
+ return {
75
+ ...metadata,
76
+ operation: "PartiallyLiquidateCreditAccount",
77
+ creditAccount: rawArgs.creditAccount,
78
+ token: rawArgs.token,
79
+ repaidAmount: rawArgs.repaidAmount,
80
+ minSeizedAmount: rawArgs.minSeizedAmount,
81
+ to: rawArgs.to
82
+ };
83
+ default:
84
+ throw new Error(
85
+ `unsupported credit facade function "${parsed.functionName}" on ${facade.address}`
86
+ );
87
+ }
88
+ }
89
+ export {
90
+ parseCreditFacadeOperation
91
+ };
@@ -0,0 +1,38 @@
1
+ import { UnsupportedPoolFunctionError } from "./errors.js";
2
+ function parsePoolOperation(props) {
3
+ const { sdk, pool, calldata } = props;
4
+ const parsed = sdk.parseFunctionDataV2(pool.address, calldata);
5
+ const functionName = parsed.functionName.split("(")[0];
6
+ const { rawArgs } = parsed;
7
+ const underlying = pool.underlying;
8
+ switch (functionName) {
9
+ case "deposit":
10
+ case "depositWithReferral":
11
+ return {
12
+ operation: "Deposit",
13
+ pool: pool.address,
14
+ receiver: rawArgs.receiver,
15
+ assets: rawArgs.assets,
16
+ underlying,
17
+ referralCode: functionName === "depositWithReferral" ? rawArgs.referralCode : void 0,
18
+ // Calldata-only parse: transfers are recovered later by simulation.
19
+ transfers: []
20
+ };
21
+ case "redeem":
22
+ return {
23
+ operation: "Redeem",
24
+ pool: pool.address,
25
+ receiver: rawArgs.receiver,
26
+ owner: rawArgs.owner,
27
+ shares: rawArgs.shares,
28
+ underlying,
29
+ // Calldata-only parse: transfers are recovered later by simulation.
30
+ transfers: []
31
+ };
32
+ default:
33
+ throw new UnsupportedPoolFunctionError(pool.address, parsed.functionName);
34
+ }
35
+ }
36
+ export {
37
+ parsePoolOperation
38
+ };
@@ -0,0 +1,25 @@
1
+ import {
2
+ CreditFacadeV310Contract,
3
+ PoolV310Contract
4
+ } from "../../sdk/index.js";
5
+ import { UnsupportedTargetError } from "./errors.js";
6
+ import { parseCreditFacadeOperation } from "./parseCreditFacadeOperation.js";
7
+ import { parsePoolOperation } from "./parsePoolOperation.js";
8
+ function parseTransaction(input) {
9
+ const { sdk, to, calldata } = input;
10
+ const contract = sdk.getContract(to);
11
+ if (contract instanceof PoolV310Contract) {
12
+ return parsePoolOperation({ sdk, pool: contract, calldata });
13
+ }
14
+ if (contract instanceof CreditFacadeV310Contract) {
15
+ return parseCreditFacadeOperation({
16
+ sdk,
17
+ facade: contract,
18
+ calldata
19
+ });
20
+ }
21
+ throw new UnsupportedTargetError(to);
22
+ }
23
+ export {
24
+ parseTransaction
25
+ };
@@ -0,0 +1,6 @@
1
+ function isPoolOperation(tx) {
2
+ return tx.operation === "Deposit" || tx.operation === "Redeem";
3
+ }
4
+ export {
5
+ isPoolOperation
6
+ };
@@ -0,0 +1,57 @@
1
+ import { erc20Abi } from "viem";
2
+ import {
3
+ Prerequisite,
4
+ toPrerequisiteError
5
+ } from "./Prerequisite.js";
6
+ class AllowancePrerequisite extends Prerequisite {
7
+ _id;
8
+ _title;
9
+ _detail;
10
+ constructor(props) {
11
+ super();
12
+ this._id = props.id ?? `allowance:${props.token}:${props.owner}:${props.spender}`;
13
+ this._title = props.title ?? "Token approval";
14
+ this._detail = {
15
+ token: props.token,
16
+ owner: props.owner,
17
+ spender: props.spender,
18
+ required: props.required
19
+ };
20
+ }
21
+ get id() {
22
+ return this._id;
23
+ }
24
+ get kind() {
25
+ return "allowance";
26
+ }
27
+ get title() {
28
+ return this._title;
29
+ }
30
+ get detail() {
31
+ return this._detail;
32
+ }
33
+ calls() {
34
+ return [
35
+ {
36
+ address: this._detail.token,
37
+ abi: erc20Abi,
38
+ functionName: "allowance",
39
+ args: [this._detail.owner, this._detail.spender]
40
+ }
41
+ ];
42
+ }
43
+ resolve(slice) {
44
+ const res = slice[0];
45
+ if (!res || res.status === "failure") {
46
+ return this.errorResult(toPrerequisiteError(res?.error));
47
+ }
48
+ const actual = res.result;
49
+ return this.satisfiedResult(actual >= this._detail.required, {
50
+ ...this._detail,
51
+ actual
52
+ });
53
+ }
54
+ }
55
+ export {
56
+ AllowancePrerequisite
57
+ };
@@ -0,0 +1,56 @@
1
+ import { erc20Abi } from "viem";
2
+ import {
3
+ Prerequisite,
4
+ toPrerequisiteError
5
+ } from "./Prerequisite.js";
6
+ class BalancePrerequisite extends Prerequisite {
7
+ _id;
8
+ _title;
9
+ _detail;
10
+ constructor(props) {
11
+ super();
12
+ this._id = props.id ?? `balance:${props.token}:${props.owner}`;
13
+ this._title = props.title ?? "Sufficient balance";
14
+ this._detail = {
15
+ token: props.token,
16
+ owner: props.owner,
17
+ required: props.required
18
+ };
19
+ }
20
+ get id() {
21
+ return this._id;
22
+ }
23
+ get kind() {
24
+ return "balance";
25
+ }
26
+ get title() {
27
+ return this._title;
28
+ }
29
+ get detail() {
30
+ return this._detail;
31
+ }
32
+ calls() {
33
+ return [
34
+ {
35
+ address: this._detail.token,
36
+ abi: erc20Abi,
37
+ functionName: "balanceOf",
38
+ args: [this._detail.owner]
39
+ }
40
+ ];
41
+ }
42
+ resolve(slice) {
43
+ const res = slice[0];
44
+ if (!res || res.status === "failure") {
45
+ return this.errorResult(toPrerequisiteError(res?.error));
46
+ }
47
+ const actual = res.result;
48
+ return this.satisfiedResult(actual >= this._detail.required, {
49
+ ...this._detail,
50
+ actual
51
+ });
52
+ }
53
+ }
54
+ export {
55
+ BalancePrerequisite
56
+ };
@@ -0,0 +1,63 @@
1
+ import {
2
+ BaseError,
3
+ ContractFunctionRevertedError
4
+ } from "viem";
5
+ function toPrerequisiteError(cause) {
6
+ if (cause instanceof BaseError) {
7
+ const reverted = cause.walk(
8
+ (e) => e instanceof ContractFunctionRevertedError
9
+ );
10
+ if (reverted instanceof ContractFunctionRevertedError) {
11
+ return {
12
+ reason: reverted.data?.errorName ?? reverted.shortMessage ?? "reverted",
13
+ cause
14
+ };
15
+ }
16
+ return { reason: cause.shortMessage ?? cause.name, cause };
17
+ }
18
+ if (cause instanceof Error) {
19
+ return { reason: cause.message, cause };
20
+ }
21
+ return { reason: "unknown error", cause };
22
+ }
23
+ class Prerequisite {
24
+ /**
25
+ * Verifies this prerequisite on its own using an `allowFailure` multicall.
26
+ * Prefer `verifyPrerequisites` to batch several checks into one round-trip.
27
+ */
28
+ 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);
38
+ }
39
+ /** Builds a successful result; `detail` carries the on-chain `actual`. */
40
+ satisfiedResult(satisfied, detail) {
41
+ return {
42
+ id: this.id,
43
+ kind: this.kind,
44
+ title: this.title,
45
+ detail,
46
+ satisfied
47
+ };
48
+ }
49
+ /** Builds a failed result from a decoded read error. */
50
+ errorResult(error) {
51
+ return {
52
+ id: this.id,
53
+ kind: this.kind,
54
+ title: this.title,
55
+ detail: this.detail,
56
+ error
57
+ };
58
+ }
59
+ }
60
+ export {
61
+ Prerequisite,
62
+ toPrerequisiteError
63
+ };
@@ -0,0 +1,117 @@
1
+ import { isAddressEqual } from "viem";
2
+ import { AllowancePrerequisite } from "./AllowancePrerequisite.js";
3
+ import { BalancePrerequisite } from "./BalancePrerequisite.js";
4
+ function buildPrerequisites(tx, ctx) {
5
+ const { wallet } = ctx;
6
+ switch (tx.operation) {
7
+ case "Deposit":
8
+ return [
9
+ new AllowancePrerequisite({
10
+ token: tx.underlying,
11
+ owner: wallet,
12
+ spender: tx.pool,
13
+ required: tx.assets,
14
+ title: "Token approved to pool"
15
+ }),
16
+ new BalancePrerequisite({
17
+ token: tx.underlying,
18
+ owner: wallet,
19
+ required: tx.assets,
20
+ title: "Sufficient token balance"
21
+ })
22
+ ];
23
+ case "Redeem": {
24
+ const prereqs = [
25
+ new BalancePrerequisite({
26
+ token: tx.pool,
27
+ owner: tx.owner,
28
+ required: tx.shares,
29
+ title: "Sufficient LP token balance"
30
+ })
31
+ ];
32
+ if (!isAddressEqual(tx.owner, wallet)) {
33
+ prereqs.push(
34
+ new AllowancePrerequisite({
35
+ token: tx.pool,
36
+ owner: tx.owner,
37
+ spender: wallet,
38
+ required: tx.shares,
39
+ title: "LP token approved to caller"
40
+ })
41
+ );
42
+ }
43
+ return prereqs;
44
+ }
45
+ case "MultiCall":
46
+ case "BotMulticall":
47
+ case "OpenCreditAccount":
48
+ case "CloseCreditAccount":
49
+ case "LiquidateCreditAccount":
50
+ return collateralPrerequisites(tx.multicall, tx.creditManager, wallet);
51
+ case "PartiallyLiquidateCreditAccount": {
52
+ const underlying = underlyingOf(ctx.sdk, tx.creditManager);
53
+ if (!underlying || tx.repaidAmount === 0n) {
54
+ return [];
55
+ }
56
+ return [
57
+ new AllowancePrerequisite({
58
+ token: underlying,
59
+ owner: wallet,
60
+ spender: tx.creditManager,
61
+ required: tx.repaidAmount,
62
+ title: "Underlying approved to credit manager"
63
+ }),
64
+ new BalancePrerequisite({
65
+ token: underlying,
66
+ owner: wallet,
67
+ required: tx.repaidAmount,
68
+ title: "Sufficient underlying balance"
69
+ })
70
+ ];
71
+ }
72
+ default:
73
+ return [];
74
+ }
75
+ }
76
+ function collateralPrerequisites(multicall, creditManager, wallet) {
77
+ const required = /* @__PURE__ */ new Map();
78
+ for (const op of multicall) {
79
+ if (op.operation !== "AddCollateral" || op.amount === 0n) {
80
+ continue;
81
+ }
82
+ const key = op.token.toLowerCase();
83
+ const existing = required.get(key);
84
+ required.set(key, {
85
+ token: op.token,
86
+ amount: (existing?.amount ?? 0n) + op.amount
87
+ });
88
+ }
89
+ const prereqs = [];
90
+ for (const { token, amount } of required.values()) {
91
+ prereqs.push(
92
+ new AllowancePrerequisite({
93
+ token,
94
+ owner: wallet,
95
+ spender: creditManager,
96
+ required: amount,
97
+ title: "Collateral approved to credit manager"
98
+ }),
99
+ new BalancePrerequisite({
100
+ token,
101
+ owner: wallet,
102
+ required: amount,
103
+ title: "Sufficient collateral balance"
104
+ })
105
+ );
106
+ }
107
+ return prereqs;
108
+ }
109
+ function underlyingOf(sdk, creditManager) {
110
+ const suite = sdk.marketRegister.creditManagers.find(
111
+ (cm) => isAddressEqual(cm.creditManager.address, creditManager)
112
+ );
113
+ return suite?.underlying;
114
+ }
115
+ export {
116
+ buildPrerequisites
117
+ };
@@ -0,0 +1,6 @@
1
+ export * from "./AllowancePrerequisite.js";
2
+ export * from "./BalancePrerequisite.js";
3
+ export * from "./buildPrerequisites.js";
4
+ export * from "./Prerequisite.js";
5
+ export * from "./runPrerequisites.js";
6
+ export * from "./types.js";