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.
- package/README.md +405 -0
- package/dist/api/index.d.mts +321 -0
- package/dist/api/index.d.ts +321 -0
- package/dist/api/index.js +312 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/index.mjs +306 -0
- package/dist/api/index.mjs.map +1 -0
- package/dist/automation/index.d.mts +140 -0
- package/dist/automation/index.d.ts +140 -0
- package/dist/automation/index.js +331 -0
- package/dist/automation/index.js.map +1 -0
- package/dist/automation/index.mjs +326 -0
- package/dist/automation/index.mjs.map +1 -0
- package/dist/campaigns/index.d.mts +286 -0
- package/dist/campaigns/index.d.ts +286 -0
- package/dist/campaigns/index.js +652 -0
- package/dist/campaigns/index.js.map +1 -0
- package/dist/campaigns/index.mjs +645 -0
- package/dist/campaigns/index.mjs.map +1 -0
- package/dist/claims/index.d.mts +190 -0
- package/dist/claims/index.d.ts +190 -0
- package/dist/claims/index.js +414 -0
- package/dist/claims/index.js.map +1 -0
- package/dist/claims/index.mjs +409 -0
- package/dist/claims/index.mjs.map +1 -0
- package/dist/index-BTG0TRJt.d.mts +555 -0
- package/dist/index-BTG0TRJt.d.ts +555 -0
- package/dist/index.d.mts +170 -0
- package/dist/index.d.ts +170 -0
- package/dist/index.js +2926 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2888 -0
- package/dist/index.mjs.map +1 -0
- package/dist/marketplace/index.d.mts +225 -0
- package/dist/marketplace/index.d.ts +225 -0
- package/dist/marketplace/index.js +529 -0
- package/dist/marketplace/index.js.map +1 -0
- package/dist/marketplace/index.mjs +524 -0
- package/dist/marketplace/index.mjs.map +1 -0
- package/dist/react/index.d.mts +185 -0
- package/dist/react/index.d.ts +185 -0
- package/dist/react/index.js +340 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/index.mjs +333 -0
- package/dist/react/index.mjs.map +1 -0
- package/dist/staking/index.d.mts +158 -0
- package/dist/staking/index.d.ts +158 -0
- package/dist/staking/index.js +359 -0
- package/dist/staking/index.js.map +1 -0
- package/dist/staking/index.mjs +354 -0
- package/dist/staking/index.mjs.map +1 -0
- package/package.json +106 -0
- package/src/api/index.ts +577 -0
- package/src/automation/index.ts +436 -0
- package/src/campaigns/index.ts +835 -0
- package/src/claims/index.ts +530 -0
- package/src/client.ts +518 -0
- package/src/index.ts +101 -0
- package/src/marketplace/index.ts +730 -0
- package/src/react/index.ts +498 -0
- package/src/staking/index.ts +449 -0
- package/src/types/index.ts +631 -0
|
@@ -0,0 +1,835 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Campaign Creation Module
|
|
3
|
+
*
|
|
4
|
+
* Provides methods for creating all campaign types:
|
|
5
|
+
* - Instant Airdrops (Kind.INSTANT = 0)
|
|
6
|
+
* - Vested Airdrops (Kind.VESTED = 1)
|
|
7
|
+
* - Token Locks (Kind.LOCK = 2)
|
|
8
|
+
* - Vesting Streams (Kind.VESTING = 3)
|
|
9
|
+
*/
|
|
10
|
+
import {
|
|
11
|
+
type PublicClient,
|
|
12
|
+
type WalletClient,
|
|
13
|
+
type Address,
|
|
14
|
+
type Hash,
|
|
15
|
+
type Hex,
|
|
16
|
+
zeroAddress,
|
|
17
|
+
} from 'viem';
|
|
18
|
+
import { DIAMOND_ABI } from '@pepay-streams/abi/diamond';
|
|
19
|
+
import type {
|
|
20
|
+
InstantAirdropParams,
|
|
21
|
+
VestedAirdropParams,
|
|
22
|
+
LockParams,
|
|
23
|
+
VestingParams,
|
|
24
|
+
CampaignInfo,
|
|
25
|
+
TransactionResult,
|
|
26
|
+
} from '../types';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Campaign Kind enum matching the contract
|
|
30
|
+
*/
|
|
31
|
+
export enum CampaignKind {
|
|
32
|
+
INSTANT = 0,
|
|
33
|
+
VESTED = 1,
|
|
34
|
+
LOCK = 2,
|
|
35
|
+
VESTING = 3,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Change policy enum matching the contract
|
|
40
|
+
*/
|
|
41
|
+
export enum ChangePolicy {
|
|
42
|
+
ONLY_RECIPIENT = 0,
|
|
43
|
+
ONLY_CREATOR = 1,
|
|
44
|
+
BOTH = 2,
|
|
45
|
+
NO_ONE = 3,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* CreateArgs struct matching the contract
|
|
50
|
+
*/
|
|
51
|
+
interface CreateArgs {
|
|
52
|
+
kind: number;
|
|
53
|
+
token: Address;
|
|
54
|
+
start: bigint;
|
|
55
|
+
end: bigint;
|
|
56
|
+
step: bigint;
|
|
57
|
+
cliffReleaseTime: bigint;
|
|
58
|
+
cliffBps: number;
|
|
59
|
+
autoClaimIncentiveBps: number;
|
|
60
|
+
cancelable: boolean;
|
|
61
|
+
claimOnce: boolean;
|
|
62
|
+
changePolicy: number;
|
|
63
|
+
claimGrace: bigint;
|
|
64
|
+
recipients: Address[];
|
|
65
|
+
amounts: bigint[];
|
|
66
|
+
feeBuffer: bigint;
|
|
67
|
+
attachDefaultRegistry: boolean;
|
|
68
|
+
unwrapWETH: boolean;
|
|
69
|
+
weth: Address;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Campaigns module for creating and managing token distribution campaigns
|
|
74
|
+
*/
|
|
75
|
+
export class CampaignsModule {
|
|
76
|
+
constructor(
|
|
77
|
+
private readonly publicClient: PublicClient,
|
|
78
|
+
private readonly walletClient: WalletClient | undefined,
|
|
79
|
+
private readonly diamondAddress: Address
|
|
80
|
+
) {}
|
|
81
|
+
|
|
82
|
+
// ============================================================================
|
|
83
|
+
// Campaign Creation
|
|
84
|
+
// ============================================================================
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Create an Instant Airdrop campaign
|
|
88
|
+
*
|
|
89
|
+
* Tokens are immediately claimable by recipients after funding.
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```typescript
|
|
93
|
+
* const result = await sdk.campaigns.createInstantAirdrop({
|
|
94
|
+
* token: '0x...',
|
|
95
|
+
* recipients: [
|
|
96
|
+
* { address: '0x...', amount: parseEther('100') },
|
|
97
|
+
* { address: '0x...', amount: parseEther('50') },
|
|
98
|
+
* ],
|
|
99
|
+
* });
|
|
100
|
+
* console.log('Campaign created, tx:', result.hash);
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
async createInstantAirdrop(
|
|
104
|
+
params: InstantAirdropParams
|
|
105
|
+
): Promise<TransactionResult> {
|
|
106
|
+
const wallet = this.requireWallet();
|
|
107
|
+
|
|
108
|
+
const recipients = params.recipients.map((r) => r.address);
|
|
109
|
+
const amounts = params.recipients.map((r) => r.amount);
|
|
110
|
+
|
|
111
|
+
const now = BigInt(Math.floor(Date.now() / 1000));
|
|
112
|
+
const args: CreateArgs = {
|
|
113
|
+
kind: CampaignKind.INSTANT,
|
|
114
|
+
token: params.token,
|
|
115
|
+
start: now,
|
|
116
|
+
end: now, // Instant airdrop - same start/end
|
|
117
|
+
step: 0n,
|
|
118
|
+
cliffReleaseTime: 0n,
|
|
119
|
+
cliffBps: 0,
|
|
120
|
+
autoClaimIncentiveBps: params.autoClaimIncentiveBps ?? 0,
|
|
121
|
+
cancelable: params.cancelable ?? true,
|
|
122
|
+
claimOnce: params.claimOnce ?? true,
|
|
123
|
+
changePolicy: this.changePolicyToEnum(params.changePolicy),
|
|
124
|
+
claimGrace: BigInt(params.claimGrace ?? 0),
|
|
125
|
+
recipients,
|
|
126
|
+
amounts,
|
|
127
|
+
feeBuffer: params.feeBuffer ?? 0n,
|
|
128
|
+
attachDefaultRegistry: params.attachDefaultRegistry ?? false,
|
|
129
|
+
unwrapWETH: params.unwrapWETH ?? false,
|
|
130
|
+
weth: params.weth ?? zeroAddress,
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const hash = await wallet.writeContract({
|
|
134
|
+
chain: wallet.chain,
|
|
135
|
+
account: wallet.account!,
|
|
136
|
+
address: this.diamondAddress,
|
|
137
|
+
abi: DIAMOND_ABI,
|
|
138
|
+
functionName: 'createCampaign',
|
|
139
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
140
|
+
args: [args] as any,
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
return this.createTransactionResult(hash);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Create a Vested Airdrop campaign
|
|
148
|
+
*
|
|
149
|
+
* Tokens vest linearly over time with optional cliff period.
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```typescript
|
|
153
|
+
* const result = await sdk.campaigns.createVestedAirdrop({
|
|
154
|
+
* token: '0x...',
|
|
155
|
+
* recipients: [
|
|
156
|
+
* { address: '0x...', amount: parseEther('1000') },
|
|
157
|
+
* ],
|
|
158
|
+
* startTime: Math.floor(Date.now() / 1000), // Start now
|
|
159
|
+
* duration: 365 * 24 * 60 * 60, // 1 year
|
|
160
|
+
* cliffDuration: 90 * 24 * 60 * 60, // 3 month cliff
|
|
161
|
+
* steps: 12, // Monthly releases
|
|
162
|
+
* });
|
|
163
|
+
* ```
|
|
164
|
+
*/
|
|
165
|
+
async createVestedAirdrop(
|
|
166
|
+
params: VestedAirdropParams
|
|
167
|
+
): Promise<TransactionResult> {
|
|
168
|
+
const wallet = this.requireWallet();
|
|
169
|
+
|
|
170
|
+
const recipients = params.recipients.map((r) => r.address);
|
|
171
|
+
const amounts = params.recipients.map((r) => r.amount);
|
|
172
|
+
|
|
173
|
+
const startTime = BigInt(params.startTime);
|
|
174
|
+
const endTime = startTime + BigInt(params.duration);
|
|
175
|
+
const steps = params.steps ?? 1;
|
|
176
|
+
const step = steps > 1 ? BigInt(params.duration) / BigInt(steps) : 0n;
|
|
177
|
+
const cliffReleaseTime = params.cliffDuration
|
|
178
|
+
? startTime + BigInt(params.cliffDuration)
|
|
179
|
+
: 0n;
|
|
180
|
+
|
|
181
|
+
const args: CreateArgs = {
|
|
182
|
+
kind: CampaignKind.VESTED,
|
|
183
|
+
token: params.token,
|
|
184
|
+
start: startTime,
|
|
185
|
+
end: endTime,
|
|
186
|
+
step,
|
|
187
|
+
cliffReleaseTime,
|
|
188
|
+
cliffBps: params.cliffBps ?? 0,
|
|
189
|
+
autoClaimIncentiveBps: params.autoClaimIncentiveBps ?? 0,
|
|
190
|
+
cancelable: params.cancelable ?? true,
|
|
191
|
+
claimOnce: false, // Vested can claim multiple times
|
|
192
|
+
changePolicy: this.changePolicyToEnum(params.changePolicy),
|
|
193
|
+
claimGrace: BigInt(params.claimGrace ?? 0),
|
|
194
|
+
recipients,
|
|
195
|
+
amounts,
|
|
196
|
+
feeBuffer: params.feeBuffer ?? 0n,
|
|
197
|
+
attachDefaultRegistry: params.attachDefaultRegistry ?? false,
|
|
198
|
+
unwrapWETH: params.unwrapWETH ?? false,
|
|
199
|
+
weth: params.weth ?? zeroAddress,
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
const hash = await wallet.writeContract({
|
|
203
|
+
chain: wallet.chain,
|
|
204
|
+
account: wallet.account!,
|
|
205
|
+
address: this.diamondAddress,
|
|
206
|
+
abi: DIAMOND_ABI,
|
|
207
|
+
functionName: 'createCampaign',
|
|
208
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
209
|
+
args: [args] as any,
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
return this.createTransactionResult(hash);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Create a Token Lock
|
|
217
|
+
*
|
|
218
|
+
* Tokens are locked until a specific unlock time, then fully releasable.
|
|
219
|
+
*
|
|
220
|
+
* @example
|
|
221
|
+
* ```typescript
|
|
222
|
+
* const result = await sdk.campaigns.createLock({
|
|
223
|
+
* token: '0x...',
|
|
224
|
+
* recipient: '0x...',
|
|
225
|
+
* amount: parseEther('1000000'),
|
|
226
|
+
* unlockTime: Math.floor(Date.now() / 1000) + 180 * 24 * 60 * 60, // 6 months
|
|
227
|
+
* });
|
|
228
|
+
* ```
|
|
229
|
+
*/
|
|
230
|
+
async createLock(params: LockParams): Promise<TransactionResult> {
|
|
231
|
+
const wallet = this.requireWallet();
|
|
232
|
+
|
|
233
|
+
const now = BigInt(Math.floor(Date.now() / 1000));
|
|
234
|
+
const unlockTime = BigInt(params.unlockTime);
|
|
235
|
+
|
|
236
|
+
const args: CreateArgs = {
|
|
237
|
+
kind: CampaignKind.LOCK,
|
|
238
|
+
token: params.token,
|
|
239
|
+
start: now,
|
|
240
|
+
end: unlockTime,
|
|
241
|
+
step: 0n,
|
|
242
|
+
cliffReleaseTime: unlockTime, // Lock releases at this time
|
|
243
|
+
cliffBps: 10000, // 100% released at cliff
|
|
244
|
+
autoClaimIncentiveBps: 0,
|
|
245
|
+
cancelable: params.cancelable ?? false,
|
|
246
|
+
claimOnce: true,
|
|
247
|
+
changePolicy: this.changePolicyToEnum(params.changePolicy),
|
|
248
|
+
claimGrace: 0n,
|
|
249
|
+
recipients: [params.recipient],
|
|
250
|
+
amounts: [params.amount],
|
|
251
|
+
feeBuffer: params.feeBuffer ?? 0n,
|
|
252
|
+
attachDefaultRegistry: false,
|
|
253
|
+
unwrapWETH: params.unwrapWETH ?? false,
|
|
254
|
+
weth: params.weth ?? zeroAddress,
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
const hash = await wallet.writeContract({
|
|
258
|
+
chain: wallet.chain,
|
|
259
|
+
account: wallet.account!,
|
|
260
|
+
address: this.diamondAddress,
|
|
261
|
+
abi: DIAMOND_ABI,
|
|
262
|
+
functionName: 'createCampaign',
|
|
263
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
264
|
+
args: [args] as any,
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
return this.createTransactionResult(hash);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Create a Vesting Stream (Payment)
|
|
272
|
+
*
|
|
273
|
+
* Single-recipient vesting with optional automation.
|
|
274
|
+
*
|
|
275
|
+
* @example
|
|
276
|
+
* ```typescript
|
|
277
|
+
* const result = await sdk.campaigns.createVesting({
|
|
278
|
+
* token: '0x...',
|
|
279
|
+
* recipient: '0x...',
|
|
280
|
+
* amount: parseEther('120000'), // 120k tokens
|
|
281
|
+
* startTime: Math.floor(Date.now() / 1000),
|
|
282
|
+
* duration: 365 * 24 * 60 * 60, // 1 year
|
|
283
|
+
* cliffDuration: 0, // No cliff
|
|
284
|
+
* steps: 12, // Monthly
|
|
285
|
+
* });
|
|
286
|
+
* ```
|
|
287
|
+
*/
|
|
288
|
+
async createVesting(params: VestingParams): Promise<TransactionResult> {
|
|
289
|
+
const wallet = this.requireWallet();
|
|
290
|
+
|
|
291
|
+
const startTime = BigInt(params.startTime);
|
|
292
|
+
const endTime = startTime + BigInt(params.duration);
|
|
293
|
+
const steps = params.steps ?? 1;
|
|
294
|
+
const step = steps > 1 ? BigInt(params.duration) / BigInt(steps) : 0n;
|
|
295
|
+
const cliffReleaseTime = params.cliffDuration
|
|
296
|
+
? startTime + BigInt(params.cliffDuration)
|
|
297
|
+
: 0n;
|
|
298
|
+
|
|
299
|
+
const args: CreateArgs = {
|
|
300
|
+
kind: CampaignKind.VESTING,
|
|
301
|
+
token: params.token,
|
|
302
|
+
start: startTime,
|
|
303
|
+
end: endTime,
|
|
304
|
+
step,
|
|
305
|
+
cliffReleaseTime,
|
|
306
|
+
cliffBps: params.cliffBps ?? 0,
|
|
307
|
+
autoClaimIncentiveBps: params.autoClaimIncentiveBps ?? 0,
|
|
308
|
+
cancelable: params.cancelable ?? true,
|
|
309
|
+
claimOnce: false,
|
|
310
|
+
changePolicy: this.changePolicyToEnum(params.changePolicy),
|
|
311
|
+
claimGrace: BigInt(params.claimGrace ?? 0),
|
|
312
|
+
recipients: [params.recipient],
|
|
313
|
+
amounts: [params.amount],
|
|
314
|
+
feeBuffer: params.feeBuffer ?? 0n,
|
|
315
|
+
attachDefaultRegistry: false,
|
|
316
|
+
unwrapWETH: params.unwrapWETH ?? false,
|
|
317
|
+
weth: params.weth ?? zeroAddress,
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
const hash = await wallet.writeContract({
|
|
321
|
+
chain: wallet.chain,
|
|
322
|
+
account: wallet.account!,
|
|
323
|
+
address: this.diamondAddress,
|
|
324
|
+
abi: DIAMOND_ABI,
|
|
325
|
+
functionName: 'createCampaign',
|
|
326
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
327
|
+
args: [args] as any,
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
return this.createTransactionResult(hash);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Create a campaign with raw CreateArgs
|
|
335
|
+
*
|
|
336
|
+
* Low-level function for full control over campaign parameters.
|
|
337
|
+
*/
|
|
338
|
+
async createCampaign(args: CreateArgs): Promise<TransactionResult> {
|
|
339
|
+
const wallet = this.requireWallet();
|
|
340
|
+
|
|
341
|
+
const hash = await wallet.writeContract({
|
|
342
|
+
chain: wallet.chain,
|
|
343
|
+
account: wallet.account!,
|
|
344
|
+
address: this.diamondAddress,
|
|
345
|
+
abi: DIAMOND_ABI,
|
|
346
|
+
functionName: 'createCampaign',
|
|
347
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
348
|
+
args: [args] as any,
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
return this.createTransactionResult(hash);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// ============================================================================
|
|
355
|
+
// Campaign Funding
|
|
356
|
+
// ============================================================================
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Fund a campaign using EIP-2612 Permit (gasless approval)
|
|
360
|
+
*
|
|
361
|
+
* @example
|
|
362
|
+
* ```typescript
|
|
363
|
+
* const result = await sdk.campaigns.fundWithPermit({
|
|
364
|
+
* campaignId,
|
|
365
|
+
* amount: parseEther('1000'),
|
|
366
|
+
* deadline: Math.floor(Date.now() / 1000) + 3600,
|
|
367
|
+
* v: 28,
|
|
368
|
+
* r: '0x...',
|
|
369
|
+
* s: '0x...',
|
|
370
|
+
* });
|
|
371
|
+
* ```
|
|
372
|
+
*/
|
|
373
|
+
async fundWithPermit(params: {
|
|
374
|
+
campaignId: bigint;
|
|
375
|
+
amount: bigint;
|
|
376
|
+
deadline: bigint;
|
|
377
|
+
v: number;
|
|
378
|
+
r: Hex;
|
|
379
|
+
s: Hex;
|
|
380
|
+
}): Promise<TransactionResult> {
|
|
381
|
+
const wallet = this.requireWallet();
|
|
382
|
+
|
|
383
|
+
const hash = await wallet.writeContract({
|
|
384
|
+
chain: wallet.chain,
|
|
385
|
+
account: wallet.account!,
|
|
386
|
+
address: this.diamondAddress,
|
|
387
|
+
abi: DIAMOND_ABI,
|
|
388
|
+
functionName: 'fundWithPermit',
|
|
389
|
+
args: [
|
|
390
|
+
params.campaignId,
|
|
391
|
+
params.amount,
|
|
392
|
+
params.deadline,
|
|
393
|
+
params.v,
|
|
394
|
+
params.r,
|
|
395
|
+
params.s,
|
|
396
|
+
],
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
return this.createTransactionResult(hash);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Fund a campaign using Permit2 (gasless approval)
|
|
404
|
+
*
|
|
405
|
+
* @example
|
|
406
|
+
* ```typescript
|
|
407
|
+
* const result = await sdk.campaigns.fundWithPermit2({
|
|
408
|
+
* campaignId,
|
|
409
|
+
* from: userAddress,
|
|
410
|
+
* amount: parseEther('1000'),
|
|
411
|
+
* permit2Data: encodedPermit2Data,
|
|
412
|
+
* });
|
|
413
|
+
* ```
|
|
414
|
+
*/
|
|
415
|
+
async fundWithPermit2(params: {
|
|
416
|
+
campaignId: bigint;
|
|
417
|
+
from: Address;
|
|
418
|
+
amount: bigint;
|
|
419
|
+
permit2Data: Hex;
|
|
420
|
+
}): Promise<TransactionResult> {
|
|
421
|
+
const wallet = this.requireWallet();
|
|
422
|
+
|
|
423
|
+
const hash = await wallet.writeContract({
|
|
424
|
+
chain: wallet.chain,
|
|
425
|
+
account: wallet.account!,
|
|
426
|
+
address: this.diamondAddress,
|
|
427
|
+
abi: DIAMOND_ABI,
|
|
428
|
+
functionName: 'fundWithPermit2',
|
|
429
|
+
args: [
|
|
430
|
+
params.campaignId,
|
|
431
|
+
params.from,
|
|
432
|
+
params.amount,
|
|
433
|
+
params.permit2Data,
|
|
434
|
+
],
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
return this.createTransactionResult(hash);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Return leftover tokens to creator
|
|
442
|
+
*
|
|
443
|
+
* @example
|
|
444
|
+
* ```typescript
|
|
445
|
+
* const result = await sdk.campaigns.returnLeftover(campaignId, parseEther('100'));
|
|
446
|
+
* ```
|
|
447
|
+
*/
|
|
448
|
+
async returnLeftover(
|
|
449
|
+
campaignId: bigint,
|
|
450
|
+
amountToReturn: bigint
|
|
451
|
+
): Promise<TransactionResult> {
|
|
452
|
+
const wallet = this.requireWallet();
|
|
453
|
+
|
|
454
|
+
const hash = await wallet.writeContract({
|
|
455
|
+
chain: wallet.chain,
|
|
456
|
+
account: wallet.account!,
|
|
457
|
+
address: this.diamondAddress,
|
|
458
|
+
abi: DIAMOND_ABI,
|
|
459
|
+
functionName: 'returnLeftover',
|
|
460
|
+
args: [campaignId, amountToReturn],
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
return this.createTransactionResult(hash);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Add native tips to a campaign for automation
|
|
468
|
+
*/
|
|
469
|
+
async addNativeTips(
|
|
470
|
+
campaignId: bigint,
|
|
471
|
+
tipAmount: bigint
|
|
472
|
+
): Promise<TransactionResult> {
|
|
473
|
+
const wallet = this.requireWallet();
|
|
474
|
+
|
|
475
|
+
const hash = await wallet.writeContract({
|
|
476
|
+
chain: wallet.chain,
|
|
477
|
+
account: wallet.account!,
|
|
478
|
+
address: this.diamondAddress,
|
|
479
|
+
abi: DIAMOND_ABI,
|
|
480
|
+
functionName: 'addNativeTips',
|
|
481
|
+
args: [campaignId, tipAmount],
|
|
482
|
+
value: tipAmount,
|
|
483
|
+
});
|
|
484
|
+
|
|
485
|
+
return this.createTransactionResult(hash);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
// ============================================================================
|
|
489
|
+
// Campaign Queries
|
|
490
|
+
// ============================================================================
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* Get campaign summary by ID
|
|
494
|
+
*
|
|
495
|
+
* Returns full campaign configuration and state.
|
|
496
|
+
*
|
|
497
|
+
* @example
|
|
498
|
+
* ```typescript
|
|
499
|
+
* const campaign = await sdk.campaigns.getCampaign(1n);
|
|
500
|
+
* console.log('Campaign token:', campaign.token);
|
|
501
|
+
* console.log('Total claimed:', campaign.totalClaimed);
|
|
502
|
+
* ```
|
|
503
|
+
*/
|
|
504
|
+
async getCampaign(campaignId: bigint): Promise<CampaignInfo> {
|
|
505
|
+
const result = await this.publicClient.readContract({
|
|
506
|
+
address: this.diamondAddress,
|
|
507
|
+
abi: DIAMOND_ABI,
|
|
508
|
+
functionName: 'campaignSummary',
|
|
509
|
+
args: [campaignId],
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
return this.parseCampaignSummary(campaignId, result as Record<string, unknown>);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* Get campaign configuration only
|
|
517
|
+
*/
|
|
518
|
+
async getCampaignConfig(campaignId: bigint): Promise<{
|
|
519
|
+
kind: number;
|
|
520
|
+
cancelable: boolean;
|
|
521
|
+
claimOnce: boolean;
|
|
522
|
+
canceled: boolean;
|
|
523
|
+
changePolicy: number;
|
|
524
|
+
token: Address;
|
|
525
|
+
creator: Address;
|
|
526
|
+
cliffBps: number;
|
|
527
|
+
autoClaimIncentiveBps: number;
|
|
528
|
+
start: number;
|
|
529
|
+
end: number;
|
|
530
|
+
step: number;
|
|
531
|
+
canceledAt: number;
|
|
532
|
+
cliffReleaseTime: number;
|
|
533
|
+
claimGrace: number;
|
|
534
|
+
unwrapWETH: boolean;
|
|
535
|
+
weth: Address;
|
|
536
|
+
}> {
|
|
537
|
+
const result = await this.publicClient.readContract({
|
|
538
|
+
address: this.diamondAddress,
|
|
539
|
+
abi: DIAMOND_ABI,
|
|
540
|
+
functionName: 'campaignConfig',
|
|
541
|
+
args: [campaignId],
|
|
542
|
+
}) as Record<string, unknown>;
|
|
543
|
+
|
|
544
|
+
return {
|
|
545
|
+
kind: Number(result.kind),
|
|
546
|
+
cancelable: Boolean(result.cancelable),
|
|
547
|
+
claimOnce: Boolean(result.claimOnce),
|
|
548
|
+
canceled: Boolean(result.canceled),
|
|
549
|
+
changePolicy: Number(result.changePolicy),
|
|
550
|
+
token: result.token as Address,
|
|
551
|
+
creator: result.creator as Address,
|
|
552
|
+
cliffBps: Number(result.cliffBps),
|
|
553
|
+
autoClaimIncentiveBps: Number(result.autoClaimIncentiveBps),
|
|
554
|
+
start: Number(result.start),
|
|
555
|
+
end: Number(result.end),
|
|
556
|
+
step: Number(result.step),
|
|
557
|
+
canceledAt: Number(result.canceledAt),
|
|
558
|
+
cliffReleaseTime: Number(result.cliffReleaseTime),
|
|
559
|
+
claimGrace: Number(result.claimGrace),
|
|
560
|
+
unwrapWETH: Boolean(result.unwrapWETH),
|
|
561
|
+
weth: result.weth as Address,
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
/**
|
|
566
|
+
* Get campaign state (totals and accounting)
|
|
567
|
+
*/
|
|
568
|
+
async getCampaignState(campaignId: bigint): Promise<{
|
|
569
|
+
totalAllocated: bigint;
|
|
570
|
+
totalClaimed: bigint;
|
|
571
|
+
nativeTips: bigint;
|
|
572
|
+
returned: bigint;
|
|
573
|
+
feeBuffer: bigint;
|
|
574
|
+
feeLoss: bigint;
|
|
575
|
+
totalFunded: bigint;
|
|
576
|
+
statusBits: number;
|
|
577
|
+
uniqueRecipients: bigint;
|
|
578
|
+
}> {
|
|
579
|
+
const result = await this.publicClient.readContract({
|
|
580
|
+
address: this.diamondAddress,
|
|
581
|
+
abi: DIAMOND_ABI,
|
|
582
|
+
functionName: 'campaignState',
|
|
583
|
+
args: [campaignId],
|
|
584
|
+
}) as Record<string, unknown>;
|
|
585
|
+
|
|
586
|
+
return {
|
|
587
|
+
totalAllocated: result.totalAllocated as bigint,
|
|
588
|
+
totalClaimed: result.totalClaimed as bigint,
|
|
589
|
+
nativeTips: result.nativeTips as bigint,
|
|
590
|
+
returned: result.returned as bigint,
|
|
591
|
+
feeBuffer: result.feeBuffer as bigint,
|
|
592
|
+
feeLoss: result.feeLoss as bigint,
|
|
593
|
+
totalFunded: result.totalFunded as bigint,
|
|
594
|
+
statusBits: Number(result.statusBits),
|
|
595
|
+
uniqueRecipients: result.uniqueRecipients as bigint,
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
/**
|
|
600
|
+
* Get campaign status bits
|
|
601
|
+
*/
|
|
602
|
+
async getCampaignStatus(campaignId: bigint): Promise<number> {
|
|
603
|
+
const result = await this.publicClient.readContract({
|
|
604
|
+
address: this.diamondAddress,
|
|
605
|
+
abi: DIAMOND_ABI,
|
|
606
|
+
functionName: 'campaignStatus',
|
|
607
|
+
args: [campaignId],
|
|
608
|
+
});
|
|
609
|
+
|
|
610
|
+
return Number(result);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// ============================================================================
|
|
614
|
+
// Campaign Administration
|
|
615
|
+
// ============================================================================
|
|
616
|
+
|
|
617
|
+
/**
|
|
618
|
+
* Pause a campaign (creator or admin only)
|
|
619
|
+
*
|
|
620
|
+
* @param campaignId - Campaign ID
|
|
621
|
+
* @param reason - Pause reason as status bits (e.g., 1 for creator pause)
|
|
622
|
+
*/
|
|
623
|
+
async pause(campaignId: bigint, reason: number = 1): Promise<TransactionResult> {
|
|
624
|
+
const wallet = this.requireWallet();
|
|
625
|
+
|
|
626
|
+
const hash = await wallet.writeContract({
|
|
627
|
+
chain: wallet.chain,
|
|
628
|
+
account: wallet.account!,
|
|
629
|
+
address: this.diamondAddress,
|
|
630
|
+
abi: DIAMOND_ABI,
|
|
631
|
+
functionName: 'pauseCampaign',
|
|
632
|
+
args: [campaignId, reason],
|
|
633
|
+
});
|
|
634
|
+
|
|
635
|
+
return this.createTransactionResult(hash);
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
/**
|
|
639
|
+
* Resume a paused campaign
|
|
640
|
+
*
|
|
641
|
+
* @param campaignId - Campaign ID
|
|
642
|
+
* @param clearBits - Status bits to clear (e.g., 1 for creator pause)
|
|
643
|
+
*/
|
|
644
|
+
async resume(campaignId: bigint, clearBits: number = 1): Promise<TransactionResult> {
|
|
645
|
+
const wallet = this.requireWallet();
|
|
646
|
+
|
|
647
|
+
const hash = await wallet.writeContract({
|
|
648
|
+
chain: wallet.chain,
|
|
649
|
+
account: wallet.account!,
|
|
650
|
+
address: this.diamondAddress,
|
|
651
|
+
abi: DIAMOND_ABI,
|
|
652
|
+
functionName: 'resumeCampaign',
|
|
653
|
+
args: [campaignId, clearBits],
|
|
654
|
+
});
|
|
655
|
+
|
|
656
|
+
return this.createTransactionResult(hash);
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
/**
|
|
660
|
+
* Finalize a campaign (no more claims possible)
|
|
661
|
+
*/
|
|
662
|
+
async finalize(campaignId: bigint): Promise<TransactionResult> {
|
|
663
|
+
const wallet = this.requireWallet();
|
|
664
|
+
|
|
665
|
+
const hash = await wallet.writeContract({
|
|
666
|
+
chain: wallet.chain,
|
|
667
|
+
account: wallet.account!,
|
|
668
|
+
address: this.diamondAddress,
|
|
669
|
+
abi: DIAMOND_ABI,
|
|
670
|
+
functionName: 'finalizeCampaign',
|
|
671
|
+
args: [campaignId],
|
|
672
|
+
});
|
|
673
|
+
|
|
674
|
+
return this.createTransactionResult(hash);
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
/**
|
|
678
|
+
* Cancel a campaign and return funds to creator
|
|
679
|
+
*/
|
|
680
|
+
async cancel(campaignId: bigint): Promise<TransactionResult> {
|
|
681
|
+
const wallet = this.requireWallet();
|
|
682
|
+
|
|
683
|
+
const hash = await wallet.writeContract({
|
|
684
|
+
chain: wallet.chain,
|
|
685
|
+
account: wallet.account!,
|
|
686
|
+
address: this.diamondAddress,
|
|
687
|
+
abi: DIAMOND_ABI,
|
|
688
|
+
functionName: 'cancel',
|
|
689
|
+
args: [campaignId],
|
|
690
|
+
});
|
|
691
|
+
|
|
692
|
+
return this.createTransactionResult(hash);
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
/**
|
|
696
|
+
* Change a recipient address (for blocked recipients)
|
|
697
|
+
*/
|
|
698
|
+
async changeRecipient(
|
|
699
|
+
campaignId: bigint,
|
|
700
|
+
fromAddress: Address,
|
|
701
|
+
toAddress: Address
|
|
702
|
+
): Promise<TransactionResult> {
|
|
703
|
+
const wallet = this.requireWallet();
|
|
704
|
+
|
|
705
|
+
const hash = await wallet.writeContract({
|
|
706
|
+
chain: wallet.chain,
|
|
707
|
+
account: wallet.account!,
|
|
708
|
+
address: this.diamondAddress,
|
|
709
|
+
abi: DIAMOND_ABI,
|
|
710
|
+
functionName: 'changeRecipient',
|
|
711
|
+
args: [campaignId, fromAddress, toAddress],
|
|
712
|
+
});
|
|
713
|
+
|
|
714
|
+
return this.createTransactionResult(hash);
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
/**
|
|
718
|
+
* Add recipients to an existing campaign
|
|
719
|
+
*/
|
|
720
|
+
async addRecipients(
|
|
721
|
+
campaignId: bigint,
|
|
722
|
+
recipients: Address[],
|
|
723
|
+
amounts: bigint[],
|
|
724
|
+
additionalBuffer: bigint = 0n
|
|
725
|
+
): Promise<TransactionResult> {
|
|
726
|
+
const wallet = this.requireWallet();
|
|
727
|
+
|
|
728
|
+
const hash = await wallet.writeContract({
|
|
729
|
+
chain: wallet.chain,
|
|
730
|
+
account: wallet.account!,
|
|
731
|
+
address: this.diamondAddress,
|
|
732
|
+
abi: DIAMOND_ABI,
|
|
733
|
+
functionName: 'addRecipients',
|
|
734
|
+
args: [campaignId, recipients, amounts, additionalBuffer],
|
|
735
|
+
});
|
|
736
|
+
|
|
737
|
+
return this.createTransactionResult(hash);
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
// ============================================================================
|
|
741
|
+
// Helpers
|
|
742
|
+
// ============================================================================
|
|
743
|
+
|
|
744
|
+
private requireWallet(): WalletClient {
|
|
745
|
+
if (!this.walletClient) {
|
|
746
|
+
throw new Error(
|
|
747
|
+
'Wallet client required for write operations. Initialize SDK with a signer.'
|
|
748
|
+
);
|
|
749
|
+
}
|
|
750
|
+
return this.walletClient;
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
private changePolicyToEnum(
|
|
754
|
+
policy?: 'only_recipient' | 'only_creator' | 'both' | 'no_one'
|
|
755
|
+
): number {
|
|
756
|
+
switch (policy) {
|
|
757
|
+
case 'only_recipient':
|
|
758
|
+
return ChangePolicy.ONLY_RECIPIENT;
|
|
759
|
+
case 'only_creator':
|
|
760
|
+
return ChangePolicy.ONLY_CREATOR;
|
|
761
|
+
case 'both':
|
|
762
|
+
return ChangePolicy.BOTH;
|
|
763
|
+
case 'no_one':
|
|
764
|
+
return ChangePolicy.NO_ONE;
|
|
765
|
+
default:
|
|
766
|
+
return ChangePolicy.ONLY_RECIPIENT;
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
private parseCampaignSummary(id: bigint, data: Record<string, unknown>): CampaignInfo {
|
|
771
|
+
const cfg = data.cfg as Record<string, unknown>;
|
|
772
|
+
const state = data.state as Record<string, unknown>;
|
|
773
|
+
|
|
774
|
+
const kindMap: Record<number, CampaignInfo['kind']> = {
|
|
775
|
+
0: 'instant_airdrop',
|
|
776
|
+
1: 'vested_airdrop',
|
|
777
|
+
2: 'lock',
|
|
778
|
+
3: 'vesting',
|
|
779
|
+
};
|
|
780
|
+
|
|
781
|
+
const kind = Number(cfg.kind);
|
|
782
|
+
|
|
783
|
+
const result: CampaignInfo = {
|
|
784
|
+
id,
|
|
785
|
+
kind: kindMap[kind] ?? 'instant_airdrop',
|
|
786
|
+
token: cfg.token as Address,
|
|
787
|
+
creator: cfg.creator as Address,
|
|
788
|
+
name: '', // Not stored on-chain
|
|
789
|
+
totalAllocated: state.totalAllocated as bigint,
|
|
790
|
+
totalFunded: state.totalFunded as bigint,
|
|
791
|
+
totalClaimed: state.totalClaimed as bigint,
|
|
792
|
+
totalReturned: state.returned as bigint,
|
|
793
|
+
feeLoss: state.feeLoss as bigint,
|
|
794
|
+
feeBuffer: state.feeBuffer as bigint,
|
|
795
|
+
startTime: Number(cfg.start),
|
|
796
|
+
endTime: Number(cfg.end),
|
|
797
|
+
cliffTime: Number(cfg.cliffReleaseTime),
|
|
798
|
+
steps: Number(cfg.step) > 0 ? Math.ceil((Number(cfg.end) - Number(cfg.start)) / Number(cfg.step)) : 1,
|
|
799
|
+
recipientCount: Number(state.uniqueRecipients),
|
|
800
|
+
statusBits: Number(state.statusBits),
|
|
801
|
+
changePolicy: Number(cfg.changePolicy),
|
|
802
|
+
hasAutomation: (Number(state.statusBits) & (1 << 5)) !== 0,
|
|
803
|
+
};
|
|
804
|
+
|
|
805
|
+
// Add optional fields
|
|
806
|
+
if (data.hasRegistry) {
|
|
807
|
+
result.hasRegistry = true;
|
|
808
|
+
}
|
|
809
|
+
if (data.merkleRoot) {
|
|
810
|
+
result.merkleRoot = data.merkleRoot as Hex;
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
return result;
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
private createTransactionResult(hash: Hash): TransactionResult {
|
|
817
|
+
return {
|
|
818
|
+
hash,
|
|
819
|
+
wait: async () => {
|
|
820
|
+
const receipt = await this.publicClient.waitForTransactionReceipt({
|
|
821
|
+
hash,
|
|
822
|
+
});
|
|
823
|
+
return {
|
|
824
|
+
blockNumber: receipt.blockNumber,
|
|
825
|
+
transactionHash: receipt.transactionHash,
|
|
826
|
+
gasUsed: receipt.gasUsed,
|
|
827
|
+
status: receipt.status,
|
|
828
|
+
logs: receipt.logs,
|
|
829
|
+
};
|
|
830
|
+
},
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
export default CampaignsModule;
|