@gearbox-protocol/sdk 14.12.0-next.30 → 14.12.0-next.32

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.
@@ -22,70 +22,106 @@ __export(buildDelayedPreview_exports, {
22
22
  });
23
23
  module.exports = __toCommonJS(buildDelayedPreview_exports);
24
24
  var import_viem = require("viem");
25
+ var import_common_utils = require("../../common-utils/index.js");
25
26
  var import_sdk = require("../../sdk/index.js");
26
27
  var import_types = require("./types.js");
27
- function buildDelayedPreview(state, before, detected, convert) {
28
+ function buildDelayedPreview(afterInstant, before, detected, convert) {
28
29
  const { request, intent } = detected;
29
- const post = state.clone();
30
+ const post = afterInstant.clone();
31
+ const converter = makeSafeConverter(convert);
32
+ const claimed = applyClaim(post, request);
33
+ const collateralWithdrawn = new import_sdk.AssetsMap();
34
+ switch (intent?.type) {
35
+ case "CLOSE_ACCOUNT":
36
+ return buildClosePreview(post, converter);
37
+ case "DECREASE_LEVERAGE":
38
+ repayFromClaim(post, request.claimToken, converter.convert, claimed);
39
+ break;
40
+ case "WITHDRAW_COLLATERAL": {
41
+ const withdrawn = import_common_utils.BigIntMath.min(
42
+ intent.withdrawAmount,
43
+ post.balances.getOrZero(intent.withdrawToken)
44
+ );
45
+ if (withdrawn > 0n) {
46
+ post.balances.dec(intent.withdrawToken, withdrawn);
47
+ collateralWithdrawn.upsert(intent.withdrawToken, withdrawn);
48
+ }
49
+ const claimSpentOnWithdrawal = (0, import_viem.isAddressEqual)(
50
+ intent.withdrawToken,
51
+ request.claimToken
52
+ ) ? withdrawn : 0n;
53
+ repayFromClaim(
54
+ post,
55
+ request.claimToken,
56
+ converter.convert,
57
+ import_common_utils.BigIntMath.max(claimed - claimSpentOnWithdrawal, 0n)
58
+ );
59
+ break;
60
+ }
61
+ default:
62
+ break;
63
+ }
64
+ return buildAdjustPreview(post, before, collateralWithdrawn, converter);
65
+ }
66
+ function makeSafeConverter(convert) {
30
67
  let error;
31
- const safeConvert = (token, to, amount) => {
32
- try {
33
- return convert(token, to, amount);
34
- } catch {
35
- error ??= {
36
- code: import_types.ERROR_UNPRICEABLE_TOKEN,
37
- message: `cannot price token ${token}`
38
- };
39
- return 0n;
68
+ return {
69
+ convert: (token, to, amount) => {
70
+ try {
71
+ return convert(token, to, amount);
72
+ } catch {
73
+ error ??= {
74
+ code: import_types.ERROR_UNPRICEABLE_TOKEN,
75
+ message: `cannot price token ${token}`
76
+ };
77
+ return 0n;
78
+ }
79
+ },
80
+ get error() {
81
+ return error;
40
82
  }
41
83
  };
84
+ }
85
+ function applyClaim(post, request) {
42
86
  const claimed = post.balances.getOrZero(request.phantomToken);
43
87
  post.balances.upsert(request.phantomToken, 0n);
44
88
  post.quotas.upsert(request.phantomToken, 0n);
45
89
  post.balances.inc(request.claimToken, claimed);
46
- if (intent?.type === "CLOSE_ACCOUNT") {
47
- const totalValue2 = post.balances.sum(
48
- (token, balance) => balance > 0n ? safeConvert(token, post.underlying, balance) : 0n
49
- );
50
- const receivedAmount = totalValue2 > post.totalDebt ? totalValue2 - post.totalDebt : 0n;
51
- const preview2 = {
52
- operation: "CloseCreditAccount",
53
- permanent: true,
54
- creditManager: post.creditManager,
55
- creditAccount: post.creditAccount,
56
- receivedAmount,
57
- error
58
- };
59
- return preview2;
90
+ return claimed;
91
+ }
92
+ function repayFromClaim(post, claimToken, convert, amount) {
93
+ const spent = import_common_utils.BigIntMath.min(amount, post.balances.getOrZero(claimToken));
94
+ if (spent <= 0n) {
95
+ return;
60
96
  }
61
- const collateralWithdrawn = new import_sdk.AssetsMap();
62
- const repayFromClaim = (amount) => {
63
- const available = post.balances.getOrZero(request.claimToken);
64
- const spent = amount > available ? available : amount;
65
- if (spent <= 0n) {
66
- return;
67
- }
68
- const received = safeConvert(request.claimToken, post.underlying, spent);
69
- post.balances.dec(request.claimToken, spent);
70
- post.balances.inc(post.underlying, received);
71
- post.repay(received);
97
+ const received = convert(claimToken, post.underlying, spent);
98
+ post.balances.dec(claimToken, spent);
99
+ post.balances.inc(post.underlying, received);
100
+ post.repay(received);
101
+ }
102
+ function totalValueInUnderlying(post, convert, dust) {
103
+ return post.balances.sum(
104
+ (token, balance) => balance > dust ? convert(token, post.underlying, balance) : 0n
105
+ );
106
+ }
107
+ function buildClosePreview(post, converter) {
108
+ const totalValue = totalValueInUnderlying(post, converter.convert, 0n);
109
+ return {
110
+ operation: "CloseCreditAccount",
111
+ permanent: false,
112
+ creditManager: post.creditManager,
113
+ creditAccount: post.creditAccount,
114
+ receivedAmount: import_common_utils.BigIntMath.max(totalValue - post.totalDebt, 0n),
115
+ error: converter.error
72
116
  };
73
- if (intent?.type === "DECREASE_LEVERAGE") {
74
- repayFromClaim(claimed);
75
- } else if (intent?.type === "WITHDRAW_COLLATERAL") {
76
- const running = post.balances.getOrZero(intent.withdrawToken);
77
- const withdrawn = intent.withdrawAmount > running ? running : intent.withdrawAmount;
78
- if (withdrawn > 0n) {
79
- post.balances.dec(intent.withdrawToken, withdrawn);
80
- collateralWithdrawn.upsert(intent.withdrawToken, withdrawn);
81
- }
82
- const remainingClaim = (0, import_viem.isAddressEqual)(intent.withdrawToken, request.claimToken) && claimed > withdrawn ? claimed - withdrawn : claimed;
83
- repayFromClaim(remainingClaim);
84
- }
85
- const totalValue = post.balances.sum(
86
- (token, balance) => balance > import_types.PREVIEW_DUST ? safeConvert(token, post.underlying, balance) : 0n
117
+ }
118
+ function buildAdjustPreview(post, before, collateralWithdrawn, converter) {
119
+ const totalValue = totalValueInUnderlying(
120
+ post,
121
+ converter.convert,
122
+ import_types.PREVIEW_DUST
87
123
  );
88
- const preview = {
124
+ return {
89
125
  operation: "AdjustCreditAccount",
90
126
  creditManager: post.creditManager,
91
127
  creditAccount: post.creditAccount,
@@ -101,9 +137,8 @@ function buildDelayedPreview(state, before, detected, convert) {
101
137
  quotasChange: post.quotas.difference(before.quotas).toAssets(),
102
138
  assets: post.balances.toAssets(import_types.PREVIEW_DUST),
103
139
  assetsChange: post.balances.difference(before.balances).toAssets(import_types.PREVIEW_DUST),
104
- error
140
+ error: converter.error
105
141
  };
106
- return preview;
107
142
  }
108
143
  // Annotate the CommonJS export names for ESM import in node:
109
144
  0 && (module.exports = {
@@ -50,23 +50,27 @@ function getKeyForPoolPointsInfo(i) {
50
50
  class PoolPointsAPI {
51
51
  constructor() {
52
52
  }
53
+ static defaultBackendUrl = "https://api.gearbox.foundation";
53
54
  static async getTotalTokensOnProtocol({
54
55
  tokensToCheck,
55
56
  tokensList,
56
- network
57
+ network,
58
+ backendUrl = PoolPointsAPI.defaultBackendUrl
57
59
  }) {
58
60
  const list = [...new Set(tokensToCheck)];
59
61
  const res = await Promise.allSettled(
60
- list.map((t) => PoolPointsAPI.getTokenTotal(t, network, tokensList))
62
+ list.map(
63
+ (t) => PoolPointsAPI.getTokenTotal(t, network, tokensList, backendUrl)
64
+ )
61
65
  );
62
66
  return res.map((r, i) => [
63
67
  list[i],
64
68
  r
65
69
  ]);
66
70
  }
67
- static async getTokenTotal(token, network, tokensList) {
71
+ static async getTokenTotal(token, network, tokensList, backendUrl) {
68
72
  const chainId = import_sdk.chains[network]?.id;
69
- const url = `https://api.gearbox.foundation/v1/getBalanceAt?asset=${token}&chainId=${chainId}`;
73
+ const url = `${backendUrl}/v1/getBalanceAt?asset=${token}&chainId=${chainId}`;
70
74
  const result = await import_axios.default.get(url);
71
75
  const balance = result.data.result.reduce(
72
76
  (sum, r) => r.effective_balance + sum,
@@ -620,10 +620,12 @@ class CreditAccountsServiceV310 extends import_base.SDKConstruct {
620
620
  assetsToWithdraw,
621
621
  to
622
622
  }) {
623
+ const unwrapCalls = await this.getRedeemDiffCalls(1n, ca.creditManager) ?? [];
623
624
  return [
624
625
  ...routerCalls,
625
626
  ...this.#prepareDisableQuotas(ca),
626
627
  ...this.#prepareDecreaseDebt(ca),
628
+ ...unwrapCalls,
627
629
  ...assetsToWithdraw.map(
628
630
  (t) => this.#prepareWithdrawToken(ca.creditFacade, t, import_constants.MAX_UINT256, to)
629
631
  )
@@ -1,71 +1,107 @@
1
1
  import { isAddressEqual } from "viem";
2
+ import { BigIntMath } from "../../common-utils/index.js";
2
3
  import { AssetsMap } from "../../sdk/index.js";
3
4
  import {
4
5
  ERROR_UNPRICEABLE_TOKEN,
5
6
  PREVIEW_DUST
6
7
  } from "./types.js";
7
- function buildDelayedPreview(state, before, detected, convert) {
8
+ function buildDelayedPreview(afterInstant, before, detected, convert) {
8
9
  const { request, intent } = detected;
9
- const post = state.clone();
10
+ const post = afterInstant.clone();
11
+ const converter = makeSafeConverter(convert);
12
+ const claimed = applyClaim(post, request);
13
+ const collateralWithdrawn = new AssetsMap();
14
+ switch (intent?.type) {
15
+ case "CLOSE_ACCOUNT":
16
+ return buildClosePreview(post, converter);
17
+ case "DECREASE_LEVERAGE":
18
+ repayFromClaim(post, request.claimToken, converter.convert, claimed);
19
+ break;
20
+ case "WITHDRAW_COLLATERAL": {
21
+ const withdrawn = BigIntMath.min(
22
+ intent.withdrawAmount,
23
+ post.balances.getOrZero(intent.withdrawToken)
24
+ );
25
+ if (withdrawn > 0n) {
26
+ post.balances.dec(intent.withdrawToken, withdrawn);
27
+ collateralWithdrawn.upsert(intent.withdrawToken, withdrawn);
28
+ }
29
+ const claimSpentOnWithdrawal = isAddressEqual(
30
+ intent.withdrawToken,
31
+ request.claimToken
32
+ ) ? withdrawn : 0n;
33
+ repayFromClaim(
34
+ post,
35
+ request.claimToken,
36
+ converter.convert,
37
+ BigIntMath.max(claimed - claimSpentOnWithdrawal, 0n)
38
+ );
39
+ break;
40
+ }
41
+ default:
42
+ break;
43
+ }
44
+ return buildAdjustPreview(post, before, collateralWithdrawn, converter);
45
+ }
46
+ function makeSafeConverter(convert) {
10
47
  let error;
11
- const safeConvert = (token, to, amount) => {
12
- try {
13
- return convert(token, to, amount);
14
- } catch {
15
- error ??= {
16
- code: ERROR_UNPRICEABLE_TOKEN,
17
- message: `cannot price token ${token}`
18
- };
19
- return 0n;
48
+ return {
49
+ convert: (token, to, amount) => {
50
+ try {
51
+ return convert(token, to, amount);
52
+ } catch {
53
+ error ??= {
54
+ code: ERROR_UNPRICEABLE_TOKEN,
55
+ message: `cannot price token ${token}`
56
+ };
57
+ return 0n;
58
+ }
59
+ },
60
+ get error() {
61
+ return error;
20
62
  }
21
63
  };
64
+ }
65
+ function applyClaim(post, request) {
22
66
  const claimed = post.balances.getOrZero(request.phantomToken);
23
67
  post.balances.upsert(request.phantomToken, 0n);
24
68
  post.quotas.upsert(request.phantomToken, 0n);
25
69
  post.balances.inc(request.claimToken, claimed);
26
- if (intent?.type === "CLOSE_ACCOUNT") {
27
- const totalValue2 = post.balances.sum(
28
- (token, balance) => balance > 0n ? safeConvert(token, post.underlying, balance) : 0n
29
- );
30
- const receivedAmount = totalValue2 > post.totalDebt ? totalValue2 - post.totalDebt : 0n;
31
- const preview2 = {
32
- operation: "CloseCreditAccount",
33
- permanent: true,
34
- creditManager: post.creditManager,
35
- creditAccount: post.creditAccount,
36
- receivedAmount,
37
- error
38
- };
39
- return preview2;
70
+ return claimed;
71
+ }
72
+ function repayFromClaim(post, claimToken, convert, amount) {
73
+ const spent = BigIntMath.min(amount, post.balances.getOrZero(claimToken));
74
+ if (spent <= 0n) {
75
+ return;
40
76
  }
41
- const collateralWithdrawn = new AssetsMap();
42
- const repayFromClaim = (amount) => {
43
- const available = post.balances.getOrZero(request.claimToken);
44
- const spent = amount > available ? available : amount;
45
- if (spent <= 0n) {
46
- return;
47
- }
48
- const received = safeConvert(request.claimToken, post.underlying, spent);
49
- post.balances.dec(request.claimToken, spent);
50
- post.balances.inc(post.underlying, received);
51
- post.repay(received);
77
+ const received = convert(claimToken, post.underlying, spent);
78
+ post.balances.dec(claimToken, spent);
79
+ post.balances.inc(post.underlying, received);
80
+ post.repay(received);
81
+ }
82
+ function totalValueInUnderlying(post, convert, dust) {
83
+ return post.balances.sum(
84
+ (token, balance) => balance > dust ? convert(token, post.underlying, balance) : 0n
85
+ );
86
+ }
87
+ function buildClosePreview(post, converter) {
88
+ const totalValue = totalValueInUnderlying(post, converter.convert, 0n);
89
+ return {
90
+ operation: "CloseCreditAccount",
91
+ permanent: false,
92
+ creditManager: post.creditManager,
93
+ creditAccount: post.creditAccount,
94
+ receivedAmount: BigIntMath.max(totalValue - post.totalDebt, 0n),
95
+ error: converter.error
52
96
  };
53
- if (intent?.type === "DECREASE_LEVERAGE") {
54
- repayFromClaim(claimed);
55
- } else if (intent?.type === "WITHDRAW_COLLATERAL") {
56
- const running = post.balances.getOrZero(intent.withdrawToken);
57
- const withdrawn = intent.withdrawAmount > running ? running : intent.withdrawAmount;
58
- if (withdrawn > 0n) {
59
- post.balances.dec(intent.withdrawToken, withdrawn);
60
- collateralWithdrawn.upsert(intent.withdrawToken, withdrawn);
61
- }
62
- const remainingClaim = isAddressEqual(intent.withdrawToken, request.claimToken) && claimed > withdrawn ? claimed - withdrawn : claimed;
63
- repayFromClaim(remainingClaim);
64
- }
65
- const totalValue = post.balances.sum(
66
- (token, balance) => balance > PREVIEW_DUST ? safeConvert(token, post.underlying, balance) : 0n
97
+ }
98
+ function buildAdjustPreview(post, before, collateralWithdrawn, converter) {
99
+ const totalValue = totalValueInUnderlying(
100
+ post,
101
+ converter.convert,
102
+ PREVIEW_DUST
67
103
  );
68
- const preview = {
104
+ return {
69
105
  operation: "AdjustCreditAccount",
70
106
  creditManager: post.creditManager,
71
107
  creditAccount: post.creditAccount,
@@ -81,9 +117,8 @@ function buildDelayedPreview(state, before, detected, convert) {
81
117
  quotasChange: post.quotas.difference(before.quotas).toAssets(),
82
118
  assets: post.balances.toAssets(PREVIEW_DUST),
83
119
  assetsChange: post.balances.difference(before.balances).toAssets(PREVIEW_DUST),
84
- error
120
+ error: converter.error
85
121
  };
86
- return preview;
87
122
  }
88
123
  export {
89
124
  buildDelayedPreview
@@ -20,23 +20,27 @@ function getKeyForPoolPointsInfo(i) {
20
20
  class PoolPointsAPI {
21
21
  constructor() {
22
22
  }
23
+ static defaultBackendUrl = "https://api.gearbox.foundation";
23
24
  static async getTotalTokensOnProtocol({
24
25
  tokensToCheck,
25
26
  tokensList,
26
- network
27
+ network,
28
+ backendUrl = PoolPointsAPI.defaultBackendUrl
27
29
  }) {
28
30
  const list = [...new Set(tokensToCheck)];
29
31
  const res = await Promise.allSettled(
30
- list.map((t) => PoolPointsAPI.getTokenTotal(t, network, tokensList))
32
+ list.map(
33
+ (t) => PoolPointsAPI.getTokenTotal(t, network, tokensList, backendUrl)
34
+ )
31
35
  );
32
36
  return res.map((r, i) => [
33
37
  list[i],
34
38
  r
35
39
  ]);
36
40
  }
37
- static async getTokenTotal(token, network, tokensList) {
41
+ static async getTokenTotal(token, network, tokensList, backendUrl) {
38
42
  const chainId = chains[network]?.id;
39
- const url = `https://api.gearbox.foundation/v1/getBalanceAt?asset=${token}&chainId=${chainId}`;
43
+ const url = `${backendUrl}/v1/getBalanceAt?asset=${token}&chainId=${chainId}`;
40
44
  const result = await axios.get(url);
41
45
  const balance = result.data.result.reduce(
42
46
  (sum, r) => r.effective_balance + sum,
@@ -616,10 +616,12 @@ class CreditAccountsServiceV310 extends SDKConstruct {
616
616
  assetsToWithdraw,
617
617
  to
618
618
  }) {
619
+ const unwrapCalls = await this.getRedeemDiffCalls(1n, ca.creditManager) ?? [];
619
620
  return [
620
621
  ...routerCalls,
621
622
  ...this.#prepareDisableQuotas(ca),
622
623
  ...this.#prepareDecreaseDebt(ca),
624
+ ...unwrapCalls,
623
625
  ...assetsToWithdraw.map(
624
626
  (t) => this.#prepareWithdrawToken(ca.creditFacade, t, MAX_UINT256, to)
625
627
  )
@@ -31,11 +31,12 @@ export type ConvertFn = (token: Address, to: Address, amount: bigint) => bigint;
31
31
  *
32
32
  * The changes (`debtChange`, `quotasChange`, `assetsChange`) are reported
33
33
  * relative to the account state before the whole transaction, not the
34
- * post-instant state: to the user the delayed preview answers "where will
34
+ * post-instant-part state: to the user the delayed preview answers "where will
35
35
  * the account end up compared to now", so the transient phantom token
36
36
  * (minted by the instant part, burned by the claim) nets out to nothing.
37
37
  *
38
- * @param state - Account state after the instant part of the transaction.
38
+ * @param afterInstant - Account state after the instant part of the
39
+ * transaction.
39
40
  * @param before - Account state before the transaction (the diff base).
40
41
  */
41
- export declare function buildDelayedPreview(state: CreditAccountState, before: CreditAccountState, detected: DetectedDelayedOperation, convert: ConvertFn): InstantOperationPreview;
42
+ export declare function buildDelayedPreview(afterInstant: CreditAccountState, before: CreditAccountState, detected: DetectedDelayedOperation, convert: ConvertFn): InstantOperationPreview;
@@ -12,6 +12,7 @@ export interface GetTotalTokensOnProtocolProps {
12
12
  tokensToCheck: Array<Address>;
13
13
  tokensList: Record<Address, TokenData>;
14
14
  network: NetworkType;
15
+ backendUrl?: string;
15
16
  }
16
17
  export type PoolPointsBase = Record<Address, Array<{
17
18
  key: string;
@@ -21,7 +22,8 @@ export type PoolPointsBase = Record<Address, Array<{
21
22
  export declare function getKeyForPoolPointsInfo(i: PoolPointsInfo<string>): string;
22
23
  export declare class PoolPointsAPI {
23
24
  private constructor();
24
- static getTotalTokensOnProtocol({ tokensToCheck, tokensList, network, }: GetTotalTokensOnProtocolProps): Promise<[`0x${string}`, PromiseSettledResult<Asset>][]>;
25
+ private static defaultBackendUrl;
26
+ static getTotalTokensOnProtocol({ tokensToCheck, tokensList, network, backendUrl, }: GetTotalTokensOnProtocolProps): Promise<[`0x${string}`, PromiseSettledResult<Asset>][]>;
25
27
  private static getTokenTotal;
26
28
  static getPointsByPool({ poolRewards, totalTokenBalances, pools, tokensList, }: GetPointsByPoolProps): PoolPointsBase;
27
29
  private static getPoolTokenPoints;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gearbox-protocol/sdk",
3
- "version": "14.12.0-next.30",
3
+ "version": "14.12.0-next.32",
4
4
  "description": "Gearbox SDK",
5
5
  "license": "MIT",
6
6
  "repository": {