@zubari/sdk 0.2.8 → 0.3.0

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