@kasufinance/kasu-sdk 1.0.3 → 2.1.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.
- package/.claude/settings.local.json +15 -0
- package/CLAUDE.md +410 -0
- package/README.md +179 -12
- package/dist/bundle.cjs.js +749 -99
- package/dist/bundle.esm.js +745 -101
- package/dist/contracts/IClearingCoordinatorAbi.js +1 -0
- package/dist/contracts/IClearingCoordinatorAbi.js.map +1 -0
- package/dist/contracts/IERC20MetadataAbi.js +1 -0
- package/dist/contracts/IERC20MetadataAbi.js.map +1 -0
- package/dist/contracts/IFeeManagerAbi.js +1 -0
- package/dist/contracts/IFeeManagerAbi.js.map +1 -0
- package/dist/contracts/IKSULockingAbi.js +1 -0
- package/dist/contracts/IKSULockingAbi.js.map +1 -0
- package/dist/contracts/IKasuAllowListAbi.js +1 -0
- package/dist/contracts/IKasuAllowListAbi.js.map +1 -0
- package/dist/contracts/IKasuControllerAbi.js +1 -0
- package/dist/contracts/IKasuControllerAbi.js.map +1 -0
- package/dist/contracts/IKasuNFTsAbi.js +1 -0
- package/dist/contracts/IKasuNFTsAbi.js.map +1 -0
- package/dist/contracts/IKsuPriceAbi.js +1 -0
- package/dist/contracts/IKsuPriceAbi.js.map +1 -0
- package/dist/contracts/ILendingPoolAbi.js +1 -0
- package/dist/contracts/ILendingPoolAbi.js.map +1 -0
- package/dist/contracts/ILendingPoolFactoryAbi.js +1 -0
- package/dist/contracts/ILendingPoolFactoryAbi.js.map +1 -0
- package/dist/contracts/ILendingPoolManagerAbi.js +1 -0
- package/dist/contracts/ILendingPoolManagerAbi.js.map +1 -0
- package/dist/contracts/ILendingPoolTrancheAbi.js +1 -0
- package/dist/contracts/ILendingPoolTrancheAbi.js.map +1 -0
- package/dist/contracts/ISystemVariablesAbi.js +1 -0
- package/dist/contracts/ISystemVariablesAbi.js.map +1 -0
- package/dist/contracts/IUserLoyaltyRewardsAbi.js +1 -0
- package/dist/contracts/IUserLoyaltyRewardsAbi.js.map +1 -0
- package/dist/contracts/IUserManagerAbi.js +1 -0
- package/dist/contracts/IUserManagerAbi.js.map +1 -0
- package/dist/contracts/KSULockBonusAbi.js +1 -0
- package/dist/contracts/KSULockBonusAbi.js.map +1 -0
- package/dist/contracts/KasuPoolExternalTVLAbi.js +1 -0
- package/dist/contracts/KasuPoolExternalTVLAbi.js.map +1 -0
- package/dist/contracts/SwapperAbi.js +1 -0
- package/dist/contracts/SwapperAbi.js.map +1 -0
- package/dist/contracts/common.js +1 -0
- package/dist/contracts/common.js.map +1 -0
- package/dist/contracts/factories/IClearingCoordinatorAbi__factory.js +1 -0
- package/dist/contracts/factories/IClearingCoordinatorAbi__factory.js.map +1 -0
- package/dist/contracts/factories/IERC20MetadataAbi__factory.js +1 -0
- package/dist/contracts/factories/IERC20MetadataAbi__factory.js.map +1 -0
- package/dist/contracts/factories/IFeeManagerAbi__factory.js +1 -0
- package/dist/contracts/factories/IFeeManagerAbi__factory.js.map +1 -0
- package/dist/contracts/factories/IKSULockingAbi__factory.js +1 -0
- package/dist/contracts/factories/IKSULockingAbi__factory.js.map +1 -0
- package/dist/contracts/factories/IKasuAllowListAbi__factory.js +1 -0
- package/dist/contracts/factories/IKasuAllowListAbi__factory.js.map +1 -0
- package/dist/contracts/factories/IKasuControllerAbi__factory.js +1 -0
- package/dist/contracts/factories/IKasuControllerAbi__factory.js.map +1 -0
- package/dist/contracts/factories/IKasuNFTsAbi__factory.js +1 -0
- package/dist/contracts/factories/IKasuNFTsAbi__factory.js.map +1 -0
- package/dist/contracts/factories/IKsuPriceAbi__factory.js +1 -0
- package/dist/contracts/factories/IKsuPriceAbi__factory.js.map +1 -0
- package/dist/contracts/factories/ILendingPoolAbi__factory.js +1 -0
- package/dist/contracts/factories/ILendingPoolAbi__factory.js.map +1 -0
- package/dist/contracts/factories/ILendingPoolFactoryAbi__factory.js +1 -0
- package/dist/contracts/factories/ILendingPoolFactoryAbi__factory.js.map +1 -0
- package/dist/contracts/factories/ILendingPoolManagerAbi__factory.js +1 -0
- package/dist/contracts/factories/ILendingPoolManagerAbi__factory.js.map +1 -0
- package/dist/contracts/factories/ILendingPoolTrancheAbi__factory.js +1 -0
- package/dist/contracts/factories/ILendingPoolTrancheAbi__factory.js.map +1 -0
- package/dist/contracts/factories/ISystemVariablesAbi__factory.js +1 -0
- package/dist/contracts/factories/ISystemVariablesAbi__factory.js.map +1 -0
- package/dist/contracts/factories/IUserLoyaltyRewardsAbi__factory.js +1 -0
- package/dist/contracts/factories/IUserLoyaltyRewardsAbi__factory.js.map +1 -0
- package/dist/contracts/factories/IUserManagerAbi__factory.js +1 -0
- package/dist/contracts/factories/IUserManagerAbi__factory.js.map +1 -0
- package/dist/contracts/factories/KSULockBonusAbi__factory.js +1 -0
- package/dist/contracts/factories/KSULockBonusAbi__factory.js.map +1 -0
- package/dist/contracts/factories/KasuPoolExternalTVLAbi__factory.js +1 -0
- package/dist/contracts/factories/KasuPoolExternalTVLAbi__factory.js.map +1 -0
- package/dist/contracts/factories/SwapperAbi__factory.js +1 -0
- package/dist/contracts/factories/SwapperAbi__factory.js.map +1 -0
- package/dist/contracts/factories/index.js +1 -0
- package/dist/contracts/factories/index.js.map +1 -0
- package/dist/contracts/index.js +1 -0
- package/dist/contracts/index.js.map +1 -0
- package/dist/facade/chain-configs.d.ts +11 -0
- package/dist/facade/chain-configs.js +84 -0
- package/dist/facade/chain-configs.js.map +1 -0
- package/dist/facade/deposits.d.ts +56 -0
- package/dist/facade/deposits.js +87 -0
- package/dist/facade/deposits.js.map +1 -0
- package/dist/facade/index.d.ts +6 -0
- package/dist/facade/index.js +9 -0
- package/dist/facade/index.js.map +1 -0
- package/dist/facade/kasu.d.ts +71 -0
- package/dist/facade/kasu.js +101 -0
- package/dist/facade/kasu.js.map +1 -0
- package/dist/facade/strategies.d.ts +37 -0
- package/dist/facade/strategies.js +112 -0
- package/dist/facade/strategies.js.map +1 -0
- package/dist/facade/types.d.ts +127 -0
- package/dist/facade/types.js +2 -0
- package/dist/facade/types.js.map +1 -0
- package/dist/facade/user-portfolio.d.ts +35 -0
- package/dist/facade/user-portfolio.js +53 -0
- package/dist/facade/user-portfolio.js.map +1 -0
- package/dist/index.d.ts +9 -17
- package/dist/index.js +10 -16
- package/dist/index.js.map +1 -0
- package/dist/kasu-sdk.d.ts +17 -0
- package/dist/kasu-sdk.js +17 -0
- package/dist/kasu-sdk.js.map +1 -0
- package/dist/sdk-config.d.ts +28 -4
- package/dist/sdk-config.js +9 -6
- package/dist/sdk-config.js.map +1 -0
- package/dist/services/DataService/data-service.d.ts +9 -2
- package/dist/services/DataService/data-service.js +91 -52
- package/dist/services/DataService/data-service.js.map +1 -0
- package/dist/services/DataService/directus-types.js +1 -0
- package/dist/services/DataService/directus-types.js.map +1 -0
- package/dist/services/DataService/queries.d.ts +0 -1
- package/dist/services/DataService/queries.js +1 -8
- package/dist/services/DataService/queries.js.map +1 -0
- package/dist/services/DataService/subgraph-types.d.ts +0 -6
- package/dist/services/DataService/subgraph-types.js +1 -0
- package/dist/services/DataService/subgraph-types.js.map +1 -0
- package/dist/services/DataService/types.d.ts +0 -1
- package/dist/services/DataService/types.js +1 -0
- package/dist/services/DataService/types.js.map +1 -0
- package/dist/services/Locking/locking.d.ts +4 -2
- package/dist/services/Locking/locking.js +90 -7
- package/dist/services/Locking/locking.js.map +1 -0
- package/dist/services/Locking/queries.js +1 -0
- package/dist/services/Locking/queries.js.map +1 -0
- package/dist/services/Locking/types.js +1 -0
- package/dist/services/Locking/types.js.map +1 -0
- package/dist/services/Portfolio/portfolio.d.ts +41 -2
- package/dist/services/Portfolio/portfolio.js +146 -34
- package/dist/services/Portfolio/portfolio.js.map +1 -0
- package/dist/services/Portfolio/queries.js +1 -0
- package/dist/services/Portfolio/queries.js.map +1 -0
- package/dist/services/Portfolio/types.js +1 -0
- package/dist/services/Portfolio/types.js.map +1 -0
- package/dist/services/Swapper/swapper.js +1 -0
- package/dist/services/Swapper/swapper.js.map +1 -0
- package/dist/services/Swapper/types.js +1 -0
- package/dist/services/Swapper/types.js.map +1 -0
- package/dist/services/UserLending/helper.js +1 -0
- package/dist/services/UserLending/helper.js.map +1 -0
- package/dist/services/UserLending/queries.js +1 -0
- package/dist/services/UserLending/queries.js.map +1 -0
- package/dist/services/UserLending/subgraph-types.js +1 -0
- package/dist/services/UserLending/subgraph-types.js.map +1 -0
- package/dist/services/UserLending/types.js +1 -0
- package/dist/services/UserLending/types.js.map +1 -0
- package/dist/services/UserLending/user-lending.js +1 -0
- package/dist/services/UserLending/user-lending.js.map +1 -0
- package/dist/services/shared.js +1 -0
- package/dist/services/shared.js.map +1 -0
- package/dist/tests/facade.test.d.ts +1 -0
- package/dist/tests/facade.test.js +196 -0
- package/dist/tests/facade.test.js.map +1 -0
- package/dist/tests/sample.test.js +20 -14
- package/dist/tests/sample.test.js.map +1 -0
- package/dist/utils/deployment-mode.d.ts +6 -0
- package/dist/utils/deployment-mode.js +8 -0
- package/dist/utils/deployment-mode.js.map +1 -0
- package/package.json +3 -2
- package/src/facade/chain-configs.ts +93 -0
- package/src/facade/deposits.ts +102 -0
- package/src/facade/index.ts +26 -0
- package/src/facade/kasu.ts +144 -0
- package/src/facade/strategies.ts +119 -0
- package/src/facade/types.ts +168 -0
- package/src/facade/user-portfolio.ts +73 -0
- package/src/index.ts +59 -25
- package/src/kasu-sdk.ts +27 -0
- package/src/sdk-config.ts +36 -15
- package/src/services/DataService/data-service.ts +105 -65
- package/src/services/DataService/queries.ts +0 -9
- package/src/services/DataService/subgraph-types.ts +0 -7
- package/src/services/DataService/types.ts +0 -1
- package/src/services/Locking/locking.ts +113 -12
- package/src/services/Portfolio/portfolio.ts +276 -50
- package/src/tests/facade.test.ts +245 -0
- package/src/tests/sample.test.ts +7 -9
- package/src/utils/deployment-mode.ts +9 -0
- package/tsconfig.json +1 -1
package/dist/bundle.esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { formatUnits, parseUnits, formatEther, defaultAbiCoder, parseEther } from 'ethers/lib/utils';
|
|
2
|
-
import { utils as utils$2, Contract,
|
|
2
|
+
import { utils as utils$2, Contract, BigNumber, ethers } from 'ethers';
|
|
3
3
|
|
|
4
4
|
function _mergeNamespaces(n, m) {
|
|
5
5
|
m.forEach(function (e) {
|
|
@@ -15614,14 +15614,6 @@ function filterArray(array, id_in) {
|
|
|
15614
15614
|
}
|
|
15615
15615
|
}
|
|
15616
15616
|
|
|
15617
|
-
const getPlumeTvl = gql `
|
|
15618
|
-
{
|
|
15619
|
-
lendingPools {
|
|
15620
|
-
id
|
|
15621
|
-
balance
|
|
15622
|
-
}
|
|
15623
|
-
}
|
|
15624
|
-
`;
|
|
15625
15617
|
const getPoolOverviewQuery = (ids) => gql `
|
|
15626
15618
|
query getAllPoolOverview($epochId: String!, $unusedPools: [String]!) {
|
|
15627
15619
|
lendingPools(
|
|
@@ -15775,17 +15767,36 @@ const getLendingPoolWithdrawalAndDepositsQuery = gql `
|
|
|
15775
15767
|
class DataService {
|
|
15776
15768
|
constructor(_kasuConfig, signerOrProvider) {
|
|
15777
15769
|
this._kasuConfig = _kasuConfig;
|
|
15778
|
-
this._plumeTvl = new Map();
|
|
15779
15770
|
this._externalTvlAbi = KasuPoolExternalTVLAbi__factory.connect(_kasuConfig.contracts.ExternalTVL, signerOrProvider);
|
|
15780
15771
|
this._graph = new GraphQLClient(_kasuConfig.subgraphUrl);
|
|
15781
|
-
|
|
15782
|
-
|
|
15783
|
-
|
|
15784
|
-
|
|
15772
|
+
if (_kasuConfig.directusUrl) {
|
|
15773
|
+
this._directus = le(_kasuConfig.directusUrl)
|
|
15774
|
+
.with(ne())
|
|
15775
|
+
.with(Zp());
|
|
15776
|
+
}
|
|
15777
|
+
else {
|
|
15778
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any
|
|
15779
|
+
this._directus = null;
|
|
15780
|
+
}
|
|
15785
15781
|
}
|
|
15786
15782
|
getUrlFromFile(fileName) {
|
|
15787
15783
|
return `${this._kasuConfig.directusUrl}assets/${fileName}`;
|
|
15788
15784
|
}
|
|
15785
|
+
/**
|
|
15786
|
+
* Maps a pool ID to its metadata source pool ID.
|
|
15787
|
+
* Used for chains (XDC, Plume) that share Directus metadata with Base pools.
|
|
15788
|
+
*/
|
|
15789
|
+
getMetadataPoolId(poolId) {
|
|
15790
|
+
var _a;
|
|
15791
|
+
const normalizedId = poolId.toLowerCase();
|
|
15792
|
+
return (_a = this._kasuConfig.poolMetadataMapping[normalizedId]) !== null && _a !== void 0 ? _a : normalizedId;
|
|
15793
|
+
}
|
|
15794
|
+
/**
|
|
15795
|
+
* Maps an array of pool IDs to their metadata source pool IDs.
|
|
15796
|
+
*/
|
|
15797
|
+
getMetadataPoolIds(poolIds) {
|
|
15798
|
+
return poolIds.map((id) => this.getMetadataPoolId(id));
|
|
15799
|
+
}
|
|
15789
15800
|
calculatePoolCapacity(poolCapacities, poolCapacityPercentages, index, spillOver, lendingPoolSubgraph, lendingPoolConfig) {
|
|
15790
15801
|
const desiredDrawAmount = lendingPoolConfig.desiredDrawAmount; // subgraph
|
|
15791
15802
|
const desiredTrancheRatio = lendingPoolConfig.tranchesConfig[index].desiredRatio;
|
|
@@ -15843,7 +15854,7 @@ class DataService {
|
|
|
15843
15854
|
}
|
|
15844
15855
|
getPoolOverview(epochId, id_in) {
|
|
15845
15856
|
return __awaiter(this, void 0, void 0, function* () {
|
|
15846
|
-
var _a, _b, _c;
|
|
15857
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
|
|
15847
15858
|
const trancheNames = [
|
|
15848
15859
|
['Senior'],
|
|
15849
15860
|
['Junior', 'Senior'],
|
|
@@ -15853,29 +15864,39 @@ class DataService {
|
|
|
15853
15864
|
unusedPools: this._kasuConfig.UNUSED_LENDING_POOL_IDS,
|
|
15854
15865
|
epochId,
|
|
15855
15866
|
});
|
|
15856
|
-
if (!this._plumeTvl.size) {
|
|
15857
|
-
const plumeResults = yield this._plumeGraph.request(getPlumeTvl);
|
|
15858
|
-
for (const pool of plumeResults.lendingPools) {
|
|
15859
|
-
this._plumeTvl.set(pool.id, pool.balance);
|
|
15860
|
-
}
|
|
15861
|
-
}
|
|
15862
15867
|
if (!this._directusPoolOverview) {
|
|
15863
|
-
|
|
15864
|
-
|
|
15865
|
-
|
|
15866
|
-
|
|
15867
|
-
|
|
15868
|
-
|
|
15869
|
-
|
|
15868
|
+
if (this._kasuConfig.directusUrl) {
|
|
15869
|
+
try {
|
|
15870
|
+
this._directusPoolOverview = yield this._directus.request(bs('PoolOverview', {
|
|
15871
|
+
filter: {
|
|
15872
|
+
enabled: {
|
|
15873
|
+
_eq: true,
|
|
15874
|
+
},
|
|
15875
|
+
},
|
|
15876
|
+
}));
|
|
15877
|
+
}
|
|
15878
|
+
catch (error) {
|
|
15879
|
+
console.warn('Directus fetch failed, falling back to on-chain data only:', error);
|
|
15880
|
+
this._directusPoolOverview = [];
|
|
15881
|
+
}
|
|
15882
|
+
}
|
|
15883
|
+
else {
|
|
15884
|
+
this._directusPoolOverview = [];
|
|
15885
|
+
}
|
|
15870
15886
|
}
|
|
15871
15887
|
const offchainTvlMap = yield this.getOffChainTvl(poolOverviewResults.lendingPools.map(({ id }) => id));
|
|
15872
15888
|
const retn = [];
|
|
15873
15889
|
for (const lendingPoolSubgraph of poolOverviewResults.lendingPools) {
|
|
15874
|
-
|
|
15890
|
+
// Use metadata mapping if available (for XDC/Plume pools that share metadata with Base)
|
|
15891
|
+
const metadataPoolId = (_a = this._kasuConfig.poolMetadataMapping[lendingPoolSubgraph.id]) !== null && _a !== void 0 ? _a : lendingPoolSubgraph.id;
|
|
15892
|
+
const lendingPoolDirectus = this._directusPoolOverview.find((r) => r.id.toLowerCase() === metadataPoolId);
|
|
15875
15893
|
const lendingPoolConfig = lendingPoolSubgraph.configuration;
|
|
15876
15894
|
if (!lendingPoolDirectus) {
|
|
15877
|
-
console.warn("Couldn't find directus pool for id: ", lendingPoolSubgraph.id
|
|
15878
|
-
|
|
15895
|
+
console.warn("Couldn't find directus pool for id: ", lendingPoolSubgraph.id, metadataPoolId !== lendingPoolSubgraph.id
|
|
15896
|
+
? `(mapped from ${metadataPoolId})`
|
|
15897
|
+
: '');
|
|
15898
|
+
// When Directus is unavailable or pool has no CMS entry,
|
|
15899
|
+
// use a fallback so the pool is still returned with on-chain data.
|
|
15879
15900
|
}
|
|
15880
15901
|
const poolCapacities = this.calculatePoolCapacity([], [], 0, 0, lendingPoolSubgraph, lendingPoolConfig);
|
|
15881
15902
|
const tranches = lendingPoolSubgraph.tranches
|
|
@@ -15942,49 +15963,50 @@ class DataService {
|
|
|
15942
15963
|
: parseFloat(tranche.balance) / trancheBalanceSum;
|
|
15943
15964
|
averageApy += parseFloat(trancheData.averageApy) * weight;
|
|
15944
15965
|
}
|
|
15945
|
-
const plumeTvl = lendingPoolDirectus.plumeStrategy &&
|
|
15946
|
-
this._plumeTvl.has(lendingPoolDirectus.plumeStrategy)
|
|
15947
|
-
? (_a = this._plumeTvl.get(lendingPoolDirectus.plumeStrategy)) !== null && _a !== void 0 ? _a : '0'
|
|
15948
|
-
: '0';
|
|
15949
15966
|
const offChainTvl = (_b = offchainTvlMap.get(lendingPoolSubgraph.id)) !== null && _b !== void 0 ? _b : '0';
|
|
15950
15967
|
const poolOverview = {
|
|
15951
15968
|
id: lendingPoolSubgraph.id,
|
|
15952
|
-
security: lendingPoolDirectus.security,
|
|
15953
|
-
enabled: lendingPoolDirectus.enabled,
|
|
15954
|
-
isOversubscribed: lendingPoolDirectus.oversubscribed,
|
|
15969
|
+
security: (_c = lendingPoolDirectus === null || lendingPoolDirectus === void 0 ? void 0 : lendingPoolDirectus.security) !== null && _c !== void 0 ? _c : [],
|
|
15970
|
+
enabled: (_d = lendingPoolDirectus === null || lendingPoolDirectus === void 0 ? void 0 : lendingPoolDirectus.enabled) !== null && _d !== void 0 ? _d : true,
|
|
15971
|
+
isOversubscribed: (_e = lendingPoolDirectus === null || lendingPoolDirectus === void 0 ? void 0 : lendingPoolDirectus.oversubscribed) !== null && _e !== void 0 ? _e : false,
|
|
15955
15972
|
apy: averageApy,
|
|
15956
|
-
description: lendingPoolDirectus.description,
|
|
15957
|
-
liteDescription: lendingPoolDirectus.liteDescription,
|
|
15958
|
-
thumbnailImageUrl:
|
|
15959
|
-
|
|
15960
|
-
|
|
15961
|
-
|
|
15962
|
-
|
|
15963
|
-
|
|
15964
|
-
|
|
15965
|
-
|
|
15966
|
-
|
|
15967
|
-
|
|
15968
|
-
|
|
15973
|
+
description: (_f = lendingPoolDirectus === null || lendingPoolDirectus === void 0 ? void 0 : lendingPoolDirectus.description) !== null && _f !== void 0 ? _f : '',
|
|
15974
|
+
liteDescription: (_g = lendingPoolDirectus === null || lendingPoolDirectus === void 0 ? void 0 : lendingPoolDirectus.liteDescription) !== null && _g !== void 0 ? _g : '',
|
|
15975
|
+
thumbnailImageUrl: (lendingPoolDirectus === null || lendingPoolDirectus === void 0 ? void 0 : lendingPoolDirectus.thumbnailImage)
|
|
15976
|
+
? this.getUrlFromFile(lendingPoolDirectus.thumbnailImage)
|
|
15977
|
+
: '',
|
|
15978
|
+
bannerImageUrl: (lendingPoolDirectus === null || lendingPoolDirectus === void 0 ? void 0 : lendingPoolDirectus.bannerImage)
|
|
15979
|
+
? this.getUrlFromFile(lendingPoolDirectus.bannerImage)
|
|
15980
|
+
: '',
|
|
15981
|
+
strategyDeckUrl: (lendingPoolDirectus === null || lendingPoolDirectus === void 0 ? void 0 : lendingPoolDirectus.strategyDeck)
|
|
15982
|
+
? this.getUrlFromFile(lendingPoolDirectus.strategyDeck)
|
|
15983
|
+
: '',
|
|
15984
|
+
assetClass: (_h = lendingPoolDirectus === null || lendingPoolDirectus === void 0 ? void 0 : lendingPoolDirectus.assetClass) !== null && _h !== void 0 ? _h : '',
|
|
15985
|
+
industryExposure: (_j = lendingPoolDirectus === null || lendingPoolDirectus === void 0 ? void 0 : lendingPoolDirectus.industryExposure) !== null && _j !== void 0 ? _j : '',
|
|
15986
|
+
poolApyStructure: (_k = lendingPoolDirectus === null || lendingPoolDirectus === void 0 ? void 0 : lendingPoolDirectus.poolApyStructure) !== null && _k !== void 0 ? _k : 'Variable',
|
|
15987
|
+
apyExpiryDate: (_l = lendingPoolDirectus === null || lendingPoolDirectus === void 0 ? void 0 : lendingPoolDirectus.apyExpiryDate) !== null && _l !== void 0 ? _l : null,
|
|
15988
|
+
poolInvestmentTerm: (_m = lendingPoolDirectus === null || lendingPoolDirectus === void 0 ? void 0 : lendingPoolDirectus.poolInvestmentTerm) !== null && _m !== void 0 ? _m : '',
|
|
15989
|
+
loanStructure: (_o = lendingPoolDirectus === null || lendingPoolDirectus === void 0 ? void 0 : lendingPoolDirectus.loanStructure) !== null && _o !== void 0 ? _o : '',
|
|
15990
|
+
poolName: (_p = lendingPoolDirectus === null || lendingPoolDirectus === void 0 ? void 0 : lendingPoolDirectus.poolName) !== null && _p !== void 0 ? _p : lendingPoolSubgraph.name,
|
|
15991
|
+
subheading: lendingPoolDirectus === null || lendingPoolDirectus === void 0 ? void 0 : lendingPoolDirectus.subheading,
|
|
15969
15992
|
totalValueLocked: {
|
|
15970
15993
|
total: (parseFloat(lendingPoolSubgraph.balance) +
|
|
15971
|
-
parseFloat(plumeTvl) +
|
|
15972
15994
|
parseFloat(offChainTvl)).toString(),
|
|
15973
15995
|
offchain: offChainTvl,
|
|
15974
|
-
plume: plumeTvl,
|
|
15975
15996
|
},
|
|
15976
|
-
loansUnderManagement: lendingPoolDirectus.loansUnderManagement,
|
|
15997
|
+
loansUnderManagement: (_q = lendingPoolDirectus === null || lendingPoolDirectus === void 0 ? void 0 : lendingPoolDirectus.loansUnderManagement) !== null && _q !== void 0 ? _q : '0',
|
|
15977
15998
|
yieldEarned: lendingPoolSubgraph.totalUserInterestAmount,
|
|
15978
15999
|
poolCapacity: poolCapacitySum.toString(),
|
|
15979
16000
|
poolCapacityPercentage: poolCapacityPercentageSum.toString(),
|
|
15980
|
-
activeLoans: lendingPoolDirectus.activeLoans,
|
|
15981
|
-
loanFundsOriginated: lendingPoolDirectus.loanFundsOriginated,
|
|
16001
|
+
activeLoans: (_r = lendingPoolDirectus === null || lendingPoolDirectus === void 0 ? void 0 : lendingPoolDirectus.activeLoans) !== null && _r !== void 0 ? _r : '0',
|
|
16002
|
+
loanFundsOriginated: (_s = lendingPoolDirectus === null || lendingPoolDirectus === void 0 ? void 0 : lendingPoolDirectus.loanFundsOriginated) !== null && _s !== void 0 ? _s : '0',
|
|
15982
16003
|
tranches: tranches,
|
|
15983
16004
|
isActive: !lendingPoolSubgraph.isStopped,
|
|
15984
16005
|
requestEpochsInAdvance: lendingPoolSubgraph.configuration
|
|
15985
16006
|
.lendingPoolWithdrawalConfig.requestEpochsInAdvance,
|
|
15986
16007
|
};
|
|
15987
|
-
// show only enabled pools
|
|
16008
|
+
// When Directus is available, show only enabled pools.
|
|
16009
|
+
// When Directus is unavailable, include all pools.
|
|
15988
16010
|
if (poolOverview.enabled) {
|
|
15989
16011
|
retn.push(poolOverview);
|
|
15990
16012
|
}
|
|
@@ -16204,7 +16226,11 @@ class DataService {
|
|
|
16204
16226
|
const lendingPoolsWithdrawalsAndDepositsSubgraph = yield this._graph.request(getLendingPoolWithdrawalAndDepositsQuery, { unusedPools: this._kasuConfig.UNUSED_LENDING_POOL_IDS });
|
|
16205
16227
|
const retn = [];
|
|
16206
16228
|
for (const data of poolRepaymentDirectus) {
|
|
16207
|
-
|
|
16229
|
+
// Find subgraph pool that maps to this Directus pool
|
|
16230
|
+
// On non-Base chains, subgraph pool IDs are different from Directus poolIdFK
|
|
16231
|
+
// Use getMetadataPoolId to map subgraph pool ID -> Directus/Base pool ID
|
|
16232
|
+
const lendingPoolSubgraph = lendingPoolsWithdrawalsAndDepositsSubgraph.lendingPools.find((pool) => this.getMetadataPoolId(pool.id) ===
|
|
16233
|
+
data.poolIdFK.toLowerCase());
|
|
16208
16234
|
if (lendingPoolSubgraph === undefined) {
|
|
16209
16235
|
continue;
|
|
16210
16236
|
}
|
|
@@ -16293,9 +16319,13 @@ class DataService {
|
|
|
16293
16319
|
retn.totalYieldEarned += parseFloat(poolOverview.yieldEarned);
|
|
16294
16320
|
}
|
|
16295
16321
|
for (const poolOverview of poolOverviews) {
|
|
16296
|
-
|
|
16322
|
+
// Map to metadata pool ID for Directus lookup (XDC pools → Base pools)
|
|
16323
|
+
const metadataPoolId = this.getMetadataPoolId(poolOverview.id);
|
|
16324
|
+
const riskManagement = riskManagements.find((rm) => rm.poolIdFK.toLowerCase() === metadataPoolId.toLowerCase());
|
|
16297
16325
|
if (!riskManagement) {
|
|
16298
|
-
console.warn("Couldn't find risk management for id: ", poolOverview.id
|
|
16326
|
+
console.warn("Couldn't find risk management for id: ", poolOverview.id, metadataPoolId !== poolOverview.id
|
|
16327
|
+
? `(mapped to ${metadataPoolId})`
|
|
16328
|
+
: '');
|
|
16299
16329
|
continue;
|
|
16300
16330
|
}
|
|
16301
16331
|
const weight = retn.totalLoanFundsOriginated === 0
|
|
@@ -16333,14 +16363,18 @@ class DataService {
|
|
|
16333
16363
|
}
|
|
16334
16364
|
|
|
16335
16365
|
class KSULocking {
|
|
16336
|
-
/**
|
|
16337
|
-
*
|
|
16338
|
-
*/
|
|
16339
16366
|
constructor(_kasuConfig, signerOrProvider) {
|
|
16340
16367
|
this._kasuConfig = _kasuConfig;
|
|
16341
16368
|
this.apyBonuses = [0, 0.001, 0.002];
|
|
16369
|
+
this._isLiteDeployment = _kasuConfig.isLiteDeployment;
|
|
16342
16370
|
this._contractAbi = IKSULockingAbi__factory.connect(_kasuConfig.contracts.IKSULocking, signerOrProvider);
|
|
16343
|
-
|
|
16371
|
+
// Only initialize KSU token contract if not a Lite deployment and address is provided
|
|
16372
|
+
if (!this._isLiteDeployment && _kasuConfig.contracts.KSUToken) {
|
|
16373
|
+
this._kasuToken = IERC20MetadataAbi__factory.connect(_kasuConfig.contracts.KSUToken, signerOrProvider);
|
|
16374
|
+
}
|
|
16375
|
+
else {
|
|
16376
|
+
this._kasuToken = null;
|
|
16377
|
+
}
|
|
16344
16378
|
this._userManagerAbi = IUserManagerAbi__factory.connect(_kasuConfig.contracts.UserManager, signerOrProvider);
|
|
16345
16379
|
this._systemVariablesAbi = ISystemVariablesAbi__factory.connect(_kasuConfig.contracts.SystemVariables, signerOrProvider);
|
|
16346
16380
|
this._ksuPriceAbi = IKsuPriceAbi__factory.connect(_kasuConfig.contracts.KsuPrice, signerOrProvider);
|
|
@@ -16348,13 +16382,25 @@ class KSULocking {
|
|
|
16348
16382
|
this._graph = new GraphQLClient(_kasuConfig.subgraphUrl);
|
|
16349
16383
|
this._userLoyaltyRewardsAbi = IUserLoyaltyRewardsAbi__factory.connect(_kasuConfig.contracts.UserLoyaltyRewards, signerOrProvider);
|
|
16350
16384
|
}
|
|
16385
|
+
/**
|
|
16386
|
+
* Check if this is a Lite deployment (no KSU token functionality)
|
|
16387
|
+
*/
|
|
16388
|
+
get isLiteDeployment() {
|
|
16389
|
+
return this._isLiteDeployment;
|
|
16390
|
+
}
|
|
16351
16391
|
lockKSUTokens(amount, lockPeriod) {
|
|
16352
16392
|
return __awaiter(this, void 0, void 0, function* () {
|
|
16393
|
+
if (this._isLiteDeployment) {
|
|
16394
|
+
throw new Error('Locking is not available on Lite deployments');
|
|
16395
|
+
}
|
|
16353
16396
|
return this._contractAbi.lock(amount, lockPeriod);
|
|
16354
16397
|
});
|
|
16355
16398
|
}
|
|
16356
16399
|
lockKSUWithPermit(amount, lockPeriod, permit) {
|
|
16357
16400
|
return __awaiter(this, void 0, void 0, function* () {
|
|
16401
|
+
if (this._isLiteDeployment) {
|
|
16402
|
+
throw new Error('Locking is not available on Lite deployments');
|
|
16403
|
+
}
|
|
16358
16404
|
const amountBN = BigNumber.from(amount);
|
|
16359
16405
|
const lockPeriodBN = BigNumber.from(lockPeriod);
|
|
16360
16406
|
const ksuPermit = {
|
|
@@ -16369,16 +16415,29 @@ class KSULocking {
|
|
|
16369
16415
|
}
|
|
16370
16416
|
unlockKSU(amount, userLockId) {
|
|
16371
16417
|
return __awaiter(this, void 0, void 0, function* () {
|
|
16418
|
+
if (this._isLiteDeployment) {
|
|
16419
|
+
throw new Error('Locking is not available on Lite deployments');
|
|
16420
|
+
}
|
|
16372
16421
|
return this._contractAbi.unlock(amount, userLockId);
|
|
16373
16422
|
});
|
|
16374
16423
|
}
|
|
16375
16424
|
claimFees() {
|
|
16376
16425
|
return __awaiter(this, void 0, void 0, function* () {
|
|
16426
|
+
if (this._isLiteDeployment) {
|
|
16427
|
+
throw new Error('Fee claiming is not available on Lite deployments');
|
|
16428
|
+
}
|
|
16377
16429
|
return yield this._contractAbi.claimFees();
|
|
16378
16430
|
});
|
|
16379
16431
|
}
|
|
16380
16432
|
lockDetails(lockPeriod) {
|
|
16381
16433
|
return __awaiter(this, void 0, void 0, function* () {
|
|
16434
|
+
if (this._isLiteDeployment) {
|
|
16435
|
+
return {
|
|
16436
|
+
rKsuMultiplier: 0,
|
|
16437
|
+
ksuBonusMultiplier: 0,
|
|
16438
|
+
isActive: false,
|
|
16439
|
+
};
|
|
16440
|
+
}
|
|
16382
16441
|
const result = yield this._contractAbi.lockDetails(lockPeriod);
|
|
16383
16442
|
return {
|
|
16384
16443
|
rKsuMultiplier: result[0].toNumber(),
|
|
@@ -16389,12 +16448,15 @@ class KSULocking {
|
|
|
16389
16448
|
}
|
|
16390
16449
|
userTotalDeposits(userAddress) {
|
|
16391
16450
|
return __awaiter(this, void 0, void 0, function* () {
|
|
16451
|
+
if (this._isLiteDeployment) {
|
|
16452
|
+
return BigNumber.from(0);
|
|
16453
|
+
}
|
|
16392
16454
|
return yield this._contractAbi.userTotalDeposits(userAddress);
|
|
16393
16455
|
});
|
|
16394
16456
|
}
|
|
16395
16457
|
calculateUserLockProjectedProtocolFeeRewards(epochId, KSULocked, lockPeriod) {
|
|
16396
16458
|
return __awaiter(this, void 0, void 0, function* () {
|
|
16397
|
-
if (KSULocked === 0) {
|
|
16459
|
+
if (this._isLiteDeployment || KSULocked === 0) {
|
|
16398
16460
|
return 0;
|
|
16399
16461
|
}
|
|
16400
16462
|
const lockingSummarySubgraph = yield this._graph.request(lockingSummariesQuery);
|
|
@@ -16440,6 +16502,9 @@ class KSULocking {
|
|
|
16440
16502
|
}
|
|
16441
16503
|
getUserLocks(userAddress) {
|
|
16442
16504
|
return __awaiter(this, void 0, void 0, function* () {
|
|
16505
|
+
if (this._isLiteDeployment) {
|
|
16506
|
+
return [];
|
|
16507
|
+
}
|
|
16443
16508
|
const result = yield this._graph.request(userLocksQuery, {
|
|
16444
16509
|
userAddress: userAddress.toLowerCase(),
|
|
16445
16510
|
});
|
|
@@ -16465,8 +16530,14 @@ class KSULocking {
|
|
|
16465
16530
|
}
|
|
16466
16531
|
getUserBonusData(userAddress) {
|
|
16467
16532
|
return __awaiter(this, void 0, void 0, function* () {
|
|
16468
|
-
|
|
16469
|
-
|
|
16533
|
+
if (this._isLiteDeployment) {
|
|
16534
|
+
return {
|
|
16535
|
+
ksuBonusAndRewards: '0',
|
|
16536
|
+
ksuBonusAndRewardsLifetime: '0',
|
|
16537
|
+
protocolFeesEarned: '0',
|
|
16538
|
+
totalLockedAmount: '0',
|
|
16539
|
+
};
|
|
16540
|
+
}
|
|
16470
16541
|
const DECIMALS = 18;
|
|
16471
16542
|
// Normalized user address
|
|
16472
16543
|
const normalizedAddress = userAddress.toLowerCase();
|
|
@@ -16499,6 +16570,10 @@ class KSULocking {
|
|
|
16499
16570
|
});
|
|
16500
16571
|
}
|
|
16501
16572
|
getLoyaltyLevelAndApyBonusFromRatio(rKSUtoUSDCRatio) {
|
|
16573
|
+
// On Lite deployments, always return level 0 with no bonus
|
|
16574
|
+
if (this._isLiteDeployment) {
|
|
16575
|
+
return { loyaltyLevel: 0, apyBonus: 0 };
|
|
16576
|
+
}
|
|
16502
16577
|
if (rKSUtoUSDCRatio < 0.01) {
|
|
16503
16578
|
return { loyaltyLevel: 0, apyBonus: this.apyBonuses[0] };
|
|
16504
16579
|
}
|
|
@@ -16509,6 +16584,9 @@ class KSULocking {
|
|
|
16509
16584
|
}
|
|
16510
16585
|
getRKSUvsUSDCRatio(rKSUAmount, userAddress) {
|
|
16511
16586
|
return __awaiter(this, void 0, void 0, function* () {
|
|
16587
|
+
if (this._isLiteDeployment) {
|
|
16588
|
+
return 0;
|
|
16589
|
+
}
|
|
16512
16590
|
const [depositedAmount, pendingAmount] = yield this._userManagerAbi.userTotalPendingAndActiveDepositedAmountForCurrentEpoch(userAddress);
|
|
16513
16591
|
const ksuPrice = yield this._systemVariablesAbi.ksuEpochTokenPrice();
|
|
16514
16592
|
const rKSUAmountBignumber = ethers.utils.parseUnits(rKSUAmount, 18);
|
|
@@ -16522,6 +16600,9 @@ class KSULocking {
|
|
|
16522
16600
|
}
|
|
16523
16601
|
getClaimableRewards(userAddress) {
|
|
16524
16602
|
return __awaiter(this, void 0, void 0, function* () {
|
|
16603
|
+
if (this._isLiteDeployment) {
|
|
16604
|
+
return BigNumber.from(0);
|
|
16605
|
+
}
|
|
16525
16606
|
const result = yield this._contractAbi.rewards(userAddress);
|
|
16526
16607
|
return result;
|
|
16527
16608
|
});
|
|
@@ -16529,6 +16610,7 @@ class KSULocking {
|
|
|
16529
16610
|
getKasuTokenPrice() {
|
|
16530
16611
|
return __awaiter(this, void 0, void 0, function* () {
|
|
16531
16612
|
const decimals = 18;
|
|
16613
|
+
// Price can still be queried on Lite deployments (set to 0 or configured value)
|
|
16532
16614
|
return Promise.resolve({
|
|
16533
16615
|
price: yield this._ksuPriceAbi.ksuTokenPrice(),
|
|
16534
16616
|
decimals,
|
|
@@ -16547,6 +16629,9 @@ class KSULocking {
|
|
|
16547
16629
|
getLifetimeRewards(userAddress, rewardDecimals, claimableRewards) {
|
|
16548
16630
|
return __awaiter(this, void 0, void 0, function* () {
|
|
16549
16631
|
var _a, _b;
|
|
16632
|
+
if (this._isLiteDeployment) {
|
|
16633
|
+
return BigNumber.from(0);
|
|
16634
|
+
}
|
|
16550
16635
|
const result = yield this._graph.request(claimedFeesQuery, {
|
|
16551
16636
|
userAddress: userAddress.toLowerCase(),
|
|
16552
16637
|
});
|
|
@@ -16558,6 +16643,9 @@ class KSULocking {
|
|
|
16558
16643
|
});
|
|
16559
16644
|
}
|
|
16560
16645
|
getLaunchBonusAmount(lockAmount, bonusMultiplier, bonusTokensLeft) {
|
|
16646
|
+
if (this._isLiteDeployment) {
|
|
16647
|
+
return BigNumber.from(0);
|
|
16648
|
+
}
|
|
16561
16649
|
const bonusMultiplierBN = ethers.utils.parseUnits(bonusMultiplier.toFixed(2), 2);
|
|
16562
16650
|
const projectedBonus = lockAmount.mul(bonusMultiplierBN).div(100);
|
|
16563
16651
|
if (bonusTokensLeft.gt(projectedBonus)) {
|
|
@@ -16569,6 +16657,9 @@ class KSULocking {
|
|
|
16569
16657
|
}
|
|
16570
16658
|
getUserStakedKsu(userAddress) {
|
|
16571
16659
|
return __awaiter(this, void 0, void 0, function* () {
|
|
16660
|
+
if (this._isLiteDeployment) {
|
|
16661
|
+
return '0';
|
|
16662
|
+
}
|
|
16572
16663
|
const result = yield this._graph.request(userStakedKsuQuery, {
|
|
16573
16664
|
userAddress: userAddress.toLowerCase(),
|
|
16574
16665
|
});
|
|
@@ -16580,6 +16671,9 @@ class KSULocking {
|
|
|
16580
16671
|
}
|
|
16581
16672
|
getUserEarnedrKsu(userAddress) {
|
|
16582
16673
|
return __awaiter(this, void 0, void 0, function* () {
|
|
16674
|
+
if (this._isLiteDeployment) {
|
|
16675
|
+
return '0';
|
|
16676
|
+
}
|
|
16583
16677
|
const result = yield this._graph.request(userEarnedrKsuQuery, {
|
|
16584
16678
|
userAddress: userAddress.toLowerCase(),
|
|
16585
16679
|
});
|
|
@@ -16591,6 +16685,9 @@ class KSULocking {
|
|
|
16591
16685
|
}
|
|
16592
16686
|
getUserTotalBonusAmount(userAddress) {
|
|
16593
16687
|
return __awaiter(this, void 0, void 0, function* () {
|
|
16688
|
+
if (this._isLiteDeployment) {
|
|
16689
|
+
return '0';
|
|
16690
|
+
}
|
|
16594
16691
|
const result = yield this._graph.request(userTotalBonusAmountQuery, {
|
|
16595
16692
|
userAddress: userAddress.toLowerCase(),
|
|
16596
16693
|
});
|
|
@@ -16602,6 +16699,12 @@ class KSULocking {
|
|
|
16602
16699
|
}
|
|
16603
16700
|
getLockingRewards(userAddress) {
|
|
16604
16701
|
return __awaiter(this, void 0, void 0, function* () {
|
|
16702
|
+
if (this._isLiteDeployment) {
|
|
16703
|
+
return {
|
|
16704
|
+
claimableRewards: '0',
|
|
16705
|
+
lifeTimeRewards: '0',
|
|
16706
|
+
};
|
|
16707
|
+
}
|
|
16605
16708
|
const rewardDecimals = 6;
|
|
16606
16709
|
const claimableRewards = yield this.getClaimableRewards(userAddress);
|
|
16607
16710
|
const lifeTimeRewards = yield this.getLifetimeRewards(userAddress, rewardDecimals, claimableRewards);
|
|
@@ -16618,12 +16721,18 @@ class KSULocking {
|
|
|
16618
16721
|
}
|
|
16619
16722
|
getAvailableKsuBonus() {
|
|
16620
16723
|
return __awaiter(this, void 0, void 0, function* () {
|
|
16724
|
+
if (this._isLiteDeployment || !this._kasuToken) {
|
|
16725
|
+
return '0';
|
|
16726
|
+
}
|
|
16621
16727
|
const amount = yield this._kasuToken.balanceOf(this._kasuBonusAddress);
|
|
16622
16728
|
return formatEther(amount);
|
|
16623
16729
|
});
|
|
16624
16730
|
}
|
|
16625
16731
|
getUserKsuBalance(userAddress) {
|
|
16626
16732
|
return __awaiter(this, void 0, void 0, function* () {
|
|
16733
|
+
if (this._isLiteDeployment || !this._kasuToken) {
|
|
16734
|
+
return '0';
|
|
16735
|
+
}
|
|
16627
16736
|
const balance = yield this._kasuToken.balanceOf(userAddress.toLowerCase());
|
|
16628
16737
|
return formatEther(balance);
|
|
16629
16738
|
});
|
|
@@ -16650,6 +16759,9 @@ class KSULocking {
|
|
|
16650
16759
|
}
|
|
16651
16760
|
getActiveLockPeriods() {
|
|
16652
16761
|
return __awaiter(this, void 0, void 0, function* () {
|
|
16762
|
+
if (this._isLiteDeployment) {
|
|
16763
|
+
return [];
|
|
16764
|
+
}
|
|
16653
16765
|
const data = yield this._graph.request(lockingPeriodsQuery);
|
|
16654
16766
|
return data.lockPeriods;
|
|
16655
16767
|
});
|
|
@@ -16662,6 +16774,14 @@ class KSULocking {
|
|
|
16662
16774
|
}
|
|
16663
16775
|
}
|
|
16664
16776
|
|
|
16777
|
+
/**
|
|
16778
|
+
* Check if the SDK is configured for a Lite deployment.
|
|
16779
|
+
* Lite deployments don't have KSU token, locking, or loyalty features.
|
|
16780
|
+
*/
|
|
16781
|
+
function isLiteDeployment(config) {
|
|
16782
|
+
return config.isLiteDeployment;
|
|
16783
|
+
}
|
|
16784
|
+
|
|
16665
16785
|
const USER_REQUEST_EVENT_MAP = {
|
|
16666
16786
|
DepositAccepted: 'Accepted',
|
|
16667
16787
|
DepositCancelled: 'Cancelled',
|
|
@@ -17512,10 +17632,113 @@ class Portfolio {
|
|
|
17512
17632
|
this._lockingService = new KSULocking(_kasuConfig, signerOrProvider);
|
|
17513
17633
|
this._dataService = new DataService(_kasuConfig, signerOrProvider);
|
|
17514
17634
|
this._systemVariablesAbi = ISystemVariablesAbi__factory.connect(_kasuConfig.contracts.SystemVariables, signerOrProvider);
|
|
17635
|
+
this._userLoyaltyRewardsAbi = IUserLoyaltyRewardsAbi__factory.connect(_kasuConfig.contracts.UserLoyaltyRewards, signerOrProvider);
|
|
17515
17636
|
this._userLendingService = new UserLending(_kasuConfig, signerOrProvider);
|
|
17516
|
-
this.
|
|
17637
|
+
this._isLiteDeployment = isLiteDeployment(_kasuConfig);
|
|
17638
|
+
this._kasuNftContract = _kasuConfig.contracts.KasuNFTs
|
|
17639
|
+
? IKasuNFTsAbi__factory.connect(_kasuConfig.contracts.KasuNFTs, signerOrProvider)
|
|
17640
|
+
: null;
|
|
17517
17641
|
this._graph = new GraphQLClient(_kasuConfig.subgraphUrl);
|
|
17518
17642
|
}
|
|
17643
|
+
computeYieldMetrics(portfolioLendingPools) {
|
|
17644
|
+
let totalInvestments = 0;
|
|
17645
|
+
let totalYieldEarned = 0;
|
|
17646
|
+
let weightedApy = 0;
|
|
17647
|
+
let weeklyYieldEarnings = 0;
|
|
17648
|
+
for (const pool of portfolioLendingPools) {
|
|
17649
|
+
for (const tranche of pool.tranches) {
|
|
17650
|
+
const investedAmount = parseFloat(tranche.investedAmount);
|
|
17651
|
+
totalInvestments += investedAmount;
|
|
17652
|
+
totalYieldEarned += parseFloat(tranche.yieldEarnings.lifetime);
|
|
17653
|
+
weightedApy += parseFloat(tranche.apy) * investedAmount;
|
|
17654
|
+
weeklyYieldEarnings +=
|
|
17655
|
+
investedAmount * parseFloat(tranche.interestRate);
|
|
17656
|
+
for (const fixedDeposits of tranche.fixedLoans) {
|
|
17657
|
+
const ftdConfig = tranche.fixedTermConfig.find((ftd) => ftd.configId === fixedDeposits.configId);
|
|
17658
|
+
if (!ftdConfig)
|
|
17659
|
+
continue;
|
|
17660
|
+
const ftdInvestedAmount = parseFloat(fixedDeposits.amount);
|
|
17661
|
+
totalInvestments += ftdInvestedAmount;
|
|
17662
|
+
totalYieldEarned += parseFloat(fixedDeposits.yieldEarnings.lifetime);
|
|
17663
|
+
weeklyYieldEarnings +=
|
|
17664
|
+
ftdInvestedAmount *
|
|
17665
|
+
parseFloat(ftdConfig.epochInterestRate);
|
|
17666
|
+
weightedApy +=
|
|
17667
|
+
parseFloat(ftdConfig.apy) * ftdInvestedAmount;
|
|
17668
|
+
}
|
|
17669
|
+
}
|
|
17670
|
+
}
|
|
17671
|
+
return {
|
|
17672
|
+
totalInvestments,
|
|
17673
|
+
totalYieldEarned,
|
|
17674
|
+
weightedApy,
|
|
17675
|
+
weeklyYieldEarnings,
|
|
17676
|
+
};
|
|
17677
|
+
}
|
|
17678
|
+
/**
|
|
17679
|
+
* Calculate aggregate yield metrics for a set of portfolio lending pools.
|
|
17680
|
+
* Accepts pre-fetched pool data and returns totals without performing any network calls.
|
|
17681
|
+
*/
|
|
17682
|
+
calculateYieldMetrics(portfolioLendingPools) {
|
|
17683
|
+
return this.computeYieldMetrics(portfolioLendingPools);
|
|
17684
|
+
}
|
|
17685
|
+
/**
|
|
17686
|
+
* Calculate the user's weekly protocol fee share (USDC) given tranche balances/configs,
|
|
17687
|
+
* system variables and locking summary. All inputs are expected to be pre-fetched.
|
|
17688
|
+
*/
|
|
17689
|
+
calculateWeeklyProtocolFees(params) {
|
|
17690
|
+
var _a, _b;
|
|
17691
|
+
const { trancheBalances, trancheConfigurations, systemVariables, lockingSummary, userRksuAmount, } = params;
|
|
17692
|
+
const totalRKsuAmount = parseFloat((_b = (_a = lockingSummary.lockingSummaries[0]) === null || _a === void 0 ? void 0 : _a.totalRKsuAmount) !== null && _b !== void 0 ? _b : '0');
|
|
17693
|
+
const userRKsuAmount = parseFloat(userRksuAmount || '0');
|
|
17694
|
+
const performanceFee = parseFloat(systemVariables.systemVariables.performanceFee) / 100;
|
|
17695
|
+
const ecosystemFeeRate = parseFloat(systemVariables.systemVariables.ecosystemFeeRate) / 100;
|
|
17696
|
+
if (totalRKsuAmount <= 0 ||
|
|
17697
|
+
userRKsuAmount <= 0 ||
|
|
17698
|
+
performanceFee <= 0 ||
|
|
17699
|
+
ecosystemFeeRate <= 0) {
|
|
17700
|
+
return 0;
|
|
17701
|
+
}
|
|
17702
|
+
let totalWeeklyEcosystemFees = 0;
|
|
17703
|
+
for (const tranche of trancheBalances.lendingPoolTranches) {
|
|
17704
|
+
const trancheConfig = trancheConfigurations.lendingPoolTrancheConfigurations.find((config) => config.id === tranche.id);
|
|
17705
|
+
if (!trancheConfig)
|
|
17706
|
+
continue;
|
|
17707
|
+
const interestUpdates = trancheConfig.lendingPoolTrancheInterestRateUpdates;
|
|
17708
|
+
const interestRate = interestUpdates.length
|
|
17709
|
+
? interestUpdates[0].epochInterestRate
|
|
17710
|
+
: trancheConfig.interestRate;
|
|
17711
|
+
totalWeeklyEcosystemFees +=
|
|
17712
|
+
parseFloat(tranche.balance) *
|
|
17713
|
+
parseFloat(interestRate) *
|
|
17714
|
+
performanceFee *
|
|
17715
|
+
ecosystemFeeRate;
|
|
17716
|
+
}
|
|
17717
|
+
return ((totalWeeklyEcosystemFees * userRKsuAmount) / totalRKsuAmount);
|
|
17718
|
+
}
|
|
17719
|
+
/**
|
|
17720
|
+
* Calculate the user's weekly KASU bonus rewards (KASU) based on current deposits,
|
|
17721
|
+
* loyalty level, reward rate, and KSU epoch price. Inputs should be pre-fetched.
|
|
17722
|
+
*/
|
|
17723
|
+
calculateWeeklyKsuBonusRewards(params) {
|
|
17724
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
17725
|
+
const { userAddress, userRksuAmount, userDepositAmounts, ksuEpochPrice } = params;
|
|
17726
|
+
const totalUserDeposits = userDepositAmounts[0].add(userDepositAmounts[1]);
|
|
17727
|
+
if (totalUserDeposits.isZero())
|
|
17728
|
+
return 0;
|
|
17729
|
+
const rKSUtoUSDCRatio = yield this._lockingService.getRKSUvsUSDCRatio(userRksuAmount, userAddress);
|
|
17730
|
+
const { loyaltyLevel } = this._lockingService.getLoyaltyLevelAndApyBonusFromRatio(rKSUtoUSDCRatio);
|
|
17731
|
+
const loyaltyRewardRate = yield this._userLoyaltyRewardsAbi.loyaltyEpochRewardRates(loyaltyLevel);
|
|
17732
|
+
if (loyaltyRewardRate.isZero() || ksuEpochPrice.price.isZero()) {
|
|
17733
|
+
return 0;
|
|
17734
|
+
}
|
|
17735
|
+
const reward = totalUserDeposits
|
|
17736
|
+
.mul(loyaltyRewardRate)
|
|
17737
|
+
.mul(BigNumber.from(10).pow(12))
|
|
17738
|
+
.div(ksuEpochPrice.price);
|
|
17739
|
+
return parseFloat(formatEther(reward));
|
|
17740
|
+
});
|
|
17741
|
+
}
|
|
17519
17742
|
getPortfolioRewards(userAddress) {
|
|
17520
17743
|
return __awaiter(this, void 0, void 0, function* () {
|
|
17521
17744
|
const userLockingData = yield this._lockingService.getUserBonusData(userAddress);
|
|
@@ -17542,40 +17765,46 @@ class Portfolio {
|
|
|
17542
17765
|
}
|
|
17543
17766
|
getUserNfts(userAddress) {
|
|
17544
17767
|
return __awaiter(this, void 0, void 0, function* () {
|
|
17768
|
+
// NFTs are not available on Lite deployments
|
|
17769
|
+
if (this._isLiteDeployment || !this._kasuNftContract) {
|
|
17770
|
+
return [];
|
|
17771
|
+
}
|
|
17545
17772
|
const usernfts = yield this._kasuNftContract.tokensOfOwner(userAddress);
|
|
17546
17773
|
return usernfts.map((nft) => nft.toNumber());
|
|
17547
17774
|
});
|
|
17548
17775
|
}
|
|
17549
|
-
getPortfolioSummary(userAddress, portfolioLendingPools) {
|
|
17776
|
+
getPortfolioSummary(userAddress, portfolioLendingPools, currentEpoch) {
|
|
17550
17777
|
return __awaiter(this, void 0, void 0, function* () {
|
|
17551
|
-
const
|
|
17552
|
-
|
|
17553
|
-
|
|
17554
|
-
|
|
17555
|
-
|
|
17556
|
-
|
|
17557
|
-
|
|
17558
|
-
|
|
17559
|
-
|
|
17560
|
-
|
|
17561
|
-
|
|
17562
|
-
|
|
17563
|
-
|
|
17564
|
-
|
|
17565
|
-
|
|
17566
|
-
|
|
17567
|
-
|
|
17568
|
-
|
|
17569
|
-
|
|
17570
|
-
|
|
17571
|
-
|
|
17572
|
-
|
|
17573
|
-
|
|
17574
|
-
|
|
17575
|
-
|
|
17576
|
-
|
|
17577
|
-
|
|
17578
|
-
|
|
17778
|
+
const epochId = currentEpoch.toString();
|
|
17779
|
+
const [userLockingData, userRksuAmount, lockingSummary, systemVariables, trancheBalances, trancheConfigurations, userDepositAmounts, ksuEpochPrice,] = yield Promise.all([
|
|
17780
|
+
this._lockingService.getUserBonusData(userAddress),
|
|
17781
|
+
this._lockingService.getUserEarnedrKsu(userAddress),
|
|
17782
|
+
this._graph.request(lockingSummariesQuery),
|
|
17783
|
+
this._graph.request(getSystemVariablesQuery),
|
|
17784
|
+
this._graph.request(getAllTranchesQuery, {
|
|
17785
|
+
unusedPools: this._kasuConfig.UNUSED_LENDING_POOL_IDS,
|
|
17786
|
+
}),
|
|
17787
|
+
this._graph.request(getAllTrancheConfigurationsQuery, {
|
|
17788
|
+
unusedPools: this._kasuConfig.UNUSED_LENDING_POOL_IDS,
|
|
17789
|
+
epochId,
|
|
17790
|
+
}),
|
|
17791
|
+
this._userLendingService.getUserTotalPendingAndActiveDepositedAmountForCurrentEpoch(userAddress),
|
|
17792
|
+
this._lockingService.getKasuEpochTokenPrice(),
|
|
17793
|
+
]);
|
|
17794
|
+
const { totalInvestments, totalYieldEarned, weightedApy, weeklyYieldEarnings, } = this.computeYieldMetrics(portfolioLendingPools);
|
|
17795
|
+
const weeklyProtocolFeesEarned = this.calculateWeeklyProtocolFees({
|
|
17796
|
+
trancheBalances,
|
|
17797
|
+
trancheConfigurations,
|
|
17798
|
+
systemVariables,
|
|
17799
|
+
lockingSummary,
|
|
17800
|
+
userRksuAmount,
|
|
17801
|
+
});
|
|
17802
|
+
const weeklyKsuBonusRewards = yield this.calculateWeeklyKsuBonusRewards({
|
|
17803
|
+
userAddress,
|
|
17804
|
+
userRksuAmount,
|
|
17805
|
+
userDepositAmounts,
|
|
17806
|
+
ksuEpochPrice,
|
|
17807
|
+
});
|
|
17579
17808
|
return {
|
|
17580
17809
|
current: {
|
|
17581
17810
|
totalKsuLocked: userLockingData.totalLockedAmount,
|
|
@@ -17589,8 +17818,8 @@ class Portfolio {
|
|
|
17589
17818
|
},
|
|
17590
17819
|
weekly: {
|
|
17591
17820
|
yieldEarnings: weeklyYieldEarnings.toString(),
|
|
17592
|
-
protocolFeesEarned:
|
|
17593
|
-
ksuBonusRewards:
|
|
17821
|
+
protocolFeesEarned: weeklyProtocolFeesEarned.toString(),
|
|
17822
|
+
ksuBonusRewards: weeklyKsuBonusRewards.toString(),
|
|
17594
17823
|
},
|
|
17595
17824
|
lifetime: {
|
|
17596
17825
|
yieldEarnings: totalYieldEarned.toString(),
|
|
@@ -17653,7 +17882,6 @@ class Portfolio {
|
|
|
17653
17882
|
for (const poolOverview of poolOverviews) {
|
|
17654
17883
|
const userPoolBalance = userPoolBalances.find(({ poolId }) => poolId === poolOverview.id);
|
|
17655
17884
|
if (!userPoolBalance) {
|
|
17656
|
-
console.warn(`Could not find user pool balance for ${poolOverview.id}`);
|
|
17657
17885
|
continue;
|
|
17658
17886
|
}
|
|
17659
17887
|
totalInvestments = userPoolBalance.balance.add(totalInvestments);
|
|
@@ -21641,4 +21869,420 @@ class KasuSdk {
|
|
|
21641
21869
|
}
|
|
21642
21870
|
}
|
|
21643
21871
|
|
|
21644
|
-
|
|
21872
|
+
class SdkConfig {
|
|
21873
|
+
constructor(options) {
|
|
21874
|
+
var _a, _b, _c;
|
|
21875
|
+
this.subgraphUrl = options.subgraphUrl;
|
|
21876
|
+
this.contracts = options.contracts;
|
|
21877
|
+
this.directusUrl = (_a = options.directusUrl) !== null && _a !== void 0 ? _a : '';
|
|
21878
|
+
this.UNUSED_LENDING_POOL_IDS = options.UNUSED_LENDING_POOL_IDS;
|
|
21879
|
+
this.isLiteDeployment = (_b = options.isLiteDeployment) !== null && _b !== void 0 ? _b : false;
|
|
21880
|
+
this.poolMetadataMapping = (_c = options.poolMetadataMapping) !== null && _c !== void 0 ? _c : {};
|
|
21881
|
+
}
|
|
21882
|
+
}
|
|
21883
|
+
|
|
21884
|
+
/**
|
|
21885
|
+
* Built-in chain configurations for Kasu-supported networks.
|
|
21886
|
+
*
|
|
21887
|
+
* Usage:
|
|
21888
|
+
* ```ts
|
|
21889
|
+
* import { CHAIN_CONFIGS } from '@kasufinance/kasu-sdk';
|
|
21890
|
+
* const base = CHAIN_CONFIGS.base;
|
|
21891
|
+
* ```
|
|
21892
|
+
*/
|
|
21893
|
+
const CHAIN_CONFIGS = {
|
|
21894
|
+
base: {
|
|
21895
|
+
chainId: 8453,
|
|
21896
|
+
name: 'Base Mainnet',
|
|
21897
|
+
isLiteDeployment: false,
|
|
21898
|
+
contracts: {
|
|
21899
|
+
KSUToken: '0x5D9b878744dbe721a3f33A60a6b102E289CeADBA',
|
|
21900
|
+
IKSULocking: '0xB145C061684C701c2C018A3f322aa14F5A553CE1',
|
|
21901
|
+
IKSULockBonus: '0xEEDE30AcF16caFf49c1a48F75185C67Be2e20B40',
|
|
21902
|
+
LendingPoolManager: '0xE1Be322323a412579b4A09fB08ff4bfcA12096B5',
|
|
21903
|
+
UserManager: '0x5Dc8D315a80fd99AbEF0f327B9a52a3FBC3C93f3',
|
|
21904
|
+
KasuAllowList: '0x807A7e119EBf0282420b5Ca0e0056c0525cBf8BB',
|
|
21905
|
+
SystemVariables: '0x193Bb02A24F5562b58fEB86550e6f09Bb6c41f69',
|
|
21906
|
+
KsuPrice: '0x221a54CbbD5f490Bd8e77CF36acBA4B1304E5c1b',
|
|
21907
|
+
UserLoyaltyRewards: '0xB4784f69Bb1F1076F50907cB0a815908a719D635',
|
|
21908
|
+
ClearingCoordinator: '0x2cF12A6d91fa4bEB5a4C17589a03e78F88f57DE2',
|
|
21909
|
+
KasuNFTs: '0x4946fF5f1a6550524C425479022D50446AA2968E',
|
|
21910
|
+
ExternalTVL: '0x662379FEBb3e4F91400B5f7d4f7F7ce4699F3c9F',
|
|
21911
|
+
},
|
|
21912
|
+
subgraphUrl: 'https://api.goldsky.com/api/public/project_cmgzlpxm300765np2a19421om/subgraphs/kasu-base/v1.0.13/gn',
|
|
21913
|
+
directusUrl: 'https://kasu-finance.directus.app/',
|
|
21914
|
+
unusedPoolIds: [],
|
|
21915
|
+
poolMetadataMapping: undefined,
|
|
21916
|
+
},
|
|
21917
|
+
xdc: {
|
|
21918
|
+
chainId: 50,
|
|
21919
|
+
name: 'XDC Mainnet',
|
|
21920
|
+
isLiteDeployment: true,
|
|
21921
|
+
contracts: {
|
|
21922
|
+
// No KSUToken on Lite deployments
|
|
21923
|
+
IKSULocking: '0x7fF469f8c5fba92A9051B8D28794CBb891760e81',
|
|
21924
|
+
IKSULockBonus: '0x7cc1434EfA50301Fdd56B7c5c6fF7e30Dc20C55c',
|
|
21925
|
+
LendingPoolManager: '0xa46143db92aBe5bB1f61d13d8C1cCd50fc40Ca10',
|
|
21926
|
+
UserManager: '0x9b57dF89e59235f0481A5Fae942302c8831e1B81',
|
|
21927
|
+
KasuAllowList: '0x32c1Ff5FbBe6D28503ddc46E5001C0D13d6E9B2A',
|
|
21928
|
+
SystemVariables: '0x34d17c9DD1f31Fb34757DE923EC083601d0eDFFe',
|
|
21929
|
+
KsuPrice: '0x666b589933965bF8B378eD973f0404b6cae0eb52',
|
|
21930
|
+
UserLoyaltyRewards: '0xb95834C5610A178be9065Dd1EF78258D29879CDb',
|
|
21931
|
+
ClearingCoordinator: '0xAF0a66953Eba1c5353eB7425b398B213Bb2c6121',
|
|
21932
|
+
// No KasuNFTs on Lite deployments
|
|
21933
|
+
ExternalTVL: '0xCCB4156964377CF36441f3775A2A800dbeCB8094',
|
|
21934
|
+
},
|
|
21935
|
+
subgraphUrl: 'https://api.goldsky.com/api/public/project_cmgzlpxm300765np2a19421om/subgraphs/kasu-xdc/v1.0.0/gn',
|
|
21936
|
+
directusUrl: 'https://kasu-finance.directus.app/',
|
|
21937
|
+
unusedPoolIds: [],
|
|
21938
|
+
poolMetadataMapping: {
|
|
21939
|
+
'0x20f42fb45f91657acf9528b99a5a16d0229c7800': '0xc987350716fe4a7d674c3591c391d29eba26b8ce',
|
|
21940
|
+
'0x3b7cb493aa22f731db2ab424d918e7375e00f6a9': '0x03f93c8caa9a82e000d35673ba34a4c0e6e117a2',
|
|
21941
|
+
'0xeda50c91a8c4ca8a83652b8542c0b3bd00a71fad': '0xc347a9e4aec8c8d11a149d2907deb2bf23b81c6f',
|
|
21942
|
+
},
|
|
21943
|
+
},
|
|
21944
|
+
plume: {
|
|
21945
|
+
chainId: 98866,
|
|
21946
|
+
name: 'Plume Mainnet',
|
|
21947
|
+
isLiteDeployment: true,
|
|
21948
|
+
contracts: {
|
|
21949
|
+
// Placeholder — update when Plume contracts are deployed
|
|
21950
|
+
IKSULocking: '',
|
|
21951
|
+
IKSULockBonus: '',
|
|
21952
|
+
LendingPoolManager: '',
|
|
21953
|
+
UserManager: '',
|
|
21954
|
+
KasuAllowList: '',
|
|
21955
|
+
SystemVariables: '',
|
|
21956
|
+
KsuPrice: '',
|
|
21957
|
+
UserLoyaltyRewards: '',
|
|
21958
|
+
ClearingCoordinator: '',
|
|
21959
|
+
ExternalTVL: '',
|
|
21960
|
+
},
|
|
21961
|
+
subgraphUrl: 'https://api.goldsky.com/api/public/project_cmgzlpxm300765np2a19421om/subgraphs/kasu-plume/prod',
|
|
21962
|
+
directusUrl: 'https://kasu-finance.directus.app/',
|
|
21963
|
+
unusedPoolIds: [],
|
|
21964
|
+
poolMetadataMapping: undefined,
|
|
21965
|
+
},
|
|
21966
|
+
};
|
|
21967
|
+
|
|
21968
|
+
/**
|
|
21969
|
+
* High-level facade for deposit and withdrawal operations.
|
|
21970
|
+
*
|
|
21971
|
+
* Integrators use this to submit on-chain transactions without
|
|
21972
|
+
* worrying about internal encoding details.
|
|
21973
|
+
*/
|
|
21974
|
+
class DepositsFacade {
|
|
21975
|
+
constructor(_userLending, _chainId) {
|
|
21976
|
+
this._userLending = _userLending;
|
|
21977
|
+
this._chainId = _chainId;
|
|
21978
|
+
}
|
|
21979
|
+
/**
|
|
21980
|
+
* Submit a deposit request.
|
|
21981
|
+
*
|
|
21982
|
+
* The integrator must first obtain a KYC signature via the Nexera flow
|
|
21983
|
+
* using the params from `buildKycParams()`.
|
|
21984
|
+
*
|
|
21985
|
+
* ```ts
|
|
21986
|
+
* const kycParams = kasu.deposits.buildKycParams('0xUser...');
|
|
21987
|
+
* // ... obtain kycSignature from your backend via Nexera ...
|
|
21988
|
+
* const tx = await kasu.deposits.deposit({
|
|
21989
|
+
* poolId: '0x...',
|
|
21990
|
+
* trancheId: '0x...',
|
|
21991
|
+
* amount: parseUnits('1000', 6),
|
|
21992
|
+
* kycSignature: { blockExpiration, signature },
|
|
21993
|
+
* });
|
|
21994
|
+
* ```
|
|
21995
|
+
*/
|
|
21996
|
+
deposit(params) {
|
|
21997
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
21998
|
+
var _a, _b, _c, _d;
|
|
21999
|
+
return yield this._userLending.requestDepositWithKyc(params.poolId, params.trancheId, params.amount, (_a = params.swapData) !== null && _a !== void 0 ? _a : '0x', (_b = params.fixedTermConfigId) !== null && _b !== void 0 ? _b : 0, (_c = params.depositData) !== null && _c !== void 0 ? _c : '0x', params.kycSignature, (_d = params.ethValue) !== null && _d !== void 0 ? _d : '0');
|
|
22000
|
+
});
|
|
22001
|
+
}
|
|
22002
|
+
/**
|
|
22003
|
+
* Submit a withdrawal request for a specific USDC amount.
|
|
22004
|
+
*/
|
|
22005
|
+
withdraw(params) {
|
|
22006
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
22007
|
+
return yield this._userLending.requestWithdrawalInUSDC(params.poolId, params.trancheId, params.amount);
|
|
22008
|
+
});
|
|
22009
|
+
}
|
|
22010
|
+
/**
|
|
22011
|
+
* Withdraw the entire balance from a tranche.
|
|
22012
|
+
*/
|
|
22013
|
+
withdrawMax(poolId, trancheId, userAddress) {
|
|
22014
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
22015
|
+
return yield this._userLending.requestWithdrawalMax(poolId, trancheId, userAddress);
|
|
22016
|
+
});
|
|
22017
|
+
}
|
|
22018
|
+
/**
|
|
22019
|
+
* Build KYC signature parameters for the Nexera verification flow.
|
|
22020
|
+
*
|
|
22021
|
+
* The integrator is responsible for sending these to their backend,
|
|
22022
|
+
* which obtains the signature from Nexera's signing service.
|
|
22023
|
+
*/
|
|
22024
|
+
buildKycParams(userAddress) {
|
|
22025
|
+
return this._userLending.buildKycSignatureParams(userAddress, this._chainId);
|
|
22026
|
+
}
|
|
22027
|
+
/**
|
|
22028
|
+
* Check whether the pool is currently in a clearing period
|
|
22029
|
+
* (deposits/withdrawals are temporarily paused).
|
|
22030
|
+
*/
|
|
22031
|
+
isClearingPending(poolId) {
|
|
22032
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
22033
|
+
return yield this._userLending.isClearingPending(poolId);
|
|
22034
|
+
});
|
|
22035
|
+
}
|
|
22036
|
+
/**
|
|
22037
|
+
* Get the current epoch number.
|
|
22038
|
+
*/
|
|
22039
|
+
getCurrentEpoch() {
|
|
22040
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
22041
|
+
return yield this._userLending.getCurrentEpoch();
|
|
22042
|
+
});
|
|
22043
|
+
}
|
|
22044
|
+
}
|
|
22045
|
+
|
|
22046
|
+
/**
|
|
22047
|
+
* High-level facade for browsing Kasu lending strategies (pools).
|
|
22048
|
+
*
|
|
22049
|
+
* Handles epoch fetching internally so callers never need to know about epochs.
|
|
22050
|
+
*/
|
|
22051
|
+
class StrategiesFacade {
|
|
22052
|
+
constructor(_dataService, _userLending) {
|
|
22053
|
+
this._dataService = _dataService;
|
|
22054
|
+
this._userLending = _userLending;
|
|
22055
|
+
}
|
|
22056
|
+
/**
|
|
22057
|
+
* Fetch all active lending strategies.
|
|
22058
|
+
*
|
|
22059
|
+
* ```ts
|
|
22060
|
+
* const strategies = await kasu.strategies.getAll();
|
|
22061
|
+
* ```
|
|
22062
|
+
*/
|
|
22063
|
+
getAll(poolIds) {
|
|
22064
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
22065
|
+
const epochId = yield this._userLending.getCurrentEpoch();
|
|
22066
|
+
const pools = yield this._dataService.getPoolOverview(epochId, poolIds);
|
|
22067
|
+
return pools.map((pool) => this.mapPoolToStrategy(pool));
|
|
22068
|
+
});
|
|
22069
|
+
}
|
|
22070
|
+
/**
|
|
22071
|
+
* Fetch a single strategy by pool ID. Returns `null` if not found.
|
|
22072
|
+
*/
|
|
22073
|
+
getById(poolId) {
|
|
22074
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
22075
|
+
var _a;
|
|
22076
|
+
const results = yield this.getAll([poolId]);
|
|
22077
|
+
return (_a = results[0]) !== null && _a !== void 0 ? _a : null;
|
|
22078
|
+
});
|
|
22079
|
+
}
|
|
22080
|
+
/**
|
|
22081
|
+
* Aggregate platform statistics (TVL, loans, yield, loss rate).
|
|
22082
|
+
*/
|
|
22083
|
+
getPlatformStats() {
|
|
22084
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
22085
|
+
const epochId = yield this._userLending.getCurrentEpoch();
|
|
22086
|
+
const pools = yield this._dataService.getPoolOverview(epochId);
|
|
22087
|
+
return yield this._dataService.getLendingTotals(pools);
|
|
22088
|
+
});
|
|
22089
|
+
}
|
|
22090
|
+
/**
|
|
22091
|
+
* Calculate deposit limits for a specific tranche.
|
|
22092
|
+
*
|
|
22093
|
+
* @param tranche - A `StrategyTranche` from `getAll()` or `getById()`.
|
|
22094
|
+
* @returns min/max/capacity in ether-formatted USDC strings.
|
|
22095
|
+
*/
|
|
22096
|
+
calculateDepositLimits(tranche) {
|
|
22097
|
+
const raw = tranche._raw;
|
|
22098
|
+
const min = parseFloat(raw.minimumDeposit) < 1
|
|
22099
|
+
? '1'
|
|
22100
|
+
: raw.minimumDeposit;
|
|
22101
|
+
const max = parseFloat(raw.maximumDeposit) > parseFloat(raw.poolCapacity)
|
|
22102
|
+
? raw.poolCapacity
|
|
22103
|
+
: raw.maximumDeposit;
|
|
22104
|
+
return {
|
|
22105
|
+
min,
|
|
22106
|
+
max,
|
|
22107
|
+
availableCapacity: raw.poolCapacity,
|
|
22108
|
+
};
|
|
22109
|
+
}
|
|
22110
|
+
// ------------------------------------------------------------------
|
|
22111
|
+
// Private helpers
|
|
22112
|
+
// ------------------------------------------------------------------
|
|
22113
|
+
mapPoolToStrategy(pool) {
|
|
22114
|
+
const tranches = pool.tranches.map((t) => ({
|
|
22115
|
+
id: t.id,
|
|
22116
|
+
name: t.name,
|
|
22117
|
+
apy: parseFloat(t.apy),
|
|
22118
|
+
minApy: parseFloat(t.minApy),
|
|
22119
|
+
maxApy: parseFloat(t.maxApy),
|
|
22120
|
+
minimumDeposit: t.minimumDeposit,
|
|
22121
|
+
maximumDeposit: t.maximumDeposit,
|
|
22122
|
+
availableCapacity: t.poolCapacity,
|
|
22123
|
+
fixedTermOptions: t.fixedTermConfig.map((ftd) => ({
|
|
22124
|
+
configId: ftd.configId,
|
|
22125
|
+
apy: parseFloat(ftd.apy),
|
|
22126
|
+
epochLockDuration: ftd.epochLockDuration,
|
|
22127
|
+
})),
|
|
22128
|
+
_raw: t,
|
|
22129
|
+
}));
|
|
22130
|
+
return {
|
|
22131
|
+
id: pool.id,
|
|
22132
|
+
name: pool.poolName,
|
|
22133
|
+
description: pool.description,
|
|
22134
|
+
isActive: pool.isActive,
|
|
22135
|
+
apy: pool.apy,
|
|
22136
|
+
tvl: pool.totalValueLocked,
|
|
22137
|
+
availableCapacity: pool.poolCapacity,
|
|
22138
|
+
capacityUtilisation: pool.poolCapacityPercentage,
|
|
22139
|
+
tranches,
|
|
22140
|
+
assetClass: pool.assetClass,
|
|
22141
|
+
apyStructure: pool.poolApyStructure,
|
|
22142
|
+
thumbnailUrl: pool.thumbnailImageUrl,
|
|
22143
|
+
bannerUrl: pool.bannerImageUrl,
|
|
22144
|
+
_raw: pool,
|
|
22145
|
+
};
|
|
22146
|
+
}
|
|
22147
|
+
}
|
|
22148
|
+
|
|
22149
|
+
/**
|
|
22150
|
+
* High-level facade for querying a user's portfolio, positions, and history.
|
|
22151
|
+
*
|
|
22152
|
+
* Orchestrates DataService, UserLending, and Portfolio services so the caller
|
|
22153
|
+
* only needs to provide a wallet address.
|
|
22154
|
+
*/
|
|
22155
|
+
class PortfolioFacade {
|
|
22156
|
+
constructor(_dataService, _userLending, _portfolio) {
|
|
22157
|
+
this._dataService = _dataService;
|
|
22158
|
+
this._userLending = _userLending;
|
|
22159
|
+
this._portfolio = _portfolio;
|
|
22160
|
+
}
|
|
22161
|
+
/**
|
|
22162
|
+
* Fetch a user's complete portfolio: per-pool positions and aggregate summary.
|
|
22163
|
+
*
|
|
22164
|
+
* ```ts
|
|
22165
|
+
* const positions = await kasu.portfolio.getPositions('0xUser...');
|
|
22166
|
+
* console.log(positions.summary.current.totalLendingPoolInvestments);
|
|
22167
|
+
* ```
|
|
22168
|
+
*
|
|
22169
|
+
* @param userAddress - Wallet address.
|
|
22170
|
+
* @param provider - Optional separate provider for balance queries (useful when the
|
|
22171
|
+
* SDK was initialised with a Signer but you need a read-only provider).
|
|
22172
|
+
*/
|
|
22173
|
+
getPositions(userAddress, provider) {
|
|
22174
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
22175
|
+
const currentEpoch = yield this._userLending.getCurrentEpoch();
|
|
22176
|
+
const poolOverviews = yield this._dataService.getPoolOverview(currentEpoch);
|
|
22177
|
+
const pools = yield this._portfolio.getPortfolioLendingData(userAddress, poolOverviews, currentEpoch, provider);
|
|
22178
|
+
const summary = yield this._portfolio.getPortfolioSummary(userAddress, pools, currentEpoch);
|
|
22179
|
+
return { pools, summary };
|
|
22180
|
+
});
|
|
22181
|
+
}
|
|
22182
|
+
/**
|
|
22183
|
+
* Fetch a user's full transaction history (deposits, withdrawals, cancellations).
|
|
22184
|
+
*/
|
|
22185
|
+
getTransactionHistory(userAddress) {
|
|
22186
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
22187
|
+
const currentEpoch = yield this._userLending.getCurrentEpoch();
|
|
22188
|
+
return yield this._userLending.getUserRequests(userAddress, currentEpoch);
|
|
22189
|
+
});
|
|
22190
|
+
}
|
|
22191
|
+
}
|
|
22192
|
+
|
|
22193
|
+
/**
|
|
22194
|
+
* High-level entry point for external integrators.
|
|
22195
|
+
*
|
|
22196
|
+
* Provides three domain facades — `strategies`, `deposits`, `portfolio` — and
|
|
22197
|
+
* exposes the underlying `KasuSdk` services via `.services` for power-users.
|
|
22198
|
+
*
|
|
22199
|
+
* ```ts
|
|
22200
|
+
* import { Kasu } from '@kasufinance/kasu-sdk';
|
|
22201
|
+
*
|
|
22202
|
+
* const kasu = Kasu.create({ chain: 'base', signerOrProvider: provider });
|
|
22203
|
+
*
|
|
22204
|
+
* // Browse strategies
|
|
22205
|
+
* const strategies = await kasu.strategies.getAll();
|
|
22206
|
+
*
|
|
22207
|
+
* // Deposit
|
|
22208
|
+
* const tx = await kasu.deposits.deposit({ poolId, trancheId, amount, kycSignature });
|
|
22209
|
+
*
|
|
22210
|
+
* // User positions
|
|
22211
|
+
* const positions = await kasu.portfolio.getPositions(userAddress);
|
|
22212
|
+
* ```
|
|
22213
|
+
*/
|
|
22214
|
+
class Kasu {
|
|
22215
|
+
constructor(sdk, chainConfig) {
|
|
22216
|
+
this._sdk = sdk;
|
|
22217
|
+
this._chainConfig = chainConfig;
|
|
22218
|
+
this.strategies = new StrategiesFacade(sdk.DataService, sdk.UserLending);
|
|
22219
|
+
this.deposits = new DepositsFacade(sdk.UserLending, chainConfig.chainId.toString());
|
|
22220
|
+
this.portfolio = new PortfolioFacade(sdk.DataService, sdk.UserLending, sdk.Portfolio);
|
|
22221
|
+
}
|
|
22222
|
+
/**
|
|
22223
|
+
* Create a Kasu instance with built-in chain config.
|
|
22224
|
+
*
|
|
22225
|
+
* ```ts
|
|
22226
|
+
* // Minimal setup — uses built-in Base mainnet config
|
|
22227
|
+
* const kasu = Kasu.create({ chain: 'base', signerOrProvider: provider });
|
|
22228
|
+
*
|
|
22229
|
+
* // Custom config override
|
|
22230
|
+
* const kasu = Kasu.create({
|
|
22231
|
+
* chain: 'base',
|
|
22232
|
+
* signerOrProvider: signer,
|
|
22233
|
+
* configOverrides: { UNUSED_LENDING_POOL_IDS: ['0x...'] },
|
|
22234
|
+
* });
|
|
22235
|
+
*
|
|
22236
|
+
* // Fully custom chain
|
|
22237
|
+
* const kasu = Kasu.create({
|
|
22238
|
+
* chain: { chainId: 123, name: 'MyChain', ... },
|
|
22239
|
+
* signerOrProvider: provider,
|
|
22240
|
+
* });
|
|
22241
|
+
* ```
|
|
22242
|
+
*/
|
|
22243
|
+
static create(options) {
|
|
22244
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
22245
|
+
const chainConfig = resolveChainConfig(options.chain);
|
|
22246
|
+
const overrides = (_a = options.configOverrides) !== null && _a !== void 0 ? _a : {};
|
|
22247
|
+
const sdkConfig = new SdkConfig({
|
|
22248
|
+
subgraphUrl: (_b = overrides.subgraphUrl) !== null && _b !== void 0 ? _b : chainConfig.subgraphUrl,
|
|
22249
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
22250
|
+
contracts: (_c = overrides.contracts) !== null && _c !== void 0 ? _c : chainConfig.contracts,
|
|
22251
|
+
directusUrl: (_d = overrides.directusUrl) !== null && _d !== void 0 ? _d : chainConfig.directusUrl,
|
|
22252
|
+
UNUSED_LENDING_POOL_IDS: (_e = overrides.UNUSED_LENDING_POOL_IDS) !== null && _e !== void 0 ? _e : chainConfig.unusedPoolIds,
|
|
22253
|
+
isLiteDeployment: (_f = overrides.isLiteDeployment) !== null && _f !== void 0 ? _f : chainConfig.isLiteDeployment,
|
|
22254
|
+
poolMetadataMapping: (_g = overrides.poolMetadataMapping) !== null && _g !== void 0 ? _g : chainConfig.poolMetadataMapping,
|
|
22255
|
+
});
|
|
22256
|
+
const sdk = new KasuSdk(sdkConfig, options.signerOrProvider);
|
|
22257
|
+
return new Kasu(sdk, chainConfig);
|
|
22258
|
+
}
|
|
22259
|
+
/**
|
|
22260
|
+
* Access the underlying `KasuSdk` services for advanced use cases.
|
|
22261
|
+
*
|
|
22262
|
+
* ```ts
|
|
22263
|
+
* const locks = await kasu.services.Locking.getUserLocks(address);
|
|
22264
|
+
* ```
|
|
22265
|
+
*/
|
|
22266
|
+
get services() {
|
|
22267
|
+
return this._sdk;
|
|
22268
|
+
}
|
|
22269
|
+
/** The resolved chain configuration. */
|
|
22270
|
+
get chainConfig() {
|
|
22271
|
+
return this._chainConfig;
|
|
22272
|
+
}
|
|
22273
|
+
/** Whether this deployment has KSU token / locking features. */
|
|
22274
|
+
get isLiteDeployment() {
|
|
22275
|
+
return this._chainConfig.isLiteDeployment;
|
|
22276
|
+
}
|
|
22277
|
+
}
|
|
22278
|
+
// ---------------------------------------------------------------------------
|
|
22279
|
+
// Helpers
|
|
22280
|
+
// ---------------------------------------------------------------------------
|
|
22281
|
+
function resolveChainConfig(chain) {
|
|
22282
|
+
if (typeof chain === 'string') {
|
|
22283
|
+
return CHAIN_CONFIGS[chain];
|
|
22284
|
+
}
|
|
22285
|
+
return chain;
|
|
22286
|
+
}
|
|
22287
|
+
|
|
22288
|
+
export { CHAIN_CONFIGS, DepositsFacade, Kasu, KasuSdk, PortfolioFacade, SdkConfig, StrategiesFacade };
|