@kasufinance/kasu-sdk 1.0.1

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 (219) hide show
  1. package/.eslintignore +3 -0
  2. package/.eslintrc.json +90 -0
  3. package/.github/workflows/ci.yml +0 -0
  4. package/.github/workflows/main.yml +43 -0
  5. package/.prettierignore +3 -0
  6. package/.prettierrc +28 -0
  7. package/abis/IClearingCoordinator.abi.json +410 -0
  8. package/abis/IERC20Metadata.abi.json +224 -0
  9. package/abis/IFeeManager.abi.json +66 -0
  10. package/abis/IKSULocking.abi.json +754 -0
  11. package/abis/IKasuAllowList.abi.json +455 -0
  12. package/abis/IKasuController.abi.json +423 -0
  13. package/abis/IKasuNFTs.abi.json +1523 -0
  14. package/abis/IKsuPrice.abi.json +15 -0
  15. package/abis/ILendingPool.abi.json +1431 -0
  16. package/abis/ILendingPoolFactory.abi.json +97 -0
  17. package/abis/ILendingPoolManager.abi.json +1347 -0
  18. package/abis/ILendingPoolTranche.abi.json +1317 -0
  19. package/abis/IPriceFeed.abi.json +1 -0
  20. package/abis/ISystemVariables.abi.json +431 -0
  21. package/abis/IUserLoyaltyRewards.abi.json +288 -0
  22. package/abis/IUserManager.abi.json +321 -0
  23. package/abis/KSULockBonus.abi.json +91 -0
  24. package/abis/KasuPoolExternalTVL.abi.json +812 -0
  25. package/abis/Swapper.abi.json +146 -0
  26. package/copy-abi.ps1 +15 -0
  27. package/dist/bundle.cjs.js +21646 -0
  28. package/dist/bundle.esm.js +21644 -0
  29. package/dist/contracts/IClearingCoordinatorAbi.d.ts +169 -0
  30. package/dist/contracts/IClearingCoordinatorAbi.js +1 -0
  31. package/dist/contracts/IERC20MetadataAbi.d.ts +162 -0
  32. package/dist/contracts/IERC20MetadataAbi.js +1 -0
  33. package/dist/contracts/IFeeManagerAbi.d.ts +96 -0
  34. package/dist/contracts/IFeeManagerAbi.js +1 -0
  35. package/dist/contracts/IKSULockingAbi.d.ts +466 -0
  36. package/dist/contracts/IKSULockingAbi.js +1 -0
  37. package/dist/contracts/IKasuAllowListAbi.d.ts +304 -0
  38. package/dist/contracts/IKasuAllowListAbi.js +1 -0
  39. package/dist/contracts/IKasuControllerAbi.d.ts +309 -0
  40. package/dist/contracts/IKasuControllerAbi.js +1 -0
  41. package/dist/contracts/IKasuNFTsAbi.d.ts +1121 -0
  42. package/dist/contracts/IKasuNFTsAbi.js +1 -0
  43. package/dist/contracts/IKsuPriceAbi.d.ts +42 -0
  44. package/dist/contracts/IKsuPriceAbi.js +1 -0
  45. package/dist/contracts/ILendingPoolAbi.d.ts +968 -0
  46. package/dist/contracts/ILendingPoolAbi.js +1 -0
  47. package/dist/contracts/ILendingPoolFactoryAbi.d.ts +103 -0
  48. package/dist/contracts/ILendingPoolFactoryAbi.js +1 -0
  49. package/dist/contracts/ILendingPoolManagerAbi.d.ts +779 -0
  50. package/dist/contracts/ILendingPoolManagerAbi.js +1 -0
  51. package/dist/contracts/ILendingPoolTrancheAbi.d.ts +752 -0
  52. package/dist/contracts/ILendingPoolTrancheAbi.js +1 -0
  53. package/dist/contracts/ISystemVariablesAbi.d.ts +378 -0
  54. package/dist/contracts/ISystemVariablesAbi.js +1 -0
  55. package/dist/contracts/IUserLoyaltyRewardsAbi.d.ts +248 -0
  56. package/dist/contracts/IUserLoyaltyRewardsAbi.js +1 -0
  57. package/dist/contracts/IUserManagerAbi.d.ts +270 -0
  58. package/dist/contracts/IUserManagerAbi.js +1 -0
  59. package/dist/contracts/KSULockBonusAbi.d.ts +61 -0
  60. package/dist/contracts/KSULockBonusAbi.js +1 -0
  61. package/dist/contracts/KasuPoolExternalTVLAbi.d.ts +411 -0
  62. package/dist/contracts/KasuPoolExternalTVLAbi.js +1 -0
  63. package/dist/contracts/SwapperAbi.d.ts +120 -0
  64. package/dist/contracts/SwapperAbi.js +1 -0
  65. package/dist/contracts/common.d.ts +21 -0
  66. package/dist/contracts/common.js +1 -0
  67. package/dist/contracts/factories/IClearingCoordinatorAbi__factory.d.ts +320 -0
  68. package/dist/contracts/factories/IClearingCoordinatorAbi__factory.js +423 -0
  69. package/dist/contracts/factories/IERC20MetadataAbi__factory.d.ts +178 -0
  70. package/dist/contracts/factories/IERC20MetadataAbi__factory.js +237 -0
  71. package/dist/contracts/factories/IFeeManagerAbi__factory.d.ts +59 -0
  72. package/dist/contracts/factories/IFeeManagerAbi__factory.js +79 -0
  73. package/dist/contracts/factories/IKSULockingAbi__factory.d.ts +588 -0
  74. package/dist/contracts/factories/IKSULockingAbi__factory.js +767 -0
  75. package/dist/contracts/factories/IKasuAllowListAbi__factory.d.ts +354 -0
  76. package/dist/contracts/factories/IKasuAllowListAbi__factory.js +468 -0
  77. package/dist/contracts/factories/IKasuControllerAbi__factory.d.ts +339 -0
  78. package/dist/contracts/factories/IKasuControllerAbi__factory.js +436 -0
  79. package/dist/contracts/factories/IKasuNFTsAbi__factory.d.ts +1629 -0
  80. package/dist/contracts/factories/IKasuNFTsAbi__factory.js +2108 -0
  81. package/dist/contracts/factories/IKsuPriceAbi__factory.d.ts +18 -0
  82. package/dist/contracts/factories/IKsuPriceAbi__factory.js +28 -0
  83. package/dist/contracts/factories/ILendingPoolAbi__factory.d.ts +1109 -0
  84. package/dist/contracts/factories/ILendingPoolAbi__factory.js +1444 -0
  85. package/dist/contracts/factories/ILendingPoolFactoryAbi__factory.d.ts +81 -0
  86. package/dist/contracts/factories/ILendingPoolFactoryAbi__factory.js +110 -0
  87. package/dist/contracts/factories/ILendingPoolManagerAbi__factory.d.ts +1045 -0
  88. package/dist/contracts/factories/ILendingPoolManagerAbi__factory.js +1360 -0
  89. package/dist/contracts/factories/ILendingPoolTrancheAbi__factory.d.ts +1015 -0
  90. package/dist/contracts/factories/ILendingPoolTrancheAbi__factory.js +1330 -0
  91. package/dist/contracts/factories/ISystemVariablesAbi__factory.d.ts +338 -0
  92. package/dist/contracts/factories/ISystemVariablesAbi__factory.js +444 -0
  93. package/dist/contracts/factories/IUserLoyaltyRewardsAbi__factory.d.ts +230 -0
  94. package/dist/contracts/factories/IUserLoyaltyRewardsAbi__factory.js +301 -0
  95. package/dist/contracts/factories/IUserManagerAbi__factory.d.ts +250 -0
  96. package/dist/contracts/factories/IUserManagerAbi__factory.js +334 -0
  97. package/dist/contracts/factories/KSULockBonusAbi__factory.d.ts +76 -0
  98. package/dist/contracts/factories/KSULockBonusAbi__factory.js +104 -0
  99. package/dist/contracts/factories/KasuPoolExternalTVLAbi__factory.d.ts +631 -0
  100. package/dist/contracts/factories/KasuPoolExternalTVLAbi__factory.js +825 -0
  101. package/dist/contracts/factories/SwapperAbi__factory.d.ts +120 -0
  102. package/dist/contracts/factories/SwapperAbi__factory.js +159 -0
  103. package/dist/contracts/factories/index.d.ts +18 -0
  104. package/dist/contracts/factories/index.js +21 -0
  105. package/dist/contracts/index.d.ts +37 -0
  106. package/dist/contracts/index.js +19 -0
  107. package/dist/index.d.ts +17 -0
  108. package/dist/index.js +16 -0
  109. package/dist/sdk-config.d.ts +22 -0
  110. package/dist/sdk-config.js +9 -0
  111. package/dist/services/DataService/data-service.d.ts +37 -0
  112. package/dist/services/DataService/data-service.js +586 -0
  113. package/dist/services/DataService/directus-types.d.ts +187 -0
  114. package/dist/services/DataService/directus-types.js +1 -0
  115. package/dist/services/DataService/queries.d.ts +7 -0
  116. package/dist/services/DataService/queries.js +158 -0
  117. package/dist/services/DataService/subgraph-types.d.ts +95 -0
  118. package/dist/services/DataService/subgraph-types.js +1 -0
  119. package/dist/services/DataService/types.d.ts +169 -0
  120. package/dist/services/DataService/types.js +1 -0
  121. package/dist/services/Locking/locking.d.ts +61 -0
  122. package/dist/services/Locking/locking.js +344 -0
  123. package/dist/services/Locking/queries.d.ts +10 -0
  124. package/dist/services/Locking/queries.js +108 -0
  125. package/dist/services/Locking/types.d.ts +117 -0
  126. package/dist/services/Locking/types.js +1 -0
  127. package/dist/services/Portfolio/portfolio.d.ts +22 -0
  128. package/dist/services/Portfolio/portfolio.js +325 -0
  129. package/dist/services/Portfolio/queries.d.ts +2 -0
  130. package/dist/services/Portfolio/queries.js +164 -0
  131. package/dist/services/Portfolio/types.d.ts +206 -0
  132. package/dist/services/Portfolio/types.js +1 -0
  133. package/dist/services/Swapper/swapper.d.ts +11 -0
  134. package/dist/services/Swapper/swapper.js +97 -0
  135. package/dist/services/Swapper/types.d.ts +51 -0
  136. package/dist/services/Swapper/types.js +1 -0
  137. package/dist/services/UserLending/helper.d.ts +2 -0
  138. package/dist/services/UserLending/helper.js +16 -0
  139. package/dist/services/UserLending/queries.d.ts +8 -0
  140. package/dist/services/UserLending/queries.js +188 -0
  141. package/dist/services/UserLending/subgraph-types.d.ts +147 -0
  142. package/dist/services/UserLending/subgraph-types.js +6 -0
  143. package/dist/services/UserLending/types.d.ts +102 -0
  144. package/dist/services/UserLending/types.js +13 -0
  145. package/dist/services/UserLending/user-lending.d.ts +55 -0
  146. package/dist/services/UserLending/user-lending.js +490 -0
  147. package/dist/services/shared.d.ts +1 -0
  148. package/dist/services/shared.js +11 -0
  149. package/dist/tests/sample.test.d.ts +1 -0
  150. package/dist/tests/sample.test.js +32 -0
  151. package/index.ts +2 -0
  152. package/jest-config.ts +9 -0
  153. package/jest.config.js +8 -0
  154. package/package.json +49 -0
  155. package/rollup.config.js +45 -0
  156. package/src/contracts/IClearingCoordinatorAbi.ts +406 -0
  157. package/src/contracts/IERC20MetadataAbi.ts +364 -0
  158. package/src/contracts/IFeeManagerAbi.ts +182 -0
  159. package/src/contracts/IKSULockingAbi.ts +965 -0
  160. package/src/contracts/IKasuAllowListAbi.ts +605 -0
  161. package/src/contracts/IKasuControllerAbi.ts +703 -0
  162. package/src/contracts/IKasuNFTsAbi.ts +2744 -0
  163. package/src/contracts/IKsuPriceAbi.ts +87 -0
  164. package/src/contracts/ILendingPoolAbi.ts +2081 -0
  165. package/src/contracts/ILendingPoolFactoryAbi.ts +161 -0
  166. package/src/contracts/ILendingPoolManagerAbi.ts +1917 -0
  167. package/src/contracts/ILendingPoolTrancheAbi.ts +1911 -0
  168. package/src/contracts/ISystemVariablesAbi.ts +908 -0
  169. package/src/contracts/IUserLoyaltyRewardsAbi.ts +544 -0
  170. package/src/contracts/IUserManagerAbi.ts +612 -0
  171. package/src/contracts/KSULockBonusAbi.ts +124 -0
  172. package/src/contracts/KasuPoolExternalTVLAbi.ts +1071 -0
  173. package/src/contracts/SwapperAbi.ts +266 -0
  174. package/src/contracts/common.ts +44 -0
  175. package/src/contracts/factories/IClearingCoordinatorAbi__factory.ts +438 -0
  176. package/src/contracts/factories/IERC20MetadataAbi__factory.ts +248 -0
  177. package/src/contracts/factories/IFeeManagerAbi__factory.ts +90 -0
  178. package/src/contracts/factories/IKSULockingAbi__factory.ts +778 -0
  179. package/src/contracts/factories/IKasuAllowListAbi__factory.ts +479 -0
  180. package/src/contracts/factories/IKasuControllerAbi__factory.ts +447 -0
  181. package/src/contracts/factories/IKasuNFTsAbi__factory.ts +2116 -0
  182. package/src/contracts/factories/IKsuPriceAbi__factory.ts +36 -0
  183. package/src/contracts/factories/ILendingPoolAbi__factory.ts +1455 -0
  184. package/src/contracts/factories/ILendingPoolFactoryAbi__factory.ts +125 -0
  185. package/src/contracts/factories/ILendingPoolManagerAbi__factory.ts +1375 -0
  186. package/src/contracts/factories/ILendingPoolTrancheAbi__factory.ts +1345 -0
  187. package/src/contracts/factories/ISystemVariablesAbi__factory.ts +455 -0
  188. package/src/contracts/factories/IUserLoyaltyRewardsAbi__factory.ts +316 -0
  189. package/src/contracts/factories/IUserManagerAbi__factory.ts +345 -0
  190. package/src/contracts/factories/KSULockBonusAbi__factory.ts +115 -0
  191. package/src/contracts/factories/KasuPoolExternalTVLAbi__factory.ts +840 -0
  192. package/src/contracts/factories/SwapperAbi__factory.ts +167 -0
  193. package/src/contracts/factories/index.ts +21 -0
  194. package/src/contracts/index.ts +40 -0
  195. package/src/index.ts +27 -0
  196. package/src/sdk-config.ts +35 -0
  197. package/src/services/DataService/data-service.ts +1017 -0
  198. package/src/services/DataService/directus-types.ts +199 -0
  199. package/src/services/DataService/queries.ts +165 -0
  200. package/src/services/DataService/subgraph-types.ts +104 -0
  201. package/src/services/DataService/types.ts +184 -0
  202. package/src/services/Locking/locking.ts +541 -0
  203. package/src/services/Locking/queries.ts +118 -0
  204. package/src/services/Locking/types.ts +141 -0
  205. package/src/services/Portfolio/portfolio.ts +593 -0
  206. package/src/services/Portfolio/queries.ts +166 -0
  207. package/src/services/Portfolio/types.ts +220 -0
  208. package/src/services/Swapper/swapper.ts +158 -0
  209. package/src/services/Swapper/types.ts +54 -0
  210. package/src/services/UserLending/helper.ts +28 -0
  211. package/src/services/UserLending/queries.ts +196 -0
  212. package/src/services/UserLending/subgraph-types.ts +173 -0
  213. package/src/services/UserLending/types.ts +123 -0
  214. package/src/services/UserLending/user-lending.ts +933 -0
  215. package/src/services/shared.ts +11 -0
  216. package/src/tests/sample.test.ts +44 -0
  217. package/tsconfig.json +27 -0
  218. package/tsconfig.tsbuildinfo +1 -0
  219. package/versioner.sh +6 -0
@@ -0,0 +1,541 @@
1
+ import { Provider } from '@ethersproject/providers';
2
+ import { BigNumber, ContractTransaction, ethers, Signer } from 'ethers';
3
+ import { formatEther, formatUnits, parseUnits } from 'ethers/lib/utils';
4
+ import { GraphQLClient } from 'graphql-request';
5
+
6
+ import {
7
+ IERC20MetadataAbi,
8
+ IERC20MetadataAbi__factory,
9
+ IKSULockingAbi,
10
+ IKSULockingAbi__factory,
11
+ IKsuPriceAbi,
12
+ IKsuPriceAbi__factory,
13
+ ISystemVariablesAbi,
14
+ ISystemVariablesAbi__factory,
15
+ IUserLoyaltyRewardsAbi,
16
+ IUserLoyaltyRewardsAbi__factory,
17
+ IUserManagerAbi,
18
+ IUserManagerAbi__factory,
19
+ } from '../../contracts';
20
+ import { SdkConfig } from '../../sdk-config';
21
+ import {
22
+ getAllTrancheConfigurationsQuery,
23
+ getAllTranchesQuery,
24
+ } from '../DataService/queries';
25
+ import {
26
+ TrancheConfigurationSubgraphResult,
27
+ TrancheSubgraphResult,
28
+ } from '../DataService/subgraph-types';
29
+
30
+ import {
31
+ claimedFeesQuery,
32
+ getSystemVariablesQuery,
33
+ getTotalUserLoyaltsRewardsQuery,
34
+ lockingPeriodsQuery,
35
+ lockingSummariesQuery,
36
+ userEarnedrKsuQuery,
37
+ userLocksQuery,
38
+ userStakedKsuQuery,
39
+ userTotalBonusAmountQuery,
40
+ } from './queries';
41
+ import {
42
+ GQLClaimedFeesForAddress,
43
+ GQLEarnedRKsuForAddress,
44
+ GQLGetLockingPeriods,
45
+ GQLStakedAmountForAddress,
46
+ GQLTotalBonusAmountForAddress,
47
+ GQLUserLocks,
48
+ LockingSummarySubgraphResult,
49
+ LockPeriod,
50
+ LockPeriodInterface,
51
+ RSVDeadlineValue,
52
+ SystemVariables,
53
+ totalUserLoyaltyRewards,
54
+ UserBonusData,
55
+ UserLock,
56
+ } from './types';
57
+
58
+ export class KSULocking {
59
+ private readonly _contractAbi: IKSULockingAbi;
60
+ private readonly _kasuToken: IERC20MetadataAbi;
61
+ private readonly _kasuBonusAddress: string;
62
+ private readonly _graph: GraphQLClient;
63
+ private readonly _userManagerAbi: IUserManagerAbi;
64
+ private readonly _systemVariablesAbi: ISystemVariablesAbi;
65
+ private readonly _ksuPriceAbi: IKsuPriceAbi;
66
+ private readonly _userLoyaltyRewardsAbi: IUserLoyaltyRewardsAbi;
67
+ private readonly apyBonuses: number[] = [0, 0.001, 0.002];
68
+ /**
69
+ *
70
+ */
71
+ constructor(
72
+ private _kasuConfig: SdkConfig,
73
+ signerOrProvider: Signer | Provider,
74
+ ) {
75
+ this._contractAbi = IKSULockingAbi__factory.connect(
76
+ _kasuConfig.contracts.IKSULocking,
77
+ signerOrProvider,
78
+ );
79
+ this._kasuToken = IERC20MetadataAbi__factory.connect(
80
+ _kasuConfig.contracts.KSUToken,
81
+ signerOrProvider,
82
+ );
83
+ this._userManagerAbi = IUserManagerAbi__factory.connect(
84
+ _kasuConfig.contracts.UserManager,
85
+ signerOrProvider,
86
+ );
87
+ this._systemVariablesAbi = ISystemVariablesAbi__factory.connect(
88
+ _kasuConfig.contracts.SystemVariables,
89
+ signerOrProvider,
90
+ );
91
+ this._ksuPriceAbi = IKsuPriceAbi__factory.connect(
92
+ _kasuConfig.contracts.KsuPrice,
93
+ signerOrProvider,
94
+ );
95
+ this._kasuBonusAddress = _kasuConfig.contracts.IKSULockBonus;
96
+ this._graph = new GraphQLClient(_kasuConfig.subgraphUrl);
97
+ this._userLoyaltyRewardsAbi = IUserLoyaltyRewardsAbi__factory.connect(
98
+ _kasuConfig.contracts.UserLoyaltyRewards,
99
+ signerOrProvider,
100
+ );
101
+ }
102
+
103
+ async lockKSUTokens(
104
+ amount: BigNumber,
105
+ lockPeriod: BigNumber,
106
+ ): Promise<ContractTransaction> {
107
+ return this._contractAbi.lock(amount, lockPeriod);
108
+ }
109
+
110
+ async lockKSUWithPermit(
111
+ amount: number,
112
+ lockPeriod: number,
113
+ permit: RSVDeadlineValue,
114
+ ): Promise<ContractTransaction> {
115
+ const amountBN = BigNumber.from(amount);
116
+ const lockPeriodBN = BigNumber.from(lockPeriod);
117
+
118
+ const ksuPermit = {
119
+ value: BigNumber.from(permit.value),
120
+ deadline: BigNumber.from(permit.deadline),
121
+ v: BigNumber.from(permit.v),
122
+ r: permit.r,
123
+ s: permit.s,
124
+ };
125
+
126
+ return this._contractAbi.lockWithPermit(
127
+ amountBN,
128
+ lockPeriodBN,
129
+ ksuPermit,
130
+ );
131
+ }
132
+
133
+ async unlockKSU(
134
+ amount: BigNumber,
135
+ userLockId: BigNumber,
136
+ ): Promise<ContractTransaction> {
137
+ return this._contractAbi.unlock(amount, userLockId);
138
+ }
139
+
140
+ async claimFees(): Promise<ContractTransaction> {
141
+ return await this._contractAbi.claimFees();
142
+ }
143
+ async lockDetails(lockPeriod: BigNumber): Promise<LockPeriodInterface> {
144
+ const result = await this._contractAbi.lockDetails(lockPeriod);
145
+ return {
146
+ rKsuMultiplier: result[0].toNumber(),
147
+ ksuBonusMultiplier: result[1].toNumber(),
148
+ isActive: result[2],
149
+ };
150
+ }
151
+
152
+ async userTotalDeposits(userAddress: string): Promise<BigNumber> {
153
+ return await this._contractAbi.userTotalDeposits(userAddress);
154
+ }
155
+
156
+ async calculateUserLockProjectedProtocolFeeRewards(
157
+ epochId: string,
158
+ KSULocked: number,
159
+ lockPeriod: BigNumber,
160
+ ): Promise<number> {
161
+ if (KSULocked === 0) {
162
+ return 0;
163
+ }
164
+
165
+ const lockingSummarySubgraph: LockingSummarySubgraphResult =
166
+ await this._graph.request(lockingSummariesQuery);
167
+ const lockingSummary = lockingSummarySubgraph.lockingSummaries[0];
168
+ const totalRKSU = lockingSummary.totalRKsuAmount;
169
+
170
+ const lockDetails = await this.lockDetails(lockPeriod);
171
+
172
+ const newUserRKSU =
173
+ (KSULocked + KSULocked * lockDetails.ksuBonusMultiplier) *
174
+ lockDetails.rKsuMultiplier;
175
+ const totalRKSUAfterLock = totalRKSU + newUserRKSU;
176
+
177
+ const systemVariables: SystemVariables = await this._graph.request(
178
+ getSystemVariablesQuery,
179
+ );
180
+ const performanceFee =
181
+ parseFloat(systemVariables.systemVariables.performanceFee) / 100;
182
+ const ecosystemFee =
183
+ parseFloat(systemVariables.systemVariables.ecosystemFeeRate) / 100;
184
+
185
+ let projectedYearlyPlatformInterest = 0;
186
+ const subgraphResults: TrancheSubgraphResult =
187
+ await this._graph.request(getAllTranchesQuery, {
188
+ unusedPools: this._kasuConfig.UNUSED_LENDING_POOL_IDS,
189
+ });
190
+ const subgraphConfigurationResults: TrancheConfigurationSubgraphResult =
191
+ await this._graph.request(getAllTrancheConfigurationsQuery, {
192
+ unusedPools: this._kasuConfig.UNUSED_LENDING_POOL_IDS,
193
+ epochId,
194
+ });
195
+
196
+ for (const tranche of subgraphResults.lendingPoolTranches) {
197
+ const trancheConfig =
198
+ subgraphConfigurationResults.lendingPoolTrancheConfigurations.find(
199
+ (r) => r.id == tranche.id,
200
+ );
201
+ if (!trancheConfig) {
202
+ console.warn(
203
+ "Couldn't find tranche configuration for id: ",
204
+ tranche.id,
205
+ );
206
+ continue;
207
+ }
208
+
209
+ const interestUpdates =
210
+ trancheConfig.lendingPoolTrancheInterestRateUpdates;
211
+
212
+ const interestRate = interestUpdates.length
213
+ ? interestUpdates[0].epochInterestRate
214
+ : trancheConfig.interestRate;
215
+
216
+ projectedYearlyPlatformInterest +=
217
+ parseFloat(tranche.balance) *
218
+ this.calculateApy(parseFloat(interestRate));
219
+ }
220
+
221
+ const totalExpectedEcosystemFees =
222
+ projectedYearlyPlatformInterest * performanceFee * ecosystemFee;
223
+ return (
224
+ (totalExpectedEcosystemFees * newUserRKSU) /
225
+ parseFloat(totalRKSUAfterLock)
226
+ );
227
+ }
228
+
229
+ calculateApy(epochInterestRate: number): number {
230
+ const EPOCHS_IN_YEAR = 52.17857;
231
+ return (1 + epochInterestRate) ^ (EPOCHS_IN_YEAR - 1);
232
+ }
233
+
234
+ async getUserLocks(userAddress: string): Promise<UserLock[]> {
235
+ const result: GQLUserLocks = await this._graph.request(userLocksQuery, {
236
+ userAddress: userAddress.toLowerCase(),
237
+ });
238
+ const resultPromises = result.userLocks.map(async (userLock) => {
239
+ const [, id] = userLock.id.split('-');
240
+ const rKSUtoUSDCRatio = await this.getRKSUvsUSDCRatio(
241
+ userLock.rKSUAmount,
242
+ userAddress,
243
+ );
244
+ const loyaltyStatus =
245
+ this.getLoyaltyLevelAndApyBonusFromRatio(rKSUtoUSDCRatio);
246
+ return {
247
+ id: BigNumber.from(id),
248
+ lockedAmount: userLock.ksuAmount,
249
+ rKSUAmount: userLock.rKSUAmount,
250
+ rKSUtoUSDCRatio: rKSUtoUSDCRatio,
251
+ apyBonus: loyaltyStatus.apyBonus,
252
+ loyaltyLevel: loyaltyStatus.loyaltyLevel,
253
+ startTime: parseFloat(userLock.startTimestamp),
254
+ endTime: parseFloat(userLock.endTimestamp),
255
+ lockPeriod: userLock.lockPeriod,
256
+ };
257
+ });
258
+
259
+ const results = await Promise.all(resultPromises);
260
+ return results.sort((a, b) => a.endTime - b.endTime);
261
+ }
262
+
263
+ async getUserBonusData(userAddress: string): Promise<UserBonusData> {
264
+ // TODO this userLocks query is kinda bad -> change to userLocksDepositInfo as u never need user locks by themselves
265
+ // whole function takes between 500 - 800ms
266
+
267
+ const DECIMALS = 18;
268
+
269
+ // Normalized user address
270
+ const normalizedAddress = userAddress.toLowerCase();
271
+
272
+ // Fetch data concurrently
273
+ const [
274
+ userLocksData,
275
+ resultLoyaltyRewards,
276
+ protocolFeesEarned,
277
+ userRewards,
278
+ ] = await Promise.all([
279
+ this._graph.request<GQLUserLocks>(userLocksQuery, {
280
+ userAddress: normalizedAddress,
281
+ }),
282
+ this._graph.request<totalUserLoyaltyRewards>(
283
+ getTotalUserLoyaltsRewardsQuery,
284
+ { userAddress: normalizedAddress },
285
+ ),
286
+ this._contractAbi.rewards(userAddress),
287
+ this._userLoyaltyRewardsAbi.userRewards(userAddress),
288
+ ]);
289
+
290
+ // Extract data and format with fallback
291
+ const { userLocks } = userLocksData;
292
+
293
+ const formattedKsuBonusAndRewards = ethers.utils.formatUnits(
294
+ userRewards,
295
+ DECIMALS,
296
+ );
297
+ const formattedProtocolFeesEarned = ethers.utils.formatUnits(
298
+ protocolFeesEarned,
299
+ DECIMALS,
300
+ );
301
+
302
+ const ksuBonusAndRewardsLifetime =
303
+ resultLoyaltyRewards.user === null
304
+ ? '0.0'
305
+ : resultLoyaltyRewards.user.totalUserLoyaltyRewards;
306
+
307
+ const totalLockedAmount =
308
+ userLocks.length === 0
309
+ ? '0.0'
310
+ : userLocks[0].userLockDepositsInfo.ksuLockedAmount;
311
+
312
+ // Construct response data
313
+ return {
314
+ ksuBonusAndRewards: formattedKsuBonusAndRewards,
315
+ ksuBonusAndRewardsLifetime: ksuBonusAndRewardsLifetime,
316
+ protocolFeesEarned: formattedProtocolFeesEarned,
317
+ totalLockedAmount: totalLockedAmount,
318
+ };
319
+ }
320
+
321
+ getLoyaltyLevelAndApyBonusFromRatio(rKSUtoUSDCRatio: number): {
322
+ loyaltyLevel: number;
323
+ apyBonus: number;
324
+ } {
325
+ if (rKSUtoUSDCRatio < 0.01) {
326
+ return { loyaltyLevel: 0, apyBonus: this.apyBonuses[0] };
327
+ } else if (rKSUtoUSDCRatio < 0.05) {
328
+ return { loyaltyLevel: 1, apyBonus: this.apyBonuses[1] };
329
+ }
330
+ return { loyaltyLevel: 2, apyBonus: this.apyBonuses[2] };
331
+ }
332
+
333
+ async getRKSUvsUSDCRatio(
334
+ rKSUAmount: string,
335
+ userAddress: string,
336
+ ): Promise<number> {
337
+ const [depositedAmount, pendingAmount]: [BigNumber, BigNumber] =
338
+ await this._userManagerAbi.userTotalPendingAndActiveDepositedAmountForCurrentEpoch(
339
+ userAddress,
340
+ );
341
+ const ksuPrice: BigNumber =
342
+ await this._systemVariablesAbi.ksuEpochTokenPrice();
343
+ const rKSUAmountBignumber: BigNumber = ethers.utils.parseUnits(
344
+ rKSUAmount,
345
+ 18,
346
+ );
347
+
348
+ const totalUserUsdcAmount =
349
+ depositedAmount.toNumber() + pendingAmount.toNumber();
350
+
351
+ const rKSUInUSDC = rKSUAmountBignumber
352
+ .mul(ksuPrice)
353
+ .div(ethers.utils.parseUnits('1', 18))
354
+ .div(ethers.utils.parseUnits('1', 12));
355
+
356
+ return rKSUInUSDC.toNumber() / totalUserUsdcAmount;
357
+ }
358
+
359
+ async getClaimableRewards(userAddress: string): Promise<BigNumber> {
360
+ const result = await this._contractAbi.rewards(userAddress);
361
+ return result;
362
+ }
363
+
364
+ async getKasuTokenPrice(): Promise<{ price: BigNumber; decimals: number }> {
365
+ const decimals = 18;
366
+
367
+ return Promise.resolve({
368
+ price: await this._ksuPriceAbi.ksuTokenPrice(),
369
+ decimals,
370
+ });
371
+ }
372
+
373
+ async getKasuEpochTokenPrice(): Promise<{
374
+ price: BigNumber;
375
+ decimals: number;
376
+ }> {
377
+ const decimals = 18;
378
+
379
+ return Promise.resolve({
380
+ price: await this._systemVariablesAbi.ksuEpochTokenPrice(),
381
+ decimals,
382
+ });
383
+ }
384
+
385
+ async getLifetimeRewards(
386
+ userAddress: string,
387
+ rewardDecimals: number,
388
+ claimableRewards?: BigNumber,
389
+ ): Promise<BigNumber> {
390
+ const result: GQLClaimedFeesForAddress = await this._graph.request(
391
+ claimedFeesQuery,
392
+ {
393
+ userAddress: userAddress.toLowerCase(),
394
+ },
395
+ );
396
+
397
+ const claimedRewards = result.userLockDepositsInfo?.feesClaimed ?? '0';
398
+
399
+ if (!claimableRewards) {
400
+ claimableRewards = await this.getClaimableRewards(userAddress);
401
+ }
402
+
403
+ return claimableRewards.add(parseUnits(claimedRewards, rewardDecimals));
404
+ }
405
+
406
+ getLaunchBonusAmount(
407
+ lockAmount: BigNumber,
408
+ bonusMultiplier: number,
409
+ bonusTokensLeft: BigNumber,
410
+ ): BigNumber {
411
+ const bonusMultiplierBN = ethers.utils.parseUnits(
412
+ bonusMultiplier.toFixed(2),
413
+ 2,
414
+ );
415
+ const projectedBonus = lockAmount.mul(bonusMultiplierBN).div(100);
416
+
417
+ if (bonusTokensLeft.gt(projectedBonus)) {
418
+ return projectedBonus;
419
+ } else {
420
+ return bonusTokensLeft;
421
+ }
422
+ }
423
+
424
+ async getUserStakedKsu(userAddress: string): Promise<string> {
425
+ const result: GQLStakedAmountForAddress = await this._graph.request(
426
+ userStakedKsuQuery,
427
+ {
428
+ userAddress: userAddress.toLowerCase(),
429
+ },
430
+ );
431
+ if (result.userLockDepositsInfo == null) {
432
+ return '0';
433
+ }
434
+ return result.userLockDepositsInfo.ksuLockedAmount;
435
+ }
436
+
437
+ async getUserEarnedrKsu(userAddress: string): Promise<string> {
438
+ const result: GQLEarnedRKsuForAddress = await this._graph.request(
439
+ userEarnedrKsuQuery,
440
+ {
441
+ userAddress: userAddress.toLowerCase(),
442
+ },
443
+ );
444
+ if (result.userLockDepositsInfo == null) {
445
+ return '0';
446
+ }
447
+
448
+ return result.userLockDepositsInfo.rKSUAmount;
449
+ }
450
+
451
+ async getUserTotalBonusAmount(userAddress: string): Promise<string> {
452
+ const result: GQLTotalBonusAmountForAddress = await this._graph.request(
453
+ userTotalBonusAmountQuery,
454
+ {
455
+ userAddress: userAddress.toLowerCase(),
456
+ },
457
+ );
458
+ if (result.userLockDepositsInfo == null) {
459
+ return '0';
460
+ }
461
+
462
+ return result.userLockDepositsInfo.totalKsuBonusAmount;
463
+ }
464
+
465
+ async getLockingRewards(
466
+ userAddress: string,
467
+ ): Promise<{ claimableRewards: string; lifeTimeRewards: string }> {
468
+ const rewardDecimals = 6;
469
+
470
+ const claimableRewards = await this.getClaimableRewards(userAddress);
471
+
472
+ const lifeTimeRewards = await this.getLifetimeRewards(
473
+ userAddress,
474
+ rewardDecimals,
475
+ claimableRewards,
476
+ );
477
+
478
+ return {
479
+ claimableRewards: formatUnits(claimableRewards, rewardDecimals),
480
+ lifeTimeRewards: formatUnits(lifeTimeRewards, rewardDecimals),
481
+ };
482
+ }
483
+
484
+ async getTotalKsuStaked(): Promise<string> {
485
+ return Promise.resolve(ethers.constants.Zero.toString());
486
+ }
487
+
488
+ async getAvailableKsuBonus(): Promise<string> {
489
+ const amount = await this._kasuToken.balanceOf(this._kasuBonusAddress);
490
+
491
+ return formatEther(amount);
492
+ }
493
+
494
+ async getUserKsuBalance(userAddress: string): Promise<string> {
495
+ const balance = await this._kasuToken.balanceOf(
496
+ userAddress.toLowerCase(),
497
+ );
498
+
499
+ return formatEther(balance);
500
+ }
501
+ async getNextEpochDate(): Promise<EpochTimeStamp> {
502
+ return (
503
+ await this._systemVariablesAbi.nextEpochStartTimestamp()
504
+ ).toNumber();
505
+ }
506
+
507
+ async getNextClearingPeriodDate(): Promise<EpochTimeStamp> {
508
+ const nextEpochDate = await this.getNextEpochDate();
509
+
510
+ const clearingPeriodLength =
511
+ await this._systemVariablesAbi.clearingPeriodLength();
512
+
513
+ const nextClearingPeriod = BigNumber.from(nextEpochDate)
514
+ .sub(clearingPeriodLength)
515
+ .toNumber();
516
+
517
+ const nowUnix = Date.now() / 1000;
518
+
519
+ if (nowUnix >= nextClearingPeriod) {
520
+ const oneWeek = 604800; // in seconds
521
+
522
+ return nextClearingPeriod + oneWeek;
523
+ }
524
+
525
+ return nextClearingPeriod;
526
+ }
527
+
528
+ async getActiveLockPeriods(): Promise<LockPeriod[]> {
529
+ const data: GQLGetLockingPeriods =
530
+ await this._graph.request(lockingPeriodsQuery);
531
+ return data.lockPeriods;
532
+ }
533
+
534
+ getProjectedApy(): string {
535
+ return '10.00';
536
+ }
537
+
538
+ getProjectedUSDC(): string {
539
+ return '20.00';
540
+ }
541
+ }
@@ -0,0 +1,118 @@
1
+ import { gql } from 'graphql-request';
2
+
3
+ export const claimedFeesQuery = gql`
4
+ query GetClaimedFeesForAddress($userAddress: String!) {
5
+ userLockDepositsInfo(id: $userAddress) {
6
+ feesClaimed
7
+ }
8
+ }
9
+ `;
10
+
11
+ export const userEarnedrKsuQuery = gql`
12
+ query GetClaimedFeesForAddress($userAddress: String!) {
13
+ userLockDepositsInfo(id: $userAddress) {
14
+ rKSUAmount
15
+ }
16
+ }
17
+ `;
18
+
19
+ export const userTotalBonusAmountQuery = gql`
20
+ query GetClaimedFeesForAddress($userAddress: String!) {
21
+ userLockDepositsInfo(id: $userAddress) {
22
+ totalKsuBonusAmount
23
+ }
24
+ }
25
+ `;
26
+
27
+ export const userStakedKsuQuery = gql`
28
+ query GetUserLockDepositsInfo($userAddress: String!) {
29
+ userLockDepositsInfo(id: $userAddress) {
30
+ ksuLockedAmount
31
+ }
32
+ }
33
+ `;
34
+
35
+ export const userLocksQuery = gql`
36
+ query GetUserLocks($userAddress: String!) {
37
+ userLocks(
38
+ where: { userLockDepositsInfo: $userAddress, ksuAmount_gt: 0 }
39
+ ) {
40
+ id
41
+ ksuAmount
42
+ endTimestamp
43
+ startTimestamp
44
+ lockPeriod {
45
+ rKSUMultiplier
46
+ lockPeriod
47
+ ksuBonusMultiplier
48
+ id
49
+ }
50
+ rKSUAmount
51
+ userLockDepositsInfo {
52
+ totalKsuBonusAmount
53
+ rKSUAmount
54
+ ksuLockedAmount
55
+ id
56
+ feesClaimed
57
+ }
58
+ }
59
+ }
60
+ `;
61
+
62
+ export const lockingPeriodsQuery = gql`
63
+ query LockingPeriodsQuery {
64
+ lockPeriods(orderBy: lockPeriod, where: { isActive: true }) {
65
+ rKSUMultiplier
66
+ lockPeriod
67
+ ksuBonusMultiplier
68
+ isActive
69
+ id
70
+ }
71
+ }
72
+ `;
73
+
74
+ export const lockingSummariesQuery = gql`
75
+ query LockingSummariesQuery {
76
+ lockingSummaries {
77
+ id
78
+ totalRKsuAmount
79
+ totalKsuLockedAmount
80
+ totalFeesEmitted
81
+ }
82
+ }
83
+ `;
84
+
85
+ export const getAllTranchesQuery = gql`
86
+ query getAllTranches($unusedPools: [String]!) {
87
+ lendingPoolTranches(where: { lendingPool_not_in: $unusedPools }) {
88
+ id
89
+ balance
90
+ }
91
+ }
92
+ `;
93
+
94
+ export const getTotalUserLoyaltsRewardsQuery = gql`
95
+ query getAllUserLoyaltsRewards($userAddress: String!) {
96
+ user(id: $userAddress) {
97
+ id
98
+ totalUserLoyaltyRewards
99
+ }
100
+ }
101
+ `;
102
+
103
+ export const getSystemVariablesQuery = gql`
104
+ query getSystemVariablesQuery {
105
+ systemVariables(id: "SYSTEM_VARIABLES") {
106
+ id
107
+ protocolFeeRate
108
+ priceUpdateEpoch
109
+ performanceFee
110
+ loyaltyThresholds
111
+ ksuEpochTokenPrice
112
+ epochDuration
113
+ ecosystemFeeRate
114
+ clearingPeriodLength
115
+ canOnlyDepositJuniorWhenUserHasRKSU
116
+ }
117
+ }
118
+ `;