@gearbox-protocol/sdk 3.0.0-next.126 → 3.0.0-next.128

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.
@@ -27,6 +27,12 @@ const APY_DICTIONARY = {
27
27
  crvUSDETHCRV: "factory-tricrypto-4",
28
28
  rETH_f: "factory-crypto-210",
29
29
  wstETHCRV: "unknown",
30
+ "2CRV": "unknown",
31
+ "3c-crvUSD": "unknown",
32
+ crvUSDC: "unknown",
33
+ crvUSDT: "unknown",
34
+ crvUSDC_e: "unknown",
35
+ "3CRV": "unknown", // 0xEfDE221f306152971D8e9f181bFe998447975810
30
36
  };
31
37
  // const CRYPTO = "https://api.curve.fi/api/getPools/ethereum/crypto";
32
38
  // const FACTORY = "https://api.curve.fi/api/getPools/ethereum/factory";
@@ -40,6 +40,7 @@ export interface CalcQuotaUpdateProps {
40
40
  initialQuotas: Record<string, Pick<CaTokenBalance, "quota">>;
41
41
  liquidationThresholds: Record<string, bigint>;
42
42
  assetsAfterUpdate: Record<string, AssetWithAmountInTarget>;
43
+ maxDebt: bigint;
43
44
  allowedToSpend: Record<string, {}>;
44
45
  allowedToObtain: Record<string, {}>;
45
46
  quotaReserve: bigint;
@@ -120,7 +121,8 @@ export declare class CreditAccountData {
120
121
  static calcHealthFactor({ assets, quotas, quotasInfo, liquidationThresholds, underlyingToken, debt, prices, }: CalcHealthFactorProps): number;
121
122
  static calcRecommendedQuota({ amount, debt, lt, quotaReserve, }: CalcRecommendedQuotaProps): bigint;
122
123
  static calcDefaultQuota({ amount, lt, quotaReserve }: CalcDefaultQuotaProps): bigint;
123
- static calcQuotaUpdate({ quotas, initialQuotas, assetsAfterUpdate, liquidationThresholds, allowedToSpend, allowedToObtain, quotaReserve, }: CalcQuotaUpdateProps): CalcQuotaUpdateReturnType;
124
+ static calcQuotaUpdate(props: CalcQuotaUpdateProps): CalcQuotaUpdateReturnType;
125
+ private static getSingleQuotaChange;
124
126
  static calcQuotaBorrowRate({ quotas, quotaRates }: CalcQuotaBorrowRateProps): bigint;
125
127
  static calcRelativeBaseBorrowRate({ debt, baseRateWithFee, assetAmountInUnderlying, totalValue, }: CalcRelativeBaseBorrowRateProps): bigint;
126
128
  static liquidationPrice({ liquidationThresholds, debt, underlyingToken, targetToken, assets, }: LiquidationPriceProps): bigint;
@@ -239,56 +239,81 @@ class CreditAccountData {
239
239
  sdk_gov_1.PERCENTAGE_FACTOR;
240
240
  return recommendedQuota;
241
241
  }
242
- static calcQuotaUpdate({ quotas, initialQuotas, assetsAfterUpdate, liquidationThresholds, allowedToSpend, allowedToObtain, quotaReserve, }) {
243
- const r = Object.values(quotas).reduce((acc, cmQuota) => {
242
+ static calcQuotaUpdate(props) {
243
+ const { quotas, initialQuotas, maxDebt, allowedToSpend, allowedToObtain } = props;
244
+ const quotaDecrease = Object.keys(allowedToSpend).reduce((acc, token) => {
245
+ const ch = CreditAccountData.getSingleQuotaChange(token, 0n, props);
246
+ if (ch)
247
+ acc[ch.token] = ch;
248
+ return acc;
249
+ }, {});
250
+ const quotaCap = maxDebt * 2n;
251
+ const quotaBought = Object.values(initialQuotas).reduce((sum, q) => sum + (q?.quota || 0n), 0n);
252
+ const quotaReduced = Object.values(quotaDecrease).reduce((sum, q) => sum + (q.balance || 0n), 0n);
253
+ const maxQuotaIncrease = math_1.BigIntMath.max(quotaCap - (quotaBought + quotaReduced), 0n);
254
+ const quotaIncrease = Object.keys(allowedToObtain).reduce((acc, token) => {
255
+ const ch = CreditAccountData.getSingleQuotaChange(token, maxQuotaIncrease, props);
256
+ if (ch)
257
+ acc[ch.token] = ch;
258
+ return acc;
259
+ }, {});
260
+ const quotaChange = {
261
+ ...quotaDecrease,
262
+ ...quotaIncrease,
263
+ };
264
+ const desiredQuota = Object.values(quotas).reduce((acc, cmQuota) => {
244
265
  const { token, isActive } = cmQuota;
245
266
  const { quota: initialQuota = 0n } = initialQuotas[token] || {};
246
267
  if (!isActive) {
247
- acc.desiredQuota[token] = {
268
+ acc[token] = {
248
269
  balance: initialQuota,
249
270
  token,
250
271
  };
251
- return acc;
252
- }
253
- // min(debt,assetAmountInUnderlying*LT)*(1+buffer)
254
- const after = assetsAfterUpdate[token];
255
- const { amountInTarget = 0n } = after || {};
256
- const lt = liquidationThresholds[token] || 0n;
257
- const desiredQuota = this.calcDefaultQuota({
258
- lt,
259
- quotaReserve,
260
- amount: amountInTarget,
261
- });
262
- const quotaChange = desiredQuota - initialQuota;
263
- const correctIncrease = after && allowedToObtain[token] && quotaChange > 0;
264
- const correctDecrease = after && allowedToSpend[token] && quotaChange < 0;
265
- if (correctIncrease || correctDecrease) {
266
- acc.desiredQuota[token] = {
267
- balance: desiredQuota,
268
- token,
269
- };
270
272
  }
271
273
  else {
272
- acc.desiredQuota[token] = {
273
- balance: initialQuota,
274
+ const change = quotaChange[token]?.balance || 0n;
275
+ const quotaAfter = initialQuota + change;
276
+ acc[token] = {
277
+ balance: quotaAfter,
274
278
  token,
275
279
  };
276
280
  }
277
- if (correctIncrease) {
278
- acc.quotaIncrease.push({
279
- balance: quotaChange,
280
- token,
281
- });
282
- }
283
- if (correctDecrease) {
284
- acc.quotaDecrease.push({
285
- balance: quotaChange,
286
- token,
287
- });
288
- }
289
281
  return acc;
290
- }, { desiredQuota: {}, quotaIncrease: [], quotaDecrease: [] });
291
- return r;
282
+ }, {});
283
+ return {
284
+ desiredQuota,
285
+ quotaDecrease: Object.values(quotaDecrease),
286
+ quotaIncrease: Object.values(quotaIncrease),
287
+ };
288
+ }
289
+ static getSingleQuotaChange(token, maxQuotaIncrease, props) {
290
+ const { isActive = false } = props.quotas[token] || {};
291
+ const { quota: initialQuota = 0n } = props.initialQuotas[token] || {};
292
+ if (!isActive) {
293
+ return undefined;
294
+ }
295
+ // min(debt,assetAmountInUnderlying*LT)*(1+buffer)
296
+ const assetAfter = props.assetsAfterUpdate[token];
297
+ const { amountInTarget = 0n } = assetAfter || {};
298
+ const lt = props.liquidationThresholds[token] || 0n;
299
+ const defaultQuota = this.calcDefaultQuota({
300
+ lt,
301
+ quotaReserve: props.quotaReserve,
302
+ amount: amountInTarget,
303
+ });
304
+ const unsafeQuotaChange = defaultQuota - initialQuota;
305
+ const quotaChange = unsafeQuotaChange > 0
306
+ ? math_1.BigIntMath.min(maxQuotaIncrease, unsafeQuotaChange)
307
+ : unsafeQuotaChange;
308
+ const correctIncrease = assetAfter && props.allowedToObtain[token] && quotaChange > 0;
309
+ const correctDecrease = assetAfter && props.allowedToSpend[token] && quotaChange < 0;
310
+ if (correctIncrease || correctDecrease) {
311
+ return {
312
+ balance: quotaChange,
313
+ token,
314
+ };
315
+ }
316
+ return undefined;
292
317
  }
293
318
  static calcQuotaBorrowRate({ quotas, quotaRates }) {
294
319
  const totalRateBalance = Object.values(quotas).reduce((acc, { token, balance }) => {
@@ -422,9 +422,11 @@ const DEFAULT_LT = {
422
422
  [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: sdk_gov_1.PERCENTAGE_FACTOR,
423
423
  [sdk_gov_1.tokenDataByNetwork.Mainnet.STETH]: sdk_gov_1.PERCENTAGE_FACTOR,
424
424
  };
425
+ const HUGE_MAX_DEBT = 20n;
425
426
  describe("CreditAccount calcQuotaUpdate test", () => {
426
427
  it("open account should buy quota", () => {
427
428
  const result = creditAccount_1.CreditAccountData.calcQuotaUpdate({
429
+ maxDebt: HUGE_MAX_DEBT,
428
430
  quotaReserve: QUOTA_RESERVE,
429
431
  quotas: cmQuotas,
430
432
  initialQuotas: {},
@@ -475,6 +477,7 @@ describe("CreditAccount calcQuotaUpdate test", () => {
475
477
  });
476
478
  it("add collateral should buy quota", () => {
477
479
  const result = creditAccount_1.CreditAccountData.calcQuotaUpdate({
480
+ maxDebt: HUGE_MAX_DEBT,
478
481
  quotaReserve: QUOTA_RESERVE,
479
482
  quotas: cmQuotas,
480
483
  initialQuotas: caQuota,
@@ -515,6 +518,7 @@ describe("CreditAccount calcQuotaUpdate test", () => {
515
518
  });
516
519
  it("add collateral should add additional quota", () => {
517
520
  const result = creditAccount_1.CreditAccountData.calcQuotaUpdate({
521
+ maxDebt: HUGE_MAX_DEBT,
518
522
  quotaReserve: QUOTA_RESERVE,
519
523
  quotas: cmQuotas,
520
524
  initialQuotas: caQuota,
@@ -555,6 +559,7 @@ describe("CreditAccount calcQuotaUpdate test", () => {
555
559
  });
556
560
  it("add collateral shouldn't add additional quota", () => {
557
561
  const result = creditAccount_1.CreditAccountData.calcQuotaUpdate({
562
+ maxDebt: HUGE_MAX_DEBT,
558
563
  quotaReserve: QUOTA_RESERVE,
559
564
  quotas: cmQuotas,
560
565
  initialQuotas: caQuota,
@@ -590,6 +595,7 @@ describe("CreditAccount calcQuotaUpdate test", () => {
590
595
  });
591
596
  it("swap should buy quota", () => {
592
597
  const result = creditAccount_1.CreditAccountData.calcQuotaUpdate({
598
+ maxDebt: HUGE_MAX_DEBT,
593
599
  quotaReserve: QUOTA_RESERVE,
594
600
  quotas: cmQuotas,
595
601
  initialQuotas: caQuota,
@@ -635,8 +641,9 @@ describe("CreditAccount calcQuotaUpdate test", () => {
635
641
  },
636
642
  });
637
643
  });
638
- it("swap should add additional quota", () => {
644
+ it("swap should buy additional quota", () => {
639
645
  const result = creditAccount_1.CreditAccountData.calcQuotaUpdate({
646
+ maxDebt: HUGE_MAX_DEBT,
640
647
  quotaReserve: QUOTA_RESERVE,
641
648
  quotas: cmQuotas,
642
649
  initialQuotas: caQuota,
@@ -687,8 +694,9 @@ describe("CreditAccount calcQuotaUpdate test", () => {
687
694
  },
688
695
  });
689
696
  });
690
- it("swap shouldn't add additional quota", () => {
697
+ it("swap shouldn't buy additional quota", () => {
691
698
  const result = creditAccount_1.CreditAccountData.calcQuotaUpdate({
699
+ maxDebt: HUGE_MAX_DEBT,
692
700
  quotaReserve: QUOTA_RESERVE,
693
701
  quotas: cmQuotas,
694
702
  initialQuotas: caQuota,
@@ -734,6 +742,7 @@ describe("CreditAccount calcQuotaUpdate test", () => {
734
742
  });
735
743
  it("shouldn't change quota if disallowed", () => {
736
744
  const result = creditAccount_1.CreditAccountData.calcQuotaUpdate({
745
+ maxDebt: HUGE_MAX_DEBT,
737
746
  quotaReserve: QUOTA_RESERVE,
738
747
  quotas: cmQuotas,
739
748
  initialQuotas: caQuota,
@@ -772,6 +781,7 @@ describe("CreditAccount calcQuotaUpdate test", () => {
772
781
  });
773
782
  it("shouldn't change quota if it is disabled", () => {
774
783
  const result = creditAccount_1.CreditAccountData.calcQuotaUpdate({
784
+ maxDebt: HUGE_MAX_DEBT,
775
785
  quotaReserve: QUOTA_RESERVE,
776
786
  quotas: {
777
787
  [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {
@@ -827,6 +837,7 @@ describe("CreditAccount calcQuotaUpdate test", () => {
827
837
  });
828
838
  it("swap shouldn't buy quota if no lt", () => {
829
839
  const result = creditAccount_1.CreditAccountData.calcQuotaUpdate({
840
+ maxDebt: HUGE_MAX_DEBT,
830
841
  quotaReserve: QUOTA_RESERVE,
831
842
  quotas: cmQuotas,
832
843
  initialQuotas: {
@@ -874,6 +885,7 @@ describe("CreditAccount calcQuotaUpdate test", () => {
874
885
  });
875
886
  it("swap should buy quota with respect to lt", () => {
876
887
  const result = creditAccount_1.CreditAccountData.calcQuotaUpdate({
888
+ maxDebt: HUGE_MAX_DEBT,
877
889
  quotaReserve: QUOTA_RESERVE,
878
890
  quotas: cmQuotas,
879
891
  initialQuotas: {
@@ -927,6 +939,7 @@ describe("CreditAccount calcQuotaUpdate test", () => {
927
939
  });
928
940
  it("swap shouldn't buy quota with respect to lt", () => {
929
941
  const result = creditAccount_1.CreditAccountData.calcQuotaUpdate({
942
+ maxDebt: HUGE_MAX_DEBT,
930
943
  quotaReserve: QUOTA_RESERVE,
931
944
  quotas: cmQuotas,
932
945
  initialQuotas: {
@@ -973,6 +986,175 @@ describe("CreditAccount calcQuotaUpdate test", () => {
973
986
  },
974
987
  });
975
988
  });
989
+ it("swap should buy additional quota after limit was increased", () => {
990
+ const result = creditAccount_1.CreditAccountData.calcQuotaUpdate({
991
+ maxDebt: 10n,
992
+ quotaReserve: QUOTA_RESERVE,
993
+ quotas: cmQuotas,
994
+ initialQuotas: {
995
+ ...caQuota,
996
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {
997
+ quota: 10n,
998
+ },
999
+ },
1000
+ assetsAfterUpdate: {
1001
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {
1002
+ amountInTarget: 20n,
1003
+ balance: 0n,
1004
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
1005
+ },
1006
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {
1007
+ amountInTarget: 0n,
1008
+ balance: 0n,
1009
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
1010
+ },
1011
+ },
1012
+ allowedToObtain: {
1013
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {},
1014
+ },
1015
+ allowedToSpend: {
1016
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {},
1017
+ },
1018
+ liquidationThresholds: DEFAULT_LT,
1019
+ });
1020
+ (0, chai_1.expect)(result.quotaIncrease).to.be.deep.eq([
1021
+ {
1022
+ balance: 10n,
1023
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
1024
+ },
1025
+ ]);
1026
+ (0, chai_1.expect)(result.quotaDecrease).to.be.deep.eq([
1027
+ {
1028
+ balance: -10n,
1029
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
1030
+ },
1031
+ ]);
1032
+ (0, chai_1.expect)(result.desiredQuota).to.be.deep.eq({
1033
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {
1034
+ balance: 20n,
1035
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
1036
+ },
1037
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {
1038
+ balance: 0n,
1039
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
1040
+ },
1041
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.STETH]: {
1042
+ balance: 0n,
1043
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.STETH,
1044
+ },
1045
+ });
1046
+ });
1047
+ it("swap should buy additional quota with respect to debt limit", () => {
1048
+ const result = creditAccount_1.CreditAccountData.calcQuotaUpdate({
1049
+ maxDebt: 9n,
1050
+ quotaReserve: QUOTA_RESERVE,
1051
+ quotas: cmQuotas,
1052
+ initialQuotas: {
1053
+ ...caQuota,
1054
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {
1055
+ quota: 10n,
1056
+ },
1057
+ },
1058
+ assetsAfterUpdate: {
1059
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {
1060
+ amountInTarget: 20n,
1061
+ balance: 0n,
1062
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
1063
+ },
1064
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {
1065
+ amountInTarget: 0n,
1066
+ balance: 0n,
1067
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
1068
+ },
1069
+ },
1070
+ allowedToObtain: {
1071
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {},
1072
+ },
1073
+ allowedToSpend: {
1074
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {},
1075
+ },
1076
+ liquidationThresholds: DEFAULT_LT,
1077
+ });
1078
+ (0, chai_1.expect)(result.quotaIncrease).to.be.deep.eq([
1079
+ {
1080
+ balance: 8n,
1081
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
1082
+ },
1083
+ ]);
1084
+ (0, chai_1.expect)(result.quotaDecrease).to.be.deep.eq([
1085
+ {
1086
+ balance: -10n,
1087
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
1088
+ },
1089
+ ]);
1090
+ (0, chai_1.expect)(result.desiredQuota).to.be.deep.eq({
1091
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {
1092
+ balance: 18n,
1093
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
1094
+ },
1095
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {
1096
+ balance: 0n,
1097
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
1098
+ },
1099
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.STETH]: {
1100
+ balance: 0n,
1101
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.STETH,
1102
+ },
1103
+ });
1104
+ });
1105
+ it("swap shouldn't buy additional quota if debt limit more then current quota", () => {
1106
+ const result = creditAccount_1.CreditAccountData.calcQuotaUpdate({
1107
+ maxDebt: 5n,
1108
+ quotaReserve: QUOTA_RESERVE,
1109
+ quotas: cmQuotas,
1110
+ initialQuotas: {
1111
+ ...caQuota,
1112
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {
1113
+ quota: 10n,
1114
+ },
1115
+ },
1116
+ assetsAfterUpdate: {
1117
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {
1118
+ amountInTarget: 20n,
1119
+ balance: 0n,
1120
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
1121
+ },
1122
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {
1123
+ amountInTarget: 0n,
1124
+ balance: 0n,
1125
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
1126
+ },
1127
+ },
1128
+ allowedToObtain: {
1129
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {},
1130
+ },
1131
+ allowedToSpend: {
1132
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {},
1133
+ },
1134
+ liquidationThresholds: DEFAULT_LT,
1135
+ });
1136
+ (0, chai_1.expect)(result.quotaIncrease).to.be.deep.eq([]);
1137
+ (0, chai_1.expect)(result.quotaDecrease).to.be.deep.eq([
1138
+ {
1139
+ balance: -10n,
1140
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
1141
+ },
1142
+ ]);
1143
+ (0, chai_1.expect)(result.desiredQuota).to.be.deep.eq({
1144
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.DAI]: {
1145
+ balance: 10n,
1146
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.DAI,
1147
+ },
1148
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.WETH]: {
1149
+ balance: 0n,
1150
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.WETH,
1151
+ },
1152
+ [sdk_gov_1.tokenDataByNetwork.Mainnet.STETH]: {
1153
+ balance: 0n,
1154
+ token: sdk_gov_1.tokenDataByNetwork.Mainnet.STETH,
1155
+ },
1156
+ });
1157
+ });
976
1158
  });
977
1159
  describe("CreditAccount calcAvgQuotaBorrowRate test", () => {
978
1160
  it("should calculate quota rate (same amounts, different rates)", () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gearbox-protocol/sdk",
3
- "version": "3.0.0-next.126",
3
+ "version": "3.0.0-next.128",
4
4
  "description": "Gearbox SDK",
5
5
  "main": "./lib/index.js",
6
6
  "types": "./lib/index.d.ts",
@@ -30,7 +30,7 @@
30
30
  "test": "npx mocha -r ts-node/register -r dotenv/config 'src/**/*.spec.ts'"
31
31
  },
32
32
  "dependencies": {
33
- "@gearbox-protocol/sdk-gov": "^1.31.1",
33
+ "@gearbox-protocol/sdk-gov": "^1.32.0",
34
34
  "axios": "^1.2.6",
35
35
  "decimal.js-light": "^2.5.1",
36
36
  "deep-eql": "^4.1.0",