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