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