@bbuilders/djeon402-sdk-client 1.0.1

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.
@@ -0,0 +1,1211 @@
1
+ // src/react/provider.tsx
2
+ import { createContext, useContext, useMemo } from "react";
3
+
4
+ // src/client.ts
5
+ import { createPublicClient, http } from "viem";
6
+ import { base } from "viem/chains";
7
+
8
+ // src/modules/admin.ts
9
+ import {
10
+ DJEON402_ABI,
11
+ validateAddress
12
+ } from "@bbuilders/djeon402-core";
13
+ var AdminModule = class {
14
+ constructor(sdk) {
15
+ this.sdk = sdk;
16
+ }
17
+ /**
18
+ * Get role hashes
19
+ */
20
+ async getRoles() {
21
+ const [minter, burner, pauser, blacklister, admin] = await Promise.all([
22
+ this.sdk.publicClient.readContract({
23
+ address: this.sdk.contractAddress,
24
+ abi: DJEON402_ABI,
25
+ functionName: "MINTER_ROLE"
26
+ }),
27
+ this.sdk.publicClient.readContract({
28
+ address: this.sdk.contractAddress,
29
+ abi: DJEON402_ABI,
30
+ functionName: "BURNER_ROLE"
31
+ }),
32
+ this.sdk.publicClient.readContract({
33
+ address: this.sdk.contractAddress,
34
+ abi: DJEON402_ABI,
35
+ functionName: "PAUSER_ROLE"
36
+ }),
37
+ this.sdk.publicClient.readContract({
38
+ address: this.sdk.contractAddress,
39
+ abi: DJEON402_ABI,
40
+ functionName: "BLACKLISTER_ROLE"
41
+ }),
42
+ this.sdk.publicClient.readContract({
43
+ address: this.sdk.contractAddress,
44
+ abi: DJEON402_ABI,
45
+ functionName: "DEFAULT_ADMIN_ROLE"
46
+ })
47
+ ]);
48
+ return {
49
+ MINTER_ROLE: minter,
50
+ BURNER_ROLE: burner,
51
+ PAUSER_ROLE: pauser,
52
+ BLACKLISTER_ROLE: blacklister,
53
+ DEFAULT_ADMIN_ROLE: admin
54
+ };
55
+ }
56
+ /**
57
+ * Check if address has role
58
+ */
59
+ async hasRole(role, account) {
60
+ validateAddress(account);
61
+ const result = await this.sdk.publicClient.readContract({
62
+ address: this.sdk.contractAddress,
63
+ abi: DJEON402_ABI,
64
+ functionName: "hasRole",
65
+ args: [role, account]
66
+ });
67
+ return {
68
+ role,
69
+ address: account,
70
+ hasRole: result
71
+ };
72
+ }
73
+ /**
74
+ * Check if address is blacklisted
75
+ */
76
+ async isBlacklisted(account) {
77
+ validateAddress(account);
78
+ const isBlacklisted = await this.sdk.publicClient.readContract({
79
+ address: this.sdk.contractAddress,
80
+ abi: DJEON402_ABI,
81
+ functionName: "isBlacklisted",
82
+ args: [account]
83
+ });
84
+ return {
85
+ isBlacklisted,
86
+ address: account
87
+ };
88
+ }
89
+ /**
90
+ * Blacklist an address
91
+ */
92
+ async blacklist(params) {
93
+ const { walletClient, account } = params;
94
+ if (!walletClient.account) {
95
+ throw new Error("Wallet client must have an account");
96
+ }
97
+ validateAddress(account);
98
+ const hash = await walletClient.writeContract({
99
+ address: this.sdk.contractAddress,
100
+ abi: DJEON402_ABI,
101
+ functionName: "blacklist",
102
+ args: [account],
103
+ account: walletClient.account,
104
+ chain: walletClient.chain
105
+ });
106
+ const receipt = await this.sdk.publicClient.waitForTransactionReceipt({ hash });
107
+ return {
108
+ success: receipt.status === "success",
109
+ hash,
110
+ blockNumber: receipt.blockNumber.toString()
111
+ };
112
+ }
113
+ /**
114
+ * Remove from blacklist
115
+ */
116
+ async unBlacklist(params) {
117
+ const { walletClient, account } = params;
118
+ if (!walletClient.account) {
119
+ throw new Error("Wallet client must have an account");
120
+ }
121
+ validateAddress(account);
122
+ const hash = await walletClient.writeContract({
123
+ address: this.sdk.contractAddress,
124
+ abi: DJEON402_ABI,
125
+ functionName: "unBlacklist",
126
+ args: [account],
127
+ account: walletClient.account,
128
+ chain: walletClient.chain
129
+ });
130
+ const receipt = await this.sdk.publicClient.waitForTransactionReceipt({ hash });
131
+ return {
132
+ success: receipt.status === "success",
133
+ hash,
134
+ blockNumber: receipt.blockNumber.toString()
135
+ };
136
+ }
137
+ /**
138
+ * Pause contract
139
+ */
140
+ async pause(params) {
141
+ const { walletClient } = params;
142
+ if (!walletClient.account) {
143
+ throw new Error("Wallet client must have an account");
144
+ }
145
+ const hash = await walletClient.writeContract({
146
+ address: this.sdk.contractAddress,
147
+ abi: DJEON402_ABI,
148
+ functionName: "pause",
149
+ account: walletClient.account,
150
+ chain: walletClient.chain
151
+ });
152
+ const receipt = await this.sdk.publicClient.waitForTransactionReceipt({ hash });
153
+ return {
154
+ success: receipt.status === "success",
155
+ hash,
156
+ blockNumber: receipt.blockNumber.toString()
157
+ };
158
+ }
159
+ /**
160
+ * Unpause contract
161
+ */
162
+ async unpause(params) {
163
+ const { walletClient } = params;
164
+ if (!walletClient.account) {
165
+ throw new Error("Wallet client must have an account");
166
+ }
167
+ const hash = await walletClient.writeContract({
168
+ address: this.sdk.contractAddress,
169
+ abi: DJEON402_ABI,
170
+ functionName: "unpause",
171
+ account: walletClient.account,
172
+ chain: walletClient.chain
173
+ });
174
+ const receipt = await this.sdk.publicClient.waitForTransactionReceipt({ hash });
175
+ return {
176
+ success: receipt.status === "success",
177
+ hash,
178
+ blockNumber: receipt.blockNumber.toString()
179
+ };
180
+ }
181
+ };
182
+
183
+ // src/modules/kyc.ts
184
+ import {
185
+ KYC_REGISTRY_ABI,
186
+ validateAddress as validateAddress2
187
+ } from "@bbuilders/djeon402-core";
188
+ var KYCModule = class {
189
+ constructor(sdk) {
190
+ this.sdk = sdk;
191
+ }
192
+ /**
193
+ * Get KYC data for an address
194
+ */
195
+ async getData(address) {
196
+ if (!this.sdk.kycRegistryAddress) {
197
+ throw new Error("KYC Registry address not configured");
198
+ }
199
+ validateAddress2(address);
200
+ const kycData = await this.sdk.publicClient.readContract({
201
+ address: this.sdk.kycRegistryAddress,
202
+ abi: KYC_REGISTRY_ABI,
203
+ functionName: "getKYCData",
204
+ args: [address]
205
+ });
206
+ const result = kycData;
207
+ const [level, expiryDate, kycHash, isActive, dailyLimit, dailySpent] = result;
208
+ const levelNames = ["None", "Tier1", "Tier2", "Tier3"];
209
+ const expiryDateReadable = new Date(Number(expiryDate) * 1e3).toISOString();
210
+ return {
211
+ level,
212
+ levelName: levelNames[level],
213
+ expiryDate: Number(expiryDate),
214
+ expiryDateReadable,
215
+ kycHash,
216
+ isActive,
217
+ dailyLimit: dailyLimit.toString(),
218
+ dailyLimitRaw: dailyLimit.toString(),
219
+ dailySpent: dailySpent.toString(),
220
+ dailySpentRaw: dailySpent.toString(),
221
+ userAddress: address
222
+ };
223
+ }
224
+ /**
225
+ * Get remaining daily limit
226
+ */
227
+ async getRemainingLimit(address) {
228
+ if (!this.sdk.kycRegistryAddress) {
229
+ throw new Error("KYC Registry address not configured");
230
+ }
231
+ validateAddress2(address);
232
+ const remaining = await this.sdk.publicClient.readContract({
233
+ address: this.sdk.kycRegistryAddress,
234
+ abi: KYC_REGISTRY_ABI,
235
+ functionName: "getRemainingDailyLimit",
236
+ args: [address]
237
+ });
238
+ return {
239
+ address,
240
+ remainingLimit: remaining.toString()
241
+ };
242
+ }
243
+ /**
244
+ * Verify KYC (admin only)
245
+ */
246
+ async verify(params) {
247
+ if (!this.sdk.kycRegistryAddress) {
248
+ throw new Error("KYC Registry address not configured");
249
+ }
250
+ const { walletClient, userAddress, level, expiryDate, documentHash } = params;
251
+ if (!walletClient.account) {
252
+ throw new Error("Wallet client must have an account");
253
+ }
254
+ validateAddress2(userAddress);
255
+ if (level < 0 || level > 3) {
256
+ throw new Error("Invalid KYC level. Must be 0-3");
257
+ }
258
+ const hash = await walletClient.writeContract({
259
+ address: this.sdk.kycRegistryAddress,
260
+ abi: KYC_REGISTRY_ABI,
261
+ functionName: "verifyKYC",
262
+ args: [userAddress, level, BigInt(expiryDate), documentHash],
263
+ account: walletClient.account,
264
+ chain: walletClient.chain
265
+ });
266
+ const receipt = await this.sdk.publicClient.waitForTransactionReceipt({ hash });
267
+ return {
268
+ success: receipt.status === "success",
269
+ hash,
270
+ blockNumber: receipt.blockNumber.toString()
271
+ };
272
+ }
273
+ /**
274
+ * Update KYC level (admin only)
275
+ */
276
+ async updateKYC(params) {
277
+ if (!this.sdk.kycRegistryAddress) {
278
+ throw new Error("KYC Registry address not configured");
279
+ }
280
+ const { walletClient, userAddress, level, expiryDate = 0 } = params;
281
+ if (!walletClient.account) {
282
+ throw new Error("Wallet client must have an account");
283
+ }
284
+ validateAddress2(userAddress);
285
+ const hash = await walletClient.writeContract({
286
+ address: this.sdk.kycRegistryAddress,
287
+ abi: KYC_REGISTRY_ABI,
288
+ functionName: "updateKYC",
289
+ args: [userAddress, level, BigInt(expiryDate)],
290
+ account: walletClient.account,
291
+ chain: walletClient.chain
292
+ });
293
+ const receipt = await this.sdk.publicClient.waitForTransactionReceipt({ hash });
294
+ return {
295
+ success: receipt.status === "success",
296
+ hash,
297
+ blockNumber: receipt.blockNumber.toString()
298
+ };
299
+ }
300
+ /**
301
+ * Revoke KYC (admin only)
302
+ */
303
+ async revokeKYC(params) {
304
+ if (!this.sdk.kycRegistryAddress) {
305
+ throw new Error("KYC Registry address not configured");
306
+ }
307
+ const { walletClient, userAddress } = params;
308
+ if (!walletClient.account) {
309
+ throw new Error("Wallet client must have an account");
310
+ }
311
+ validateAddress2(userAddress);
312
+ const hash = await walletClient.writeContract({
313
+ address: this.sdk.kycRegistryAddress,
314
+ abi: KYC_REGISTRY_ABI,
315
+ functionName: "revokeKYC",
316
+ args: [userAddress],
317
+ account: walletClient.account,
318
+ chain: walletClient.chain
319
+ });
320
+ const receipt = await this.sdk.publicClient.waitForTransactionReceipt({ hash });
321
+ return {
322
+ success: receipt.status === "success",
323
+ hash,
324
+ blockNumber: receipt.blockNumber.toString()
325
+ };
326
+ }
327
+ /**
328
+ * Set daily limit for a user (admin only)
329
+ */
330
+ async setDailyLimit(params) {
331
+ if (!this.sdk.kycRegistryAddress) {
332
+ throw new Error("KYC Registry address not configured");
333
+ }
334
+ const { walletClient, userAddress, limitUSD } = params;
335
+ if (!walletClient.account) {
336
+ throw new Error("Wallet client must have an account");
337
+ }
338
+ validateAddress2(userAddress);
339
+ const limitInSmallestUnit = BigInt(parseFloat(limitUSD) * 1e6);
340
+ const hash = await walletClient.writeContract({
341
+ address: this.sdk.kycRegistryAddress,
342
+ abi: KYC_REGISTRY_ABI,
343
+ functionName: "setDailyLimit",
344
+ args: [userAddress, limitInSmallestUnit],
345
+ account: walletClient.account,
346
+ chain: walletClient.chain
347
+ });
348
+ const receipt = await this.sdk.publicClient.waitForTransactionReceipt({ hash });
349
+ return {
350
+ success: receipt.status === "success",
351
+ hash,
352
+ blockNumber: receipt.blockNumber.toString()
353
+ };
354
+ }
355
+ /**
356
+ * Check if a transaction amount is within the user's daily limit
357
+ */
358
+ async checkDailyLimit(params) {
359
+ if (!this.sdk.kycRegistryAddress) {
360
+ throw new Error("KYC Registry address not configured");
361
+ }
362
+ const { walletClient, userAddress, amountUSD } = params;
363
+ if (!walletClient.account) {
364
+ throw new Error("Wallet client must have an account");
365
+ }
366
+ validateAddress2(userAddress);
367
+ const amountInSmallestUnit = BigInt(parseFloat(amountUSD) * 1e6);
368
+ const result = await walletClient.writeContract({
369
+ address: this.sdk.kycRegistryAddress,
370
+ abi: KYC_REGISTRY_ABI,
371
+ functionName: "checkDailyLimit",
372
+ args: [userAddress, amountInSmallestUnit],
373
+ account: walletClient.account,
374
+ chain: walletClient.chain
375
+ });
376
+ return result;
377
+ }
378
+ /**
379
+ * Check if a user's KYC is valid (view)
380
+ */
381
+ async isKYCValid(userAddress) {
382
+ if (!this.sdk.kycRegistryAddress) {
383
+ throw new Error("KYC Registry address not configured");
384
+ }
385
+ validateAddress2(userAddress);
386
+ const result = await this.sdk.publicClient.readContract({
387
+ address: this.sdk.kycRegistryAddress,
388
+ abi: KYC_REGISTRY_ABI,
389
+ functionName: "isKYCValid",
390
+ args: [userAddress]
391
+ });
392
+ return result;
393
+ }
394
+ };
395
+
396
+ // src/modules/token.ts
397
+ import {
398
+ DJEON402_ABI as DJEON402_ABI2,
399
+ formatTokenAmount,
400
+ parseTokenAmount,
401
+ validateAddress as validateAddress3,
402
+ validateAmount
403
+ } from "@bbuilders/djeon402-core";
404
+ var TokenModule = class {
405
+ constructor(sdk) {
406
+ this.sdk = sdk;
407
+ }
408
+ /**
409
+ * Get token information
410
+ */
411
+ async getInfo() {
412
+ const [name, symbol, decimals, totalSupply, paused] = await Promise.all([
413
+ this.sdk.publicClient.readContract({
414
+ address: this.sdk.contractAddress,
415
+ abi: DJEON402_ABI2,
416
+ functionName: "name"
417
+ }),
418
+ this.sdk.publicClient.readContract({
419
+ address: this.sdk.contractAddress,
420
+ abi: DJEON402_ABI2,
421
+ functionName: "symbol"
422
+ }),
423
+ this.sdk.publicClient.readContract({
424
+ address: this.sdk.contractAddress,
425
+ abi: DJEON402_ABI2,
426
+ functionName: "decimals"
427
+ }),
428
+ this.sdk.publicClient.readContract({
429
+ address: this.sdk.contractAddress,
430
+ abi: DJEON402_ABI2,
431
+ functionName: "totalSupply"
432
+ }),
433
+ this.sdk.publicClient.readContract({
434
+ address: this.sdk.contractAddress,
435
+ abi: DJEON402_ABI2,
436
+ functionName: "paused"
437
+ })
438
+ ]);
439
+ return {
440
+ name,
441
+ symbol,
442
+ decimals,
443
+ totalSupply: formatTokenAmount(totalSupply, decimals),
444
+ totalSupplyRaw: totalSupply.toString(),
445
+ paused,
446
+ contractAddress: this.sdk.contractAddress
447
+ };
448
+ }
449
+ /**
450
+ * Get balance of an address
451
+ */
452
+ async getBalance(address) {
453
+ validateAddress3(address);
454
+ const [balance, decimals] = await Promise.all([
455
+ this.sdk.publicClient.readContract({
456
+ address: this.sdk.contractAddress,
457
+ abi: DJEON402_ABI2,
458
+ functionName: "balanceOf",
459
+ args: [address]
460
+ }),
461
+ this.sdk.publicClient.readContract({
462
+ address: this.sdk.contractAddress,
463
+ abi: DJEON402_ABI2,
464
+ functionName: "decimals"
465
+ })
466
+ ]);
467
+ return {
468
+ address,
469
+ balance: formatTokenAmount(balance, decimals),
470
+ balanceRaw: balance.toString()
471
+ };
472
+ }
473
+ /**
474
+ * Get allowance
475
+ */
476
+ async getAllowance(owner, spender) {
477
+ validateAddress3(owner);
478
+ validateAddress3(spender);
479
+ const [allowance, decimals] = await Promise.all([
480
+ this.sdk.publicClient.readContract({
481
+ address: this.sdk.contractAddress,
482
+ abi: DJEON402_ABI2,
483
+ functionName: "allowance",
484
+ args: [owner, spender]
485
+ }),
486
+ this.sdk.publicClient.readContract({
487
+ address: this.sdk.contractAddress,
488
+ abi: DJEON402_ABI2,
489
+ functionName: "decimals"
490
+ })
491
+ ]);
492
+ return {
493
+ owner,
494
+ spender,
495
+ allowance: formatTokenAmount(allowance, decimals),
496
+ allowanceRaw: allowance.toString()
497
+ };
498
+ }
499
+ /**
500
+ * Transfer tokens using wallet client
501
+ */
502
+ async transfer(params) {
503
+ const { walletClient, to, amount } = params;
504
+ if (!walletClient.account) {
505
+ throw new Error("Wallet client must have an account");
506
+ }
507
+ validateAddress3(to);
508
+ validateAmount(amount);
509
+ const decimals = await this.sdk.publicClient.readContract({
510
+ address: this.sdk.contractAddress,
511
+ abi: DJEON402_ABI2,
512
+ functionName: "decimals"
513
+ });
514
+ const amountBigInt = parseTokenAmount(amount, decimals);
515
+ const hash = await walletClient.writeContract({
516
+ address: this.sdk.contractAddress,
517
+ abi: DJEON402_ABI2,
518
+ functionName: "transfer",
519
+ args: [to, amountBigInt],
520
+ account: walletClient.account,
521
+ chain: walletClient.chain
522
+ });
523
+ const receipt = await this.sdk.publicClient.waitForTransactionReceipt({
524
+ hash
525
+ });
526
+ return {
527
+ success: receipt.status === "success",
528
+ hash,
529
+ from: walletClient.account.address,
530
+ to,
531
+ amount,
532
+ amountRaw: amountBigInt.toString(),
533
+ blockNumber: receipt.blockNumber.toString(),
534
+ status: receipt.status
535
+ };
536
+ }
537
+ /**
538
+ * Approve spending
539
+ */
540
+ async approve(params) {
541
+ const { walletClient, spender, amount } = params;
542
+ if (!walletClient.account) {
543
+ throw new Error("Wallet client must have an account");
544
+ }
545
+ validateAddress3(spender);
546
+ validateAmount(amount);
547
+ const decimals = await this.sdk.publicClient.readContract({
548
+ address: this.sdk.contractAddress,
549
+ abi: DJEON402_ABI2,
550
+ functionName: "decimals"
551
+ });
552
+ const amountBigInt = parseTokenAmount(amount, decimals);
553
+ const hash = await walletClient.writeContract({
554
+ address: this.sdk.contractAddress,
555
+ abi: DJEON402_ABI2,
556
+ functionName: "approve",
557
+ args: [spender, amountBigInt],
558
+ account: walletClient.account,
559
+ chain: walletClient.chain
560
+ });
561
+ const receipt = await this.sdk.publicClient.waitForTransactionReceipt({ hash });
562
+ return {
563
+ success: receipt.status === "success",
564
+ hash,
565
+ blockNumber: receipt.blockNumber.toString()
566
+ };
567
+ }
568
+ /**
569
+ * Mint tokens (requires MINTER_ROLE)
570
+ */
571
+ async mint(params) {
572
+ const { walletClient, to, amount } = params;
573
+ if (!walletClient.account) {
574
+ throw new Error("Wallet client must have an account");
575
+ }
576
+ validateAddress3(to);
577
+ validateAmount(amount);
578
+ const decimals = await this.sdk.publicClient.readContract({
579
+ address: this.sdk.contractAddress,
580
+ abi: DJEON402_ABI2,
581
+ functionName: "decimals"
582
+ });
583
+ const amountBigInt = parseTokenAmount(amount, decimals);
584
+ const hash = await walletClient.writeContract({
585
+ address: this.sdk.contractAddress,
586
+ abi: DJEON402_ABI2,
587
+ functionName: "mint",
588
+ args: [to, amountBigInt],
589
+ account: walletClient.account,
590
+ chain: walletClient.chain
591
+ });
592
+ const receipt = await this.sdk.publicClient.waitForTransactionReceipt({ hash });
593
+ return {
594
+ success: receipt.status === "success",
595
+ hash,
596
+ blockNumber: receipt.blockNumber.toString()
597
+ };
598
+ }
599
+ /**
600
+ * Burn tokens (requires BURNER_ROLE)
601
+ */
602
+ async burn(params) {
603
+ const { walletClient, amount } = params;
604
+ if (!walletClient.account) {
605
+ throw new Error("Wallet client must have an account");
606
+ }
607
+ validateAmount(amount);
608
+ const decimals = await this.sdk.publicClient.readContract({
609
+ address: this.sdk.contractAddress,
610
+ abi: DJEON402_ABI2,
611
+ functionName: "decimals"
612
+ });
613
+ const amountBigInt = parseTokenAmount(amount, decimals);
614
+ const hash = await walletClient.writeContract({
615
+ address: this.sdk.contractAddress,
616
+ abi: DJEON402_ABI2,
617
+ functionName: "burn",
618
+ args: [amountBigInt],
619
+ account: walletClient.account,
620
+ chain: walletClient.chain
621
+ });
622
+ const receipt = await this.sdk.publicClient.waitForTransactionReceipt({ hash });
623
+ return {
624
+ success: receipt.status === "success",
625
+ hash,
626
+ blockNumber: receipt.blockNumber.toString()
627
+ };
628
+ }
629
+ };
630
+
631
+ // src/modules/x402.ts
632
+ import {
633
+ DJEON402_ABI as DJEON402_ABI3,
634
+ parseTokenAmount as parseTokenAmount2,
635
+ validateAddress as validateAddress4,
636
+ validateAmount as validateAmount2
637
+ } from "@bbuilders/djeon402-core";
638
+ var X402Module = class {
639
+ constructor(sdk) {
640
+ this.sdk = sdk;
641
+ }
642
+ /**
643
+ * Generate a random nonce
644
+ */
645
+ generateNonce() {
646
+ const randomBytes = new Uint8Array(32);
647
+ crypto.getRandomValues(randomBytes);
648
+ return `0x${Array.from(randomBytes).map((b) => b.toString(16).padStart(2, "0")).join("")}`;
649
+ }
650
+ /**
651
+ * Get EIP-712 domain separator
652
+ */
653
+ async getDomainSeparator() {
654
+ const domain = await this.sdk.publicClient.readContract({
655
+ address: this.sdk.contractAddress,
656
+ abi: DJEON402_ABI3,
657
+ functionName: "DOMAIN_SEPARATOR"
658
+ });
659
+ return domain;
660
+ }
661
+ /**
662
+ * Get authorization state (whether a nonce has been used)
663
+ */
664
+ async getAuthorizationState(authorizer, nonce) {
665
+ return await this.sdk.publicClient.readContract({
666
+ address: this.sdk.contractAddress,
667
+ abi: DJEON402_ABI3,
668
+ functionName: "authorizationState",
669
+ args: [authorizer, nonce]
670
+ });
671
+ }
672
+ /**
673
+ * Sign transfer authorization using wallet
674
+ */
675
+ async signTransferWithWallet(params) {
676
+ const { walletClient, to, amount, validAfter = 0n, validBefore, nonce } = params;
677
+ if (!walletClient.account) {
678
+ throw new Error("Wallet client must have an account");
679
+ }
680
+ validateAddress4(to);
681
+ validateAmount2(amount);
682
+ const from = walletClient.account.address;
683
+ const decimals = await this.sdk.publicClient.readContract({
684
+ address: this.sdk.contractAddress,
685
+ abi: DJEON402_ABI3,
686
+ functionName: "decimals"
687
+ });
688
+ const value = parseTokenAmount2(amount, decimals);
689
+ const transferNonce = nonce || this.generateNonce();
690
+ const validBeforeTimestamp = validBefore ?? BigInt(Math.floor(Date.now() / 1e3) + 3600);
691
+ const name = await this.sdk.publicClient.readContract({
692
+ address: this.sdk.contractAddress,
693
+ abi: DJEON402_ABI3,
694
+ functionName: "name"
695
+ });
696
+ const domain = {
697
+ name,
698
+ version: "1",
699
+ chainId: this.sdk.chainId,
700
+ verifyingContract: this.sdk.contractAddress
701
+ };
702
+ const types = {
703
+ TransferWithAuthorization: [
704
+ { name: "from", type: "address" },
705
+ { name: "to", type: "address" },
706
+ { name: "value", type: "uint256" },
707
+ { name: "validAfter", type: "uint256" },
708
+ { name: "validBefore", type: "uint256" },
709
+ { name: "nonce", type: "bytes32" }
710
+ ]
711
+ };
712
+ const message = {
713
+ from,
714
+ to,
715
+ value,
716
+ validAfter,
717
+ validBefore: validBeforeTimestamp,
718
+ nonce: transferNonce
719
+ };
720
+ const signature = await walletClient.signTypedData({
721
+ account: walletClient.account,
722
+ domain,
723
+ types,
724
+ primaryType: "TransferWithAuthorization",
725
+ message
726
+ });
727
+ const v = parseInt(signature.slice(130, 132), 16);
728
+ const r = `0x${signature.slice(2, 66)}`;
729
+ const s = `0x${signature.slice(66, 130)}`;
730
+ return {
731
+ from,
732
+ to,
733
+ value,
734
+ validAfter,
735
+ validBefore: validBeforeTimestamp,
736
+ nonce: transferNonce,
737
+ v,
738
+ r,
739
+ s
740
+ };
741
+ }
742
+ /**
743
+ * Sign receive authorization using wallet (receiver signs)
744
+ */
745
+ async signReceiveWithWallet(params) {
746
+ const { walletClient, from, amount, validAfter = 0n, validBefore, nonce } = params;
747
+ if (!walletClient.account) {
748
+ throw new Error("Wallet client must have an account");
749
+ }
750
+ validateAddress4(from);
751
+ validateAmount2(amount);
752
+ const to = walletClient.account.address;
753
+ const decimals = await this.sdk.publicClient.readContract({
754
+ address: this.sdk.contractAddress,
755
+ abi: DJEON402_ABI3,
756
+ functionName: "decimals"
757
+ });
758
+ const value = parseTokenAmount2(amount, decimals);
759
+ const receiveNonce = nonce || this.generateNonce();
760
+ const validBeforeTimestamp = validBefore ?? BigInt(Math.floor(Date.now() / 1e3) + 3600);
761
+ const name = await this.sdk.publicClient.readContract({
762
+ address: this.sdk.contractAddress,
763
+ abi: DJEON402_ABI3,
764
+ functionName: "name"
765
+ });
766
+ const domain = {
767
+ name,
768
+ version: "1",
769
+ chainId: this.sdk.chainId,
770
+ verifyingContract: this.sdk.contractAddress
771
+ };
772
+ const types = {
773
+ ReceiveWithAuthorization: [
774
+ { name: "from", type: "address" },
775
+ { name: "to", type: "address" },
776
+ { name: "value", type: "uint256" },
777
+ { name: "validAfter", type: "uint256" },
778
+ { name: "validBefore", type: "uint256" },
779
+ { name: "nonce", type: "bytes32" }
780
+ ]
781
+ };
782
+ const message = {
783
+ from,
784
+ to,
785
+ value,
786
+ validAfter,
787
+ validBefore: validBeforeTimestamp,
788
+ nonce: receiveNonce
789
+ };
790
+ const signature = await walletClient.signTypedData({
791
+ account: walletClient.account,
792
+ domain,
793
+ types,
794
+ primaryType: "ReceiveWithAuthorization",
795
+ message
796
+ });
797
+ const v = parseInt(signature.slice(130, 132), 16);
798
+ const r = `0x${signature.slice(2, 66)}`;
799
+ const s = `0x${signature.slice(66, 130)}`;
800
+ return {
801
+ from,
802
+ to,
803
+ value,
804
+ validAfter,
805
+ validBefore: validBeforeTimestamp,
806
+ nonce: receiveNonce,
807
+ v,
808
+ r,
809
+ s
810
+ };
811
+ }
812
+ /**
813
+ * Execute receive with authorization (caller must be the receiver)
814
+ */
815
+ async executeReceive(params) {
816
+ const { walletClient, authorization } = params;
817
+ if (!walletClient.account) {
818
+ throw new Error("Wallet client must have an account");
819
+ }
820
+ const { from, to, value, validAfter, validBefore, nonce, v, r, s } = authorization;
821
+ const hash = await walletClient.writeContract({
822
+ address: this.sdk.contractAddress,
823
+ abi: DJEON402_ABI3,
824
+ functionName: "receiveWithAuthorization",
825
+ args: [from, to, value, validAfter, validBefore, nonce, v, r, s],
826
+ account: walletClient.account,
827
+ chain: walletClient.chain
828
+ });
829
+ const receipt = await this.sdk.publicClient.waitForTransactionReceipt({ hash });
830
+ return {
831
+ success: receipt.status === "success",
832
+ hash,
833
+ blockNumber: receipt.blockNumber.toString()
834
+ };
835
+ }
836
+ /**
837
+ * Sign cancel authorization using wallet
838
+ */
839
+ async signCancelWithWallet(params) {
840
+ const { walletClient, authorizer, nonce: authNonce } = params;
841
+ if (!walletClient.account) {
842
+ throw new Error("Wallet client must have an account");
843
+ }
844
+ const name = await this.sdk.publicClient.readContract({
845
+ address: this.sdk.contractAddress,
846
+ abi: DJEON402_ABI3,
847
+ functionName: "name"
848
+ });
849
+ const domain = {
850
+ name,
851
+ version: "1",
852
+ chainId: this.sdk.chainId,
853
+ verifyingContract: this.sdk.contractAddress
854
+ };
855
+ const types = {
856
+ CancelAuthorization: [
857
+ { name: "authorizer", type: "address" },
858
+ { name: "nonce", type: "bytes32" }
859
+ ]
860
+ };
861
+ const message = { authorizer, nonce: authNonce };
862
+ const signature = await walletClient.signTypedData({
863
+ account: walletClient.account,
864
+ domain,
865
+ types,
866
+ primaryType: "CancelAuthorization",
867
+ message
868
+ });
869
+ const v = parseInt(signature.slice(130, 132), 16);
870
+ const r = `0x${signature.slice(2, 66)}`;
871
+ const s = `0x${signature.slice(66, 130)}`;
872
+ return { authorizer, nonce: authNonce, v, r, s };
873
+ }
874
+ /**
875
+ * Cancel an authorization (marks nonce as used)
876
+ */
877
+ async cancelAuthorization(params) {
878
+ const { walletClient } = params;
879
+ const { authorizer, nonce, v, r, s } = await this.signCancelWithWallet(params);
880
+ const hash = await walletClient.writeContract({
881
+ address: this.sdk.contractAddress,
882
+ abi: DJEON402_ABI3,
883
+ functionName: "cancelAuthorization",
884
+ args: [authorizer, nonce, v, r, s],
885
+ account: walletClient.account,
886
+ chain: walletClient.chain
887
+ });
888
+ const receipt = await this.sdk.publicClient.waitForTransactionReceipt({ hash });
889
+ return {
890
+ success: receipt.status === "success",
891
+ hash,
892
+ blockNumber: receipt.blockNumber.toString()
893
+ };
894
+ }
895
+ /**
896
+ * Execute transfer with authorization (relayer function)
897
+ */
898
+ async executeTransfer(params) {
899
+ const { walletClient, authorization } = params;
900
+ if (!walletClient.account) {
901
+ throw new Error("Wallet client must have an account");
902
+ }
903
+ const { from, to, value, validAfter, validBefore, nonce, v, r, s } = authorization;
904
+ const hash = await walletClient.writeContract({
905
+ address: this.sdk.contractAddress,
906
+ abi: DJEON402_ABI3,
907
+ functionName: "transferWithAuthorization",
908
+ args: [from, to, value, validAfter, validBefore, nonce, v, r, s],
909
+ account: walletClient.account,
910
+ chain: walletClient.chain
911
+ });
912
+ const receipt = await this.sdk.publicClient.waitForTransactionReceipt({ hash });
913
+ return {
914
+ success: receipt.status === "success",
915
+ hash,
916
+ blockNumber: receipt.blockNumber.toString()
917
+ };
918
+ }
919
+ /**
920
+ * Fetch wrapper that auto-handles 402 Payment Required responses.
921
+ * On 402, decodes PAYMENT-REQUIRED header, signs authorization, retries with PAYMENT-SIGNATURE.
922
+ */
923
+ async fetchWithPayment(walletClient, url, options = {}) {
924
+ const response = await fetch(url, options);
925
+ if (response.status !== 402) return response;
926
+ const paymentRequiredHeader = response.headers.get("PAYMENT-REQUIRED");
927
+ if (!paymentRequiredHeader) {
928
+ throw new Error("402 response missing PAYMENT-REQUIRED header");
929
+ }
930
+ const paymentRequired = JSON.parse(atob(paymentRequiredHeader));
931
+ const accepted = paymentRequired.accepts?.[0];
932
+ if (!accepted) {
933
+ throw new Error("No accepted payment methods in 402 response");
934
+ }
935
+ const authData = await this.signTransferWithWallet({
936
+ walletClient,
937
+ to: accepted.payTo,
938
+ amount: accepted.amount
939
+ });
940
+ const paymentPayload = {
941
+ x402Version: paymentRequired.x402Version || 2,
942
+ resource: paymentRequired.resource,
943
+ accepted,
944
+ payload: {
945
+ signature: `0x${authData.r.slice(2)}${authData.s.slice(2)}${authData.v.toString(16).padStart(2, "0")}`,
946
+ authorization: {
947
+ from: authData.from,
948
+ to: authData.to,
949
+ value: authData.value.toString(),
950
+ validAfter: authData.validAfter.toString(),
951
+ validBefore: authData.validBefore.toString(),
952
+ nonce: authData.nonce
953
+ }
954
+ }
955
+ };
956
+ const encoded = btoa(JSON.stringify(paymentPayload));
957
+ return fetch(url, {
958
+ ...options,
959
+ headers: {
960
+ ...Object.fromEntries(new Headers(options.headers).entries()),
961
+ "PAYMENT-SIGNATURE": encoded
962
+ }
963
+ });
964
+ }
965
+ };
966
+
967
+ // src/client.ts
968
+ var Djeon402ClientSDK = class {
969
+ constructor(config) {
970
+ const { rpcUrl, contractAddress, kycRegistryAddress, chainId } = config;
971
+ this.contractAddress = contractAddress;
972
+ this.kycRegistryAddress = kycRegistryAddress;
973
+ this.chainId = chainId;
974
+ const chain = chainId === 8453 ? base : {
975
+ id: chainId,
976
+ name: "Custom Chain",
977
+ nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
978
+ rpcUrls: {
979
+ default: { http: [rpcUrl || ""] },
980
+ public: { http: [rpcUrl || ""] }
981
+ }
982
+ };
983
+ this.publicClient = createPublicClient({
984
+ chain,
985
+ transport: http(rpcUrl)
986
+ });
987
+ this.token = new TokenModule(this);
988
+ this.admin = new AdminModule(this);
989
+ this.kyc = new KYCModule(this);
990
+ this.x402 = new X402Module(this);
991
+ }
992
+ /**
993
+ * Get chain configuration
994
+ */
995
+ getChain() {
996
+ return this.chainId === 8453 ? base : {
997
+ id: this.chainId,
998
+ name: "Custom Chain",
999
+ nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
1000
+ rpcUrls: {
1001
+ default: { http: [this.publicClient.transport.url || ""] },
1002
+ public: { http: [this.publicClient.transport.url || ""] }
1003
+ }
1004
+ };
1005
+ }
1006
+ };
1007
+
1008
+ // src/react/provider.tsx
1009
+ import { jsx } from "react/jsx-runtime";
1010
+ var Djeon402Context = createContext(null);
1011
+ function Djeon402Provider({
1012
+ children,
1013
+ config
1014
+ }) {
1015
+ const sdk = useMemo(() => {
1016
+ return new Djeon402ClientSDK({
1017
+ contractAddress: config.contractAddress,
1018
+ kycRegistryAddress: config.kycRegistryAddress,
1019
+ chainId: config.chainId,
1020
+ rpcUrl: config.rpcUrl || ""
1021
+ });
1022
+ }, [config.contractAddress, config.kycRegistryAddress, config.chainId, config.rpcUrl]);
1023
+ const value = useMemo(() => ({ sdk, config }), [sdk, config]);
1024
+ return /* @__PURE__ */ jsx(Djeon402Context.Provider, { value, children });
1025
+ }
1026
+ function useDjeon402() {
1027
+ const context = useContext(Djeon402Context);
1028
+ if (!context) {
1029
+ throw new Error("useDjeon402 must be used within Djeon402Provider");
1030
+ }
1031
+ return context;
1032
+ }
1033
+
1034
+ // src/react/useApprove.ts
1035
+ import { useMutation, useQueryClient } from "@tanstack/react-query";
1036
+ import { useWalletClient } from "wagmi";
1037
+ function useApprove() {
1038
+ const { sdk } = useDjeon402();
1039
+ const { data: walletClient } = useWalletClient();
1040
+ const queryClient = useQueryClient();
1041
+ const mutation = useMutation({
1042
+ mutationFn: async ({ spender, amount }) => {
1043
+ if (!walletClient) {
1044
+ throw new Error("Wallet not connected");
1045
+ }
1046
+ return sdk.token.approve({ walletClient, spender, amount });
1047
+ },
1048
+ onSuccess: () => {
1049
+ queryClient.invalidateQueries({ queryKey: ["djeon402", "allowance"] });
1050
+ }
1051
+ });
1052
+ return {
1053
+ approve: mutation.mutateAsync,
1054
+ isLoading: mutation.isPending,
1055
+ isSuccess: mutation.isSuccess,
1056
+ error: mutation.error,
1057
+ data: mutation.data
1058
+ };
1059
+ }
1060
+
1061
+ // src/react/useBalance.ts
1062
+ import { useQuery } from "@tanstack/react-query";
1063
+ function useBalance(address) {
1064
+ const { sdk } = useDjeon402();
1065
+ return useQuery({
1066
+ queryKey: ["djeon402", "balance", sdk.contractAddress, address],
1067
+ queryFn: () => {
1068
+ if (!address) throw new Error("Address is required");
1069
+ return sdk.token.getBalance(address);
1070
+ },
1071
+ enabled: !!address,
1072
+ staleTime: 1e4
1073
+ // 10 seconds
1074
+ });
1075
+ }
1076
+
1077
+ // src/react/useIsBlacklisted.ts
1078
+ import { useQuery as useQuery2 } from "@tanstack/react-query";
1079
+ function useIsBlacklisted(address) {
1080
+ const { sdk } = useDjeon402();
1081
+ return useQuery2({
1082
+ queryKey: ["djeon402", "blacklist", sdk.contractAddress, address],
1083
+ queryFn: () => {
1084
+ if (!address) throw new Error("Address is required");
1085
+ return sdk.admin.isBlacklisted(address);
1086
+ },
1087
+ enabled: !!address,
1088
+ staleTime: 3e4
1089
+ // 30 seconds
1090
+ });
1091
+ }
1092
+
1093
+ // src/react/useKYCData.ts
1094
+ import { useQuery as useQuery3 } from "@tanstack/react-query";
1095
+ function useKYCData(address) {
1096
+ const { sdk } = useDjeon402();
1097
+ return useQuery3({
1098
+ queryKey: ["djeon402", "kyc", sdk.kycRegistryAddress, address],
1099
+ queryFn: () => {
1100
+ if (!address) throw new Error("Address is required");
1101
+ return sdk.kyc.getData(address);
1102
+ },
1103
+ enabled: !!address && !!sdk.kycRegistryAddress,
1104
+ staleTime: 3e4
1105
+ // 30 seconds
1106
+ });
1107
+ }
1108
+
1109
+ // src/react/useTokenInfo.ts
1110
+ import { useQuery as useQuery4 } from "@tanstack/react-query";
1111
+ function useTokenInfo() {
1112
+ const { sdk } = useDjeon402();
1113
+ return useQuery4({
1114
+ queryKey: ["djeon402", "tokenInfo", sdk.contractAddress],
1115
+ queryFn: () => sdk.token.getInfo(),
1116
+ staleTime: 6e4
1117
+ // 1 minute
1118
+ });
1119
+ }
1120
+
1121
+ // src/react/useTransfer.ts
1122
+ import { useMutation as useMutation2, useQueryClient as useQueryClient2 } from "@tanstack/react-query";
1123
+ import { useWalletClient as useWalletClient2 } from "wagmi";
1124
+ function useTransfer() {
1125
+ const { sdk } = useDjeon402();
1126
+ const { data: walletClient } = useWalletClient2();
1127
+ const queryClient = useQueryClient2();
1128
+ const mutation = useMutation2({
1129
+ mutationFn: async ({ to, amount }) => {
1130
+ if (!walletClient) {
1131
+ throw new Error("Wallet not connected");
1132
+ }
1133
+ return sdk.token.transfer({ walletClient, to, amount });
1134
+ },
1135
+ onSuccess: () => {
1136
+ queryClient.invalidateQueries({ queryKey: ["djeon402", "balance"] });
1137
+ }
1138
+ });
1139
+ return {
1140
+ transfer: mutation.mutateAsync,
1141
+ isLoading: mutation.isPending,
1142
+ isSuccess: mutation.isSuccess,
1143
+ error: mutation.error,
1144
+ data: mutation.data
1145
+ };
1146
+ }
1147
+
1148
+ // src/react/useX402Receive.ts
1149
+ import { useMutation as useMutation3 } from "@tanstack/react-query";
1150
+ import { useWalletClient as useWalletClient3 } from "wagmi";
1151
+ function useX402Receive() {
1152
+ const { sdk } = useDjeon402();
1153
+ const { data: walletClient } = useWalletClient3();
1154
+ const mutation = useMutation3({
1155
+ mutationFn: async (params) => {
1156
+ if (!walletClient) {
1157
+ throw new Error("Wallet not connected");
1158
+ }
1159
+ return sdk.x402.signReceiveWithWallet({
1160
+ walletClient,
1161
+ ...params
1162
+ });
1163
+ }
1164
+ });
1165
+ return {
1166
+ signReceive: mutation.mutateAsync,
1167
+ isLoading: mutation.isPending,
1168
+ isSuccess: mutation.isSuccess,
1169
+ error: mutation.error,
1170
+ authorization: mutation.data
1171
+ };
1172
+ }
1173
+
1174
+ // src/react/useX402Transfer.ts
1175
+ import { useMutation as useMutation4 } from "@tanstack/react-query";
1176
+ import { useWalletClient as useWalletClient4 } from "wagmi";
1177
+ function useX402Transfer() {
1178
+ const { sdk } = useDjeon402();
1179
+ const { data: walletClient } = useWalletClient4();
1180
+ const mutation = useMutation4({
1181
+ mutationFn: async (params) => {
1182
+ if (!walletClient) {
1183
+ throw new Error("Wallet not connected");
1184
+ }
1185
+ return sdk.x402.signTransferWithWallet({
1186
+ walletClient,
1187
+ ...params
1188
+ });
1189
+ }
1190
+ });
1191
+ return {
1192
+ signTransfer: mutation.mutateAsync,
1193
+ isLoading: mutation.isPending,
1194
+ isSuccess: mutation.isSuccess,
1195
+ error: mutation.error,
1196
+ authorization: mutation.data
1197
+ };
1198
+ }
1199
+ export {
1200
+ Djeon402Provider,
1201
+ useApprove,
1202
+ useBalance,
1203
+ useDjeon402,
1204
+ useIsBlacklisted,
1205
+ useKYCData,
1206
+ useTokenInfo,
1207
+ useTransfer,
1208
+ useX402Receive,
1209
+ useX402Transfer
1210
+ };
1211
+ //# sourceMappingURL=index.js.map