@gearbox-protocol/sdk 10.2.10 → 10.3.0

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.
@@ -0,0 +1,160 @@
1
+ const iWithdrawalCompressorV310Abi = [
2
+ {
3
+ type: "function",
4
+ inputs: [],
5
+ name: "contractType",
6
+ outputs: [{ name: "", internalType: "bytes32", type: "bytes32" }],
7
+ stateMutability: "view"
8
+ },
9
+ {
10
+ type: "function",
11
+ inputs: [
12
+ { name: "creditAccount", internalType: "address", type: "address" }
13
+ ],
14
+ name: "getCurrentWithdrawals",
15
+ outputs: [
16
+ {
17
+ name: "",
18
+ internalType: "struct ClaimableWithdrawal[]",
19
+ type: "tuple[]",
20
+ components: [
21
+ { name: "token", internalType: "address", type: "address" },
22
+ {
23
+ name: "withdrawalPhantomToken",
24
+ internalType: "address",
25
+ type: "address"
26
+ },
27
+ {
28
+ name: "withdrawalTokenSpent",
29
+ internalType: "uint256",
30
+ type: "uint256"
31
+ },
32
+ {
33
+ name: "outputs",
34
+ internalType: "struct WithdrawalOutput[]",
35
+ type: "tuple[]",
36
+ components: [
37
+ { name: "token", internalType: "address", type: "address" },
38
+ { name: "isDelayed", internalType: "bool", type: "bool" },
39
+ { name: "amount", internalType: "uint256", type: "uint256" }
40
+ ]
41
+ },
42
+ {
43
+ name: "claimCalls",
44
+ internalType: "struct MultiCall[]",
45
+ type: "tuple[]",
46
+ components: [
47
+ { name: "target", internalType: "address", type: "address" },
48
+ { name: "callData", internalType: "bytes", type: "bytes" }
49
+ ]
50
+ }
51
+ ]
52
+ },
53
+ {
54
+ name: "",
55
+ internalType: "struct PendingWithdrawal[]",
56
+ type: "tuple[]",
57
+ components: [
58
+ { name: "token", internalType: "address", type: "address" },
59
+ {
60
+ name: "withdrawalPhantomToken",
61
+ internalType: "address",
62
+ type: "address"
63
+ },
64
+ {
65
+ name: "expectedOutputs",
66
+ internalType: "struct WithdrawalOutput[]",
67
+ type: "tuple[]",
68
+ components: [
69
+ { name: "token", internalType: "address", type: "address" },
70
+ { name: "isDelayed", internalType: "bool", type: "bool" },
71
+ { name: "amount", internalType: "uint256", type: "uint256" }
72
+ ]
73
+ },
74
+ { name: "claimableAt", internalType: "uint256", type: "uint256" }
75
+ ]
76
+ }
77
+ ],
78
+ stateMutability: "view"
79
+ },
80
+ {
81
+ type: "function",
82
+ inputs: [
83
+ { name: "creditManager", internalType: "address", type: "address" }
84
+ ],
85
+ name: "getWithdrawableAssets",
86
+ outputs: [
87
+ {
88
+ name: "",
89
+ internalType: "struct WithdrawableAsset[]",
90
+ type: "tuple[]",
91
+ components: [
92
+ { name: "token", internalType: "address", type: "address" },
93
+ {
94
+ name: "withdrawalPhantomToken",
95
+ internalType: "address",
96
+ type: "address"
97
+ },
98
+ { name: "underlying", internalType: "address", type: "address" },
99
+ {
100
+ name: "withdrawalLength",
101
+ internalType: "uint256",
102
+ type: "uint256"
103
+ }
104
+ ]
105
+ }
106
+ ],
107
+ stateMutability: "view"
108
+ },
109
+ {
110
+ type: "function",
111
+ inputs: [
112
+ { name: "creditAccount", internalType: "address", type: "address" },
113
+ { name: "token", internalType: "address", type: "address" },
114
+ { name: "amount", internalType: "uint256", type: "uint256" }
115
+ ],
116
+ name: "getWithdrawalRequestResult",
117
+ outputs: [
118
+ {
119
+ name: "",
120
+ internalType: "struct RequestableWithdrawal",
121
+ type: "tuple",
122
+ components: [
123
+ { name: "token", internalType: "address", type: "address" },
124
+ { name: "amountIn", internalType: "uint256", type: "uint256" },
125
+ {
126
+ name: "outputs",
127
+ internalType: "struct WithdrawalOutput[]",
128
+ type: "tuple[]",
129
+ components: [
130
+ { name: "token", internalType: "address", type: "address" },
131
+ { name: "isDelayed", internalType: "bool", type: "bool" },
132
+ { name: "amount", internalType: "uint256", type: "uint256" }
133
+ ]
134
+ },
135
+ {
136
+ name: "requestCalls",
137
+ internalType: "struct MultiCall[]",
138
+ type: "tuple[]",
139
+ components: [
140
+ { name: "target", internalType: "address", type: "address" },
141
+ { name: "callData", internalType: "bytes", type: "bytes" }
142
+ ]
143
+ },
144
+ { name: "claimableAt", internalType: "uint256", type: "uint256" }
145
+ ]
146
+ }
147
+ ],
148
+ stateMutability: "view"
149
+ },
150
+ {
151
+ type: "function",
152
+ inputs: [],
153
+ name: "version",
154
+ outputs: [{ name: "", internalType: "uint256", type: "uint256" }],
155
+ stateMutability: "view"
156
+ }
157
+ ];
158
+ export {
159
+ iWithdrawalCompressorV310Abi
160
+ };
@@ -0,0 +1,85 @@
1
+ import { iWithdrawalCompressorV310Abi } from "../../abi/IWithdrawalCompressorV310.js";
2
+ import {
3
+ AddressMap,
4
+ BasePlugin,
5
+ getWithdrawalCompressorAddress
6
+ } from "../../sdk/index.js";
7
+ const MAP_LABEL = "delayedWithdrawal";
8
+ class DelayedWithdrawalPlugin extends BasePlugin {
9
+ #withdrawableAssets;
10
+ async load(force) {
11
+ if (!force && this.loaded) {
12
+ return this.state;
13
+ }
14
+ const compressor = getWithdrawalCompressorAddress(this.sdk.chainId);
15
+ this.sdk.logger?.debug(
16
+ `loading delayed withdrawal plugin with compressor ${compressor}`
17
+ );
18
+ const creditManagers = this.sdk.marketRegister.creditManagers;
19
+ const resp = await this.client.multicall({
20
+ contracts: compressor ? creditManagers.map(
21
+ (cm) => ({
22
+ abi: iWithdrawalCompressorV310Abi,
23
+ address: compressor,
24
+ functionName: "getWithdrawableAssets",
25
+ args: [cm.creditManager.address]
26
+ })
27
+ ) : [],
28
+ allowFailure: true
29
+ });
30
+ this.#withdrawableAssets = new AddressMap(void 0, MAP_LABEL);
31
+ resp.forEach((r, index) => {
32
+ const cm = creditManagers[index];
33
+ if (r.status === "success") {
34
+ this.#withdrawableAssets?.upsert(
35
+ cm.creditManager.address,
36
+ r.result.map((cfg) => ({
37
+ ...cfg,
38
+ creditManager: cm.creditManager.address
39
+ }))
40
+ );
41
+ } else {
42
+ }
43
+ });
44
+ return this.state;
45
+ }
46
+ get loaded() {
47
+ return !!this.#withdrawableAssets;
48
+ }
49
+ /**
50
+ * Returns a map of cmAddress -> array of delayed assets
51
+ * @throws if plugin is not attached
52
+ */
53
+ get withdrawableAssets() {
54
+ if (!this.#withdrawableAssets) {
55
+ throw new Error("withdrawable assets plugin not attached");
56
+ }
57
+ return this.#withdrawableAssets;
58
+ }
59
+ stateHuman(_) {
60
+ return this.withdrawableAssets.values().flatMap((cm) => {
61
+ const cmAssets = cm.map((a) => {
62
+ return {
63
+ address: a.creditManager,
64
+ version: this.version,
65
+ ...a
66
+ };
67
+ });
68
+ return cmAssets;
69
+ });
70
+ }
71
+ get state() {
72
+ return {
73
+ withdrawableAssets: this.withdrawableAssets.asRecord()
74
+ };
75
+ }
76
+ hydrate(state) {
77
+ this.#withdrawableAssets = new AddressMap(
78
+ Object.entries(state.withdrawableAssets),
79
+ MAP_LABEL
80
+ );
81
+ }
82
+ }
83
+ export {
84
+ DelayedWithdrawalPlugin
85
+ };
@@ -0,0 +1,2 @@
1
+ export * from "./DelayedWithdrawalPlugin.js";
2
+ export * from "./types.js";
@@ -0,0 +1 @@
1
+ {"type": "module","sideEffects":false}
File without changes
@@ -12,7 +12,7 @@ class AbstractMigrateCreditAccountsService extends SDKConstruct {
12
12
  #logger;
13
13
  #version;
14
14
  #service;
15
- // TODO: any better way to handle this?
15
+ // TODO: HARDCODED
16
16
  static V300_TO_V310_TOKENS_OVERRIDES = {
17
17
  [CHAINS.Mainnet.id]: {
18
18
  // stkcvxRLUSD_USDC
@@ -23,17 +23,15 @@ class AbstractMigrateCreditAccountsService extends SDKConstruct {
23
23
  ["0xcB5D10A57Aeb622b92784D53F730eE2210ab370E".toLowerCase()]: "0x00F7C0d39B05089e93858A82439EA17dE7160B5a".toLowerCase()
24
24
  }
25
25
  };
26
+ // TODO: HARDCODED
26
27
  static accountMigratorBot = "0x286Fe53994f5668D56538Aa10eaa3Ac36f878e9C".toLowerCase();
27
- // "0xc19ddEbDEB7Ba119eB9F23d079dcEaBC1B25B41f".toLowerCase() as Address;
28
+ // TODO: HARDCODED
28
29
  static accountMigratorPreviewer = "0x6523B8c9daB92eea7944a79b4Dbb598c7934DCca".toLowerCase();
29
- // "0x5514de935f39AB0a137b4A1c984c872513C02f29".toLowerCase() as Address;
30
- // "0xe6d2A2477722Af204899cfd3257A43aDAE1Ea264".toLowerCase() as Address;
31
- // 0x99B63E7030e6f066731CF4e166e87D1D18e98B45.toLowerCase() as Address;
32
30
  constructor(sdk, version) {
33
31
  super(sdk);
34
32
  this.#version = version;
35
33
  this.#service = createCreditAccountService(this.sdk, version);
36
- this.#logger = childLogger("CreditAccountsService", sdk.logger);
34
+ this.#logger = childLogger("MigrateCreditAccountsService", sdk.logger);
37
35
  this.#logger?.debug(
38
36
  `Created MigrateCreditAccountsService with version: ${this.#version}`
39
37
  );
@@ -3,6 +3,7 @@ import { iBotListV310Abi } from "../../abi/310/generated.js";
3
3
  import { creditAccountCompressorAbi } from "../../abi/compressors/creditAccountCompressor.js";
4
4
  import { peripheryCompressorAbi } from "../../abi/compressors/peripheryCompressor.js";
5
5
  import { rewardsCompressorAbi } from "../../abi/compressors/rewardsCompressor.js";
6
+ import { iWithdrawalCompressorV310Abi } from "../../abi/IWithdrawalCompressorV310.js";
6
7
  import { iBaseRewardPoolAbi } from "../../abi/iBaseRewardPool.js";
7
8
  import {
8
9
  iBotListV300Abi,
@@ -22,10 +23,14 @@ import {
22
23
  RAY,
23
24
  VERSION_RANGE_310
24
25
  } from "../constants/index.js";
25
- import { BigIntMath } from "../index.js";
26
26
  import { assetsMap } from "../router/index.js";
27
+ import { BigIntMath } from "../sdk-legacy/index.js";
27
28
  import { AddressMap, childLogger } from "../utils/index.js";
28
29
  import { simulateWithPriceUpdates } from "../utils/viem/index.js";
30
+ function getWithdrawalCompressorAddress(chainId) {
31
+ const compressor = chainId === 1 ? "0xfB79b6713fe214B8748ED7b0db1f93E4f1aC9d29" : void 0;
32
+ return compressor;
33
+ }
29
34
  class AbstractCreditAccountService extends SDKConstruct {
30
35
  #compressor;
31
36
  #batchSize;
@@ -478,34 +483,93 @@ class AbstractCreditAccountService extends SDKConstruct {
478
483
  const tx = cm.creditFacade.multicall(creditAccount.creditAccount, calls);
479
484
  return { tx, calls, creditFacade: cm.creditFacade };
480
485
  }
486
+ /**
487
+ * Preview delayed withdrawal for given token
488
+ * @param props - {@link PreviewDelayedWithdrawalProps}
489
+ * @returns
490
+ */
491
+ async previewDelayedWithdrawal({
492
+ creditAccount,
493
+ amount,
494
+ token
495
+ }) {
496
+ const compressor = getWithdrawalCompressorAddress(this.sdk.chainId);
497
+ if (!compressor)
498
+ throw new Error(
499
+ `No compressor for current chain ${this.sdk.networkType}`
500
+ );
501
+ const contract = getContract({
502
+ address: compressor,
503
+ abi: iWithdrawalCompressorV310Abi,
504
+ client: this.client
505
+ });
506
+ const resp = await contract.read.getWithdrawalRequestResult([
507
+ creditAccount,
508
+ token,
509
+ amount
510
+ ]);
511
+ return resp;
512
+ }
513
+ /**
514
+ * Get claimable and pending withdrawals of an account
515
+ * @param props - {@link GetPendingWithdrawalsProps}
516
+ * @returns
517
+ */
518
+ async getPendingWithdrawals({
519
+ creditAccount
520
+ }) {
521
+ const compressor = getWithdrawalCompressorAddress(this.sdk.chainId);
522
+ if (!compressor)
523
+ throw new Error(
524
+ `No compressor for current chain ${this.sdk.networkType}`
525
+ );
526
+ const contract = getContract({
527
+ address: compressor,
528
+ abi: iWithdrawalCompressorV310Abi,
529
+ client: this.client
530
+ });
531
+ const resp = await contract.read.getCurrentWithdrawals([creditAccount]);
532
+ const claimableNow = resp?.[0] || [];
533
+ const pendingResult = [...resp?.[1] || []].sort(
534
+ (a, b) => a.claimableAt < b.claimableAt ? -1 : 1
535
+ );
536
+ const respResult = {
537
+ claimableNow: [...claimableNow],
538
+ pending: pendingResult
539
+ };
540
+ return respResult;
541
+ }
481
542
  /**
482
543
  * Start delayed withdrawal for given token
483
544
  - Withdrawal is executed in the following order: price update -> execute withdraw calls -> update quotas
484
545
  * @param props - {@link StartDelayedWithdrawalProps}
485
546
  * @returns
486
547
  */
487
- async startDelayedWithdrawal_Mellow({
548
+ async startDelayedWithdrawal({
488
549
  creditAccount,
489
550
  minQuota,
490
551
  averageQuota,
491
- instantWithdrawals,
492
- delayedWithdrawals,
493
- sourceAmount,
494
- sourceToken
552
+ preview
495
553
  }) {
496
554
  const cm = this.sdk.marketRegister.findCreditManager(
497
555
  creditAccount.creditManager
498
556
  );
499
- const balances = [...instantWithdrawals, ...delayedWithdrawals].filter(
500
- (a) => a.balance > 0
501
- );
557
+ const record = preview.outputs.reduce((acc, o) => {
558
+ const token = o.token.toLowerCase();
559
+ acc[token] = (acc[token] || 0n) + o.amount;
560
+ return acc;
561
+ }, {});
562
+ const balances = Object.entries(record).filter(([, a]) => a > 10n);
502
563
  const storeExpectedBalances = {
503
564
  target: cm.creditFacade.address,
504
565
  callData: encodeFunctionData({
505
566
  abi: iCreditFacadeV300MulticallAbi,
506
567
  functionName: "storeExpectedBalances",
507
568
  args: [
508
- balances.map((a) => ({ token: a.token, amount: a.balance - 10n }))
569
+ balances.map(([token, amount]) => ({
570
+ token,
571
+ amount: BigIntMath.max(0n, amount - 10n)
572
+ }))
509
573
  ]
510
574
  })
511
575
  };
@@ -522,38 +586,10 @@ class AbstractCreditAccountService extends SDKConstruct {
522
586
  creditAccount,
523
587
  desiredQuotas: averageQuota
524
588
  });
525
- const mellowAdapter = cm.creditManager.adapters.mustGet(sourceToken);
526
- const redeem = {
527
- target: mellowAdapter.address,
528
- callData: encodeFunctionData({
529
- abi: ierc4626AdapterAbi,
530
- functionName: "redeem",
531
- args: [sourceAmount, ADDRESS_0X0, ADDRESS_0X0]
532
- })
533
- };
534
- const CLAIMER = "0x25024a3017B8da7161d8c5DCcF768F8678fB5802";
535
- const mellowClaimerAdapter = cm.creditManager.adapters.mustGet(CLAIMER);
536
- const multiAcceptContract = getContract({
537
- address: mellowClaimerAdapter.address,
538
- abi: iMellowClaimerAdapterAbi,
539
- client: this.client
540
- });
541
- const indices = await multiAcceptContract.read.getMultiVaultSubvaultIndices(
542
- [sourceToken]
543
- );
544
- const multiaccept = {
545
- target: mellowClaimerAdapter.address,
546
- callData: encodeFunctionData({
547
- abi: iMellowClaimerAdapterAbi,
548
- functionName: "multiAccept",
549
- args: [sourceToken, ...indices]
550
- })
551
- };
552
589
  const calls = [
553
590
  ...priceUpdatesCalls,
554
591
  storeExpectedBalances,
555
- redeem,
556
- multiaccept,
592
+ ...preview.requestCalls,
557
593
  compareBalances,
558
594
  ...this.prepareUpdateQuotas(creditAccount.creditFacade, {
559
595
  minQuota,
@@ -569,24 +605,35 @@ class AbstractCreditAccountService extends SDKConstruct {
569
605
  * @param props - {@link ClaimDelayedProps}
570
606
  * @returns
571
607
  */
572
- async claimDelayed_Mellow({
608
+ async claimDelayed({
573
609
  creditAccount,
574
610
  minQuota,
575
611
  averageQuota,
576
- sourceToken,
577
- phantom,
578
- target
612
+ claimableNow
579
613
  }) {
614
+ const zeroDebt = creditAccount.debt === 0n;
580
615
  const cm = this.sdk.marketRegister.findCreditManager(
581
616
  creditAccount.creditManager
582
617
  );
618
+ const record = claimableNow.outputs.reduce(
619
+ (acc, o) => {
620
+ const token = o.token.toLowerCase();
621
+ acc[token] = (acc[token] || 0n) + o.amount;
622
+ return acc;
623
+ },
624
+ {}
625
+ );
626
+ const balances = Object.entries(record).filter(([, a]) => a > 10n);
583
627
  const storeExpectedBalances = {
584
628
  target: cm.creditFacade.address,
585
629
  callData: encodeFunctionData({
586
630
  abi: iCreditFacadeV300MulticallAbi,
587
631
  functionName: "storeExpectedBalances",
588
632
  args: [
589
- [target].map((a) => ({ token: a.token, amount: a.balance - 10n }))
633
+ balances.map(([token, amount]) => ({
634
+ token,
635
+ amount: BigIntMath.max(0n, amount - 10n)
636
+ }))
590
637
  ]
591
638
  })
592
639
  };
@@ -598,39 +645,21 @@ class AbstractCreditAccountService extends SDKConstruct {
598
645
  args: []
599
646
  })
600
647
  };
601
- const priceUpdatesCalls = await this.getPriceUpdatesForFacade({
648
+ const priceUpdatesCalls = zeroDebt ? [] : await this.getPriceUpdatesForFacade({
602
649
  creditManager: creditAccount.creditManager,
603
650
  creditAccount,
604
651
  desiredQuotas: averageQuota
605
652
  });
606
- const CLAIMER = "0x25024a3017B8da7161d8c5DCcF768F8678fB5802";
607
- const mellowClaimerAdapter = cm.creditManager.adapters.mustGet(CLAIMER);
608
- const multiAcceptContract = getContract({
609
- address: mellowClaimerAdapter.address,
610
- abi: iMellowClaimerAdapterAbi,
611
- client: this.client
653
+ const quotaCalls = zeroDebt ? [] : this.prepareUpdateQuotas(creditAccount.creditFacade, {
654
+ minQuota,
655
+ averageQuota
612
656
  });
613
- const indices = await multiAcceptContract.read.getUserSubvaultIndices([
614
- sourceToken,
615
- creditAccount.creditAccount
616
- ]);
617
- const multiaccept = {
618
- target: mellowClaimerAdapter.address,
619
- callData: encodeFunctionData({
620
- abi: iMellowClaimerAdapterAbi,
621
- functionName: "multiAcceptAndClaim",
622
- args: [sourceToken, ...indices, ADDRESS_0X0, phantom.balance]
623
- })
624
- };
625
657
  const calls = [
626
658
  ...priceUpdatesCalls,
627
659
  storeExpectedBalances,
628
- multiaccept,
660
+ ...claimableNow.claimCalls,
629
661
  compareBalances,
630
- ...this.prepareUpdateQuotas(creditAccount.creditFacade, {
631
- minQuota,
632
- averageQuota
633
- })
662
+ ...quotaCalls
634
663
  ];
635
664
  const tx = cm.creditFacade.multicall(creditAccount.creditAccount, calls);
636
665
  return { tx, calls, creditFacade: cm.creditFacade };
@@ -1134,19 +1163,7 @@ const iMellowClaimerAdapterAbi = [
1134
1163
  stateMutability: "nonpayable"
1135
1164
  }
1136
1165
  ];
1137
- const ierc4626AdapterAbi = [
1138
- {
1139
- type: "function",
1140
- inputs: [
1141
- { name: "shares", internalType: "uint256", type: "uint256" },
1142
- { name: "", internalType: "address", type: "address" },
1143
- { name: "", internalType: "address", type: "address" }
1144
- ],
1145
- name: "redeem",
1146
- outputs: [{ name: "useSafePrices", internalType: "bool", type: "bool" }],
1147
- stateMutability: "nonpayable"
1148
- }
1149
- ];
1150
1166
  export {
1151
- AbstractCreditAccountService
1167
+ AbstractCreditAccountService,
1168
+ getWithdrawalCompressorAddress
1152
1169
  };