@kasufinance/kasu-sdk 2.11.0 → 2.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/README.md +37 -2
  2. package/dist/bundle.cjs.js +1516 -71
  3. package/dist/bundle.esm.js +1511 -73
  4. package/dist/domain/index.d.ts +6 -2
  5. package/dist/domain/index.js +2 -0
  6. package/dist/domain/index.js.map +1 -1
  7. package/dist/domain/pool-tvl.d.ts +62 -0
  8. package/dist/domain/pool-tvl.js +22 -0
  9. package/dist/domain/pool-tvl.js.map +1 -0
  10. package/dist/domain/yield-history.d.ts +122 -0
  11. package/dist/domain/yield-history.js +95 -0
  12. package/dist/domain/yield-history.js.map +1 -0
  13. package/dist/facade/chain-configs.js +24 -0
  14. package/dist/facade/chain-configs.js.map +1 -1
  15. package/dist/facade/kasu.d.ts +2 -0
  16. package/dist/facade/kasu.js +13 -5
  17. package/dist/facade/kasu.js.map +1 -1
  18. package/dist/facade/strategies.d.ts +20 -0
  19. package/dist/facade/strategies.js +22 -0
  20. package/dist/facade/strategies.js.map +1 -1
  21. package/dist/facade/types.d.ts +20 -0
  22. package/dist/facade/user-portfolio.d.ts +32 -0
  23. package/dist/facade/user-portfolio.js +34 -0
  24. package/dist/facade/user-portfolio.js.map +1 -1
  25. package/dist/index.d.ts +5 -0
  26. package/dist/index.js +2 -0
  27. package/dist/index.js.map +1 -1
  28. package/dist/kasu-sdk.d.ts +9 -1
  29. package/dist/kasu-sdk.js +2 -2
  30. package/dist/kasu-sdk.js.map +1 -1
  31. package/dist/sdk-config.d.ts +20 -0
  32. package/dist/sdk-config.js +3 -1
  33. package/dist/sdk-config.js.map +1 -1
  34. package/dist/services/DataService/data-service.d.ts +81 -1
  35. package/dist/services/DataService/data-service.js +211 -6
  36. package/dist/services/DataService/data-service.js.map +1 -1
  37. package/dist/services/DataService/tvl-history.d.ts +296 -0
  38. package/dist/services/DataService/tvl-history.js +558 -0
  39. package/dist/services/DataService/tvl-history.js.map +1 -0
  40. package/dist/services/Portfolio/portfolio.d.ts +37 -0
  41. package/dist/services/Portfolio/portfolio.js +136 -56
  42. package/dist/services/Portfolio/portfolio.js.map +1 -1
  43. package/dist/services/Portfolio/queries.js +15 -3
  44. package/dist/services/Portfolio/queries.js.map +1 -1
  45. package/dist/services/Portfolio/types.d.ts +8 -0
  46. package/dist/services/Portfolio/yield-history.d.ts +162 -0
  47. package/dist/services/Portfolio/yield-history.js +378 -0
  48. package/dist/services/Portfolio/yield-history.js.map +1 -0
  49. package/dist/services/shared.d.ts +16 -0
  50. package/dist/services/shared.js +30 -0
  51. package/dist/services/shared.js.map +1 -1
  52. package/package.json +1 -1
  53. package/src/domain/index.ts +15 -10
  54. package/src/domain/pool-tvl.ts +66 -0
  55. package/src/domain/yield-history.ts +194 -0
  56. package/src/facade/chain-configs.ts +26 -0
  57. package/src/facade/kasu.ts +20 -2
  58. package/src/facade/strategies.ts +26 -0
  59. package/src/facade/types.ts +20 -0
  60. package/src/facade/user-portfolio.ts +40 -3
  61. package/src/index.ts +11 -0
  62. package/src/kasu-sdk.ts +19 -2
  63. package/src/sdk-config.ts +22 -0
  64. package/src/services/DataService/data-service.ts +296 -6
  65. package/src/services/DataService/tvl-history.ts +853 -0
  66. package/src/services/Portfolio/portfolio.ts +263 -153
  67. package/src/services/Portfolio/queries.ts +15 -3
  68. package/src/services/Portfolio/types.ts +10 -0
  69. package/src/services/Portfolio/yield-history.ts +541 -0
  70. package/src/services/shared.ts +38 -1
@@ -1,7 +1,9 @@
1
1
  import { Provider } from '@ethersproject/providers';
2
2
  import { RequestState } from '../domain/requests';
3
+ import { YieldHistoryEntry } from '../domain/yield-history';
3
4
  import { DataService } from '../services/DataService/data-service';
4
5
  import { Portfolio } from '../services/Portfolio/portfolio';
6
+ import { YieldHistoryOptions } from '../services/Portfolio/yield-history';
5
7
  import { UserRequest } from '../services/UserLending/types';
6
8
  import { UserLending } from '../services/UserLending/user-lending';
7
9
  import { UserPositions } from './types';
@@ -29,6 +31,36 @@ export declare class PortfolioFacade {
29
31
  * SDK was initialised with a Signer but you need a read-only provider).
30
32
  */
31
33
  getPositions(userAddress: string, provider?: Provider): Promise<UserPositions>;
34
+ /**
35
+ * The lender's settled yield per cycle, per pool and tranche: what each
36
+ * close credited them, NET of the performance fee (the chain credits it
37
+ * net), in display units of the deployment's own stable token (AUDD on
38
+ * XDC AUDD). `epochEnd` is unix seconds. Net only — no gross is offered.
39
+ *
40
+ * Validates `options` before any read (`RangeError` on a malformed one).
41
+ *
42
+ * ```ts
43
+ * const entries = await kasu.portfolio.getYieldHistory('0xUser...', { count: 52 });
44
+ * const allStrategies = aggregateYieldHistory(entries);
45
+ * const oneStrategy = aggregateYieldHistory(entries, { poolId });
46
+ * ```
47
+ *
48
+ * `getPositions`' `totalYieldEarningsLastEpoch` for a pool equals that
49
+ * pool's bar for the epoch of its most recently APPLIED interest — which
50
+ * is older than the last cycle for a pool that has not cleared since (the
51
+ * bar carries that older `epochId`). A lender who held nothing at that
52
+ * epoch has no bar there and a figure of 0; their newest bar is from
53
+ * when they last held shares.
54
+ *
55
+ * For a fixed-term lock holder the bars can sum to slightly more than the
56
+ * lifetime interest (up to about 0.2 %), because each top-up is valued at
57
+ * today's share price — show "earned to date" from the lifetime figure,
58
+ * never from the sum of the bars.
59
+ *
60
+ * `[]` for a lender with no history, and on a LITE deployment whose
61
+ * subgraph lacks the entities; on a full deployment that error throws.
62
+ */
63
+ getYieldHistory(userAddress: string, options?: YieldHistoryOptions): Promise<YieldHistoryEntry[]>;
32
64
  /**
33
65
  * Fetch a user's full transaction history (deposits, withdrawals, cancellations).
34
66
  */
@@ -41,6 +41,40 @@ export class PortfolioFacade {
41
41
  return { pools, summary };
42
42
  });
43
43
  }
44
+ /**
45
+ * The lender's settled yield per cycle, per pool and tranche: what each
46
+ * close credited them, NET of the performance fee (the chain credits it
47
+ * net), in display units of the deployment's own stable token (AUDD on
48
+ * XDC AUDD). `epochEnd` is unix seconds. Net only — no gross is offered.
49
+ *
50
+ * Validates `options` before any read (`RangeError` on a malformed one).
51
+ *
52
+ * ```ts
53
+ * const entries = await kasu.portfolio.getYieldHistory('0xUser...', { count: 52 });
54
+ * const allStrategies = aggregateYieldHistory(entries);
55
+ * const oneStrategy = aggregateYieldHistory(entries, { poolId });
56
+ * ```
57
+ *
58
+ * `getPositions`' `totalYieldEarningsLastEpoch` for a pool equals that
59
+ * pool's bar for the epoch of its most recently APPLIED interest — which
60
+ * is older than the last cycle for a pool that has not cleared since (the
61
+ * bar carries that older `epochId`). A lender who held nothing at that
62
+ * epoch has no bar there and a figure of 0; their newest bar is from
63
+ * when they last held shares.
64
+ *
65
+ * For a fixed-term lock holder the bars can sum to slightly more than the
66
+ * lifetime interest (up to about 0.2 %), because each top-up is valued at
67
+ * today's share price — show "earned to date" from the lifetime figure,
68
+ * never from the sum of the bars.
69
+ *
70
+ * `[]` for a lender with no history, and on a LITE deployment whose
71
+ * subgraph lacks the entities; on a full deployment that error throws.
72
+ */
73
+ getYieldHistory(userAddress, options) {
74
+ return __awaiter(this, void 0, void 0, function* () {
75
+ return yield this._portfolio.getYieldHistory(userAddress, options);
76
+ });
77
+ }
44
78
  /**
45
79
  * Fetch a user's full transaction history (deposits, withdrawals, cancellations).
46
80
  */
@@ -1 +1 @@
1
- {"version":3,"file":"user-portfolio.js","sourceRoot":"","sources":["../../src/facade/user-portfolio.ts"],"names":[],"mappings":";;;;;;;;;AAEA,OAAO,EAAE,kBAAkB,EAAgB,MAAM,oBAAoB,CAAC;AAQtE;;;;;GAKG;AACH,MAAM,OAAO,eAAe;IACxB,YACY,YAAyB,EACzB,YAAyB,EACzB,UAAqB;QAFrB,iBAAY,GAAZ,YAAY,CAAa;QACzB,iBAAY,GAAZ,YAAY,CAAa;QACzB,eAAU,GAAV,UAAU,CAAW;IAC9B,CAAC;IAEJ;;;;;;;;;;;OAWG;IACG,YAAY,CACd,WAAmB,EACnB,QAAmB;;YAEnB,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,eAAe,EAAE,CAAC;YAE/D,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,eAAe,CACzD,YAAY,CACf,CAAC;YAEF,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,uBAAuB,CACvD,WAAW,EACX,aAAa,EACb,YAAY,EACZ,QAAQ,CACX,CAAC;YAEF,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,mBAAmB,CACrD,WAAW,EACX,KAAK,EACL,YAAY,CACf,CAAC;YAEF,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;QAC9B,CAAC;KAAA;IAED;;OAEG;IACG,qBAAqB,CACvB,WAA0B;;YAE1B,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,eAAe,EAAE,CAAC;YAC/D,OAAO,MAAM,IAAI,CAAC,YAAY,CAAC,eAAe,CAC1C,WAAW,EACX,YAAY,CACf,CAAC;QACN,CAAC;KAAA;IAED;;;;;;;;;;;;;;;OAeG;IACG,gBAAgB,CAClB,WAA0B;;YAE1B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,WAAW,CAAC,CAAC;YAC/D,OAAO,QAAQ,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;QAC5C,CAAC;KAAA;CACJ"}
1
+ {"version":3,"file":"user-portfolio.js","sourceRoot":"","sources":["../../src/facade/user-portfolio.ts"],"names":[],"mappings":";;;;;;;;;AAEA,OAAO,EAAE,kBAAkB,EAAgB,MAAM,oBAAoB,CAAC;AAUtE;;;;;GAKG;AACH,MAAM,OAAO,eAAe;IACxB,YACY,YAAyB,EACzB,YAAyB,EACzB,UAAqB;QAFrB,iBAAY,GAAZ,YAAY,CAAa;QACzB,iBAAY,GAAZ,YAAY,CAAa;QACzB,eAAU,GAAV,UAAU,CAAW;IAC9B,CAAC;IAEJ;;;;;;;;;;;OAWG;IACG,YAAY,CACd,WAAmB,EACnB,QAAmB;;YAEnB,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,eAAe,EAAE,CAAC;YAE/D,MAAM,aAAa,GACf,MAAM,IAAI,CAAC,YAAY,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;YAE1D,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,uBAAuB,CACvD,WAAW,EACX,aAAa,EACb,YAAY,EACZ,QAAQ,CACX,CAAC;YAEF,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,mBAAmB,CACrD,WAAW,EACX,KAAK,EACL,YAAY,CACf,CAAC;YAEF,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;QAC9B,CAAC;KAAA;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;IACG,eAAe,CACjB,WAAmB,EACnB,OAA6B;;YAE7B,OAAO,MAAM,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACvE,CAAC;KAAA;IAED;;OAEG;IACG,qBAAqB,CACvB,WAA0B;;YAE1B,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,eAAe,EAAE,CAAC;YAC/D,OAAO,MAAM,IAAI,CAAC,YAAY,CAAC,eAAe,CAC1C,WAAW,EACX,YAAY,CACf,CAAC;QACN,CAAC;KAAA;IAED;;;;;;;;;;;;;;;OAeG;IACG,gBAAgB,CAClB,WAA0B;;YAE1B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,WAAW,CAAC,CAAC;YAC/D,OAAO,QAAQ,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;QAC5C,CAAC;KAAA;CACJ"}
package/dist/index.d.ts CHANGED
@@ -1,9 +1,14 @@
1
1
  export { KasuSdk } from './kasu-sdk';
2
+ export type { KasuSdkOptions } from './kasu-sdk';
2
3
  export type { ContractAddresses, SdkConfigOptions } from './sdk-config';
3
4
  export { SdkConfig } from './sdk-config';
4
5
  export type { PoolOverview, TrancheData, LendingTotals, PoolRepayment, RiskManagement, PoolDelegateProfileAndHistory, PoolTranche, PoolCreditMetrics, BadAndDoubtfulDebts, FinancialReportingDocuments, } from './services/DataService/types';
5
6
  export type { UserRequest, UserRequestEvent, UserTrancheBalance, UserPoolBalance, UserApyBonus, PortfolioUserTrancheBalance, } from './services/UserLending/types';
6
7
  export type { PortfolioSummary, PortfolioLendingPool, PortfolioTranche, PortfolioRewards, PortfolioTrancheDepositDetails, } from './services/Portfolio/types';
8
+ export type { YieldHistoryOptions } from './services/Portfolio/yield-history';
9
+ export type { PoolTvlHistoryOptions } from './services/DataService/tvl-history';
10
+ export { PastStateUnavailableError, PoolTvlHistoryAbortedError, PoolTvlHistoryTimeoutError, } from './services/DataService/tvl-history';
11
+ export { NO_HISTORY_PROVIDER_MESSAGE } from './services/DataService/data-service';
7
12
  export type { UserLock, UserBonusData, LockPeriod, GQLGetLockingPeriods, SystemVariables, } from './services/Locking/types';
8
13
  export type { PoolOverviewDirectus, PlatformOverviewDirectus, } from './services/DataService/directus-types';
9
14
  export { NO_DIRECTUS_URL_MESSAGE } from './services/DataService/directus-client';
package/dist/index.js CHANGED
@@ -3,6 +3,8 @@
3
3
  // ---------------------------------------------------------------------------
4
4
  export { KasuSdk } from './kasu-sdk';
5
5
  export { SdkConfig } from './sdk-config';
6
+ export { PastStateUnavailableError, PoolTvlHistoryAbortedError, PoolTvlHistoryTimeoutError, } from './services/DataService/tvl-history';
7
+ export { NO_HISTORY_PROVIDER_MESSAGE } from './services/DataService/data-service';
6
8
  export { NO_DIRECTUS_URL_MESSAGE } from './services/DataService/directus-client';
7
9
  // ---------------------------------------------------------------------------
8
10
  // Re-export facade (high-level integrator API)
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,4CAA4C;AAC5C,8EAA8E;AAC9E,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAMrC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAgDzC,OAAO,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AAEjF,8EAA8E;AAC9E,+CAA+C;AAC/C,8EAA8E;AAC9E,cAAc,UAAU,CAAC;AAEzB,8EAA8E;AAC9E,6EAA6E;AAC7E,uDAAuD;AACvD,8EAA8E;AAC9E,cAAc,UAAU,CAAC;AAEzB,8EAA8E;AAC9E,6EAA6E;AAC7E,uEAAuE;AACvE,wDAAwD;AACxD,8EAA8E;AAC9E,cAAc,SAAS,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,4CAA4C;AAC5C,8EAA8E;AAC9E,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAOrC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAsCzC,OAAO,EACH,yBAAyB,EACzB,0BAA0B,EAC1B,0BAA0B,GAC7B,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,2BAA2B,EAAE,MAAM,qCAAqC,CAAC;AAelF,OAAO,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AAEjF,8EAA8E;AAC9E,+CAA+C;AAC/C,8EAA8E;AAC9E,cAAc,UAAU,CAAC;AAEzB,8EAA8E;AAC9E,6EAA6E;AAC7E,uDAAuD;AACvD,8EAA8E;AAC9E,cAAc,UAAU,CAAC;AAEzB,8EAA8E;AAC9E,6EAA6E;AAC7E,uEAAuE;AACvE,wDAAwD;AACxD,8EAA8E;AAC9E,cAAc,SAAS,CAAC"}
@@ -6,6 +6,14 @@ import { KSULocking } from './services/Locking/locking';
6
6
  import { Portfolio } from './services/Portfolio/portfolio';
7
7
  import { Swapper } from './services/Swapper/swapper';
8
8
  import { UserLending } from './services/UserLending/user-lending';
9
+ /** Optional providers beyond the main signer-or-provider. */
10
+ export interface KasuSdkOptions {
11
+ /**
12
+ * A provider that SERVES PAST STATE (an archive RPC), for
13
+ * `DataService.getPoolTvlHistory`. Wins over `SdkConfig.historyRpcUrls`.
14
+ */
15
+ historyProvider?: Provider;
16
+ }
9
17
  export declare class KasuSdk {
10
18
  private readonly _graphClient;
11
19
  readonly Locking: KSULocking;
@@ -13,5 +21,5 @@ export declare class KasuSdk {
13
21
  readonly UserLending: UserLending;
14
22
  readonly Portfolio: Portfolio;
15
23
  readonly Swapper: Swapper;
16
- constructor(config: SdkConfig, signerOrProvider: Provider | Signer);
24
+ constructor(config: SdkConfig, signerOrProvider: Provider | Signer, options?: KasuSdkOptions);
17
25
  }
package/dist/kasu-sdk.js CHANGED
@@ -5,11 +5,11 @@ import { Portfolio } from './services/Portfolio/portfolio';
5
5
  import { Swapper } from './services/Swapper/swapper';
6
6
  import { UserLending } from './services/UserLending/user-lending';
7
7
  export class KasuSdk {
8
- constructor(config, signerOrProvider) {
8
+ constructor(config, signerOrProvider, options = {}) {
9
9
  this._graphClient = new GraphQLClient(config.subgraphUrl);
10
10
  this.Locking = new KSULocking(config, signerOrProvider);
11
11
  this.UserLending = new UserLending(config, signerOrProvider);
12
- this.DataService = new DataService(config, signerOrProvider);
12
+ this.DataService = new DataService(config, signerOrProvider, options.historyProvider);
13
13
  this.Portfolio = new Portfolio(config, signerOrProvider);
14
14
  this.Swapper = new Swapper();
15
15
  }
@@ -1 +1 @@
1
- {"version":3,"file":"kasu-sdk.js","sourceRoot":"","sources":["../src/kasu-sdk.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhD,OAAO,EAAE,WAAW,EAAE,MAAM,qCAAqC,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAC3D,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,qCAAqC,CAAC;AAElE,MAAM,OAAO,OAAO;IAOhB,YAAY,MAAiB,EAAE,gBAAmC;QAC9D,IAAI,CAAC,YAAY,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAC1D,IAAI,CAAC,OAAO,GAAG,IAAI,UAAU,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;QACxD,IAAI,CAAC,WAAW,GAAG,IAAI,WAAW,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;QAC7D,IAAI,CAAC,WAAW,GAAG,IAAI,WAAW,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;QAC7D,IAAI,CAAC,SAAS,GAAG,IAAI,SAAS,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;QACzD,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IACjC,CAAC;CACJ"}
1
+ {"version":3,"file":"kasu-sdk.js","sourceRoot":"","sources":["../src/kasu-sdk.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhD,OAAO,EAAE,WAAW,EAAE,MAAM,qCAAqC,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAC3D,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,qCAAqC,CAAC;AAWlE,MAAM,OAAO,OAAO;IAOhB,YACI,MAAiB,EACjB,gBAAmC,EACnC,UAA0B,EAAE;QAE5B,IAAI,CAAC,YAAY,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAC1D,IAAI,CAAC,OAAO,GAAG,IAAI,UAAU,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;QACxD,IAAI,CAAC,WAAW,GAAG,IAAI,WAAW,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;QAC7D,IAAI,CAAC,WAAW,GAAG,IAAI,WAAW,CAC9B,MAAM,EACN,gBAAgB,EAChB,OAAO,CAAC,eAAe,CAC1B,CAAC;QACF,IAAI,CAAC,SAAS,GAAG,IAAI,SAAS,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;QACzD,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IACjC,CAAC;CACJ"}
@@ -49,6 +49,22 @@ export interface SdkConfigOptions {
49
49
  * @default 6
50
50
  */
51
51
  stableAssetDecimals?: number;
52
+ /**
53
+ * RPC URLs that SERVE PAST STATE (archive nodes), tried IN ORDER on
54
+ * failure, used only by `DataService.getPoolTvlHistory` to read the
55
+ * off-chain TVL at old blocks. A pruned node refuses those reads (some
56
+ * answer as if the call reverted), so these are never the default read
57
+ * RPC. An explicit `historyProvider` passed to `KasuSdk` / `Kasu.create`
58
+ * wins over them. The public defaults are rate-limited: an integrator
59
+ * should pass its own archive provider.
60
+ * @default [] — none
61
+ */
62
+ historyRpcUrls?: string[];
63
+ /**
64
+ * The chain id the history providers are pinned to (no `eth_chainId`
65
+ * round trip). `Kasu.create` sets it from the chain config.
66
+ */
67
+ chainId?: number;
52
68
  }
53
69
  export declare class SdkConfig {
54
70
  subgraphUrl: string;
@@ -59,5 +75,9 @@ export declare class SdkConfig {
59
75
  isLiteDeployment: boolean;
60
76
  poolMetadataMapping: Record<string, string>;
61
77
  stableAssetDecimals: number;
78
+ /** See `SdkConfigOptions.historyRpcUrls`. `[]` when none. */
79
+ historyRpcUrls: string[];
80
+ /** See `SdkConfigOptions.chainId`. */
81
+ chainId: number | undefined;
62
82
  constructor(options: SdkConfigOptions);
63
83
  }
@@ -1,6 +1,6 @@
1
1
  export class SdkConfig {
2
2
  constructor(options) {
3
- var _a, _b, _c, _d;
3
+ var _a, _b, _c, _d, _e;
4
4
  this.subgraphUrl = options.subgraphUrl;
5
5
  this.contracts = options.contracts;
6
6
  this.directusUrl = (_a = options.directusUrl) !== null && _a !== void 0 ? _a : '';
@@ -15,6 +15,8 @@ export class SdkConfig {
15
15
  this.isLiteDeployment = (_b = options.isLiteDeployment) !== null && _b !== void 0 ? _b : false;
16
16
  this.poolMetadataMapping = (_c = options.poolMetadataMapping) !== null && _c !== void 0 ? _c : {};
17
17
  this.stableAssetDecimals = (_d = options.stableAssetDecimals) !== null && _d !== void 0 ? _d : 6;
18
+ this.historyRpcUrls = [...((_e = options.historyRpcUrls) !== null && _e !== void 0 ? _e : [])];
19
+ this.chainId = options.chainId;
18
20
  }
19
21
  }
20
22
  //# sourceMappingURL=sdk-config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sdk-config.js","sourceRoot":"","sources":["../src/sdk-config.ts"],"names":[],"mappings":"AAsDA,MAAM,OAAO,SAAS;IAUlB,YAAY,OAAyB;;QACjC,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;QACvC,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;QACnC,IAAI,CAAC,WAAW,GAAG,MAAA,OAAO,CAAC,WAAW,mCAAI,EAAE,CAAC;QAC7C,+DAA+D;QAC/D,qEAAqE;QACrE,uEAAuE;QACvE,0DAA0D;QAC1D,IAAI,CAAC,uBAAuB;YACxB,OAAO,CAAC,uBAAuB,CAAC,MAAM,GAAG,CAAC;gBACtC,CAAC,CAAC,OAAO,CAAC,uBAAuB;gBACjC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACf,IAAI,CAAC,gBAAgB,GAAG,MAAA,OAAO,CAAC,gBAAgB,mCAAI,KAAK,CAAC;QAC1D,IAAI,CAAC,mBAAmB,GAAG,MAAA,OAAO,CAAC,mBAAmB,mCAAI,EAAE,CAAC;QAC7D,IAAI,CAAC,mBAAmB,GAAG,MAAA,OAAO,CAAC,mBAAmB,mCAAI,CAAC,CAAC;IAChE,CAAC;CACJ"}
1
+ {"version":3,"file":"sdk-config.js","sourceRoot":"","sources":["../src/sdk-config.ts"],"names":[],"mappings":"AAsEA,MAAM,OAAO,SAAS;IAclB,YAAY,OAAyB;;QACjC,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;QACvC,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;QACnC,IAAI,CAAC,WAAW,GAAG,MAAA,OAAO,CAAC,WAAW,mCAAI,EAAE,CAAC;QAC7C,+DAA+D;QAC/D,qEAAqE;QACrE,uEAAuE;QACvE,0DAA0D;QAC1D,IAAI,CAAC,uBAAuB;YACxB,OAAO,CAAC,uBAAuB,CAAC,MAAM,GAAG,CAAC;gBACtC,CAAC,CAAC,OAAO,CAAC,uBAAuB;gBACjC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACf,IAAI,CAAC,gBAAgB,GAAG,MAAA,OAAO,CAAC,gBAAgB,mCAAI,KAAK,CAAC;QAC1D,IAAI,CAAC,mBAAmB,GAAG,MAAA,OAAO,CAAC,mBAAmB,mCAAI,EAAE,CAAC;QAC7D,IAAI,CAAC,mBAAmB,GAAG,MAAA,OAAO,CAAC,mBAAmB,mCAAI,CAAC,CAAC;QAC5D,IAAI,CAAC,cAAc,GAAG,CAAC,GAAG,CAAC,MAAA,OAAO,CAAC,cAAc,mCAAI,EAAE,CAAC,CAAC,CAAC;QAC1D,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IACnC,CAAC;CACJ"}
@@ -1,16 +1,33 @@
1
1
  import { Provider } from '@ethersproject/abstract-provider';
2
2
  import { Signer } from 'ethers';
3
+ import { PoolTvlHistoryEntry } from '../../domain/pool-tvl';
3
4
  import { SdkConfig } from '../../sdk-config';
4
5
  import { NftBoostDirectus, PlatformOverviewDirectus } from './directus-types';
5
6
  import { LendingPoolConfigurationSubgraph, LendingPoolSubgraph } from './subgraph-types';
7
+ import { PoolTvlHistoryOptions } from './tvl-history';
6
8
  import { BadAndDoubtfulDebts, FinancialReportingDocuments, LendingTotals, PoolCreditMetrics, PoolDelegateProfileAndHistory, PoolOverview, PoolRepayment, PoolTranche, RiskManagement } from './types';
9
+ /** Thrown by `getPoolTvlHistory` when no provider that serves past state is configured. */
10
+ export declare const NO_HISTORY_PROVIDER_MESSAGE = "getPoolTvlHistory: no history provider; pass historyProvider or set historyRpcUrls to RPCs that serve past state";
7
11
  export declare class DataService {
8
12
  private _kasuConfig;
9
13
  private readonly _graph;
10
14
  private readonly _externalTvlAbi;
15
+ private readonly _systemVariablesAbi;
11
16
  private readonly _directus;
12
17
  private _directusPoolOverview;
13
- constructor(_kasuConfig: SdkConfig, signerOrProvider: Signer | Provider);
18
+ private readonly _explicitHistoryProvider;
19
+ private _builtHistoryProviders;
20
+ /** Immutable past-block reads, kept for the life of this instance. */
21
+ private readonly _tvlHistoryCache;
22
+ /**
23
+ * @param historyProvider - a provider that SERVES PAST STATE (an archive
24
+ * RPC), used only by `getPoolTvlHistory` for the off-chain TVL at old
25
+ * blocks. Without one, providers are built on `SdkConfig.historyRpcUrls`
26
+ * (tried in order); with neither, that one call throws
27
+ * `NO_HISTORY_PROVIDER_MESSAGE`. Never the default provider: a pruned
28
+ * node refuses old blocks.
29
+ */
30
+ constructor(_kasuConfig: SdkConfig, signerOrProvider: Signer | Provider, historyProvider?: Provider);
14
31
  private getUrlFromFile;
15
32
  /**
16
33
  * Maps a pool ID to its metadata source pool ID.
@@ -34,6 +51,69 @@ export declare class DataService {
34
51
  getPlatformOverview(): Promise<PlatformOverviewDirectus>;
35
52
  getNftBoost(): Promise<Omit<NftBoostDirectus, 'id'>>;
36
53
  getOffChainTvl(poolIds: string[]): Promise<Map<string, string>>;
54
+ /**
55
+ * The pool's TVL — the total lent into it by everyone — at every cycle
56
+ * boundary, then as of now: the data behind a TVL chart.
57
+ *
58
+ * One `clearing` point per FINISHED clearing, read at the block it
59
+ * finished in (`LendingPoolClearing.endBlockNumber`), then one `current`
60
+ * point. Every point is `poolTvl(onChain, offChain)`, the definition
61
+ * `getPoolOverview` uses for `totalValueLocked.total`:
62
+ *
63
+ * - on-chain: `lendingPool.balance` from the subgraph, read with
64
+ * time-travel queries (`block: { number }`);
65
+ * - off-chain: `ExternalTVL.externalTVLOfPool(pool)` at the same block,
66
+ * through the HISTORY providers (see the constructor). 0 before the
67
+ * contract was deployed (decided by `getCode`, and only if the same
68
+ * provider shows the pool's own code there); any failed read throws.
69
+ *
70
+ * The `current` point mixes two sources: the subgraph's latest balance
71
+ * (and its latest block time) and `externalTVLOfPool` at `latest` on the
72
+ * history provider. `getPoolOverview` reads the same two, the off-chain
73
+ * one on the default provider, so the last point equals
74
+ * `totalValueLocked.total` when both reads succeed. They can differ when
75
+ * `getPoolOverview`'s off-chain read FAILS — it then falls back to 0 —
76
+ * or when the figure moves between the two calls.
77
+ *
78
+ * Units: `tvl` in display units of the deployment's own stable token
79
+ * (USDC on Base and XDC USDC, AUDD on XDC AUDD); `timestamp` in unix
80
+ * seconds. Ascending in time. See `PoolTvlHistoryEntry`.
81
+ *
82
+ * Cost: one subgraph request for the clearings (per thousand), one per
83
+ * hundred distinct uncached clearing blocks, a `currentEpochNumber` read;
84
+ * then, on the history providers, one `externalTVLOfPool` per distinct
85
+ * uncached block plus the latest, and one to about log2(n) `getCode`s —
86
+ * at most `TVL_HISTORY_RPC_CONCURRENCY` in flight. Final blocks are
87
+ * cached on this instance, so a second call reads only what is new.
88
+ * `timeoutMs` (default 30 s) bounds the whole call.
89
+ *
90
+ * `[]` for a pool the subgraph does not know, for a window with no epoch
91
+ * in it, and on a LITE deployment whose subgraph lacks the entities. On a
92
+ * full deployment that schema error throws, like every network, indexing
93
+ * or past-state failure.
94
+ *
95
+ * @throws RangeError / TypeError on a malformed option or a pool id that
96
+ * is not an address, and `NO_HISTORY_PROVIDER_MESSAGE` when the
97
+ * deployment has an `ExternalTVL` contract but no history provider — all
98
+ * before any network read. `PoolTvlHistoryTimeoutError` /
99
+ * `PoolTvlHistoryAbortedError` on the deadline or the signal,
100
+ * `PastStateUnavailableError` from a pruned history provider.
101
+ */
102
+ getPoolTvlHistory(poolId: string, options?: PoolTvlHistoryOptions): Promise<PoolTvlHistoryEntry[]>;
103
+ private _readPoolTvlHistory;
104
+ /** The pool's balance at each block: cached final blocks, then one batch. */
105
+ private _balancesAtBlocks;
106
+ /** `null` when the deployment has no `ExternalTVL` contract. */
107
+ private _externalTvlAddress;
108
+ /** Seam for tests: the real reader over the history RPCs. */
109
+ private _createOffChainTvlReader;
110
+ /**
111
+ * The history RPCs, in fallback order: the explicit provider, else ONE
112
+ * provider per `historyRpcUrls` entry — built here and nowhere else,
113
+ * pinned to `SdkConfig.chainId` when known, each with a per-call timeout.
114
+ * Built once per instance.
115
+ */
116
+ private _historyRpcs;
37
117
  getPoolOverview(epochId: string, id_in?: string[]): Promise<PoolOverview[]>;
38
118
  getPerformanceFee(): Promise<number>;
39
119
  getRiskManagement(id_in?: string[]): Promise<RiskManagement[]>;
@@ -19,19 +19,36 @@ var __rest = (this && this.__rest) || function (s, e) {
19
19
  return t;
20
20
  };
21
21
  import { readItems, readSingleton } from '@directus/sdk';
22
- import { formatUnits } from 'ethers/lib/utils';
22
+ import { BigNumber, providers } from 'ethers';
23
+ import { formatUnits, isAddress } from 'ethers/lib/utils';
23
24
  import { GraphQLClient } from 'graphql-request';
24
- import { KasuPoolExternalTVLAbi__factory, } from '../../contracts';
25
+ import { ISystemVariablesAbi__factory, KasuPoolExternalTVLAbi__factory, } from '../../contracts';
26
+ import { poolTvl } from '../../domain/pool-tvl';
25
27
  import { epochRateToApy } from '../../domain/rates';
26
28
  import { getSystemVariablesQuery } from '../Locking/queries';
27
- import { filterArray } from '../shared';
29
+ import { filterArray, isEmptyHistoryError } from '../shared';
28
30
  import { createDirectusClient, } from './directus-client';
29
31
  import { getAllTrancheConfigurationsQuery, getAllTranchesQuery, getLendingPoolWithdrawalAndDepositsQuery, getPoolNameQuery, getPoolOverviewQuery, } from './queries';
32
+ import { buildPoolTvlHistory, createOffChainTvlReader, distinctBlocks, fetchOffChainTvlAtBlocks, fetchPoolBalancesAtBlocks, fetchPoolClearings, PastBlockCache, resolvePoolTvlHistoryWindow, runCancellable, TVL_HISTORY_CACHE_DEPTH, TVL_HISTORY_DEFAULT_TIMEOUT_MS, TVL_HISTORY_RPC_TIMEOUT_MS, validatePoolTvlHistoryOptions, } from './tvl-history';
33
+ /** Thrown by `getPoolTvlHistory` when no provider that serves past state is configured. */
34
+ export const NO_HISTORY_PROVIDER_MESSAGE = 'getPoolTvlHistory: no history provider; pass historyProvider or set historyRpcUrls to RPCs that serve past state';
30
35
  export class DataService {
31
- constructor(_kasuConfig, signerOrProvider) {
36
+ /**
37
+ * @param historyProvider - a provider that SERVES PAST STATE (an archive
38
+ * RPC), used only by `getPoolTvlHistory` for the off-chain TVL at old
39
+ * blocks. Without one, providers are built on `SdkConfig.historyRpcUrls`
40
+ * (tried in order); with neither, that one call throws
41
+ * `NO_HISTORY_PROVIDER_MESSAGE`. Never the default provider: a pruned
42
+ * node refuses old blocks.
43
+ */
44
+ constructor(_kasuConfig, signerOrProvider, historyProvider) {
32
45
  this._kasuConfig = _kasuConfig;
46
+ /** Immutable past-block reads, kept for the life of this instance. */
47
+ this._tvlHistoryCache = new PastBlockCache();
33
48
  this._externalTvlAbi = KasuPoolExternalTVLAbi__factory.connect(_kasuConfig.contracts.ExternalTVL, signerOrProvider);
49
+ this._systemVariablesAbi = ISystemVariablesAbi__factory.connect(_kasuConfig.contracts.SystemVariables, signerOrProvider);
34
50
  this._graph = new GraphQLClient(_kasuConfig.subgraphUrl);
51
+ this._explicitHistoryProvider = historyProvider;
35
52
  this._directus = createDirectusClient(_kasuConfig.directusUrl);
36
53
  }
37
54
  getUrlFromFile(fileName) {
@@ -111,6 +128,194 @@ export class DataService {
111
128
  return tvlMap;
112
129
  });
113
130
  }
131
+ /**
132
+ * The pool's TVL — the total lent into it by everyone — at every cycle
133
+ * boundary, then as of now: the data behind a TVL chart.
134
+ *
135
+ * One `clearing` point per FINISHED clearing, read at the block it
136
+ * finished in (`LendingPoolClearing.endBlockNumber`), then one `current`
137
+ * point. Every point is `poolTvl(onChain, offChain)`, the definition
138
+ * `getPoolOverview` uses for `totalValueLocked.total`:
139
+ *
140
+ * - on-chain: `lendingPool.balance` from the subgraph, read with
141
+ * time-travel queries (`block: { number }`);
142
+ * - off-chain: `ExternalTVL.externalTVLOfPool(pool)` at the same block,
143
+ * through the HISTORY providers (see the constructor). 0 before the
144
+ * contract was deployed (decided by `getCode`, and only if the same
145
+ * provider shows the pool's own code there); any failed read throws.
146
+ *
147
+ * The `current` point mixes two sources: the subgraph's latest balance
148
+ * (and its latest block time) and `externalTVLOfPool` at `latest` on the
149
+ * history provider. `getPoolOverview` reads the same two, the off-chain
150
+ * one on the default provider, so the last point equals
151
+ * `totalValueLocked.total` when both reads succeed. They can differ when
152
+ * `getPoolOverview`'s off-chain read FAILS — it then falls back to 0 —
153
+ * or when the figure moves between the two calls.
154
+ *
155
+ * Units: `tvl` in display units of the deployment's own stable token
156
+ * (USDC on Base and XDC USDC, AUDD on XDC AUDD); `timestamp` in unix
157
+ * seconds. Ascending in time. See `PoolTvlHistoryEntry`.
158
+ *
159
+ * Cost: one subgraph request for the clearings (per thousand), one per
160
+ * hundred distinct uncached clearing blocks, a `currentEpochNumber` read;
161
+ * then, on the history providers, one `externalTVLOfPool` per distinct
162
+ * uncached block plus the latest, and one to about log2(n) `getCode`s —
163
+ * at most `TVL_HISTORY_RPC_CONCURRENCY` in flight. Final blocks are
164
+ * cached on this instance, so a second call reads only what is new.
165
+ * `timeoutMs` (default 30 s) bounds the whole call.
166
+ *
167
+ * `[]` for a pool the subgraph does not know, for a window with no epoch
168
+ * in it, and on a LITE deployment whose subgraph lacks the entities. On a
169
+ * full deployment that schema error throws, like every network, indexing
170
+ * or past-state failure.
171
+ *
172
+ * @throws RangeError / TypeError on a malformed option or a pool id that
173
+ * is not an address, and `NO_HISTORY_PROVIDER_MESSAGE` when the
174
+ * deployment has an `ExternalTVL` contract but no history provider — all
175
+ * before any network read. `PoolTvlHistoryTimeoutError` /
176
+ * `PoolTvlHistoryAbortedError` on the deadline or the signal,
177
+ * `PastStateUnavailableError` from a pruned history provider.
178
+ */
179
+ getPoolTvlHistory(poolId_1) {
180
+ return __awaiter(this, arguments, void 0, function* (poolId, options = {}) {
181
+ var _a;
182
+ validatePoolTvlHistoryOptions(options);
183
+ if (!isAddress(poolId)) {
184
+ throw new TypeError(`getPoolTvlHistory: poolId must be an address, got ${String(poolId)}`);
185
+ }
186
+ const pool = poolId.toLowerCase();
187
+ const externalTvl = this._externalTvlAddress();
188
+ const rpcs = externalTvl ? this._historyRpcs() : [];
189
+ if (externalTvl && rpcs.length === 0) {
190
+ throw new Error(NO_HISTORY_PROVIDER_MESSAGE);
191
+ }
192
+ return yield runCancellable((_a = options.timeoutMs) !== null && _a !== void 0 ? _a : TVL_HISTORY_DEFAULT_TIMEOUT_MS, options.signal, (cancellation) => this._readPoolTvlHistory(pool, options, externalTvl
193
+ ? this._createOffChainTvlReader({
194
+ externalTvl,
195
+ pool,
196
+ rpcs,
197
+ cancellation,
198
+ })
199
+ : null, externalTvl !== null && externalTvl !== void 0 ? externalTvl : '', cancellation));
200
+ });
201
+ }
202
+ _readPoolTvlHistory(pool, options, reader, externalTvl, cancellation) {
203
+ return __awaiter(this, void 0, void 0, function* () {
204
+ var _a, _b, _c;
205
+ const graph = (document, variables, signal) => this._graph.request({ document, variables, signal });
206
+ const scope = options.fromEpoch === undefined && options.count !== undefined
207
+ ? { kind: 'newest', count: options.count }
208
+ : { kind: 'from', fromEpoch: (_a = options.fromEpoch) !== null && _a !== void 0 ? _a : 0 };
209
+ try {
210
+ const [currentEpochNumber, { clearings, snapshot }] = yield Promise.all([
211
+ this._systemVariablesAbi.currentEpochNumber(),
212
+ fetchPoolClearings(graph, pool, scope, cancellation),
213
+ ]);
214
+ const currentEpoch = currentEpochNumber.toNumber();
215
+ const window = resolvePoolTvlHistoryWindow(options, currentEpoch);
216
+ const poolNow = snapshot.pool;
217
+ if (!window || !poolNow)
218
+ return [];
219
+ const head = (_b = snapshot.meta) === null || _b === void 0 ? void 0 : _b.block;
220
+ if (!head || typeof head.timestamp !== 'number') {
221
+ throw new Error('getPoolTvlHistory: the subgraph returned no latest block time');
222
+ }
223
+ const inWindow = clearings.filter((c) => c.epochId >= window.fromEpoch &&
224
+ c.epochId <= window.toEpoch);
225
+ const blocks = distinctBlocks(inWindow);
226
+ const withCurrent = window.toEpoch >= currentEpoch;
227
+ const cacheable = (block) => block <= head.number - TVL_HISTORY_CACHE_DEPTH;
228
+ const [balances, offChainRead] = yield Promise.all([
229
+ this._balancesAtBlocks(graph, pool, blocks, cacheable, cancellation),
230
+ reader
231
+ ? fetchOffChainTvlAtBlocks(reader, blocks, {
232
+ withLatest: withCurrent,
233
+ cancellation,
234
+ cache: this._tvlHistoryCache,
235
+ cacheKey: (kind, block) => `${kind}|${externalTvl}|${pool}|${String(block)}`,
236
+ cacheable,
237
+ })
238
+ : {
239
+ offChain: new Map(blocks.map((b) => [b, BigNumber.from(0)])),
240
+ latest: null,
241
+ },
242
+ ]);
243
+ return buildPoolTvlHistory({
244
+ clearings: inWindow,
245
+ balances,
246
+ offChain: offChainRead.offChain,
247
+ current: withCurrent
248
+ ? {
249
+ epochId: currentEpoch,
250
+ timestamp: head.timestamp,
251
+ balance: poolNow.balance,
252
+ offChain: (_c = offChainRead.latest) !== null && _c !== void 0 ? _c : BigNumber.from(0),
253
+ }
254
+ : null,
255
+ decimals: this._kasuConfig.stableAssetDecimals,
256
+ });
257
+ }
258
+ catch (error) {
259
+ if (isEmptyHistoryError(error, this._kasuConfig.isLiteDeployment)) {
260
+ return [];
261
+ }
262
+ throw error;
263
+ }
264
+ });
265
+ }
266
+ /** The pool's balance at each block: cached final blocks, then one batch. */
267
+ _balancesAtBlocks(graph, pool, blocks, cacheable, cancellation) {
268
+ return __awaiter(this, void 0, void 0, function* () {
269
+ const key = (block) => `balance|${this._kasuConfig.subgraphUrl}|${pool}|${String(block)}`;
270
+ const balances = new Map();
271
+ const missing = [];
272
+ for (const block of blocks) {
273
+ const hit = cacheable(block)
274
+ ? this._tvlHistoryCache.get(key(block))
275
+ : undefined;
276
+ if (hit === undefined)
277
+ missing.push(block);
278
+ else
279
+ balances.set(block, hit);
280
+ }
281
+ if (missing.length > 0) {
282
+ const read = yield fetchPoolBalancesAtBlocks(graph, pool, missing, cancellation);
283
+ for (const [block, balance] of read.balances) {
284
+ balances.set(block, balance);
285
+ if (cacheable(block))
286
+ this._tvlHistoryCache.set(key(block), balance);
287
+ }
288
+ }
289
+ return balances;
290
+ });
291
+ }
292
+ /** `null` when the deployment has no `ExternalTVL` contract. */
293
+ _externalTvlAddress() {
294
+ const address = this._kasuConfig.contracts.ExternalTVL;
295
+ if (!address || /^0x0{40}$/i.test(address))
296
+ return null;
297
+ return address.toLowerCase();
298
+ }
299
+ /** Seam for tests: the real reader over the history RPCs. */
300
+ _createOffChainTvlReader(args) {
301
+ return createOffChainTvlReader(args);
302
+ }
303
+ /**
304
+ * The history RPCs, in fallback order: the explicit provider, else ONE
305
+ * provider per `historyRpcUrls` entry — built here and nowhere else,
306
+ * pinned to `SdkConfig.chainId` when known, each with a per-call timeout.
307
+ * Built once per instance.
308
+ */
309
+ _historyRpcs() {
310
+ if (this._explicitHistoryProvider)
311
+ return [this._explicitHistoryProvider];
312
+ if (!this._builtHistoryProviders) {
313
+ // Through the `ethers` namespace, so the consumer's own build
314
+ // (Node or browser) is used — see `defaultProvider` in the facade.
315
+ this._builtHistoryProviders = this._kasuConfig.historyRpcUrls.map((url) => new providers.StaticJsonRpcProvider({ url, timeout: TVL_HISTORY_RPC_TIMEOUT_MS }, this._kasuConfig.chainId));
316
+ }
317
+ return this._builtHistoryProviders;
318
+ }
114
319
  getPoolOverview(epochId, id_in) {
115
320
  return __awaiter(this, void 0, void 0, function* () {
116
321
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
@@ -251,8 +456,8 @@ export class DataService {
251
456
  subheading: lendingPoolDirectus === null || lendingPoolDirectus === void 0 ? void 0 : lendingPoolDirectus.subheading,
252
457
  operatingSince: lendingPoolDirectus === null || lendingPoolDirectus === void 0 ? void 0 : lendingPoolDirectus.operatingSince,
253
458
  totalValueLocked: {
254
- total: (parseFloat(lendingPoolSubgraph.balance) +
255
- parseFloat(offChainTvl)).toString(),
459
+ // The one TVL definition, shared with getPoolTvlHistory.
460
+ total: poolTvl(lendingPoolSubgraph.balance, offChainTvl).toString(),
256
461
  offchain: offChainTvl,
257
462
  },
258
463
  loansUnderManagement: (_q = lendingPoolDirectus === null || lendingPoolDirectus === void 0 ? void 0 : lendingPoolDirectus.loansUnderManagement) !== null && _q !== void 0 ? _q : '0',