@zubari/sdk 0.1.29 → 0.2.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.
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  // src/config/contracts.ts
4
+ var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
4
5
  var PLATFORM_CONFIG = {
5
6
  // Platform fee in basis points (300 = 3%)
6
7
  tipFeeBps: 300,
@@ -18,37 +19,116 @@ var NFT_VOUCHER_TYPES = {
18
19
  { name: "uri", type: "string" },
19
20
  { name: "creator", type: "address" },
20
21
  { name: "royaltyBps", type: "uint256" },
21
- { name: "deadline", type: "uint256" }
22
+ { name: "deadline", type: "uint256" },
23
+ // Pricing fields
24
+ { name: "price", type: "uint256" },
25
+ { name: "currency", type: "address" },
26
+ { name: "nonce", type: "uint256" },
27
+ // Watermarking fields
28
+ { name: "contentHash", type: "bytes32" },
29
+ { name: "userId", type: "bytes32" },
30
+ { name: "watermarkTimestamp", type: "uint256" },
31
+ { name: "sessionId", type: "bytes32" }
22
32
  ]
23
33
  };
34
+ var CURRENCY_ADDRESSES = {
35
+ testnet: {
36
+ ETH: ZERO_ADDRESS,
37
+ USDT: "0xaA8E23Fb1079EA71e0a56F48a2aA51851D8433D0"
38
+ // USDT on Sepolia
39
+ },
40
+ mainnet: {
41
+ ETH: ZERO_ADDRESS,
42
+ USDT: "0xdAC17F958D2ee523a2206206994597C13D831ec7"
43
+ // USDT on Ethereum
44
+ }
45
+ };
24
46
 
25
47
  // src/protocols/NFTProtocol.ts
26
48
  var ZubariNFTProtocol = class {
27
49
  contractAddress;
28
50
  _marketplaceAddress;
29
51
  chainId;
30
- constructor(contractAddress, marketplaceAddress, chainId) {
52
+ network;
53
+ nonceCounter = 0;
54
+ constructor(contractAddress, marketplaceAddress, chainId, network = "testnet") {
31
55
  this.contractAddress = contractAddress;
32
56
  this._marketplaceAddress = marketplaceAddress;
33
57
  this.chainId = chainId;
58
+ this.network = network;
59
+ }
60
+ /**
61
+ * Convert human-readable price to wei
62
+ * @param price - Price in human-readable format (e.g., "1.5")
63
+ * @param currency - ETH (18 decimals) or USDT (6 decimals)
64
+ */
65
+ priceToWei(price, currency) {
66
+ const decimals = currency === "ETH" ? 18 : 6;
67
+ const [whole, fraction = ""] = price.split(".");
68
+ const paddedFraction = fraction.padEnd(decimals, "0").slice(0, decimals);
69
+ const wei = whole + paddedFraction;
70
+ return wei.replace(/^0+/, "") || "0";
71
+ }
72
+ /**
73
+ * Get currency address for the configured network
74
+ */
75
+ getCurrencyAddress(currency) {
76
+ return CURRENCY_ADDRESSES[this.network][currency];
77
+ }
78
+ /**
79
+ * Generate a unique nonce
80
+ */
81
+ generateNonce() {
82
+ return Date.now() * 1e3 + this.nonceCounter++;
83
+ }
84
+ /**
85
+ * Pad string to bytes32 format
86
+ */
87
+ toBytes32(value) {
88
+ if (value.startsWith("0x")) {
89
+ return value.padEnd(66, "0");
90
+ }
91
+ const hex = Buffer.from(value).toString("hex");
92
+ return "0x" + hex.padEnd(64, "0");
34
93
  }
35
94
  /**
36
95
  * Create a lazy mint voucher for off-chain NFT creation
37
96
  * The voucher can be redeemed on-chain when purchased
97
+ *
98
+ * @param params - Voucher creation parameters
99
+ * @param signer - Object with signTypedData method (ethers.js wallet or viem client)
38
100
  */
39
- async createLazyMintVoucher(metadata, creatorAddress, signer) {
101
+ async createLazyMintVoucher(params, signer) {
102
+ const { metadata, creatorAddress, price, currency, nonce, watermarking } = params;
40
103
  if (metadata.royaltyBps > PLATFORM_CONFIG.maxRoyaltyBps) {
41
104
  throw new Error(`Royalty cannot exceed ${PLATFORM_CONFIG.maxRoyaltyBps / 100}%`);
42
105
  }
106
+ if (!price || parseFloat(price) <= 0) {
107
+ throw new Error("Price must be greater than 0");
108
+ }
43
109
  const tokenId = this.generateTokenId();
44
110
  const deadline = Math.floor(Date.now() / 1e3) + PLATFORM_CONFIG.voucherValiditySecs;
111
+ const priceInWei = this.priceToWei(price, currency);
112
+ const currencyAddress = this.getCurrencyAddress(currency);
113
+ const voucherNonce = nonce ?? this.generateNonce();
114
+ const watermarkTimestamp = watermarking ? Math.floor(Date.now() / 1e3) : 0;
115
+ const contentHash = watermarking ? this.toBytes32(watermarking.contentHash) : ZERO_ADDRESS.replace("0x", "0x" + "0".repeat(64)).slice(0, 66);
116
+ const userId = watermarking ? this.toBytes32(watermarking.userId) : ZERO_ADDRESS.replace("0x", "0x" + "0".repeat(64)).slice(0, 66);
117
+ const sessionId = watermarking ? this.toBytes32(watermarking.sessionId) : ZERO_ADDRESS.replace("0x", "0x" + "0".repeat(64)).slice(0, 66);
45
118
  const voucherData = {
46
119
  tokenId,
47
120
  uri: metadata.image,
48
121
  // Will be IPFS URI
49
122
  creator: creatorAddress,
50
123
  royaltyBps: metadata.royaltyBps,
51
- deadline
124
+ deadline,
125
+ price: priceInWei,
126
+ currency: currencyAddress,
127
+ nonce: voucherNonce,
128
+ contentHash,
129
+ userId,
130
+ watermarkTimestamp,
131
+ sessionId
52
132
  };
53
133
  const domain = {
54
134
  ...NFT_VOUCHER_DOMAIN,
@@ -57,10 +137,36 @@ var ZubariNFTProtocol = class {
57
137
  };
58
138
  const signature = await signer.signTypedData(domain, NFT_VOUCHER_TYPES, voucherData);
59
139
  return {
60
- ...voucherData,
61
- signature
140
+ tokenId,
141
+ uri: metadata.image,
142
+ creator: creatorAddress,
143
+ royaltyBps: metadata.royaltyBps,
144
+ deadline,
145
+ signature,
146
+ price: priceInWei,
147
+ currency: currencyAddress,
148
+ nonce: voucherNonce,
149
+ contentHash: watermarking ? contentHash : void 0,
150
+ userId: watermarking ? userId : void 0,
151
+ watermarkTimestamp: watermarking ? watermarkTimestamp : void 0,
152
+ sessionId: watermarking ? sessionId : void 0
62
153
  };
63
154
  }
155
+ /**
156
+ * @deprecated Use createLazyMintVoucher(params, signer) instead
157
+ * Legacy method for backward compatibility
158
+ */
159
+ async createLazyMintVoucherLegacy(metadata, creatorAddress, signer) {
160
+ return this.createLazyMintVoucher(
161
+ {
162
+ metadata,
163
+ creatorAddress,
164
+ price: "0.01",
165
+ currency: "ETH"
166
+ },
167
+ signer
168
+ );
169
+ }
64
170
  /**
65
171
  * Redeem a lazy mint voucher to mint the NFT on-chain
66
172
  */
@@ -1008,187 +1114,2021 @@ var ZubariMarketProtocol = class {
1008
1114
  }
1009
1115
  };
1010
1116
 
1011
- // src/protocols/TipsProtocol.ts
1012
- var ZubariTipsProtocol = class {
1013
- contractAddress;
1014
- chainId;
1015
- gaslessEnabled;
1016
- constructor(contractAddress, chainId, gaslessEnabled = false) {
1017
- this.contractAddress = contractAddress;
1018
- this.chainId = chainId;
1019
- this.gaslessEnabled = gaslessEnabled;
1020
- }
1021
- /**
1022
- * Send a tip to a creator
1023
- */
1024
- async sendTip(tip) {
1025
- const { recipient, amount, token, message } = tip;
1026
- const platformFee = amount * BigInt(PLATFORM_CONFIG.tipFeeBps) / BigInt(1e4);
1027
- const creatorAmount = amount - platformFee;
1028
- if (amount <= 0n) {
1029
- throw new Error("Tip amount must be greater than 0");
1030
- }
1031
- const txResult = {
1032
- hash: ""};
1033
- return {
1034
- txHash: txResult.hash,
1035
- tipId: "",
1036
- // Will be returned from contract event
1037
- recipient,
1038
- amount: creatorAmount,
1039
- platformFee,
1040
- timestamp: Math.floor(Date.now() / 1e3)
1041
- };
1042
- }
1043
- /**
1044
- * Send tips to multiple creators in a single transaction
1045
- */
1046
- async sendBatchTips(tips) {
1047
- if (tips.length === 0) {
1048
- throw new Error("At least one tip is required");
1049
- }
1050
- tips.reduce((sum, tip) => sum + tip.amount, BigInt(0));
1051
- return tips.map((tip) => ({
1052
- txHash: "",
1053
- tipId: "",
1054
- recipient: tip.recipient,
1055
- amount: tip.amount - tip.amount * BigInt(PLATFORM_CONFIG.tipFeeBps) / BigInt(1e4),
1056
- platformFee: tip.amount * BigInt(PLATFORM_CONFIG.tipFeeBps) / BigInt(1e4),
1057
- timestamp: Math.floor(Date.now() / 1e3)
1058
- }));
1059
- }
1060
- /**
1061
- * Get tips received by an address
1062
- */
1063
- async getTipsReceived(address) {
1064
- return [];
1065
- }
1066
- /**
1067
- * Get tips sent by an address
1068
- */
1069
- async getTipsSent(address) {
1070
- return [];
1071
- }
1072
- /**
1073
- * Get tip statistics for a creator
1074
- */
1075
- async getCreatorTipStats(creator) {
1076
- return {
1077
- totalReceived: BigInt(0),
1078
- tipCount: 0,
1079
- uniqueTippers: 0
1080
- };
1081
- }
1082
- /**
1083
- * Get platform fee in basis points
1084
- */
1085
- getPlatformFeeBps() {
1086
- return PLATFORM_CONFIG.tipFeeBps;
1087
- }
1088
- };
1089
-
1090
- // src/protocols/SubscriptionProtocol.ts
1091
- var ZubariSubscriptionProtocol = class {
1092
- contractAddress;
1093
- chainId;
1094
- constructor(contractAddress, chainId) {
1095
- this.contractAddress = contractAddress;
1096
- this.chainId = chainId;
1097
- }
1098
- /**
1099
- * Create a new subscription plan
1100
- */
1101
- async createPlan(plan) {
1102
- if (!plan.name || plan.name.length === 0) {
1103
- throw new Error("Plan name is required");
1104
- }
1105
- if (plan.price <= 0n) {
1106
- throw new Error("Plan price must be greater than 0");
1107
- }
1108
- if (plan.duration <= 0) {
1109
- throw new Error("Plan duration must be greater than 0");
1110
- }
1111
- const planId = this.generatePlanId(plan.name);
1112
- return planId;
1113
- }
1114
- /**
1115
- * Update an existing subscription plan
1116
- */
1117
- async updatePlan(planId, updates) {
1118
- return {
1119
- hash: "",
1120
- network: "ethereum",
1121
- status: "pending"
1122
- };
1123
- }
1124
- /**
1125
- * Subscribe to a creator's plan
1126
- */
1127
- async subscribe(creator, planId, months = 1) {
1128
- if (months <= 0) {
1129
- throw new Error("Subscription duration must be at least 1 month");
1130
- }
1131
- const now = Math.floor(Date.now() / 1e3);
1132
- const durationSeconds = months * 30 * 24 * 60 * 60;
1133
- return {
1134
- subscriptionId: "",
1135
- planId,
1136
- creator,
1137
- subscriber: "",
1138
- // Current user address
1139
- startTime: now,
1140
- endTime: now + durationSeconds,
1141
- autoRenew: false,
1142
- status: "active"
1143
- };
1144
- }
1145
- /**
1146
- * Cancel an active subscription
1147
- */
1148
- async cancel(subscriptionId) {
1149
- return {
1150
- hash: "",
1151
- network: "ethereum",
1152
- status: "pending"
1153
- };
1154
- }
1155
- /**
1156
- * Check if an address is subscribed to a creator
1157
- */
1158
- async isSubscribed(creator, subscriber) {
1159
- return false;
1160
- }
1161
- /**
1162
- * Get active subscriptions for a subscriber
1163
- */
1164
- async getActiveSubscriptions(subscriber) {
1165
- return [];
1166
- }
1167
- /**
1168
- * Get all subscribers for a creator
1169
- */
1170
- async getSubscribers(creator) {
1171
- return [];
1172
- }
1173
- /**
1174
- * Get a specific plan by ID
1175
- */
1176
- async getPlan(planId) {
1177
- return null;
1178
- }
1179
- /**
1180
- * Get all plans for a creator
1181
- */
1182
- async getCreatorPlans(creator) {
1183
- return [];
1184
- }
1185
- /**
1186
- * Generate a unique plan ID
1187
- */
1188
- generatePlanId(name) {
1189
- const bytes = new Uint8Array(16);
1190
- crypto.getRandomValues(bytes);
1191
- return "0x" + Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
1117
+ // src/abi/ZubariTips.json
1118
+ var ZubariTips_default = [
1119
+ {
1120
+ inputs: [
1121
+ {
1122
+ internalType: "address",
1123
+ name: "_treasury",
1124
+ type: "address"
1125
+ },
1126
+ {
1127
+ internalType: "uint256",
1128
+ name: "_platformFeeBps",
1129
+ type: "uint256"
1130
+ }
1131
+ ],
1132
+ stateMutability: "nonpayable",
1133
+ type: "constructor"
1134
+ },
1135
+ {
1136
+ inputs: [],
1137
+ name: "EnforcedPause",
1138
+ type: "error"
1139
+ },
1140
+ {
1141
+ inputs: [],
1142
+ name: "ExpectedPause",
1143
+ type: "error"
1144
+ },
1145
+ {
1146
+ inputs: [],
1147
+ name: "InvalidAddress",
1148
+ type: "error"
1149
+ },
1150
+ {
1151
+ inputs: [],
1152
+ name: "InvalidAmount",
1153
+ type: "error"
1154
+ },
1155
+ {
1156
+ inputs: [],
1157
+ name: "InvalidFee",
1158
+ type: "error"
1159
+ },
1160
+ {
1161
+ inputs: [],
1162
+ name: "InvalidRecipient",
1163
+ type: "error"
1164
+ },
1165
+ {
1166
+ inputs: [
1167
+ {
1168
+ internalType: "address",
1169
+ name: "owner",
1170
+ type: "address"
1171
+ }
1172
+ ],
1173
+ name: "OwnableInvalidOwner",
1174
+ type: "error"
1175
+ },
1176
+ {
1177
+ inputs: [
1178
+ {
1179
+ internalType: "address",
1180
+ name: "account",
1181
+ type: "address"
1182
+ }
1183
+ ],
1184
+ name: "OwnableUnauthorizedAccount",
1185
+ type: "error"
1186
+ },
1187
+ {
1188
+ inputs: [],
1189
+ name: "ReentrancyGuardReentrantCall",
1190
+ type: "error"
1191
+ },
1192
+ {
1193
+ inputs: [
1194
+ {
1195
+ internalType: "address",
1196
+ name: "token",
1197
+ type: "address"
1198
+ }
1199
+ ],
1200
+ name: "SafeERC20FailedOperation",
1201
+ type: "error"
1202
+ },
1203
+ {
1204
+ inputs: [],
1205
+ name: "TransferFailed",
1206
+ type: "error"
1207
+ },
1208
+ {
1209
+ anonymous: false,
1210
+ inputs: [
1211
+ {
1212
+ indexed: false,
1213
+ internalType: "uint256[]",
1214
+ name: "tipIds",
1215
+ type: "uint256[]"
1216
+ },
1217
+ {
1218
+ indexed: true,
1219
+ internalType: "address",
1220
+ name: "sender",
1221
+ type: "address"
1222
+ }
1223
+ ],
1224
+ name: "BatchTipSent",
1225
+ type: "event"
1226
+ },
1227
+ {
1228
+ anonymous: false,
1229
+ inputs: [
1230
+ {
1231
+ indexed: true,
1232
+ internalType: "address",
1233
+ name: "previousOwner",
1234
+ type: "address"
1235
+ },
1236
+ {
1237
+ indexed: true,
1238
+ internalType: "address",
1239
+ name: "newOwner",
1240
+ type: "address"
1241
+ }
1242
+ ],
1243
+ name: "OwnershipTransferred",
1244
+ type: "event"
1245
+ },
1246
+ {
1247
+ anonymous: false,
1248
+ inputs: [
1249
+ {
1250
+ indexed: false,
1251
+ internalType: "address",
1252
+ name: "account",
1253
+ type: "address"
1254
+ }
1255
+ ],
1256
+ name: "Paused",
1257
+ type: "event"
1258
+ },
1259
+ {
1260
+ anonymous: false,
1261
+ inputs: [
1262
+ {
1263
+ indexed: false,
1264
+ internalType: "uint256",
1265
+ name: "oldFee",
1266
+ type: "uint256"
1267
+ },
1268
+ {
1269
+ indexed: false,
1270
+ internalType: "uint256",
1271
+ name: "newFee",
1272
+ type: "uint256"
1273
+ }
1274
+ ],
1275
+ name: "PlatformFeeUpdated",
1276
+ type: "event"
1277
+ },
1278
+ {
1279
+ anonymous: false,
1280
+ inputs: [
1281
+ {
1282
+ indexed: true,
1283
+ internalType: "uint256",
1284
+ name: "tipId",
1285
+ type: "uint256"
1286
+ },
1287
+ {
1288
+ indexed: true,
1289
+ internalType: "address",
1290
+ name: "sender",
1291
+ type: "address"
1292
+ },
1293
+ {
1294
+ indexed: true,
1295
+ internalType: "address",
1296
+ name: "recipient",
1297
+ type: "address"
1298
+ },
1299
+ {
1300
+ indexed: false,
1301
+ internalType: "address",
1302
+ name: "token",
1303
+ type: "address"
1304
+ },
1305
+ {
1306
+ indexed: false,
1307
+ internalType: "uint256",
1308
+ name: "amount",
1309
+ type: "uint256"
1310
+ },
1311
+ {
1312
+ indexed: false,
1313
+ internalType: "uint256",
1314
+ name: "platformFee",
1315
+ type: "uint256"
1316
+ },
1317
+ {
1318
+ indexed: false,
1319
+ internalType: "string",
1320
+ name: "message",
1321
+ type: "string"
1322
+ }
1323
+ ],
1324
+ name: "TipSent",
1325
+ type: "event"
1326
+ },
1327
+ {
1328
+ anonymous: false,
1329
+ inputs: [
1330
+ {
1331
+ indexed: false,
1332
+ internalType: "address",
1333
+ name: "oldTreasury",
1334
+ type: "address"
1335
+ },
1336
+ {
1337
+ indexed: false,
1338
+ internalType: "address",
1339
+ name: "newTreasury",
1340
+ type: "address"
1341
+ }
1342
+ ],
1343
+ name: "TreasuryUpdated",
1344
+ type: "event"
1345
+ },
1346
+ {
1347
+ anonymous: false,
1348
+ inputs: [
1349
+ {
1350
+ indexed: false,
1351
+ internalType: "address",
1352
+ name: "account",
1353
+ type: "address"
1354
+ }
1355
+ ],
1356
+ name: "Unpaused",
1357
+ type: "event"
1358
+ },
1359
+ {
1360
+ inputs: [
1361
+ {
1362
+ internalType: "uint256",
1363
+ name: "tipId",
1364
+ type: "uint256"
1365
+ }
1366
+ ],
1367
+ name: "getTip",
1368
+ outputs: [
1369
+ {
1370
+ components: [
1371
+ {
1372
+ internalType: "uint256",
1373
+ name: "tipId",
1374
+ type: "uint256"
1375
+ },
1376
+ {
1377
+ internalType: "address",
1378
+ name: "sender",
1379
+ type: "address"
1380
+ },
1381
+ {
1382
+ internalType: "address",
1383
+ name: "recipient",
1384
+ type: "address"
1385
+ },
1386
+ {
1387
+ internalType: "address",
1388
+ name: "token",
1389
+ type: "address"
1390
+ },
1391
+ {
1392
+ internalType: "uint256",
1393
+ name: "amount",
1394
+ type: "uint256"
1395
+ },
1396
+ {
1397
+ internalType: "uint256",
1398
+ name: "platformFee",
1399
+ type: "uint256"
1400
+ },
1401
+ {
1402
+ internalType: "string",
1403
+ name: "message",
1404
+ type: "string"
1405
+ },
1406
+ {
1407
+ internalType: "uint256",
1408
+ name: "timestamp",
1409
+ type: "uint256"
1410
+ }
1411
+ ],
1412
+ internalType: "struct ZubariTips.Tip",
1413
+ name: "",
1414
+ type: "tuple"
1415
+ }
1416
+ ],
1417
+ stateMutability: "view",
1418
+ type: "function"
1419
+ },
1420
+ {
1421
+ inputs: [],
1422
+ name: "owner",
1423
+ outputs: [
1424
+ {
1425
+ internalType: "address",
1426
+ name: "",
1427
+ type: "address"
1428
+ }
1429
+ ],
1430
+ stateMutability: "view",
1431
+ type: "function"
1432
+ },
1433
+ {
1434
+ inputs: [],
1435
+ name: "pause",
1436
+ outputs: [],
1437
+ stateMutability: "nonpayable",
1438
+ type: "function"
1439
+ },
1440
+ {
1441
+ inputs: [],
1442
+ name: "paused",
1443
+ outputs: [
1444
+ {
1445
+ internalType: "bool",
1446
+ name: "",
1447
+ type: "bool"
1448
+ }
1449
+ ],
1450
+ stateMutability: "view",
1451
+ type: "function"
1452
+ },
1453
+ {
1454
+ inputs: [],
1455
+ name: "platformFeeBps",
1456
+ outputs: [
1457
+ {
1458
+ internalType: "uint256",
1459
+ name: "",
1460
+ type: "uint256"
1461
+ }
1462
+ ],
1463
+ stateMutability: "view",
1464
+ type: "function"
1465
+ },
1466
+ {
1467
+ inputs: [],
1468
+ name: "renounceOwnership",
1469
+ outputs: [],
1470
+ stateMutability: "nonpayable",
1471
+ type: "function"
1472
+ },
1473
+ {
1474
+ inputs: [
1475
+ {
1476
+ internalType: "address[]",
1477
+ name: "recipients",
1478
+ type: "address[]"
1479
+ },
1480
+ {
1481
+ internalType: "uint256[]",
1482
+ name: "amounts",
1483
+ type: "uint256[]"
1484
+ },
1485
+ {
1486
+ internalType: "string[]",
1487
+ name: "messages",
1488
+ type: "string[]"
1489
+ }
1490
+ ],
1491
+ name: "sendBatchTips",
1492
+ outputs: [],
1493
+ stateMutability: "payable",
1494
+ type: "function"
1495
+ },
1496
+ {
1497
+ inputs: [
1498
+ {
1499
+ internalType: "uint256",
1500
+ name: "_feeBps",
1501
+ type: "uint256"
1502
+ }
1503
+ ],
1504
+ name: "setPlatformFee",
1505
+ outputs: [],
1506
+ stateMutability: "nonpayable",
1507
+ type: "function"
1508
+ },
1509
+ {
1510
+ inputs: [
1511
+ {
1512
+ internalType: "address",
1513
+ name: "_treasury",
1514
+ type: "address"
1515
+ }
1516
+ ],
1517
+ name: "setTreasury",
1518
+ outputs: [],
1519
+ stateMutability: "nonpayable",
1520
+ type: "function"
1521
+ },
1522
+ {
1523
+ inputs: [],
1524
+ name: "tipCounter",
1525
+ outputs: [
1526
+ {
1527
+ internalType: "uint256",
1528
+ name: "",
1529
+ type: "uint256"
1530
+ }
1531
+ ],
1532
+ stateMutability: "view",
1533
+ type: "function"
1534
+ },
1535
+ {
1536
+ inputs: [
1537
+ {
1538
+ internalType: "address",
1539
+ name: "recipient",
1540
+ type: "address"
1541
+ },
1542
+ {
1543
+ internalType: "string",
1544
+ name: "message",
1545
+ type: "string"
1546
+ }
1547
+ ],
1548
+ name: "tipETH",
1549
+ outputs: [],
1550
+ stateMutability: "payable",
1551
+ type: "function"
1552
+ },
1553
+ {
1554
+ inputs: [
1555
+ {
1556
+ internalType: "address",
1557
+ name: "recipient",
1558
+ type: "address"
1559
+ },
1560
+ {
1561
+ internalType: "address",
1562
+ name: "token",
1563
+ type: "address"
1564
+ },
1565
+ {
1566
+ internalType: "uint256",
1567
+ name: "amount",
1568
+ type: "uint256"
1569
+ },
1570
+ {
1571
+ internalType: "string",
1572
+ name: "message",
1573
+ type: "string"
1574
+ }
1575
+ ],
1576
+ name: "tipToken",
1577
+ outputs: [],
1578
+ stateMutability: "nonpayable",
1579
+ type: "function"
1580
+ },
1581
+ {
1582
+ inputs: [
1583
+ {
1584
+ internalType: "uint256",
1585
+ name: "",
1586
+ type: "uint256"
1587
+ }
1588
+ ],
1589
+ name: "tips",
1590
+ outputs: [
1591
+ {
1592
+ internalType: "uint256",
1593
+ name: "tipId",
1594
+ type: "uint256"
1595
+ },
1596
+ {
1597
+ internalType: "address",
1598
+ name: "sender",
1599
+ type: "address"
1600
+ },
1601
+ {
1602
+ internalType: "address",
1603
+ name: "recipient",
1604
+ type: "address"
1605
+ },
1606
+ {
1607
+ internalType: "address",
1608
+ name: "token",
1609
+ type: "address"
1610
+ },
1611
+ {
1612
+ internalType: "uint256",
1613
+ name: "amount",
1614
+ type: "uint256"
1615
+ },
1616
+ {
1617
+ internalType: "uint256",
1618
+ name: "platformFee",
1619
+ type: "uint256"
1620
+ },
1621
+ {
1622
+ internalType: "string",
1623
+ name: "message",
1624
+ type: "string"
1625
+ },
1626
+ {
1627
+ internalType: "uint256",
1628
+ name: "timestamp",
1629
+ type: "uint256"
1630
+ }
1631
+ ],
1632
+ stateMutability: "view",
1633
+ type: "function"
1634
+ },
1635
+ {
1636
+ inputs: [
1637
+ {
1638
+ internalType: "address",
1639
+ name: "",
1640
+ type: "address"
1641
+ }
1642
+ ],
1643
+ name: "totalTipsReceived",
1644
+ outputs: [
1645
+ {
1646
+ internalType: "uint256",
1647
+ name: "",
1648
+ type: "uint256"
1649
+ }
1650
+ ],
1651
+ stateMutability: "view",
1652
+ type: "function"
1653
+ },
1654
+ {
1655
+ inputs: [
1656
+ {
1657
+ internalType: "address",
1658
+ name: "newOwner",
1659
+ type: "address"
1660
+ }
1661
+ ],
1662
+ name: "transferOwnership",
1663
+ outputs: [],
1664
+ stateMutability: "nonpayable",
1665
+ type: "function"
1666
+ },
1667
+ {
1668
+ inputs: [],
1669
+ name: "treasury",
1670
+ outputs: [
1671
+ {
1672
+ internalType: "address",
1673
+ name: "",
1674
+ type: "address"
1675
+ }
1676
+ ],
1677
+ stateMutability: "view",
1678
+ type: "function"
1679
+ },
1680
+ {
1681
+ inputs: [],
1682
+ name: "unpause",
1683
+ outputs: [],
1684
+ stateMutability: "nonpayable",
1685
+ type: "function"
1686
+ }
1687
+ ];
1688
+
1689
+ // src/protocols/TipsProtocol.ts
1690
+ var ZubariTipsProtocol = class {
1691
+ contractAddress;
1692
+ chainId;
1693
+ abi = ZubariTips_default;
1694
+ constructor(contractAddress, chainId) {
1695
+ this.contractAddress = contractAddress;
1696
+ this.chainId = chainId;
1697
+ }
1698
+ /**
1699
+ * Get the contract ABI
1700
+ */
1701
+ getAbi() {
1702
+ return this.abi;
1703
+ }
1704
+ /**
1705
+ * Get the contract address
1706
+ */
1707
+ getAddress() {
1708
+ return this.contractAddress;
1709
+ }
1710
+ /**
1711
+ * Send ETH tip to a creator
1712
+ * @param recipient The recipient address
1713
+ * @param message Optional tip message
1714
+ * @param signer Wallet signer with sendTransaction method
1715
+ * @param value ETH amount to tip (in wei)
1716
+ */
1717
+ async tipETH(recipient, message, signer, value) {
1718
+ if (!recipient || recipient === "0x0000000000000000000000000000000000000000") {
1719
+ throw new Error("Invalid recipient address");
1720
+ }
1721
+ if (value <= 0n) {
1722
+ throw new Error("Tip amount must be greater than 0");
1723
+ }
1724
+ const iface = new (await import('ethers')).Interface(this.abi);
1725
+ const data = iface.encodeFunctionData("tipETH", [recipient, message || ""]);
1726
+ const result = await signer.sendTransaction({
1727
+ to: this.contractAddress,
1728
+ value,
1729
+ data
1730
+ });
1731
+ return {
1732
+ hash: result.hash,
1733
+ network: "ethereum",
1734
+ status: "pending"
1735
+ };
1736
+ }
1737
+ /**
1738
+ * Send ERC-20 token tip to a creator
1739
+ * @param recipient The recipient address
1740
+ * @param token The ERC-20 token address
1741
+ * @param amount The amount of tokens to tip
1742
+ * @param message Optional tip message
1743
+ * @param signer Wallet signer
1744
+ */
1745
+ async tipToken(recipient, token, amount, message, signer) {
1746
+ if (!recipient || recipient === "0x0000000000000000000000000000000000000000") {
1747
+ throw new Error("Invalid recipient address");
1748
+ }
1749
+ if (!token || token === "0x0000000000000000000000000000000000000000") {
1750
+ throw new Error("Use tipETH for native ETH tips");
1751
+ }
1752
+ if (amount <= 0n) {
1753
+ throw new Error("Tip amount must be greater than 0");
1754
+ }
1755
+ const iface = new (await import('ethers')).Interface(this.abi);
1756
+ const data = iface.encodeFunctionData("tipToken", [recipient, token, amount, message || ""]);
1757
+ const result = await signer.sendTransaction({
1758
+ to: this.contractAddress,
1759
+ value: 0n,
1760
+ data
1761
+ });
1762
+ return {
1763
+ hash: result.hash,
1764
+ network: "ethereum",
1765
+ status: "pending"
1766
+ };
1767
+ }
1768
+ /**
1769
+ * Send batch tips to multiple creators in a single transaction
1770
+ * @param recipients Array of recipient addresses
1771
+ * @param amounts Array of tip amounts (in wei)
1772
+ * @param messages Array of tip messages
1773
+ * @param signer Wallet signer
1774
+ * @param value Total ETH to send
1775
+ */
1776
+ async sendBatchTips(recipients, amounts, messages, signer, value) {
1777
+ if (recipients.length === 0) {
1778
+ throw new Error("At least one recipient is required");
1779
+ }
1780
+ if (recipients.length !== amounts.length || recipients.length !== messages.length) {
1781
+ throw new Error("Recipients, amounts, and messages arrays must have the same length");
1782
+ }
1783
+ for (const recipient of recipients) {
1784
+ if (!recipient || recipient === "0x0000000000000000000000000000000000000000") {
1785
+ throw new Error("Invalid recipient address in batch");
1786
+ }
1787
+ }
1788
+ const totalAmount = amounts.reduce((sum, amount) => sum + amount, 0n);
1789
+ if (totalAmount <= 0n) {
1790
+ throw new Error("Total tip amount must be greater than 0");
1791
+ }
1792
+ const iface = new (await import('ethers')).Interface(this.abi);
1793
+ const data = iface.encodeFunctionData("sendBatchTips", [recipients, amounts, messages]);
1794
+ const result = await signer.sendTransaction({
1795
+ to: this.contractAddress,
1796
+ value,
1797
+ data
1798
+ });
1799
+ return {
1800
+ hash: result.hash,
1801
+ network: "ethereum",
1802
+ status: "pending"
1803
+ };
1804
+ }
1805
+ /**
1806
+ * Get tip details by ID
1807
+ * @param tipId The tip ID
1808
+ * @param provider JSON-RPC provider
1809
+ */
1810
+ async getTip(tipId, provider) {
1811
+ const iface = new (await import('ethers')).Interface(this.abi);
1812
+ const data = iface.encodeFunctionData("getTip", [tipId]);
1813
+ try {
1814
+ const result = await provider.call({
1815
+ to: this.contractAddress,
1816
+ data
1817
+ });
1818
+ const decoded = iface.decodeFunctionResult("getTip", result);
1819
+ const tip = decoded[0];
1820
+ if (BigInt(tip.tipId) === 0n) {
1821
+ return null;
1822
+ }
1823
+ return {
1824
+ tipId: tip.tipId.toString(),
1825
+ sender: tip.sender,
1826
+ recipient: tip.recipient,
1827
+ token: tip.token,
1828
+ amount: BigInt(tip.amount),
1829
+ platformFee: BigInt(tip.platformFee),
1830
+ message: tip.message,
1831
+ timestamp: Number(tip.timestamp)
1832
+ };
1833
+ } catch {
1834
+ return null;
1835
+ }
1836
+ }
1837
+ /**
1838
+ * Get total tips received by an address
1839
+ * @param address The address to query
1840
+ * @param provider JSON-RPC provider
1841
+ */
1842
+ async getTotalTipsReceived(address, provider) {
1843
+ const iface = new (await import('ethers')).Interface(this.abi);
1844
+ const data = iface.encodeFunctionData("totalTipsReceived", [address]);
1845
+ try {
1846
+ const result = await provider.call({
1847
+ to: this.contractAddress,
1848
+ data
1849
+ });
1850
+ const decoded = iface.decodeFunctionResult("totalTipsReceived", result);
1851
+ return BigInt(decoded[0]);
1852
+ } catch {
1853
+ return 0n;
1854
+ }
1855
+ }
1856
+ /**
1857
+ * Get platform fee in basis points
1858
+ * @param provider JSON-RPC provider
1859
+ */
1860
+ async getPlatformFeeBps(provider) {
1861
+ const iface = new (await import('ethers')).Interface(this.abi);
1862
+ const data = iface.encodeFunctionData("platformFeeBps", []);
1863
+ try {
1864
+ const result = await provider.call({
1865
+ to: this.contractAddress,
1866
+ data
1867
+ });
1868
+ const decoded = iface.decodeFunctionResult("platformFeeBps", result);
1869
+ return Number(decoded[0]);
1870
+ } catch {
1871
+ return 300;
1872
+ }
1873
+ }
1874
+ /**
1875
+ * Get current tip counter
1876
+ * @param provider JSON-RPC provider
1877
+ */
1878
+ async getTipCounter(provider) {
1879
+ const iface = new (await import('ethers')).Interface(this.abi);
1880
+ const data = iface.encodeFunctionData("tipCounter", []);
1881
+ try {
1882
+ const result = await provider.call({
1883
+ to: this.contractAddress,
1884
+ data
1885
+ });
1886
+ const decoded = iface.decodeFunctionResult("tipCounter", result);
1887
+ return BigInt(decoded[0]);
1888
+ } catch {
1889
+ return 0n;
1890
+ }
1891
+ }
1892
+ /**
1893
+ * Get treasury address
1894
+ * @param provider JSON-RPC provider
1895
+ */
1896
+ async getTreasury(provider) {
1897
+ const iface = new (await import('ethers')).Interface(this.abi);
1898
+ const data = iface.encodeFunctionData("treasury", []);
1899
+ try {
1900
+ const result = await provider.call({
1901
+ to: this.contractAddress,
1902
+ data
1903
+ });
1904
+ const decoded = iface.decodeFunctionResult("treasury", result);
1905
+ return decoded[0];
1906
+ } catch {
1907
+ return "0x0000000000000000000000000000000000000000";
1908
+ }
1909
+ }
1910
+ /**
1911
+ * Calculate platform fee for a given amount
1912
+ * @param amount The tip amount
1913
+ * @param feeBps Fee in basis points (default: 300 = 3%)
1914
+ */
1915
+ calculateFee(amount, feeBps = 300) {
1916
+ const fee = amount * BigInt(feeBps) / 10000n;
1917
+ return {
1918
+ fee,
1919
+ creatorAmount: amount - fee
1920
+ };
1921
+ }
1922
+ };
1923
+
1924
+ // src/abi/ZubariSubscription.json
1925
+ var ZubariSubscription_default = [
1926
+ {
1927
+ inputs: [
1928
+ {
1929
+ internalType: "address",
1930
+ name: "_treasury",
1931
+ type: "address"
1932
+ },
1933
+ {
1934
+ internalType: "uint256",
1935
+ name: "_platformFeeBps",
1936
+ type: "uint256"
1937
+ }
1938
+ ],
1939
+ stateMutability: "nonpayable",
1940
+ type: "constructor"
1941
+ },
1942
+ {
1943
+ inputs: [],
1944
+ name: "AlreadySubscribed",
1945
+ type: "error"
1946
+ },
1947
+ {
1948
+ inputs: [],
1949
+ name: "EnforcedPause",
1950
+ type: "error"
1951
+ },
1952
+ {
1953
+ inputs: [],
1954
+ name: "ExpectedPause",
1955
+ type: "error"
1956
+ },
1957
+ {
1958
+ inputs: [],
1959
+ name: "InvalidAddress",
1960
+ type: "error"
1961
+ },
1962
+ {
1963
+ inputs: [],
1964
+ name: "InvalidAmount",
1965
+ type: "error"
1966
+ },
1967
+ {
1968
+ inputs: [],
1969
+ name: "InvalidDuration",
1970
+ type: "error"
1971
+ },
1972
+ {
1973
+ inputs: [],
1974
+ name: "InvalidFee",
1975
+ type: "error"
1976
+ },
1977
+ {
1978
+ inputs: [],
1979
+ name: "NotSubscriber",
1980
+ type: "error"
1981
+ },
1982
+ {
1983
+ inputs: [
1984
+ {
1985
+ internalType: "address",
1986
+ name: "owner",
1987
+ type: "address"
1988
+ }
1989
+ ],
1990
+ name: "OwnableInvalidOwner",
1991
+ type: "error"
1992
+ },
1993
+ {
1994
+ inputs: [
1995
+ {
1996
+ internalType: "address",
1997
+ name: "account",
1998
+ type: "address"
1999
+ }
2000
+ ],
2001
+ name: "OwnableUnauthorizedAccount",
2002
+ type: "error"
2003
+ },
2004
+ {
2005
+ inputs: [],
2006
+ name: "PlanFull",
2007
+ type: "error"
2008
+ },
2009
+ {
2010
+ inputs: [],
2011
+ name: "PlanNotActive",
2012
+ type: "error"
2013
+ },
2014
+ {
2015
+ inputs: [],
2016
+ name: "PlanNotFound",
2017
+ type: "error"
2018
+ },
2019
+ {
2020
+ inputs: [],
2021
+ name: "ReentrancyGuardReentrantCall",
2022
+ type: "error"
2023
+ },
2024
+ {
2025
+ inputs: [
2026
+ {
2027
+ internalType: "address",
2028
+ name: "token",
2029
+ type: "address"
2030
+ }
2031
+ ],
2032
+ name: "SafeERC20FailedOperation",
2033
+ type: "error"
2034
+ },
2035
+ {
2036
+ anonymous: false,
2037
+ inputs: [
2038
+ {
2039
+ indexed: true,
2040
+ internalType: "address",
2041
+ name: "previousOwner",
2042
+ type: "address"
2043
+ },
2044
+ {
2045
+ indexed: true,
2046
+ internalType: "address",
2047
+ name: "newOwner",
2048
+ type: "address"
2049
+ }
2050
+ ],
2051
+ name: "OwnershipTransferred",
2052
+ type: "event"
2053
+ },
2054
+ {
2055
+ anonymous: false,
2056
+ inputs: [
2057
+ {
2058
+ indexed: false,
2059
+ internalType: "address",
2060
+ name: "account",
2061
+ type: "address"
2062
+ }
2063
+ ],
2064
+ name: "Paused",
2065
+ type: "event"
2066
+ },
2067
+ {
2068
+ anonymous: false,
2069
+ inputs: [
2070
+ {
2071
+ indexed: true,
2072
+ internalType: "bytes32",
2073
+ name: "planId",
2074
+ type: "bytes32"
2075
+ },
2076
+ {
2077
+ indexed: true,
2078
+ internalType: "address",
2079
+ name: "creator",
2080
+ type: "address"
2081
+ },
2082
+ {
2083
+ indexed: false,
2084
+ internalType: "string",
2085
+ name: "name",
2086
+ type: "string"
2087
+ },
2088
+ {
2089
+ indexed: false,
2090
+ internalType: "uint256",
2091
+ name: "price",
2092
+ type: "uint256"
2093
+ }
2094
+ ],
2095
+ name: "PlanCreated",
2096
+ type: "event"
2097
+ },
2098
+ {
2099
+ anonymous: false,
2100
+ inputs: [
2101
+ {
2102
+ indexed: true,
2103
+ internalType: "bytes32",
2104
+ name: "planId",
2105
+ type: "bytes32"
2106
+ }
2107
+ ],
2108
+ name: "PlanDeactivated",
2109
+ type: "event"
2110
+ },
2111
+ {
2112
+ anonymous: false,
2113
+ inputs: [
2114
+ {
2115
+ indexed: true,
2116
+ internalType: "bytes32",
2117
+ name: "planId",
2118
+ type: "bytes32"
2119
+ }
2120
+ ],
2121
+ name: "PlanUpdated",
2122
+ type: "event"
2123
+ },
2124
+ {
2125
+ anonymous: false,
2126
+ inputs: [
2127
+ {
2128
+ indexed: true,
2129
+ internalType: "bytes32",
2130
+ name: "subscriptionId",
2131
+ type: "bytes32"
2132
+ },
2133
+ {
2134
+ indexed: true,
2135
+ internalType: "bytes32",
2136
+ name: "planId",
2137
+ type: "bytes32"
2138
+ },
2139
+ {
2140
+ indexed: true,
2141
+ internalType: "address",
2142
+ name: "subscriber",
2143
+ type: "address"
2144
+ },
2145
+ {
2146
+ indexed: false,
2147
+ internalType: "address",
2148
+ name: "creator",
2149
+ type: "address"
2150
+ },
2151
+ {
2152
+ indexed: false,
2153
+ internalType: "uint256",
2154
+ name: "endTime",
2155
+ type: "uint256"
2156
+ }
2157
+ ],
2158
+ name: "Subscribed",
2159
+ type: "event"
2160
+ },
2161
+ {
2162
+ anonymous: false,
2163
+ inputs: [
2164
+ {
2165
+ indexed: true,
2166
+ internalType: "bytes32",
2167
+ name: "subscriptionId",
2168
+ type: "bytes32"
2169
+ }
2170
+ ],
2171
+ name: "SubscriptionCancelled",
2172
+ type: "event"
2173
+ },
2174
+ {
2175
+ anonymous: false,
2176
+ inputs: [
2177
+ {
2178
+ indexed: true,
2179
+ internalType: "bytes32",
2180
+ name: "subscriptionId",
2181
+ type: "bytes32"
2182
+ },
2183
+ {
2184
+ indexed: false,
2185
+ internalType: "uint256",
2186
+ name: "newEndTime",
2187
+ type: "uint256"
2188
+ }
2189
+ ],
2190
+ name: "SubscriptionRenewed",
2191
+ type: "event"
2192
+ },
2193
+ {
2194
+ anonymous: false,
2195
+ inputs: [
2196
+ {
2197
+ indexed: false,
2198
+ internalType: "address",
2199
+ name: "account",
2200
+ type: "address"
2201
+ }
2202
+ ],
2203
+ name: "Unpaused",
2204
+ type: "event"
2205
+ },
2206
+ {
2207
+ inputs: [
2208
+ {
2209
+ internalType: "address",
2210
+ name: "",
2211
+ type: "address"
2212
+ },
2213
+ {
2214
+ internalType: "address",
2215
+ name: "",
2216
+ type: "address"
2217
+ }
2218
+ ],
2219
+ name: "activeSubscription",
2220
+ outputs: [
2221
+ {
2222
+ internalType: "bytes32",
2223
+ name: "",
2224
+ type: "bytes32"
2225
+ }
2226
+ ],
2227
+ stateMutability: "view",
2228
+ type: "function"
2229
+ },
2230
+ {
2231
+ inputs: [
2232
+ {
2233
+ internalType: "bytes32",
2234
+ name: "subscriptionId",
2235
+ type: "bytes32"
2236
+ }
2237
+ ],
2238
+ name: "cancel",
2239
+ outputs: [],
2240
+ stateMutability: "nonpayable",
2241
+ type: "function"
2242
+ },
2243
+ {
2244
+ inputs: [
2245
+ {
2246
+ internalType: "string",
2247
+ name: "name",
2248
+ type: "string"
2249
+ },
2250
+ {
2251
+ internalType: "string",
2252
+ name: "description",
2253
+ type: "string"
2254
+ },
2255
+ {
2256
+ internalType: "uint256",
2257
+ name: "price",
2258
+ type: "uint256"
2259
+ },
2260
+ {
2261
+ internalType: "address",
2262
+ name: "paymentToken",
2263
+ type: "address"
2264
+ },
2265
+ {
2266
+ internalType: "uint256",
2267
+ name: "durationDays",
2268
+ type: "uint256"
2269
+ },
2270
+ {
2271
+ internalType: "uint256",
2272
+ name: "maxSubscribers",
2273
+ type: "uint256"
2274
+ }
2275
+ ],
2276
+ name: "createPlan",
2277
+ outputs: [
2278
+ {
2279
+ internalType: "bytes32",
2280
+ name: "",
2281
+ type: "bytes32"
2282
+ }
2283
+ ],
2284
+ stateMutability: "nonpayable",
2285
+ type: "function"
2286
+ },
2287
+ {
2288
+ inputs: [
2289
+ {
2290
+ internalType: "address",
2291
+ name: "",
2292
+ type: "address"
2293
+ },
2294
+ {
2295
+ internalType: "uint256",
2296
+ name: "",
2297
+ type: "uint256"
2298
+ }
2299
+ ],
2300
+ name: "creatorPlans",
2301
+ outputs: [
2302
+ {
2303
+ internalType: "bytes32",
2304
+ name: "",
2305
+ type: "bytes32"
2306
+ }
2307
+ ],
2308
+ stateMutability: "view",
2309
+ type: "function"
2310
+ },
2311
+ {
2312
+ inputs: [
2313
+ {
2314
+ internalType: "bytes32",
2315
+ name: "planId",
2316
+ type: "bytes32"
2317
+ }
2318
+ ],
2319
+ name: "deactivatePlan",
2320
+ outputs: [],
2321
+ stateMutability: "nonpayable",
2322
+ type: "function"
2323
+ },
2324
+ {
2325
+ inputs: [
2326
+ {
2327
+ internalType: "address",
2328
+ name: "creator",
2329
+ type: "address"
2330
+ }
2331
+ ],
2332
+ name: "getCreatorPlans",
2333
+ outputs: [
2334
+ {
2335
+ internalType: "bytes32[]",
2336
+ name: "",
2337
+ type: "bytes32[]"
2338
+ }
2339
+ ],
2340
+ stateMutability: "view",
2341
+ type: "function"
2342
+ },
2343
+ {
2344
+ inputs: [
2345
+ {
2346
+ internalType: "bytes32",
2347
+ name: "planId",
2348
+ type: "bytes32"
2349
+ }
2350
+ ],
2351
+ name: "getPlan",
2352
+ outputs: [
2353
+ {
2354
+ components: [
2355
+ {
2356
+ internalType: "bytes32",
2357
+ name: "planId",
2358
+ type: "bytes32"
2359
+ },
2360
+ {
2361
+ internalType: "address",
2362
+ name: "creator",
2363
+ type: "address"
2364
+ },
2365
+ {
2366
+ internalType: "string",
2367
+ name: "name",
2368
+ type: "string"
2369
+ },
2370
+ {
2371
+ internalType: "string",
2372
+ name: "description",
2373
+ type: "string"
2374
+ },
2375
+ {
2376
+ internalType: "uint256",
2377
+ name: "price",
2378
+ type: "uint256"
2379
+ },
2380
+ {
2381
+ internalType: "address",
2382
+ name: "paymentToken",
2383
+ type: "address"
2384
+ },
2385
+ {
2386
+ internalType: "uint256",
2387
+ name: "durationDays",
2388
+ type: "uint256"
2389
+ },
2390
+ {
2391
+ internalType: "uint256",
2392
+ name: "maxSubscribers",
2393
+ type: "uint256"
2394
+ },
2395
+ {
2396
+ internalType: "uint256",
2397
+ name: "subscriberCount",
2398
+ type: "uint256"
2399
+ },
2400
+ {
2401
+ internalType: "bool",
2402
+ name: "isActive",
2403
+ type: "bool"
2404
+ }
2405
+ ],
2406
+ internalType: "struct ZubariSubscription.SubscriptionPlan",
2407
+ name: "",
2408
+ type: "tuple"
2409
+ }
2410
+ ],
2411
+ stateMutability: "view",
2412
+ type: "function"
2413
+ },
2414
+ {
2415
+ inputs: [
2416
+ {
2417
+ internalType: "bytes32",
2418
+ name: "subscriptionId",
2419
+ type: "bytes32"
2420
+ }
2421
+ ],
2422
+ name: "getSubscription",
2423
+ outputs: [
2424
+ {
2425
+ components: [
2426
+ {
2427
+ internalType: "bytes32",
2428
+ name: "subscriptionId",
2429
+ type: "bytes32"
2430
+ },
2431
+ {
2432
+ internalType: "bytes32",
2433
+ name: "planId",
2434
+ type: "bytes32"
2435
+ },
2436
+ {
2437
+ internalType: "address",
2438
+ name: "creator",
2439
+ type: "address"
2440
+ },
2441
+ {
2442
+ internalType: "address",
2443
+ name: "subscriber",
2444
+ type: "address"
2445
+ },
2446
+ {
2447
+ internalType: "uint256",
2448
+ name: "startTime",
2449
+ type: "uint256"
2450
+ },
2451
+ {
2452
+ internalType: "uint256",
2453
+ name: "endTime",
2454
+ type: "uint256"
2455
+ },
2456
+ {
2457
+ internalType: "bool",
2458
+ name: "autoRenew",
2459
+ type: "bool"
2460
+ },
2461
+ {
2462
+ internalType: "enum ZubariSubscription.SubscriptionStatus",
2463
+ name: "status",
2464
+ type: "uint8"
2465
+ }
2466
+ ],
2467
+ internalType: "struct ZubariSubscription.Subscription",
2468
+ name: "",
2469
+ type: "tuple"
2470
+ }
2471
+ ],
2472
+ stateMutability: "view",
2473
+ type: "function"
2474
+ },
2475
+ {
2476
+ inputs: [
2477
+ {
2478
+ internalType: "address",
2479
+ name: "subscriber",
2480
+ type: "address"
2481
+ },
2482
+ {
2483
+ internalType: "address",
2484
+ name: "creator",
2485
+ type: "address"
2486
+ }
2487
+ ],
2488
+ name: "isSubscribed",
2489
+ outputs: [
2490
+ {
2491
+ internalType: "bool",
2492
+ name: "",
2493
+ type: "bool"
2494
+ }
2495
+ ],
2496
+ stateMutability: "view",
2497
+ type: "function"
2498
+ },
2499
+ {
2500
+ inputs: [],
2501
+ name: "owner",
2502
+ outputs: [
2503
+ {
2504
+ internalType: "address",
2505
+ name: "",
2506
+ type: "address"
2507
+ }
2508
+ ],
2509
+ stateMutability: "view",
2510
+ type: "function"
2511
+ },
2512
+ {
2513
+ inputs: [],
2514
+ name: "pause",
2515
+ outputs: [],
2516
+ stateMutability: "nonpayable",
2517
+ type: "function"
2518
+ },
2519
+ {
2520
+ inputs: [],
2521
+ name: "paused",
2522
+ outputs: [
2523
+ {
2524
+ internalType: "bool",
2525
+ name: "",
2526
+ type: "bool"
2527
+ }
2528
+ ],
2529
+ stateMutability: "view",
2530
+ type: "function"
2531
+ },
2532
+ {
2533
+ inputs: [
2534
+ {
2535
+ internalType: "bytes32",
2536
+ name: "",
2537
+ type: "bytes32"
2538
+ }
2539
+ ],
2540
+ name: "plans",
2541
+ outputs: [
2542
+ {
2543
+ internalType: "bytes32",
2544
+ name: "planId",
2545
+ type: "bytes32"
2546
+ },
2547
+ {
2548
+ internalType: "address",
2549
+ name: "creator",
2550
+ type: "address"
2551
+ },
2552
+ {
2553
+ internalType: "string",
2554
+ name: "name",
2555
+ type: "string"
2556
+ },
2557
+ {
2558
+ internalType: "string",
2559
+ name: "description",
2560
+ type: "string"
2561
+ },
2562
+ {
2563
+ internalType: "uint256",
2564
+ name: "price",
2565
+ type: "uint256"
2566
+ },
2567
+ {
2568
+ internalType: "address",
2569
+ name: "paymentToken",
2570
+ type: "address"
2571
+ },
2572
+ {
2573
+ internalType: "uint256",
2574
+ name: "durationDays",
2575
+ type: "uint256"
2576
+ },
2577
+ {
2578
+ internalType: "uint256",
2579
+ name: "maxSubscribers",
2580
+ type: "uint256"
2581
+ },
2582
+ {
2583
+ internalType: "uint256",
2584
+ name: "subscriberCount",
2585
+ type: "uint256"
2586
+ },
2587
+ {
2588
+ internalType: "bool",
2589
+ name: "isActive",
2590
+ type: "bool"
2591
+ }
2592
+ ],
2593
+ stateMutability: "view",
2594
+ type: "function"
2595
+ },
2596
+ {
2597
+ inputs: [],
2598
+ name: "platformFeeBps",
2599
+ outputs: [
2600
+ {
2601
+ internalType: "uint256",
2602
+ name: "",
2603
+ type: "uint256"
2604
+ }
2605
+ ],
2606
+ stateMutability: "view",
2607
+ type: "function"
2608
+ },
2609
+ {
2610
+ inputs: [],
2611
+ name: "renounceOwnership",
2612
+ outputs: [],
2613
+ stateMutability: "nonpayable",
2614
+ type: "function"
2615
+ },
2616
+ {
2617
+ inputs: [
2618
+ {
2619
+ internalType: "bytes32",
2620
+ name: "subscriptionId",
2621
+ type: "bytes32"
2622
+ },
2623
+ {
2624
+ internalType: "bool",
2625
+ name: "autoRenew",
2626
+ type: "bool"
2627
+ }
2628
+ ],
2629
+ name: "setAutoRenew",
2630
+ outputs: [],
2631
+ stateMutability: "nonpayable",
2632
+ type: "function"
2633
+ },
2634
+ {
2635
+ inputs: [
2636
+ {
2637
+ internalType: "uint256",
2638
+ name: "_feeBps",
2639
+ type: "uint256"
2640
+ }
2641
+ ],
2642
+ name: "setPlatformFee",
2643
+ outputs: [],
2644
+ stateMutability: "nonpayable",
2645
+ type: "function"
2646
+ },
2647
+ {
2648
+ inputs: [
2649
+ {
2650
+ internalType: "address",
2651
+ name: "_treasury",
2652
+ type: "address"
2653
+ }
2654
+ ],
2655
+ name: "setTreasury",
2656
+ outputs: [],
2657
+ stateMutability: "nonpayable",
2658
+ type: "function"
2659
+ },
2660
+ {
2661
+ inputs: [
2662
+ {
2663
+ internalType: "bytes32",
2664
+ name: "planId",
2665
+ type: "bytes32"
2666
+ },
2667
+ {
2668
+ internalType: "uint256",
2669
+ name: "months",
2670
+ type: "uint256"
2671
+ }
2672
+ ],
2673
+ name: "subscribe",
2674
+ outputs: [
2675
+ {
2676
+ internalType: "bytes32",
2677
+ name: "",
2678
+ type: "bytes32"
2679
+ }
2680
+ ],
2681
+ stateMutability: "payable",
2682
+ type: "function"
2683
+ },
2684
+ {
2685
+ inputs: [
2686
+ {
2687
+ internalType: "address",
2688
+ name: "",
2689
+ type: "address"
2690
+ },
2691
+ {
2692
+ internalType: "uint256",
2693
+ name: "",
2694
+ type: "uint256"
2695
+ }
2696
+ ],
2697
+ name: "subscriberSubscriptions",
2698
+ outputs: [
2699
+ {
2700
+ internalType: "bytes32",
2701
+ name: "",
2702
+ type: "bytes32"
2703
+ }
2704
+ ],
2705
+ stateMutability: "view",
2706
+ type: "function"
2707
+ },
2708
+ {
2709
+ inputs: [
2710
+ {
2711
+ internalType: "bytes32",
2712
+ name: "",
2713
+ type: "bytes32"
2714
+ }
2715
+ ],
2716
+ name: "subscriptions",
2717
+ outputs: [
2718
+ {
2719
+ internalType: "bytes32",
2720
+ name: "subscriptionId",
2721
+ type: "bytes32"
2722
+ },
2723
+ {
2724
+ internalType: "bytes32",
2725
+ name: "planId",
2726
+ type: "bytes32"
2727
+ },
2728
+ {
2729
+ internalType: "address",
2730
+ name: "creator",
2731
+ type: "address"
2732
+ },
2733
+ {
2734
+ internalType: "address",
2735
+ name: "subscriber",
2736
+ type: "address"
2737
+ },
2738
+ {
2739
+ internalType: "uint256",
2740
+ name: "startTime",
2741
+ type: "uint256"
2742
+ },
2743
+ {
2744
+ internalType: "uint256",
2745
+ name: "endTime",
2746
+ type: "uint256"
2747
+ },
2748
+ {
2749
+ internalType: "bool",
2750
+ name: "autoRenew",
2751
+ type: "bool"
2752
+ },
2753
+ {
2754
+ internalType: "enum ZubariSubscription.SubscriptionStatus",
2755
+ name: "status",
2756
+ type: "uint8"
2757
+ }
2758
+ ],
2759
+ stateMutability: "view",
2760
+ type: "function"
2761
+ },
2762
+ {
2763
+ inputs: [
2764
+ {
2765
+ internalType: "address",
2766
+ name: "newOwner",
2767
+ type: "address"
2768
+ }
2769
+ ],
2770
+ name: "transferOwnership",
2771
+ outputs: [],
2772
+ stateMutability: "nonpayable",
2773
+ type: "function"
2774
+ },
2775
+ {
2776
+ inputs: [],
2777
+ name: "treasury",
2778
+ outputs: [
2779
+ {
2780
+ internalType: "address",
2781
+ name: "",
2782
+ type: "address"
2783
+ }
2784
+ ],
2785
+ stateMutability: "view",
2786
+ type: "function"
2787
+ },
2788
+ {
2789
+ inputs: [],
2790
+ name: "unpause",
2791
+ outputs: [],
2792
+ stateMutability: "nonpayable",
2793
+ type: "function"
2794
+ }
2795
+ ];
2796
+
2797
+ // src/protocols/SubscriptionProtocol.ts
2798
+ var ZubariSubscriptionProtocol = class {
2799
+ contractAddress;
2800
+ chainId;
2801
+ abi = ZubariSubscription_default;
2802
+ constructor(contractAddress, chainId) {
2803
+ this.contractAddress = contractAddress;
2804
+ this.chainId = chainId;
2805
+ }
2806
+ /**
2807
+ * Get the contract ABI
2808
+ */
2809
+ getAbi() {
2810
+ return this.abi;
2811
+ }
2812
+ /**
2813
+ * Get the contract address
2814
+ */
2815
+ getAddress() {
2816
+ return this.contractAddress;
2817
+ }
2818
+ /**
2819
+ * Create a new subscription plan
2820
+ * @param plan The plan details
2821
+ * @param signer Wallet signer with sendTransaction method
2822
+ */
2823
+ async createPlan(plan, signer) {
2824
+ if (!plan.name || plan.name.length === 0) {
2825
+ throw new Error("Plan name is required");
2826
+ }
2827
+ if (plan.price <= 0n) {
2828
+ throw new Error("Plan price must be greater than 0");
2829
+ }
2830
+ if (plan.duration <= 0) {
2831
+ throw new Error("Plan duration must be greater than 0");
2832
+ }
2833
+ const iface = new (await import('ethers')).Interface(this.abi);
2834
+ const durationDays = Math.ceil(plan.duration / (24 * 60 * 60));
2835
+ const data = iface.encodeFunctionData("createPlan", [
2836
+ plan.name,
2837
+ plan.description || "",
2838
+ plan.price,
2839
+ plan.paymentToken || "0x0000000000000000000000000000000000000000",
2840
+ // ETH by default
2841
+ durationDays,
2842
+ plan.maxSubscribers || 0
2843
+ // 0 = unlimited
2844
+ ]);
2845
+ const result = await signer.sendTransaction({
2846
+ to: this.contractAddress,
2847
+ value: 0n,
2848
+ data
2849
+ });
2850
+ return result.hash;
2851
+ }
2852
+ /**
2853
+ * Deactivate a subscription plan (only creator can do this)
2854
+ * @param planId The plan ID to deactivate
2855
+ * @param signer Wallet signer
2856
+ */
2857
+ async deactivatePlan(planId, signer) {
2858
+ const iface = new (await import('ethers')).Interface(this.abi);
2859
+ const data = iface.encodeFunctionData("deactivatePlan", [planId]);
2860
+ const result = await signer.sendTransaction({
2861
+ to: this.contractAddress,
2862
+ value: 0n,
2863
+ data
2864
+ });
2865
+ return {
2866
+ hash: result.hash,
2867
+ network: "ethereum",
2868
+ status: "pending"
2869
+ };
2870
+ }
2871
+ /**
2872
+ * Subscribe to a creator's plan
2873
+ * @param planId The plan ID to subscribe to
2874
+ * @param months Number of months to subscribe
2875
+ * @param signer Wallet signer
2876
+ * @param value ETH value to send (if paying with ETH)
2877
+ */
2878
+ async subscribe(planId, months, signer, value) {
2879
+ if (months <= 0) {
2880
+ throw new Error("Subscription duration must be at least 1 month");
2881
+ }
2882
+ const iface = new (await import('ethers')).Interface(this.abi);
2883
+ const data = iface.encodeFunctionData("subscribe", [planId, months]);
2884
+ const result = await signer.sendTransaction({
2885
+ to: this.contractAddress,
2886
+ value: value || 0n,
2887
+ data
2888
+ });
2889
+ return {
2890
+ hash: result.hash,
2891
+ network: "ethereum",
2892
+ status: "pending"
2893
+ };
2894
+ }
2895
+ /**
2896
+ * Cancel an active subscription
2897
+ * @param subscriptionId The subscription ID to cancel
2898
+ * @param signer Wallet signer
2899
+ */
2900
+ async cancel(subscriptionId, signer) {
2901
+ const iface = new (await import('ethers')).Interface(this.abi);
2902
+ const data = iface.encodeFunctionData("cancel", [subscriptionId]);
2903
+ const result = await signer.sendTransaction({
2904
+ to: this.contractAddress,
2905
+ value: 0n,
2906
+ data
2907
+ });
2908
+ return {
2909
+ hash: result.hash,
2910
+ network: "ethereum",
2911
+ status: "pending"
2912
+ };
2913
+ }
2914
+ /**
2915
+ * Set auto-renew for a subscription
2916
+ * @param subscriptionId The subscription ID
2917
+ * @param autoRenew Whether to enable auto-renew
2918
+ * @param signer Wallet signer
2919
+ */
2920
+ async setAutoRenew(subscriptionId, autoRenew, signer) {
2921
+ const iface = new (await import('ethers')).Interface(this.abi);
2922
+ const data = iface.encodeFunctionData("setAutoRenew", [subscriptionId, autoRenew]);
2923
+ const result = await signer.sendTransaction({
2924
+ to: this.contractAddress,
2925
+ value: 0n,
2926
+ data
2927
+ });
2928
+ return {
2929
+ hash: result.hash,
2930
+ network: "ethereum",
2931
+ status: "pending"
2932
+ };
2933
+ }
2934
+ /**
2935
+ * Check if an address is subscribed to a creator
2936
+ * @param subscriber The subscriber address
2937
+ * @param creator The creator address
2938
+ * @param provider JSON-RPC provider
2939
+ */
2940
+ async isSubscribed(subscriber, creator, provider) {
2941
+ const iface = new (await import('ethers')).Interface(this.abi);
2942
+ const data = iface.encodeFunctionData("isSubscribed", [subscriber, creator]);
2943
+ try {
2944
+ const result = await provider.call({
2945
+ to: this.contractAddress,
2946
+ data
2947
+ });
2948
+ const decoded = iface.decodeFunctionResult("isSubscribed", result);
2949
+ return decoded[0];
2950
+ } catch {
2951
+ return false;
2952
+ }
2953
+ }
2954
+ /**
2955
+ * Get the active subscription ID between subscriber and creator
2956
+ * @param subscriber The subscriber address
2957
+ * @param creator The creator address
2958
+ * @param provider JSON-RPC provider
2959
+ */
2960
+ async getActiveSubscriptionId(subscriber, creator, provider) {
2961
+ const iface = new (await import('ethers')).Interface(this.abi);
2962
+ const data = iface.encodeFunctionData("activeSubscription", [subscriber, creator]);
2963
+ try {
2964
+ const result = await provider.call({
2965
+ to: this.contractAddress,
2966
+ data
2967
+ });
2968
+ const decoded = iface.decodeFunctionResult("activeSubscription", result);
2969
+ const subscriptionId = decoded[0];
2970
+ if (subscriptionId === "0x0000000000000000000000000000000000000000000000000000000000000000") {
2971
+ return null;
2972
+ }
2973
+ return subscriptionId;
2974
+ } catch {
2975
+ return null;
2976
+ }
2977
+ }
2978
+ /**
2979
+ * Get subscription details by ID
2980
+ * @param subscriptionId The subscription ID
2981
+ * @param provider JSON-RPC provider
2982
+ */
2983
+ async getSubscription(subscriptionId, provider) {
2984
+ const iface = new (await import('ethers')).Interface(this.abi);
2985
+ const data = iface.encodeFunctionData("getSubscription", [subscriptionId]);
2986
+ try {
2987
+ const result = await provider.call({
2988
+ to: this.contractAddress,
2989
+ data
2990
+ });
2991
+ const decoded = iface.decodeFunctionResult("getSubscription", result);
2992
+ const sub = decoded[0];
2993
+ if (sub.subscriptionId === "0x0000000000000000000000000000000000000000000000000000000000000000") {
2994
+ return null;
2995
+ }
2996
+ let status;
2997
+ switch (Number(sub.status)) {
2998
+ case 0 /* Active */:
2999
+ status = "active";
3000
+ break;
3001
+ case 1 /* Cancelled */:
3002
+ status = "cancelled";
3003
+ break;
3004
+ case 2 /* Expired */:
3005
+ status = "expired";
3006
+ break;
3007
+ default:
3008
+ status = "active";
3009
+ }
3010
+ return {
3011
+ subscriptionId: sub.subscriptionId,
3012
+ planId: sub.planId,
3013
+ creator: sub.creator,
3014
+ subscriber: sub.subscriber,
3015
+ startTime: Number(sub.startTime),
3016
+ endTime: Number(sub.endTime),
3017
+ autoRenew: sub.autoRenew,
3018
+ status
3019
+ };
3020
+ } catch {
3021
+ return null;
3022
+ }
3023
+ }
3024
+ /**
3025
+ * Get a specific plan by ID
3026
+ * @param planId The plan ID
3027
+ * @param provider JSON-RPC provider
3028
+ */
3029
+ async getPlan(planId, provider) {
3030
+ const iface = new (await import('ethers')).Interface(this.abi);
3031
+ const data = iface.encodeFunctionData("getPlan", [planId]);
3032
+ try {
3033
+ const result = await provider.call({
3034
+ to: this.contractAddress,
3035
+ data
3036
+ });
3037
+ const decoded = iface.decodeFunctionResult("getPlan", result);
3038
+ const plan = decoded[0];
3039
+ if (plan.planId === "0x0000000000000000000000000000000000000000000000000000000000000000") {
3040
+ return null;
3041
+ }
3042
+ const durationSeconds = Number(plan.durationDays) * 24 * 60 * 60;
3043
+ return {
3044
+ planId: plan.planId,
3045
+ name: plan.name,
3046
+ description: plan.description,
3047
+ price: plan.price,
3048
+ paymentToken: plan.paymentToken,
3049
+ duration: durationSeconds,
3050
+ perks: [],
3051
+ // Not stored on-chain
3052
+ maxSubscribers: Number(plan.maxSubscribers),
3053
+ nftBadge: false
3054
+ // Not stored on-chain in this contract version
3055
+ };
3056
+ } catch {
3057
+ return null;
3058
+ }
3059
+ }
3060
+ /**
3061
+ * Get all plan IDs for a creator
3062
+ * @param creator The creator address
3063
+ * @param provider JSON-RPC provider
3064
+ */
3065
+ async getCreatorPlanIds(creator, provider) {
3066
+ const iface = new (await import('ethers')).Interface(this.abi);
3067
+ const data = iface.encodeFunctionData("getCreatorPlans", [creator]);
3068
+ try {
3069
+ const result = await provider.call({
3070
+ to: this.contractAddress,
3071
+ data
3072
+ });
3073
+ const decoded = iface.decodeFunctionResult("getCreatorPlans", result);
3074
+ return decoded[0];
3075
+ } catch {
3076
+ return [];
3077
+ }
3078
+ }
3079
+ /**
3080
+ * Get all plans for a creator with full details
3081
+ * @param creator The creator address
3082
+ * @param provider JSON-RPC provider
3083
+ */
3084
+ async getCreatorPlans(creator, provider) {
3085
+ const planIds = await this.getCreatorPlanIds(creator, provider);
3086
+ const plans = [];
3087
+ for (const planId of planIds) {
3088
+ const plan = await this.getPlan(planId, provider);
3089
+ if (plan && plan.planId) {
3090
+ plans.push(plan);
3091
+ }
3092
+ }
3093
+ return plans;
3094
+ }
3095
+ /**
3096
+ * Get platform fee in basis points
3097
+ * @param provider JSON-RPC provider
3098
+ */
3099
+ async getPlatformFeeBps(provider) {
3100
+ const iface = new (await import('ethers')).Interface(this.abi);
3101
+ const data = iface.encodeFunctionData("platformFeeBps", []);
3102
+ try {
3103
+ const result = await provider.call({
3104
+ to: this.contractAddress,
3105
+ data
3106
+ });
3107
+ const decoded = iface.decodeFunctionResult("platformFeeBps", result);
3108
+ return Number(decoded[0]);
3109
+ } catch {
3110
+ return 300;
3111
+ }
3112
+ }
3113
+ /**
3114
+ * Calculate the total cost for a subscription
3115
+ * @param planPrice The plan price per period
3116
+ * @param months Number of months
3117
+ */
3118
+ calculateSubscriptionCost(planPrice, months) {
3119
+ return planPrice * BigInt(months);
3120
+ }
3121
+ /**
3122
+ * Calculate platform fee for a given amount
3123
+ * @param amount The amount
3124
+ * @param feeBps Fee in basis points
3125
+ */
3126
+ calculateFee(amount, feeBps = 300) {
3127
+ const fee = amount * BigInt(feeBps) / 10000n;
3128
+ return {
3129
+ fee,
3130
+ creatorAmount: amount - fee
3131
+ };
1192
3132
  }
1193
3133
  };
1194
3134