@mantle-rwa/sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/dist/cjs/client.js +198 -0
  2. package/dist/cjs/client.js.map +1 -0
  3. package/dist/cjs/constants/index.js +211 -0
  4. package/dist/cjs/constants/index.js.map +1 -0
  5. package/dist/cjs/errors/index.js +218 -0
  6. package/dist/cjs/errors/index.js.map +1 -0
  7. package/dist/cjs/index.js +51 -0
  8. package/dist/cjs/index.js.map +1 -0
  9. package/dist/cjs/modules/compliance.js +202 -0
  10. package/dist/cjs/modules/compliance.js.map +1 -0
  11. package/dist/cjs/modules/index.js +18 -0
  12. package/dist/cjs/modules/index.js.map +1 -0
  13. package/dist/cjs/modules/kyc.js +278 -0
  14. package/dist/cjs/modules/kyc.js.map +1 -0
  15. package/dist/cjs/modules/token.js +365 -0
  16. package/dist/cjs/modules/token.js.map +1 -0
  17. package/dist/cjs/modules/yield.js +406 -0
  18. package/dist/cjs/modules/yield.js.map +1 -0
  19. package/dist/cjs/package.json +3 -0
  20. package/dist/cjs/types/index.js +20 -0
  21. package/dist/cjs/types/index.js.map +1 -0
  22. package/dist/cjs/utils/index.js +206 -0
  23. package/dist/cjs/utils/index.js.map +1 -0
  24. package/dist/esm/client.js +194 -0
  25. package/dist/esm/client.js.map +1 -0
  26. package/dist/esm/constants/index.js +208 -0
  27. package/dist/esm/constants/index.js.map +1 -0
  28. package/dist/esm/errors/index.js +209 -0
  29. package/dist/esm/errors/index.js.map +1 -0
  30. package/dist/esm/index.js +17 -0
  31. package/dist/esm/index.js.map +1 -0
  32. package/dist/esm/modules/compliance.js +198 -0
  33. package/dist/esm/modules/compliance.js.map +1 -0
  34. package/dist/esm/modules/index.js +8 -0
  35. package/dist/esm/modules/index.js.map +1 -0
  36. package/dist/esm/modules/kyc.js +273 -0
  37. package/dist/esm/modules/kyc.js.map +1 -0
  38. package/dist/esm/modules/token.js +360 -0
  39. package/dist/esm/modules/token.js.map +1 -0
  40. package/dist/esm/modules/yield.js +401 -0
  41. package/dist/esm/modules/yield.js.map +1 -0
  42. package/dist/esm/types/index.js +17 -0
  43. package/dist/esm/types/index.js.map +1 -0
  44. package/dist/esm/utils/index.js +188 -0
  45. package/dist/esm/utils/index.js.map +1 -0
  46. package/dist/types/client.d.ts +93 -0
  47. package/dist/types/client.d.ts.map +1 -0
  48. package/dist/types/constants/index.d.ts +83 -0
  49. package/dist/types/constants/index.d.ts.map +1 -0
  50. package/dist/types/errors/index.d.ts +83 -0
  51. package/dist/types/errors/index.d.ts.map +1 -0
  52. package/dist/types/index.d.ts +13 -0
  53. package/dist/types/index.d.ts.map +1 -0
  54. package/dist/types/modules/compliance.d.ts +29 -0
  55. package/dist/types/modules/compliance.d.ts.map +1 -0
  56. package/dist/types/modules/index.d.ts +8 -0
  57. package/dist/types/modules/index.d.ts.map +1 -0
  58. package/dist/types/modules/kyc.d.ts +131 -0
  59. package/dist/types/modules/kyc.d.ts.map +1 -0
  60. package/dist/types/modules/token.d.ts +145 -0
  61. package/dist/types/modules/token.d.ts.map +1 -0
  62. package/dist/types/modules/yield.d.ts +143 -0
  63. package/dist/types/modules/yield.d.ts.map +1 -0
  64. package/dist/types/types/index.d.ts +254 -0
  65. package/dist/types/types/index.d.ts.map +1 -0
  66. package/dist/types/utils/index.d.ts +80 -0
  67. package/dist/types/utils/index.d.ts.map +1 -0
  68. package/package.json +52 -0
  69. package/src/client.ts +258 -0
  70. package/src/constants/index.ts +226 -0
  71. package/src/errors/index.ts +291 -0
  72. package/src/index.ts +42 -0
  73. package/src/modules/compliance.ts +252 -0
  74. package/src/modules/index.ts +8 -0
  75. package/src/modules/kyc.ts +446 -0
  76. package/src/modules/token.ts +488 -0
  77. package/src/modules/yield.ts +566 -0
  78. package/src/types/index.ts +326 -0
  79. package/src/utils/index.ts +240 -0
@@ -0,0 +1,566 @@
1
+ /**
2
+ * YieldModule - Handles yield distribution management
3
+ */
4
+
5
+ import { ethers, type Provider, type Signer } from 'ethers';
6
+ import type {
7
+ Distribution,
8
+ DistributionConfig,
9
+ DistributionPreview,
10
+ HolderDistribution,
11
+ PendingClaim,
12
+ TransactionResult,
13
+ TransactionOptions,
14
+ } from '../types';
15
+ import { YIELD_DISTRIBUTOR_ABI, RWA_TOKEN_ABI, DEFAULTS } from '../constants';
16
+ import { RWAError, ErrorCode, parseContractError } from '../errors';
17
+ import {
18
+ isValidAddress,
19
+ normalizeAddress,
20
+ parseAmount,
21
+ parseEvents,
22
+ createTransactionResult,
23
+ retry,
24
+ estimateGasWithBuffer,
25
+ timestampToDate,
26
+ } from '../utils';
27
+
28
+ /**
29
+ * Instance of a connected yield distributor
30
+ */
31
+ export class YieldDistributorInstance {
32
+ private readonly _contract: ethers.Contract;
33
+ private readonly _retries: number;
34
+ private readonly _retryDelay: number;
35
+
36
+ /** Distributor contract address */
37
+ readonly address: string;
38
+
39
+ constructor(
40
+ address: string,
41
+ provider: Provider,
42
+ signer: Signer | null,
43
+ retries: number,
44
+ retryDelay: number
45
+ ) {
46
+ this.address = normalizeAddress(address);
47
+ this._retries = retries;
48
+ this._retryDelay = retryDelay;
49
+
50
+ this._contract = new ethers.Contract(
51
+ this.address,
52
+ YIELD_DISTRIBUTOR_ABI,
53
+ signer || provider
54
+ );
55
+ }
56
+
57
+ /*//////////////////////////////////////////////////////////////
58
+ READ FUNCTIONS
59
+ //////////////////////////////////////////////////////////////*/
60
+
61
+ /**
62
+ * Get the number of distributions
63
+ */
64
+ async distributionCount(): Promise<number> {
65
+ const count = await this._contract.distributionCount();
66
+ return Number(count);
67
+ }
68
+
69
+ /**
70
+ * Get distribution information
71
+ */
72
+ async getDistributionInfo(distributionId: number): Promise<Distribution> {
73
+ const [paymentToken, totalAmount, snapshotId, claimDeadline, claimedAmount] =
74
+ await this._contract.getDistributionInfo(distributionId);
75
+
76
+ return {
77
+ id: distributionId,
78
+ paymentToken,
79
+ totalAmount,
80
+ snapshotId,
81
+ claimDeadline: timestampToDate(claimDeadline),
82
+ claimedAmount,
83
+ };
84
+ }
85
+
86
+ /**
87
+ * Get claimable amount for an account
88
+ */
89
+ async getClaimableAmount(distributionId: number, account: string): Promise<bigint> {
90
+ return this._contract.getClaimableAmount(distributionId, normalizeAddress(account));
91
+ }
92
+
93
+ /**
94
+ * Check if an account has claimed from a distribution
95
+ */
96
+ async hasClaimed(distributionId: number, account: string): Promise<boolean> {
97
+ return this._contract.hasClaimed(distributionId, normalizeAddress(account));
98
+ }
99
+
100
+ /**
101
+ * Get all distributions
102
+ */
103
+ async getDistributionHistory(): Promise<Distribution[]> {
104
+ const count = await this.distributionCount();
105
+ const distributions: Distribution[] = [];
106
+
107
+ for (let i = 0; i < count; i++) {
108
+ distributions.push(await this.getDistributionInfo(i));
109
+ }
110
+
111
+ return distributions;
112
+ }
113
+
114
+ /**
115
+ * Get pending claims for an account
116
+ */
117
+ async getPendingClaims(account: string): Promise<PendingClaim[]> {
118
+ const count = await this.distributionCount();
119
+ const pendingClaims: PendingClaim[] = [];
120
+ const now = new Date();
121
+
122
+ for (let i = 0; i < count; i++) {
123
+ const hasClaimed = await this.hasClaimed(i, account);
124
+ if (hasClaimed) continue;
125
+
126
+ const distribution = await this.getDistributionInfo(i);
127
+ if (distribution.claimDeadline < now) continue;
128
+
129
+ const amount = await this.getClaimableAmount(i, account);
130
+ if (amount === 0n) continue;
131
+
132
+ pendingClaims.push({
133
+ distributionId: i,
134
+ amount,
135
+ paymentToken: distribution.paymentToken,
136
+ deadline: distribution.claimDeadline,
137
+ });
138
+ }
139
+
140
+ return pendingClaims;
141
+ }
142
+
143
+ /*//////////////////////////////////////////////////////////////
144
+ WRITE FUNCTIONS
145
+ //////////////////////////////////////////////////////////////*/
146
+
147
+ /**
148
+ * Create a new distribution
149
+ */
150
+ async createDistribution(
151
+ paymentToken: string,
152
+ totalAmount: string,
153
+ claimWindowDays: number = DEFAULTS.YIELD_CLAIM_WINDOW_DAYS,
154
+ options?: TransactionOptions
155
+ ): Promise<{ result: TransactionResult; distributionId: number }> {
156
+ const tokenAddress = normalizeAddress(paymentToken);
157
+ const amountWei = parseAmount(totalAmount);
158
+
159
+ try {
160
+ const tx = await retry(
161
+ async () => {
162
+ const gasLimit = options?.gasLimit || await estimateGasWithBuffer(
163
+ () => this._contract.createDistribution.estimateGas(
164
+ tokenAddress,
165
+ amountWei,
166
+ claimWindowDays
167
+ )
168
+ );
169
+ return this._contract.createDistribution(
170
+ tokenAddress,
171
+ amountWei,
172
+ claimWindowDays,
173
+ { gasLimit }
174
+ );
175
+ },
176
+ { retries: options?.retries ?? this._retries, delay: options?.retryDelay ?? this._retryDelay }
177
+ );
178
+
179
+ const receipt = await tx.wait();
180
+ const events = parseEvents(receipt, this._contract.interface);
181
+ const result = createTransactionResult(receipt, events);
182
+
183
+ // Extract distribution ID from event
184
+ const createdEvent = events.find((e) => e.name === 'DistributionCreated');
185
+ const distributionId = Number(createdEvent?.args.distributionId || 0);
186
+
187
+ return { result, distributionId };
188
+ } catch (error) {
189
+ throw parseContractError(error, this.address, 'createDistribution');
190
+ }
191
+ }
192
+
193
+ /**
194
+ * Claim yield from a distribution
195
+ */
196
+ async claim(distributionId: number, options?: TransactionOptions): Promise<TransactionResult> {
197
+ try {
198
+ const tx = await retry(
199
+ async () => {
200
+ const gasLimit = options?.gasLimit || await estimateGasWithBuffer(
201
+ () => this._contract.claim.estimateGas(distributionId)
202
+ );
203
+ return this._contract.claim(distributionId, { gasLimit });
204
+ },
205
+ { retries: options?.retries ?? this._retries, delay: options?.retryDelay ?? this._retryDelay }
206
+ );
207
+
208
+ const receipt = await tx.wait();
209
+ const events = parseEvents(receipt, this._contract.interface);
210
+ return createTransactionResult(receipt, events);
211
+ } catch (error) {
212
+ throw parseContractError(error, this.address, 'claim');
213
+ }
214
+ }
215
+
216
+ /**
217
+ * Claim yield from multiple distributions
218
+ */
219
+ async claimMultiple(
220
+ distributionIds: number[],
221
+ options?: TransactionOptions
222
+ ): Promise<TransactionResult> {
223
+ try {
224
+ const tx = await retry(
225
+ async () => {
226
+ const gasLimit = options?.gasLimit || await estimateGasWithBuffer(
227
+ () => this._contract.claimMultiple.estimateGas(distributionIds)
228
+ );
229
+ return this._contract.claimMultiple(distributionIds, { gasLimit });
230
+ },
231
+ { retries: options?.retries ?? this._retries, delay: options?.retryDelay ?? this._retryDelay }
232
+ );
233
+
234
+ const receipt = await tx.wait();
235
+ const events = parseEvents(receipt, this._contract.interface);
236
+ return createTransactionResult(receipt, events);
237
+ } catch (error) {
238
+ throw parseContractError(error, this.address, 'claimMultiple');
239
+ }
240
+ }
241
+
242
+ /**
243
+ * Handle unclaimed funds after claim window expires
244
+ */
245
+ async handleUnclaimedFunds(
246
+ distributionId: number,
247
+ options?: TransactionOptions
248
+ ): Promise<TransactionResult> {
249
+ try {
250
+ const tx = await retry(
251
+ async () => {
252
+ const gasLimit = options?.gasLimit || await estimateGasWithBuffer(
253
+ () => this._contract.handleUnclaimedFunds.estimateGas(distributionId)
254
+ );
255
+ return this._contract.handleUnclaimedFunds(distributionId, { gasLimit });
256
+ },
257
+ { retries: options?.retries ?? this._retries, delay: options?.retryDelay ?? this._retryDelay }
258
+ );
259
+
260
+ const receipt = await tx.wait();
261
+ const events = parseEvents(receipt, this._contract.interface);
262
+ return createTransactionResult(receipt, events);
263
+ } catch (error) {
264
+ throw parseContractError(error, this.address, 'handleUnclaimedFunds');
265
+ }
266
+ }
267
+
268
+ /**
269
+ * Set the unclaimed funds recipient
270
+ */
271
+ async setUnclaimedFundsRecipient(
272
+ recipient: string,
273
+ options?: TransactionOptions
274
+ ): Promise<TransactionResult> {
275
+ const recipientAddress = normalizeAddress(recipient);
276
+
277
+ try {
278
+ const tx = await retry(
279
+ async () => {
280
+ const gasLimit = options?.gasLimit || await estimateGasWithBuffer(
281
+ () => this._contract.setUnclaimedFundsRecipient.estimateGas(recipientAddress)
282
+ );
283
+ return this._contract.setUnclaimedFundsRecipient(recipientAddress, { gasLimit });
284
+ },
285
+ { retries: options?.retries ?? this._retries, delay: options?.retryDelay ?? this._retryDelay }
286
+ );
287
+
288
+ const receipt = await tx.wait();
289
+ const events = parseEvents(receipt, this._contract.interface);
290
+ return createTransactionResult(receipt, events);
291
+ } catch (error) {
292
+ throw parseContractError(error, this.address, 'setUnclaimedFundsRecipient');
293
+ }
294
+ }
295
+
296
+ /*//////////////////////////////////////////////////////////////
297
+ EVENT LISTENERS
298
+ //////////////////////////////////////////////////////////////*/
299
+
300
+ /**
301
+ * Listen for DistributionCreated events
302
+ */
303
+ onDistributionCreated(
304
+ callback: (distributionId: bigint, paymentToken: string, totalAmount: bigint, snapshotId: bigint) => void
305
+ ): () => void {
306
+ const listener = (
307
+ distributionId: bigint,
308
+ paymentToken: string,
309
+ totalAmount: bigint,
310
+ snapshotId: bigint
311
+ ) => {
312
+ callback(distributionId, paymentToken, totalAmount, snapshotId);
313
+ };
314
+ this._contract.on('DistributionCreated', listener);
315
+ return () => this._contract.off('DistributionCreated', listener);
316
+ }
317
+
318
+ /**
319
+ * Listen for YieldClaimed events
320
+ */
321
+ onYieldClaimed(
322
+ callback: (distributionId: bigint, claimant: string, amount: bigint) => void
323
+ ): () => void {
324
+ const listener = (distributionId: bigint, claimant: string, amount: bigint) => {
325
+ callback(distributionId, claimant, amount);
326
+ };
327
+ this._contract.on('YieldClaimed', listener);
328
+ return () => this._contract.off('YieldClaimed', listener);
329
+ }
330
+ }
331
+
332
+ /**
333
+ * Module for yield distribution operations
334
+ */
335
+ export class YieldModule {
336
+ private readonly _provider: Provider;
337
+ private readonly _signer: Signer | null;
338
+ private readonly _retries: number;
339
+ private readonly _retryDelay: number;
340
+
341
+ constructor(provider: Provider, signer: Signer | null, retries: number, retryDelay: number) {
342
+ this._provider = provider;
343
+ this._signer = signer;
344
+ this._retries = retries;
345
+ this._retryDelay = retryDelay;
346
+ }
347
+
348
+ /**
349
+ * Connect to an existing yield distributor
350
+ */
351
+ connect(address: string): YieldDistributorInstance {
352
+ if (!isValidAddress(address)) {
353
+ throw new RWAError(ErrorCode.INVALID_ADDRESS, `Invalid distributor address: ${address}`);
354
+ }
355
+ return new YieldDistributorInstance(
356
+ address,
357
+ this._provider,
358
+ this._signer,
359
+ this._retries,
360
+ this._retryDelay
361
+ );
362
+ }
363
+
364
+ /**
365
+ * Create a distribution
366
+ *
367
+ * @param config - Distribution configuration
368
+ * @returns Transaction result with distribution ID
369
+ */
370
+ async distribute(config: DistributionConfig): Promise<{ result: TransactionResult; distributionId: number }> {
371
+ if (!isValidAddress(config.tokenAddress)) {
372
+ throw new RWAError(ErrorCode.INVALID_ADDRESS, `Invalid token address: ${config.tokenAddress}`);
373
+ }
374
+ if (!isValidAddress(config.paymentToken)) {
375
+ throw new RWAError(ErrorCode.INVALID_ADDRESS, `Invalid payment token address: ${config.paymentToken}`);
376
+ }
377
+
378
+ const distributor = this.connect(config.tokenAddress);
379
+ return distributor.createDistribution(
380
+ config.paymentToken,
381
+ config.totalAmount,
382
+ config.claimWindowDays
383
+ );
384
+ }
385
+
386
+ /**
387
+ * Preview a distribution (calculate per-holder amounts)
388
+ *
389
+ * This method calculates what each holder would receive based on their
390
+ * proportional ownership at the snapshot time.
391
+ *
392
+ * @param tokenAddress - The RWA token address
393
+ * @param totalAmount - Total amount to distribute (in token units)
394
+ * @param snapshotId - Optional snapshot ID (uses current balances if not provided)
395
+ * @param holderAddresses - Optional array of holder addresses to calculate for
396
+ * @returns Preview of the distribution with per-holder breakdown
397
+ */
398
+ async previewDistribution(
399
+ tokenAddress: string,
400
+ totalAmount: string,
401
+ snapshotId?: bigint,
402
+ holderAddresses?: string[]
403
+ ): Promise<DistributionPreview> {
404
+ if (!isValidAddress(tokenAddress)) {
405
+ throw new RWAError(ErrorCode.INVALID_ADDRESS, `Invalid token address: ${tokenAddress}`);
406
+ }
407
+
408
+ const token = new ethers.Contract(tokenAddress, RWA_TOKEN_ABI, this._provider);
409
+ const totalAmountWei = parseAmount(totalAmount);
410
+
411
+ // Get total supply at snapshot
412
+ let totalSupply: bigint;
413
+ if (snapshotId !== undefined) {
414
+ totalSupply = await token.totalSupplyAt(snapshotId);
415
+ } else {
416
+ totalSupply = await token.totalSupply();
417
+ }
418
+
419
+ if (totalSupply === 0n) {
420
+ return {
421
+ totalHolders: 0,
422
+ totalSupplyAtSnapshot: 0n,
423
+ distributions: [],
424
+ };
425
+ }
426
+
427
+ // If holder addresses are provided, calculate their distributions
428
+ const distributions: HolderDistribution[] = [];
429
+ if (holderAddresses && holderAddresses.length > 0) {
430
+ for (const address of holderAddresses) {
431
+ const normalizedAddress = normalizeAddress(address);
432
+ let balance: bigint;
433
+
434
+ if (snapshotId !== undefined) {
435
+ balance = await token.balanceOfAt(normalizedAddress, snapshotId);
436
+ } else {
437
+ balance = await token.balanceOf(normalizedAddress);
438
+ }
439
+
440
+ if (balance > 0n) {
441
+ // Calculate proportional yield amount
442
+ const yieldAmount = (totalAmountWei * balance) / totalSupply;
443
+ const percentage = Number((balance * 10000n) / totalSupply) / 100;
444
+
445
+ distributions.push({
446
+ address: normalizedAddress,
447
+ balance,
448
+ yieldAmount,
449
+ percentage,
450
+ });
451
+ }
452
+ }
453
+ }
454
+
455
+ return {
456
+ totalHolders: distributions.length,
457
+ totalSupplyAtSnapshot: totalSupply,
458
+ distributions,
459
+ };
460
+ }
461
+
462
+ /**
463
+ * Calculate yield amount for a specific holder
464
+ *
465
+ * @param tokenAddress - The RWA token address
466
+ * @param holderAddress - The holder's address
467
+ * @param totalAmount - Total distribution amount
468
+ * @param snapshotId - Optional snapshot ID
469
+ * @returns The calculated yield amount for the holder
470
+ */
471
+ async calculateHolderYield(
472
+ tokenAddress: string,
473
+ holderAddress: string,
474
+ totalAmount: string,
475
+ snapshotId?: bigint
476
+ ): Promise<{ balance: bigint; yieldAmount: bigint; percentage: number }> {
477
+ if (!isValidAddress(tokenAddress)) {
478
+ throw new RWAError(ErrorCode.INVALID_ADDRESS, `Invalid token address: ${tokenAddress}`);
479
+ }
480
+ if (!isValidAddress(holderAddress)) {
481
+ throw new RWAError(ErrorCode.INVALID_ADDRESS, `Invalid holder address: ${holderAddress}`);
482
+ }
483
+
484
+ const token = new ethers.Contract(tokenAddress, RWA_TOKEN_ABI, this._provider);
485
+ const totalAmountWei = parseAmount(totalAmount);
486
+ const normalizedHolder = normalizeAddress(holderAddress);
487
+
488
+ // Get total supply and holder balance
489
+ let totalSupply: bigint;
490
+ let balance: bigint;
491
+
492
+ if (snapshotId !== undefined) {
493
+ totalSupply = await token.totalSupplyAt(snapshotId);
494
+ balance = await token.balanceOfAt(normalizedHolder, snapshotId);
495
+ } else {
496
+ totalSupply = await token.totalSupply();
497
+ balance = await token.balanceOf(normalizedHolder);
498
+ }
499
+
500
+ if (totalSupply === 0n || balance === 0n) {
501
+ return { balance: 0n, yieldAmount: 0n, percentage: 0 };
502
+ }
503
+
504
+ // Calculate proportional yield amount
505
+ const yieldAmount = (totalAmountWei * balance) / totalSupply;
506
+ const percentage = Number((balance * 10000n) / totalSupply) / 100;
507
+
508
+ return { balance, yieldAmount, percentage };
509
+ }
510
+
511
+ /**
512
+ * Claim yield from a distribution
513
+ */
514
+ async claim(distributorAddress: string, distributionId: number): Promise<TransactionResult> {
515
+ const distributor = this.connect(distributorAddress);
516
+ return distributor.claim(distributionId);
517
+ }
518
+
519
+ /**
520
+ * Claim all pending yields
521
+ */
522
+ async claimAll(distributorAddress: string): Promise<TransactionResult> {
523
+ if (!this._signer) {
524
+ throw new RWAError(ErrorCode.SIGNER_REQUIRED, 'A signer is required to claim yields');
525
+ }
526
+
527
+ const distributor = this.connect(distributorAddress);
528
+ const signerAddress = await this._signer.getAddress();
529
+ const pendingClaims = await distributor.getPendingClaims(signerAddress);
530
+
531
+ if (pendingClaims.length === 0) {
532
+ throw new RWAError(ErrorCode.INVALID_CONFIGURATION, 'No pending claims to process');
533
+ }
534
+
535
+ const distributionIds = pendingClaims.map((c) => c.distributionId);
536
+ return distributor.claimMultiple(distributionIds);
537
+ }
538
+
539
+ /**
540
+ * Get claimable amount for an account
541
+ */
542
+ async getClaimableAmount(
543
+ distributorAddress: string,
544
+ distributionId: number,
545
+ account: string
546
+ ): Promise<bigint> {
547
+ const distributor = this.connect(distributorAddress);
548
+ return distributor.getClaimableAmount(distributionId, account);
549
+ }
550
+
551
+ /**
552
+ * Get distribution history
553
+ */
554
+ async getDistributionHistory(distributorAddress: string): Promise<Distribution[]> {
555
+ const distributor = this.connect(distributorAddress);
556
+ return distributor.getDistributionHistory();
557
+ }
558
+
559
+ /**
560
+ * Get pending claims for an account
561
+ */
562
+ async getPendingClaims(distributorAddress: string, account: string): Promise<PendingClaim[]> {
563
+ const distributor = this.connect(distributorAddress);
564
+ return distributor.getPendingClaims(account);
565
+ }
566
+ }