pepay-streams-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 (62) hide show
  1. package/README.md +405 -0
  2. package/dist/api/index.d.mts +321 -0
  3. package/dist/api/index.d.ts +321 -0
  4. package/dist/api/index.js +312 -0
  5. package/dist/api/index.js.map +1 -0
  6. package/dist/api/index.mjs +306 -0
  7. package/dist/api/index.mjs.map +1 -0
  8. package/dist/automation/index.d.mts +140 -0
  9. package/dist/automation/index.d.ts +140 -0
  10. package/dist/automation/index.js +331 -0
  11. package/dist/automation/index.js.map +1 -0
  12. package/dist/automation/index.mjs +326 -0
  13. package/dist/automation/index.mjs.map +1 -0
  14. package/dist/campaigns/index.d.mts +286 -0
  15. package/dist/campaigns/index.d.ts +286 -0
  16. package/dist/campaigns/index.js +652 -0
  17. package/dist/campaigns/index.js.map +1 -0
  18. package/dist/campaigns/index.mjs +645 -0
  19. package/dist/campaigns/index.mjs.map +1 -0
  20. package/dist/claims/index.d.mts +190 -0
  21. package/dist/claims/index.d.ts +190 -0
  22. package/dist/claims/index.js +414 -0
  23. package/dist/claims/index.js.map +1 -0
  24. package/dist/claims/index.mjs +409 -0
  25. package/dist/claims/index.mjs.map +1 -0
  26. package/dist/index-BTG0TRJt.d.mts +555 -0
  27. package/dist/index-BTG0TRJt.d.ts +555 -0
  28. package/dist/index.d.mts +170 -0
  29. package/dist/index.d.ts +170 -0
  30. package/dist/index.js +2926 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/index.mjs +2888 -0
  33. package/dist/index.mjs.map +1 -0
  34. package/dist/marketplace/index.d.mts +225 -0
  35. package/dist/marketplace/index.d.ts +225 -0
  36. package/dist/marketplace/index.js +529 -0
  37. package/dist/marketplace/index.js.map +1 -0
  38. package/dist/marketplace/index.mjs +524 -0
  39. package/dist/marketplace/index.mjs.map +1 -0
  40. package/dist/react/index.d.mts +185 -0
  41. package/dist/react/index.d.ts +185 -0
  42. package/dist/react/index.js +340 -0
  43. package/dist/react/index.js.map +1 -0
  44. package/dist/react/index.mjs +333 -0
  45. package/dist/react/index.mjs.map +1 -0
  46. package/dist/staking/index.d.mts +158 -0
  47. package/dist/staking/index.d.ts +158 -0
  48. package/dist/staking/index.js +359 -0
  49. package/dist/staking/index.js.map +1 -0
  50. package/dist/staking/index.mjs +354 -0
  51. package/dist/staking/index.mjs.map +1 -0
  52. package/package.json +106 -0
  53. package/src/api/index.ts +577 -0
  54. package/src/automation/index.ts +436 -0
  55. package/src/campaigns/index.ts +835 -0
  56. package/src/claims/index.ts +530 -0
  57. package/src/client.ts +518 -0
  58. package/src/index.ts +101 -0
  59. package/src/marketplace/index.ts +730 -0
  60. package/src/react/index.ts +498 -0
  61. package/src/staking/index.ts +449 -0
  62. package/src/types/index.ts +631 -0
package/dist/index.mjs ADDED
@@ -0,0 +1,2888 @@
1
+ import { zeroAddress, keccak256, encodePacked, createPublicClient, http, custom, createWalletClient, erc20Abi } from 'viem';
2
+ import { DIAMOND_ABI } from '@pepay-streams/abi/diamond';
3
+ export { CampaignKind, ChangePolicy, DeliveryKind, OrderStatus, StartMode, StatusBits, Visibility } from '@pepay-streams/shared';
4
+
5
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
6
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
7
+ }) : x)(function(x) {
8
+ if (typeof require !== "undefined") return require.apply(this, arguments);
9
+ throw Error('Dynamic require of "' + x + '" is not supported');
10
+ });
11
+ var CampaignsModule = class {
12
+ constructor(publicClient, walletClient, diamondAddress) {
13
+ this.publicClient = publicClient;
14
+ this.walletClient = walletClient;
15
+ this.diamondAddress = diamondAddress;
16
+ }
17
+ // ============================================================================
18
+ // Campaign Creation
19
+ // ============================================================================
20
+ /**
21
+ * Create an Instant Airdrop campaign
22
+ *
23
+ * Tokens are immediately claimable by recipients after funding.
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * const result = await sdk.campaigns.createInstantAirdrop({
28
+ * token: '0x...',
29
+ * recipients: [
30
+ * { address: '0x...', amount: parseEther('100') },
31
+ * { address: '0x...', amount: parseEther('50') },
32
+ * ],
33
+ * });
34
+ * console.log('Campaign created, tx:', result.hash);
35
+ * ```
36
+ */
37
+ async createInstantAirdrop(params) {
38
+ const wallet = this.requireWallet();
39
+ const recipients = params.recipients.map((r) => r.address);
40
+ const amounts = params.recipients.map((r) => r.amount);
41
+ const now = BigInt(Math.floor(Date.now() / 1e3));
42
+ const args = {
43
+ kind: 0 /* INSTANT */,
44
+ token: params.token,
45
+ start: now,
46
+ end: now,
47
+ // Instant airdrop - same start/end
48
+ step: 0n,
49
+ cliffReleaseTime: 0n,
50
+ cliffBps: 0,
51
+ autoClaimIncentiveBps: params.autoClaimIncentiveBps ?? 0,
52
+ cancelable: params.cancelable ?? true,
53
+ claimOnce: params.claimOnce ?? true,
54
+ changePolicy: this.changePolicyToEnum(params.changePolicy),
55
+ claimGrace: BigInt(params.claimGrace ?? 0),
56
+ recipients,
57
+ amounts,
58
+ feeBuffer: params.feeBuffer ?? 0n,
59
+ attachDefaultRegistry: params.attachDefaultRegistry ?? false,
60
+ unwrapWETH: params.unwrapWETH ?? false,
61
+ weth: params.weth ?? zeroAddress
62
+ };
63
+ const hash = await wallet.writeContract({
64
+ chain: wallet.chain,
65
+ account: wallet.account,
66
+ address: this.diamondAddress,
67
+ abi: DIAMOND_ABI,
68
+ functionName: "createCampaign",
69
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
70
+ args: [args]
71
+ });
72
+ return this.createTransactionResult(hash);
73
+ }
74
+ /**
75
+ * Create a Vested Airdrop campaign
76
+ *
77
+ * Tokens vest linearly over time with optional cliff period.
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * const result = await sdk.campaigns.createVestedAirdrop({
82
+ * token: '0x...',
83
+ * recipients: [
84
+ * { address: '0x...', amount: parseEther('1000') },
85
+ * ],
86
+ * startTime: Math.floor(Date.now() / 1000), // Start now
87
+ * duration: 365 * 24 * 60 * 60, // 1 year
88
+ * cliffDuration: 90 * 24 * 60 * 60, // 3 month cliff
89
+ * steps: 12, // Monthly releases
90
+ * });
91
+ * ```
92
+ */
93
+ async createVestedAirdrop(params) {
94
+ const wallet = this.requireWallet();
95
+ const recipients = params.recipients.map((r) => r.address);
96
+ const amounts = params.recipients.map((r) => r.amount);
97
+ const startTime = BigInt(params.startTime);
98
+ const endTime = startTime + BigInt(params.duration);
99
+ const steps = params.steps ?? 1;
100
+ const step = steps > 1 ? BigInt(params.duration) / BigInt(steps) : 0n;
101
+ const cliffReleaseTime = params.cliffDuration ? startTime + BigInt(params.cliffDuration) : 0n;
102
+ const args = {
103
+ kind: 1 /* VESTED */,
104
+ token: params.token,
105
+ start: startTime,
106
+ end: endTime,
107
+ step,
108
+ cliffReleaseTime,
109
+ cliffBps: params.cliffBps ?? 0,
110
+ autoClaimIncentiveBps: params.autoClaimIncentiveBps ?? 0,
111
+ cancelable: params.cancelable ?? true,
112
+ claimOnce: false,
113
+ // Vested can claim multiple times
114
+ changePolicy: this.changePolicyToEnum(params.changePolicy),
115
+ claimGrace: BigInt(params.claimGrace ?? 0),
116
+ recipients,
117
+ amounts,
118
+ feeBuffer: params.feeBuffer ?? 0n,
119
+ attachDefaultRegistry: params.attachDefaultRegistry ?? false,
120
+ unwrapWETH: params.unwrapWETH ?? false,
121
+ weth: params.weth ?? zeroAddress
122
+ };
123
+ const hash = await wallet.writeContract({
124
+ chain: wallet.chain,
125
+ account: wallet.account,
126
+ address: this.diamondAddress,
127
+ abi: DIAMOND_ABI,
128
+ functionName: "createCampaign",
129
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
130
+ args: [args]
131
+ });
132
+ return this.createTransactionResult(hash);
133
+ }
134
+ /**
135
+ * Create a Token Lock
136
+ *
137
+ * Tokens are locked until a specific unlock time, then fully releasable.
138
+ *
139
+ * @example
140
+ * ```typescript
141
+ * const result = await sdk.campaigns.createLock({
142
+ * token: '0x...',
143
+ * recipient: '0x...',
144
+ * amount: parseEther('1000000'),
145
+ * unlockTime: Math.floor(Date.now() / 1000) + 180 * 24 * 60 * 60, // 6 months
146
+ * });
147
+ * ```
148
+ */
149
+ async createLock(params) {
150
+ const wallet = this.requireWallet();
151
+ const now = BigInt(Math.floor(Date.now() / 1e3));
152
+ const unlockTime = BigInt(params.unlockTime);
153
+ const args = {
154
+ kind: 2 /* LOCK */,
155
+ token: params.token,
156
+ start: now,
157
+ end: unlockTime,
158
+ step: 0n,
159
+ cliffReleaseTime: unlockTime,
160
+ // Lock releases at this time
161
+ cliffBps: 1e4,
162
+ // 100% released at cliff
163
+ autoClaimIncentiveBps: 0,
164
+ cancelable: params.cancelable ?? false,
165
+ claimOnce: true,
166
+ changePolicy: this.changePolicyToEnum(params.changePolicy),
167
+ claimGrace: 0n,
168
+ recipients: [params.recipient],
169
+ amounts: [params.amount],
170
+ feeBuffer: params.feeBuffer ?? 0n,
171
+ attachDefaultRegistry: false,
172
+ unwrapWETH: params.unwrapWETH ?? false,
173
+ weth: params.weth ?? zeroAddress
174
+ };
175
+ const hash = await wallet.writeContract({
176
+ chain: wallet.chain,
177
+ account: wallet.account,
178
+ address: this.diamondAddress,
179
+ abi: DIAMOND_ABI,
180
+ functionName: "createCampaign",
181
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
182
+ args: [args]
183
+ });
184
+ return this.createTransactionResult(hash);
185
+ }
186
+ /**
187
+ * Create a Vesting Stream (Payment)
188
+ *
189
+ * Single-recipient vesting with optional automation.
190
+ *
191
+ * @example
192
+ * ```typescript
193
+ * const result = await sdk.campaigns.createVesting({
194
+ * token: '0x...',
195
+ * recipient: '0x...',
196
+ * amount: parseEther('120000'), // 120k tokens
197
+ * startTime: Math.floor(Date.now() / 1000),
198
+ * duration: 365 * 24 * 60 * 60, // 1 year
199
+ * cliffDuration: 0, // No cliff
200
+ * steps: 12, // Monthly
201
+ * });
202
+ * ```
203
+ */
204
+ async createVesting(params) {
205
+ const wallet = this.requireWallet();
206
+ const startTime = BigInt(params.startTime);
207
+ const endTime = startTime + BigInt(params.duration);
208
+ const steps = params.steps ?? 1;
209
+ const step = steps > 1 ? BigInt(params.duration) / BigInt(steps) : 0n;
210
+ const cliffReleaseTime = params.cliffDuration ? startTime + BigInt(params.cliffDuration) : 0n;
211
+ const args = {
212
+ kind: 3 /* VESTING */,
213
+ token: params.token,
214
+ start: startTime,
215
+ end: endTime,
216
+ step,
217
+ cliffReleaseTime,
218
+ cliffBps: params.cliffBps ?? 0,
219
+ autoClaimIncentiveBps: params.autoClaimIncentiveBps ?? 0,
220
+ cancelable: params.cancelable ?? true,
221
+ claimOnce: false,
222
+ changePolicy: this.changePolicyToEnum(params.changePolicy),
223
+ claimGrace: BigInt(params.claimGrace ?? 0),
224
+ recipients: [params.recipient],
225
+ amounts: [params.amount],
226
+ feeBuffer: params.feeBuffer ?? 0n,
227
+ attachDefaultRegistry: false,
228
+ unwrapWETH: params.unwrapWETH ?? false,
229
+ weth: params.weth ?? zeroAddress
230
+ };
231
+ const hash = await wallet.writeContract({
232
+ chain: wallet.chain,
233
+ account: wallet.account,
234
+ address: this.diamondAddress,
235
+ abi: DIAMOND_ABI,
236
+ functionName: "createCampaign",
237
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
238
+ args: [args]
239
+ });
240
+ return this.createTransactionResult(hash);
241
+ }
242
+ /**
243
+ * Create a campaign with raw CreateArgs
244
+ *
245
+ * Low-level function for full control over campaign parameters.
246
+ */
247
+ async createCampaign(args) {
248
+ const wallet = this.requireWallet();
249
+ const hash = await wallet.writeContract({
250
+ chain: wallet.chain,
251
+ account: wallet.account,
252
+ address: this.diamondAddress,
253
+ abi: DIAMOND_ABI,
254
+ functionName: "createCampaign",
255
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
256
+ args: [args]
257
+ });
258
+ return this.createTransactionResult(hash);
259
+ }
260
+ // ============================================================================
261
+ // Campaign Funding
262
+ // ============================================================================
263
+ /**
264
+ * Fund a campaign using EIP-2612 Permit (gasless approval)
265
+ *
266
+ * @example
267
+ * ```typescript
268
+ * const result = await sdk.campaigns.fundWithPermit({
269
+ * campaignId,
270
+ * amount: parseEther('1000'),
271
+ * deadline: Math.floor(Date.now() / 1000) + 3600,
272
+ * v: 28,
273
+ * r: '0x...',
274
+ * s: '0x...',
275
+ * });
276
+ * ```
277
+ */
278
+ async fundWithPermit(params) {
279
+ const wallet = this.requireWallet();
280
+ const hash = await wallet.writeContract({
281
+ chain: wallet.chain,
282
+ account: wallet.account,
283
+ address: this.diamondAddress,
284
+ abi: DIAMOND_ABI,
285
+ functionName: "fundWithPermit",
286
+ args: [
287
+ params.campaignId,
288
+ params.amount,
289
+ params.deadline,
290
+ params.v,
291
+ params.r,
292
+ params.s
293
+ ]
294
+ });
295
+ return this.createTransactionResult(hash);
296
+ }
297
+ /**
298
+ * Fund a campaign using Permit2 (gasless approval)
299
+ *
300
+ * @example
301
+ * ```typescript
302
+ * const result = await sdk.campaigns.fundWithPermit2({
303
+ * campaignId,
304
+ * from: userAddress,
305
+ * amount: parseEther('1000'),
306
+ * permit2Data: encodedPermit2Data,
307
+ * });
308
+ * ```
309
+ */
310
+ async fundWithPermit2(params) {
311
+ const wallet = this.requireWallet();
312
+ const hash = await wallet.writeContract({
313
+ chain: wallet.chain,
314
+ account: wallet.account,
315
+ address: this.diamondAddress,
316
+ abi: DIAMOND_ABI,
317
+ functionName: "fundWithPermit2",
318
+ args: [
319
+ params.campaignId,
320
+ params.from,
321
+ params.amount,
322
+ params.permit2Data
323
+ ]
324
+ });
325
+ return this.createTransactionResult(hash);
326
+ }
327
+ /**
328
+ * Return leftover tokens to creator
329
+ *
330
+ * @example
331
+ * ```typescript
332
+ * const result = await sdk.campaigns.returnLeftover(campaignId, parseEther('100'));
333
+ * ```
334
+ */
335
+ async returnLeftover(campaignId, amountToReturn) {
336
+ const wallet = this.requireWallet();
337
+ const hash = await wallet.writeContract({
338
+ chain: wallet.chain,
339
+ account: wallet.account,
340
+ address: this.diamondAddress,
341
+ abi: DIAMOND_ABI,
342
+ functionName: "returnLeftover",
343
+ args: [campaignId, amountToReturn]
344
+ });
345
+ return this.createTransactionResult(hash);
346
+ }
347
+ /**
348
+ * Add native tips to a campaign for automation
349
+ */
350
+ async addNativeTips(campaignId, tipAmount) {
351
+ const wallet = this.requireWallet();
352
+ const hash = await wallet.writeContract({
353
+ chain: wallet.chain,
354
+ account: wallet.account,
355
+ address: this.diamondAddress,
356
+ abi: DIAMOND_ABI,
357
+ functionName: "addNativeTips",
358
+ args: [campaignId, tipAmount],
359
+ value: tipAmount
360
+ });
361
+ return this.createTransactionResult(hash);
362
+ }
363
+ // ============================================================================
364
+ // Campaign Queries
365
+ // ============================================================================
366
+ /**
367
+ * Get campaign summary by ID
368
+ *
369
+ * Returns full campaign configuration and state.
370
+ *
371
+ * @example
372
+ * ```typescript
373
+ * const campaign = await sdk.campaigns.getCampaign(1n);
374
+ * console.log('Campaign token:', campaign.token);
375
+ * console.log('Total claimed:', campaign.totalClaimed);
376
+ * ```
377
+ */
378
+ async getCampaign(campaignId) {
379
+ const result = await this.publicClient.readContract({
380
+ address: this.diamondAddress,
381
+ abi: DIAMOND_ABI,
382
+ functionName: "campaignSummary",
383
+ args: [campaignId]
384
+ });
385
+ return this.parseCampaignSummary(campaignId, result);
386
+ }
387
+ /**
388
+ * Get campaign configuration only
389
+ */
390
+ async getCampaignConfig(campaignId) {
391
+ const result = await this.publicClient.readContract({
392
+ address: this.diamondAddress,
393
+ abi: DIAMOND_ABI,
394
+ functionName: "campaignConfig",
395
+ args: [campaignId]
396
+ });
397
+ return {
398
+ kind: Number(result.kind),
399
+ cancelable: Boolean(result.cancelable),
400
+ claimOnce: Boolean(result.claimOnce),
401
+ canceled: Boolean(result.canceled),
402
+ changePolicy: Number(result.changePolicy),
403
+ token: result.token,
404
+ creator: result.creator,
405
+ cliffBps: Number(result.cliffBps),
406
+ autoClaimIncentiveBps: Number(result.autoClaimIncentiveBps),
407
+ start: Number(result.start),
408
+ end: Number(result.end),
409
+ step: Number(result.step),
410
+ canceledAt: Number(result.canceledAt),
411
+ cliffReleaseTime: Number(result.cliffReleaseTime),
412
+ claimGrace: Number(result.claimGrace),
413
+ unwrapWETH: Boolean(result.unwrapWETH),
414
+ weth: result.weth
415
+ };
416
+ }
417
+ /**
418
+ * Get campaign state (totals and accounting)
419
+ */
420
+ async getCampaignState(campaignId) {
421
+ const result = await this.publicClient.readContract({
422
+ address: this.diamondAddress,
423
+ abi: DIAMOND_ABI,
424
+ functionName: "campaignState",
425
+ args: [campaignId]
426
+ });
427
+ return {
428
+ totalAllocated: result.totalAllocated,
429
+ totalClaimed: result.totalClaimed,
430
+ nativeTips: result.nativeTips,
431
+ returned: result.returned,
432
+ feeBuffer: result.feeBuffer,
433
+ feeLoss: result.feeLoss,
434
+ totalFunded: result.totalFunded,
435
+ statusBits: Number(result.statusBits),
436
+ uniqueRecipients: result.uniqueRecipients
437
+ };
438
+ }
439
+ /**
440
+ * Get campaign status bits
441
+ */
442
+ async getCampaignStatus(campaignId) {
443
+ const result = await this.publicClient.readContract({
444
+ address: this.diamondAddress,
445
+ abi: DIAMOND_ABI,
446
+ functionName: "campaignStatus",
447
+ args: [campaignId]
448
+ });
449
+ return Number(result);
450
+ }
451
+ // ============================================================================
452
+ // Campaign Administration
453
+ // ============================================================================
454
+ /**
455
+ * Pause a campaign (creator or admin only)
456
+ *
457
+ * @param campaignId - Campaign ID
458
+ * @param reason - Pause reason as status bits (e.g., 1 for creator pause)
459
+ */
460
+ async pause(campaignId, reason = 1) {
461
+ const wallet = this.requireWallet();
462
+ const hash = await wallet.writeContract({
463
+ chain: wallet.chain,
464
+ account: wallet.account,
465
+ address: this.diamondAddress,
466
+ abi: DIAMOND_ABI,
467
+ functionName: "pauseCampaign",
468
+ args: [campaignId, reason]
469
+ });
470
+ return this.createTransactionResult(hash);
471
+ }
472
+ /**
473
+ * Resume a paused campaign
474
+ *
475
+ * @param campaignId - Campaign ID
476
+ * @param clearBits - Status bits to clear (e.g., 1 for creator pause)
477
+ */
478
+ async resume(campaignId, clearBits = 1) {
479
+ const wallet = this.requireWallet();
480
+ const hash = await wallet.writeContract({
481
+ chain: wallet.chain,
482
+ account: wallet.account,
483
+ address: this.diamondAddress,
484
+ abi: DIAMOND_ABI,
485
+ functionName: "resumeCampaign",
486
+ args: [campaignId, clearBits]
487
+ });
488
+ return this.createTransactionResult(hash);
489
+ }
490
+ /**
491
+ * Finalize a campaign (no more claims possible)
492
+ */
493
+ async finalize(campaignId) {
494
+ const wallet = this.requireWallet();
495
+ const hash = await wallet.writeContract({
496
+ chain: wallet.chain,
497
+ account: wallet.account,
498
+ address: this.diamondAddress,
499
+ abi: DIAMOND_ABI,
500
+ functionName: "finalizeCampaign",
501
+ args: [campaignId]
502
+ });
503
+ return this.createTransactionResult(hash);
504
+ }
505
+ /**
506
+ * Cancel a campaign and return funds to creator
507
+ */
508
+ async cancel(campaignId) {
509
+ const wallet = this.requireWallet();
510
+ const hash = await wallet.writeContract({
511
+ chain: wallet.chain,
512
+ account: wallet.account,
513
+ address: this.diamondAddress,
514
+ abi: DIAMOND_ABI,
515
+ functionName: "cancel",
516
+ args: [campaignId]
517
+ });
518
+ return this.createTransactionResult(hash);
519
+ }
520
+ /**
521
+ * Change a recipient address (for blocked recipients)
522
+ */
523
+ async changeRecipient(campaignId, fromAddress, toAddress) {
524
+ const wallet = this.requireWallet();
525
+ const hash = await wallet.writeContract({
526
+ chain: wallet.chain,
527
+ account: wallet.account,
528
+ address: this.diamondAddress,
529
+ abi: DIAMOND_ABI,
530
+ functionName: "changeRecipient",
531
+ args: [campaignId, fromAddress, toAddress]
532
+ });
533
+ return this.createTransactionResult(hash);
534
+ }
535
+ /**
536
+ * Add recipients to an existing campaign
537
+ */
538
+ async addRecipients(campaignId, recipients, amounts, additionalBuffer = 0n) {
539
+ const wallet = this.requireWallet();
540
+ const hash = await wallet.writeContract({
541
+ chain: wallet.chain,
542
+ account: wallet.account,
543
+ address: this.diamondAddress,
544
+ abi: DIAMOND_ABI,
545
+ functionName: "addRecipients",
546
+ args: [campaignId, recipients, amounts, additionalBuffer]
547
+ });
548
+ return this.createTransactionResult(hash);
549
+ }
550
+ // ============================================================================
551
+ // Helpers
552
+ // ============================================================================
553
+ requireWallet() {
554
+ if (!this.walletClient) {
555
+ throw new Error(
556
+ "Wallet client required for write operations. Initialize SDK with a signer."
557
+ );
558
+ }
559
+ return this.walletClient;
560
+ }
561
+ changePolicyToEnum(policy) {
562
+ switch (policy) {
563
+ case "only_recipient":
564
+ return 0 /* ONLY_RECIPIENT */;
565
+ case "only_creator":
566
+ return 1 /* ONLY_CREATOR */;
567
+ case "both":
568
+ return 2 /* BOTH */;
569
+ case "no_one":
570
+ return 3 /* NO_ONE */;
571
+ default:
572
+ return 0 /* ONLY_RECIPIENT */;
573
+ }
574
+ }
575
+ parseCampaignSummary(id, data) {
576
+ const cfg = data.cfg;
577
+ const state = data.state;
578
+ const kindMap = {
579
+ 0: "instant_airdrop",
580
+ 1: "vested_airdrop",
581
+ 2: "lock",
582
+ 3: "vesting"
583
+ };
584
+ const kind = Number(cfg.kind);
585
+ const result = {
586
+ id,
587
+ kind: kindMap[kind] ?? "instant_airdrop",
588
+ token: cfg.token,
589
+ creator: cfg.creator,
590
+ name: "",
591
+ // Not stored on-chain
592
+ totalAllocated: state.totalAllocated,
593
+ totalFunded: state.totalFunded,
594
+ totalClaimed: state.totalClaimed,
595
+ totalReturned: state.returned,
596
+ feeLoss: state.feeLoss,
597
+ feeBuffer: state.feeBuffer,
598
+ startTime: Number(cfg.start),
599
+ endTime: Number(cfg.end),
600
+ cliffTime: Number(cfg.cliffReleaseTime),
601
+ steps: Number(cfg.step) > 0 ? Math.ceil((Number(cfg.end) - Number(cfg.start)) / Number(cfg.step)) : 1,
602
+ recipientCount: Number(state.uniqueRecipients),
603
+ statusBits: Number(state.statusBits),
604
+ changePolicy: Number(cfg.changePolicy),
605
+ hasAutomation: (Number(state.statusBits) & 1 << 5) !== 0
606
+ };
607
+ if (data.hasRegistry) {
608
+ result.hasRegistry = true;
609
+ }
610
+ if (data.merkleRoot) {
611
+ result.merkleRoot = data.merkleRoot;
612
+ }
613
+ return result;
614
+ }
615
+ createTransactionResult(hash) {
616
+ return {
617
+ hash,
618
+ wait: async () => {
619
+ const receipt = await this.publicClient.waitForTransactionReceipt({
620
+ hash
621
+ });
622
+ return {
623
+ blockNumber: receipt.blockNumber,
624
+ transactionHash: receipt.transactionHash,
625
+ gasUsed: receipt.gasUsed,
626
+ status: receipt.status,
627
+ logs: receipt.logs
628
+ };
629
+ }
630
+ };
631
+ }
632
+ };
633
+ var ClaimsModule = class {
634
+ constructor(publicClient, walletClient, diamondAddress, chainId) {
635
+ this.publicClient = publicClient;
636
+ this.walletClient = walletClient;
637
+ this.diamondAddress = diamondAddress;
638
+ this.chainId = chainId;
639
+ }
640
+ // ============================================================================
641
+ // Standard Claims
642
+ // ============================================================================
643
+ /**
644
+ * Claim vested tokens from a campaign
645
+ *
646
+ * For merkle-tree campaigns, requires allocation and proof.
647
+ * For direct campaigns, allocation should be 0 and proof empty.
648
+ *
649
+ * @example
650
+ * ```typescript
651
+ * // Direct campaign claim
652
+ * const result = await sdk.claims.claim({
653
+ * campaignId: 1n,
654
+ * allocation: 0n,
655
+ * proof: [],
656
+ * });
657
+ *
658
+ * // Merkle campaign claim
659
+ * const result = await sdk.claims.claim({
660
+ * campaignId: 1n,
661
+ * allocation: parseEther('100'),
662
+ * proof: ['0x...', '0x...'],
663
+ * });
664
+ * ```
665
+ */
666
+ async claim(params) {
667
+ const wallet = this.requireWallet();
668
+ let hash;
669
+ if (params.claimTo) {
670
+ hash = await wallet.writeContract({
671
+ chain: wallet.chain,
672
+ account: wallet.account,
673
+ address: this.diamondAddress,
674
+ abi: DIAMOND_ABI,
675
+ functionName: "claimTo",
676
+ args: [
677
+ params.campaignId,
678
+ params.claimTo,
679
+ params.allocation ?? 0n,
680
+ params.proof ?? []
681
+ ]
682
+ });
683
+ } else {
684
+ hash = await wallet.writeContract({
685
+ chain: wallet.chain,
686
+ account: wallet.account,
687
+ address: this.diamondAddress,
688
+ abi: DIAMOND_ABI,
689
+ functionName: "claim",
690
+ args: [
691
+ params.campaignId,
692
+ params.allocation ?? 0n,
693
+ params.proof ?? []
694
+ ]
695
+ });
696
+ }
697
+ return this.createTransactionResult(hash);
698
+ }
699
+ /**
700
+ * Claim from a campaign for multiple recipients in a single transaction
701
+ *
702
+ * More gas efficient than multiple individual claims.
703
+ * For direct allocation campaigns only.
704
+ *
705
+ * @example
706
+ * ```typescript
707
+ * const result = await sdk.claims.claimBatch({
708
+ * campaignId: 1n,
709
+ * recipients: ['0x...', '0x...', '0x...'],
710
+ * });
711
+ * ```
712
+ */
713
+ async claimBatch(params) {
714
+ const wallet = this.requireWallet();
715
+ const hash = await wallet.writeContract({
716
+ chain: wallet.chain,
717
+ account: wallet.account,
718
+ address: this.diamondAddress,
719
+ abi: DIAMOND_ABI,
720
+ functionName: "claimMany",
721
+ args: [params.campaignId, params.recipients]
722
+ });
723
+ return this.createTransactionResult(hash);
724
+ }
725
+ /**
726
+ * Release locked tokens (for Lock campaigns)
727
+ *
728
+ * Can only be called after the unlock time has passed.
729
+ *
730
+ * @example
731
+ * ```typescript
732
+ * const result = await sdk.claims.releaseLock(campaignId, [recipient1, recipient2]);
733
+ * ```
734
+ */
735
+ async releaseLock(campaignId, recipients) {
736
+ const wallet = this.requireWallet();
737
+ const hash = await wallet.writeContract({
738
+ chain: wallet.chain,
739
+ account: wallet.account,
740
+ address: this.diamondAddress,
741
+ abi: DIAMOND_ABI,
742
+ functionName: "releaseLock",
743
+ args: [campaignId, recipients]
744
+ });
745
+ return this.createTransactionResult(hash);
746
+ }
747
+ // ============================================================================
748
+ // Meta-Transaction Claims (Gasless)
749
+ // ============================================================================
750
+ /**
751
+ * Claim via meta-transaction (gasless for recipient)
752
+ *
753
+ * A relayer submits the transaction on behalf of the recipient.
754
+ * The recipient signs an EIP-712 message off-chain.
755
+ *
756
+ * @example
757
+ * ```typescript
758
+ * // Recipient signs off-chain
759
+ * const signedAuth = await sdk.claims.signClaimMessage({
760
+ * campaignId,
761
+ * allocation: parseEther('100'),
762
+ * proof: ['0x...'],
763
+ * deadline: Math.floor(Date.now() / 1000) + 3600, // 1 hour
764
+ * });
765
+ *
766
+ * // Relayer submits
767
+ * const result = await sdk.claims.claimWithSig(signedAuth);
768
+ * ```
769
+ */
770
+ async claimWithSig(params) {
771
+ const wallet = this.requireWallet();
772
+ const auth = {
773
+ id: params.campaignId,
774
+ claimant: params.claimant,
775
+ payoutTo: params.payoutTo ?? params.claimant,
776
+ allocation: params.allocation,
777
+ proofHash: this.computeProofHash(params.proof),
778
+ deadline: BigInt(params.deadline),
779
+ nonce: params.nonce
780
+ };
781
+ const hash = await wallet.writeContract({
782
+ chain: wallet.chain,
783
+ account: wallet.account,
784
+ address: this.diamondAddress,
785
+ abi: DIAMOND_ABI,
786
+ functionName: "claimWithSig",
787
+ args: [auth, params.proof, params.signature]
788
+ });
789
+ return this.createTransactionResult(hash);
790
+ }
791
+ /**
792
+ * Generate the EIP-712 typed data for a claim signature
793
+ *
794
+ * The recipient signs this message off-chain.
795
+ */
796
+ getClaimTypedData(campaignId, claimant, payoutTo, allocation, proofHash, nonce, deadline) {
797
+ return {
798
+ domain: {
799
+ name: "PepayStreams",
800
+ version: "1",
801
+ chainId: this.chainId,
802
+ verifyingContract: this.diamondAddress
803
+ },
804
+ types: {
805
+ ClaimAuth: [
806
+ { name: "id", type: "uint256" },
807
+ { name: "claimant", type: "address" },
808
+ { name: "payoutTo", type: "address" },
809
+ { name: "allocation", type: "uint128" },
810
+ { name: "proofHash", type: "bytes32" },
811
+ { name: "deadline", type: "uint64" },
812
+ { name: "nonce", type: "uint256" }
813
+ ]
814
+ },
815
+ primaryType: "ClaimAuth",
816
+ message: {
817
+ id: campaignId,
818
+ claimant,
819
+ payoutTo,
820
+ allocation,
821
+ proofHash,
822
+ deadline: BigInt(deadline),
823
+ nonce
824
+ }
825
+ };
826
+ }
827
+ /**
828
+ * Sign a claim message for meta-transaction
829
+ *
830
+ * Returns the signature that can be submitted by a relayer.
831
+ */
832
+ async signClaimMessage(params) {
833
+ const wallet = this.requireWallet();
834
+ const claimant = wallet.account.address;
835
+ const payoutTo = params.payoutTo ?? claimant;
836
+ const nonce = await this.getClaimNonce(params.campaignId, claimant);
837
+ const proofHash = this.computeProofHash(params.proof);
838
+ const typedData = this.getClaimTypedData(
839
+ params.campaignId,
840
+ claimant,
841
+ payoutTo,
842
+ params.allocation,
843
+ proofHash,
844
+ nonce,
845
+ params.deadline
846
+ );
847
+ const signature = await wallet.signTypedData({
848
+ account: wallet.account,
849
+ domain: typedData.domain,
850
+ types: typedData.types,
851
+ primaryType: typedData.primaryType,
852
+ message: typedData.message
853
+ });
854
+ return {
855
+ signature,
856
+ nonce,
857
+ deadline: params.deadline,
858
+ claimant,
859
+ payoutTo,
860
+ allocation: params.allocation,
861
+ proof: params.proof,
862
+ campaignId: params.campaignId
863
+ };
864
+ }
865
+ /**
866
+ * Get the current nonce for claim meta-transactions
867
+ */
868
+ async getClaimNonce(campaignId, address) {
869
+ const result = await this.publicClient.readContract({
870
+ address: this.diamondAddress,
871
+ abi: DIAMOND_ABI,
872
+ functionName: "noncesClaim",
873
+ args: [campaignId, address]
874
+ });
875
+ return result;
876
+ }
877
+ // ============================================================================
878
+ // Claim Status Queries
879
+ // ============================================================================
880
+ /**
881
+ * Get the amount currently claimable for a recipient
882
+ *
883
+ * @example
884
+ * ```typescript
885
+ * const claimable = await sdk.claims.getClaimable(campaignId, recipientAddress);
886
+ * console.log('Claimable:', formatEther(claimable));
887
+ * ```
888
+ */
889
+ async getClaimable(campaignId, recipient) {
890
+ const result = await this.publicClient.readContract({
891
+ address: this.diamondAddress,
892
+ abi: DIAMOND_ABI,
893
+ functionName: "claimableOf",
894
+ args: [campaignId, recipient]
895
+ });
896
+ return result;
897
+ }
898
+ /**
899
+ * Check if a recipient is blocked from claiming
900
+ */
901
+ async isBlocked(campaignId, recipient) {
902
+ const result = await this.publicClient.readContract({
903
+ address: this.diamondAddress,
904
+ abi: DIAMOND_ABI,
905
+ functionName: "isBlocked",
906
+ args: [campaignId, recipient]
907
+ });
908
+ return result;
909
+ }
910
+ /**
911
+ * Get vested amount for a recipient (how much has vested so far)
912
+ */
913
+ async getVestedAmount(campaignId, recipient, allocation) {
914
+ const result = await this.publicClient.readContract({
915
+ address: this.diamondAddress,
916
+ abi: DIAMOND_ABI,
917
+ functionName: "vestedAmount",
918
+ args: [campaignId, recipient, allocation]
919
+ });
920
+ return result;
921
+ }
922
+ /**
923
+ * Get merkle claimed shares for a recipient
924
+ */
925
+ async getMerkleClaimedShares(campaignId, recipient) {
926
+ const result = await this.publicClient.readContract({
927
+ address: this.diamondAddress,
928
+ abi: DIAMOND_ABI,
929
+ functionName: "merkleClaimedShares",
930
+ args: [campaignId, recipient]
931
+ });
932
+ return result;
933
+ }
934
+ /**
935
+ * Get detailed recipient status for a campaign
936
+ */
937
+ async getRecipientStatus(campaignId, recipient, allocation) {
938
+ const [claimable, blocked, vested, claimed] = await Promise.all([
939
+ this.getClaimable(campaignId, recipient),
940
+ this.isBlocked(campaignId, recipient),
941
+ this.getVestedAmount(campaignId, recipient, allocation),
942
+ this.getMerkleClaimedShares(campaignId, recipient)
943
+ ]);
944
+ return {
945
+ allocated: allocation,
946
+ claimed,
947
+ due: claimable,
948
+ blocked,
949
+ fullyVested: vested >= allocation
950
+ };
951
+ }
952
+ /**
953
+ * Check if a recipient can claim from a campaign
954
+ */
955
+ async canClaim(campaignId, recipient) {
956
+ try {
957
+ const [claimable, blocked] = await Promise.all([
958
+ this.getClaimable(campaignId, recipient),
959
+ this.isBlocked(campaignId, recipient)
960
+ ]);
961
+ return claimable > 0n && !blocked;
962
+ } catch {
963
+ return false;
964
+ }
965
+ }
966
+ // ============================================================================
967
+ // Merkle Proof Helpers
968
+ // ============================================================================
969
+ /**
970
+ * Verify a Merkle proof locally
971
+ *
972
+ * Useful for validating proofs before submitting transactions.
973
+ */
974
+ verifyMerkleProof(root, leaf, proof) {
975
+ let computedHash = leaf;
976
+ for (const proofElement of proof) {
977
+ if (computedHash < proofElement) {
978
+ computedHash = keccak256(
979
+ encodePacked(["bytes32", "bytes32"], [computedHash, proofElement])
980
+ );
981
+ } else {
982
+ computedHash = keccak256(
983
+ encodePacked(["bytes32", "bytes32"], [proofElement, computedHash])
984
+ );
985
+ }
986
+ }
987
+ return computedHash === root;
988
+ }
989
+ /**
990
+ * Compute Merkle leaf for an allocation
991
+ */
992
+ computeMerkleLeaf(address, amount) {
993
+ return keccak256(encodePacked(["address", "uint256"], [address, amount]));
994
+ }
995
+ /**
996
+ * Compute proof hash for meta-transaction
997
+ */
998
+ computeProofHash(proof) {
999
+ if (proof.length === 0) {
1000
+ return "0x0000000000000000000000000000000000000000000000000000000000000000";
1001
+ }
1002
+ return keccak256(encodePacked(["bytes32[]"], [proof]));
1003
+ }
1004
+ // ============================================================================
1005
+ // Helpers
1006
+ // ============================================================================
1007
+ requireWallet() {
1008
+ if (!this.walletClient) {
1009
+ throw new Error(
1010
+ "Wallet client required for write operations. Initialize SDK with a signer."
1011
+ );
1012
+ }
1013
+ return this.walletClient;
1014
+ }
1015
+ createTransactionResult(hash) {
1016
+ return {
1017
+ hash,
1018
+ wait: async () => {
1019
+ const receipt = await this.publicClient.waitForTransactionReceipt({
1020
+ hash
1021
+ });
1022
+ return {
1023
+ blockNumber: receipt.blockNumber,
1024
+ transactionHash: receipt.transactionHash,
1025
+ gasUsed: receipt.gasUsed,
1026
+ status: receipt.status,
1027
+ logs: receipt.logs
1028
+ };
1029
+ }
1030
+ };
1031
+ }
1032
+ };
1033
+ var StakingModule = class {
1034
+ constructor(publicClient, walletClient, diamondAddress) {
1035
+ this.publicClient = publicClient;
1036
+ this.walletClient = walletClient;
1037
+ this.diamondAddress = diamondAddress;
1038
+ }
1039
+ // ============================================================================
1040
+ // Staking Operations
1041
+ // ============================================================================
1042
+ /**
1043
+ * Stake tokens in a pool
1044
+ *
1045
+ * Must approve the Diamond contract first.
1046
+ *
1047
+ * @example
1048
+ * ```typescript
1049
+ * await sdk.approve(stakeToken, amount);
1050
+ * const result = await sdk.staking.stake(poolId, amount);
1051
+ * ```
1052
+ */
1053
+ async stake(poolId, amount) {
1054
+ const wallet = this.requireWallet();
1055
+ const hash = await wallet.writeContract({
1056
+ chain: wallet.chain,
1057
+ account: wallet.account,
1058
+ address: this.diamondAddress,
1059
+ abi: DIAMOND_ABI,
1060
+ functionName: "stake",
1061
+ args: [poolId, amount]
1062
+ });
1063
+ return this.createTransactionResult(hash);
1064
+ }
1065
+ /**
1066
+ * Increase stake in an existing deposit
1067
+ */
1068
+ async increaseStake(poolId, amount) {
1069
+ const wallet = this.requireWallet();
1070
+ const hash = await wallet.writeContract({
1071
+ chain: wallet.chain,
1072
+ account: wallet.account,
1073
+ address: this.diamondAddress,
1074
+ abi: DIAMOND_ABI,
1075
+ functionName: "increaseStake",
1076
+ args: [poolId, amount]
1077
+ });
1078
+ return this.createTransactionResult(hash);
1079
+ }
1080
+ /**
1081
+ * Unstake all tokens from a pool
1082
+ *
1083
+ * Automatically claims pending rewards.
1084
+ *
1085
+ * @example
1086
+ * ```typescript
1087
+ * const result = await sdk.staking.unstake(poolId);
1088
+ * ```
1089
+ */
1090
+ async unstake(poolId) {
1091
+ const wallet = this.requireWallet();
1092
+ const hash = await wallet.writeContract({
1093
+ chain: wallet.chain,
1094
+ account: wallet.account,
1095
+ address: this.diamondAddress,
1096
+ abi: DIAMOND_ABI,
1097
+ functionName: "unstake",
1098
+ args: [poolId]
1099
+ });
1100
+ return this.createTransactionResult(hash);
1101
+ }
1102
+ /**
1103
+ * Partial unstake - withdraw some tokens but keep position open
1104
+ */
1105
+ async partialUnstake(poolId, amount) {
1106
+ const wallet = this.requireWallet();
1107
+ const hash = await wallet.writeContract({
1108
+ chain: wallet.chain,
1109
+ account: wallet.account,
1110
+ address: this.diamondAddress,
1111
+ abi: DIAMOND_ABI,
1112
+ functionName: "partialUnstake",
1113
+ args: [poolId, amount]
1114
+ });
1115
+ return this.createTransactionResult(hash);
1116
+ }
1117
+ /**
1118
+ * Emergency unstake - forfeit rewards but get principal back
1119
+ *
1120
+ * Use when pool has issues or you need immediate exit.
1121
+ */
1122
+ async emergencyUnstake(poolId) {
1123
+ const wallet = this.requireWallet();
1124
+ const hash = await wallet.writeContract({
1125
+ chain: wallet.chain,
1126
+ account: wallet.account,
1127
+ address: this.diamondAddress,
1128
+ abi: DIAMOND_ABI,
1129
+ functionName: "emergencyUnstake",
1130
+ args: [poolId]
1131
+ });
1132
+ return this.createTransactionResult(hash);
1133
+ }
1134
+ // ============================================================================
1135
+ // Pool Queries
1136
+ // ============================================================================
1137
+ /**
1138
+ * Get pool information
1139
+ *
1140
+ * @example
1141
+ * ```typescript
1142
+ * const pool = await sdk.staking.getPool(1n);
1143
+ * console.log('Total staked:', formatEther(pool.totalStaked));
1144
+ * ```
1145
+ */
1146
+ async getPool(poolId) {
1147
+ const result = await this.publicClient.readContract({
1148
+ address: this.diamondAddress,
1149
+ abi: DIAMOND_ABI,
1150
+ functionName: "pools",
1151
+ args: [poolId]
1152
+ });
1153
+ return this.parsePoolInfo(poolId, result);
1154
+ }
1155
+ /**
1156
+ * Get total number of staking pools
1157
+ */
1158
+ async getPoolCount() {
1159
+ const result = await this.publicClient.readContract({
1160
+ address: this.diamondAddress,
1161
+ abi: DIAMOND_ABI,
1162
+ functionName: "poolCount",
1163
+ args: []
1164
+ });
1165
+ return result;
1166
+ }
1167
+ /**
1168
+ * Get pool stats (runtime state)
1169
+ */
1170
+ async getPoolStats(poolId) {
1171
+ const result = await this.publicClient.readContract({
1172
+ address: this.diamondAddress,
1173
+ abi: DIAMOND_ABI,
1174
+ functionName: "poolStats",
1175
+ args: [poolId]
1176
+ });
1177
+ return {
1178
+ statusBits: result[0],
1179
+ rewardRemaining: result[1],
1180
+ totalStaked: result[2],
1181
+ endAt: Number(result[4]),
1182
+ finalized: result[6],
1183
+ rewardRatePerSecond: result[9]
1184
+ };
1185
+ }
1186
+ // ============================================================================
1187
+ // User Stake Queries
1188
+ // ============================================================================
1189
+ /**
1190
+ * Get user's deposit info for a pool
1191
+ *
1192
+ * @example
1193
+ * ```typescript
1194
+ * const stake = await sdk.staking.getUserDeposit(poolId, address);
1195
+ * console.log('Staked:', formatEther(stake.amount));
1196
+ * ```
1197
+ */
1198
+ async getUserDeposit(poolId, user) {
1199
+ const result = await this.publicClient.readContract({
1200
+ address: this.diamondAddress,
1201
+ abi: DIAMOND_ABI,
1202
+ functionName: "deposits",
1203
+ args: [poolId, user]
1204
+ });
1205
+ return {
1206
+ amount: result.amount,
1207
+ startAt: Number(result.startAt),
1208
+ rewardDebtRay: result.rewardDebtRay,
1209
+ claimedReward: result.claimedReward,
1210
+ claimedAt: Number(result.claimedAt),
1211
+ active: result.active
1212
+ };
1213
+ }
1214
+ /**
1215
+ * Get comprehensive deposit status for a user
1216
+ */
1217
+ async getDepositStatus(poolId, user) {
1218
+ const result = await this.publicClient.readContract({
1219
+ address: this.diamondAddress,
1220
+ abi: DIAMOND_ABI,
1221
+ functionName: "depositStatus",
1222
+ args: [poolId, user]
1223
+ });
1224
+ return {
1225
+ active: result[0],
1226
+ stakedAmount: result[1],
1227
+ pendingRewards: result[2],
1228
+ canUnstakeNow: result[3],
1229
+ secondsUntilUnstake: Number(result[4]),
1230
+ totalClaimed: result[5]
1231
+ };
1232
+ }
1233
+ /**
1234
+ * Get pending rewards for a user in a pool
1235
+ */
1236
+ async getPendingRewards(poolId, user) {
1237
+ const result = await this.publicClient.readContract({
1238
+ address: this.diamondAddress,
1239
+ abi: DIAMOND_ABI,
1240
+ functionName: "pendingReward",
1241
+ args: [poolId, user]
1242
+ });
1243
+ return result;
1244
+ }
1245
+ /**
1246
+ * Check if user can unstake from a pool
1247
+ */
1248
+ async canUnstake(poolId, user) {
1249
+ const result = await this.publicClient.readContract({
1250
+ address: this.diamondAddress,
1251
+ abi: DIAMOND_ABI,
1252
+ functionName: "canUnstake",
1253
+ args: [poolId, user]
1254
+ });
1255
+ return result;
1256
+ }
1257
+ /**
1258
+ * Get time until user can unstake
1259
+ */
1260
+ async secondsUntilUnstakeable(poolId, user) {
1261
+ const result = await this.publicClient.readContract({
1262
+ address: this.diamondAddress,
1263
+ abi: DIAMOND_ABI,
1264
+ functionName: "secondsUntilUnstakeable",
1265
+ args: [poolId, user]
1266
+ });
1267
+ return result;
1268
+ }
1269
+ /**
1270
+ * Get user's stake info for a pool (convenience wrapper)
1271
+ *
1272
+ * @example
1273
+ * ```typescript
1274
+ * const stake = await sdk.staking.getUserStake(poolId, address);
1275
+ * console.log('Staked:', formatEther(stake.amount));
1276
+ * console.log('Pending rewards:', formatEther(stake.pendingRewards));
1277
+ * ```
1278
+ */
1279
+ async getUserStake(poolId, user) {
1280
+ const [deposit, pendingRewards] = await Promise.all([
1281
+ this.getUserDeposit(poolId, user),
1282
+ this.getPendingRewards(poolId, user)
1283
+ ]);
1284
+ return {
1285
+ amount: deposit.amount,
1286
+ pendingRewards,
1287
+ lastClaimTime: deposit.claimedAt,
1288
+ stakeTime: deposit.startAt
1289
+ };
1290
+ }
1291
+ // ============================================================================
1292
+ // Utility Functions
1293
+ // ============================================================================
1294
+ /**
1295
+ * Get APY preview for a pool
1296
+ */
1297
+ async getApyPreview(poolId) {
1298
+ const result = await this.publicClient.readContract({
1299
+ address: this.diamondAddress,
1300
+ abi: DIAMOND_ABI,
1301
+ functionName: "apyPreview",
1302
+ args: [poolId]
1303
+ });
1304
+ return {
1305
+ ratePerSecond: result[0],
1306
+ totalStaked: result[1]
1307
+ };
1308
+ }
1309
+ /**
1310
+ * Calculate APY for a pool
1311
+ *
1312
+ * @example
1313
+ * ```typescript
1314
+ * const pool = await sdk.staking.getPool(poolId);
1315
+ * const apy = sdk.staking.calculateApy(pool);
1316
+ * console.log('APY:', apy.toFixed(2), '%');
1317
+ * ```
1318
+ */
1319
+ calculateApy(pool) {
1320
+ if (pool.totalStaked === 0n) {
1321
+ return 0;
1322
+ }
1323
+ const durationInYears = (pool.endTime - pool.startTime) / (365 * 24 * 60 * 60);
1324
+ const rewardRate = Number(pool.rewardBudget) / Number(pool.totalStaked);
1325
+ return rewardRate / durationInYears * 100;
1326
+ }
1327
+ // ============================================================================
1328
+ // Helpers
1329
+ // ============================================================================
1330
+ requireWallet() {
1331
+ if (!this.walletClient) {
1332
+ throw new Error(
1333
+ "Wallet client required for write operations. Initialize SDK with a signer."
1334
+ );
1335
+ }
1336
+ return this.walletClient;
1337
+ }
1338
+ parsePoolInfo(id, data) {
1339
+ return {
1340
+ id,
1341
+ stakeToken: data.stake,
1342
+ rewardToken: data.reward,
1343
+ creator: data.creator,
1344
+ totalStaked: data.totalStaked,
1345
+ rewardBudget: data.rewardRemaining,
1346
+ // Current remaining
1347
+ rewardsDistributed: 0n,
1348
+ // Not directly available
1349
+ startTime: 0,
1350
+ // Not in pool struct
1351
+ endTime: Number(data.endAt),
1352
+ minStake: 0n,
1353
+ // Not in pool struct
1354
+ maxStake: data.cap,
1355
+ stakerCount: 0,
1356
+ // Not in pool struct
1357
+ isActive: !(data.statusBits > 0),
1358
+ isFinalized: data.finalized
1359
+ };
1360
+ }
1361
+ createTransactionResult(hash) {
1362
+ return {
1363
+ hash,
1364
+ wait: async () => {
1365
+ const receipt = await this.publicClient.waitForTransactionReceipt({
1366
+ hash
1367
+ });
1368
+ return {
1369
+ blockNumber: receipt.blockNumber,
1370
+ transactionHash: receipt.transactionHash,
1371
+ gasUsed: receipt.gasUsed,
1372
+ status: receipt.status,
1373
+ logs: receipt.logs
1374
+ };
1375
+ }
1376
+ };
1377
+ }
1378
+ };
1379
+ var MarketplaceModule = class {
1380
+ constructor(publicClient, walletClient, diamondAddress) {
1381
+ this.publicClient = publicClient;
1382
+ this.walletClient = walletClient;
1383
+ this.diamondAddress = diamondAddress;
1384
+ }
1385
+ // ============================================================================
1386
+ // Order Creation
1387
+ // ============================================================================
1388
+ /**
1389
+ * Create an INSTANT order
1390
+ *
1391
+ * Seller deposits tokens upfront, buyer pays and receives immediately.
1392
+ *
1393
+ * @example
1394
+ * ```typescript
1395
+ * // Approve first
1396
+ * await sdk.approve(sellToken, amount);
1397
+ *
1398
+ * const result = await sdk.marketplace.createInstantOrder({
1399
+ * sellToken: '0x...',
1400
+ * sellAmount: parseEther('1000'),
1401
+ * payToken: zeroAddress, // Native ETH
1402
+ * pricePerToken: parseEther('0.001'), // 0.001 ETH per token
1403
+ * expiryTTL: 7 * 24 * 60 * 60, // 7 days
1404
+ * });
1405
+ * ```
1406
+ */
1407
+ async createInstantOrder(params) {
1408
+ const wallet = this.requireWallet();
1409
+ const visibility = params.privateBuyers && params.privateBuyers.length > 0 ? 1 /* PRIVATE */ : 0 /* PUBLIC */;
1410
+ const expiry = BigInt(
1411
+ Math.floor(Date.now() / 1e3) + (params.expiryTTL ?? 7 * 24 * 60 * 60)
1412
+ );
1413
+ const args = {
1414
+ payToken: params.payToken,
1415
+ price: params.pricePerToken,
1416
+ sellToken: params.sellToken,
1417
+ sellAmount: params.sellAmount,
1418
+ visibility,
1419
+ allowedBuyers: params.privateBuyers ?? [],
1420
+ expiry
1421
+ };
1422
+ const hash = await wallet.writeContract({
1423
+ chain: wallet.chain,
1424
+ account: wallet.account,
1425
+ address: this.diamondAddress,
1426
+ abi: DIAMOND_ABI,
1427
+ functionName: "createOrderInstant",
1428
+ args: [args]
1429
+ });
1430
+ return this.createTransactionResult(hash);
1431
+ }
1432
+ /**
1433
+ * Create a VESTED order
1434
+ *
1435
+ * Seller deposits tokens that vest over time for the buyer.
1436
+ *
1437
+ * @example
1438
+ * ```typescript
1439
+ * const result = await sdk.marketplace.createVestedOrder({
1440
+ * sellToken: '0x...',
1441
+ * sellAmount: parseEther('10000'),
1442
+ * payToken: '0x...', // USDC
1443
+ * pricePerToken: 1000000n, // 1 USDC (6 decimals)
1444
+ * vestingDuration: 365 * 24 * 60 * 60, // 1 year
1445
+ * cliffDuration: 30 * 24 * 60 * 60, // 30 day cliff
1446
+ * startMode: 'upon_fill', // Vesting starts when order is filled
1447
+ * });
1448
+ * ```
1449
+ */
1450
+ async createVestedOrder(params) {
1451
+ const wallet = this.requireWallet();
1452
+ const visibility = params.privateBuyers && params.privateBuyers.length > 0 ? 1 /* PRIVATE */ : 0 /* PUBLIC */;
1453
+ const expiry = BigInt(
1454
+ Math.floor(Date.now() / 1e3) + (params.expiryTTL ?? 7 * 24 * 60 * 60)
1455
+ );
1456
+ const cliffBps = params.cliffDuration && params.vestingDuration ? Math.floor(params.cliffDuration / params.vestingDuration * 1e4) : 0;
1457
+ const args = {
1458
+ payToken: params.payToken,
1459
+ price: params.pricePerToken,
1460
+ sellToken: params.sellToken,
1461
+ sellAmount: params.sellAmount,
1462
+ visibility,
1463
+ allowedBuyers: params.privateBuyers ?? [],
1464
+ expiry,
1465
+ vest: {
1466
+ startMode: params.startMode === "fixed_timestamp" ? 1 /* FIXED_TIMESTAMP */ : 0 /* UPON_FILL */,
1467
+ startAt: BigInt(params.fixedStartTime ?? 0),
1468
+ durationSec: params.vestingDuration,
1469
+ stepSec: 0,
1470
+ // Linear vesting
1471
+ cliffBps
1472
+ }
1473
+ };
1474
+ const hash = await wallet.writeContract({
1475
+ chain: wallet.chain,
1476
+ account: wallet.account,
1477
+ address: this.diamondAddress,
1478
+ abi: DIAMOND_ABI,
1479
+ functionName: "createOrderVested",
1480
+ args: [args]
1481
+ });
1482
+ return this.createTransactionResult(hash);
1483
+ }
1484
+ /**
1485
+ * Create a TRADABLE order
1486
+ *
1487
+ * List an unvested campaign position for sale. No upfront deposit -
1488
+ * the position is transferred when the order is filled.
1489
+ *
1490
+ * @example
1491
+ * ```typescript
1492
+ * // Must have a position in a VestedAirdrop campaign with trading enabled
1493
+ * const result = await sdk.marketplace.createTradableOrder({
1494
+ * campaignId: 10n,
1495
+ * pricePerToken: parseEther('0.05'), // 0.05 ETH per token
1496
+ * payToken: zeroAddress, // Native ETH
1497
+ * expiryTTL: 30 * 24 * 60 * 60, // 30 days
1498
+ * });
1499
+ * console.log('Order created, tx:', result.hash);
1500
+ * ```
1501
+ */
1502
+ async createTradableOrder(params) {
1503
+ const wallet = this.requireWallet();
1504
+ const visibility = params.privateBuyers && params.privateBuyers.length > 0 ? 1 /* PRIVATE */ : 0 /* PUBLIC */;
1505
+ const expiry = BigInt(
1506
+ Math.floor(Date.now() / 1e3) + (params.expiryTTL ?? 30 * 24 * 60 * 60)
1507
+ );
1508
+ const args = {
1509
+ payToken: params.payToken,
1510
+ price: params.pricePerToken,
1511
+ campaignId: params.campaignId,
1512
+ visibility,
1513
+ allowedBuyers: params.privateBuyers ?? [],
1514
+ expiry,
1515
+ escrowRouting: zeroAddress
1516
+ // Default to no escrow routing
1517
+ };
1518
+ const hash = await wallet.writeContract({
1519
+ chain: wallet.chain,
1520
+ account: wallet.account,
1521
+ address: this.diamondAddress,
1522
+ abi: DIAMOND_ABI,
1523
+ functionName: "createOrderTradable",
1524
+ args: [args]
1525
+ });
1526
+ return this.createTransactionResult(hash);
1527
+ }
1528
+ // ============================================================================
1529
+ // Order Settlement
1530
+ // ============================================================================
1531
+ /**
1532
+ * Fill an order (buy)
1533
+ *
1534
+ * For native payment orders, send ETH as value.
1535
+ * For token payment orders, approve the Diamond first.
1536
+ *
1537
+ * @example
1538
+ * ```typescript
1539
+ * // Get quote first
1540
+ * const quote = await sdk.marketplace.getQuote(orderId);
1541
+ *
1542
+ * // Fill with native ETH
1543
+ * const result = await sdk.marketplace.fillOrder(orderId, {
1544
+ * value: quote.totalPrice,
1545
+ * });
1546
+ *
1547
+ * // Or fill with ERC20 (approve first)
1548
+ * await sdk.approve(payToken, quote.totalPrice);
1549
+ * await sdk.marketplace.fillOrder(orderId);
1550
+ * ```
1551
+ */
1552
+ async fillOrder(orderId, options) {
1553
+ const wallet = this.requireWallet();
1554
+ const hash = await wallet.writeContract({
1555
+ chain: wallet.chain,
1556
+ account: wallet.account,
1557
+ address: this.diamondAddress,
1558
+ abi: DIAMOND_ABI,
1559
+ functionName: "fillOrder",
1560
+ args: [orderId],
1561
+ value: options?.value
1562
+ });
1563
+ return this.createTransactionResult(hash);
1564
+ }
1565
+ /**
1566
+ * Fill an order using Permit2 (gasless token approval)
1567
+ */
1568
+ async fillOrderWithPermit(params) {
1569
+ const wallet = this.requireWallet();
1570
+ const hash = await wallet.writeContract({
1571
+ chain: wallet.chain,
1572
+ account: wallet.account,
1573
+ address: this.diamondAddress,
1574
+ abi: DIAMOND_ABI,
1575
+ functionName: "fillOrderWithPermit",
1576
+ args: [params.orderId, params.permit2Payload]
1577
+ });
1578
+ return this.createTransactionResult(hash);
1579
+ }
1580
+ /**
1581
+ * Cancel an order (seller only)
1582
+ *
1583
+ * Returns deposited tokens to seller.
1584
+ *
1585
+ * @example
1586
+ * ```typescript
1587
+ * const result = await sdk.marketplace.cancelOrder(orderId);
1588
+ * ```
1589
+ */
1590
+ async cancelOrder(orderId) {
1591
+ const wallet = this.requireWallet();
1592
+ const hash = await wallet.writeContract({
1593
+ chain: wallet.chain,
1594
+ account: wallet.account,
1595
+ address: this.diamondAddress,
1596
+ abi: DIAMOND_ABI,
1597
+ functionName: "cancelOrder",
1598
+ args: [orderId]
1599
+ });
1600
+ return this.createTransactionResult(hash);
1601
+ }
1602
+ /**
1603
+ * Expire an order (anyone can call after expiry)
1604
+ *
1605
+ * Returns deposited tokens to seller.
1606
+ */
1607
+ async expireOrder(orderId) {
1608
+ const wallet = this.requireWallet();
1609
+ const hash = await wallet.writeContract({
1610
+ chain: wallet.chain,
1611
+ account: wallet.account,
1612
+ address: this.diamondAddress,
1613
+ abi: DIAMOND_ABI,
1614
+ functionName: "expireOrder",
1615
+ args: [orderId]
1616
+ });
1617
+ return this.createTransactionResult(hash);
1618
+ }
1619
+ // ============================================================================
1620
+ // Order Queries
1621
+ // ============================================================================
1622
+ /**
1623
+ * Get order information by ID
1624
+ *
1625
+ * @example
1626
+ * ```typescript
1627
+ * const order = await sdk.marketplace.getOrder(1n);
1628
+ * console.log('Seller:', order.seller);
1629
+ * console.log('Price:', formatEther(order.totalPrice));
1630
+ * console.log('Status:', order.status);
1631
+ * ```
1632
+ */
1633
+ async getOrder(orderId) {
1634
+ const result = await this.publicClient.readContract({
1635
+ address: this.diamondAddress,
1636
+ abi: DIAMOND_ABI,
1637
+ functionName: "getOrder",
1638
+ args: [orderId]
1639
+ });
1640
+ return this.parseOrderInfo(result);
1641
+ }
1642
+ /**
1643
+ * Get order quote (price breakdown)
1644
+ *
1645
+ * @example
1646
+ * ```typescript
1647
+ * const quote = await sdk.marketplace.getQuote(orderId);
1648
+ * console.log('Total price:', formatEther(quote.totalPrice));
1649
+ * console.log('Protocol fee:', formatEther(quote.protocolFee));
1650
+ * ```
1651
+ */
1652
+ async getQuote(orderId) {
1653
+ const result = await this.publicClient.readContract({
1654
+ address: this.diamondAddress,
1655
+ abi: DIAMOND_ABI,
1656
+ functionName: "quote",
1657
+ args: [orderId]
1658
+ });
1659
+ const order = await this.getOrder(orderId);
1660
+ return {
1661
+ orderId,
1662
+ totalPrice: result.price,
1663
+ protocolFee: result.feeAmount,
1664
+ buyerReceives: order.sellAmount,
1665
+ sellerReceives: result.proceeds,
1666
+ isValid: order.status === "open" && order.expiresAt > Math.floor(Date.now() / 1e3),
1667
+ expiresAt: order.expiresAt
1668
+ };
1669
+ }
1670
+ /**
1671
+ * Get detailed quote for filling an order
1672
+ */
1673
+ async getQuoteFill(orderId) {
1674
+ const result = await this.publicClient.readContract({
1675
+ address: this.diamondAddress,
1676
+ abi: DIAMOND_ABI,
1677
+ functionName: "quoteFill",
1678
+ args: [orderId]
1679
+ });
1680
+ return result;
1681
+ }
1682
+ /**
1683
+ * Get next order ID (also indicates total orders created)
1684
+ */
1685
+ async getNextOrderId() {
1686
+ const result = await this.publicClient.readContract({
1687
+ address: this.diamondAddress,
1688
+ abi: DIAMOND_ABI,
1689
+ functionName: "nextOrderId",
1690
+ args: []
1691
+ });
1692
+ return result;
1693
+ }
1694
+ /**
1695
+ * Get orders by seller with pagination
1696
+ */
1697
+ async getOrdersBySeller(seller, offset = 0, limit = 100) {
1698
+ const result = await this.publicClient.readContract({
1699
+ address: this.diamondAddress,
1700
+ abi: DIAMOND_ABI,
1701
+ functionName: "ordersOf",
1702
+ args: [seller, BigInt(offset), BigInt(limit)]
1703
+ });
1704
+ return result.map((order) => this.parseOrderInfo(order));
1705
+ }
1706
+ /**
1707
+ * Get orders for a campaign
1708
+ */
1709
+ async getOrdersForCampaign(campaignId) {
1710
+ const result = await this.publicClient.readContract({
1711
+ address: this.diamondAddress,
1712
+ abi: DIAMOND_ABI,
1713
+ functionName: "ordersByCampaign",
1714
+ args: [campaignId]
1715
+ });
1716
+ return result;
1717
+ }
1718
+ /**
1719
+ * Get active order for a campaign
1720
+ */
1721
+ async getActiveOrderForCampaign(campaignId) {
1722
+ const result = await this.publicClient.readContract({
1723
+ address: this.diamondAddress,
1724
+ abi: DIAMOND_ABI,
1725
+ functionName: "getActiveOrderForCampaign",
1726
+ args: [campaignId]
1727
+ });
1728
+ return result;
1729
+ }
1730
+ /**
1731
+ * Preview available amount to sell for a campaign
1732
+ */
1733
+ async previewAvailableToSell(campaignId) {
1734
+ const result = await this.publicClient.readContract({
1735
+ address: this.diamondAddress,
1736
+ abi: DIAMOND_ABI,
1737
+ functionName: "previewAvailableToSell",
1738
+ args: [campaignId]
1739
+ });
1740
+ return {
1741
+ futureUnlockable: result.futureUnlockable,
1742
+ claimableNow: result.claimableNow,
1743
+ asOf: Number(result.asOf)
1744
+ };
1745
+ }
1746
+ /**
1747
+ * Get all open orders
1748
+ */
1749
+ async getOpenOrders(limit = 100) {
1750
+ const nextId = await this.getNextOrderId();
1751
+ const orders = [];
1752
+ for (let i = 0n; i < nextId && orders.length < limit; i++) {
1753
+ try {
1754
+ const order = await this.getOrder(i);
1755
+ if (order.status === "open") {
1756
+ orders.push(order);
1757
+ }
1758
+ } catch {
1759
+ }
1760
+ }
1761
+ return orders;
1762
+ }
1763
+ // ============================================================================
1764
+ // Validation
1765
+ // ============================================================================
1766
+ /**
1767
+ * Check if trading is allowed for a campaign
1768
+ */
1769
+ async isTradingEnabled(campaignId) {
1770
+ const result = await this.publicClient.readContract({
1771
+ address: this.diamondAddress,
1772
+ abi: DIAMOND_ABI,
1773
+ functionName: "isTradeLocked",
1774
+ args: [campaignId]
1775
+ });
1776
+ return !result;
1777
+ }
1778
+ // ============================================================================
1779
+ // Trade Policy (Creator Functions)
1780
+ // ============================================================================
1781
+ /**
1782
+ * Lock trading for a campaign (creator only)
1783
+ *
1784
+ * Prevents new orders from being created for this campaign.
1785
+ */
1786
+ async lockTrading(campaignId) {
1787
+ const wallet = this.requireWallet();
1788
+ const hash = await wallet.writeContract({
1789
+ chain: wallet.chain,
1790
+ account: wallet.account,
1791
+ address: this.diamondAddress,
1792
+ abi: DIAMOND_ABI,
1793
+ functionName: "setTradeLocked",
1794
+ args: [campaignId, true]
1795
+ });
1796
+ return this.createTransactionResult(hash);
1797
+ }
1798
+ /**
1799
+ * Unlock trading for a campaign (creator only)
1800
+ */
1801
+ async unlockTrading(campaignId) {
1802
+ const wallet = this.requireWallet();
1803
+ const hash = await wallet.writeContract({
1804
+ chain: wallet.chain,
1805
+ account: wallet.account,
1806
+ address: this.diamondAddress,
1807
+ abi: DIAMOND_ABI,
1808
+ functionName: "setTradeLocked",
1809
+ args: [campaignId, false]
1810
+ });
1811
+ return this.createTransactionResult(hash);
1812
+ }
1813
+ // ============================================================================
1814
+ // Utility Functions
1815
+ // ============================================================================
1816
+ /**
1817
+ * Calculate total price for a given amount at price per token
1818
+ */
1819
+ calculateTotalPrice(amount, pricePerToken) {
1820
+ return amount * pricePerToken / BigInt(1e18);
1821
+ }
1822
+ /**
1823
+ * Check if payment is in native token (ETH/BNB/etc)
1824
+ */
1825
+ isNativePayment(payToken) {
1826
+ return payToken === zeroAddress;
1827
+ }
1828
+ // ============================================================================
1829
+ // Helpers
1830
+ // ============================================================================
1831
+ requireWallet() {
1832
+ if (!this.walletClient) {
1833
+ throw new Error(
1834
+ "Wallet client required for write operations. Initialize SDK with a signer."
1835
+ );
1836
+ }
1837
+ return this.walletClient;
1838
+ }
1839
+ parseOrderInfo(order) {
1840
+ const orderTypeMap = {
1841
+ 0: "instant",
1842
+ 1: "vested",
1843
+ 2: "tradable"
1844
+ };
1845
+ const statusMap = {
1846
+ 0: "open",
1847
+ 1: "filled",
1848
+ 2: "canceled",
1849
+ 3: "expired"
1850
+ };
1851
+ const result = {
1852
+ id: order.id,
1853
+ orderType: orderTypeMap[order.kind] ?? "instant",
1854
+ seller: order.seller,
1855
+ sellToken: order.sellToken,
1856
+ sellAmount: order.sellAmount,
1857
+ payToken: order.payToken,
1858
+ totalPrice: order.price,
1859
+ pricePerToken: order.sellAmount > 0n ? order.price * BigInt(1e18) / order.sellAmount : 0n,
1860
+ status: statusMap[order.status] ?? "open",
1861
+ createdAt: 0,
1862
+ // Not stored in Order struct
1863
+ expiresAt: Number(order.expiry)
1864
+ };
1865
+ if (order.campaignId > 0n) {
1866
+ result.campaignId = order.campaignId;
1867
+ }
1868
+ if (order.vest.durationSec > 0) {
1869
+ result.vestingDuration = order.vest.durationSec;
1870
+ }
1871
+ if (order.vest.cliffBps > 0) {
1872
+ result.cliffDuration = Math.floor(order.vest.durationSec * order.vest.cliffBps / 1e4);
1873
+ }
1874
+ return result;
1875
+ }
1876
+ createTransactionResult(hash) {
1877
+ return {
1878
+ hash,
1879
+ wait: async () => {
1880
+ const receipt = await this.publicClient.waitForTransactionReceipt({
1881
+ hash
1882
+ });
1883
+ return {
1884
+ blockNumber: receipt.blockNumber,
1885
+ transactionHash: receipt.transactionHash,
1886
+ gasUsed: receipt.gasUsed,
1887
+ status: receipt.status,
1888
+ logs: receipt.logs
1889
+ };
1890
+ }
1891
+ };
1892
+ }
1893
+ };
1894
+ var AutomationModule = class {
1895
+ constructor(publicClient, walletClient, diamondAddress) {
1896
+ this.publicClient = publicClient;
1897
+ this.walletClient = walletClient;
1898
+ this.diamondAddress = diamondAddress;
1899
+ }
1900
+ // ============================================================================
1901
+ // Auto-Withdraw (for Vesting campaigns)
1902
+ // ============================================================================
1903
+ /**
1904
+ * Enable auto-withdraw for a vesting campaign
1905
+ *
1906
+ * Keepers will automatically claim vested tokens on behalf of recipients.
1907
+ *
1908
+ * @example
1909
+ * ```typescript
1910
+ * const result = await sdk.automation.enableAutoWithdraw({
1911
+ * campaignId: 1n,
1912
+ * frequency: 7 * 24 * 60 * 60, // Weekly
1913
+ * tipAmount: parseEther('0.1'), // 0.1 ETH for keeper
1914
+ * });
1915
+ * ```
1916
+ */
1917
+ async enableAutoWithdraw(params) {
1918
+ const wallet = this.requireWallet();
1919
+ const hash = await wallet.writeContract({
1920
+ chain: wallet.chain,
1921
+ account: wallet.account,
1922
+ address: this.diamondAddress,
1923
+ abi: DIAMOND_ABI,
1924
+ functionName: "enableAutoWithdraw",
1925
+ args: [params.campaignId, BigInt(params.frequency)],
1926
+ value: params.tipAmount ?? 0n
1927
+ });
1928
+ return this.createTransactionResult(hash);
1929
+ }
1930
+ /**
1931
+ * Disable auto-withdraw for a campaign
1932
+ *
1933
+ * Returns remaining tip balance to caller.
1934
+ */
1935
+ async disableAutoWithdraw(campaignId) {
1936
+ const wallet = this.requireWallet();
1937
+ const hash = await wallet.writeContract({
1938
+ chain: wallet.chain,
1939
+ account: wallet.account,
1940
+ address: this.diamondAddress,
1941
+ abi: DIAMOND_ABI,
1942
+ functionName: "disableAutoWithdraw",
1943
+ args: [campaignId]
1944
+ });
1945
+ return this.createTransactionResult(hash);
1946
+ }
1947
+ // ============================================================================
1948
+ // Auto-Release (for Lock campaigns)
1949
+ // ============================================================================
1950
+ /**
1951
+ * Enable auto-release for a lock campaign
1952
+ *
1953
+ * Keepers will automatically release tokens when unlock time passes.
1954
+ *
1955
+ * @example
1956
+ * ```typescript
1957
+ * const result = await sdk.automation.enableAutoRelease({
1958
+ * campaignId: 5n,
1959
+ * frequency: 3600, // Check every hour
1960
+ * tipAmount: parseEther('0.05'), // 0.05 ETH for keeper
1961
+ * });
1962
+ * ```
1963
+ */
1964
+ async enableAutoRelease(params) {
1965
+ const wallet = this.requireWallet();
1966
+ const frequency = params.frequency ?? 3600;
1967
+ const hash = await wallet.writeContract({
1968
+ chain: wallet.chain,
1969
+ account: wallet.account,
1970
+ address: this.diamondAddress,
1971
+ abi: DIAMOND_ABI,
1972
+ functionName: "enableAutoReleaseLock",
1973
+ args: [params.campaignId, BigInt(frequency)],
1974
+ value: params.tipAmount ?? 0n
1975
+ });
1976
+ return this.createTransactionResult(hash);
1977
+ }
1978
+ /**
1979
+ * Disable auto-release for a lock campaign
1980
+ */
1981
+ async disableAutoRelease(campaignId) {
1982
+ const wallet = this.requireWallet();
1983
+ const hash = await wallet.writeContract({
1984
+ chain: wallet.chain,
1985
+ account: wallet.account,
1986
+ address: this.diamondAddress,
1987
+ abi: DIAMOND_ABI,
1988
+ functionName: "disableAutoReleaseLock",
1989
+ args: [campaignId]
1990
+ });
1991
+ return this.createTransactionResult(hash);
1992
+ }
1993
+ // ============================================================================
1994
+ // Automation Status Queries
1995
+ // ============================================================================
1996
+ /**
1997
+ * Get auto-withdraw status for a campaign
1998
+ *
1999
+ * @example
2000
+ * ```typescript
2001
+ * const status = await sdk.automation.getAutoWithdrawStatus(campaignId);
2002
+ * console.log('Enabled:', status.enabled);
2003
+ * console.log('Next run:', new Date(status.nextRun * 1000));
2004
+ * console.log('Tip balance:', formatEther(status.tipBalance));
2005
+ * ```
2006
+ */
2007
+ async getAutoWithdrawStatus(campaignId) {
2008
+ const [config, pendingCount, cursor] = await Promise.all([
2009
+ this.publicClient.readContract({
2010
+ address: this.diamondAddress,
2011
+ abi: DIAMOND_ABI,
2012
+ functionName: "automationConfig",
2013
+ args: [campaignId]
2014
+ }),
2015
+ this.publicClient.readContract({
2016
+ address: this.diamondAddress,
2017
+ abi: DIAMOND_ABI,
2018
+ functionName: "recipientsPending",
2019
+ args: [campaignId]
2020
+ }),
2021
+ this.publicClient.readContract({
2022
+ address: this.diamondAddress,
2023
+ abi: DIAMOND_ABI,
2024
+ functionName: "regCursor",
2025
+ args: [campaignId]
2026
+ })
2027
+ ]);
2028
+ const [enabled, frequency, lastRun] = config;
2029
+ const nextRun = Number(lastRun) + Number(frequency);
2030
+ return {
2031
+ enabled,
2032
+ lastRun: Number(lastRun),
2033
+ nextRun,
2034
+ frequency: Number(frequency),
2035
+ tipBalance: 0n,
2036
+ // Tip balance is managed internally
2037
+ recipientsProcessed: Number(cursor),
2038
+ totalRecipients: Number(pendingCount) + Number(cursor)
2039
+ };
2040
+ }
2041
+ /**
2042
+ * Get auto-release status for a lock campaign
2043
+ */
2044
+ async getAutoReleaseStatus(campaignId) {
2045
+ const config = await this.publicClient.readContract({
2046
+ address: this.diamondAddress,
2047
+ abi: DIAMOND_ABI,
2048
+ functionName: "automationLockConfig",
2049
+ args: [campaignId]
2050
+ });
2051
+ const [enabled, frequency, lastRun] = config;
2052
+ const nextRun = Number(lastRun) + Number(frequency);
2053
+ return {
2054
+ enabled,
2055
+ frequency: Number(frequency),
2056
+ lastRun: Number(lastRun),
2057
+ nextRun
2058
+ };
2059
+ }
2060
+ /**
2061
+ * Preview automation for specific recipients
2062
+ */
2063
+ async previewAutomation(campaignId, recipients) {
2064
+ const result = await this.publicClient.readContract({
2065
+ address: this.diamondAddress,
2066
+ abi: DIAMOND_ABI,
2067
+ functionName: "automationPreviewFor",
2068
+ args: [campaignId, recipients]
2069
+ });
2070
+ return {
2071
+ pendingCount: result[0],
2072
+ nextFeeWei: result[1],
2073
+ escrowWei: result[2]
2074
+ };
2075
+ }
2076
+ /**
2077
+ * Get automation run statistics
2078
+ */
2079
+ async getAutomationStats(campaignId, lockMode = false) {
2080
+ const result = await this.publicClient.readContract({
2081
+ address: this.diamondAddress,
2082
+ abi: DIAMOND_ABI,
2083
+ functionName: "automationRunStats",
2084
+ args: [campaignId, lockMode]
2085
+ });
2086
+ return {
2087
+ runsObserved: Number(result.runsObserved),
2088
+ avgRecipientsPerRun: Number(result.avgRecipientsPerRun),
2089
+ lastRecipientsProcessed: Number(result.lastRecipientsProcessed),
2090
+ maxRecipientsPerRun: Number(result.maxRecipientsPerRun)
2091
+ };
2092
+ }
2093
+ /**
2094
+ * Check if auto-withdraw is currently runnable
2095
+ *
2096
+ * Returns true if cooldown has passed and there are pending recipients.
2097
+ */
2098
+ async isAutoWithdrawRunnable(campaignId) {
2099
+ const status = await this.getAutoWithdrawStatus(campaignId);
2100
+ const now = Math.floor(Date.now() / 1e3);
2101
+ return status.enabled && now >= status.nextRun && status.recipientsProcessed < status.totalRecipients;
2102
+ }
2103
+ /**
2104
+ * Check if auto-release is currently runnable
2105
+ */
2106
+ async isAutoReleaseRunnable(campaignId) {
2107
+ const status = await this.getAutoReleaseStatus(campaignId);
2108
+ const now = Math.floor(Date.now() / 1e3);
2109
+ return status.enabled && now >= status.nextRun;
2110
+ }
2111
+ // ============================================================================
2112
+ // Keeper Functions (for automation operators)
2113
+ // ============================================================================
2114
+ /**
2115
+ * Execute auto-withdraw for specific recipients (keeper only)
2116
+ *
2117
+ * @example
2118
+ * ```typescript
2119
+ * // Get recipients from registry or external source
2120
+ * const recipients = ['0x...', '0x...', '0x...'];
2121
+ * await sdk.automation.executeAutoWithdraw(campaignId, recipients);
2122
+ * ```
2123
+ */
2124
+ async executeAutoWithdraw(campaignId, recipients) {
2125
+ const wallet = this.requireWallet();
2126
+ const hash = await wallet.writeContract({
2127
+ chain: wallet.chain,
2128
+ account: wallet.account,
2129
+ address: this.diamondAddress,
2130
+ abi: DIAMOND_ABI,
2131
+ functionName: "autoWithdraw",
2132
+ args: [campaignId, recipients]
2133
+ });
2134
+ return this.createTransactionResult(hash);
2135
+ }
2136
+ /**
2137
+ * Execute auto-withdraw using registry cursor (keeper only)
2138
+ *
2139
+ * Processes up to batchSize recipients from the registry.
2140
+ */
2141
+ async executeAutoWithdrawNext(campaignId, batchSize = 50) {
2142
+ const wallet = this.requireWallet();
2143
+ const hash = await wallet.writeContract({
2144
+ chain: wallet.chain,
2145
+ account: wallet.account,
2146
+ address: this.diamondAddress,
2147
+ abi: DIAMOND_ABI,
2148
+ functionName: "autoWithdrawNext",
2149
+ args: [campaignId, BigInt(batchSize)]
2150
+ });
2151
+ return this.createTransactionResult(hash);
2152
+ }
2153
+ /**
2154
+ * Execute auto-release for specific recipients (keeper only)
2155
+ */
2156
+ async executeAutoRelease(campaignId, recipients) {
2157
+ const wallet = this.requireWallet();
2158
+ const hash = await wallet.writeContract({
2159
+ chain: wallet.chain,
2160
+ account: wallet.account,
2161
+ address: this.diamondAddress,
2162
+ abi: DIAMOND_ABI,
2163
+ functionName: "autoReleaseLock",
2164
+ args: [campaignId, recipients]
2165
+ });
2166
+ return this.createTransactionResult(hash);
2167
+ }
2168
+ /**
2169
+ * Execute auto-release using registry cursor (keeper only)
2170
+ */
2171
+ async executeAutoReleaseNext(campaignId, batchSize = 50) {
2172
+ const wallet = this.requireWallet();
2173
+ const hash = await wallet.writeContract({
2174
+ chain: wallet.chain,
2175
+ account: wallet.account,
2176
+ address: this.diamondAddress,
2177
+ abi: DIAMOND_ABI,
2178
+ functionName: "autoReleaseLockNext",
2179
+ args: [campaignId, BigInt(batchSize)]
2180
+ });
2181
+ return this.createTransactionResult(hash);
2182
+ }
2183
+ // ============================================================================
2184
+ // Helpers
2185
+ // ============================================================================
2186
+ requireWallet() {
2187
+ if (!this.walletClient) {
2188
+ throw new Error(
2189
+ "Wallet client required for write operations. Initialize SDK with a signer."
2190
+ );
2191
+ }
2192
+ return this.walletClient;
2193
+ }
2194
+ createTransactionResult(hash) {
2195
+ return {
2196
+ hash,
2197
+ wait: async () => {
2198
+ const receipt = await this.publicClient.waitForTransactionReceipt({
2199
+ hash
2200
+ });
2201
+ return {
2202
+ blockNumber: receipt.blockNumber,
2203
+ transactionHash: receipt.transactionHash,
2204
+ gasUsed: receipt.gasUsed,
2205
+ status: receipt.status,
2206
+ logs: receipt.logs
2207
+ };
2208
+ }
2209
+ };
2210
+ }
2211
+ };
2212
+
2213
+ // src/api/index.ts
2214
+ var ApiClient = class {
2215
+ baseUrl;
2216
+ chainId;
2217
+ constructor(baseUrl, chainId) {
2218
+ this.baseUrl = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
2219
+ this.chainId = chainId;
2220
+ }
2221
+ // ============================================================================
2222
+ // Campaign Queries
2223
+ // ============================================================================
2224
+ /**
2225
+ * Get campaigns with optional filtering
2226
+ *
2227
+ * @example
2228
+ * ```typescript
2229
+ * const campaigns = await sdk.api.getCampaigns({
2230
+ * kind: 'vested_airdrop',
2231
+ * status: 'active',
2232
+ * page: 1,
2233
+ * pageSize: 20,
2234
+ * });
2235
+ * ```
2236
+ */
2237
+ async getCampaigns(params = {}) {
2238
+ const searchParams = new URLSearchParams();
2239
+ if (params.kind) searchParams.set("kind", params.kind);
2240
+ if (params.creator) searchParams.set("creator", params.creator);
2241
+ if (params.token) searchParams.set("token", params.token);
2242
+ if (params.status) searchParams.set("status", params.status);
2243
+ if (params.page) searchParams.set("page", String(params.page));
2244
+ if (params.pageSize) searchParams.set("pageSize", String(params.pageSize));
2245
+ if (params.sortBy) searchParams.set("sortBy", params.sortBy);
2246
+ if (params.sortOrder) searchParams.set("sortOrder", params.sortOrder);
2247
+ searchParams.set("chainId", String(this.chainId));
2248
+ return this.fetch(
2249
+ `/v1/campaigns?${searchParams.toString()}`
2250
+ );
2251
+ }
2252
+ /**
2253
+ * Get a single campaign by ID
2254
+ */
2255
+ async getCampaign(campaignId) {
2256
+ return this.fetch(
2257
+ `/v1/campaigns/${campaignId}?chainId=${this.chainId}`
2258
+ );
2259
+ }
2260
+ /**
2261
+ * Get campaign recipients
2262
+ */
2263
+ async getCampaignRecipients(campaignId, params = {}) {
2264
+ const searchParams = new URLSearchParams();
2265
+ searchParams.set("chainId", String(this.chainId));
2266
+ if (params.page) searchParams.set("page", String(params.page));
2267
+ if (params.pageSize) searchParams.set("pageSize", String(params.pageSize));
2268
+ return this.fetch(
2269
+ `/v1/campaigns/${campaignId}/recipients?${searchParams.toString()}`
2270
+ );
2271
+ }
2272
+ /**
2273
+ * Get campaign activity/claims
2274
+ */
2275
+ async getCampaignActivity(campaignId, params = {}) {
2276
+ const searchParams = new URLSearchParams();
2277
+ searchParams.set("chainId", String(this.chainId));
2278
+ if (params.page) searchParams.set("page", String(params.page));
2279
+ if (params.pageSize) searchParams.set("pageSize", String(params.pageSize));
2280
+ return this.fetch(
2281
+ `/v1/campaigns/${campaignId}/activity?${searchParams.toString()}`
2282
+ );
2283
+ }
2284
+ // ============================================================================
2285
+ // Order Queries
2286
+ // ============================================================================
2287
+ /**
2288
+ * Get marketplace orders with optional filtering
2289
+ *
2290
+ * @example
2291
+ * ```typescript
2292
+ * const orders = await sdk.api.getOrders({
2293
+ * orderType: 'tradable',
2294
+ * status: 'open',
2295
+ * sortBy: 'totalPrice',
2296
+ * sortOrder: 'asc',
2297
+ * });
2298
+ * ```
2299
+ */
2300
+ async getOrders(params = {}) {
2301
+ const searchParams = new URLSearchParams();
2302
+ if (params.orderType) searchParams.set("orderType", params.orderType);
2303
+ if (params.seller) searchParams.set("seller", params.seller);
2304
+ if (params.sellToken) searchParams.set("sellToken", params.sellToken);
2305
+ if (params.payToken) searchParams.set("payToken", params.payToken);
2306
+ if (params.status) searchParams.set("status", params.status);
2307
+ if (params.campaignId) searchParams.set("campaignId", params.campaignId);
2308
+ if (params.page) searchParams.set("page", String(params.page));
2309
+ if (params.pageSize) searchParams.set("pageSize", String(params.pageSize));
2310
+ if (params.sortBy) searchParams.set("sortBy", params.sortBy);
2311
+ if (params.sortOrder) searchParams.set("sortOrder", params.sortOrder);
2312
+ searchParams.set("chainId", String(this.chainId));
2313
+ return this.fetch(
2314
+ `/v1/marketplace/orders?${searchParams.toString()}`
2315
+ );
2316
+ }
2317
+ /**
2318
+ * Get a single order by ID
2319
+ */
2320
+ async getOrder(orderId) {
2321
+ return this.fetch(
2322
+ `/v1/marketplace/orders/${orderId}?chainId=${this.chainId}`
2323
+ );
2324
+ }
2325
+ /**
2326
+ * Get order price quote
2327
+ */
2328
+ async getOrderQuote(orderId) {
2329
+ return this.fetch(
2330
+ `/v1/marketplace/orders/${orderId}/quote?chainId=${this.chainId}`
2331
+ );
2332
+ }
2333
+ // ============================================================================
2334
+ // Staking Queries
2335
+ // ============================================================================
2336
+ /**
2337
+ * Get staking pools with optional filtering
2338
+ */
2339
+ async getStakingPools(params = {}) {
2340
+ const searchParams = new URLSearchParams();
2341
+ if (params.stakeToken) searchParams.set("stakeToken", params.stakeToken);
2342
+ if (params.rewardToken) searchParams.set("rewardToken", params.rewardToken);
2343
+ if (params.creator) searchParams.set("creator", params.creator);
2344
+ if (params.isActive !== void 0)
2345
+ searchParams.set("isActive", String(params.isActive));
2346
+ if (params.page) searchParams.set("page", String(params.page));
2347
+ if (params.pageSize) searchParams.set("pageSize", String(params.pageSize));
2348
+ searchParams.set("chainId", String(this.chainId));
2349
+ return this.fetch(
2350
+ `/v1/staking/pools?${searchParams.toString()}`
2351
+ );
2352
+ }
2353
+ /**
2354
+ * Get a single staking pool by ID
2355
+ */
2356
+ async getStakingPool(poolId) {
2357
+ return this.fetch(
2358
+ `/v1/staking/pools/${poolId}?chainId=${this.chainId}`
2359
+ );
2360
+ }
2361
+ /**
2362
+ * Get stakers for a pool
2363
+ */
2364
+ async getPoolStakers(poolId, params = {}) {
2365
+ const searchParams = new URLSearchParams();
2366
+ searchParams.set("chainId", String(this.chainId));
2367
+ if (params.page) searchParams.set("page", String(params.page));
2368
+ if (params.pageSize) searchParams.set("pageSize", String(params.pageSize));
2369
+ return this.fetch(
2370
+ `/v1/staking/pools/${poolId}/stakers?${searchParams.toString()}`
2371
+ );
2372
+ }
2373
+ // ============================================================================
2374
+ // Wallet Queries
2375
+ // ============================================================================
2376
+ /**
2377
+ * Get wallet activity summary
2378
+ *
2379
+ * @example
2380
+ * ```typescript
2381
+ * const activity = await sdk.api.getWalletActivity(address);
2382
+ * console.log('Campaigns:', activity.campaigns.length);
2383
+ * console.log('Open orders:', activity.openOrders.length);
2384
+ * console.log('Stakes:', activity.stakes.length);
2385
+ * ```
2386
+ */
2387
+ async getWalletActivity(address) {
2388
+ return this.fetch(
2389
+ `/v1/wallets/${address}?chainId=${this.chainId}`
2390
+ );
2391
+ }
2392
+ /**
2393
+ * Get wallet claims history
2394
+ */
2395
+ async getWalletClaims(address, params = {}) {
2396
+ const searchParams = new URLSearchParams();
2397
+ searchParams.set("chainId", String(this.chainId));
2398
+ if (params.page) searchParams.set("page", String(params.page));
2399
+ if (params.pageSize) searchParams.set("pageSize", String(params.pageSize));
2400
+ return this.fetch(
2401
+ `/v1/wallets/${address}/claims?${searchParams.toString()}`
2402
+ );
2403
+ }
2404
+ /**
2405
+ * Get wallet positions (campaigns where wallet has allocations)
2406
+ */
2407
+ async getWalletPositions(address) {
2408
+ return this.fetch(
2409
+ `/v1/wallets/${address}/positions?chainId=${this.chainId}`
2410
+ );
2411
+ }
2412
+ // ============================================================================
2413
+ // Token Queries
2414
+ // ============================================================================
2415
+ /**
2416
+ * Search for tokens
2417
+ *
2418
+ * @example
2419
+ * ```typescript
2420
+ * const tokens = await sdk.api.searchTokens('USDC');
2421
+ * ```
2422
+ */
2423
+ async searchTokens(query) {
2424
+ return this.fetch(
2425
+ `/v1/tokens?q=${encodeURIComponent(query)}&chainId=${this.chainId}`
2426
+ );
2427
+ }
2428
+ /**
2429
+ * Get token information by address
2430
+ */
2431
+ async getToken(address) {
2432
+ return this.fetch(
2433
+ `/v1/tokens/${address}?chainId=${this.chainId}`
2434
+ );
2435
+ }
2436
+ /**
2437
+ * Get token price
2438
+ */
2439
+ async getTokenPrice(address) {
2440
+ return this.fetch(
2441
+ `/v1/tokens/${address}/price?chainId=${this.chainId}`
2442
+ );
2443
+ }
2444
+ // ============================================================================
2445
+ // Health & Status
2446
+ // ============================================================================
2447
+ /**
2448
+ * Check API health
2449
+ */
2450
+ async health() {
2451
+ return this.fetch("/health");
2452
+ }
2453
+ /**
2454
+ * Get supported chains
2455
+ */
2456
+ async getChains() {
2457
+ return this.fetch("/v1/chains");
2458
+ }
2459
+ // ============================================================================
2460
+ // Actions (Transaction Preparation)
2461
+ // ============================================================================
2462
+ /**
2463
+ * Prepare a claim transaction
2464
+ *
2465
+ * Returns the calldata for a claim transaction.
2466
+ */
2467
+ async prepareClaimTx(params) {
2468
+ return this.fetch("/v1/actions/claim", {
2469
+ method: "POST",
2470
+ body: JSON.stringify({
2471
+ ...params,
2472
+ chainId: this.chainId
2473
+ })
2474
+ });
2475
+ }
2476
+ /**
2477
+ * Prepare a fill order transaction
2478
+ */
2479
+ async prepareFillOrderTx(params) {
2480
+ return this.fetch("/v1/actions/fill-order", {
2481
+ method: "POST",
2482
+ body: JSON.stringify({
2483
+ ...params,
2484
+ chainId: this.chainId
2485
+ })
2486
+ });
2487
+ }
2488
+ // ============================================================================
2489
+ // Helpers
2490
+ // ============================================================================
2491
+ async fetch(endpoint, options = {}) {
2492
+ const url = `${this.baseUrl}${endpoint}`;
2493
+ const response = await fetch(url, {
2494
+ ...options,
2495
+ headers: {
2496
+ "Content-Type": "application/json",
2497
+ ...options.headers
2498
+ }
2499
+ });
2500
+ if (!response.ok) {
2501
+ const error = await response.text();
2502
+ throw new ApiError(response.status, error);
2503
+ }
2504
+ return response.json();
2505
+ }
2506
+ };
2507
+ var ApiError = class extends Error {
2508
+ constructor(status, message) {
2509
+ super(`API Error (${status}): ${message}`);
2510
+ this.status = status;
2511
+ this.name = "ApiError";
2512
+ }
2513
+ };
2514
+
2515
+ // src/client.ts
2516
+ var CHAINS = {
2517
+ 1: {
2518
+ id: 1,
2519
+ name: "Ethereum",
2520
+ nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
2521
+ rpcUrls: { default: { http: ["https://eth.llamarpc.com"] } }
2522
+ },
2523
+ 56: {
2524
+ id: 56,
2525
+ name: "BNB Smart Chain",
2526
+ nativeCurrency: { name: "BNB", symbol: "BNB", decimals: 18 },
2527
+ rpcUrls: { default: { http: ["https://bsc-dataseed.binance.org"] } }
2528
+ },
2529
+ 31337: {
2530
+ id: 31337,
2531
+ name: "Anvil Local",
2532
+ nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
2533
+ rpcUrls: { default: { http: ["http://127.0.0.1:8545"] } }
2534
+ }
2535
+ };
2536
+ var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
2537
+ var WETH_ADDRESSES = {
2538
+ 1: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
2539
+ 56: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
2540
+ // WBNB
2541
+ 31337: "0x2bdCC0de6bE1f7D2ee689a0342D76F52E8EFABa3"
2542
+ // Local WETH
2543
+ };
2544
+ var PepayStreamsClient = class {
2545
+ publicClient;
2546
+ walletClient;
2547
+ diamondAddress;
2548
+ chainId;
2549
+ wethAddress;
2550
+ permit2Address;
2551
+ // Modules
2552
+ campaigns;
2553
+ claims;
2554
+ staking;
2555
+ marketplace;
2556
+ automation;
2557
+ api;
2558
+ constructor(config) {
2559
+ this.diamondAddress = config.diamondAddress;
2560
+ this.chainId = config.chainId;
2561
+ this.wethAddress = config.wethAddress ?? WETH_ADDRESSES[config.chainId] ?? "0x0000000000000000000000000000000000000000";
2562
+ this.permit2Address = config.permit2Address ?? PERMIT2_ADDRESS;
2563
+ const chain = CHAINS[config.chainId];
2564
+ this.publicClient = createPublicClient({
2565
+ chain,
2566
+ transport: http(config.rpcUrl)
2567
+ });
2568
+ this.campaigns = new CampaignsModule(
2569
+ this.publicClient,
2570
+ void 0,
2571
+ this.diamondAddress
2572
+ );
2573
+ this.claims = new ClaimsModule(
2574
+ this.publicClient,
2575
+ void 0,
2576
+ this.diamondAddress,
2577
+ this.chainId
2578
+ );
2579
+ this.staking = new StakingModule(
2580
+ this.publicClient,
2581
+ void 0,
2582
+ this.diamondAddress
2583
+ );
2584
+ this.marketplace = new MarketplaceModule(
2585
+ this.publicClient,
2586
+ void 0,
2587
+ this.diamondAddress
2588
+ );
2589
+ this.automation = new AutomationModule(
2590
+ this.publicClient,
2591
+ void 0,
2592
+ this.diamondAddress
2593
+ );
2594
+ if (config.apiBaseUrl) {
2595
+ this.api = new ApiClient(config.apiBaseUrl, config.chainId);
2596
+ }
2597
+ }
2598
+ /**
2599
+ * Create a client with a wallet for signing transactions
2600
+ */
2601
+ withSigner(walletClient) {
2602
+ return new PepayStreamsClientWithSigner(
2603
+ this.publicClient,
2604
+ walletClient,
2605
+ this.diamondAddress,
2606
+ this.chainId,
2607
+ this.wethAddress,
2608
+ this.permit2Address,
2609
+ this.api
2610
+ );
2611
+ }
2612
+ /**
2613
+ * Create a client from browser wallet (window.ethereum)
2614
+ */
2615
+ static async fromBrowserWallet(config) {
2616
+ if (typeof window === "undefined" || !window.ethereum) {
2617
+ throw new Error("Browser wallet not available");
2618
+ }
2619
+ const ethereum = window.ethereum;
2620
+ const accounts = await ethereum.request({
2621
+ method: "eth_requestAccounts"
2622
+ });
2623
+ if (!accounts[0]) {
2624
+ throw new Error("No account available");
2625
+ }
2626
+ const chain = CHAINS[config.chainId];
2627
+ if (!chain) {
2628
+ throw new Error(`Chain ${config.chainId} not supported`);
2629
+ }
2630
+ const publicClient = createPublicClient({
2631
+ chain,
2632
+ transport: custom(ethereum)
2633
+ });
2634
+ const walletClient = createWalletClient({
2635
+ chain,
2636
+ transport: custom(ethereum),
2637
+ account: accounts[0]
2638
+ });
2639
+ return new PepayStreamsClientWithSigner(
2640
+ publicClient,
2641
+ walletClient,
2642
+ config.diamondAddress,
2643
+ config.chainId,
2644
+ WETH_ADDRESSES[config.chainId] ?? "0x0000000000000000000000000000000000000000",
2645
+ PERMIT2_ADDRESS,
2646
+ config.apiBaseUrl ? new ApiClient(config.apiBaseUrl, config.chainId) : void 0
2647
+ );
2648
+ }
2649
+ /**
2650
+ * Create a client with private key (for Node.js/scripts)
2651
+ */
2652
+ static fromPrivateKey(config) {
2653
+ const chain = CHAINS[config.chainId];
2654
+ if (!chain) {
2655
+ throw new Error(`Chain ${config.chainId} not supported`);
2656
+ }
2657
+ const publicClient = createPublicClient({
2658
+ chain,
2659
+ transport: http(config.rpcUrl)
2660
+ });
2661
+ const { privateKeyToAccount } = __require("viem/accounts");
2662
+ const account = privateKeyToAccount(config.privateKey);
2663
+ const walletClient = createWalletClient({
2664
+ chain,
2665
+ transport: http(config.rpcUrl),
2666
+ account
2667
+ });
2668
+ return new PepayStreamsClientWithSigner(
2669
+ publicClient,
2670
+ walletClient,
2671
+ config.diamondAddress,
2672
+ config.chainId,
2673
+ config.wethAddress ?? WETH_ADDRESSES[config.chainId] ?? "0x0000000000000000000000000000000000000000",
2674
+ config.permit2Address ?? PERMIT2_ADDRESS,
2675
+ config.apiBaseUrl ? new ApiClient(config.apiBaseUrl, config.chainId) : void 0
2676
+ );
2677
+ }
2678
+ // ============================================================================
2679
+ // Read-only utilities
2680
+ // ============================================================================
2681
+ /**
2682
+ * Get token balance
2683
+ */
2684
+ async getTokenBalance(token, account) {
2685
+ return this.publicClient.readContract({
2686
+ address: token,
2687
+ abi: erc20Abi,
2688
+ functionName: "balanceOf",
2689
+ args: [account]
2690
+ });
2691
+ }
2692
+ /**
2693
+ * Get token allowance for Diamond contract
2694
+ */
2695
+ async getTokenAllowance(token, owner) {
2696
+ return this.publicClient.readContract({
2697
+ address: token,
2698
+ abi: erc20Abi,
2699
+ functionName: "allowance",
2700
+ args: [owner, this.diamondAddress]
2701
+ });
2702
+ }
2703
+ /**
2704
+ * Get token info (symbol, decimals, name)
2705
+ */
2706
+ async getTokenInfo(token) {
2707
+ const [symbol, decimals, name] = await Promise.all([
2708
+ this.publicClient.readContract({
2709
+ address: token,
2710
+ abi: erc20Abi,
2711
+ functionName: "symbol"
2712
+ }),
2713
+ this.publicClient.readContract({
2714
+ address: token,
2715
+ abi: erc20Abi,
2716
+ functionName: "decimals"
2717
+ }),
2718
+ this.publicClient.readContract({
2719
+ address: token,
2720
+ abi: erc20Abi,
2721
+ functionName: "name"
2722
+ })
2723
+ ]);
2724
+ return { symbol, decimals, name };
2725
+ }
2726
+ /**
2727
+ * Get version of a specific facet
2728
+ *
2729
+ * @param facetAddress - The address of the facet to query
2730
+ */
2731
+ async getFacetVersion(facetAddress) {
2732
+ const result = await this.publicClient.readContract({
2733
+ address: this.diamondAddress,
2734
+ abi: DIAMOND_ABI,
2735
+ functionName: "getVersion",
2736
+ args: [facetAddress]
2737
+ });
2738
+ return result;
2739
+ }
2740
+ /**
2741
+ * Get all facet versions
2742
+ */
2743
+ async getAllVersions() {
2744
+ const result = await this.publicClient.readContract({
2745
+ address: this.diamondAddress,
2746
+ abi: DIAMOND_ABI,
2747
+ functionName: "getAllVersions"
2748
+ });
2749
+ const [facets, versions] = result;
2750
+ return { facets, versions };
2751
+ }
2752
+ /**
2753
+ * Check if Diamond contract is in emergency pause
2754
+ */
2755
+ async isEmergencyPaused() {
2756
+ const result = await this.publicClient.readContract({
2757
+ address: this.diamondAddress,
2758
+ abi: DIAMOND_ABI,
2759
+ functionName: "isEmergencyPaused"
2760
+ });
2761
+ return result;
2762
+ }
2763
+ };
2764
+ var PepayStreamsClientWithSigner = class extends PepayStreamsClient {
2765
+ walletClient;
2766
+ campaigns;
2767
+ claims;
2768
+ staking;
2769
+ marketplace;
2770
+ automation;
2771
+ constructor(publicClient, walletClient, diamondAddress, chainId, wethAddress, permit2Address, apiClient) {
2772
+ const config = {
2773
+ rpcUrl: "",
2774
+ // Not used, we pass clients directly
2775
+ diamondAddress,
2776
+ chainId,
2777
+ wethAddress,
2778
+ permit2Address
2779
+ };
2780
+ super(config);
2781
+ this.publicClient = publicClient;
2782
+ this.walletClient = walletClient;
2783
+ if (apiClient) {
2784
+ this.api = apiClient;
2785
+ }
2786
+ this.campaigns = new CampaignsModule(
2787
+ publicClient,
2788
+ walletClient,
2789
+ diamondAddress
2790
+ );
2791
+ this.claims = new ClaimsModule(
2792
+ publicClient,
2793
+ walletClient,
2794
+ diamondAddress,
2795
+ chainId
2796
+ );
2797
+ this.staking = new StakingModule(
2798
+ publicClient,
2799
+ walletClient,
2800
+ diamondAddress
2801
+ );
2802
+ this.marketplace = new MarketplaceModule(
2803
+ publicClient,
2804
+ walletClient,
2805
+ diamondAddress
2806
+ );
2807
+ this.automation = new AutomationModule(
2808
+ publicClient,
2809
+ walletClient,
2810
+ diamondAddress
2811
+ );
2812
+ }
2813
+ /**
2814
+ * Get the connected wallet address
2815
+ */
2816
+ get address() {
2817
+ if (!this.walletClient.account) {
2818
+ throw new Error("No account connected");
2819
+ }
2820
+ return this.walletClient.account.address;
2821
+ }
2822
+ // ============================================================================
2823
+ // Token Operations
2824
+ // ============================================================================
2825
+ /**
2826
+ * Approve tokens for the Diamond contract
2827
+ *
2828
+ * @example
2829
+ * ```typescript
2830
+ * await client.approve(tokenAddress, parseEther('1000'));
2831
+ * ```
2832
+ */
2833
+ async approve(token, amount) {
2834
+ const hash = await this.walletClient.writeContract({
2835
+ chain: this.walletClient.chain,
2836
+ account: this.walletClient.account,
2837
+ address: token,
2838
+ abi: erc20Abi,
2839
+ functionName: "approve",
2840
+ args: [this.diamondAddress, amount]
2841
+ });
2842
+ return {
2843
+ hash,
2844
+ wait: async () => {
2845
+ const receipt = await this.publicClient.waitForTransactionReceipt({
2846
+ hash
2847
+ });
2848
+ return {
2849
+ blockNumber: receipt.blockNumber,
2850
+ transactionHash: receipt.transactionHash,
2851
+ gasUsed: receipt.gasUsed,
2852
+ status: receipt.status,
2853
+ logs: receipt.logs
2854
+ };
2855
+ }
2856
+ };
2857
+ }
2858
+ /**
2859
+ * Approve max tokens (type(uint256).max)
2860
+ */
2861
+ async approveMax(token) {
2862
+ const MAX_UINT256 = 2n ** 256n - 1n;
2863
+ return this.approve(token, MAX_UINT256);
2864
+ }
2865
+ /**
2866
+ * Check and approve if needed
2867
+ */
2868
+ async ensureAllowance(token, requiredAmount) {
2869
+ const currentAllowance = await this.getTokenAllowance(
2870
+ token,
2871
+ this.address
2872
+ );
2873
+ if (currentAllowance >= requiredAmount) {
2874
+ return null;
2875
+ }
2876
+ return this.approve(token, requiredAmount);
2877
+ }
2878
+ /**
2879
+ * Get native balance (ETH/BNB)
2880
+ */
2881
+ async getNativeBalance() {
2882
+ return this.publicClient.getBalance({ address: this.address });
2883
+ }
2884
+ };
2885
+
2886
+ export { ApiClient, ApiError, AutomationModule, CampaignsModule, ClaimsModule, MarketplaceModule, PepayStreamsClient, PepayStreamsClientWithSigner, StakingModule };
2887
+ //# sourceMappingURL=index.mjs.map
2888
+ //# sourceMappingURL=index.mjs.map