@zubari/sdk 0.2.8 → 0.3.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.
Files changed (39) hide show
  1. package/dist/{TransactionService-8xSEGoWA.d.mts → TransactionService-DURp3bRL.d.ts} +34 -10
  2. package/dist/{TransactionService-CaIcCoqY.d.ts → TransactionService-DuMJmrG3.d.mts} +34 -10
  3. package/dist/{WalletManager-CCs4Jsv7.d.ts → WalletManager-CEjN-YBF.d.ts} +12 -12
  4. package/dist/{WalletManager-B1qvFF4K.d.mts → WalletManager-bo35aHOJ.d.mts} +12 -12
  5. package/dist/{index-BOc9U2TK.d.mts → index-BpjMiC3n.d.ts} +22 -11
  6. package/dist/{index-Cx389p_j.d.mts → index-DF0Gf8NK.d.mts} +7 -1
  7. package/dist/{index-Cx389p_j.d.ts → index-DF0Gf8NK.d.ts} +7 -1
  8. package/dist/{index-Cqrpp3XA.d.ts → index-DJnsirV5.d.mts} +22 -11
  9. package/dist/index.d.mts +4 -4
  10. package/dist/index.d.ts +4 -4
  11. package/dist/index.js +3064 -1770
  12. package/dist/index.js.map +1 -1
  13. package/dist/index.mjs +3064 -1770
  14. package/dist/index.mjs.map +1 -1
  15. package/dist/protocols/index.d.mts +54 -22
  16. package/dist/protocols/index.d.ts +54 -22
  17. package/dist/protocols/index.js +1008 -76
  18. package/dist/protocols/index.js.map +1 -1
  19. package/dist/protocols/index.mjs +1008 -76
  20. package/dist/protocols/index.mjs.map +1 -1
  21. package/dist/react/index.d.mts +3 -3
  22. package/dist/react/index.d.ts +3 -3
  23. package/dist/react/index.js +884 -884
  24. package/dist/react/index.js.map +1 -1
  25. package/dist/react/index.mjs +884 -884
  26. package/dist/react/index.mjs.map +1 -1
  27. package/dist/services/index.d.mts +2 -2
  28. package/dist/services/index.d.ts +2 -2
  29. package/dist/services/index.js +152 -75
  30. package/dist/services/index.js.map +1 -1
  31. package/dist/services/index.mjs +152 -75
  32. package/dist/services/index.mjs.map +1 -1
  33. package/dist/wallet/index.d.mts +3 -3
  34. package/dist/wallet/index.d.ts +3 -3
  35. package/dist/wallet/index.js +1352 -1105
  36. package/dist/wallet/index.js.map +1 -1
  37. package/dist/wallet/index.mjs +1352 -1105
  38. package/dist/wallet/index.mjs.map +1 -1
  39. package/package.json +13 -12
@@ -42,18 +42,702 @@ var CURRENCY_ADDRESSES = {
42
42
  }
43
43
  };
44
44
 
45
+ // src/services/ZubariApiClient.ts
46
+ var ZubariApiClient = class {
47
+ config;
48
+ constructor(config) {
49
+ this.config = {
50
+ baseUrl: config.baseUrl.replace(/\/$/, ""),
51
+ // Remove trailing slash
52
+ timeout: config.timeout || 3e4,
53
+ authToken: config.authToken
54
+ };
55
+ }
56
+ /**
57
+ * Set the authentication token
58
+ */
59
+ setAuthToken(token) {
60
+ this.config.authToken = token;
61
+ }
62
+ /**
63
+ * Clear the authentication token
64
+ */
65
+ clearAuthToken() {
66
+ this.config.authToken = void 0;
67
+ }
68
+ /**
69
+ * Make an authenticated request to the API
70
+ */
71
+ async request(method, path, body) {
72
+ const headers = {
73
+ "Content-Type": "application/json"
74
+ };
75
+ if (this.config.authToken) {
76
+ headers["Authorization"] = `Bearer ${this.config.authToken}`;
77
+ }
78
+ const response = await fetch(`${this.config.baseUrl}${path}`, {
79
+ method,
80
+ headers,
81
+ body: body ? JSON.stringify(body) : void 0
82
+ });
83
+ if (!response.ok) {
84
+ const errorData = await response.json().catch(() => ({}));
85
+ throw new Error(errorData.error || `HTTP ${response.status}: ${response.statusText}`);
86
+ }
87
+ return response.json();
88
+ }
89
+ // ============ NFT Methods ============
90
+ /**
91
+ * Get all NFTs with optional filters
92
+ */
93
+ async getNFTs(filters) {
94
+ try {
95
+ const params = new URLSearchParams();
96
+ if (filters) {
97
+ Object.entries(filters).forEach(([key, value]) => {
98
+ if (value !== void 0) {
99
+ params.append(key, String(value));
100
+ }
101
+ });
102
+ }
103
+ const queryString = params.toString();
104
+ const path = `/api/nfts${queryString ? `?${queryString}` : ""}`;
105
+ return await this.request("GET", path);
106
+ } catch (error) {
107
+ return {
108
+ success: false,
109
+ error: error instanceof Error ? error.message : "Failed to get NFTs"
110
+ };
111
+ }
112
+ }
113
+ /**
114
+ * Get a single NFT by ID
115
+ */
116
+ async getNFT(nftId) {
117
+ try {
118
+ const nft = await this.request("GET", `/api/nfts/${nftId}`);
119
+ return { success: true, nft };
120
+ } catch (error) {
121
+ return {
122
+ success: false,
123
+ error: error instanceof Error ? error.message : "Failed to get NFT"
124
+ };
125
+ }
126
+ }
127
+ /**
128
+ * Create a new NFT (lazy minted)
129
+ */
130
+ async createNFT(data, image) {
131
+ try {
132
+ const formData = new FormData();
133
+ formData.append("image", image);
134
+ formData.append("name", data.name);
135
+ if (data.description) formData.append("description", data.description);
136
+ formData.append("price", data.price);
137
+ formData.append("currency", data.currency);
138
+ if (data.royaltyBps !== void 0) formData.append("royaltyBps", String(data.royaltyBps));
139
+ if (data.attributes) formData.append("attributes", JSON.stringify(data.attributes));
140
+ if (data.externalUrl) formData.append("externalUrl", data.externalUrl);
141
+ const headers = {};
142
+ if (this.config.authToken) {
143
+ headers["Authorization"] = `Bearer ${this.config.authToken}`;
144
+ }
145
+ const response = await fetch(`${this.config.baseUrl}/api/nfts`, {
146
+ method: "POST",
147
+ headers,
148
+ body: formData
149
+ });
150
+ if (!response.ok) {
151
+ const errorData = await response.json().catch(() => ({}));
152
+ throw new Error(errorData.error || `HTTP ${response.status}`);
153
+ }
154
+ const nft = await response.json();
155
+ return { success: true, nft };
156
+ } catch (error) {
157
+ return {
158
+ success: false,
159
+ error: error instanceof Error ? error.message : "Failed to create NFT"
160
+ };
161
+ }
162
+ }
163
+ /**
164
+ * Create a voucher for an NFT (EIP-712 signed)
165
+ */
166
+ async createVoucher(nftId, params) {
167
+ try {
168
+ return await this.request("POST", `/api/nfts/${nftId}/voucher`, params);
169
+ } catch (error) {
170
+ return {
171
+ success: false,
172
+ error: error instanceof Error ? error.message : "Failed to create voucher"
173
+ };
174
+ }
175
+ }
176
+ /**
177
+ * Redeem an NFT voucher (buy/mint)
178
+ */
179
+ async redeemVoucher(nftId, params) {
180
+ try {
181
+ return await this.request("POST", `/api/nfts/${nftId}/redeem`, params);
182
+ } catch (error) {
183
+ return {
184
+ success: false,
185
+ error: error instanceof Error ? error.message : "Failed to redeem voucher"
186
+ };
187
+ }
188
+ }
189
+ /**
190
+ * Get voucher status for an NFT
191
+ */
192
+ async getVoucherStatus(nftId) {
193
+ try {
194
+ return await this.request("GET", `/api/nfts/${nftId}/voucher/status`);
195
+ } catch (error) {
196
+ return {
197
+ success: false,
198
+ error: error instanceof Error ? error.message : "Failed to get voucher status"
199
+ };
200
+ }
201
+ }
202
+ // ============ Marketplace Methods ============
203
+ /**
204
+ * Get all active listings
205
+ */
206
+ async getListings(filters) {
207
+ try {
208
+ const params = new URLSearchParams();
209
+ if (filters) {
210
+ Object.entries(filters).forEach(([key, value]) => {
211
+ if (value !== void 0) {
212
+ params.append(key, String(value));
213
+ }
214
+ });
215
+ }
216
+ const queryString = params.toString();
217
+ const path = `/api/market/listings${queryString ? `?${queryString}` : ""}`;
218
+ return await this.request("GET", path);
219
+ } catch (error) {
220
+ return {
221
+ success: false,
222
+ error: error instanceof Error ? error.message : "Failed to get listings"
223
+ };
224
+ }
225
+ }
226
+ /**
227
+ * List an NFT for sale
228
+ */
229
+ async listItem(params) {
230
+ try {
231
+ return await this.request("POST", "/api/market/list", params);
232
+ } catch (error) {
233
+ return {
234
+ success: false,
235
+ error: error instanceof Error ? error.message : "Failed to list item"
236
+ };
237
+ }
238
+ }
239
+ /**
240
+ * Buy a listed NFT
241
+ */
242
+ async buyItem(params) {
243
+ try {
244
+ return await this.request("POST", "/api/market/buy", params);
245
+ } catch (error) {
246
+ return {
247
+ success: false,
248
+ error: error instanceof Error ? error.message : "Failed to buy item"
249
+ };
250
+ }
251
+ }
252
+ /**
253
+ * Cancel a listing
254
+ */
255
+ async cancelListing(params) {
256
+ try {
257
+ return await this.request("POST", "/api/market/cancel", params);
258
+ } catch (error) {
259
+ return {
260
+ success: false,
261
+ error: error instanceof Error ? error.message : "Failed to cancel listing"
262
+ };
263
+ }
264
+ }
265
+ /**
266
+ * Update listing price
267
+ */
268
+ async updateListingPrice(params) {
269
+ try {
270
+ return await this.request("PATCH", "/api/market/price", params);
271
+ } catch (error) {
272
+ return {
273
+ success: false,
274
+ error: error instanceof Error ? error.message : "Failed to update price"
275
+ };
276
+ }
277
+ }
278
+ /**
279
+ * Get current user's listings
280
+ */
281
+ async getMyListings(filters) {
282
+ try {
283
+ const params = new URLSearchParams();
284
+ if (filters) {
285
+ Object.entries(filters).forEach(([key, value]) => {
286
+ if (value !== void 0) {
287
+ params.append(key, String(value));
288
+ }
289
+ });
290
+ }
291
+ const queryString = params.toString();
292
+ const path = `/api/market/my/listings${queryString ? `?${queryString}` : ""}`;
293
+ return await this.request("GET", path);
294
+ } catch (error) {
295
+ return {
296
+ success: false,
297
+ error: error instanceof Error ? error.message : "Failed to get my listings"
298
+ };
299
+ }
300
+ }
301
+ /**
302
+ * Get marketplace statistics
303
+ */
304
+ async getMarketStats() {
305
+ try {
306
+ return await this.request("GET", "/api/market/stats");
307
+ } catch (error) {
308
+ return {
309
+ success: false,
310
+ error: error instanceof Error ? error.message : "Failed to get market stats"
311
+ };
312
+ }
313
+ }
314
+ // ============ Tips Methods ============
315
+ /**
316
+ * Send a tip to a creator
317
+ */
318
+ async sendTip(params) {
319
+ try {
320
+ return await this.request("POST", "/api/tips", params);
321
+ } catch (error) {
322
+ return {
323
+ success: false,
324
+ error: error instanceof Error ? error.message : "Failed to send tip"
325
+ };
326
+ }
327
+ }
328
+ /**
329
+ * Get tip statistics for current user
330
+ */
331
+ async getTipStats() {
332
+ try {
333
+ const data = await this.request("GET", "/api/tips/my/stats");
334
+ return { success: true, ...data };
335
+ } catch (error) {
336
+ return {
337
+ success: false,
338
+ error: error instanceof Error ? error.message : "Failed to get tip stats"
339
+ };
340
+ }
341
+ }
342
+ /**
343
+ * Get tips sent by current user
344
+ */
345
+ async getSentTips(filters) {
346
+ try {
347
+ const params = new URLSearchParams();
348
+ if (filters) {
349
+ Object.entries(filters).forEach(([key, value]) => {
350
+ if (value !== void 0) {
351
+ params.append(key, String(value));
352
+ }
353
+ });
354
+ }
355
+ const queryString = params.toString();
356
+ const path = `/api/tips/sent${queryString ? `?${queryString}` : ""}`;
357
+ const data = await this.request("GET", path);
358
+ return { success: true, ...data };
359
+ } catch (error) {
360
+ return {
361
+ success: false,
362
+ error: error instanceof Error ? error.message : "Failed to get sent tips"
363
+ };
364
+ }
365
+ }
366
+ /**
367
+ * Get tips received by current user
368
+ */
369
+ async getReceivedTips(filters) {
370
+ try {
371
+ const params = new URLSearchParams();
372
+ if (filters) {
373
+ Object.entries(filters).forEach(([key, value]) => {
374
+ if (value !== void 0) {
375
+ params.append(key, String(value));
376
+ }
377
+ });
378
+ }
379
+ const queryString = params.toString();
380
+ const path = `/api/tips/received${queryString ? `?${queryString}` : ""}`;
381
+ const data = await this.request("GET", path);
382
+ return { success: true, ...data };
383
+ } catch (error) {
384
+ return {
385
+ success: false,
386
+ error: error instanceof Error ? error.message : "Failed to get received tips"
387
+ };
388
+ }
389
+ }
390
+ /**
391
+ * Get a single tip by ID
392
+ */
393
+ async getTip(tipId) {
394
+ try {
395
+ const data = await this.request("GET", `/api/tips/${tipId}`);
396
+ return { success: true, tip: data.tip };
397
+ } catch (error) {
398
+ return {
399
+ success: false,
400
+ error: error instanceof Error ? error.message : "Failed to get tip"
401
+ };
402
+ }
403
+ }
404
+ /**
405
+ * Update tip status (for transaction confirmation)
406
+ */
407
+ async updateTipStatus(tipId, params) {
408
+ try {
409
+ const data = await this.request(
410
+ "PATCH",
411
+ `/api/tips/${tipId}/status`,
412
+ params
413
+ );
414
+ return { success: true, ...data };
415
+ } catch (error) {
416
+ return {
417
+ success: false,
418
+ error: error instanceof Error ? error.message : "Failed to update tip status"
419
+ };
420
+ }
421
+ }
422
+ // ============ Subscription Methods ============
423
+ /**
424
+ * Create a new subscription plan (creator only)
425
+ */
426
+ async createSubscriptionPlan(params) {
427
+ try {
428
+ return await this.request("POST", "/api/subscriptions/plans", params);
429
+ } catch (error) {
430
+ return {
431
+ success: false,
432
+ error: error instanceof Error ? error.message : "Failed to create subscription plan"
433
+ };
434
+ }
435
+ }
436
+ /**
437
+ * Get current user's subscription plans
438
+ */
439
+ async getMySubscriptionPlans() {
440
+ try {
441
+ const data = await this.request("GET", "/api/subscriptions/plans");
442
+ return { success: true, plans: data.plans };
443
+ } catch (error) {
444
+ return {
445
+ success: false,
446
+ error: error instanceof Error ? error.message : "Failed to get subscription plans"
447
+ };
448
+ }
449
+ }
450
+ /**
451
+ * Get subscription plan by ID
452
+ */
453
+ async getSubscriptionPlan(planId) {
454
+ try {
455
+ const plan = await this.request(
456
+ "GET",
457
+ `/api/subscriptions/plans/${planId}`
458
+ );
459
+ return { success: true, plan };
460
+ } catch (error) {
461
+ return {
462
+ success: false,
463
+ error: error instanceof Error ? error.message : "Failed to get subscription plan"
464
+ };
465
+ }
466
+ }
467
+ /**
468
+ * Delete/deactivate subscription plan
469
+ */
470
+ async deleteSubscriptionPlan(planId) {
471
+ try {
472
+ const data = await this.request(
473
+ "DELETE",
474
+ `/api/subscriptions/plans/${planId}`
475
+ );
476
+ return { success: true, ...data };
477
+ } catch (error) {
478
+ return {
479
+ success: false,
480
+ error: error instanceof Error ? error.message : "Failed to delete subscription plan"
481
+ };
482
+ }
483
+ }
484
+ /**
485
+ * Subscribe to a plan
486
+ */
487
+ async subscribe(params) {
488
+ try {
489
+ return await this.request("POST", "/api/subscriptions/subscribe", params);
490
+ } catch (error) {
491
+ return {
492
+ success: false,
493
+ error: error instanceof Error ? error.message : "Failed to subscribe"
494
+ };
495
+ }
496
+ }
497
+ /**
498
+ * Get current user's subscriptions (as subscriber)
499
+ */
500
+ async getMySubscriptions(filters) {
501
+ try {
502
+ const params = new URLSearchParams();
503
+ if (filters) {
504
+ Object.entries(filters).forEach(([key, value]) => {
505
+ if (value !== void 0) {
506
+ params.append(key, String(value));
507
+ }
508
+ });
509
+ }
510
+ const queryString = params.toString();
511
+ const path = `/api/subscriptions${queryString ? `?${queryString}` : ""}`;
512
+ const data = await this.request("GET", path);
513
+ return { success: true, ...data };
514
+ } catch (error) {
515
+ return {
516
+ success: false,
517
+ error: error instanceof Error ? error.message : "Failed to get subscriptions"
518
+ };
519
+ }
520
+ }
521
+ /**
522
+ * Get subscribers to current user's plans (as creator)
523
+ */
524
+ async getMySubscribers(filters) {
525
+ try {
526
+ const params = new URLSearchParams();
527
+ if (filters) {
528
+ Object.entries(filters).forEach(([key, value]) => {
529
+ if (value !== void 0) {
530
+ params.append(key, String(value));
531
+ }
532
+ });
533
+ }
534
+ const queryString = params.toString();
535
+ const path = `/api/subscriptions/subscribers${queryString ? `?${queryString}` : ""}`;
536
+ const data = await this.request("GET", path);
537
+ return { success: true, ...data };
538
+ } catch (error) {
539
+ return {
540
+ success: false,
541
+ error: error instanceof Error ? error.message : "Failed to get subscribers"
542
+ };
543
+ }
544
+ }
545
+ /**
546
+ * Cancel subscription
547
+ */
548
+ async cancelSubscription(subscriptionId) {
549
+ try {
550
+ const data = await this.request("DELETE", `/api/subscriptions/${subscriptionId}`);
551
+ return { success: true, ...data };
552
+ } catch (error) {
553
+ return {
554
+ success: false,
555
+ error: error instanceof Error ? error.message : "Failed to cancel subscription"
556
+ };
557
+ }
558
+ }
559
+ /**
560
+ * Create a subscription plan on-chain
561
+ */
562
+ async createSubscriptionPlanOnChain(params) {
563
+ try {
564
+ return await this.request("POST", "/api/subscriptions/contract/plans", params);
565
+ } catch (error) {
566
+ return {
567
+ success: false,
568
+ error: error instanceof Error ? error.message : "Failed to create plan on-chain"
569
+ };
570
+ }
571
+ }
572
+ /**
573
+ * Subscribe to a plan on-chain
574
+ */
575
+ async subscribeOnChain(params) {
576
+ try {
577
+ return await this.request("POST", "/api/subscriptions/contract/subscribe", params);
578
+ } catch (error) {
579
+ return {
580
+ success: false,
581
+ error: error instanceof Error ? error.message : "Failed to subscribe on-chain"
582
+ };
583
+ }
584
+ }
585
+ /**
586
+ * Cancel subscription on-chain
587
+ */
588
+ async cancelSubscriptionOnChain(subscriptionId, seed) {
589
+ try {
590
+ return await this.request(
591
+ "POST",
592
+ "/api/subscriptions/contract/cancel",
593
+ { subscriptionId, seed }
594
+ );
595
+ } catch (error) {
596
+ return {
597
+ success: false,
598
+ error: error instanceof Error ? error.message : "Failed to cancel subscription on-chain"
599
+ };
600
+ }
601
+ }
602
+ /**
603
+ * Check if user is subscribed to a creator on-chain
604
+ */
605
+ async isSubscribed(subscriber, creator) {
606
+ try {
607
+ return await this.request(
608
+ "GET",
609
+ `/api/subscriptions/contract/is-subscribed?subscriber=${subscriber}&creator=${creator}`
610
+ );
611
+ } catch (error) {
612
+ return {
613
+ subscriber,
614
+ creator,
615
+ isSubscribed: false
616
+ };
617
+ }
618
+ }
619
+ /**
620
+ * Get subscription platform fee
621
+ */
622
+ async getSubscriptionPlatformFee() {
623
+ try {
624
+ return await this.request("GET", "/api/subscriptions/platform-fee");
625
+ } catch (error) {
626
+ return {
627
+ feeBps: 0,
628
+ feePercent: "0"
629
+ };
630
+ }
631
+ }
632
+ // ============ Payouts Methods ============
633
+ /**
634
+ * Get pending and claimed earnings for the authenticated user
635
+ */
636
+ async getEarnings() {
637
+ try {
638
+ const data = await this.request("GET", "/api/payouts/earnings");
639
+ return { success: true, ...data };
640
+ } catch (error) {
641
+ return {
642
+ success: false,
643
+ error: error instanceof Error ? error.message : "Failed to get earnings"
644
+ };
645
+ }
646
+ }
647
+ /**
648
+ * Claim pending earnings
649
+ */
650
+ async claimEarnings(params) {
651
+ try {
652
+ return await this.request("POST", "/api/payouts/claim", params);
653
+ } catch (error) {
654
+ return {
655
+ success: false,
656
+ error: error instanceof Error ? error.message : "Failed to claim earnings"
657
+ };
658
+ }
659
+ }
660
+ /**
661
+ * Get payout history for the authenticated user
662
+ */
663
+ async getPayoutHistory(filters) {
664
+ try {
665
+ const params = new URLSearchParams();
666
+ if (filters) {
667
+ Object.entries(filters).forEach(([key, value]) => {
668
+ if (value !== void 0) {
669
+ params.append(key, String(value));
670
+ }
671
+ });
672
+ }
673
+ const queryString = params.toString();
674
+ const path = `/api/payouts/history${queryString ? `?${queryString}` : ""}`;
675
+ const data = await this.request("GET", path);
676
+ return { success: true, ...data };
677
+ } catch (error) {
678
+ return {
679
+ success: false,
680
+ error: error instanceof Error ? error.message : "Failed to get payout history"
681
+ };
682
+ }
683
+ }
684
+ /**
685
+ * Get earnings breakdown by source
686
+ */
687
+ async getEarningsBreakdown() {
688
+ try {
689
+ const data = await this.request("GET", "/api/payouts/breakdown");
690
+ return { success: true, ...data };
691
+ } catch (error) {
692
+ return {
693
+ success: false,
694
+ error: error instanceof Error ? error.message : "Failed to get earnings breakdown"
695
+ };
696
+ }
697
+ }
698
+ /**
699
+ * Get current platform fee for payouts
700
+ */
701
+ async getPayoutsPlatformFee() {
702
+ try {
703
+ return await this.request("GET", "/api/payouts/platform-fee");
704
+ } catch (error) {
705
+ return {
706
+ feeBps: 0,
707
+ feePercent: "0"
708
+ };
709
+ }
710
+ }
711
+ };
712
+ var DEFAULT_API_URL = process.env.NEXT_PUBLIC_API_URL || "https://ckgwifsxka.us-east-2.awsapprunner.com";
713
+ var zubariApiClient = null;
714
+ function getZubariApiClient(config) {
715
+ if (!zubariApiClient || config?.baseUrl && zubariApiClient["config"].baseUrl !== config.baseUrl) {
716
+ zubariApiClient = new ZubariApiClient({
717
+ baseUrl: config?.baseUrl || DEFAULT_API_URL,
718
+ timeout: config?.timeout,
719
+ authToken: config?.authToken
720
+ });
721
+ } else if (config?.authToken) {
722
+ zubariApiClient.setAuthToken(config.authToken);
723
+ }
724
+ return zubariApiClient;
725
+ }
726
+
45
727
  // src/protocols/NFTProtocol.ts
46
728
  var ZubariNFTProtocol = class {
47
729
  contractAddress;
48
730
  _marketplaceAddress;
49
731
  chainId;
50
732
  network;
733
+ apiClient;
51
734
  nonceCounter = 0;
52
- constructor(contractAddress, marketplaceAddress, chainId, network = "testnet") {
735
+ constructor(contractAddress, marketplaceAddress, chainId, network = "testnet", apiUrl) {
53
736
  this.contractAddress = contractAddress;
54
737
  this._marketplaceAddress = marketplaceAddress;
55
738
  this.chainId = chainId;
56
739
  this.network = network;
740
+ this.apiClient = getZubariApiClient(apiUrl ? { baseUrl: apiUrl } : void 0);
57
741
  }
58
742
  /**
59
743
  * Convert human-readable price to wei
@@ -170,52 +854,153 @@ var ZubariNFTProtocol = class {
170
854
  }
171
855
  /**
172
856
  * Redeem a lazy mint voucher to mint the NFT on-chain
857
+ * Uses the backend API which handles the on-chain transaction
173
858
  */
174
- async redeemVoucher(voucher, _buyerAddress) {
859
+ async redeemVoucher(voucher, buyerAddress, nftId, authToken) {
175
860
  if (voucher.deadline < Math.floor(Date.now() / 1e3)) {
176
861
  throw new Error("Voucher has expired");
177
862
  }
178
- return {
179
- hash: "",
180
- network: "ethereum",
181
- status: "pending"
182
- };
863
+ try {
864
+ const result = await this.apiClient.redeemVoucher(nftId, {
865
+ buyerAddress
866
+ });
867
+ if (result.success && result.transactionHash) {
868
+ return {
869
+ hash: result.transactionHash,
870
+ network: "ethereum",
871
+ status: "pending",
872
+ metadata: {
873
+ nftId: result.nftId,
874
+ tokenId: voucher.tokenId,
875
+ buyer: buyerAddress
876
+ }
877
+ };
878
+ }
879
+ throw new Error(result.error || "Failed to redeem voucher");
880
+ } catch (error) {
881
+ console.error("Failed to redeem voucher:", error);
882
+ throw new Error(`Voucher redemption failed: ${error instanceof Error ? error.message : "Unknown error"}`);
883
+ }
183
884
  }
184
885
  /**
185
- * List an NFT for sale on the marketplace
886
+ * List an NFT for sale on the marketplace via backend API
186
887
  */
187
- async listForSale(_params) {
188
- return {
189
- hash: "",
190
- network: "ethereum",
191
- status: "pending"
192
- };
888
+ async listForSale(params, authToken) {
889
+ try {
890
+ const currency = params.paymentToken === ZERO_ADDRESS ? "ETH" : "USDT";
891
+ const result = await this.apiClient.listItem({
892
+ nftId: params.tokenId,
893
+ // Using tokenId as nftId
894
+ price: params.price.toString(),
895
+ currency,
896
+ duration: params.duration || 30 * 24 * 60 * 60
897
+ // 30 days default
898
+ });
899
+ if (result.success && result.listing) {
900
+ return {
901
+ hash: result.listing.id || "",
902
+ network: "ethereum",
903
+ status: "pending",
904
+ metadata: {
905
+ listingId: result.listing.id,
906
+ price: params.price.toString(),
907
+ tokenId: params.tokenId
908
+ }
909
+ };
910
+ }
911
+ throw new Error(result.error || "Failed to list NFT");
912
+ } catch (error) {
913
+ console.error("Failed to list NFT:", error);
914
+ throw new Error(`Listing failed: ${error instanceof Error ? error.message : "Unknown error"}`);
915
+ }
193
916
  }
194
917
  /**
195
- * Buy an NFT from the marketplace
918
+ * Buy an NFT from the marketplace via backend API
196
919
  */
197
- async buyNFT(_listingId, _price) {
198
- return {
199
- hash: "",
200
- network: "ethereum",
201
- status: "pending"
202
- };
920
+ async buyNFT(listingId, price, buyerAddress) {
921
+ try {
922
+ const result = await this.apiClient.buyItem({
923
+ listingId,
924
+ buyerAddress
925
+ });
926
+ if (result.success && result.transactionHash) {
927
+ return {
928
+ hash: result.transactionHash,
929
+ network: "ethereum",
930
+ status: "pending",
931
+ metadata: {
932
+ listingId,
933
+ price: price.toString(),
934
+ buyer: buyerAddress
935
+ }
936
+ };
937
+ }
938
+ throw new Error(result.error || "Failed to buy NFT");
939
+ } catch (error) {
940
+ console.error("Failed to buy NFT:", error);
941
+ throw new Error(`Purchase failed: ${error instanceof Error ? error.message : "Unknown error"}`);
942
+ }
203
943
  }
204
944
  /**
205
945
  * Transfer an NFT to another address
946
+ * Note: This requires direct contract interaction via wallet
206
947
  */
207
- async transfer(_tokenId, _to) {
208
- return {
209
- hash: "",
210
- network: "ethereum",
211
- status: "pending"
212
- };
948
+ async transfer(tokenId, to, from, signer) {
949
+ try {
950
+ const functionSelector = "0x23b872dd";
951
+ const encodedFrom = from.toLowerCase().replace("0x", "").padStart(64, "0");
952
+ const encodedTo = to.toLowerCase().replace("0x", "").padStart(64, "0");
953
+ const encodedTokenId = BigInt(tokenId).toString(16).padStart(64, "0");
954
+ const data = `${functionSelector}${encodedFrom}${encodedTo}${encodedTokenId}`;
955
+ const tx = await signer.sendTransaction({
956
+ to: this.contractAddress,
957
+ data,
958
+ value: "0x0"
959
+ });
960
+ return {
961
+ hash: tx.hash,
962
+ network: "ethereum",
963
+ status: "pending",
964
+ metadata: {
965
+ tokenId,
966
+ from,
967
+ to
968
+ }
969
+ };
970
+ } catch (error) {
971
+ console.error("Failed to transfer NFT:", error);
972
+ throw new Error(`Transfer failed: ${error instanceof Error ? error.message : "Unknown error"}`);
973
+ }
213
974
  }
214
975
  /**
215
- * Get NFTs owned by an address
976
+ * Get NFTs owned by an address via backend API
216
977
  */
217
- async getOwnedNFTs(_address) {
218
- return [];
978
+ async getOwnedNFTs(address) {
979
+ try {
980
+ const result = await this.apiClient.getNFTs({ ownerId: address });
981
+ if (result.success && result.nfts) {
982
+ return result.nfts.map((nft) => ({
983
+ tokenId: nft.tokenId || nft.id,
984
+ contractAddress: nft.contractAddress || this.contractAddress,
985
+ owner: nft.ownerId || address,
986
+ creator: nft.creatorId || "",
987
+ uri: nft.imageUrl || nft.animationUrl || "",
988
+ metadata: nft.name ? {
989
+ name: nft.name,
990
+ description: nft.description || "",
991
+ image: nft.imageUrl || "",
992
+ royaltyBps: 0
993
+ // Default royalty, actual value from contract
994
+ } : void 0,
995
+ isLazyMinted: !nft.tokenId
996
+ // If no tokenId, it's lazy minted
997
+ }));
998
+ }
999
+ return [];
1000
+ } catch (error) {
1001
+ console.error("Failed to get owned NFTs:", error);
1002
+ return [];
1003
+ }
219
1004
  }
220
1005
  /**
221
1006
  * Generate a random tokenId (32 bytes hex)
@@ -3134,26 +3919,65 @@ var ZubariSubscriptionProtocol = class {
3134
3919
  };
3135
3920
 
3136
3921
  // src/protocols/PayoutsProtocol.ts
3922
+ var PAYOUTS_SELECTORS = {
3923
+ getEarningsBreakdown: "0xd4e9329c",
3924
+ // getEarningsBreakdown(address)
3925
+ claimEarnings: "0x48c54b9d",
3926
+ // claimEarnings(address)
3927
+ claimPartialEarnings: "0x7e3bfb5a",
3928
+ // claimPartialEarnings(address,uint256)
3929
+ setRevenueSplit: "0x92a8e3f5",
3930
+ // setRevenueSplit((address,uint256)[])
3931
+ getRevenueSplit: "0x6c8a4fd0",
3932
+ // getRevenueSplit(address)
3933
+ removeRevenueSplit: "0x8a4e3c5b"
3934
+ // removeRevenueSplit()
3935
+ };
3137
3936
  var ZubariPayoutsProtocol = class {
3138
3937
  contractAddress;
3139
3938
  chainId;
3140
3939
  apiBaseUrl;
3940
+ apiClient;
3141
3941
  constructor(contractAddress, chainId, apiBaseUrl) {
3142
3942
  this.contractAddress = contractAddress;
3143
3943
  this.chainId = chainId;
3144
3944
  this.apiBaseUrl = apiBaseUrl || "https://ckgwifsxka.us-east-2.awsapprunner.com";
3945
+ this.apiClient = getZubariApiClient({ baseUrl: this.apiBaseUrl });
3145
3946
  }
3146
3947
  /**
3147
- * Get pending earnings breakdown for the current user (on-chain)
3948
+ * Get pending earnings breakdown for the current user via API
3949
+ * Uses backend API which reads from contract/database
3148
3950
  */
3149
- async getPendingEarnings() {
3150
- return {
3151
- tips: BigInt(0),
3152
- subscriptions: BigInt(0),
3153
- nftSales: BigInt(0),
3154
- royalties: BigInt(0),
3155
- total: BigInt(0)
3156
- };
3951
+ async getPendingEarnings(authToken) {
3952
+ try {
3953
+ const response = await this.apiClient.getEarnings();
3954
+ if (response.success && response.earningsBreakdown) {
3955
+ const breakdown = response.earningsBreakdown;
3956
+ return {
3957
+ tips: BigInt(breakdown.tips || "0"),
3958
+ subscriptions: BigInt(breakdown.subscriptions || "0"),
3959
+ nftSales: BigInt(breakdown.nftSales || "0"),
3960
+ royalties: BigInt(breakdown.royalties || "0"),
3961
+ total: BigInt(breakdown.tips || "0") + BigInt(breakdown.subscriptions || "0") + BigInt(breakdown.nftSales || "0") + BigInt(breakdown.royalties || "0")
3962
+ };
3963
+ }
3964
+ return {
3965
+ tips: BigInt(0),
3966
+ subscriptions: BigInt(0),
3967
+ nftSales: BigInt(0),
3968
+ royalties: BigInt(0),
3969
+ total: BigInt(0)
3970
+ };
3971
+ } catch (error) {
3972
+ console.error("Failed to get pending earnings:", error);
3973
+ return {
3974
+ tips: BigInt(0),
3975
+ subscriptions: BigInt(0),
3976
+ nftSales: BigInt(0),
3977
+ royalties: BigInt(0),
3978
+ total: BigInt(0)
3979
+ };
3980
+ }
3157
3981
  }
3158
3982
  /**
3159
3983
  * Get earnings data from API (includes pending, total, breakdown, and recent payouts)
@@ -3225,10 +4049,30 @@ var ZubariPayoutsProtocol = class {
3225
4049
  return response.json();
3226
4050
  }
3227
4051
  /**
3228
- * Get historical earnings for a time period
4052
+ * Get historical earnings for a time period via API
3229
4053
  */
3230
- async getEarningsHistory(period = "all") {
3231
- return [];
4054
+ async getEarningsHistory(authToken, period = "all") {
4055
+ try {
4056
+ const response = await this.apiClient.getPayoutHistory({
4057
+ limit: period === "day" ? 24 : period === "week" ? 7 : period === "month" ? 30 : 100
4058
+ });
4059
+ if (response.success && response.payouts) {
4060
+ return response.payouts.map((payout) => ({
4061
+ tips: BigInt(0),
4062
+ // Individual payouts don't have breakdown
4063
+ subscriptions: BigInt(0),
4064
+ nftSales: BigInt(0),
4065
+ royalties: BigInt(0),
4066
+ total: BigInt(payout.amount || "0"),
4067
+ timestamp: payout.createdAt,
4068
+ status: payout.status
4069
+ }));
4070
+ }
4071
+ return [];
4072
+ } catch (error) {
4073
+ console.error("Failed to get earnings history:", error);
4074
+ return [];
4075
+ }
3232
4076
  }
3233
4077
  /**
3234
4078
  * Claim all pending earnings via API
@@ -3251,32 +4095,62 @@ var ZubariPayoutsProtocol = class {
3251
4095
  }
3252
4096
  /**
3253
4097
  * Claim all pending earnings (direct contract call)
4098
+ * Requires a signer with sendTransaction capability
3254
4099
  */
3255
- async claimEarnings() {
3256
- return {
3257
- hash: "",
3258
- network: "ethereum",
3259
- status: "pending"
3260
- };
4100
+ async claimEarnings(tokenAddress, signer) {
4101
+ try {
4102
+ const encodedToken = tokenAddress.toLowerCase().replace("0x", "").padStart(64, "0");
4103
+ const data = `${PAYOUTS_SELECTORS.claimEarnings}${encodedToken}`;
4104
+ const tx = await signer.sendTransaction({
4105
+ to: this.contractAddress,
4106
+ data,
4107
+ value: "0x0"
4108
+ });
4109
+ return {
4110
+ hash: tx.hash,
4111
+ network: "ethereum",
4112
+ status: "pending",
4113
+ metadata: { token: tokenAddress }
4114
+ };
4115
+ } catch (error) {
4116
+ console.error("Failed to claim earnings:", error);
4117
+ throw new Error(`Claim failed: ${error instanceof Error ? error.message : "Unknown error"}`);
4118
+ }
3261
4119
  }
3262
4120
  /**
3263
4121
  * Claim specific amount of earnings
4122
+ * Requires a signer with sendTransaction capability
3264
4123
  */
3265
- async claimPartialEarnings(amount) {
4124
+ async claimPartialEarnings(tokenAddress, amount, signer) {
3266
4125
  if (amount <= 0n) {
3267
4126
  throw new Error("Amount must be greater than 0");
3268
4127
  }
3269
- return {
3270
- hash: "",
3271
- network: "ethereum",
3272
- status: "pending"
3273
- };
4128
+ try {
4129
+ const encodedToken = tokenAddress.toLowerCase().replace("0x", "").padStart(64, "0");
4130
+ const encodedAmount = amount.toString(16).padStart(64, "0");
4131
+ const data = `${PAYOUTS_SELECTORS.claimPartialEarnings}${encodedToken}${encodedAmount}`;
4132
+ const tx = await signer.sendTransaction({
4133
+ to: this.contractAddress,
4134
+ data,
4135
+ value: "0x0"
4136
+ });
4137
+ return {
4138
+ hash: tx.hash,
4139
+ network: "ethereum",
4140
+ status: "pending",
4141
+ metadata: { token: tokenAddress, amount: amount.toString() }
4142
+ };
4143
+ } catch (error) {
4144
+ console.error("Failed to claim partial earnings:", error);
4145
+ throw new Error(`Partial claim failed: ${error instanceof Error ? error.message : "Unknown error"}`);
4146
+ }
3274
4147
  }
3275
4148
  /**
3276
4149
  * Setup revenue split with collaborators
3277
4150
  * Basis points must sum to 10000 (100%)
4151
+ * Requires a signer with sendTransaction capability
3278
4152
  */
3279
- async setupRevenueSplit(splits) {
4153
+ async setupRevenueSplit(splits, signer) {
3280
4154
  const totalBps = splits.reduce((sum, split) => sum + split.basisPoints, 0);
3281
4155
  if (totalBps !== 1e4) {
3282
4156
  throw new Error("Revenue splits must sum to 100% (10000 basis points)");
@@ -3289,40 +4163,98 @@ var ZubariPayoutsProtocol = class {
3289
4163
  throw new Error("Each split must have a valid recipient address");
3290
4164
  }
3291
4165
  }
3292
- return {
3293
- hash: "",
3294
- network: "ethereum",
3295
- status: "pending"
3296
- };
4166
+ try {
4167
+ const offset = "0".padStart(64, "0").slice(-64);
4168
+ const arrayLength = splits.length.toString(16).padStart(64, "0");
4169
+ let encodedSplits = "";
4170
+ for (const split of splits) {
4171
+ const encodedRecipient = split.recipient.toLowerCase().replace("0x", "").padStart(64, "0");
4172
+ const encodedBps = split.basisPoints.toString(16).padStart(64, "0");
4173
+ encodedSplits += encodedRecipient + encodedBps;
4174
+ }
4175
+ const data = `${PAYOUTS_SELECTORS.setRevenueSplit}${"0000000000000000000000000000000000000000000000000000000000000020"}${arrayLength}${encodedSplits}`;
4176
+ const tx = await signer.sendTransaction({
4177
+ to: this.contractAddress,
4178
+ data,
4179
+ value: "0x0"
4180
+ });
4181
+ return {
4182
+ hash: tx.hash,
4183
+ network: "ethereum",
4184
+ status: "pending",
4185
+ metadata: { splits }
4186
+ };
4187
+ } catch (error) {
4188
+ console.error("Failed to setup revenue split:", error);
4189
+ throw new Error(`Revenue split setup failed: ${error instanceof Error ? error.message : "Unknown error"}`);
4190
+ }
3297
4191
  }
3298
4192
  /**
3299
- * Get current revenue split configuration
4193
+ * Get current revenue split configuration via API
3300
4194
  */
3301
- async getRevenueSplit() {
3302
- return [];
4195
+ async getRevenueSplit(creatorAddress) {
4196
+ try {
4197
+ const response = await fetch(`${this.apiBaseUrl}/api/payouts/revenue-split/${creatorAddress}`, {
4198
+ headers: { "Content-Type": "application/json" }
4199
+ });
4200
+ if (response.ok) {
4201
+ const data = await response.json();
4202
+ if (data.success && data.splits) {
4203
+ return data.splits;
4204
+ }
4205
+ }
4206
+ return [];
4207
+ } catch (error) {
4208
+ console.error("Failed to get revenue split:", error);
4209
+ return [];
4210
+ }
3303
4211
  }
3304
4212
  /**
3305
4213
  * Remove revenue split (creator gets 100%)
4214
+ * Requires a signer with sendTransaction capability
3306
4215
  */
3307
- async removeRevenueSplit() {
3308
- return {
3309
- hash: "",
3310
- network: "ethereum",
3311
- status: "pending"
3312
- };
4216
+ async removeRevenueSplit(signer) {
4217
+ try {
4218
+ const data = PAYOUTS_SELECTORS.removeRevenueSplit;
4219
+ const tx = await signer.sendTransaction({
4220
+ to: this.contractAddress,
4221
+ data,
4222
+ value: "0x0"
4223
+ });
4224
+ return {
4225
+ hash: tx.hash,
4226
+ network: "ethereum",
4227
+ status: "pending"
4228
+ };
4229
+ } catch (error) {
4230
+ console.error("Failed to remove revenue split:", error);
4231
+ throw new Error(`Remove revenue split failed: ${error instanceof Error ? error.message : "Unknown error"}`);
4232
+ }
3313
4233
  }
3314
4234
  /**
3315
- * Convert earnings to stablecoin (USDT)
4235
+ * Convert earnings to stablecoin (USDT) via swap
4236
+ * This will be implemented when SwapService is complete
3316
4237
  */
3317
- async convertToStable(token, amount) {
4238
+ async convertToStable(token, amount, swapService) {
3318
4239
  if (amount <= 0n) {
3319
4240
  throw new Error("Amount must be greater than 0");
3320
4241
  }
3321
- return {
3322
- hash: "",
3323
- network: "ethereum",
3324
- status: "pending"
3325
- };
4242
+ if (!swapService) {
4243
+ throw new Error("SwapService required for conversion. Import and pass SwapService instance.");
4244
+ }
4245
+ try {
4246
+ return await swapService.executeSwap({
4247
+ tokenIn: token,
4248
+ tokenOut: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
4249
+ // USDT mainnet
4250
+ amountIn: amount,
4251
+ slippageBps: 50
4252
+ // 0.5% slippage
4253
+ });
4254
+ } catch (error) {
4255
+ console.error("Failed to convert to stable:", error);
4256
+ throw new Error(`Conversion failed: ${error instanceof Error ? error.message : "Unknown error"}`);
4257
+ }
3326
4258
  }
3327
4259
  /**
3328
4260
  * Get the contract address