@kasufinance/kasu-sdk 2.10.3 → 2.12.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/README.md +28 -1
- package/dist/bundle.cjs.js +752 -59
- package/dist/bundle.esm.js +750 -60
- package/dist/domain/index.d.ts +10 -2
- package/dist/domain/index.js +6 -0
- package/dist/domain/index.js.map +1 -1
- package/dist/domain/strategy-summary.d.ts +47 -0
- package/dist/domain/strategy-summary.js +76 -0
- package/dist/domain/strategy-summary.js.map +1 -0
- package/dist/domain/yield-history.d.ts +122 -0
- package/dist/domain/yield-history.js +95 -0
- package/dist/domain/yield-history.js.map +1 -0
- package/dist/facade/strategies.js +2 -0
- package/dist/facade/strategies.js.map +1 -1
- package/dist/facade/types.d.ts +13 -0
- package/dist/facade/user-portfolio.d.ts +32 -0
- package/dist/facade/user-portfolio.js +34 -0
- package/dist/facade/user-portfolio.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js.map +1 -1
- package/dist/services/Portfolio/portfolio.d.ts +37 -0
- package/dist/services/Portfolio/portfolio.js +136 -56
- package/dist/services/Portfolio/portfolio.js.map +1 -1
- package/dist/services/Portfolio/queries.js +15 -3
- package/dist/services/Portfolio/queries.js.map +1 -1
- package/dist/services/Portfolio/types.d.ts +8 -0
- package/dist/services/Portfolio/yield-history.d.ts +177 -0
- package/dist/services/Portfolio/yield-history.js +405 -0
- package/dist/services/Portfolio/yield-history.js.map +1 -0
- package/package.json +2 -1
- package/src/domain/index.ts +19 -10
- package/src/domain/strategy-summary.ts +88 -0
- package/src/domain/yield-history.ts +194 -0
- package/src/facade/strategies.ts +2 -0
- package/src/facade/types.ts +13 -0
- package/src/facade/user-portfolio.ts +40 -3
- package/src/index.ts +2 -0
- package/src/services/Portfolio/portfolio.ts +263 -153
- package/src/services/Portfolio/queries.ts +15 -3
- package/src/services/Portfolio/types.ts +10 -0
- package/src/services/Portfolio/yield-history.ts +574 -0
|
@@ -10,6 +10,10 @@ import {
|
|
|
10
10
|
ISystemVariablesAbi__factory,
|
|
11
11
|
IUserLoyaltyRewardsAbi__factory,
|
|
12
12
|
} from '../../contracts';
|
|
13
|
+
import {
|
|
14
|
+
epochTrancheYield,
|
|
15
|
+
YieldHistoryEntry,
|
|
16
|
+
} from '../../domain/yield-history';
|
|
13
17
|
import { SdkConfig } from '../../sdk-config';
|
|
14
18
|
import { isLiteDeployment } from '../../utils/deployment-mode';
|
|
15
19
|
import { DataService } from '../DataService/data-service';
|
|
@@ -43,6 +47,19 @@ import {
|
|
|
43
47
|
PortfolioTrancheDepositDetails,
|
|
44
48
|
UserLendingPoolTrancheFixedTermDepositLock,
|
|
45
49
|
} from './types';
|
|
50
|
+
import {
|
|
51
|
+
buildYieldHistory,
|
|
52
|
+
fetchYieldHistorySeries,
|
|
53
|
+
isEmptyHistoryError,
|
|
54
|
+
resolveYieldHistoryWindow,
|
|
55
|
+
validateYieldHistoryOptions,
|
|
56
|
+
YIELD_HISTORY_PAGE_SIZE,
|
|
57
|
+
YieldHistoryOptions,
|
|
58
|
+
yieldHistoryPageQuery,
|
|
59
|
+
YieldHistoryPageResult,
|
|
60
|
+
yieldHistoryPositionsQuery,
|
|
61
|
+
YieldHistoryPositionsResult,
|
|
62
|
+
} from './yield-history';
|
|
46
63
|
|
|
47
64
|
export class Portfolio {
|
|
48
65
|
private _lockingService: KSULocking;
|
|
@@ -235,9 +252,7 @@ export class Portfolio {
|
|
|
235
252
|
ecosystemFeeRate;
|
|
236
253
|
}
|
|
237
254
|
|
|
238
|
-
return (
|
|
239
|
-
(totalWeeklyEcosystemFees * userRKsuAmount) / totalRKsuAmount
|
|
240
|
-
);
|
|
255
|
+
return (totalWeeklyEcosystemFees * userRKsuAmount) / totalRKsuAmount;
|
|
241
256
|
}
|
|
242
257
|
|
|
243
258
|
/**
|
|
@@ -250,8 +265,12 @@ export class Portfolio {
|
|
|
250
265
|
userDepositAmounts: [BigNumber, BigNumber];
|
|
251
266
|
ksuEpochPrice: { price: BigNumber; decimals: number };
|
|
252
267
|
}): Promise<number> {
|
|
253
|
-
const {
|
|
254
|
-
|
|
268
|
+
const {
|
|
269
|
+
userAddress,
|
|
270
|
+
userRksuAmount,
|
|
271
|
+
userDepositAmounts,
|
|
272
|
+
ksuEpochPrice,
|
|
273
|
+
} = params;
|
|
255
274
|
|
|
256
275
|
const totalUserDeposits = userDepositAmounts[0].add(
|
|
257
276
|
userDepositAmounts[1],
|
|
@@ -259,10 +278,11 @@ export class Portfolio {
|
|
|
259
278
|
|
|
260
279
|
if (totalUserDeposits.isZero()) return 0;
|
|
261
280
|
|
|
262
|
-
const rKSUtoStableRatio =
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
281
|
+
const rKSUtoStableRatio =
|
|
282
|
+
await this._lockingService.getRKSUvsStableRatio(
|
|
283
|
+
userRksuAmount,
|
|
284
|
+
userAddress,
|
|
285
|
+
);
|
|
266
286
|
const { loyaltyLevel } =
|
|
267
287
|
this._lockingService.getLoyaltyLevelAndApyBonusFromRatio(
|
|
268
288
|
rKSUtoStableRatio,
|
|
@@ -374,13 +394,14 @@ export class Portfolio {
|
|
|
374
394
|
userRksuAmount,
|
|
375
395
|
});
|
|
376
396
|
|
|
377
|
-
const weeklyKsuBonusRewards =
|
|
378
|
-
|
|
397
|
+
const weeklyKsuBonusRewards = await this.calculateWeeklyKsuBonusRewards(
|
|
398
|
+
{
|
|
379
399
|
userAddress,
|
|
380
400
|
userRksuAmount,
|
|
381
401
|
userDepositAmounts,
|
|
382
402
|
ksuEpochPrice,
|
|
383
|
-
}
|
|
403
|
+
},
|
|
404
|
+
);
|
|
384
405
|
|
|
385
406
|
return {
|
|
386
407
|
current: {
|
|
@@ -440,6 +461,7 @@ export class Portfolio {
|
|
|
440
461
|
epochId: parseFloat(currentEpoch),
|
|
441
462
|
lastEpochId: previousEpoch.toNumber(),
|
|
442
463
|
unusedPools: this._kasuConfig.UNUSED_LENDING_POOL_IDS,
|
|
464
|
+
first: YIELD_HISTORY_PAGE_SIZE,
|
|
443
465
|
},
|
|
444
466
|
),
|
|
445
467
|
this._userLendingService.getPortfolioUserTrancheBalances(
|
|
@@ -505,7 +527,6 @@ export class Portfolio {
|
|
|
505
527
|
}
|
|
506
528
|
|
|
507
529
|
let totalInvestments = BigNumber.from(0);
|
|
508
|
-
let totalYieldEarnedLastEpoch = 0;
|
|
509
530
|
|
|
510
531
|
for (const poolOverview of poolOverviews) {
|
|
511
532
|
const userPoolBalance = userPoolBalances.find(
|
|
@@ -522,6 +543,8 @@ export class Portfolio {
|
|
|
522
543
|
};
|
|
523
544
|
})[] = [];
|
|
524
545
|
|
|
546
|
+
let poolYieldEarnedLastEpoch = 0;
|
|
547
|
+
|
|
525
548
|
const lendingPoolUserDetails =
|
|
526
549
|
lastEpochData.user.lendingPoolUserDetails.find(
|
|
527
550
|
({ lendingPool }) => lendingPool.id === poolOverview.id,
|
|
@@ -558,35 +581,66 @@ export class Portfolio {
|
|
|
558
581
|
});
|
|
559
582
|
continue;
|
|
560
583
|
}
|
|
561
|
-
const
|
|
562
|
-
lastEpochUserTrancheDetails.tranche
|
|
563
|
-
.lendingPoolTrancheEpochInterest?.[0]
|
|
564
|
-
?.epochInterestAmount ?? '0',
|
|
565
|
-
);
|
|
584
|
+
const lastEpoch = previousEpoch.toNumber();
|
|
566
585
|
|
|
567
|
-
const
|
|
586
|
+
const userHasLastEpochShares = Boolean(
|
|
568
587
|
lastEpochUserTrancheDetails
|
|
569
|
-
.lendingPoolTrancheUserEpochSharesUpdates?.
|
|
570
|
-
?.shares ?? '0',
|
|
588
|
+
.lendingPoolTrancheUserEpochSharesUpdates?.length,
|
|
571
589
|
);
|
|
572
590
|
|
|
573
|
-
const
|
|
574
|
-
lastEpochUserTrancheDetails.
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
591
|
+
const fixedTermDeposits =
|
|
592
|
+
lastEpochUserTrancheDetails.userLendingPoolTrancheFixedTermDepositLocks;
|
|
593
|
+
|
|
594
|
+
// The one per-epoch formula `getYieldHistory` runs too, with
|
|
595
|
+
// the same share selection — so the last bar of a history
|
|
596
|
+
// equals these figures.
|
|
597
|
+
const lastEpochYield = epochTrancheYield({
|
|
598
|
+
epochInterest: parseFloat(
|
|
599
|
+
lastEpochUserTrancheDetails.tranche
|
|
600
|
+
.lendingPoolTrancheEpochInterest?.[0]
|
|
601
|
+
?.epochInterestAmount ?? '0',
|
|
602
|
+
),
|
|
603
|
+
userShares: parseFloat(
|
|
604
|
+
lastEpochUserTrancheDetails
|
|
605
|
+
.lendingPoolTrancheUserEpochSharesUpdates?.[0]
|
|
606
|
+
?.shares ?? '0',
|
|
607
|
+
),
|
|
608
|
+
trancheShares: parseFloat(
|
|
609
|
+
lastEpochUserTrancheDetails.tranche
|
|
610
|
+
.lendingPoolTrancheShareUpdates?.[0]?.shares ?? '0',
|
|
611
|
+
),
|
|
612
|
+
trancheBalanceNow: parseFloat(
|
|
613
|
+
lastEpochUserTrancheDetails.tranche.balance,
|
|
614
|
+
),
|
|
615
|
+
trancheSharesNow: parseFloat(
|
|
616
|
+
lastEpochUserTrancheDetails.tranche.shares,
|
|
617
|
+
),
|
|
618
|
+
locks: fixedTermDeposits.map((fixedTermDeposit) => ({
|
|
619
|
+
active:
|
|
620
|
+
parseFloat(fixedTermDeposit.epochLockStart) <
|
|
621
|
+
lastEpoch &&
|
|
622
|
+
parseFloat(fixedTermDeposit.epochLockEnd) >=
|
|
623
|
+
lastEpoch &&
|
|
624
|
+
userHasLastEpochShares,
|
|
625
|
+
// No snapshot = the lock's opening shares, exactly
|
|
626
|
+
// as `getYieldHistory` reads it: a lock made after
|
|
627
|
+
// clearing E starts at E with its first update
|
|
628
|
+
// tagged E + 1. Never the CURRENT shares, which
|
|
629
|
+
// would carry a top-up from a clearing that ran
|
|
630
|
+
// after the last settled epoch.
|
|
631
|
+
sharesAtEpoch: parseFloat(
|
|
632
|
+
fixedTermDeposit.lockSharesAtLastEpoch?.[0]
|
|
633
|
+
?.shares ??
|
|
634
|
+
fixedTermDeposit.initialTrancheShares,
|
|
635
|
+
),
|
|
636
|
+
sharesBeforeEpoch: parseFloat(
|
|
637
|
+
fixedTermDeposit
|
|
638
|
+
.userLendingPoolTrancheFixedTermDepositLockShareUpdate?.[0]
|
|
639
|
+
?.shares ??
|
|
640
|
+
fixedTermDeposit.initialTrancheShares,
|
|
641
|
+
),
|
|
642
|
+
})),
|
|
643
|
+
});
|
|
590
644
|
|
|
591
645
|
const userTrancheBalance = {
|
|
592
646
|
balance: '0',
|
|
@@ -609,129 +663,85 @@ export class Portfolio {
|
|
|
609
663
|
|
|
610
664
|
let totalLifetimeFtdYield = 0;
|
|
611
665
|
|
|
612
|
-
let lastEpochVariableBaseYield = lastEpochTotalBaseYield;
|
|
613
|
-
|
|
614
666
|
const fixedLoans: PortfolioTranche['fixedLoans'] =
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
667
|
+
fixedTermDeposits.map((fixedTermDeposit, lockIndex) => {
|
|
668
|
+
const fixedLoanDepositDetails =
|
|
669
|
+
userRequest?.[
|
|
670
|
+
fixedTermDeposit
|
|
671
|
+
.lendingPoolTrancheFixedTermConfig.configId
|
|
672
|
+
] ?? [];
|
|
673
|
+
|
|
674
|
+
const lastEpochYieldEarned =
|
|
675
|
+
lastEpochYield.locks[lockIndex] ?? 0;
|
|
676
|
+
|
|
677
|
+
const lifetimeYieldEarned =
|
|
678
|
+
this.calculateFixedTermDepositEarnings(
|
|
679
|
+
fixedTermDeposit,
|
|
680
|
+
lastEpochUserTrancheDetails.tranche.balance,
|
|
681
|
+
lastEpochUserTrancheDetails.tranche.shares,
|
|
682
|
+
);
|
|
683
|
+
|
|
684
|
+
totalLifetimeFtdYield += lifetimeYieldEarned;
|
|
685
|
+
|
|
686
|
+
const lockDuration =
|
|
687
|
+
parseFloat(
|
|
688
|
+
fixedTermDeposit
|
|
689
|
+
.lendingPoolTrancheFixedTermConfig
|
|
690
|
+
.epochLockDuration,
|
|
691
|
+
) * SECONDS_PER_EPOCH;
|
|
692
|
+
|
|
693
|
+
return {
|
|
694
|
+
lockId: fixedTermDeposit.lockId,
|
|
695
|
+
configId:
|
|
696
|
+
fixedTermDeposit
|
|
697
|
+
.lendingPoolTrancheFixedTermConfig.configId,
|
|
698
|
+
epochLockDuration:
|
|
699
|
+
fixedTermDeposit
|
|
700
|
+
.lendingPoolTrancheFixedTermConfig
|
|
701
|
+
.epochLockDuration,
|
|
702
|
+
epochLockEnd: fixedTermDeposit.epochLockEnd,
|
|
703
|
+
epochInterestRate:
|
|
704
|
+
fixedTermDeposit
|
|
705
|
+
.lendingPoolTrancheFixedTermConfig
|
|
706
|
+
.epochInterestRate,
|
|
707
|
+
epochLockStart: fixedTermDeposit.epochLockStart,
|
|
708
|
+
amount: this._userLendingService
|
|
709
|
+
.convertSharesToAssets(
|
|
639
710
|
fixedTermDeposit.trancheShares,
|
|
640
|
-
);
|
|
641
|
-
|
|
642
|
-
const lastEpochFtdShares = parseFloat(
|
|
643
|
-
fixedTermDeposit
|
|
644
|
-
.userLendingPoolTrancheFixedTermDepositLockShareUpdate?.[0]
|
|
645
|
-
?.shares ?? '0',
|
|
646
|
-
);
|
|
647
|
-
|
|
648
|
-
const additionalFtdYield =
|
|
649
|
-
((currentEpochFtdShares -
|
|
650
|
-
lastEpochFtdShares) *
|
|
651
|
-
currentTotalAmount) /
|
|
652
|
-
currentTotalShares;
|
|
653
|
-
|
|
654
|
-
const lastEpochFtdBaseYield =
|
|
655
|
-
(lastEpochTotalBaseYield *
|
|
656
|
-
lastEpochFtdShares) /
|
|
657
|
-
lastEpochUserShares;
|
|
658
|
-
|
|
659
|
-
lastEpochVariableBaseYield -=
|
|
660
|
-
lastEpochFtdBaseYield;
|
|
661
|
-
|
|
662
|
-
lastEpochYieldEarned =
|
|
663
|
-
lastEpochFtdBaseYield + additionalFtdYield;
|
|
664
|
-
}
|
|
665
|
-
|
|
666
|
-
lifetimeYieldEarned =
|
|
667
|
-
this.calculateFixedTermDepositEarnings(
|
|
668
|
-
fixedTermDeposit,
|
|
669
711
|
lastEpochUserTrancheDetails.tranche.balance,
|
|
670
712
|
lastEpochUserTrancheDetails.tranche.shares,
|
|
671
|
-
)
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
fixedTermDeposit
|
|
692
|
-
.lendingPoolTrancheFixedTermConfig
|
|
693
|
-
.epochLockDuration,
|
|
694
|
-
epochLockEnd: fixedTermDeposit.epochLockEnd,
|
|
695
|
-
epochInterestRate:
|
|
696
|
-
fixedTermDeposit
|
|
697
|
-
.lendingPoolTrancheFixedTermConfig
|
|
698
|
-
.epochInterestRate,
|
|
699
|
-
epochLockStart: fixedTermDeposit.epochLockStart,
|
|
700
|
-
amount: this._userLendingService
|
|
701
|
-
.convertSharesToAssets(
|
|
702
|
-
fixedTermDeposit.trancheShares,
|
|
703
|
-
lastEpochUserTrancheDetails.tranche
|
|
704
|
-
.balance,
|
|
705
|
-
lastEpochUserTrancheDetails.tranche
|
|
706
|
-
.shares,
|
|
707
|
-
)
|
|
708
|
-
.toString(),
|
|
709
|
-
endTime:
|
|
710
|
-
parseInt(fixedTermDeposit.createdOn) +
|
|
711
|
-
lockDuration,
|
|
712
|
-
isLocked: fixedTermDeposit.isLocked,
|
|
713
|
-
isWithdrawalRequested:
|
|
714
|
-
fixedTermDeposit.isWithdrawalRequested,
|
|
715
|
-
startTime: parseInt(fixedTermDeposit.createdOn),
|
|
716
|
-
yieldEarnings: {
|
|
717
|
-
lastEpoch: lastEpochYieldEarned.toString(),
|
|
718
|
-
lifetime:
|
|
719
|
-
this.precisionToString(
|
|
720
|
-
lifetimeYieldEarned,
|
|
721
|
-
),
|
|
722
|
-
},
|
|
723
|
-
depositDetails: fixedLoanDepositDetails,
|
|
724
|
-
};
|
|
725
|
-
},
|
|
726
|
-
);
|
|
713
|
+
)
|
|
714
|
+
.toString(),
|
|
715
|
+
endTime:
|
|
716
|
+
parseInt(fixedTermDeposit.createdOn) +
|
|
717
|
+
lockDuration,
|
|
718
|
+
isLocked: fixedTermDeposit.isLocked,
|
|
719
|
+
isWithdrawalRequested:
|
|
720
|
+
fixedTermDeposit.isWithdrawalRequested,
|
|
721
|
+
startTime: parseInt(fixedTermDeposit.createdOn),
|
|
722
|
+
yieldEarnings: {
|
|
723
|
+
lastEpoch:
|
|
724
|
+
this.precisionToString(
|
|
725
|
+
lastEpochYieldEarned,
|
|
726
|
+
),
|
|
727
|
+
lifetime:
|
|
728
|
+
this.precisionToString(lifetimeYieldEarned),
|
|
729
|
+
},
|
|
730
|
+
depositDetails: fixedLoanDepositDetails,
|
|
731
|
+
};
|
|
732
|
+
});
|
|
727
733
|
|
|
728
|
-
|
|
734
|
+
// This POOL's last-epoch total: the tranche totals summed, the
|
|
735
|
+
// locks counted once (inside `total`).
|
|
736
|
+
poolYieldEarnedLastEpoch += lastEpochYield.total;
|
|
729
737
|
|
|
730
738
|
tranches.push({
|
|
731
739
|
...tranche,
|
|
732
740
|
investedAmount: userTrancheBalance,
|
|
733
741
|
yieldEarnings: {
|
|
734
|
-
lastEpoch:
|
|
742
|
+
lastEpoch: this.precisionToString(
|
|
743
|
+
lastEpochYield.variable,
|
|
744
|
+
),
|
|
735
745
|
lifetime: this.precisionToString(totalLifetimeFtdYield), // passing in total FTD yield to be subtracted by total trache lifetime later down
|
|
736
746
|
},
|
|
737
747
|
fixedLoans,
|
|
@@ -741,8 +751,9 @@ export class Portfolio {
|
|
|
741
751
|
|
|
742
752
|
portfolioLendingPoolsPromise.push({
|
|
743
753
|
...poolOverview,
|
|
744
|
-
totalYieldEarningsLastEpoch:
|
|
745
|
-
|
|
754
|
+
totalYieldEarningsLastEpoch: this.precisionToString(
|
|
755
|
+
poolYieldEarnedLastEpoch,
|
|
756
|
+
),
|
|
746
757
|
totalInvestedAmount: userPoolBalance.balance.toString(),
|
|
747
758
|
totalYieldEarningsLifetime:
|
|
748
759
|
userPoolBalance.yieldEarned.toString(),
|
|
@@ -796,7 +807,106 @@ export class Portfolio {
|
|
|
796
807
|
);
|
|
797
808
|
}
|
|
798
809
|
|
|
810
|
+
/**
|
|
811
|
+
* The lender's settled yield per cycle (epoch), per pool and tranche —
|
|
812
|
+
* what the chain credited at each close, NET of the performance fee
|
|
813
|
+
* (`domain/yield-history.ts`), in the deployment's own stable token. Each
|
|
814
|
+
* entry runs the same `epochTrancheYield` as `getPortfolioLendingData`'s
|
|
815
|
+
* last-epoch figures: a tranche's `yieldEarnings.lastEpoch` plus its
|
|
816
|
+
* locks' equals its entry for the epoch of the tranche's most recently
|
|
817
|
+
* APPLIED interest (older than the last cycle for a pool that has not
|
|
818
|
+
* cleared since; no entry, and a figure of 0, when the lender held
|
|
819
|
+
* nothing at that epoch).
|
|
820
|
+
*
|
|
821
|
+
* Sum entries with `aggregateYieldHistory` (all strategies, or one with
|
|
822
|
+
* `{ poolId }`). Only epochs in which the lender held shares appear — a
|
|
823
|
+
* new lender gets `[]`. Pools in `UNUSED_LENDING_POOL_IDS` are left out,
|
|
824
|
+
* as in `lendingPortfolioQuery`; Directus enablement is NOT applied.
|
|
825
|
+
*
|
|
826
|
+
* Cost: three parallel `SystemVariables` reads and the positions query in
|
|
827
|
+
* one round, then one subgraph request per page of the longest series
|
|
828
|
+
* (1000 rows a page) — normally two subgraph round trips in all, never one
|
|
829
|
+
* per epoch.
|
|
830
|
+
*
|
|
831
|
+
* On a LITE deployment, a subgraph that lacks the entities (a validation
|
|
832
|
+
* error naming them) yields `[]`; on a full deployment that error throws,
|
|
833
|
+
* like every other failure (`isEmptyHistoryError`).
|
|
834
|
+
*
|
|
835
|
+
* @throws RangeError on a malformed `fromEpoch` / `count`, before any
|
|
836
|
+
* network read.
|
|
837
|
+
*/
|
|
838
|
+
async getYieldHistory(
|
|
839
|
+
userAddress: string,
|
|
840
|
+
options: YieldHistoryOptions = {},
|
|
841
|
+
): Promise<YieldHistoryEntry[]> {
|
|
842
|
+
validateYieldHistoryOptions(options);
|
|
843
|
+
|
|
844
|
+
try {
|
|
845
|
+
const [currentEpoch, epochZeroStart, epochDuration, positions] =
|
|
846
|
+
await Promise.all([
|
|
847
|
+
this._systemVariablesAbi.currentEpochNumber(),
|
|
848
|
+
this._systemVariablesAbi.epochStartTimestamp(0),
|
|
849
|
+
this._systemVariablesAbi.epochDuration(),
|
|
850
|
+
this._graph.request<YieldHistoryPositionsResult>(
|
|
851
|
+
yieldHistoryPositionsQuery,
|
|
852
|
+
{
|
|
853
|
+
userAddress: userAddress.toLowerCase(),
|
|
854
|
+
unusedPools:
|
|
855
|
+
this._kasuConfig.UNUSED_LENDING_POOL_IDS,
|
|
856
|
+
first: YIELD_HISTORY_PAGE_SIZE,
|
|
857
|
+
},
|
|
858
|
+
),
|
|
859
|
+
]);
|
|
860
|
+
|
|
861
|
+
const window = resolveYieldHistoryWindow(
|
|
862
|
+
options,
|
|
863
|
+
currentEpoch.toNumber(),
|
|
864
|
+
);
|
|
865
|
+
if (!window || !positions.user) return [];
|
|
866
|
+
|
|
867
|
+
const userTranches: string[] = [];
|
|
868
|
+
const tranches = new Set<string>();
|
|
869
|
+
const locks: string[] = [];
|
|
870
|
+
for (const pool of positions.user.lendingPoolUserDetails) {
|
|
871
|
+
for (const position of pool.lendingPoolTrancheUserDetails) {
|
|
872
|
+
userTranches.push(position.id);
|
|
873
|
+
tranches.add(position.tranche.id);
|
|
874
|
+
for (const lock of position.userLendingPoolTrancheFixedTermDepositLocks) {
|
|
875
|
+
locks.push(lock.id);
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
if (userTranches.length === 0) return [];
|
|
880
|
+
|
|
881
|
+
const { rows } = await fetchYieldHistorySeries(
|
|
882
|
+
(variables) =>
|
|
883
|
+
this._graph.request<YieldHistoryPageResult>(
|
|
884
|
+
yieldHistoryPageQuery,
|
|
885
|
+
variables,
|
|
886
|
+
),
|
|
887
|
+
{ tranches: [...tranches], userTranches, locks },
|
|
888
|
+
window,
|
|
889
|
+
);
|
|
890
|
+
|
|
891
|
+
return buildYieldHistory({ positions, ...rows }, window, {
|
|
892
|
+
epochZeroStart: epochZeroStart.toNumber(),
|
|
893
|
+
epochDuration: epochDuration.toNumber(),
|
|
894
|
+
});
|
|
895
|
+
} catch (error) {
|
|
896
|
+
if (isEmptyHistoryError(error, this._isLiteDeployment)) return [];
|
|
897
|
+
throw error;
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
/**
|
|
902
|
+
* A money figure as a plain decimal string. Below a millionth of a token
|
|
903
|
+
* (the stable asset's own precision) is float noise, never money, so it
|
|
904
|
+
* is `'0'` — not `'1e-7'`, which `parseUnits` rejects, nor `'-3e-12'`. A
|
|
905
|
+
* small negative remainder (above −0.0001) is `'0'` as well.
|
|
906
|
+
*/
|
|
799
907
|
precisionToString(val: number): string {
|
|
908
|
+
if (Math.abs(val) < 1e-6) return '0';
|
|
909
|
+
|
|
800
910
|
if (val < 0 && val > -0.0001) {
|
|
801
911
|
return '0';
|
|
802
912
|
}
|
|
@@ -67,9 +67,11 @@ export const lendingPortfolioQuery = gql`
|
|
|
67
67
|
$epochId: BigInt!
|
|
68
68
|
$lastEpochId: BigInt!
|
|
69
69
|
$unusedPools: [String!]!
|
|
70
|
+
$first: Int!
|
|
70
71
|
) {
|
|
71
72
|
user(id: $userAddress) {
|
|
72
73
|
lendingPoolUserDetails(
|
|
74
|
+
first: $first
|
|
73
75
|
where: { lendingPool_not_in: $unusedPools }
|
|
74
76
|
) {
|
|
75
77
|
id
|
|
@@ -77,11 +79,11 @@ export const lendingPortfolioQuery = gql`
|
|
|
77
79
|
id
|
|
78
80
|
name
|
|
79
81
|
balance
|
|
80
|
-
tranches {
|
|
82
|
+
tranches(first: $first) {
|
|
81
83
|
shares
|
|
82
84
|
}
|
|
83
85
|
}
|
|
84
|
-
lendingPoolTrancheUserDetails {
|
|
86
|
+
lendingPoolTrancheUserDetails(first: $first) {
|
|
85
87
|
shares
|
|
86
88
|
lendingPoolTrancheUserEpochSharesUpdates(
|
|
87
89
|
orderDirection: desc
|
|
@@ -91,7 +93,7 @@ export const lendingPortfolioQuery = gql`
|
|
|
91
93
|
) {
|
|
92
94
|
shares
|
|
93
95
|
}
|
|
94
|
-
userLendingPoolTrancheFixedTermDepositLocks {
|
|
96
|
+
userLendingPoolTrancheFixedTermDepositLocks(first: $first) {
|
|
95
97
|
isLocked
|
|
96
98
|
unlockAmount
|
|
97
99
|
initialAmount
|
|
@@ -115,6 +117,14 @@ export const lendingPortfolioQuery = gql`
|
|
|
115
117
|
) {
|
|
116
118
|
shares
|
|
117
119
|
}
|
|
120
|
+
lockSharesAtLastEpoch: userLendingPoolTrancheFixedTermDepositLockShareUpdate(
|
|
121
|
+
orderBy: shareUpdatesIndex
|
|
122
|
+
orderDirection: desc
|
|
123
|
+
first: 1
|
|
124
|
+
where: { epochId_lt: $epochId }
|
|
125
|
+
) {
|
|
126
|
+
shares
|
|
127
|
+
}
|
|
118
128
|
}
|
|
119
129
|
tranche {
|
|
120
130
|
id
|
|
@@ -141,6 +151,7 @@ export const lendingPortfolioQuery = gql`
|
|
|
141
151
|
}
|
|
142
152
|
}
|
|
143
153
|
userRequests(
|
|
154
|
+
first: $first
|
|
144
155
|
where: {
|
|
145
156
|
user: $userAddress
|
|
146
157
|
userRequestEvents_: {
|
|
@@ -156,6 +167,7 @@ export const lendingPortfolioQuery = gql`
|
|
|
156
167
|
}
|
|
157
168
|
fixedTermConfigId
|
|
158
169
|
userRequestEvents(
|
|
170
|
+
first: $first
|
|
159
171
|
where: { type_in: [DepositInitiated, DepositIncreased] }
|
|
160
172
|
) {
|
|
161
173
|
id
|
|
@@ -110,6 +110,16 @@ export interface UserLendingPoolTrancheFixedTermDepositLock {
|
|
|
110
110
|
shares: string;
|
|
111
111
|
}[]
|
|
112
112
|
| undefined;
|
|
113
|
+
/**
|
|
114
|
+
* The lock's shares as of the last settled epoch (`epochId < currentEpoch`),
|
|
115
|
+
* the `sharesAtEpoch` of `epochTrancheYield`. Present in
|
|
116
|
+
* `lendingPortfolioQuery` responses only.
|
|
117
|
+
*/
|
|
118
|
+
lockSharesAtLastEpoch?:
|
|
119
|
+
| {
|
|
120
|
+
shares: string;
|
|
121
|
+
}[]
|
|
122
|
+
| undefined;
|
|
113
123
|
}
|
|
114
124
|
|
|
115
125
|
export interface LastEpochQueryResult {
|