@gearbox-protocol/sdk 0.0.99 → 0.0.102

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 (86) hide show
  1. package/lib/apy/convexAPY.d.ts +8 -0
  2. package/lib/apy/convexAPY.js +202 -0
  3. package/lib/apy/lidoAPY.d.ts +4 -0
  4. package/lib/apy/lidoAPY.js +104 -0
  5. package/lib/config.d.ts +1 -0
  6. package/lib/config.js +2 -1
  7. package/lib/contracts/contracts.d.ts +6 -1
  8. package/lib/contracts/contracts.js +52 -14
  9. package/lib/contracts/contractsRegister.js +16 -4
  10. package/lib/core/constants.d.ts +6 -0
  11. package/lib/core/constants.js +10 -4
  12. package/lib/core/creditAccount.d.ts +3 -1
  13. package/lib/core/creditAccount.js +31 -31
  14. package/lib/core/creditManager.d.ts +13 -2
  15. package/lib/core/creditManager.js +79 -29
  16. package/lib/core/errors.d.ts +10 -0
  17. package/lib/core/errors.js +16 -1
  18. package/lib/core/events.js +9 -9
  19. package/lib/core/multicall.d.ts +1 -1
  20. package/lib/core/pool.d.ts +1 -1
  21. package/lib/core/pool.js +7 -5
  22. package/lib/core/price.d.ts +2 -0
  23. package/lib/core/price.js +9 -0
  24. package/lib/core/strategy.d.ts +38 -0
  25. package/lib/core/strategy.js +56 -0
  26. package/lib/index.d.ts +7 -1
  27. package/lib/index.js +8 -3
  28. package/lib/pathfinder/path.js +1 -1
  29. package/lib/pathfinder/yVault.js +5 -5
  30. package/lib/payload/creditAccount.d.ts +4 -26
  31. package/lib/payload/creditManager.d.ts +3 -25
  32. package/lib/payload/pool.d.ts +2 -17
  33. package/lib/payload/pool.js +0 -1
  34. package/lib/tokens/token.js +8 -8
  35. package/lib/utils/formatter.d.ts +1 -0
  36. package/lib/utils/formatter.js +6 -1
  37. package/lib/utils/mappers.d.ts +2 -1
  38. package/lib/utils/mappers.js +13 -5
  39. package/lib/utils/multicall.js +4 -3
  40. package/lib/utils/types.d.ts +1 -0
  41. package/package.json +1 -1
  42. package/src/apy/convexAPY.ts +250 -0
  43. package/src/apy/lidoAPY.ts +88 -0
  44. package/src/config.ts +2 -1
  45. package/src/contracts/contracts.ts +69 -16
  46. package/src/contracts/contractsRegister.ts +19 -4
  47. package/src/core/constants.ts +10 -3
  48. package/src/core/creditAccount.ts +46 -37
  49. package/src/core/creditManager.ts +231 -148
  50. package/src/core/errors.ts +24 -0
  51. package/src/core/events.ts +921 -915
  52. package/src/core/multicall.ts +1 -1
  53. package/src/core/pool.ts +56 -51
  54. package/src/core/price.ts +9 -0
  55. package/src/core/strategy.ts +130 -0
  56. package/src/index.ts +8 -1
  57. package/src/pathfinder/path.ts +154 -154
  58. package/src/pathfinder/yVault.ts +63 -62
  59. package/src/payload/creditAccount.ts +4 -26
  60. package/src/payload/creditManager.ts +4 -26
  61. package/src/payload/pool.ts +2 -19
  62. package/src/tokens/token.ts +14 -9
  63. package/src/utils/formatter.ts +5 -1
  64. package/src/utils/mappers.ts +12 -5
  65. package/src/utils/multicall.ts +4 -9
  66. package/src/utils/types.ts +6 -2
  67. package/lib/core/adapters.d.ts +0 -15
  68. package/lib/core/adapters.js +0 -19
  69. package/lib/core/contracts.d.ts +0 -67
  70. package/lib/core/contracts.js +0 -254
  71. package/lib/core/contractsRegister.d.ts +0 -2
  72. package/lib/core/contractsRegister.js +0 -58
  73. package/lib/core/creditCard.d.ts +0 -13
  74. package/lib/core/creditCard.js +0 -2
  75. package/lib/core/oracles.d.ts +0 -38
  76. package/lib/core/oracles.js +0 -12
  77. package/lib/core/priceFeeds.d.ts +0 -3
  78. package/lib/core/priceFeeds.js +0 -492
  79. package/lib/core/protocols.d.ts +0 -13
  80. package/lib/core/protocols.js +0 -39
  81. package/lib/core/swap.d.ts +0 -4
  82. package/lib/core/swap.js +0 -8
  83. package/lib/core/trade.d.ts +0 -35
  84. package/lib/core/trade.js +0 -62
  85. package/lib/core/tradeTypes.d.ts +0 -79
  86. package/lib/core/tradeTypes.js +0 -21
@@ -1,174 +1,257 @@
1
- import {BigNumber, ethers, Signer} from "ethers";
2
- import {formatBN} from "../utils/formatter";
1
+ import { BigNumber, ethers, Signer } from "ethers";
3
2
  import {
4
- PERCENTAGE_FACTOR,
5
- RAY,
6
- UNDERLYING_TOKEN_LIQUIDATION_THRESHOLD
7
- } from "./constants";
8
- import {
9
- CreditManagerDataPayload,
10
- CreditManagerStatPayload
3
+ CreditManagerDataPayload,
4
+ CreditManagerStatPayload
11
5
  } from "../payload/creditManager";
12
- import {ICreditManager, ICreditManager__factory} from "../types";
6
+
7
+ import {
8
+ ICreditManager,
9
+ ICreditManager__factory,
10
+ ICreditFacade__factory
11
+ } from "../types";
12
+
13
+ import { MultiCall } from "./multicall";
14
+ import {
15
+ PERCENTAGE_FACTOR,
16
+ RAY,
17
+ UNDERLYING_TOKEN_LIQUIDATION_THRESHOLD,
18
+ LEVERAGE_DECIMALS,
19
+ PERCENTAGE_DECIMALS
20
+ } from "./constants";
21
+ import { OpenAccountError } from "./errors";
13
22
 
14
23
  export class CreditManagerData {
15
- public readonly id: string;
16
- public readonly address: string;
17
- public readonly underlyingToken: string;
18
- public readonly isWETH: boolean;
19
- public readonly canBorrow: boolean;
20
- public readonly borrowRate: number;
21
- public readonly minAmount: BigNumber;
22
- public readonly maxAmount: BigNumber;
23
- public readonly maxLeverageFactor: number;
24
- public readonly availableLiquidity: BigNumber;
25
- public readonly allowedTokens: Array<string>;
26
- public readonly adapters: Record<string, string> = {};
27
- public readonly version: number = 1;
28
-
29
- constructor(payload: CreditManagerDataPayload) {
30
- this.id = payload.addr;
31
- this.address = payload.addr;
32
-
33
- this.underlyingToken = payload.underlyingToken || "";
34
- this.isWETH = payload.isWETH || false;
35
- this.canBorrow = payload.canBorrow || false;
36
- this.borrowRate =
37
- BigNumber.from(payload.borrowRate || 0)
38
- .mul(PERCENTAGE_FACTOR)
39
- .mul(100)
40
- .div(RAY)
41
- .toNumber() / PERCENTAGE_FACTOR;
42
- this.minAmount = BigNumber.from(payload.minAmount || 0);
43
- this.maxAmount = BigNumber.from(payload.maxAmount || 0);
44
- this.maxLeverageFactor = BigNumber.from(
45
- payload.maxLeverageFactor || 0
46
- ).toNumber();
47
- this.availableLiquidity = BigNumber.from(payload.availableLiquidity || 0);
48
- this.allowedTokens = payload.allowedTokens || [];
49
- payload.adapters?.forEach(a => {
50
- this.adapters[a.allowedContract] = a.adapter;
51
- });
52
- }
53
-
54
- validateOpenAccount(
55
- balance: BigNumber,
56
- decimals: number,
57
- amount_BN: BigNumber,
58
- leverage: number
59
- ): string | null {
60
- if (balance.lt(amount_BN)) return "Insufficient funds";
61
-
62
- if (amount_BN.lt(this.minAmount))
63
- return `Amount is less than minimal (${formatBN(
64
- this.minAmount,
65
- decimals
66
- )})`;
67
-
68
- if (amount_BN.gt(this.maxAmount))
69
- return `Amount is greater than maximum (${formatBN(
70
- this.maxAmount,
71
- decimals
72
- )})`;
73
-
74
- if (leverage > this.maxLeverageFactor) return `Leverage is bigger than max`;
75
-
76
- if (amount_BN.mul(leverage).div(100).gt(this.availableLiquidity))
77
- return "Insufficient liquidity in the pool";
78
-
79
- return null;
80
- }
81
-
82
- getContractETH(
83
- signer: Signer | ethers.providers.Provider
84
- ): ICreditManager {
85
- return ICreditManager__factory.connect(this.address, signer);
86
- }
87
-
88
- get isPaused(): boolean {
89
- return false;
90
- }
24
+ public readonly id: string;
25
+ public readonly address: string;
26
+ public readonly underlyingToken: string;
27
+ public readonly isWETH: boolean;
28
+ public readonly canBorrow: boolean;
29
+ public readonly borrowRate: number;
30
+ public readonly minAmount: BigNumber;
31
+ public readonly maxAmount: BigNumber;
32
+ public readonly maxLeverageFactor: number; // for V1 only
33
+ public readonly availableLiquidity: BigNumber;
34
+ public readonly allowedTokens: Array<string>;
35
+ public readonly adapters: Record<string, string>;
36
+
37
+ public readonly liquidationThresholds: Record<string, BigNumber>;
38
+ public readonly version: number;
39
+ public readonly creditFacade: string; // V2 only: address of creditFacade
40
+ public readonly isDegenMode: boolean; // V2 only: true if contract is in Degen mode
41
+ public readonly degenNFT: string; // V2 only: degenNFT, address(0) if not in degen mode
42
+ public readonly isIncreaseDebtForbidden: boolean; // V2 only: true if increasing debt is forbidden
43
+ public readonly forbiddenTokenMask: BigNumber; // V2 only: mask which forbids some particular tokens
44
+
45
+ constructor(payload: CreditManagerDataPayload) {
46
+ this.id = payload.addr;
47
+ this.address = payload.addr;
48
+
49
+ this.underlyingToken = payload.underlying || "";
50
+
51
+ this.isWETH = payload.isWETH || false;
52
+ this.canBorrow = payload.canBorrow || false;
53
+
54
+ this.borrowRate =
55
+ BigNumber.from(payload.borrowRate || 0)
56
+ .mul(PERCENTAGE_FACTOR)
57
+ .mul(PERCENTAGE_DECIMALS)
58
+ .div(RAY)
59
+ .toNumber() / PERCENTAGE_FACTOR;
60
+ this.minAmount = BigNumber.from(payload.minAmount || 0);
61
+ this.maxAmount = BigNumber.from(payload.maxAmount || 0);
62
+
63
+ this.maxLeverageFactor = BigNumber.from(
64
+ payload.maxLeverageFactor || 0
65
+ ).toNumber();
66
+ this.availableLiquidity = BigNumber.from(payload.availableLiquidity || 0);
67
+
68
+ this.allowedTokens = payload.collateralTokens || [];
69
+ this.adapters = (payload.adapters || []).reduce<Record<string, string>>(
70
+ (acc, { allowedContract, adapter }) => ({
71
+ ...acc,
72
+ [allowedContract]: adapter
73
+ }),
74
+ {}
75
+ );
76
+
77
+ this.liquidationThresholds = (payload.liquidationThresholds || []).reduce<
78
+ Record<string, BigNumber>
79
+ >((acc, threshold, index) => {
80
+ const address = payload.collateralTokens[index];
81
+
82
+ if (address) acc[address.toLowerCase()] = BigNumber.from(threshold);
83
+
84
+ return acc;
85
+ }, {});
86
+
87
+ this.version = BigNumber.from(payload.version || 1).toNumber();
88
+ this.creditFacade = payload.creditFacade || "";
89
+ this.isDegenMode = payload.isDegenMode || false;
90
+ this.degenNFT = payload.degenNFT || "";
91
+ this.isIncreaseDebtForbidden = payload.isIncreaseDebtForbidden || false;
92
+ this.forbiddenTokenMask = BigNumber.from(payload.forbiddenTokenMask || 0);
93
+ }
94
+
95
+ get isPaused(): boolean {
96
+ return false;
97
+ }
98
+
99
+ getContractETH(signer: Signer | ethers.providers.Provider): ICreditManager {
100
+ return ICreditManager__factory.connect(this.address, signer);
101
+ }
102
+
103
+ contractToAdapter(contractAddress: string): string | undefined {
104
+ return this.adapters[contractAddress];
105
+ }
106
+
107
+ encodeAddCollateral(
108
+ accountAddress: string,
109
+ tokenAddress: string,
110
+ amount: BigNumber
111
+ ): MultiCall {
112
+ if (this.version !== 2)
113
+ throw new Error("Multicall is eligible only for version 2");
114
+ return {
115
+ target: this.creditFacade,
116
+ callData: ICreditFacade__factory.createInterface().encodeFunctionData(
117
+ "addCollateral",
118
+ [accountAddress, tokenAddress, amount]
119
+ )
120
+ };
121
+ }
122
+
123
+ encodeIncreaseDebt(amount: BigNumber): MultiCall {
124
+ if (this.version !== 2)
125
+ throw new Error("Multicall is eligible only for version 2");
126
+ return {
127
+ target: this.creditFacade,
128
+ callData: ICreditFacade__factory.createInterface().encodeFunctionData(
129
+ "increaseDebt",
130
+ [amount]
131
+ )
132
+ };
133
+ }
134
+
135
+ encodeDecreaseDebt(amount: BigNumber): MultiCall {
136
+ if (this.version !== 2)
137
+ throw new Error("Multicall is eligible only for version 2");
138
+ return {
139
+ target: this.creditFacade,
140
+ callData: ICreditFacade__factory.createInterface().encodeFunctionData(
141
+ "decreaseDebt",
142
+ [amount]
143
+ )
144
+ };
145
+ }
146
+
147
+ validateOpenAccount(totalAmount: BigNumber, leverage: number): true {
148
+ if (totalAmount.lt(this.minAmount))
149
+ throw new OpenAccountError("amountLessMin", this.minAmount);
150
+
151
+ if (totalAmount.gt(this.maxAmount))
152
+ throw new OpenAccountError("amountGreaterMax", this.maxAmount);
153
+
154
+ if (leverage > this.maxLeverageFactor)
155
+ throw new OpenAccountError(
156
+ "leverageGreaterMax",
157
+ BigNumber.from(this.maxLeverageFactor)
158
+ );
159
+
160
+ if (
161
+ totalAmount
162
+ .mul(leverage)
163
+ .div(LEVERAGE_DECIMALS)
164
+ .gt(this.availableLiquidity)
165
+ )
166
+ throw new OpenAccountError(
167
+ "insufficientPoolLiquidity",
168
+ BigNumber.from(this.availableLiquidity)
169
+ );
170
+
171
+ return true;
172
+ }
91
173
  }
92
174
 
93
175
  export function calcMaxIncreaseBorrow(
94
- healthFactor: number,
95
- borrowAmountPlusInterest: BigNumber,
96
- maxLeverageFactor: number
176
+ healthFactor: number,
177
+ borrowAmountPlusInterest: BigNumber,
178
+ maxLeverageFactor: number
97
179
  ): BigNumber {
98
- const healthFactorPercentage = Math.floor(healthFactor * PERCENTAGE_FACTOR);
180
+ const healthFactorPercentage = Math.floor(healthFactor * PERCENTAGE_FACTOR);
99
181
 
100
- const minHealthFactor = Math.floor(
101
- (UNDERLYING_TOKEN_LIQUIDATION_THRESHOLD * (maxLeverageFactor + 100)) /
102
- maxLeverageFactor
103
- );
182
+ const minHealthFactor = Math.floor(
183
+ (UNDERLYING_TOKEN_LIQUIDATION_THRESHOLD *
184
+ (maxLeverageFactor + LEVERAGE_DECIMALS)) /
185
+ maxLeverageFactor
186
+ );
104
187
 
105
- const result = borrowAmountPlusInterest
106
- .mul(healthFactorPercentage - minHealthFactor)
107
- .div(minHealthFactor - UNDERLYING_TOKEN_LIQUIDATION_THRESHOLD);
108
- return result.isNegative() ? BigNumber.from(0) : result;
188
+ const result = borrowAmountPlusInterest
189
+ .mul(healthFactorPercentage - minHealthFactor)
190
+ .div(minHealthFactor - UNDERLYING_TOKEN_LIQUIDATION_THRESHOLD);
191
+ return result.isNegative() ? BigNumber.from(0) : result;
109
192
  }
110
193
 
111
194
  export function calcHealthFactorAfterIncreasingBorrow(
112
- healthFactor: number | undefined,
113
- borrowAmountPlusInterest: BigNumber | undefined,
114
- additional: BigNumber
195
+ healthFactor: number | undefined,
196
+ borrowAmountPlusInterest: BigNumber | undefined,
197
+ additional: BigNumber
115
198
  ): number {
116
- if (!healthFactor || !borrowAmountPlusInterest) return 0;
199
+ if (!healthFactor || !borrowAmountPlusInterest) return 0;
117
200
 
118
- const healthFactorPercentage = Math.floor(healthFactor * PERCENTAGE_FACTOR);
201
+ const healthFactorPercentage = Math.floor(healthFactor * PERCENTAGE_FACTOR);
119
202
 
120
- return (
121
- borrowAmountPlusInterest
122
- .mul(healthFactorPercentage)
123
- .add(additional.mul(UNDERLYING_TOKEN_LIQUIDATION_THRESHOLD))
124
- .div(borrowAmountPlusInterest.add(additional))
125
- .toNumber() / PERCENTAGE_FACTOR
126
- );
203
+ return (
204
+ borrowAmountPlusInterest
205
+ .mul(healthFactorPercentage)
206
+ .add(additional.mul(UNDERLYING_TOKEN_LIQUIDATION_THRESHOLD))
207
+ .div(borrowAmountPlusInterest.add(additional))
208
+ .toNumber() / PERCENTAGE_FACTOR
209
+ );
127
210
  }
128
211
 
129
212
  export function calcHealthFactorAfterAddingCollateral(
130
- healthFactor: number | undefined,
131
- borrowAmountPlusInterest: BigNumber | undefined,
132
- additionalCollateral: BigNumber
213
+ healthFactor: number | undefined,
214
+ borrowAmountPlusInterest: BigNumber | undefined,
215
+ additionalCollateral: BigNumber
133
216
  ): number {
134
- if (!healthFactor || !borrowAmountPlusInterest) return 0;
217
+ if (!healthFactor || !borrowAmountPlusInterest) return 0;
135
218
 
136
- const healthFactorPercentage = Math.floor(healthFactor * PERCENTAGE_FACTOR);
219
+ const healthFactorPercentage = Math.floor(healthFactor * PERCENTAGE_FACTOR);
137
220
 
138
- return (
139
- borrowAmountPlusInterest
140
- .mul(healthFactorPercentage)
141
- .add(additionalCollateral.mul(UNDERLYING_TOKEN_LIQUIDATION_THRESHOLD))
142
- .div(borrowAmountPlusInterest)
143
- .toNumber() / PERCENTAGE_FACTOR
144
- );
221
+ return (
222
+ borrowAmountPlusInterest
223
+ .mul(healthFactorPercentage)
224
+ .add(additionalCollateral.mul(UNDERLYING_TOKEN_LIQUIDATION_THRESHOLD))
225
+ .div(borrowAmountPlusInterest)
226
+ .toNumber() / PERCENTAGE_FACTOR
227
+ );
145
228
  }
146
229
 
147
230
  export class CreditManagerStat extends CreditManagerData {
148
- public readonly uniqueUsers: number;
149
- public readonly openedAccountsCount: number;
150
- public readonly totalOpenedAccounts: number;
151
- public readonly totalClosedAccounts: number;
152
- public readonly totalRepaidAccounts: number;
153
- public readonly totalLiquidatedAccounts: number;
154
- public readonly totalBorrowed: BigNumber;
155
- public readonly cumulativeBorrowed: BigNumber;
156
- public readonly totalRepaid: BigNumber;
157
- public readonly totalProfit: BigNumber;
158
- public readonly totalLosses: BigNumber;
159
-
160
- constructor(payload: CreditManagerStatPayload) {
161
- super(payload);
162
- this.uniqueUsers = payload.uniqueUsers;
163
- this.openedAccountsCount = payload.openedAccountsCount || 0;
164
- this.totalOpenedAccounts = payload.totalOpenedAccounts || 0;
165
- this.totalClosedAccounts = payload.totalClosedAccounts || 0;
166
- this.totalRepaidAccounts = payload.totalRepaidAccounts || 0;
167
- this.totalLiquidatedAccounts = payload.totalLiquidatedAccounts || 0;
168
- this.totalBorrowed = BigNumber.from(payload.totalBorrowed || 0);
169
- this.cumulativeBorrowed = BigNumber.from(payload.cumulativeBorrowed || 0);
170
- this.totalRepaid = BigNumber.from(payload.totalRepaid || 0);
171
- this.totalProfit = BigNumber.from(payload.totalProfit || 0);
172
- this.totalLosses = BigNumber.from(payload.totalLosses || 0);
173
- }
231
+ public readonly uniqueUsers: number;
232
+ public readonly openedAccountsCount: number;
233
+ public readonly totalOpenedAccounts: number;
234
+ public readonly totalClosedAccounts: number;
235
+ public readonly totalRepaidAccounts: number;
236
+ public readonly totalLiquidatedAccounts: number;
237
+ public readonly totalBorrowed: BigNumber;
238
+ public readonly cumulativeBorrowed: BigNumber;
239
+ public readonly totalRepaid: BigNumber;
240
+ public readonly totalProfit: BigNumber;
241
+ public readonly totalLosses: BigNumber;
242
+
243
+ constructor(payload: CreditManagerStatPayload) {
244
+ super(payload);
245
+ this.uniqueUsers = payload.uniqueUsers;
246
+ this.openedAccountsCount = payload.openedAccountsCount || 0;
247
+ this.totalOpenedAccounts = payload.totalOpenedAccounts || 0;
248
+ this.totalClosedAccounts = payload.totalClosedAccounts || 0;
249
+ this.totalRepaidAccounts = payload.totalRepaidAccounts || 0;
250
+ this.totalLiquidatedAccounts = payload.totalLiquidatedAccounts || 0;
251
+ this.totalBorrowed = BigNumber.from(payload.totalBorrowed || 0);
252
+ this.cumulativeBorrowed = BigNumber.from(payload.cumulativeBorrowed || 0);
253
+ this.totalRepaid = BigNumber.from(payload.totalRepaid || 0);
254
+ this.totalProfit = BigNumber.from(payload.totalProfit || 0);
255
+ this.totalLosses = BigNumber.from(payload.totalLosses || 0);
256
+ }
174
257
  }
@@ -1,3 +1,5 @@
1
+ import { BigNumber } from "ethers";
2
+
1
3
  export interface MetamaskError {
2
4
  code: number;
3
5
  message: string;
@@ -43,3 +45,25 @@ export class AccountsInAlllCreditManagersError extends Error {
43
45
  super("errors.youOpenedAccountsInAllCreditManagersError");
44
46
  }
45
47
  }
48
+
49
+ export type OpenAccountErrorTypes =
50
+ | "insufficientPoolLiquidity"
51
+ | "leverageGreaterMax"
52
+ | "amountGreaterMax"
53
+ | "amountLessMin";
54
+
55
+ export class OpenAccountError extends Error {
56
+ message: OpenAccountErrorTypes;
57
+ payload: { amount: BigNumber };
58
+
59
+ constructor(errorType: OpenAccountErrorTypes, amount: BigNumber) {
60
+ super();
61
+ Object.setPrototypeOf(this, OpenAccountError.prototype);
62
+ this.message = errorType;
63
+ this.payload = { amount };
64
+ }
65
+
66
+ static isOpenAccountError(e: unknown): e is OpenAccountError {
67
+ return e instanceof OpenAccountError;
68
+ }
69
+ }