@gearbox-protocol/sdk 14.5.6 → 14.5.7

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.
@@ -32,16 +32,24 @@ function assembleOperations(input) {
32
32
  underlying,
33
33
  liquidationRemainingFunds,
34
34
  phantomTokens,
35
+ withdrawCollateralEvents = [],
35
36
  strict
36
37
  } = input;
37
- let offset = 0;
38
+ let executeOffset = 0;
39
+ let withdrawOffset = 0;
38
40
  return facadeCalls.map((fc) => {
39
41
  if (fc.operation === "PartiallyLiquidateCreditAccount") {
40
42
  return assemblePartialLiquidation(fc);
41
43
  }
42
44
  const count = countAdapterCalls(fc.innerCalls, register);
43
- const sliced = executeResults.slice(offset, offset + count);
44
- offset += count;
45
+ const sliced = executeResults.slice(executeOffset, executeOffset + count);
46
+ executeOffset += count;
47
+ const withdrawCount = countWithdrawCollateralCalls(fc.innerCalls);
48
+ const slicedWithdrawEvents = withdrawCollateralEvents.slice(
49
+ withdrawOffset,
50
+ withdrawOffset + withdrawCount
51
+ );
52
+ withdrawOffset += withdrawCount;
45
53
  const protocolCalldatas = (0, import_extractProtocolCalls.extractProtocolCalls)(fc.trace, sliced);
46
54
  const multicall = (0, import_classifyMulticallOperations.classifyMulticallOperations)({
47
55
  innerCalls: fc.innerCalls,
@@ -51,7 +59,8 @@ function assembleOperations(input) {
51
59
  creditAccount: fc.creditAccount,
52
60
  underlying,
53
61
  strict,
54
- phantomTokens
62
+ phantomTokens,
63
+ withdrawCollateralEvents: slicedWithdrawEvents
55
64
  });
56
65
  switch (fc.operation) {
57
66
  case "OpenCreditAccount":
@@ -86,6 +95,11 @@ function countAdapterCalls(innerCalls, register) {
86
95
  return !contract || contract instanceof import_adapters.AbstractAdapterContract;
87
96
  }).length;
88
97
  }
98
+ function countWithdrawCollateralCalls(innerCalls) {
99
+ return innerCalls.filter(
100
+ (call) => call.functionName.startsWith("withdrawCollateral")
101
+ ).length;
102
+ }
89
103
  function assemblePartialLiquidation(fc) {
90
104
  const { rawArgs } = fc.parsed;
91
105
  return {
@@ -33,9 +33,11 @@ function classifyMulticallOperations(input) {
33
33
  creditAccount,
34
34
  underlying,
35
35
  strict,
36
- phantomTokens
36
+ phantomTokens,
37
+ withdrawCollateralEvents
37
38
  } = input;
38
39
  let transferIdx = 0;
40
+ let withdrawIdx = 0;
39
41
  const result = [];
40
42
  for (const call of innerCalls) {
41
43
  const contract = register.getContract(call.target);
@@ -58,7 +60,14 @@ function classifyMulticallOperations(input) {
58
60
  continue;
59
61
  }
60
62
  if (contract !== void 0) {
61
- const op = classifyFacadeInnerCall(call, underlying, phantomTokens);
63
+ const isWithdraw = call.functionName.startsWith("withdrawCollateral");
64
+ const withdrawEvent = isWithdraw ? withdrawCollateralEvents?.[withdrawIdx++] : void 0;
65
+ const op = classifyFacadeInnerCall(
66
+ call,
67
+ underlying,
68
+ phantomTokens,
69
+ withdrawEvent
70
+ );
62
71
  if (op) result.push(op);
63
72
  continue;
64
73
  }
@@ -93,9 +102,15 @@ function classifyMulticallOperations(input) {
93
102
  if (transferIdx !== executeResults.length) {
94
103
  throw new import_errors.TransferAlignmentError(executeResults.length, transferIdx);
95
104
  }
105
+ if (withdrawCollateralEvents && withdrawCollateralEvents.length > 0 && withdrawIdx !== withdrawCollateralEvents.length) {
106
+ throw new import_errors.WithdrawCollateralAlignmentError(
107
+ withdrawCollateralEvents.length,
108
+ withdrawIdx
109
+ );
110
+ }
96
111
  return result;
97
112
  }
98
- function classifyFacadeInnerCall(call, underlying, phantomTokens) {
113
+ function classifyFacadeInnerCall(call, underlying, phantomTokens, withdrawEvent) {
99
114
  const { functionName: sig, rawArgs } = call;
100
115
  const functionName = sig.split("(")[0];
101
116
  switch (functionName) {
@@ -124,10 +139,11 @@ function classifyFacadeInnerCall(call, underlying, phantomTokens) {
124
139
  calldataToken,
125
140
  phantomTokens
126
141
  );
142
+ const amount = withdrawEvent ? withdrawEvent.amount : rawArgs.amount;
127
143
  return {
128
144
  operation: "WithdrawCollateral",
129
145
  token: depositedToken ?? calldataToken,
130
- amount: rawArgs.amount,
146
+ amount,
131
147
  to: rawArgs.to,
132
148
  ...depositedToken ? { phantomToken: calldataToken } : {}
133
149
  };
@@ -23,7 +23,8 @@ __export(errors_exports, {
23
23
  TransferAlignmentError: () => TransferAlignmentError,
24
24
  UnexpectedFacadeEventOrderError: () => UnexpectedFacadeEventOrderError,
25
25
  UnknownAdapterError: () => UnknownAdapterError,
26
- UnknownFacadeCallError: () => UnknownFacadeCallError
26
+ UnknownFacadeCallError: () => UnknownFacadeCallError,
27
+ WithdrawCollateralAlignmentError: () => WithdrawCollateralAlignmentError
27
28
  });
28
29
  module.exports = __toCommonJS(errors_exports);
29
30
  class UnknownAdapterError extends Error {
@@ -42,6 +43,14 @@ class TransferAlignmentError extends Error {
42
43
  this.name = "TransferAlignmentError";
43
44
  }
44
45
  }
46
+ class WithdrawCollateralAlignmentError extends Error {
47
+ constructor(expected, actual) {
48
+ super(
49
+ `withdrawCollateral event alignment mismatch: expected ${expected} events, consumed ${actual}`
50
+ );
51
+ this.name = "WithdrawCollateralAlignmentError";
52
+ }
53
+ }
45
54
  class ProtocolCallNotFoundError extends Error {
46
55
  targetContract;
47
56
  executeIndex;
@@ -89,5 +98,6 @@ class UnknownFacadeCallError extends Error {
89
98
  TransferAlignmentError,
90
99
  UnexpectedFacadeEventOrderError,
91
100
  UnknownAdapterError,
92
- UnknownFacadeCallError
101
+ UnknownFacadeCallError,
102
+ WithdrawCollateralAlignmentError
93
103
  });
@@ -32,6 +32,7 @@ function extractTransfers(logs, creditAccount, pool, creditFacade) {
32
32
  const executeResults = [];
33
33
  const directTransfers = [];
34
34
  const phantomTokens = new import_sdk.AddressMap();
35
+ const withdrawCollateralEvents = [];
35
36
  let liquidationRemainingFunds;
36
37
  for (const log of logs) {
37
38
  const facadeEvent = tryDecodeFacadeEvent(log, creditFacade);
@@ -62,6 +63,12 @@ function extractTransfers(logs, creditAccount, pool, creditFacade) {
62
63
  facadeEvent.args.token,
63
64
  (0, import_viem.getAddress)(rawDeposit.token)
64
65
  );
66
+ } else if (isWithdrawCollateral(facadeEvent, creditAccount)) {
67
+ withdrawCollateralEvents.push({
68
+ token: (0, import_viem.getAddress)(facadeEvent.args.token),
69
+ amount: facadeEvent.args.amount,
70
+ to: (0, import_viem.getAddress)(facadeEvent.args.to)
71
+ });
65
72
  }
66
73
  currentEntries = [];
67
74
  continue;
@@ -86,7 +93,8 @@ function extractTransfers(logs, creditAccount, pool, creditFacade) {
86
93
  executeResults,
87
94
  directTransfers,
88
95
  liquidationRemainingFunds,
89
- phantomTokens
96
+ phantomTokens,
97
+ withdrawCollateralEvents
90
98
  };
91
99
  }
92
100
  function buildOperationRanges(logs, facadeAddress, creditAccount) {
@@ -162,6 +170,9 @@ function isLiquidation(e, creditAccount) {
162
170
  function isWithdrawPhantomToken(e, creditAccount) {
163
171
  return e.eventName === "WithdrawPhantomToken" && (0, import_viem.isAddressEqual)(e.args.creditAccount, creditAccount);
164
172
  }
173
+ function isWithdrawCollateral(e, creditAccount) {
174
+ return e.eventName === "WithdrawCollateral" && (0, import_viem.isAddressEqual)(e.args.creditAccount, creditAccount);
175
+ }
165
176
  // Annotate the CommonJS export names for ESM import in node:
166
177
  0 && (module.exports = {
167
178
  extractTransfers
@@ -51,7 +51,8 @@ function parseCreditAccountTransaction(input) {
51
51
  executeResults,
52
52
  directTransfers,
53
53
  liquidationRemainingFunds,
54
- phantomTokens
54
+ phantomTokens,
55
+ withdrawCollateralEvents
55
56
  } = (0, import_extractTransfers.extractTransfers)(logs, creditAccount, pool, creditFacade);
56
57
  const meta = {
57
58
  creditManager,
@@ -67,6 +68,7 @@ function parseCreditAccountTransaction(input) {
67
68
  underlying,
68
69
  liquidationRemainingFunds,
69
70
  phantomTokens,
71
+ withdrawCollateralEvents,
70
72
  strict
71
73
  }).map((o) => ({ ...o, ...meta }));
72
74
  const directOps = directTransfers.map((dt) => ({
@@ -9,16 +9,24 @@ function assembleOperations(input) {
9
9
  underlying,
10
10
  liquidationRemainingFunds,
11
11
  phantomTokens,
12
+ withdrawCollateralEvents = [],
12
13
  strict
13
14
  } = input;
14
- let offset = 0;
15
+ let executeOffset = 0;
16
+ let withdrawOffset = 0;
15
17
  return facadeCalls.map((fc) => {
16
18
  if (fc.operation === "PartiallyLiquidateCreditAccount") {
17
19
  return assemblePartialLiquidation(fc);
18
20
  }
19
21
  const count = countAdapterCalls(fc.innerCalls, register);
20
- const sliced = executeResults.slice(offset, offset + count);
21
- offset += count;
22
+ const sliced = executeResults.slice(executeOffset, executeOffset + count);
23
+ executeOffset += count;
24
+ const withdrawCount = countWithdrawCollateralCalls(fc.innerCalls);
25
+ const slicedWithdrawEvents = withdrawCollateralEvents.slice(
26
+ withdrawOffset,
27
+ withdrawOffset + withdrawCount
28
+ );
29
+ withdrawOffset += withdrawCount;
22
30
  const protocolCalldatas = extractProtocolCalls(fc.trace, sliced);
23
31
  const multicall = classifyMulticallOperations({
24
32
  innerCalls: fc.innerCalls,
@@ -28,7 +36,8 @@ function assembleOperations(input) {
28
36
  creditAccount: fc.creditAccount,
29
37
  underlying,
30
38
  strict,
31
- phantomTokens
39
+ phantomTokens,
40
+ withdrawCollateralEvents: slicedWithdrawEvents
32
41
  });
33
42
  switch (fc.operation) {
34
43
  case "OpenCreditAccount":
@@ -63,6 +72,11 @@ function countAdapterCalls(innerCalls, register) {
63
72
  return !contract || contract instanceof AbstractAdapterContract;
64
73
  }).length;
65
74
  }
75
+ function countWithdrawCollateralCalls(innerCalls) {
76
+ return innerCalls.filter(
77
+ (call) => call.functionName.startsWith("withdrawCollateral")
78
+ ).length;
79
+ }
66
80
  function assemblePartialLiquidation(fc) {
67
81
  const { rawArgs } = fc.parsed;
68
82
  return {
@@ -4,7 +4,11 @@ import {
4
4
  swapFromTransfers,
5
5
  toNetTransfers
6
6
  } from "../plugins/adapters/index.js";
7
- import { TransferAlignmentError, UnknownAdapterError } from "./errors.js";
7
+ import {
8
+ TransferAlignmentError,
9
+ UnknownAdapterError,
10
+ WithdrawCollateralAlignmentError
11
+ } from "./errors.js";
8
12
  function classifyMulticallOperations(input) {
9
13
  const {
10
14
  innerCalls,
@@ -14,9 +18,11 @@ function classifyMulticallOperations(input) {
14
18
  creditAccount,
15
19
  underlying,
16
20
  strict,
17
- phantomTokens
21
+ phantomTokens,
22
+ withdrawCollateralEvents
18
23
  } = input;
19
24
  let transferIdx = 0;
25
+ let withdrawIdx = 0;
20
26
  const result = [];
21
27
  for (const call of innerCalls) {
22
28
  const contract = register.getContract(call.target);
@@ -39,7 +45,14 @@ function classifyMulticallOperations(input) {
39
45
  continue;
40
46
  }
41
47
  if (contract !== void 0) {
42
- const op = classifyFacadeInnerCall(call, underlying, phantomTokens);
48
+ const isWithdraw = call.functionName.startsWith("withdrawCollateral");
49
+ const withdrawEvent = isWithdraw ? withdrawCollateralEvents?.[withdrawIdx++] : void 0;
50
+ const op = classifyFacadeInnerCall(
51
+ call,
52
+ underlying,
53
+ phantomTokens,
54
+ withdrawEvent
55
+ );
43
56
  if (op) result.push(op);
44
57
  continue;
45
58
  }
@@ -74,9 +87,15 @@ function classifyMulticallOperations(input) {
74
87
  if (transferIdx !== executeResults.length) {
75
88
  throw new TransferAlignmentError(executeResults.length, transferIdx);
76
89
  }
90
+ if (withdrawCollateralEvents && withdrawCollateralEvents.length > 0 && withdrawIdx !== withdrawCollateralEvents.length) {
91
+ throw new WithdrawCollateralAlignmentError(
92
+ withdrawCollateralEvents.length,
93
+ withdrawIdx
94
+ );
95
+ }
77
96
  return result;
78
97
  }
79
- function classifyFacadeInnerCall(call, underlying, phantomTokens) {
98
+ function classifyFacadeInnerCall(call, underlying, phantomTokens, withdrawEvent) {
80
99
  const { functionName: sig, rawArgs } = call;
81
100
  const functionName = sig.split("(")[0];
82
101
  switch (functionName) {
@@ -105,10 +124,11 @@ function classifyFacadeInnerCall(call, underlying, phantomTokens) {
105
124
  calldataToken,
106
125
  phantomTokens
107
126
  );
127
+ const amount = withdrawEvent ? withdrawEvent.amount : rawArgs.amount;
108
128
  return {
109
129
  operation: "WithdrawCollateral",
110
130
  token: depositedToken ?? calldataToken,
111
- amount: rawArgs.amount,
131
+ amount,
112
132
  to: rawArgs.to,
113
133
  ...depositedToken ? { phantomToken: calldataToken } : {}
114
134
  };
@@ -14,6 +14,14 @@ class TransferAlignmentError extends Error {
14
14
  this.name = "TransferAlignmentError";
15
15
  }
16
16
  }
17
+ class WithdrawCollateralAlignmentError extends Error {
18
+ constructor(expected, actual) {
19
+ super(
20
+ `withdrawCollateral event alignment mismatch: expected ${expected} events, consumed ${actual}`
21
+ );
22
+ this.name = "WithdrawCollateralAlignmentError";
23
+ }
24
+ }
17
25
  class ProtocolCallNotFoundError extends Error {
18
26
  targetContract;
19
27
  executeIndex;
@@ -60,5 +68,6 @@ export {
60
68
  TransferAlignmentError,
61
69
  UnexpectedFacadeEventOrderError,
62
70
  UnknownAdapterError,
63
- UnknownFacadeCallError
71
+ UnknownFacadeCallError,
72
+ WithdrawCollateralAlignmentError
64
73
  };
@@ -13,6 +13,7 @@ function extractTransfers(logs, creditAccount, pool, creditFacade) {
13
13
  const executeResults = [];
14
14
  const directTransfers = [];
15
15
  const phantomTokens = new AddressMap();
16
+ const withdrawCollateralEvents = [];
16
17
  let liquidationRemainingFunds;
17
18
  for (const log of logs) {
18
19
  const facadeEvent = tryDecodeFacadeEvent(log, creditFacade);
@@ -43,6 +44,12 @@ function extractTransfers(logs, creditAccount, pool, creditFacade) {
43
44
  facadeEvent.args.token,
44
45
  getAddress(rawDeposit.token)
45
46
  );
47
+ } else if (isWithdrawCollateral(facadeEvent, creditAccount)) {
48
+ withdrawCollateralEvents.push({
49
+ token: getAddress(facadeEvent.args.token),
50
+ amount: facadeEvent.args.amount,
51
+ to: getAddress(facadeEvent.args.to)
52
+ });
46
53
  }
47
54
  currentEntries = [];
48
55
  continue;
@@ -67,7 +74,8 @@ function extractTransfers(logs, creditAccount, pool, creditFacade) {
67
74
  executeResults,
68
75
  directTransfers,
69
76
  liquidationRemainingFunds,
70
- phantomTokens
77
+ phantomTokens,
78
+ withdrawCollateralEvents
71
79
  };
72
80
  }
73
81
  function buildOperationRanges(logs, facadeAddress, creditAccount) {
@@ -143,6 +151,9 @@ function isLiquidation(e, creditAccount) {
143
151
  function isWithdrawPhantomToken(e, creditAccount) {
144
152
  return e.eventName === "WithdrawPhantomToken" && isAddressEqual(e.args.creditAccount, creditAccount);
145
153
  }
154
+ function isWithdrawCollateral(e, creditAccount) {
155
+ return e.eventName === "WithdrawCollateral" && isAddressEqual(e.args.creditAccount, creditAccount);
156
+ }
146
157
  export {
147
158
  extractTransfers
148
159
  };
@@ -28,7 +28,8 @@ function parseCreditAccountTransaction(input) {
28
28
  executeResults,
29
29
  directTransfers,
30
30
  liquidationRemainingFunds,
31
- phantomTokens
31
+ phantomTokens,
32
+ withdrawCollateralEvents
32
33
  } = extractTransfers(logs, creditAccount, pool, creditFacade);
33
34
  const meta = {
34
35
  creditManager,
@@ -44,6 +45,7 @@ function parseCreditAccountTransaction(input) {
44
45
  underlying,
45
46
  liquidationRemainingFunds,
46
47
  phantomTokens,
48
+ withdrawCollateralEvents,
47
49
  strict
48
50
  }).map((o) => ({ ...o, ...meta }));
49
51
  const directOps = directTransfers.map((dt) => ({
@@ -1,5 +1,6 @@
1
1
  import type { Address } from "viem";
2
2
  import type { AddressMap, ChainContractsRegister } from "../sdk/index.js";
3
+ import type { WithdrawCollateralEventInfo } from "./extractTransfers.js";
3
4
  import type { ExecuteResult, FacadeParsedCall } from "./internal-types.js";
4
5
  import type { FacadeOperationMetadata, OuterFacadeOperation } from "./types.js";
5
6
  export interface AssembleOperationsInput {
@@ -9,6 +10,7 @@ export interface AssembleOperationsInput {
9
10
  underlying: Address;
10
11
  liquidationRemainingFunds?: bigint;
11
12
  phantomTokens?: AddressMap<Address>;
13
+ withdrawCollateralEvents?: WithdrawCollateralEventInfo[];
12
14
  strict?: boolean;
13
15
  }
14
16
  /**
@@ -1,5 +1,6 @@
1
1
  import { type Address, type Hex } from "viem";
2
2
  import type { AddressMap, ChainContractsRegister, ParsedCallV2 } from "../sdk/index.js";
3
+ import type { WithdrawCollateralEventInfo } from "./extractTransfers.js";
3
4
  import type { InnerOperation } from "./inner-operations.js";
4
5
  import type { ExecuteResult } from "./internal-types.js";
5
6
  export interface ClassifyMulticallOperationsInput {
@@ -11,6 +12,7 @@ export interface ClassifyMulticallOperationsInput {
11
12
  underlying: Address;
12
13
  strict?: boolean;
13
14
  phantomTokens?: AddressMap<Address>;
15
+ withdrawCollateralEvents?: WithdrawCollateralEventInfo[];
14
16
  }
15
17
  /**
16
18
  * Classifies each multicall inner call into a {@link InnerOperation}:
@@ -6,6 +6,9 @@ export declare class UnknownAdapterError extends Error {
6
6
  export declare class TransferAlignmentError extends Error {
7
7
  constructor(expected: number, actual: number);
8
8
  }
9
+ export declare class WithdrawCollateralAlignmentError extends Error {
10
+ constructor(expected: number, actual: number);
11
+ }
9
12
  export declare class ProtocolCallNotFoundError extends Error {
10
13
  readonly targetContract: Address;
11
14
  readonly executeIndex: number;
@@ -3,6 +3,19 @@ import { AddressMap } from "../sdk/index.js";
3
3
  import type { ExecuteResult } from "./internal-types.js";
4
4
  import type { DirectTransferInfo } from "./types.js";
5
5
  type RawLog = Log<bigint | number, number, false>;
6
+ /**
7
+ * Effective `withdrawCollateral` outcome decoded from the facade's
8
+ * `WithdrawCollateral` event.
9
+ */
10
+ export interface WithdrawCollateralEventInfo {
11
+ /**
12
+ * For regular withdrawals: the calldata token.
13
+ * For phantom withdrawals: the deposited (resolved) token.
14
+ */
15
+ token: Address;
16
+ amount: bigint;
17
+ to: Address;
18
+ }
6
19
  /**
7
20
  * Extracts per-adapter-call token balance changes and detects direct
8
21
  * incoming transfers to the credit account.
@@ -17,6 +30,12 @@ export interface ExtractTransfersResult {
17
30
  liquidationRemainingFunds?: bigint;
18
31
  /** Maps phantom token address to its deposited (underlying) token address. */
19
32
  phantomTokens: AddressMap<Address>;
33
+ /**
34
+ * One entry per facade `WithdrawCollateral` event targeting `creditAccount`,
35
+ * in transaction order. Used to recover the effective amount when the
36
+ * calldata uses the `type(uint256).max` "withdraw all" sentinel.
37
+ */
38
+ withdrawCollateralEvents: WithdrawCollateralEventInfo[];
20
39
  }
21
40
  export declare function extractTransfers(logs: RawLog[], creditAccount: Address, pool: Address, creditFacade: Address): ExtractTransfersResult;
22
41
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gearbox-protocol/sdk",
3
- "version": "14.5.6",
3
+ "version": "14.5.7",
4
4
  "description": "Gearbox SDK",
5
5
  "license": "MIT",
6
6
  "main": "./dist/cjs/sdk/index.js",