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
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
|