@curvefi/llamalend-api 1.1.9 → 2.0.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.
Files changed (138) hide show
  1. package/docs/MIGRATION.md +325 -0
  2. package/docs/SUPPORT_LLv2.md +409 -0
  3. package/lib/constants/abis/OneWayLendingFactoryV2ABI.json +543 -0
  4. package/lib/constants/aliases.d.ts +0 -11
  5. package/lib/constants/aliases.js +1 -86
  6. package/lib/constants/coins.d.ts +0 -11
  7. package/lib/constants/coins.js +0 -14
  8. package/lib/constants/utils.d.ts +2 -0
  9. package/lib/constants/utils.js +2 -0
  10. package/lib/index.d.ts +10 -4
  11. package/lib/interfaces.d.ts +3 -2
  12. package/lib/lendMarkets/LendMarketTemplate.d.ts +13 -501
  13. package/lib/lendMarkets/LendMarketTemplate.js +237 -2854
  14. package/lib/lendMarkets/fetch/fetchFactoryData.d.ts +13 -0
  15. package/lib/lendMarkets/fetch/fetchFactoryData.js +101 -0
  16. package/lib/lendMarkets/fetch/fetchLendMarkets.d.ts +3 -0
  17. package/lib/lendMarkets/fetch/fetchLendMarkets.js +94 -0
  18. package/lib/lendMarkets/interfaces/common/amm.d.ts +10 -0
  19. package/lib/lendMarkets/interfaces/common/amm.js +1 -0
  20. package/lib/lendMarkets/interfaces/common/index.d.ts +5 -0
  21. package/lib/lendMarkets/interfaces/common/index.js +5 -0
  22. package/lib/lendMarkets/interfaces/common/prices.d.ts +13 -0
  23. package/lib/lendMarkets/interfaces/common/prices.js +1 -0
  24. package/lib/lendMarkets/interfaces/common/userPosition.d.ts +39 -0
  25. package/lib/lendMarkets/interfaces/common/userPosition.js +1 -0
  26. package/lib/lendMarkets/interfaces/common/vault.d.ts +55 -0
  27. package/lib/lendMarkets/interfaces/common/vault.js +1 -0
  28. package/lib/lendMarkets/interfaces/common/wallet.d.ts +8 -0
  29. package/lib/lendMarkets/interfaces/common/wallet.js +1 -0
  30. package/lib/lendMarkets/interfaces/v1/index.d.ts +4 -0
  31. package/lib/lendMarkets/interfaces/v1/index.js +4 -0
  32. package/lib/lendMarkets/interfaces/v1/leverageV1.d.ts +90 -0
  33. package/lib/lendMarkets/interfaces/v1/leverageV1.js +1 -0
  34. package/lib/lendMarkets/interfaces/v1/loanV1.d.ts +73 -0
  35. package/lib/lendMarkets/interfaces/v1/loanV1.js +1 -0
  36. package/lib/lendMarkets/interfaces/v1/statsV1.d.ts +49 -0
  37. package/lib/lendMarkets/interfaces/v1/statsV1.js +1 -0
  38. package/lib/lendMarkets/interfaces/v2/index.d.ts +3 -0
  39. package/lib/lendMarkets/interfaces/v2/index.js +3 -0
  40. package/lib/lendMarkets/interfaces/v2/leverageV2.d.ts +90 -0
  41. package/lib/lendMarkets/interfaces/v2/leverageV2.js +1 -0
  42. package/lib/lendMarkets/interfaces/v2/loanV2.d.ts +73 -0
  43. package/lib/lendMarkets/interfaces/v2/loanV2.js +1 -0
  44. package/lib/lendMarkets/interfaces/v2/statsV2.d.ts +49 -0
  45. package/lib/lendMarkets/interfaces/v2/statsV2.js +1 -0
  46. package/lib/lendMarkets/lendMarketConstructor.js +1 -1
  47. package/lib/lendMarkets/modules/common/amm.d.ts +19 -0
  48. package/lib/lendMarkets/modules/common/amm.js +137 -0
  49. package/lib/lendMarkets/modules/common/index.d.ts +9 -0
  50. package/lib/lendMarkets/modules/common/index.js +9 -0
  51. package/lib/lendMarkets/modules/common/leverageZapV1Base.d.ts +118 -0
  52. package/lib/lendMarkets/modules/common/leverageZapV1Base.js +770 -0
  53. package/lib/lendMarkets/modules/{leverageZapV2.d.ts → common/leverageZapV2Base.d.ts} +10 -5
  54. package/lib/lendMarkets/modules/{leverageZapV2.js → common/leverageZapV2Base.js} +36 -32
  55. package/lib/lendMarkets/modules/common/loanBase.d.ts +115 -0
  56. package/lib/lendMarkets/modules/common/loanBase.js +793 -0
  57. package/lib/lendMarkets/modules/common/prices.d.ts +19 -0
  58. package/lib/lendMarkets/modules/common/prices.js +104 -0
  59. package/lib/lendMarkets/modules/common/statsBase.d.ts +69 -0
  60. package/lib/lendMarkets/modules/common/statsBase.js +291 -0
  61. package/lib/lendMarkets/modules/common/userPosition.d.ts +46 -0
  62. package/lib/lendMarkets/modules/common/userPosition.js +223 -0
  63. package/lib/lendMarkets/modules/common/vault.d.ts +69 -0
  64. package/lib/lendMarkets/modules/common/vault.js +535 -0
  65. package/lib/lendMarkets/modules/common/wallet.d.ts +13 -0
  66. package/lib/lendMarkets/modules/common/wallet.js +28 -0
  67. package/lib/lendMarkets/modules/index.d.ts +1 -1
  68. package/lib/lendMarkets/modules/index.js +1 -1
  69. package/lib/lendMarkets/modules/v1/index.d.ts +4 -0
  70. package/lib/lendMarkets/modules/v1/index.js +4 -0
  71. package/lib/lendMarkets/modules/v1/leverageV1ZapV1.d.ts +3 -0
  72. package/lib/lendMarkets/modules/v1/leverageV1ZapV1.js +3 -0
  73. package/lib/lendMarkets/modules/v1/leverageV1ZapV2.d.ts +3 -0
  74. package/lib/lendMarkets/modules/v1/leverageV1ZapV2.js +3 -0
  75. package/lib/lendMarkets/modules/v1/loanV1.d.ts +4 -0
  76. package/lib/lendMarkets/modules/v1/loanV1.js +3 -0
  77. package/lib/lendMarkets/modules/v1/statsV1.d.ts +3 -0
  78. package/lib/lendMarkets/modules/v1/statsV1.js +3 -0
  79. package/lib/lendMarkets/modules/v2/index.d.ts +4 -0
  80. package/lib/lendMarkets/modules/v2/index.js +4 -0
  81. package/lib/lendMarkets/modules/v2/leverageV2ZapV1.d.ts +3 -0
  82. package/lib/lendMarkets/modules/v2/leverageV2ZapV1.js +3 -0
  83. package/lib/lendMarkets/modules/v2/leverageV2ZapV2.d.ts +3 -0
  84. package/lib/lendMarkets/modules/v2/leverageV2ZapV2.js +3 -0
  85. package/lib/lendMarkets/modules/v2/loanV2.d.ts +4 -0
  86. package/lib/lendMarkets/modules/v2/loanV2.js +3 -0
  87. package/lib/lendMarkets/modules/v2/statsV2.d.ts +3 -0
  88. package/lib/lendMarkets/modules/v2/statsV2.js +3 -0
  89. package/lib/llamalend.d.ts +6 -6
  90. package/lib/llamalend.js +46 -210
  91. package/lib/utils.js +2 -33
  92. package/package.json +1 -1
  93. package/src/constants/abis/OneWayLendingFactoryV2ABI.json +543 -0
  94. package/src/constants/aliases.ts +1 -97
  95. package/src/constants/coins.ts +0 -25
  96. package/src/constants/utils.ts +4 -0
  97. package/src/interfaces.ts +3 -2
  98. package/src/lendMarkets/LendMarketTemplate.ts +318 -3214
  99. package/src/lendMarkets/fetch/fetchFactoryData.ts +113 -0
  100. package/src/lendMarkets/fetch/fetchLendMarkets.ts +108 -0
  101. package/src/lendMarkets/interfaces/common/amm.ts +11 -0
  102. package/src/lendMarkets/interfaces/common/index.ts +5 -0
  103. package/src/lendMarkets/interfaces/common/prices.ts +13 -0
  104. package/src/lendMarkets/interfaces/common/userPosition.ts +24 -0
  105. package/src/lendMarkets/interfaces/common/vault.ts +48 -0
  106. package/src/lendMarkets/interfaces/common/wallet.ts +3 -0
  107. package/src/lendMarkets/interfaces/v1/index.ts +4 -0
  108. package/src/lendMarkets/interfaces/v1/leverageV1.ts +84 -0
  109. package/src/lendMarkets/interfaces/v1/loanV1.ts +77 -0
  110. package/src/lendMarkets/interfaces/v1/statsV1.ts +21 -0
  111. package/src/lendMarkets/interfaces/v2/index.ts +3 -0
  112. package/src/lendMarkets/interfaces/v2/leverageV2.ts +84 -0
  113. package/src/lendMarkets/interfaces/v2/loanV2.ts +77 -0
  114. package/src/lendMarkets/interfaces/v2/statsV2.ts +21 -0
  115. package/src/lendMarkets/lendMarketConstructor.ts +1 -1
  116. package/src/lendMarkets/modules/common/amm.ts +132 -0
  117. package/src/lendMarkets/modules/common/index.ts +9 -0
  118. package/src/lendMarkets/modules/common/leverageZapV1Base.ts +912 -0
  119. package/src/lendMarkets/modules/{leverageZapV2.ts → common/leverageZapV2Base.ts} +41 -37
  120. package/src/lendMarkets/modules/common/loanBase.ts +773 -0
  121. package/src/lendMarkets/modules/common/prices.ts +111 -0
  122. package/src/lendMarkets/modules/common/statsBase.ts +313 -0
  123. package/src/lendMarkets/modules/common/userPosition.ts +243 -0
  124. package/src/lendMarkets/modules/common/vault.ts +551 -0
  125. package/src/lendMarkets/modules/common/wallet.ts +29 -0
  126. package/src/lendMarkets/modules/index.ts +1 -1
  127. package/src/lendMarkets/modules/v1/index.ts +4 -0
  128. package/src/lendMarkets/modules/v1/leverageV1ZapV1.ts +3 -0
  129. package/src/lendMarkets/modules/v1/leverageV1ZapV2.ts +3 -0
  130. package/src/lendMarkets/modules/v1/loanV1.ts +4 -0
  131. package/src/lendMarkets/modules/v1/statsV1.ts +3 -0
  132. package/src/lendMarkets/modules/v2/index.ts +4 -0
  133. package/src/lendMarkets/modules/v2/leverageV2ZapV1.ts +3 -0
  134. package/src/lendMarkets/modules/v2/leverageV2ZapV2.ts +3 -0
  135. package/src/lendMarkets/modules/v2/loanV2.ts +4 -0
  136. package/src/lendMarkets/modules/v2/statsV2.ts +3 -0
  137. package/src/llamalend.ts +47 -244
  138. package/src/utils.ts +2 -35
@@ -0,0 +1,551 @@
1
+ import memoize from "memoizee";
2
+ import type { TAmount, TGas, IReward } from "../../../interfaces";
3
+ import type { LendMarketTemplate } from "../../LendMarketTemplate";
4
+ import {
5
+ _getAddress,
6
+ parseUnits,
7
+ BN,
8
+ toBN,
9
+ ensureAllowance,
10
+ hasAllowance,
11
+ ensureAllowanceEstimateGas,
12
+ formatUnits,
13
+ smartNumber,
14
+ _mulBy1_3,
15
+ _getUsdRate,
16
+ _ensureAllowance,
17
+ DIGas,
18
+ } from "../../../utils";
19
+ import {Llamalend} from "../../../llamalend";
20
+ import BigNumber from "bignumber.js";
21
+ import { _getMarketsData } from "../../../external-api";
22
+ import ERC20Abi from '../../../constants/abis/ERC20.json' with {type: 'json'};
23
+ import {WEEK} from "../../../constants/utils";
24
+
25
+ export class VaultModule {
26
+ private market: LendMarketTemplate;
27
+ private llamalend: Llamalend;
28
+
29
+ constructor(market: LendMarketTemplate) {
30
+ this.market = market;
31
+ this.llamalend = market.getLlamalend();
32
+ }
33
+
34
+ public async vaultMaxDeposit(address = ""): Promise<string> {
35
+ address = _getAddress.call(this.llamalend, address);
36
+ // const _amount = await this.llamalend.contracts[this.market.addresses.vault].contract.maxDeposit(address); TODO use maxDeposit
37
+ const _amount = await this.llamalend.contracts[this.market.addresses.borrowed_token].contract.balanceOf(address);
38
+
39
+ return formatUnits(_amount, this.market.borrowed_token.decimals);
40
+ }
41
+
42
+ public async vaultPreviewDeposit(amount: TAmount): Promise<string> {
43
+ const _amount = parseUnits(amount, this.market.borrowed_token.decimals);
44
+ const _shares = await this.llamalend.contracts[this.market.addresses.vault].contract.previewDeposit(_amount);
45
+
46
+ return formatUnits(_shares, 18);
47
+ }
48
+
49
+ public async vaultDepositIsApproved(borrowed: TAmount): Promise<boolean> {
50
+ return await hasAllowance.call(this.llamalend, [this.market.borrowed_token.address], [borrowed], this.llamalend.signerAddress, this.market.addresses.vault);
51
+ }
52
+
53
+ public async vaultDepositApproveEstimateGas (borrowed: TAmount): Promise<TGas> {
54
+ return await ensureAllowanceEstimateGas.call(this.llamalend, [this.market.borrowed_token.address], [borrowed], this.market.addresses.vault);
55
+ }
56
+
57
+ public async vaultDepositApprove(borrowed: TAmount): Promise<string[]> {
58
+ return await ensureAllowance.call(this.llamalend, [this.market.borrowed_token.address], [borrowed], this.market.addresses.vault);
59
+ }
60
+
61
+ private async _vaultDeposit(amount: TAmount, estimateGas = false): Promise<string | TGas> {
62
+ const _amount = parseUnits(amount, this.market.borrowed_token.decimals);
63
+ const gas = await this.llamalend.contracts[this.market.addresses.vault].contract.deposit.estimateGas(_amount, { ...this.llamalend.constantOptions });
64
+ if (estimateGas) return smartNumber(gas);
65
+
66
+ await this.llamalend.updateFeeData();
67
+
68
+ const gasLimit = _mulBy1_3(DIGas(gas));
69
+
70
+ return (await this.llamalend.contracts[this.market.addresses.vault].contract.deposit(_amount, { ...this.llamalend.options, gasLimit })).hash;
71
+ }
72
+
73
+ public async vaultDepositEstimateGas(amount: TAmount): Promise<TGas> {
74
+ if (!(await this.vaultDepositIsApproved(amount))) throw Error("Approval is needed for gas estimation");
75
+ return await this._vaultDeposit(amount, true) as number;
76
+ }
77
+
78
+ public async vaultDeposit(amount: TAmount): Promise<string> {
79
+ await this.vaultDepositApprove(amount);
80
+ return await this._vaultDeposit(amount, false) as string;
81
+ }
82
+
83
+
84
+ public async vaultMaxMint(address = ""): Promise<string> {
85
+ address = _getAddress.call(this.llamalend, address);
86
+ // const _shares = await this.llamalend.contracts[this.market.addresses.vault].contract.maxMint(address); TODO use maxMint
87
+ const _assetBalance = await this.llamalend.contracts[this.market.addresses.borrowed_token].contract.balanceOf(address);
88
+ const _shares = await this.llamalend.contracts[this.market.addresses.vault].contract.convertToShares(_assetBalance);
89
+
90
+ return formatUnits(_shares, 18);
91
+ }
92
+
93
+ public async vaultPreviewMint(amount: TAmount): Promise<string> {
94
+ const _amount = parseUnits(amount, 18);
95
+ const _assets = await this.llamalend.contracts[this.market.addresses.vault].contract.previewMint(_amount);
96
+
97
+ return formatUnits(_assets, this.market.borrowed_token.decimals);
98
+ }
99
+
100
+ public async vaultMintIsApproved(borrowed: TAmount): Promise<boolean> {
101
+ return await hasAllowance.call(this.llamalend, [this.market.borrowed_token.address], [borrowed], this.llamalend.signerAddress, this.market.addresses.vault);
102
+ }
103
+
104
+ public async vaultMintApproveEstimateGas (borrowed: TAmount): Promise<TGas> {
105
+ return await ensureAllowanceEstimateGas.call(this.llamalend, [this.market.borrowed_token.address], [borrowed], this.market.addresses.vault);
106
+ }
107
+
108
+ public async vaultMintApprove(borrowed: TAmount): Promise<string[]> {
109
+ return await ensureAllowance.call(this.llamalend, [this.market.borrowed_token.address], [borrowed], this.market.addresses.vault);
110
+ }
111
+
112
+ private async _vaultMint(amount: TAmount, estimateGas = false): Promise<string | TGas> {
113
+ const _amount = parseUnits(amount, 18);
114
+ const gas = await this.llamalend.contracts[this.market.addresses.vault].contract.mint.estimateGas(_amount, { ...this.llamalend.constantOptions });
115
+ if (estimateGas) return smartNumber(gas);
116
+
117
+ await this.llamalend.updateFeeData();
118
+
119
+ const gasLimit = _mulBy1_3(DIGas(gas));
120
+
121
+ return (await this.llamalend.contracts[this.market.addresses.vault].contract.mint(_amount, { ...this.llamalend.options, gasLimit })).hash;
122
+ }
123
+
124
+ public async vaultMintEstimateGas(amount: TAmount): Promise<TGas> {
125
+ if (!(await this.vaultMintIsApproved(amount))) throw Error("Approval is needed for gas estimation");
126
+ return await this._vaultMint(amount, true) as number;
127
+ }
128
+
129
+ public async vaultMint(amount: TAmount): Promise<string> {
130
+ await this.vaultMintApprove(amount);
131
+ return await this._vaultMint(amount, false) as string;
132
+ }
133
+
134
+
135
+ public async vaultMaxWithdraw(address = ""): Promise<string> {
136
+ address = _getAddress.call(this.llamalend, address);
137
+ const _assets = await this.llamalend.contracts[this.market.addresses.vault].contract.maxWithdraw(address);
138
+
139
+ return formatUnits(_assets, this.market.borrowed_token.decimals);
140
+ }
141
+
142
+ public async vaultPreviewWithdraw(amount: TAmount): Promise<string> {
143
+ const _amount = parseUnits(amount, this.market.borrowed_token.decimals);
144
+ const _shares = await this.llamalend.contracts[this.market.addresses.vault].contract.previewWithdraw(_amount);
145
+
146
+ return formatUnits(_shares, 18);
147
+ }
148
+
149
+ private async _vaultWithdraw(amount: TAmount, estimateGas = false): Promise<string | TGas> {
150
+ const _amount = parseUnits(amount, this.market.borrowed_token.decimals);
151
+ const gas = await this.llamalend.contracts[this.market.addresses.vault].contract.withdraw.estimateGas(_amount, { ...this.llamalend.constantOptions });
152
+ if (estimateGas) return smartNumber(gas);
153
+
154
+ await this.llamalend.updateFeeData();
155
+
156
+ const gasLimit = _mulBy1_3(DIGas(gas));
157
+
158
+ return (await this.llamalend.contracts[this.market.addresses.vault].contract.withdraw(_amount, { ...this.llamalend.options, gasLimit })).hash;
159
+ }
160
+
161
+ public async vaultWithdrawEstimateGas(amount: TAmount): Promise<TGas> {
162
+ return await this._vaultWithdraw(amount, true) as number;
163
+ }
164
+
165
+ public async vaultWithdraw(amount: TAmount): Promise<string> {
166
+ return await this._vaultWithdraw(amount, false) as string;
167
+ }
168
+
169
+
170
+ public async vaultMaxRedeem(address = ""): Promise<string> {
171
+ address = _getAddress.call(this.llamalend, address);
172
+ const _shares = await this.llamalend.contracts[this.market.addresses.vault].contract.maxRedeem(address)
173
+
174
+ return formatUnits(_shares, 18);
175
+ }
176
+
177
+ public async vaultPreviewRedeem(amount: TAmount): Promise<string> {
178
+ const _amount = parseUnits(amount, 18);
179
+ const _assets = await this.llamalend.contracts[this.market.addresses.vault].contract.previewRedeem(_amount);
180
+
181
+ return formatUnits(_assets, this.market.borrowed_token.decimals);
182
+ }
183
+
184
+ private async _vaultRedeem(amount: TAmount, estimateGas = false): Promise<string | TGas> {
185
+ const _amount = parseUnits(amount, 18);
186
+ const gas = await this.llamalend.contracts[this.market.addresses.vault].contract.redeem.estimateGas(_amount, { ...this.llamalend.constantOptions });
187
+ if (estimateGas) return smartNumber(gas);
188
+
189
+ await this.llamalend.updateFeeData();
190
+
191
+ const gasLimit = _mulBy1_3(DIGas(gas));
192
+
193
+ return (await this.llamalend.contracts[this.market.addresses.vault].contract.redeem(_amount, { ...this.llamalend.options, gasLimit })).hash;
194
+ }
195
+
196
+ public async vaultRedeemEstimateGas(amount: TAmount): Promise<TGas> {
197
+ return await this._vaultRedeem(amount, true) as number;
198
+ }
199
+
200
+ public async vaultRedeem(amount: TAmount): Promise<string> {
201
+ return await this._vaultRedeem(amount, false) as string;
202
+ }
203
+
204
+ // ---------------- VAULT UTILS ----------------
205
+
206
+ public async vaultConvertToShares(assets: TAmount): Promise<string> {
207
+ const _assets = parseUnits(assets, this.market.borrowed_token.decimals);
208
+ const _shares = await this.llamalend.contracts[this.market.addresses.vault].contract.convertToShares(_assets);
209
+
210
+ return this.llamalend.formatUnits(_shares);
211
+ }
212
+
213
+ public async vaultConvertToAssets(shares: TAmount): Promise<string> {
214
+ const _shares = parseUnits(shares);
215
+ const _assets = await this.llamalend.contracts[this.market.addresses.vault].contract.convertToAssets(_shares);
216
+
217
+ return this.llamalend.formatUnits(_assets, this.market.borrowed_token.decimals);
218
+ }
219
+
220
+ // ---------------- VAULT STAKING ----------------
221
+
222
+ public async vaultStakeIsApproved(vaultShares: number | string): Promise<boolean> {
223
+ if (this.market.addresses.gauge === this.llamalend.constants.ZERO_ADDRESS) {
224
+ throw Error(`stakeIsApproved method doesn't exist for pool ${this.market.name} (id: ${this.market.name}). There is no gauge`);
225
+ }
226
+ return await hasAllowance.call(this.llamalend, [this.market.addresses.vault], [vaultShares], this.llamalend.signerAddress, this.market.addresses.gauge);
227
+ }
228
+
229
+ public async vaultStakeApproveEstimateGas(vaultShares: number | string): Promise<TGas> {
230
+ if (this.market.addresses.gauge === this.llamalend.constants.ZERO_ADDRESS) {
231
+ throw Error(`stakeApproveEstimateGas method doesn't exist for pool ${this.market.name} (id: ${this.market.name}). There is no gauge`);
232
+ }
233
+ return await ensureAllowanceEstimateGas.call(this.llamalend, [this.market.addresses.vault], [vaultShares], this.market.addresses.gauge);
234
+ }
235
+
236
+ public async vaultStakeApprove(vaultShares: number | string): Promise<string[]> {
237
+ if (this.market.addresses.gauge === this.llamalend.constants.ZERO_ADDRESS) {
238
+ throw Error(`stakeApprove method doesn't exist for pool ${this.market.name} (id: ${this.market.name}). There is no gauge`);
239
+ }
240
+ return await ensureAllowance.call(this.llamalend, [this.market.addresses.vault], [vaultShares], this.market.addresses.gauge);
241
+ }
242
+
243
+ public async vaultStakeEstimateGas(vaultShares: number | string): Promise<TGas> {
244
+ if (this.market.addresses.gauge === this.llamalend.constants.ZERO_ADDRESS) {
245
+ throw Error(`stakeEstimateGas method doesn't exist for pool ${this.market.name} (id: ${this.market.name}). There is no gauge`);
246
+ }
247
+ const _vaultShares = parseUnits(vaultShares);
248
+ return smartNumber(await this.llamalend.contracts[this.market.addresses.gauge].contract.deposit.estimateGas(_vaultShares, this.llamalend.constantOptions));
249
+ }
250
+
251
+ public async vaultStake(vaultShares: number | string): Promise<string> {
252
+ if (this.market.addresses.gauge === this.llamalend.constants.ZERO_ADDRESS) {
253
+ throw Error(`stake method doesn't exist for pool ${this.market.name} (id: ${this.market.name}). There is no gauge`);
254
+ }
255
+ const _vaultShares = parseUnits(vaultShares);
256
+ await _ensureAllowance.call(this.llamalend, [this.market.addresses.vault], [_vaultShares], this.market.addresses.gauge)
257
+
258
+ await this.llamalend.updateFeeData();
259
+ const gasLimit = _mulBy1_3(DIGas(await this.llamalend.contracts[this.market.addresses.gauge].contract.deposit.estimateGas(_vaultShares, this.llamalend.constantOptions)));
260
+ return (await this.llamalend.contracts[this.market.addresses.gauge].contract.deposit(_vaultShares, { ...this.llamalend.options, gasLimit })).hash;
261
+ }
262
+
263
+ public async vaultUnstakeEstimateGas(vaultShares: number | string): Promise<TGas> {
264
+ if (this.market.addresses.gauge === this.llamalend.constants.ZERO_ADDRESS) {
265
+ throw Error(`unstakeEstimateGas method doesn't exist for pool ${this.market.name} (id: ${this.market.name}). There is no gauge`);
266
+ }
267
+ const _vaultShares = parseUnits(vaultShares);
268
+ return smartNumber(await this.llamalend.contracts[this.market.addresses.gauge].contract.withdraw.estimateGas(_vaultShares, this.llamalend.constantOptions));
269
+ }
270
+
271
+ public async vaultUnstake(vaultShares: number | string): Promise<string> {
272
+ if (this.market.addresses.gauge === this.llamalend.constants.ZERO_ADDRESS) {
273
+ throw Error(`unstake method doesn't exist for pool ${this.market.name} (id: ${this.market.name}). There is no gauge`);
274
+ }
275
+ const _vaultShares = parseUnits(vaultShares);
276
+
277
+ await this.llamalend.updateFeeData();
278
+ const gasLimit = _mulBy1_3(DIGas((await this.llamalend.contracts[this.market.addresses.gauge].contract.withdraw.estimateGas(_vaultShares, this.llamalend.constantOptions))));
279
+ return (await this.llamalend.contracts[this.market.addresses.gauge].contract.withdraw(_vaultShares, { ...this.llamalend.options, gasLimit })).hash;
280
+ }
281
+
282
+ // ---------------- VAULT STAKING REWARDS ----------------
283
+
284
+ public vaultRewardsOnly(): boolean {
285
+ if (this.market.addresses.gauge === this.llamalend.constants.ZERO_ADDRESS) throw Error(`${this.market.name} doesn't have gauge`);
286
+ const gaugeContract = this.llamalend.contracts[this.market.addresses.gauge].contract;
287
+
288
+ return !('inflation_rate()' in gaugeContract || 'inflation_rate(uint256)' in gaugeContract);
289
+ }
290
+
291
+ public async vaultTotalLiquidity(useAPI = true): Promise<string> {
292
+ const { cap } = await this.market.stats.capAndAvailable(true, useAPI);
293
+ const price = await _getUsdRate.call(this.llamalend, this.market.addresses.borrowed_token);
294
+
295
+ return BN(cap).times(price).toFixed(6)
296
+ }
297
+
298
+ private _calcCrvApr = async (futureWorkingSupplyBN: BigNumber | null = null): Promise<[baseApy: number, boostedApy: number]> => {
299
+ const totalLiquidityUSD = await this.vaultTotalLiquidity();
300
+ if (Number(totalLiquidityUSD) === 0) return [0, 0];
301
+
302
+ let inflationRateBN, workingSupplyBN, totalSupplyBN;
303
+ if (this.llamalend.chainId !== 1) {
304
+ const gaugeContract = this.llamalend.contracts[this.market.addresses.gauge].multicallContract;
305
+ const lpTokenContract = this.llamalend.contracts[this.market.addresses.vault].multicallContract;
306
+ const crvContract = this.llamalend.contracts[this.llamalend.constants.ALIASES.crv].contract;
307
+
308
+ const currentWeek = Math.floor(Date.now() / 1000 / WEEK);
309
+ [inflationRateBN, workingSupplyBN, totalSupplyBN] = (await this.llamalend.multicallProvider.all([
310
+ gaugeContract.inflation_rate(currentWeek),
311
+ gaugeContract.working_supply(),
312
+ lpTokenContract.totalSupply(),
313
+ ]) as bigint[]).map((value) => toBN(value));
314
+
315
+ if (inflationRateBN.eq(0)) {
316
+ inflationRateBN = toBN(await crvContract.balanceOf(this.market.addresses.gauge, this.llamalend.constantOptions)).div(WEEK);
317
+ }
318
+ } else {
319
+ const gaugeContract = this.llamalend.contracts[this.market.addresses.gauge].multicallContract;
320
+ const lpTokenContract = this.llamalend.contracts[this.market.addresses.vault].multicallContract;
321
+ const gaugeControllerContract = this.llamalend.contracts[this.llamalend.constants.ALIASES.gauge_controller].multicallContract;
322
+
323
+ let weightBN;
324
+ [inflationRateBN, weightBN, workingSupplyBN, totalSupplyBN] = (await this.llamalend.multicallProvider.all([
325
+ gaugeContract.inflation_rate(),
326
+ gaugeControllerContract.gauge_relative_weight(this.market.addresses.gauge),
327
+ gaugeContract.working_supply(),
328
+ lpTokenContract.totalSupply(),
329
+ ]) as bigint[]).map((value) => toBN(value));
330
+
331
+ inflationRateBN = inflationRateBN.times(weightBN);
332
+ }
333
+
334
+ if (inflationRateBN.eq(0)) return [0, 0];
335
+ if (futureWorkingSupplyBN !== null) workingSupplyBN = futureWorkingSupplyBN;
336
+
337
+ // If you added 1$ value of LP it would be 0.4$ of working LP. So your annual reward per 1$ in USD is:
338
+ // (annual reward per working liquidity in $) * (0.4$ of working LP)
339
+ const rateBN = inflationRateBN.times(31536000).div(workingSupplyBN).times(totalSupplyBN).div(Number(totalLiquidityUSD)).times(0.4);
340
+ const crvPrice = await _getUsdRate.call(this.llamalend, this.llamalend.constants.ALIASES.crv);
341
+ const baseApyBN = rateBN.times(crvPrice);
342
+ const boostedApyBN = baseApyBN.times(2.5);
343
+
344
+ return [baseApyBN.times(100).toNumber(), boostedApyBN.times(100).toNumber()]
345
+ }
346
+
347
+ public async vaultCrvApr(): Promise<[baseApy: number, boostedApy: number]> {
348
+ if (this.vaultRewardsOnly()) throw Error(`${this.market.name} has Rewards-Only Gauge. Use stats.rewardsApy instead`);
349
+
350
+ // const isDisabledChain = [1313161554].includes(this.llamalend.chainId); // Disable Aurora
351
+ // if (useApi && !isDisabledChain) {
352
+ // const crvAPYs = await _getCrvApyFromApi();
353
+ // const poolCrvApy = crvAPYs[this.market.addresses.gauge] ?? [0, 0]; // new pools might be missing
354
+ // return [poolCrvApy[0], poolCrvApy[1]];
355
+ // }
356
+
357
+ return await this._calcCrvApr();
358
+ }
359
+
360
+ public async vaultClaimableCrv (address = ""): Promise<string> {
361
+ if (this.vaultRewardsOnly()) throw Error(`${this.market.name} has Rewards-Only Gauge. Use claimableRewards instead`);
362
+ address = address || this.llamalend.signerAddress;
363
+ if (!address) throw Error("Need to connect wallet or pass address into args");
364
+
365
+ return this.llamalend.formatUnits(await this.llamalend.contracts[this.market.addresses.gauge].contract.claimable_tokens(address, this.llamalend.constantOptions));
366
+ }
367
+
368
+ private async _vaultClaimCrv(estimateGas: boolean): Promise<string | TGas> {
369
+ if (this.vaultRewardsOnly()) throw Error(`${this.market.name} has Rewards-Only Gauge. Use claimRewards instead`);
370
+
371
+ let isOldFactory = false;
372
+ let contract;
373
+
374
+ if (this.llamalend.chainId !== 1) {
375
+ if (this.llamalend.constants.ALIASES.gauge_factory_old && this.llamalend.constants.ALIASES.gauge_factory_old !== this.llamalend.constants.ZERO_ADDRESS) {
376
+ const oldFactoryContract = this.llamalend.contracts[this.llamalend.constants.ALIASES.gauge_factory_old].contract;
377
+ const lpToken = await this.llamalend.contracts[this.market.addresses.gauge].contract.lp_token();
378
+ const gaugeAddress = await oldFactoryContract.get_gauge_from_lp_token(lpToken);
379
+
380
+ isOldFactory = gaugeAddress.toLowerCase() === this.market.addresses.gauge.toLowerCase();
381
+
382
+ if (isOldFactory) {
383
+ contract = oldFactoryContract;
384
+ }
385
+ }
386
+ }
387
+
388
+ if (!isOldFactory) {
389
+ contract = this.llamalend.contracts[this.llamalend.constants.ALIASES.minter].contract
390
+ }
391
+
392
+ if(!contract) {
393
+ throw Error(`${this.market.name} couldn't match gauge factory`);
394
+ }
395
+
396
+ const gas = await contract.mint.estimateGas(this.market.addresses.gauge, this.llamalend.constantOptions);
397
+ if (estimateGas) return smartNumber(gas);
398
+
399
+ await this.llamalend.updateFeeData();
400
+ const gasLimit = _mulBy1_3(DIGas(gas));
401
+ return (await contract.mint(this.market.addresses.gauge, { ...this.llamalend.options, gasLimit })).hash
402
+ }
403
+
404
+ public async vaultClaimCrvEstimateGas(): Promise<TGas> {
405
+ return await this._vaultClaimCrv(true) as TGas;
406
+ }
407
+
408
+ public async vaultClaimCrv(): Promise<string> {
409
+ return await this._vaultClaimCrv(false) as string;
410
+ }
411
+
412
+ public vaultRewardTokens = memoize(async (): Promise<{token: string, symbol: string, decimals: number}[]> => {
413
+ if (this.market.addresses.gauge === this.llamalend.constants.ZERO_ADDRESS) return []
414
+
415
+ // if (useApi) {
416
+ // const rewards = await _getRewardsFromApi();
417
+ // if (!rewards[this.market.addresses.gauge]) return [];
418
+ // rewards[this.market.addresses.gauge].forEach((r) => _setContracts(r.tokenAddress, ERC20Abi));
419
+ // return rewards[this.market.addresses.gauge].map((r) => ({ token: r.tokenAddress, symbol: r.symbol, decimals: Number(r.decimals) }));
420
+ // }
421
+
422
+ const gaugeContract = this.llamalend.contracts[this.market.addresses.gauge].contract;
423
+ const gaugeMulticallContract = this.llamalend.contracts[this.market.addresses.gauge].multicallContract;
424
+ const rewardCount = Number(this.llamalend.formatUnits(await gaugeContract.reward_count(this.llamalend.constantOptions), 0));
425
+
426
+ const tokenCalls = [];
427
+ for (let i = 0; i < rewardCount; i++) {
428
+ tokenCalls.push(gaugeMulticallContract.reward_tokens(i));
429
+ }
430
+ const tokens = (await this.llamalend.multicallProvider.all(tokenCalls) as string[])
431
+ .filter((addr) => addr !== this.llamalend.constants.ZERO_ADDRESS)
432
+ .map((addr) => addr.toLowerCase())
433
+ .filter((addr) => this.llamalend.chainId === 1 || addr !== this.llamalend.constants.COINS.crv);
434
+
435
+ const tokenInfoCalls = [];
436
+ for (const token of tokens) {
437
+ this.llamalend.setContract(token, ERC20Abi);
438
+ const tokenMulticallContract = this.llamalend.contracts[token].multicallContract;
439
+ tokenInfoCalls.push(tokenMulticallContract.symbol(), tokenMulticallContract.decimals());
440
+ }
441
+ const tokenInfo = await this.llamalend.multicallProvider.all(tokenInfoCalls);
442
+ for (let i = 0; i < tokens.length; i++) {
443
+ this.llamalend.constants.DECIMALS[tokens[i]] = Number(tokenInfo[(i * 2) + 1]);
444
+ }
445
+
446
+ return tokens.map((token, i) => ({ token, symbol: tokenInfo[i * 2] as string, decimals: Number(tokenInfo[(i * 2) + 1]) }));
447
+ }, {
448
+ promise: true,
449
+ maxAge: 30 * 60 * 1000, // 30m
450
+ });
451
+
452
+ public vaultRewardsApr = async (useApi = true): Promise<IReward[]> => {
453
+ if(useApi) {
454
+ const response = await _getMarketsData(this.llamalend.constants.NETWORK_NAME);
455
+
456
+ const market = response.lendingVaultData.find((item) => item.address.toLowerCase() === this.market.addresses.vault.toLowerCase())
457
+
458
+ if(market) {
459
+ return market.gaugeRewards
460
+ } else {
461
+ throw new Error('Market not found in API')
462
+ }
463
+ } else {
464
+ if (this.market.addresses.gauge === this.llamalend.constants.ZERO_ADDRESS) return [];
465
+
466
+ // const isDisabledChain = [1313161554].includes(this.llamalend.chainId); // Disable Aurora
467
+ // if (useApi && !isDisabledChain) {
468
+ // const rewards = await _getRewardsFromApi();
469
+ // if (!rewards[this.market.addresses.gauge]) return [];
470
+ // return rewards[this.market.addresses.gauge].map((r) => ({ gaugeAddress: r.gaugeAddress, tokenAddress: r.tokenAddress, symbol: r.symbol, apy: r.apy }));
471
+ // }
472
+
473
+ const apy: IReward[] = [];
474
+ const rewardTokens = await this.vaultRewardTokens();
475
+ for (const rewardToken of rewardTokens) {
476
+ const gaugeContract = this.llamalend.contracts[this.market.addresses.gauge].multicallContract;
477
+ const lpTokenContract = this.llamalend.contracts[this.market.addresses.vault].multicallContract;
478
+ const rewardContract = this.llamalend.contracts[this.market.addresses.gauge].multicallContract;
479
+
480
+ const totalLiquidityUSD = await this.vaultTotalLiquidity();
481
+ const rewardRate = await _getUsdRate.call(this.llamalend, rewardToken.token);
482
+
483
+ const [rewardData, _stakedSupply, _totalSupply] = (await this.llamalend.multicallProvider.all([
484
+ rewardContract.reward_data(rewardToken.token),
485
+ gaugeContract.totalSupply(),
486
+ lpTokenContract.totalSupply(),
487
+ ]) as any[]);
488
+ const stakedSupplyBN = toBN(_stakedSupply as bigint);
489
+ const totalSupplyBN = toBN(_totalSupply as bigint);
490
+ const inflationBN = toBN(rewardData.rate, rewardToken.decimals);
491
+ const periodFinish = Number(this.llamalend.formatUnits(rewardData.period_finish, 0)) * 1000;
492
+ const baseApy = periodFinish > Date.now() ?
493
+ inflationBN.times(31536000).times(rewardRate).div(stakedSupplyBN).times(totalSupplyBN).div(Number(totalLiquidityUSD)) :
494
+ BN(0);
495
+
496
+ apy.push({
497
+ gaugeAddress: this.market.addresses.gauge,
498
+ tokenAddress: rewardToken.token,
499
+ symbol: rewardToken.symbol,
500
+ apy: baseApy.times(100).toNumber(),
501
+ });
502
+ }
503
+
504
+ return apy
505
+ }
506
+ }
507
+
508
+ public async vaultClaimableRewards(address = ""): Promise<{token: string, symbol: string, amount: string}[]> {
509
+ if (this.market.addresses.gauge === this.llamalend.constants.ZERO_ADDRESS) {
510
+ throw Error(`claimableRewards method doesn't exist for pool ${this.market.name} (id: ${this.market.name}). There is no gauge`);
511
+ }
512
+ address = address || this.llamalend.signerAddress;
513
+ if (!address) throw Error("Need to connect wallet or pass address into args");
514
+
515
+ const gaugeContract = this.llamalend.contracts[this.market.addresses.gauge].contract;
516
+ const rewardTokens = await this.vaultRewardTokens();
517
+ const rewards = [];
518
+ for (const rewardToken of rewardTokens) {
519
+ const _amount = await gaugeContract.claimable_reward(address, rewardToken.token, this.llamalend.constantOptions);
520
+ rewards.push({
521
+ token: rewardToken.token,
522
+ symbol: rewardToken.symbol,
523
+ amount: this.llamalend.formatUnits(_amount, rewardToken.decimals),
524
+ });
525
+ }
526
+
527
+ return rewards
528
+ }
529
+
530
+ private async _vaultClaimRewards(estimateGas: boolean): Promise<string | TGas> {
531
+ if (this.market.addresses.gauge === this.llamalend.constants.ZERO_ADDRESS) {
532
+ throw Error(`claimRewards method doesn't exist for pool ${this.market.name} (id: ${this.market.name}). There is no gauge`);
533
+ }
534
+ const gaugeContract = this.llamalend.contracts[this.market.addresses.gauge].contract;
535
+ if (!("claim_rewards()" in gaugeContract)) throw Error (`${this.market.name} pool doesn't have such method`);
536
+ const gas = await gaugeContract.claim_rewards.estimateGas(this.llamalend.constantOptions);
537
+ if (estimateGas) return smartNumber(gas);
538
+
539
+ await this.llamalend.updateFeeData();
540
+ const gasLimit = _mulBy1_3(DIGas(gas));
541
+ return (await gaugeContract.claim_rewards({ ...this.llamalend.options, gasLimit })).hash;
542
+ }
543
+
544
+ public async vaultClaimRewardsEstimateGas(): Promise<TGas> {
545
+ return await this._vaultClaimRewards(true) as TGas;
546
+ }
547
+
548
+ public async vaultClaimRewards(): Promise<string> {
549
+ return await this._vaultClaimRewards(false) as string;
550
+ }
551
+ }
@@ -0,0 +1,29 @@
1
+ import type { LendMarketTemplate } from "../../LendMarketTemplate";
2
+ import {
3
+ getBalances,
4
+ } from "../../../utils";
5
+ import {Llamalend} from "../../../llamalend";
6
+ import {IWallet} from "../../interfaces/common";
7
+
8
+ export class WalletModule implements IWallet {
9
+ private market: LendMarketTemplate;
10
+ private llamalend: Llamalend;
11
+
12
+ constructor(market: LendMarketTemplate) {
13
+ this.market = market;
14
+ this.llamalend = market.getLlamalend();
15
+ }
16
+
17
+ public async balances(address = ""): Promise<{ collateral: string, borrowed: string, vaultShares: string, gauge: string }> {
18
+ if (this.market.addresses.gauge === this.llamalend.constants.ZERO_ADDRESS) {
19
+ const [collateral, borrowed, vaultShares] =
20
+ await getBalances.call(this.llamalend, [this.market.collateral_token.address, this.market.borrowed_token.address, this.market.addresses.vault], address);
21
+ return { collateral, borrowed, vaultShares, gauge: "0" }
22
+ } else {
23
+ const [collateral, borrowed, vaultShares, gauge] =
24
+ await getBalances.call(this.llamalend, [this.market.collateral_token.address, this.market.borrowed_token.address, this.market.addresses.vault, this.market.addresses.gauge], address);
25
+ return { collateral, borrowed, vaultShares, gauge }
26
+ }
27
+ }
28
+
29
+ }
@@ -1 +1 @@
1
- export { LeverageZapV2Module } from './leverageZapV2.js';
1
+ export { LeverageV1ZapV2Module } from './v1/leverageV1ZapV2';
@@ -0,0 +1,4 @@
1
+ export { LoanV1Module } from './loanV1.js';
2
+ export { LeverageV1ZapV1Module } from './leverageV1ZapV1.js';
3
+ export { LeverageV1ZapV2Module } from './leverageV1ZapV2.js';
4
+ export { StatsV1Module } from './statsV1.js';
@@ -0,0 +1,3 @@
1
+ import { LeverageZapV1BaseModule } from "../common/leverageZapV1Base.js";
2
+
3
+ export class LeverageV1ZapV1Module extends LeverageZapV1BaseModule {}
@@ -0,0 +1,3 @@
1
+ import { LeverageZapV2BaseModule } from "../common/leverageZapV2Base.js";
2
+
3
+ export class LeverageV1ZapV2Module extends LeverageZapV2BaseModule {}
@@ -0,0 +1,4 @@
1
+ import { LoanBaseModule } from "../common/loanBase.js";
2
+ import { ILoanV1 } from "../../interfaces/v1/loanV1";
3
+
4
+ export class LoanV1Module extends LoanBaseModule implements ILoanV1 {}
@@ -0,0 +1,3 @@
1
+ import { StatsBaseModule } from "../common/statsBase.js";
2
+
3
+ export class StatsV1Module extends StatsBaseModule {}
@@ -0,0 +1,4 @@
1
+ export { LoanV2Module } from './loanV2';
2
+ export { LeverageV2ZapV1Module } from './leverageV2ZapV1';
3
+ export { LeverageV2ZapV2Module } from './leverageV2ZapV2';
4
+ export { StatsV2Module } from './statsV2';
@@ -0,0 +1,3 @@
1
+ import { LeverageZapV1BaseModule } from "../common/leverageZapV1Base.js";
2
+
3
+ export class LeverageV2ZapV1Module extends LeverageZapV1BaseModule {}
@@ -0,0 +1,3 @@
1
+ import { LeverageZapV2BaseModule } from "../common/leverageZapV2Base.js";
2
+
3
+ export class LeverageV2ZapV2Module extends LeverageZapV2BaseModule {}
@@ -0,0 +1,4 @@
1
+ import { LoanBaseModule } from "../common/loanBase.js";
2
+ import { ILoanV2 } from "../../interfaces/v2";
3
+
4
+ export class LoanV2Module extends LoanBaseModule implements ILoanV2 {}
@@ -0,0 +1,3 @@
1
+ import { StatsBaseModule } from "../common/statsBase.js";
2
+
3
+ export class StatsV2Module extends StatsBaseModule {}