@centrifuge/sdk 1.2.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -191,37 +191,147 @@ export class ShareClass extends Entity {
191
191
  * Get the pending and approved amounts for deposits and redemptions for each asset.
192
192
  */
193
193
  pendingAmounts() {
194
- return this._query(['pendingAmounts'], () => this._allVaults().pipe(map((vaults) => vaults.filter((v) => v.status === 'Linked')), switchMap((vaults) => {
195
- if (vaults.length === 0)
196
- return of([]);
197
- return combineLatest([
198
- combineLatest(vaults.map((v) => this._epoch(v.assetId))),
199
- this._epochOutstandingInvests(),
200
- this._epochOutstandingRedeems(),
201
- this.balances(),
202
- ]).pipe(map(([epochs, outInv, outRed, balancesData]) => {
203
- const invByKey = new Map();
204
- outInv.forEach((o) => invByKey.set(`${o.assetId.toString()}-${o.centrifugeId}`, o.amount));
205
- const redByKey = new Map();
206
- outRed.forEach((o) => redByKey.set(`${o.assetId.toString()}-${o.centrifugeId}`, o.amount));
207
- const priceByAsset = new Map();
208
- balancesData.forEach((b) => priceByAsset.set(b.assetId.toString(), b.price));
209
- return epochs.map((epoch, i) => {
210
- const vault = vaults[i];
211
- const key = `${vault.assetId.toString()}-${vault.centrifugeId}`;
212
- const queuedInvest = invByKey.get(key) ?? new Balance(0n, 18);
213
- const queuedRedeem = redByKey.get(key) ?? new Balance(0n, 18);
214
- const assetPrice = priceByAsset.get(vault.assetId.toString()) ?? Price.fromFloat(1);
215
- return {
216
- assetId: vault.assetId,
217
- centrifugeId: vault.centrifugeId,
218
- queuedInvest,
219
- queuedRedeem,
220
- assetPrice,
221
- ...epoch,
222
- };
223
- });
224
- }));
194
+ return this._query(['pendingAmounts'], () => combineLatest([
195
+ this._allVaults().pipe(map((vaults) => vaults.filter((v) => v.status === 'Linked'))),
196
+ this._investOrders(),
197
+ this._redeemOrders(),
198
+ this.balances(),
199
+ this.pool.currency(),
200
+ ]).pipe(map(([vaults, investData, redeemData, balancesData, poolCurrency]) => {
201
+ const poolDecimals = poolCurrency.decimals;
202
+ if (vaults.length === 0) {
203
+ const zeroBalance = new Balance(0n, poolDecimals);
204
+ return {
205
+ byVault: [],
206
+ shareClassTotals: {
207
+ pendingInvestments: zeroBalance,
208
+ pendingRedemptions: zeroBalance,
209
+ approvedInvestments: zeroBalance,
210
+ approvedRedemptions: zeroBalance,
211
+ },
212
+ };
213
+ }
214
+ const investmentsPending = new Map();
215
+ investData.epochOutstandingInvests.forEach((order) => {
216
+ investmentsPending.set(`${order.assetId.toString()}-${order.centrifugeId}`, order.pendingAmount);
217
+ });
218
+ const redemptionsPending = new Map();
219
+ redeemData.epochOutstandingRedeems.forEach((order) => {
220
+ redemptionsPending.set(`${order.assetId.toString()}-${order.centrifugeId}`, order.pendingAmount);
221
+ });
222
+ const investmentsApproved = new Map();
223
+ investData.epochInvestOrders.forEach((order) => {
224
+ const isApproved = !!order.approvedAt && !order.issuedAt;
225
+ const key = `${order.assetId.toString()}-${order.centrifugeId}`;
226
+ if (isApproved) {
227
+ if (!investmentsApproved.has(key))
228
+ investmentsApproved.set(key, []);
229
+ investmentsApproved.get(key).push({
230
+ amount: order.approvedAmount,
231
+ approvedAt: order.approvedAt,
232
+ epoch: order.index,
233
+ });
234
+ }
235
+ });
236
+ const redemptionsApproved = new Map();
237
+ redeemData.epochRedeemOrders.forEach((order) => {
238
+ const isApproved = !!order.approvedAt && !order.revokedAt;
239
+ const key = `${order.assetId.toString()}-${order.centrifugeId}`;
240
+ if (isApproved) {
241
+ if (!redemptionsApproved.has(key))
242
+ redemptionsApproved.set(key, []);
243
+ redemptionsApproved.get(key).push({
244
+ amount: order.approvedAmount,
245
+ approvedAt: order.approvedAt,
246
+ epoch: order.index,
247
+ });
248
+ }
249
+ });
250
+ const assetDecimals = new Map();
251
+ balancesData.forEach((b) => assetDecimals.set(b.assetId.toString(), b.asset.decimals));
252
+ const queuedInvestments = new Map();
253
+ investData.pendingInvestOrders.forEach((order) => {
254
+ const key = `${order.assetId.toString()}-${order.centrifugeId}`;
255
+ const decimals = assetDecimals.get(order.assetId.toString()) ?? 18;
256
+ const queuedAmount = new Balance(order.queuedAmount, decimals);
257
+ const existing = queuedInvestments.get(key);
258
+ if (existing) {
259
+ queuedInvestments.set(key, existing.add(queuedAmount));
260
+ }
261
+ else {
262
+ queuedInvestments.set(key, queuedAmount);
263
+ }
264
+ });
265
+ const queuedRedemptions = new Map();
266
+ redeemData.pendingRedeemOrders.forEach((order) => {
267
+ const key = `${order.assetId.toString()}-${order.centrifugeId}`;
268
+ const queuedAmount = new Balance(order.queuedAmount, 18); // Share tokens are always 18 decimals
269
+ const existing = queuedRedemptions.get(key);
270
+ if (existing) {
271
+ queuedRedemptions.set(key, existing.add(queuedAmount));
272
+ }
273
+ else {
274
+ queuedRedemptions.set(key, queuedAmount);
275
+ }
276
+ });
277
+ const priceByAsset = new Map();
278
+ balancesData.forEach((b) => priceByAsset.set(b.assetId.toString(), b.price));
279
+ let totalPendingInvestments = new Balance(0n, poolDecimals);
280
+ let totalPendingRedemptions = new Balance(0n, poolDecimals);
281
+ let totalApprovedInvestments = new Balance(0n, poolDecimals);
282
+ let totalApprovedRedemptions = new Balance(0n, poolDecimals);
283
+ const byVault = vaults.map((vault) => {
284
+ const key = `${vault.assetId.toString()}-${vault.centrifugeId}`;
285
+ const pendingDeposit = investmentsPending.get(key) ?? new Balance(0n, 18);
286
+ const pendingRedeem = redemptionsPending.get(key) ?? new Balance(0n, 18);
287
+ const pendingIssuances = investmentsApproved.get(key) ?? [];
288
+ const pendingRevocations = redemptionsApproved.get(key) ?? [];
289
+ const pendingIssuancesTotal = pendingIssuances.reduce((acc, curr) => acc.add(curr.amount), new Balance(0n, pendingIssuances[0]?.amount.decimals ?? 18));
290
+ const pendingRevocationsTotal = pendingRevocations.reduce((acc, curr) => acc.add(curr.amount), new Balance(0n, 18));
291
+ const queuedInvest = queuedInvestments.get(key) ?? new Balance(0n, 18);
292
+ const queuedRedeem = queuedRedemptions.get(key) ?? new Balance(0n, 18);
293
+ const assetPrice = priceByAsset.get(vault.assetId.toString()) ?? Price.fromFloat(1);
294
+ const pendingDepositInPoolCurrency = pendingDeposit.mul(assetPrice).scale(poolDecimals);
295
+ totalPendingInvestments = totalPendingInvestments.add(pendingDepositInPoolCurrency);
296
+ const pendingRedeemScaled = pendingRedeem.scale(poolDecimals);
297
+ totalPendingRedemptions = totalPendingRedemptions.add(pendingRedeemScaled);
298
+ const approvedInvestInPoolCurrency = pendingIssuancesTotal.mul(assetPrice).scale(poolDecimals);
299
+ totalApprovedInvestments = totalApprovedInvestments.add(approvedInvestInPoolCurrency);
300
+ const approvedRedeemScaled = pendingRevocationsTotal.scale(poolDecimals);
301
+ totalApprovedRedemptions = totalApprovedRedemptions.add(approvedRedeemScaled);
302
+ const maxInvestIndex = investData.maxEpochByAsset.get(vault.assetId.toString()) ??
303
+ (pendingIssuances.length > 0 ? Math.max(...pendingIssuances.map((p) => p.epoch)) : 0);
304
+ const minInvestIndex = pendingIssuances.length > 0 ? Math.min(...pendingIssuances.map((p) => p.epoch)) : maxInvestIndex + 1;
305
+ const maxRedeemIndex = redeemData.maxEpochByAsset.get(vault.assetId.toString()) ??
306
+ (pendingRevocations.length > 0 ? Math.max(...pendingRevocations.map((p) => p.epoch)) : 0);
307
+ const minRedeemIndex = pendingRevocations.length > 0 ? Math.min(...pendingRevocations.map((p) => p.epoch)) : maxRedeemIndex + 1;
308
+ return {
309
+ assetId: vault.assetId,
310
+ centrifugeId: vault.centrifugeId,
311
+ pendingDeposit,
312
+ pendingRedeem,
313
+ pendingIssuances,
314
+ pendingIssuancesTotal,
315
+ pendingRevocations,
316
+ pendingRevocationsTotal,
317
+ queuedInvest,
318
+ queuedRedeem,
319
+ assetPrice,
320
+ depositEpoch: maxInvestIndex + 1,
321
+ redeemEpoch: maxRedeemIndex + 1,
322
+ issueEpoch: minInvestIndex,
323
+ revokeEpoch: minRedeemIndex,
324
+ };
325
+ });
326
+ return {
327
+ byVault,
328
+ shareClassTotals: {
329
+ pendingInvestments: totalPendingInvestments,
330
+ pendingRedemptions: totalPendingRedemptions,
331
+ approvedInvestments: totalApprovedInvestments,
332
+ approvedRedemptions: totalApprovedRedemptions,
333
+ },
334
+ };
225
335
  })));
226
336
  }
227
337
  /**
@@ -477,15 +587,16 @@ export class ShareClass extends Entity {
477
587
  approveDepositsAndIssueShares(assets) {
478
588
  const self = this;
479
589
  return this._transact(async function* (ctx) {
480
- const [{ batchRequestManager }, pendingAmounts, orders] = await Promise.all([
590
+ const [{ batchRequestManager }, pendingAmountsData, orders] = await Promise.all([
481
591
  self._root._protocolAddresses(self.pool.centrifugeId),
482
592
  self.pendingAmounts(),
483
- firstValueFrom(self._investorOrders().pipe(switchMap((orders) => {
484
- if (orders.outstandingInvests.length === 0)
593
+ firstValueFrom(self._investOrders().pipe(switchMap((investOrders) => {
594
+ if (investOrders.pendingInvestOrders.length === 0)
485
595
  return of([]);
486
- return combineLatest(orders.outstandingInvests.map((order) => self._investorOrder(order.assetId, order.investor)));
596
+ return combineLatest(investOrders.pendingInvestOrders.map((order) => self._investorOrder(order.assetId, order.investor)));
487
597
  }))),
488
598
  ]);
599
+ const pendingAmounts = pendingAmountsData.byVault;
489
600
  const assetsWithApprove = assets.filter((a) => 'approveAssetAmount' in a).length;
490
601
  const assetsWithIssue = assets.filter((a) => 'issuePricePerShare' in a).length;
491
602
  const gasLimitPerAsset = assetsWithIssue ? GAS_LIMIT / BigInt(assetsWithIssue) : 0n;
@@ -622,15 +733,16 @@ export class ShareClass extends Entity {
622
733
  approveRedeemsAndRevokeShares(assets) {
623
734
  const self = this;
624
735
  return this._transact(async function* (ctx) {
625
- const [{ batchRequestManager }, pendingAmounts, orders] = await Promise.all([
736
+ const [{ batchRequestManager }, pendingAmountsData, orders] = await Promise.all([
626
737
  self._root._protocolAddresses(self.pool.centrifugeId),
627
738
  self.pendingAmounts(),
628
- firstValueFrom(self._investorOrders().pipe(switchMap((orders) => {
629
- if (orders.outstandingRedeems.length === 0)
739
+ firstValueFrom(self._redeemOrders().pipe(switchMap((redeemOrders) => {
740
+ if (redeemOrders.pendingRedeemOrders.length === 0)
630
741
  return of([]);
631
- return combineLatest(orders.outstandingRedeems.map((order) => self._investorOrder(order.assetId, order.investor)));
742
+ return combineLatest(redeemOrders.pendingRedeemOrders.map((order) => self._investorOrder(order.assetId, order.investor)));
632
743
  }))),
633
744
  ]);
745
+ const pendingAmounts = pendingAmountsData.byVault;
634
746
  const assetsWithApprove = assets.filter((a) => 'approveShareAmount' in a).length;
635
747
  const assetsWithRevoke = assets.filter((a) => 'revokePricePerShare' in a).length;
636
748
  const gasLimitPerAsset = assetsWithRevoke ? GAS_LIMIT / BigInt(assetsWithRevoke) : 0n;
@@ -896,9 +1008,10 @@ export class ShareClass extends Entity {
896
1008
  orderDirection,
897
1009
  ], () => combineLatest([
898
1010
  this.pool.currency(),
899
- this._investorOrders(),
1011
+ this._investOrders(),
1012
+ this._redeemOrders(),
900
1013
  this._tokenInstancePositions({ limit, offset, orderBy, orderDirection, filter }),
901
- ]).pipe(switchMap(([poolCurrency, { outstandingInvests, outstandingRedeems }, { items: tokenInstancePositions, assets, pageInfo, totalCount },]) => {
1014
+ ]).pipe(switchMap(([poolCurrency, { outstandingInvests }, { outstandingRedeems }, { items: tokenInstancePositions, assets, pageInfo, totalCount },]) => {
902
1015
  // Handle empty positions case or else combineLatest([]) can hang indefinitely
903
1016
  if (tokenInstancePositions.length === 0) {
904
1017
  return of({
@@ -967,7 +1080,12 @@ export class ShareClass extends Entity {
967
1080
  whitelistedHolders(options) {
968
1081
  const limit = options?.limit ?? 20;
969
1082
  const offset = options?.offset ?? 0;
970
- return this._query(['whitelistedHolders', this.id.raw, limit, offset], () => combineLatest([this.pool.currency(), this._investorOrders(), this._whitelistedInvestors({ limit, offset })]).pipe(switchMap(([poolCurrency, { outstandingInvests, outstandingRedeems }, { items: whitelistedInvestors, assets, pageInfo, totalCount },]) => {
1083
+ return this._query(['whitelistedHolders', this.id.raw, limit, offset], () => combineLatest([
1084
+ this.pool.currency(),
1085
+ this._investOrders(),
1086
+ this._redeemOrders(),
1087
+ this._whitelistedInvestors({ limit, offset }),
1088
+ ]).pipe(switchMap(([poolCurrency, { outstandingInvests }, { outstandingRedeems }, { items: whitelistedInvestors, assets, pageInfo, totalCount },]) => {
971
1089
  if (whitelistedInvestors.length === 0) {
972
1090
  return of({
973
1091
  investors: [],
@@ -1030,9 +1148,9 @@ export class ShareClass extends Entity {
1030
1148
  */
1031
1149
  investorOrders() {
1032
1150
  const self = this;
1033
- return this._query(['investorOrders'], () => self._investorOrders().pipe(switchMap((orders) => combineLatest([
1034
- ...orders.outstandingInvests.map((order) => self._investorOrder(order.assetId, order.investor)),
1035
- ...orders.outstandingRedeems.map((order) => self._investorOrder(order.assetId, order.investor)),
1151
+ return this._query(['investorOrders'], () => combineLatest([self._investOrders(), self._redeemOrders()]).pipe(switchMap(([investOrders, redeemOrders]) => combineLatest([
1152
+ ...investOrders.outstandingInvests.map((order) => self._investorOrder(order.assetId, order.investor)),
1153
+ ...redeemOrders.outstandingRedeems.map((order) => self._investorOrder(order.assetId, order.investor)),
1036
1154
  ]).pipe(map((investorOrders) => {
1037
1155
  const ordersByInvestor = new AddressMap();
1038
1156
  investorOrders.forEach((order) => {
@@ -1100,20 +1218,26 @@ export class ShareClass extends Entity {
1100
1218
  * in a given share class (per vault/chain)
1101
1219
  */
1102
1220
  investmentsByVault(centrifugeId) {
1103
- return this._query(['investmentsByVault', centrifugeId], () => combineLatest([this._investorOrders(), this.vaults(centrifugeId), this.pendingAmounts()]).pipe(switchMap(([orders, vaults, pendingAmounts]) => {
1221
+ return this._query(['investmentsByVault', centrifugeId], () => combineLatest([
1222
+ this._investOrders(),
1223
+ this._redeemOrders(),
1224
+ this.vaults(centrifugeId),
1225
+ this.pendingAmounts(),
1226
+ ]).pipe(switchMap(([investOrders, redeemOrders, vaults, pendingAmountsData]) => {
1104
1227
  if (!vaults.length)
1105
1228
  return of([]);
1229
+ const pendingAmounts = pendingAmountsData.byVault;
1106
1230
  const allInvestors = new Set();
1107
- orders.outstandingInvests.forEach((o) => allInvestors.add(o.investor));
1108
- orders.outstandingRedeems.forEach((o) => allInvestors.add(o.investor));
1231
+ investOrders.outstandingInvests.forEach((o) => allInvestors.add(o.investor));
1232
+ redeemOrders.outstandingRedeems.forEach((o) => allInvestors.add(o.investor));
1109
1233
  if (allInvestors.size === 0)
1110
1234
  return of([]);
1111
1235
  return combineLatest(vaults.map((vault) => {
1112
1236
  const vaultInvestors = new Set();
1113
- orders.outstandingInvests
1237
+ investOrders.outstandingInvests
1114
1238
  .filter((o) => o.assetId.equals(vault.assetId))
1115
1239
  .forEach((o) => vaultInvestors.add(o.investor));
1116
- orders.outstandingRedeems
1240
+ redeemOrders.outstandingRedeems
1117
1241
  .filter((o) => o.assetId.equals(vault.assetId))
1118
1242
  .forEach((o) => vaultInvestors.add(o.investor));
1119
1243
  if (vaultInvestors.size === 0)
@@ -1321,7 +1445,6 @@ export class ShareClass extends Entity {
1321
1445
  }
1322
1446
  token {
1323
1447
  decimals
1324
- }
1325
1448
  }
1326
1449
  }
1327
1450
  }
@@ -1507,6 +1630,131 @@ export class ShareClass extends Entity {
1507
1630
  return allOrders;
1508
1631
  })));
1509
1632
  }
1633
+ /**
1634
+ * Get detailed invest order information including per-user breakdowns with helper methods.
1635
+ * @returns Invest order data with helper methods for efficient lookups
1636
+ */
1637
+ investOrdersDetails() {
1638
+ return this._query(['investOrdersDetails'], () => combineLatest([this._investOrders(), this.balances()]).pipe(map(([investData, balancesData]) => {
1639
+ const assetPrices = new Map();
1640
+ const assetDecimals = new Map();
1641
+ balancesData.forEach((b) => {
1642
+ assetPrices.set(b.assetId.toString(), b.price);
1643
+ assetDecimals.set(b.assetId.toString(), b.asset.decimals);
1644
+ });
1645
+ const pendingInvestsByVault = new Map();
1646
+ const queuedInvestByAsset = new Map();
1647
+ for (const order of investData.pendingInvestOrders) {
1648
+ const assetKey = order.assetId.toString();
1649
+ const decimals = assetDecimals.get(assetKey) ?? 18;
1650
+ const parsedOrder = {
1651
+ ...order,
1652
+ pendingAmount: new Balance(order.pendingAmount, decimals),
1653
+ queuedAmount: new Balance(order.queuedAmount, decimals),
1654
+ };
1655
+ const vaultKey = `${order.assetId.toString()}-${order.centrifugeId}`;
1656
+ if (!pendingInvestsByVault.has(vaultKey)) {
1657
+ pendingInvestsByVault.set(vaultKey, []);
1658
+ }
1659
+ pendingInvestsByVault.get(vaultKey).push(parsedOrder);
1660
+ const queuedAmount = parsedOrder.queuedAmount;
1661
+ const existing = queuedInvestByAsset.get(assetKey);
1662
+ if (existing) {
1663
+ queuedInvestByAsset.set(assetKey, existing.add(queuedAmount));
1664
+ }
1665
+ else {
1666
+ queuedInvestByAsset.set(assetKey, queuedAmount);
1667
+ }
1668
+ }
1669
+ const approvedInvestsByVaultAndEpoch = new Map();
1670
+ const filteredApprovedInvests = investData.investOrders.filter((i) => !!i.approvedAt && !i.issuedAt);
1671
+ for (const order of filteredApprovedInvests) {
1672
+ const key = `${order.assetId.toString()}-${order.centrifugeId}-${order.index}`;
1673
+ if (!approvedInvestsByVaultAndEpoch.has(key)) {
1674
+ approvedInvestsByVaultAndEpoch.set(key, []);
1675
+ }
1676
+ approvedInvestsByVaultAndEpoch.get(key).push(order);
1677
+ }
1678
+ const toAssetKey = (assetId) => typeof assetId === 'string' ? assetId : assetId.toString();
1679
+ return {
1680
+ getPendingInvestsByVault: (assetId, centrifugeId) => {
1681
+ const key = `${toAssetKey(assetId)}-${centrifugeId}`;
1682
+ return pendingInvestsByVault.get(key) ?? [];
1683
+ },
1684
+ getApprovedInvestsByVaultAndEpoch: (assetId, centrifugeId, epoch) => {
1685
+ const key = `${toAssetKey(assetId)}-${centrifugeId}-${epoch}`;
1686
+ return approvedInvestsByVaultAndEpoch.get(key) ?? [];
1687
+ },
1688
+ getQueuedInvestByAsset: (assetId) => {
1689
+ return queuedInvestByAsset.get(toAssetKey(assetId));
1690
+ },
1691
+ getAssetPrice: (assetId) => {
1692
+ return assetPrices.get(toAssetKey(assetId));
1693
+ },
1694
+ };
1695
+ })));
1696
+ }
1697
+ /**
1698
+ * Get detailed redeem order information including per-user breakdowns with helper methods.
1699
+ * @returns Redeem order data with helper methods for efficient lookups
1700
+ */
1701
+ redeemOrdersDetails() {
1702
+ return this._query(['redeemOrdersDetails'], () => combineLatest([this._redeemOrders(), this.balances()]).pipe(map(([redeemData, balancesData]) => {
1703
+ const assetPrices = new Map();
1704
+ balancesData.forEach((b) => {
1705
+ assetPrices.set(b.assetId.toString(), b.price);
1706
+ });
1707
+ const pendingRedeemsByVault = new Map();
1708
+ const queuedRedeemByAsset = new Map();
1709
+ for (const order of redeemData.pendingRedeemOrders) {
1710
+ const parsedOrder = {
1711
+ ...order,
1712
+ pendingAmount: new Balance(order.pendingAmount, 18),
1713
+ queuedAmount: new Balance(order.queuedAmount, 18),
1714
+ };
1715
+ const vaultKey = `${order.assetId.toString()}-${order.centrifugeId}`;
1716
+ if (!pendingRedeemsByVault.has(vaultKey)) {
1717
+ pendingRedeemsByVault.set(vaultKey, []);
1718
+ }
1719
+ pendingRedeemsByVault.get(vaultKey).push(parsedOrder);
1720
+ const assetKey = order.assetId.toString();
1721
+ const queuedAmount = parsedOrder.queuedAmount;
1722
+ const existing = queuedRedeemByAsset.get(assetKey);
1723
+ if (existing) {
1724
+ queuedRedeemByAsset.set(assetKey, existing.add(queuedAmount));
1725
+ }
1726
+ else {
1727
+ queuedRedeemByAsset.set(assetKey, queuedAmount);
1728
+ }
1729
+ }
1730
+ const approvedRedeemsByVaultAndEpoch = new Map();
1731
+ const filteredApprovedRedeems = redeemData.redeemOrders.filter((i) => !!i.approvedAt && !i.revokedAt);
1732
+ for (const order of filteredApprovedRedeems) {
1733
+ const key = `${order.assetId.toString()}-${order.centrifugeId}-${order.index}`;
1734
+ if (!approvedRedeemsByVaultAndEpoch.has(key)) {
1735
+ approvedRedeemsByVaultAndEpoch.set(key, []);
1736
+ }
1737
+ approvedRedeemsByVaultAndEpoch.get(key).push(order);
1738
+ }
1739
+ const toAssetKey = (assetId) => typeof assetId === 'string' ? assetId : assetId.toString();
1740
+ return {
1741
+ getPendingRedeemsByVault: (assetId, centrifugeId) => {
1742
+ const key = `${toAssetKey(assetId)}-${centrifugeId}`;
1743
+ return pendingRedeemsByVault.get(key) ?? [];
1744
+ },
1745
+ getApprovedRedeemsByVaultAndEpoch: (assetId, centrifugeId, epoch) => {
1746
+ const key = `${toAssetKey(assetId)}-${centrifugeId}-${epoch}`;
1747
+ return approvedRedeemsByVaultAndEpoch.get(key) ?? [];
1748
+ },
1749
+ getQueuedRedeemByAsset: (assetId) => {
1750
+ return queuedRedeemByAsset.get(toAssetKey(assetId));
1751
+ },
1752
+ getAssetPrice: (assetId) => {
1753
+ return assetPrices.get(toAssetKey(assetId));
1754
+ },
1755
+ };
1756
+ })));
1757
+ }
1510
1758
  /**
1511
1759
  * Get the valuation contract address for this share class on a specific chain.
1512
1760
  * @param centrifugeId
@@ -1751,43 +1999,263 @@ export class ShareClass extends Entity {
1751
1999
  }, centrifugeId)))));
1752
2000
  }
1753
2001
  /** @internal */
1754
- _investorOrders() {
1755
- return this._root._queryIndexer(`query ($scId: String!) {
1756
- pendingInvestOrders(where: {tokenId: $scId}) {
1757
- items {
1758
- account
1759
- assetId
1760
- tokenId
1761
- pendingAssetsAmount
1762
- queuedAssetsAmount
2002
+ _investOrders() {
2003
+ return this._query(['investOrders'], () => this._root._queryIndexer(`query ($scId: String!) {
2004
+ epochOutstandingInvests(where: { tokenId: $scId }, limit: 1000) {
2005
+ items {
2006
+ assetId
2007
+ poolId
2008
+ tokenId
2009
+ pendingAssetsAmount
2010
+ asset { decimals centrifugeId }
2011
+ }
1763
2012
  }
1764
- }
1765
- pendingRedeemOrders(where: {tokenId: $scId}) {
1766
- items {
1767
- account
1768
- assetId
1769
- tokenId
1770
- pendingSharesAmount
1771
- queuedSharesAmount
2013
+ epochInvestOrders(where: { tokenId: $scId }, limit: 1000) {
2014
+ items {
2015
+ poolId
2016
+ tokenId
2017
+ assetId
2018
+ index
2019
+ approvedAt
2020
+ approvedAssetsAmount
2021
+ issuedAt
2022
+ issuedSharesAmount
2023
+ token { decimals }
2024
+ asset { decimals centrifugeId }
2025
+ }
1772
2026
  }
1773
- }
1774
- }`, { scId: this.id.raw }, (data) => ({
1775
- outstandingInvests: data.pendingInvestOrders.items.map((item) => ({
1776
- assetId: new AssetId(item.assetId),
1777
- account: item.account.toLowerCase(),
1778
- investor: item.account.toLowerCase(),
1779
- tokenId: item.tokenId.toLowerCase(),
1780
- pendingAmount: item.pendingAssetsAmount,
1781
- queuedAmount: item.queuedAssetsAmount,
1782
- })),
1783
- outstandingRedeems: data.pendingRedeemOrders.items.map((item) => ({
1784
- assetId: new AssetId(item.assetId),
1785
- account: item.account.toLowerCase(),
1786
- investor: item.account.toLowerCase(),
1787
- tokenId: item.tokenId.toLowerCase(),
1788
- pendingAmount: item.pendingSharesAmount,
1789
- queuedAmount: item.queuedSharesAmount,
1790
- })),
2027
+ pendingInvestOrders(where: { tokenId: $scId }, limit: 1000) {
2028
+ items {
2029
+ account
2030
+ assetId
2031
+ tokenId
2032
+ queuedAssetsAmount
2033
+ pendingAssetsAmount
2034
+ }
2035
+ }
2036
+ investOrders(where: { tokenId: $scId, issuedAt: null }, limit: 1000) {
2037
+ items {
2038
+ account
2039
+ assetId
2040
+ tokenId
2041
+ index
2042
+ approvedAt
2043
+ approvedAssetsAmount
2044
+ issuedAt
2045
+ issuedSharesAmount
2046
+ claimedAt
2047
+ claimedSharesAmount
2048
+ asset { decimals centrifugeId }
2049
+ }
2050
+ }
2051
+ outstandingInvests(where: { tokenId: $scId }, limit: 1000) {
2052
+ items {
2053
+ account
2054
+ assetId
2055
+ tokenId
2056
+ approvedAmount
2057
+ approvedAt
2058
+ depositAmount
2059
+ epochIndex
2060
+ pendingAmount
2061
+ queuedAmount
2062
+ }
2063
+ }
2064
+ }`, { scId: this.id.raw }, (data) => {
2065
+ const maxEpochByAsset = new Map();
2066
+ for (const item of data.epochInvestOrders.items) {
2067
+ const current = maxEpochByAsset.get(item.assetId) ?? -1;
2068
+ if (item.index > current) {
2069
+ maxEpochByAsset.set(item.assetId, item.index);
2070
+ }
2071
+ }
2072
+ return {
2073
+ maxEpochByAsset,
2074
+ epochOutstandingInvests: data.epochOutstandingInvests.items.map((item) => ({
2075
+ assetId: new AssetId(item.assetId),
2076
+ centrifugeId: Number(item.asset.centrifugeId),
2077
+ pendingAmount: new Balance(item.pendingAssetsAmount || '0', item.asset.decimals),
2078
+ })),
2079
+ epochInvestOrders: data.epochInvestOrders.items.map((item) => ({
2080
+ assetId: new AssetId(item.assetId),
2081
+ centrifugeId: Number(item.asset.centrifugeId),
2082
+ index: item.index,
2083
+ approvedAt: item.approvedAt ? new Date(item.approvedAt) : null,
2084
+ approvedAmount: new Balance(item.approvedAssetsAmount || '0', item.asset.decimals),
2085
+ issuedAt: item.issuedAt,
2086
+ tokenDecimals: item.token.decimals,
2087
+ assetDecimals: item.asset.decimals,
2088
+ })),
2089
+ pendingInvestOrders: data.pendingInvestOrders.items.map((item) => {
2090
+ const assetId = new AssetId(item.assetId);
2091
+ return {
2092
+ assetId,
2093
+ centrifugeId: assetId.centrifugeId,
2094
+ account: item.account.toLowerCase(),
2095
+ investor: item.account.toLowerCase(),
2096
+ pendingAmount: item.pendingAssetsAmount || '0',
2097
+ queuedAmount: item.queuedAssetsAmount || '0',
2098
+ };
2099
+ }),
2100
+ investOrders: data.investOrders.items.map((item) => {
2101
+ const assetId = new AssetId(item.assetId);
2102
+ return {
2103
+ assetId,
2104
+ centrifugeId: assetId.centrifugeId,
2105
+ account: item.account.toLowerCase(),
2106
+ investor: item.account.toLowerCase(),
2107
+ index: item.index,
2108
+ approvedAt: item.approvedAt ? new Date(item.approvedAt) : null,
2109
+ approvedAmount: new Balance(item.approvedAssetsAmount || '0', item.asset.decimals),
2110
+ issuedAt: item.issuedAt ? new Date(item.issuedAt) : null,
2111
+ };
2112
+ }),
2113
+ outstandingInvests: data.outstandingInvests.items.map((item) => ({
2114
+ assetId: new AssetId(item.assetId),
2115
+ account: item.account.toLowerCase(),
2116
+ investor: item.account.toLowerCase(),
2117
+ tokenId: item.tokenId.toLowerCase(),
2118
+ approvedAmount: item.approvedAmount,
2119
+ depositAmount: item.depositAmount,
2120
+ pendingAmount: item.pendingAmount,
2121
+ queuedAmount: item.queuedAmount,
2122
+ })),
2123
+ };
2124
+ }));
2125
+ }
2126
+ /** @internal */
2127
+ _redeemOrders() {
2128
+ return this._query(['redeemOrders'], () => this._root._queryIndexer(`query ($scId: String!) {
2129
+ epochOutstandingRedeems(where: { tokenId: $scId }, limit: 1000) {
2130
+ items {
2131
+ assetId
2132
+ poolId
2133
+ tokenId
2134
+ pendingSharesAmount
2135
+ asset { decimals centrifugeId }
2136
+ }
2137
+ }
2138
+ epochRedeemOrders(where: { tokenId: $scId }, limit: 1000) {
2139
+ items {
2140
+ poolId
2141
+ tokenId
2142
+ assetId
2143
+ index
2144
+ approvedAt
2145
+ approvedSharesAmount
2146
+ revokedAt
2147
+ revokedSharesAmount
2148
+ revokedAssetsAmount
2149
+ token { decimals }
2150
+ asset { decimals centrifugeId }
2151
+ }
2152
+ }
2153
+ pendingRedeemOrders(where: { tokenId: $scId }, limit: 1000) {
2154
+ items {
2155
+ account
2156
+ assetId
2157
+ tokenId
2158
+ queuedSharesAmount
2159
+ pendingSharesAmount
2160
+ }
2161
+ }
2162
+ redeemOrders(where: { tokenId: $scId, revokedAt: null }, limit: 1000) {
2163
+ items {
2164
+ account
2165
+ assetId
2166
+ tokenId
2167
+ index
2168
+ approvedAt
2169
+ approvedSharesAmount
2170
+ revokedAt
2171
+ revokedSharesAmount
2172
+ revokedAssetsAmount
2173
+ claimedAt
2174
+ claimedAssetsAmount
2175
+ asset { decimals centrifugeId }
2176
+ token { decimals }
2177
+ }
2178
+ }
2179
+ outstandingRedeems(where: {tokenId: $scId}, limit: 1000) {
2180
+ items {
2181
+ account
2182
+ assetId
2183
+ tokenId
2184
+ epochIndex
2185
+ approvedAmount
2186
+ approvedAt
2187
+ depositAmount
2188
+ pendingAmount
2189
+ queuedAmount
2190
+ }
2191
+ }
2192
+ }`, { scId: this.id.raw }, (data) => {
2193
+ const maxEpochByAsset = new Map();
2194
+ for (const item of data.epochRedeemOrders.items) {
2195
+ const current = maxEpochByAsset.get(item.assetId) ?? -1;
2196
+ if (item.index > current) {
2197
+ maxEpochByAsset.set(item.assetId, item.index);
2198
+ }
2199
+ }
2200
+ return {
2201
+ maxEpochByAsset,
2202
+ epochOutstandingRedeems: data.epochOutstandingRedeems.items.map((item) => {
2203
+ const assetId = new AssetId(item.assetId);
2204
+ return {
2205
+ assetId,
2206
+ centrifugeId: assetId.centrifugeId,
2207
+ pendingAmount: new Balance(item.pendingSharesAmount || '0', 18),
2208
+ };
2209
+ }),
2210
+ epochRedeemOrders: data.epochRedeemOrders.items.map((item) => {
2211
+ const assetId = new AssetId(item.assetId);
2212
+ return {
2213
+ assetId,
2214
+ centrifugeId: assetId.centrifugeId,
2215
+ index: item.index,
2216
+ approvedAt: item.approvedAt ? new Date(item.approvedAt) : null,
2217
+ revokedAt: item.revokedAt ? new Date(item.revokedAt) : null,
2218
+ approvedAmount: new Balance(item.approvedSharesAmount || '0', 18),
2219
+ tokenDecimals: item.token.decimals,
2220
+ assetDecimals: item.asset.decimals,
2221
+ };
2222
+ }),
2223
+ pendingRedeemOrders: data.pendingRedeemOrders.items.map((item) => {
2224
+ const assetId = new AssetId(item.assetId);
2225
+ return {
2226
+ assetId,
2227
+ centrifugeId: assetId.centrifugeId,
2228
+ account: item.account.toLowerCase(),
2229
+ investor: item.account.toLowerCase(),
2230
+ pendingAmount: item.pendingSharesAmount || '0',
2231
+ queuedAmount: item.queuedSharesAmount || '0',
2232
+ };
2233
+ }),
2234
+ redeemOrders: data.redeemOrders.items.map((item) => {
2235
+ const assetId = new AssetId(item.assetId);
2236
+ return {
2237
+ assetId,
2238
+ centrifugeId: assetId.centrifugeId,
2239
+ account: item.account.toLowerCase(),
2240
+ investor: item.account.toLowerCase(),
2241
+ index: item.index,
2242
+ approvedAt: item.approvedAt ? new Date(item.approvedAt) : null,
2243
+ approvedAmount: new Balance(item.approvedSharesAmount || '0', 18),
2244
+ revokedAt: item.revokedAt ? new Date(item.revokedAt) : null,
2245
+ };
2246
+ }),
2247
+ outstandingRedeems: data.outstandingRedeems.items.map((item) => ({
2248
+ assetId: new AssetId(item.assetId),
2249
+ account: item.account.toLowerCase(),
2250
+ investor: item.account.toLowerCase(),
2251
+ tokenId: item.tokenId.toLowerCase(),
2252
+ approvedAt: item.approvedAt ? new Date(item.approvedAt) : null,
2253
+ approvedAmount: item.approvedAmount,
2254
+ depositAmount: item.depositAmount,
2255
+ pendingAmount: item.pendingAmount,
2256
+ queuedAmount: item.queuedAmount,
2257
+ })),
2258
+ };
1791
2259
  }));
1792
2260
  }
1793
2261
  /** @internal */
@@ -1928,127 +2396,6 @@ export class ShareClass extends Entity {
1928
2396
  }, this.pool.centrifugeId)))));
1929
2397
  }
1930
2398
  /** @internal */
1931
- _epochInvestOrders() {
1932
- return this._query(['epochInvestOrders'], () => this._root._queryIndexer(`query ($scId: String!) {
1933
- epochInvestOrders(where: {tokenId: $scId, issuedAt: null, approvedAt_not: null}, limit: 1000) {
1934
- items {
1935
- approvedAt
1936
- assetId
1937
- index
1938
- }
1939
- }
1940
- }`, { scId: this.id.raw }, (data) => {
1941
- const ordersMap = new Map();
1942
- data.epochInvestOrders.items.forEach((item) => {
1943
- const key = item.assetId.toString();
1944
- if (!ordersMap.has(key)) {
1945
- ordersMap.set(key, []);
1946
- }
1947
- ordersMap.get(key)[item.index] = {
1948
- approvedAt: item.approvedAt,
1949
- assetId: item.assetId,
1950
- index: item.index,
1951
- };
1952
- });
1953
- return ordersMap;
1954
- }));
1955
- }
1956
- /** @internal */
1957
- _epochRedeemOrders() {
1958
- return this._query(['epochRedeemOrders'], () => this._root._queryIndexer(`query ($scId: String!) {
1959
- epochRedeemOrders(where: {tokenId: $scId, revokedAt: null, approvedAt_not: null}, limit: 1000) {
1960
- items {
1961
- approvedAt
1962
- assetId
1963
- index
1964
- }
1965
- }
1966
- }`, { scId: this.id.raw }, (data) => {
1967
- const ordersMap = new Map();
1968
- data.epochRedeemOrders.items.forEach((item) => {
1969
- const key = item.assetId.toString();
1970
- if (!ordersMap.has(key)) {
1971
- ordersMap.set(key, []);
1972
- }
1973
- ordersMap.get(key)[item.index] = {
1974
- approvedAt: item.approvedAt,
1975
- assetId: item.assetId,
1976
- index: item.index,
1977
- };
1978
- });
1979
- return ordersMap;
1980
- }));
1981
- }
1982
- /** @internal */
1983
- _epoch(assetId) {
1984
- return this._query(['epoch', assetId.toString()], () => combineLatest([
1985
- this._root._protocolAddresses(this.pool.centrifugeId),
1986
- this.pool.currency(),
1987
- this._root._assetDecimals(assetId, this.pool.centrifugeId),
1988
- this._epochInvestOrders(),
1989
- this._epochRedeemOrders(),
1990
- this._root.getClient(this.pool.centrifugeId),
1991
- ]).pipe(switchMap(([{ batchRequestManager }, poolCurrency, assetDecimals, epochInvestOrders, epochRedeemOrders, client]) => defer(async () => {
1992
- const scm = getContract({
1993
- address: batchRequestManager,
1994
- abi: ABI.BatchRequestManager,
1995
- client,
1996
- });
1997
- const [epoch, pendingDeposit, pendingRedeem] = await Promise.all([
1998
- scm.read.epochId([this.pool.id.raw, this.id.raw, assetId.raw]),
1999
- scm.read.pendingDeposit([this.pool.id.raw, this.id.raw, assetId.raw]),
2000
- scm.read.pendingRedeem([this.pool.id.raw, this.id.raw, assetId.raw]),
2001
- ]);
2002
- const depositEpoch = epoch[0] + 1;
2003
- const redeemEpoch = epoch[1] + 1;
2004
- const issueEpoch = epoch[2] + 1;
2005
- const revokeEpoch = epoch[3] + 1;
2006
- const [depositEpochAmounts, redeemEpochAmount] = await Promise.all([
2007
- Promise.all(Array.from({ length: depositEpoch - issueEpoch }).map((_, i) => scm.read.epochInvestAmounts([this.pool.id.raw, this.id.raw, assetId.raw, issueEpoch + i]))),
2008
- Promise.all(Array.from({ length: redeemEpoch - revokeEpoch }).map((_, i) => scm.read.epochRedeemAmounts([this.pool.id.raw, this.id.raw, assetId.raw, revokeEpoch + i]))),
2009
- ]);
2010
- const approvedDeposit = depositEpochAmounts.reduce((acc, amount) => acc + amount[1], 0n);
2011
- const approvedRedeem = redeemEpochAmount.reduce((acc, amount) => acc + amount[1], 0n);
2012
- return {
2013
- depositEpoch,
2014
- redeemEpoch,
2015
- issueEpoch,
2016
- revokeEpoch,
2017
- pendingDeposit: new Balance(pendingDeposit, assetDecimals),
2018
- pendingRedeem: new Balance(pendingRedeem, poolCurrency.decimals),
2019
- pendingIssuancesTotal: new Balance(approvedDeposit, assetDecimals),
2020
- pendingIssuances: depositEpochAmounts.map(([, amount], i) => ({
2021
- amount: new Balance(amount, assetDecimals),
2022
- approvedAt: epochInvestOrders.get(assetId.toString())?.[issueEpoch + i]?.approvedAt,
2023
- epoch: issueEpoch + i,
2024
- })),
2025
- pendingRevocationsTotal: new Balance(approvedRedeem, poolCurrency.decimals),
2026
- pendingRevocations: redeemEpochAmount.map(([, amount], i) => ({
2027
- amount: new Balance(amount, poolCurrency.decimals),
2028
- approvedAt: epochRedeemOrders.get(assetId.toString())?.[revokeEpoch + i]?.approvedAt,
2029
- epoch: revokeEpoch + i,
2030
- })),
2031
- };
2032
- }).pipe(repeatOnEvents(this._root, {
2033
- address: batchRequestManager,
2034
- eventName: [
2035
- 'ApproveDeposits',
2036
- 'ApproveRedeems',
2037
- 'IssueShares',
2038
- 'RevokeShares',
2039
- 'RemoteIssueShares',
2040
- 'RemoteRevokeShares',
2041
- 'UpdateDepositRequest',
2042
- 'UpdateRedeemRequest',
2043
- ],
2044
- filter: (events) => {
2045
- return events.some((event) => {
2046
- return event.args.scId === this.id.raw;
2047
- });
2048
- },
2049
- }, this.pool.centrifugeId)))));
2050
- }
2051
- /** @internal */
2052
2399
  _updateContract(centrifugeId, target, payload) {
2053
2400
  const self = this;
2054
2401
  return this._transact(async function* (ctx) {
@@ -2073,42 +2420,6 @@ export class ShareClass extends Entity {
2073
2420
  }, this.pool.centrifugeId);
2074
2421
  }
2075
2422
  /** @internal */
2076
- _epochOutstandingInvests() {
2077
- return this._query(['epochOutstandingInvests'], () => this._root._queryIndexer(`query ($scId: String!) {
2078
- epochOutstandingInvests(where: { tokenId: $scId }, limit: 1000) {
2079
- items {
2080
- assetId
2081
- pendingAssetsAmount
2082
- asset { decimals centrifugeId }
2083
- }
2084
- }
2085
- }`, { scId: this.id.raw }, (data) => {
2086
- return data.epochOutstandingInvests.items.map((item) => ({
2087
- assetId: new AssetId(item.assetId),
2088
- centrifugeId: item.asset.centrifugeId,
2089
- amount: new Balance(item.pendingAssetsAmount || 0, item.asset.decimals),
2090
- }));
2091
- }));
2092
- }
2093
- /** @internal */
2094
- _epochOutstandingRedeems() {
2095
- return this._query(['epochOutstandingRedeems'], () => this._root._queryIndexer(`query ($scId: String!) {
2096
- epochOutstandingRedeems(where: { tokenId: $scId }, limit: 1000) {
2097
- items {
2098
- assetId
2099
- pendingSharesAmount
2100
- asset { decimals centrifugeId }
2101
- }
2102
- }
2103
- }`, { scId: this.id.raw }, (data) => {
2104
- return data.epochOutstandingRedeems.items.map((item) => ({
2105
- assetId: new AssetId(item.assetId),
2106
- centrifugeId: item.asset.centrifugeId,
2107
- amount: new Balance(item.pendingSharesAmount || 0, 18),
2108
- }));
2109
- }));
2110
- }
2111
- /** @internal */
2112
2423
  _share(centrifugeId) {
2113
2424
  return this._query(['share', centrifugeId], () => this.pool.network(centrifugeId).pipe(switchMap((network) => network._share(this.id))));
2114
2425
  }