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
@@ -0,0 +1,449 @@
1
+ /**
2
+ * Staking Module
3
+ *
4
+ * Provides methods for staking operations:
5
+ * - Stake tokens
6
+ * - Unstake tokens
7
+ * - Claim rewards
8
+ * - Pool queries
9
+ */
10
+ import {
11
+ type PublicClient,
12
+ type WalletClient,
13
+ type Address,
14
+ type Hash,
15
+ } from 'viem';
16
+ import { DIAMOND_ABI } from '@pepay-streams/abi/diamond';
17
+ import type {
18
+ PoolInfo,
19
+ UserStake,
20
+ TransactionResult,
21
+ } from '../types';
22
+
23
+ /**
24
+ * Staking module for fixed-duration staking pools
25
+ */
26
+ export class StakingModule {
27
+ constructor(
28
+ private readonly publicClient: PublicClient,
29
+ private readonly walletClient: WalletClient | undefined,
30
+ private readonly diamondAddress: Address
31
+ ) {}
32
+
33
+ // ============================================================================
34
+ // Staking Operations
35
+ // ============================================================================
36
+
37
+ /**
38
+ * Stake tokens in a pool
39
+ *
40
+ * Must approve the Diamond contract first.
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * await sdk.approve(stakeToken, amount);
45
+ * const result = await sdk.staking.stake(poolId, amount);
46
+ * ```
47
+ */
48
+ async stake(poolId: bigint, amount: bigint): Promise<TransactionResult> {
49
+ const wallet = this.requireWallet();
50
+
51
+ const hash = await wallet.writeContract({
52
+ chain: wallet.chain,
53
+ account: wallet.account!,
54
+ address: this.diamondAddress,
55
+ abi: DIAMOND_ABI,
56
+ functionName: 'stake',
57
+ args: [poolId, amount],
58
+ });
59
+
60
+ return this.createTransactionResult(hash);
61
+ }
62
+
63
+ /**
64
+ * Increase stake in an existing deposit
65
+ */
66
+ async increaseStake(
67
+ poolId: bigint,
68
+ amount: bigint
69
+ ): Promise<TransactionResult> {
70
+ const wallet = this.requireWallet();
71
+
72
+ const hash = await wallet.writeContract({
73
+ chain: wallet.chain,
74
+ account: wallet.account!,
75
+ address: this.diamondAddress,
76
+ abi: DIAMOND_ABI,
77
+ functionName: 'increaseStake',
78
+ args: [poolId, amount],
79
+ });
80
+
81
+ return this.createTransactionResult(hash);
82
+ }
83
+
84
+ /**
85
+ * Unstake all tokens from a pool
86
+ *
87
+ * Automatically claims pending rewards.
88
+ *
89
+ * @example
90
+ * ```typescript
91
+ * const result = await sdk.staking.unstake(poolId);
92
+ * ```
93
+ */
94
+ async unstake(poolId: bigint): Promise<TransactionResult> {
95
+ const wallet = this.requireWallet();
96
+
97
+ const hash = await wallet.writeContract({
98
+ chain: wallet.chain,
99
+ account: wallet.account!,
100
+ address: this.diamondAddress,
101
+ abi: DIAMOND_ABI,
102
+ functionName: 'unstake',
103
+ args: [poolId],
104
+ });
105
+
106
+ return this.createTransactionResult(hash);
107
+ }
108
+
109
+ /**
110
+ * Partial unstake - withdraw some tokens but keep position open
111
+ */
112
+ async partialUnstake(
113
+ poolId: bigint,
114
+ amount: bigint
115
+ ): Promise<TransactionResult> {
116
+ const wallet = this.requireWallet();
117
+
118
+ const hash = await wallet.writeContract({
119
+ chain: wallet.chain,
120
+ account: wallet.account!,
121
+ address: this.diamondAddress,
122
+ abi: DIAMOND_ABI,
123
+ functionName: 'partialUnstake',
124
+ args: [poolId, amount],
125
+ });
126
+
127
+ return this.createTransactionResult(hash);
128
+ }
129
+
130
+ /**
131
+ * Emergency unstake - forfeit rewards but get principal back
132
+ *
133
+ * Use when pool has issues or you need immediate exit.
134
+ */
135
+ async emergencyUnstake(poolId: bigint): Promise<TransactionResult> {
136
+ const wallet = this.requireWallet();
137
+
138
+ const hash = await wallet.writeContract({
139
+ chain: wallet.chain,
140
+ account: wallet.account!,
141
+ address: this.diamondAddress,
142
+ abi: DIAMOND_ABI,
143
+ functionName: 'emergencyUnstake',
144
+ args: [poolId],
145
+ });
146
+
147
+ return this.createTransactionResult(hash);
148
+ }
149
+
150
+ // ============================================================================
151
+ // Pool Queries
152
+ // ============================================================================
153
+
154
+ /**
155
+ * Get pool information
156
+ *
157
+ * @example
158
+ * ```typescript
159
+ * const pool = await sdk.staking.getPool(1n);
160
+ * console.log('Total staked:', formatEther(pool.totalStaked));
161
+ * ```
162
+ */
163
+ async getPool(poolId: bigint): Promise<PoolInfo> {
164
+ const result = await this.publicClient.readContract({
165
+ address: this.diamondAddress,
166
+ abi: DIAMOND_ABI,
167
+ functionName: 'pools',
168
+ args: [poolId],
169
+ });
170
+
171
+ return this.parsePoolInfo(poolId, result as Record<string, unknown>);
172
+ }
173
+
174
+ /**
175
+ * Get total number of staking pools
176
+ */
177
+ async getPoolCount(): Promise<bigint> {
178
+ const result = await this.publicClient.readContract({
179
+ address: this.diamondAddress,
180
+ abi: DIAMOND_ABI,
181
+ functionName: 'poolCount',
182
+ args: [],
183
+ });
184
+
185
+ return result as bigint;
186
+ }
187
+
188
+ /**
189
+ * Get pool stats (runtime state)
190
+ */
191
+ async getPoolStats(poolId: bigint): Promise<{
192
+ statusBits: number;
193
+ rewardRemaining: bigint;
194
+ totalStaked: bigint;
195
+ endAt: number;
196
+ finalized: boolean;
197
+ rewardRatePerSecond: bigint;
198
+ }> {
199
+ const result = await this.publicClient.readContract({
200
+ address: this.diamondAddress,
201
+ abi: DIAMOND_ABI,
202
+ functionName: 'poolStats',
203
+ args: [poolId],
204
+ }) as [number, bigint, bigint, bigint, bigint, bigint, boolean, bigint, bigint, bigint];
205
+
206
+ return {
207
+ statusBits: result[0],
208
+ rewardRemaining: result[1],
209
+ totalStaked: result[2],
210
+ endAt: Number(result[4]),
211
+ finalized: result[6],
212
+ rewardRatePerSecond: result[9],
213
+ };
214
+ }
215
+
216
+ // ============================================================================
217
+ // User Stake Queries
218
+ // ============================================================================
219
+
220
+ /**
221
+ * Get user's deposit info for a pool
222
+ *
223
+ * @example
224
+ * ```typescript
225
+ * const stake = await sdk.staking.getUserDeposit(poolId, address);
226
+ * console.log('Staked:', formatEther(stake.amount));
227
+ * ```
228
+ */
229
+ async getUserDeposit(poolId: bigint, user: Address): Promise<{
230
+ amount: bigint;
231
+ startAt: number;
232
+ rewardDebtRay: bigint;
233
+ claimedReward: bigint;
234
+ claimedAt: number;
235
+ active: boolean;
236
+ }> {
237
+ const result = await this.publicClient.readContract({
238
+ address: this.diamondAddress,
239
+ abi: DIAMOND_ABI,
240
+ functionName: 'deposits',
241
+ args: [poolId, user],
242
+ }) as { amount: bigint; startAt: bigint; rewardDebtRay: bigint; claimedReward: bigint; claimedAt: bigint; active: boolean };
243
+
244
+ return {
245
+ amount: result.amount,
246
+ startAt: Number(result.startAt),
247
+ rewardDebtRay: result.rewardDebtRay,
248
+ claimedReward: result.claimedReward,
249
+ claimedAt: Number(result.claimedAt),
250
+ active: result.active,
251
+ };
252
+ }
253
+
254
+ /**
255
+ * Get comprehensive deposit status for a user
256
+ */
257
+ async getDepositStatus(poolId: bigint, user: Address): Promise<{
258
+ active: boolean;
259
+ stakedAmount: bigint;
260
+ pendingRewards: bigint;
261
+ canUnstakeNow: boolean;
262
+ secondsUntilUnstake: number;
263
+ totalClaimed: bigint;
264
+ }> {
265
+ const result = await this.publicClient.readContract({
266
+ address: this.diamondAddress,
267
+ abi: DIAMOND_ABI,
268
+ functionName: 'depositStatus',
269
+ args: [poolId, user],
270
+ }) as [boolean, bigint, bigint, boolean, bigint, bigint];
271
+
272
+ return {
273
+ active: result[0],
274
+ stakedAmount: result[1],
275
+ pendingRewards: result[2],
276
+ canUnstakeNow: result[3],
277
+ secondsUntilUnstake: Number(result[4]),
278
+ totalClaimed: result[5],
279
+ };
280
+ }
281
+
282
+ /**
283
+ * Get pending rewards for a user in a pool
284
+ */
285
+ async getPendingRewards(poolId: bigint, user: Address): Promise<bigint> {
286
+ const result = await this.publicClient.readContract({
287
+ address: this.diamondAddress,
288
+ abi: DIAMOND_ABI,
289
+ functionName: 'pendingReward',
290
+ args: [poolId, user],
291
+ });
292
+
293
+ return result as bigint;
294
+ }
295
+
296
+ /**
297
+ * Check if user can unstake from a pool
298
+ */
299
+ async canUnstake(poolId: bigint, user: Address): Promise<boolean> {
300
+ const result = await this.publicClient.readContract({
301
+ address: this.diamondAddress,
302
+ abi: DIAMOND_ABI,
303
+ functionName: 'canUnstake',
304
+ args: [poolId, user],
305
+ });
306
+
307
+ return result as boolean;
308
+ }
309
+
310
+ /**
311
+ * Get time until user can unstake
312
+ */
313
+ async secondsUntilUnstakeable(
314
+ poolId: bigint,
315
+ user: Address
316
+ ): Promise<bigint> {
317
+ const result = await this.publicClient.readContract({
318
+ address: this.diamondAddress,
319
+ abi: DIAMOND_ABI,
320
+ functionName: 'secondsUntilUnstakeable',
321
+ args: [poolId, user],
322
+ });
323
+
324
+ return result as bigint;
325
+ }
326
+
327
+ /**
328
+ * Get user's stake info for a pool (convenience wrapper)
329
+ *
330
+ * @example
331
+ * ```typescript
332
+ * const stake = await sdk.staking.getUserStake(poolId, address);
333
+ * console.log('Staked:', formatEther(stake.amount));
334
+ * console.log('Pending rewards:', formatEther(stake.pendingRewards));
335
+ * ```
336
+ */
337
+ async getUserStake(poolId: bigint, user: Address): Promise<UserStake> {
338
+ const [deposit, pendingRewards] = await Promise.all([
339
+ this.getUserDeposit(poolId, user),
340
+ this.getPendingRewards(poolId, user),
341
+ ]);
342
+
343
+ return {
344
+ amount: deposit.amount,
345
+ pendingRewards,
346
+ lastClaimTime: deposit.claimedAt,
347
+ stakeTime: deposit.startAt,
348
+ };
349
+ }
350
+
351
+ // ============================================================================
352
+ // Utility Functions
353
+ // ============================================================================
354
+
355
+ /**
356
+ * Get APY preview for a pool
357
+ */
358
+ async getApyPreview(poolId: bigint): Promise<{
359
+ ratePerSecond: bigint;
360
+ totalStaked: bigint;
361
+ }> {
362
+ const result = await this.publicClient.readContract({
363
+ address: this.diamondAddress,
364
+ abi: DIAMOND_ABI,
365
+ functionName: 'apyPreview',
366
+ args: [poolId],
367
+ }) as [bigint, bigint];
368
+
369
+ return {
370
+ ratePerSecond: result[0],
371
+ totalStaked: result[1],
372
+ };
373
+ }
374
+
375
+ /**
376
+ * Calculate APY for a pool
377
+ *
378
+ * @example
379
+ * ```typescript
380
+ * const pool = await sdk.staking.getPool(poolId);
381
+ * const apy = sdk.staking.calculateApy(pool);
382
+ * console.log('APY:', apy.toFixed(2), '%');
383
+ * ```
384
+ */
385
+ calculateApy(pool: PoolInfo): number {
386
+ if (pool.totalStaked === 0n) {
387
+ return 0;
388
+ }
389
+
390
+ const durationInYears =
391
+ (pool.endTime - pool.startTime) / (365 * 24 * 60 * 60);
392
+ const rewardRate =
393
+ Number(pool.rewardBudget) / Number(pool.totalStaked);
394
+
395
+ return (rewardRate / durationInYears) * 100;
396
+ }
397
+
398
+ // ============================================================================
399
+ // Helpers
400
+ // ============================================================================
401
+
402
+ private requireWallet(): WalletClient {
403
+ if (!this.walletClient) {
404
+ throw new Error(
405
+ 'Wallet client required for write operations. Initialize SDK with a signer.'
406
+ );
407
+ }
408
+ return this.walletClient;
409
+ }
410
+
411
+ private parsePoolInfo(id: bigint, data: Record<string, unknown>): PoolInfo {
412
+ return {
413
+ id,
414
+ stakeToken: data.stake as Address,
415
+ rewardToken: data.reward as Address,
416
+ creator: data.creator as Address,
417
+ totalStaked: data.totalStaked as bigint,
418
+ rewardBudget: data.rewardRemaining as bigint, // Current remaining
419
+ rewardsDistributed: 0n, // Not directly available
420
+ startTime: 0, // Not in pool struct
421
+ endTime: Number(data.endAt as bigint),
422
+ minStake: 0n, // Not in pool struct
423
+ maxStake: data.cap as bigint,
424
+ stakerCount: 0, // Not in pool struct
425
+ isActive: !((data.statusBits as number) > 0),
426
+ isFinalized: data.finalized as boolean,
427
+ };
428
+ }
429
+
430
+ private createTransactionResult(hash: Hash): TransactionResult {
431
+ return {
432
+ hash,
433
+ wait: async () => {
434
+ const receipt = await this.publicClient.waitForTransactionReceipt({
435
+ hash,
436
+ });
437
+ return {
438
+ blockNumber: receipt.blockNumber,
439
+ transactionHash: receipt.transactionHash,
440
+ gasUsed: receipt.gasUsed,
441
+ status: receipt.status,
442
+ logs: receipt.logs,
443
+ };
444
+ },
445
+ };
446
+ }
447
+ }
448
+
449
+ export default StakingModule;