@net-protocol/bazaar 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,1371 @@
1
+ 'use strict';
2
+
3
+ var viem = require('viem');
4
+ var core = require('@net-protocol/core');
5
+ var seaportJs = require('@opensea/seaport-js');
6
+ var ethers = require('ethers');
7
+ var actions = require('viem/actions');
8
+
9
+ // src/client/BazaarClient.ts
10
+
11
+ // src/types.ts
12
+ var SeaportOrderStatus = /* @__PURE__ */ ((SeaportOrderStatus2) => {
13
+ SeaportOrderStatus2[SeaportOrderStatus2["CANCELLED"] = 0] = "CANCELLED";
14
+ SeaportOrderStatus2[SeaportOrderStatus2["EXPIRED"] = 1] = "EXPIRED";
15
+ SeaportOrderStatus2[SeaportOrderStatus2["OPEN"] = 2] = "OPEN";
16
+ SeaportOrderStatus2[SeaportOrderStatus2["FILLED"] = 3] = "FILLED";
17
+ return SeaportOrderStatus2;
18
+ })(SeaportOrderStatus || {});
19
+ var ItemType = /* @__PURE__ */ ((ItemType2) => {
20
+ ItemType2[ItemType2["NATIVE"] = 0] = "NATIVE";
21
+ ItemType2[ItemType2["ERC20"] = 1] = "ERC20";
22
+ ItemType2[ItemType2["ERC721"] = 2] = "ERC721";
23
+ ItemType2[ItemType2["ERC1155"] = 3] = "ERC1155";
24
+ ItemType2[ItemType2["ERC721_WITH_CRITERIA"] = 4] = "ERC721_WITH_CRITERIA";
25
+ ItemType2[ItemType2["ERC1155_WITH_CRITERIA"] = 5] = "ERC1155_WITH_CRITERIA";
26
+ return ItemType2;
27
+ })(ItemType || {});
28
+ var OrderType = /* @__PURE__ */ ((OrderType2) => {
29
+ OrderType2[OrderType2["FULL_OPEN"] = 0] = "FULL_OPEN";
30
+ OrderType2[OrderType2["PARTIAL_OPEN"] = 1] = "PARTIAL_OPEN";
31
+ OrderType2[OrderType2["FULL_RESTRICTED"] = 2] = "FULL_RESTRICTED";
32
+ OrderType2[OrderType2["PARTIAL_RESTRICTED"] = 3] = "PARTIAL_RESTRICTED";
33
+ return OrderType2;
34
+ })(OrderType || {});
35
+
36
+ // src/abis/bazaarV2.ts
37
+ var BAZAAR_V2_ABI = [
38
+ {
39
+ type: "function",
40
+ name: "submit",
41
+ inputs: [
42
+ {
43
+ name: "submission",
44
+ type: "tuple",
45
+ internalType: "struct BazaarV1.Submission",
46
+ components: [
47
+ {
48
+ name: "parameters",
49
+ type: "tuple",
50
+ internalType: "struct OrderParameters",
51
+ components: [
52
+ { name: "offerer", type: "address", internalType: "address" },
53
+ { name: "zone", type: "address", internalType: "address" },
54
+ {
55
+ name: "offer",
56
+ type: "tuple[]",
57
+ internalType: "struct OfferItem[]",
58
+ components: [
59
+ { name: "itemType", type: "uint8", internalType: "enum ItemType" },
60
+ { name: "token", type: "address", internalType: "address" },
61
+ { name: "identifierOrCriteria", type: "uint256", internalType: "uint256" },
62
+ { name: "startAmount", type: "uint256", internalType: "uint256" },
63
+ { name: "endAmount", type: "uint256", internalType: "uint256" }
64
+ ]
65
+ },
66
+ {
67
+ name: "consideration",
68
+ type: "tuple[]",
69
+ internalType: "struct ConsiderationItem[]",
70
+ components: [
71
+ { name: "itemType", type: "uint8", internalType: "enum ItemType" },
72
+ { name: "token", type: "address", internalType: "address" },
73
+ { name: "identifierOrCriteria", type: "uint256", internalType: "uint256" },
74
+ { name: "startAmount", type: "uint256", internalType: "uint256" },
75
+ { name: "endAmount", type: "uint256", internalType: "uint256" },
76
+ { name: "recipient", type: "address", internalType: "address payable" }
77
+ ]
78
+ },
79
+ { name: "orderType", type: "uint8", internalType: "enum OrderType" },
80
+ { name: "startTime", type: "uint256", internalType: "uint256" },
81
+ { name: "endTime", type: "uint256", internalType: "uint256" },
82
+ { name: "zoneHash", type: "bytes32", internalType: "bytes32" },
83
+ { name: "salt", type: "uint256", internalType: "uint256" },
84
+ { name: "conduitKey", type: "bytes32", internalType: "bytes32" },
85
+ { name: "totalOriginalConsiderationItems", type: "uint256", internalType: "uint256" }
86
+ ]
87
+ },
88
+ { name: "counter", type: "uint256", internalType: "uint256" },
89
+ { name: "signature", type: "bytes", internalType: "bytes" }
90
+ ]
91
+ }
92
+ ],
93
+ outputs: [],
94
+ stateMutability: "nonpayable"
95
+ },
96
+ {
97
+ type: "event",
98
+ name: "Submitted",
99
+ inputs: [
100
+ { name: "tokenAddress", type: "address", indexed: true, internalType: "address" },
101
+ { name: "tokenId", type: "uint256", indexed: true, internalType: "uint256" }
102
+ ],
103
+ anonymous: false
104
+ },
105
+ { type: "error", name: "ConsiderationItemsMustContainTwoItems", inputs: [] },
106
+ { type: "error", name: "OfferItemsMustContainOneItem", inputs: [] }
107
+ ];
108
+ var BAZAAR_COLLECTION_OFFERS_ABI = [
109
+ {
110
+ type: "function",
111
+ name: "NET_APP_NAME",
112
+ inputs: [],
113
+ outputs: [{ name: "", type: "string", internalType: "string" }],
114
+ stateMutability: "view"
115
+ },
116
+ {
117
+ type: "function",
118
+ name: "submit",
119
+ inputs: [
120
+ {
121
+ name: "submission",
122
+ type: "tuple",
123
+ internalType: "struct BazaarV2CollectionOffers.Submission",
124
+ components: [
125
+ {
126
+ name: "parameters",
127
+ type: "tuple",
128
+ internalType: "struct OrderParameters",
129
+ components: [
130
+ { name: "offerer", type: "address", internalType: "address" },
131
+ { name: "zone", type: "address", internalType: "address" },
132
+ {
133
+ name: "offer",
134
+ type: "tuple[]",
135
+ internalType: "struct OfferItem[]",
136
+ components: [
137
+ { name: "itemType", type: "uint8", internalType: "enum ItemType" },
138
+ { name: "token", type: "address", internalType: "address" },
139
+ { name: "identifierOrCriteria", type: "uint256", internalType: "uint256" },
140
+ { name: "startAmount", type: "uint256", internalType: "uint256" },
141
+ { name: "endAmount", type: "uint256", internalType: "uint256" }
142
+ ]
143
+ },
144
+ {
145
+ name: "consideration",
146
+ type: "tuple[]",
147
+ internalType: "struct ConsiderationItem[]",
148
+ components: [
149
+ { name: "itemType", type: "uint8", internalType: "enum ItemType" },
150
+ { name: "token", type: "address", internalType: "address" },
151
+ { name: "identifierOrCriteria", type: "uint256", internalType: "uint256" },
152
+ { name: "startAmount", type: "uint256", internalType: "uint256" },
153
+ { name: "endAmount", type: "uint256", internalType: "uint256" },
154
+ { name: "recipient", type: "address", internalType: "address payable" }
155
+ ]
156
+ },
157
+ { name: "orderType", type: "uint8", internalType: "enum OrderType" },
158
+ { name: "startTime", type: "uint256", internalType: "uint256" },
159
+ { name: "endTime", type: "uint256", internalType: "uint256" },
160
+ { name: "zoneHash", type: "bytes32", internalType: "bytes32" },
161
+ { name: "salt", type: "uint256", internalType: "uint256" },
162
+ { name: "conduitKey", type: "bytes32", internalType: "bytes32" },
163
+ { name: "totalOriginalConsiderationItems", type: "uint256", internalType: "uint256" }
164
+ ]
165
+ },
166
+ { name: "counter", type: "uint256", internalType: "uint256" },
167
+ { name: "signature", type: "bytes", internalType: "bytes" }
168
+ ]
169
+ }
170
+ ],
171
+ outputs: [],
172
+ stateMutability: "nonpayable"
173
+ },
174
+ {
175
+ type: "event",
176
+ name: "Submitted",
177
+ inputs: [
178
+ { name: "tokenAddress", type: "address", indexed: true, internalType: "address" },
179
+ { name: "tokenId", type: "uint256", indexed: true, internalType: "uint256" }
180
+ ],
181
+ anonymous: false
182
+ },
183
+ { type: "error", name: "ConsiderationItemsMustContainTwoItems", inputs: [] },
184
+ { type: "error", name: "ConsiderationItemsMustIncludeFeeAddress", inputs: [] },
185
+ { type: "error", name: "ConsiderationItemsMustIncludeMsgSender", inputs: [] },
186
+ { type: "error", name: "InvalidFee", inputs: [] },
187
+ { type: "error", name: "OfferItemsMustContainOneItem", inputs: [] }
188
+ ];
189
+
190
+ // src/abis/helpers.ts
191
+ var BULK_SEAPORT_ORDER_STATUS_FETCHER_ABI = [
192
+ { type: "constructor", inputs: [], stateMutability: "nonpayable" },
193
+ {
194
+ type: "function",
195
+ name: "getOrderStatuses",
196
+ inputs: [
197
+ { name: "seaport", type: "address", internalType: "address" },
198
+ { name: "orderHashes", type: "bytes32[]", internalType: "bytes32[]" }
199
+ ],
200
+ outputs: [
201
+ {
202
+ name: "results",
203
+ type: "tuple[]",
204
+ internalType: "struct BulkSeaportOrderStatusFetcher.OrderStatusInfo[]",
205
+ components: [
206
+ { name: "isValidated", type: "bool", internalType: "bool" },
207
+ { name: "isCancelled", type: "bool", internalType: "bool" },
208
+ { name: "totalFilled", type: "uint256", internalType: "uint256" },
209
+ { name: "totalSize", type: "uint256", internalType: "uint256" }
210
+ ]
211
+ }
212
+ ],
213
+ stateMutability: "view"
214
+ }
215
+ ];
216
+ var ERC721_OWNER_OF_HELPER_ABI = [
217
+ {
218
+ type: "function",
219
+ name: "getTokenOwners",
220
+ inputs: [
221
+ { name: "nftContract", type: "address", internalType: "address" },
222
+ { name: "tokenIds", type: "uint256[]", internalType: "uint256[]" }
223
+ ],
224
+ outputs: [
225
+ { name: "owners", type: "address[]", internalType: "address[]" }
226
+ ],
227
+ stateMutability: "view"
228
+ },
229
+ { type: "error", name: "InvalidAddress", inputs: [] },
230
+ { type: "error", name: "TokenQueryFailed", inputs: [] }
231
+ ];
232
+ var ERC20_BULK_BALANCE_CHECKER_ABI = [
233
+ {
234
+ type: "function",
235
+ name: "getBalances",
236
+ inputs: [
237
+ { name: "token", type: "address", internalType: "address" },
238
+ { name: "addresses", type: "address[]", internalType: "address[]" }
239
+ ],
240
+ outputs: [
241
+ { name: "balances", type: "uint256[]", internalType: "uint256[]" }
242
+ ],
243
+ stateMutability: "view"
244
+ }
245
+ ];
246
+
247
+ // src/abis/seaport.ts
248
+ var SEAPORT_CANCEL_ABI = [
249
+ {
250
+ inputs: [
251
+ {
252
+ components: [
253
+ { internalType: "address", name: "offerer", type: "address" },
254
+ { internalType: "address", name: "zone", type: "address" },
255
+ {
256
+ components: [
257
+ { internalType: "enum ItemType", name: "itemType", type: "uint8" },
258
+ { internalType: "address", name: "token", type: "address" },
259
+ { internalType: "uint256", name: "identifierOrCriteria", type: "uint256" },
260
+ { internalType: "uint256", name: "startAmount", type: "uint256" },
261
+ { internalType: "uint256", name: "endAmount", type: "uint256" }
262
+ ],
263
+ internalType: "struct OfferItem[]",
264
+ name: "offer",
265
+ type: "tuple[]"
266
+ },
267
+ {
268
+ components: [
269
+ { internalType: "enum ItemType", name: "itemType", type: "uint8" },
270
+ { internalType: "address", name: "token", type: "address" },
271
+ { internalType: "uint256", name: "identifierOrCriteria", type: "uint256" },
272
+ { internalType: "uint256", name: "startAmount", type: "uint256" },
273
+ { internalType: "uint256", name: "endAmount", type: "uint256" },
274
+ { internalType: "address payable", name: "recipient", type: "address" }
275
+ ],
276
+ internalType: "struct ConsiderationItem[]",
277
+ name: "consideration",
278
+ type: "tuple[]"
279
+ },
280
+ { internalType: "enum OrderType", name: "orderType", type: "uint8" },
281
+ { internalType: "uint256", name: "startTime", type: "uint256" },
282
+ { internalType: "uint256", name: "endTime", type: "uint256" },
283
+ { internalType: "bytes32", name: "zoneHash", type: "bytes32" },
284
+ { internalType: "uint256", name: "salt", type: "uint256" },
285
+ { internalType: "bytes32", name: "conduitKey", type: "bytes32" },
286
+ { internalType: "uint256", name: "counter", type: "uint256" }
287
+ ],
288
+ internalType: "struct OrderComponents[]",
289
+ name: "orders",
290
+ type: "tuple[]"
291
+ }
292
+ ],
293
+ name: "cancel",
294
+ outputs: [{ internalType: "bool", name: "cancelled", type: "bool" }],
295
+ stateMutability: "nonpayable",
296
+ type: "function"
297
+ }
298
+ ];
299
+
300
+ // src/abis/index.ts
301
+ var BAZAAR_SUBMISSION_ABI = [
302
+ {
303
+ name: "submission",
304
+ type: "tuple",
305
+ internalType: "struct BazaarV2.Submission",
306
+ components: [
307
+ {
308
+ name: "parameters",
309
+ type: "tuple",
310
+ internalType: "struct OrderParameters",
311
+ components: [
312
+ { name: "offerer", type: "address", internalType: "address" },
313
+ { name: "zone", type: "address", internalType: "address" },
314
+ {
315
+ name: "offer",
316
+ type: "tuple[]",
317
+ internalType: "struct OfferItem[]",
318
+ components: [
319
+ { name: "itemType", type: "uint8", internalType: "enum ItemType" },
320
+ { name: "token", type: "address", internalType: "address" },
321
+ { name: "identifierOrCriteria", type: "uint256", internalType: "uint256" },
322
+ { name: "startAmount", type: "uint256", internalType: "uint256" },
323
+ { name: "endAmount", type: "uint256", internalType: "uint256" }
324
+ ]
325
+ },
326
+ {
327
+ name: "consideration",
328
+ type: "tuple[]",
329
+ internalType: "struct ConsiderationItem[]",
330
+ components: [
331
+ { name: "itemType", type: "uint8", internalType: "enum ItemType" },
332
+ { name: "token", type: "address", internalType: "address" },
333
+ { name: "identifierOrCriteria", type: "uint256", internalType: "uint256" },
334
+ { name: "startAmount", type: "uint256", internalType: "uint256" },
335
+ { name: "endAmount", type: "uint256", internalType: "uint256" },
336
+ { name: "recipient", type: "address", internalType: "address payable" }
337
+ ]
338
+ },
339
+ { name: "orderType", type: "uint8", internalType: "enum OrderType" },
340
+ { name: "startTime", type: "uint256", internalType: "uint256" },
341
+ { name: "endTime", type: "uint256", internalType: "uint256" },
342
+ { name: "zoneHash", type: "bytes32", internalType: "bytes32" },
343
+ { name: "salt", type: "uint256", internalType: "uint256" },
344
+ { name: "conduitKey", type: "bytes32", internalType: "bytes32" },
345
+ { name: "totalOriginalConsiderationItems", type: "uint256", internalType: "uint256" }
346
+ ]
347
+ },
348
+ { name: "counter", type: "uint256", internalType: "uint256" },
349
+ { name: "signature", type: "bytes", internalType: "bytes" }
350
+ ]
351
+ }
352
+ ];
353
+
354
+ // src/chainConfig.ts
355
+ var DEFAULT_SEAPORT_ADDRESS = "0x0000000000000068F116a894984e2DB1123eB395";
356
+ var DEFAULT_BAZAAR_ADDRESS = "0x00000000E3dA5fC031282A39759bDDA78ae7fAE5";
357
+ var DEFAULT_COLLECTION_OFFERS_ADDRESS = "0x0000000D43423E0A12CecB307a74591999b32B32";
358
+ var DEFAULT_FEE_COLLECTOR_ADDRESS = "0x32D16C15410248bef498D7aF50D10Db1a546b9E5";
359
+ var DEFAULT_NFT_FEE_BPS = 500;
360
+ var BULK_SEAPORT_ORDER_STATUS_FETCHER_ADDRESS = "0x0000009112ABCE652674b4fE3eD9C765B22d11A7";
361
+ var ERC721_OWNER_OF_HELPER_ADDRESS = "0x000000aa4eFa2e5A4a6002C7F08B6e8Ec8cf1dDa";
362
+ var ERC20_BULK_BALANCE_CHECKER_ADDRESS = "0x000000b50a9f2923f2db931391824f6d1278f712";
363
+ var NET_SEAPORT_ZONE_ADDRESS = "0x000000007F8c58fbf215bF91Bda7421A806cf3ae";
364
+ var NET_SEAPORT_COLLECTION_OFFER_ZONE_ADDRESS = "0x000000B799ec6D7aCC1B578f62bFc324c25DFC5A";
365
+ var BAZAAR_CHAIN_CONFIGS = {
366
+ // Base Mainnet
367
+ 8453: {
368
+ bazaarAddress: "0x000000058f3ade587388daf827174d0e6fc97595",
369
+ collectionOffersAddress: "0x0000000f9c45efcff0f78d8b54aa6a40092d66dc",
370
+ erc20OffersAddress: "0x0000000e23a89aa06f317306aa1ae231d3503082",
371
+ seaportAddress: DEFAULT_SEAPORT_ADDRESS,
372
+ feeCollectorAddress: "0x66547ff4f7206e291F7BC157b54C026Fc6660961",
373
+ nftFeeBps: 0,
374
+ // 0% on Base
375
+ wrappedNativeCurrency: {
376
+ address: "0x4200000000000000000000000000000000000006",
377
+ name: "Wrapped Ether",
378
+ symbol: "WETH"
379
+ },
380
+ currencySymbol: "eth"
381
+ },
382
+ // Base Sepolia (Testnet)
383
+ 84532: {
384
+ bazaarAddress: DEFAULT_BAZAAR_ADDRESS,
385
+ collectionOffersAddress: DEFAULT_COLLECTION_OFFERS_ADDRESS,
386
+ seaportAddress: DEFAULT_SEAPORT_ADDRESS,
387
+ feeCollectorAddress: DEFAULT_FEE_COLLECTOR_ADDRESS,
388
+ nftFeeBps: DEFAULT_NFT_FEE_BPS,
389
+ wrappedNativeCurrency: {
390
+ address: "0x4200000000000000000000000000000000000006",
391
+ name: "Wrapped Ether",
392
+ symbol: "WETH"
393
+ },
394
+ currencySymbol: "eth"
395
+ },
396
+ // Degen
397
+ 666666666: {
398
+ bazaarAddress: DEFAULT_BAZAAR_ADDRESS,
399
+ collectionOffersAddress: DEFAULT_COLLECTION_OFFERS_ADDRESS,
400
+ seaportAddress: DEFAULT_SEAPORT_ADDRESS,
401
+ feeCollectorAddress: DEFAULT_FEE_COLLECTOR_ADDRESS,
402
+ nftFeeBps: DEFAULT_NFT_FEE_BPS,
403
+ wrappedNativeCurrency: {
404
+ address: "0xEb54dACB4C2ccb64F8074eceEa33b5eBb38E5387",
405
+ name: "Wrapped Degen",
406
+ symbol: "WDEGEN"
407
+ },
408
+ currencySymbol: "degen"
409
+ },
410
+ // Ham Chain
411
+ 5112: {
412
+ bazaarAddress: DEFAULT_BAZAAR_ADDRESS,
413
+ collectionOffersAddress: DEFAULT_COLLECTION_OFFERS_ADDRESS,
414
+ seaportAddress: DEFAULT_SEAPORT_ADDRESS,
415
+ feeCollectorAddress: DEFAULT_FEE_COLLECTOR_ADDRESS,
416
+ nftFeeBps: DEFAULT_NFT_FEE_BPS,
417
+ wrappedNativeCurrency: {
418
+ address: "0x4200000000000000000000000000000000000006",
419
+ name: "Wrapped Ether",
420
+ symbol: "WETH"
421
+ },
422
+ highEthAddress: "0x4200000000000000000000000000000000000006",
423
+ currencySymbol: "eth"
424
+ },
425
+ // Ink Chain
426
+ 57073: {
427
+ bazaarAddress: DEFAULT_BAZAAR_ADDRESS,
428
+ collectionOffersAddress: DEFAULT_COLLECTION_OFFERS_ADDRESS,
429
+ // Custom Seaport address for Ink (no create2 factory)
430
+ seaportAddress: "0xD00C96804e9fF35f10C7D2a92239C351Ff3F94e5",
431
+ feeCollectorAddress: DEFAULT_FEE_COLLECTOR_ADDRESS,
432
+ nftFeeBps: DEFAULT_NFT_FEE_BPS,
433
+ wrappedNativeCurrency: {
434
+ address: "0x4200000000000000000000000000000000000006",
435
+ name: "Wrapped ETH",
436
+ symbol: "WETH"
437
+ },
438
+ highEthAddress: "0x4200000000000000000000000000000000000006",
439
+ currencySymbol: "eth"
440
+ },
441
+ // Unichain
442
+ 130: {
443
+ bazaarAddress: DEFAULT_BAZAAR_ADDRESS,
444
+ collectionOffersAddress: DEFAULT_COLLECTION_OFFERS_ADDRESS,
445
+ seaportAddress: DEFAULT_SEAPORT_ADDRESS,
446
+ feeCollectorAddress: DEFAULT_FEE_COLLECTOR_ADDRESS,
447
+ nftFeeBps: DEFAULT_NFT_FEE_BPS,
448
+ wrappedNativeCurrency: {
449
+ address: "0x4200000000000000000000000000000000000006",
450
+ name: "Wrapped Ether",
451
+ symbol: "WETH"
452
+ },
453
+ currencySymbol: "eth"
454
+ },
455
+ // HyperEVM (Hyperliquid)
456
+ 999: {
457
+ bazaarAddress: "0x000000058f3ade587388daf827174d0e6fc97595",
458
+ collectionOffersAddress: "0x0000000f9c45efcff0f78d8b54aa6a40092d66dc",
459
+ erc20OffersAddress: "0x0000000e23a89aa06f317306aa1ae231d3503082",
460
+ seaportAddress: DEFAULT_SEAPORT_ADDRESS,
461
+ feeCollectorAddress: "0x66547ff4f7206e291F7BC157b54C026Fc6660961",
462
+ nftFeeBps: 0,
463
+ // 0% on HyperEVM
464
+ wrappedNativeCurrency: {
465
+ address: "0x5555555555555555555555555555555555555555",
466
+ name: "Wrapped Hype",
467
+ symbol: "WHYPE"
468
+ },
469
+ currencySymbol: "hype"
470
+ },
471
+ // Plasma
472
+ 9745: {
473
+ bazaarAddress: DEFAULT_BAZAAR_ADDRESS,
474
+ collectionOffersAddress: DEFAULT_COLLECTION_OFFERS_ADDRESS,
475
+ seaportAddress: DEFAULT_SEAPORT_ADDRESS,
476
+ feeCollectorAddress: DEFAULT_FEE_COLLECTOR_ADDRESS,
477
+ nftFeeBps: DEFAULT_NFT_FEE_BPS,
478
+ wrappedNativeCurrency: {
479
+ address: "0x6100e367285b01f48d07953803a2d8dca5d19873",
480
+ name: "Wrapped XPL",
481
+ symbol: "WXPL"
482
+ },
483
+ currencySymbol: "xpl"
484
+ },
485
+ // Monad
486
+ 143: {
487
+ bazaarAddress: DEFAULT_BAZAAR_ADDRESS,
488
+ collectionOffersAddress: DEFAULT_COLLECTION_OFFERS_ADDRESS,
489
+ seaportAddress: DEFAULT_SEAPORT_ADDRESS,
490
+ feeCollectorAddress: DEFAULT_FEE_COLLECTOR_ADDRESS,
491
+ nftFeeBps: DEFAULT_NFT_FEE_BPS,
492
+ wrappedNativeCurrency: {
493
+ address: "0x3bd359C1119dA7Da1D913D1C4D2B7c461115433A",
494
+ name: "Wrapped Monad",
495
+ symbol: "WMONAD"
496
+ },
497
+ currencySymbol: "monad"
498
+ }
499
+ };
500
+ function getBazaarChainConfig(chainId) {
501
+ return BAZAAR_CHAIN_CONFIGS[chainId];
502
+ }
503
+ function getBazaarSupportedChainIds() {
504
+ return Object.keys(BAZAAR_CHAIN_CONFIGS).map(Number);
505
+ }
506
+ function isBazaarSupportedOnChain(chainId) {
507
+ return chainId in BAZAAR_CHAIN_CONFIGS;
508
+ }
509
+ function getBazaarAddress(chainId) {
510
+ return BAZAAR_CHAIN_CONFIGS[chainId]?.bazaarAddress ?? DEFAULT_BAZAAR_ADDRESS;
511
+ }
512
+ function getCollectionOffersAddress(chainId) {
513
+ return BAZAAR_CHAIN_CONFIGS[chainId]?.collectionOffersAddress ?? DEFAULT_COLLECTION_OFFERS_ADDRESS;
514
+ }
515
+ function getSeaportAddress(chainId) {
516
+ return BAZAAR_CHAIN_CONFIGS[chainId]?.seaportAddress ?? DEFAULT_SEAPORT_ADDRESS;
517
+ }
518
+ function getFeeCollectorAddress(chainId) {
519
+ return BAZAAR_CHAIN_CONFIGS[chainId]?.feeCollectorAddress ?? DEFAULT_FEE_COLLECTOR_ADDRESS;
520
+ }
521
+ function getNftFeeBps(chainId) {
522
+ return BAZAAR_CHAIN_CONFIGS[chainId]?.nftFeeBps ?? DEFAULT_NFT_FEE_BPS;
523
+ }
524
+ function getWrappedNativeCurrency(chainId) {
525
+ return BAZAAR_CHAIN_CONFIGS[chainId]?.wrappedNativeCurrency;
526
+ }
527
+ function getCurrencySymbol(chainId) {
528
+ return BAZAAR_CHAIN_CONFIGS[chainId]?.currencySymbol ?? "eth";
529
+ }
530
+ function getHighEthAddress(chainId) {
531
+ return BAZAAR_CHAIN_CONFIGS[chainId]?.highEthAddress;
532
+ }
533
+ function getErc20OffersAddress(chainId) {
534
+ return BAZAAR_CHAIN_CONFIGS[chainId]?.erc20OffersAddress;
535
+ }
536
+ function decodeSeaportSubmission(messageData) {
537
+ const [decoded] = viem.decodeAbiParameters(BAZAAR_SUBMISSION_ABI, messageData);
538
+ return {
539
+ parameters: {
540
+ offerer: decoded.parameters.offerer,
541
+ zone: decoded.parameters.zone,
542
+ offer: decoded.parameters.offer.map((item) => ({
543
+ itemType: item.itemType,
544
+ token: item.token,
545
+ identifierOrCriteria: BigInt(item.identifierOrCriteria),
546
+ startAmount: BigInt(item.startAmount),
547
+ endAmount: BigInt(item.endAmount)
548
+ })),
549
+ consideration: decoded.parameters.consideration.map((item) => ({
550
+ itemType: item.itemType,
551
+ token: item.token,
552
+ identifierOrCriteria: BigInt(item.identifierOrCriteria),
553
+ startAmount: BigInt(item.startAmount),
554
+ endAmount: BigInt(item.endAmount),
555
+ recipient: item.recipient
556
+ })),
557
+ orderType: decoded.parameters.orderType,
558
+ startTime: BigInt(decoded.parameters.startTime),
559
+ endTime: BigInt(decoded.parameters.endTime),
560
+ zoneHash: decoded.parameters.zoneHash,
561
+ salt: BigInt(decoded.parameters.salt),
562
+ conduitKey: decoded.parameters.conduitKey,
563
+ totalOriginalConsiderationItems: BigInt(decoded.parameters.totalOriginalConsiderationItems)
564
+ },
565
+ counter: BigInt(decoded.counter),
566
+ signature: decoded.signature
567
+ };
568
+ }
569
+ function getSeaportOrderFromMessageData(messageData) {
570
+ const submission = decodeSeaportSubmission(messageData);
571
+ return {
572
+ parameters: {
573
+ ...submission.parameters,
574
+ // Convert BigInts to strings for Seaport SDK compatibility
575
+ offer: submission.parameters.offer.map((item) => ({
576
+ ...item,
577
+ identifierOrCriteria: item.identifierOrCriteria.toString(),
578
+ startAmount: item.startAmount.toString(),
579
+ endAmount: item.endAmount.toString()
580
+ })),
581
+ consideration: submission.parameters.consideration.map((item) => ({
582
+ ...item,
583
+ identifierOrCriteria: item.identifierOrCriteria.toString(),
584
+ startAmount: item.startAmount.toString(),
585
+ endAmount: item.endAmount.toString()
586
+ })),
587
+ startTime: submission.parameters.startTime.toString(),
588
+ endTime: submission.parameters.endTime.toString(),
589
+ salt: submission.parameters.salt.toString(),
590
+ totalOriginalConsiderationItems: submission.parameters.totalOriginalConsiderationItems.toString(),
591
+ counter: submission.counter.toString()
592
+ },
593
+ signature: submission.signature,
594
+ counter: submission.counter
595
+ };
596
+ }
597
+ function createSeaportInstance(chainId, rpcUrl) {
598
+ const provider = new ethers.ethers.JsonRpcProvider(rpcUrl);
599
+ const signer = new ethers.ethers.Wallet(
600
+ // Random private key for read-only operations
601
+ "dc63e9af2088e2afd61499411cb6dd718d00a3d9e46e2cb5e33912c781bd77fe",
602
+ provider
603
+ );
604
+ const highEthAddress = getHighEthAddress(chainId);
605
+ const finalSigner = highEthAddress ? {
606
+ ...signer,
607
+ getAddress: () => highEthAddress,
608
+ address: highEthAddress
609
+ } : signer;
610
+ return new seaportJs.Seaport(finalSigner, {
611
+ overrides: { contractAddress: getSeaportAddress(chainId) }
612
+ });
613
+ }
614
+ function computeOrderHash(seaport, orderParameters, counter) {
615
+ return seaport.getOrderHash({
616
+ ...orderParameters,
617
+ counter: counter.toString()
618
+ });
619
+ }
620
+ function getOrderStatusFromInfo(orderParameters, statusInfo) {
621
+ if (statusInfo.isCancelled) {
622
+ return 0 /* CANCELLED */;
623
+ }
624
+ if (statusInfo.totalFilled === statusInfo.totalSize && statusInfo.totalFilled > BigInt(0)) {
625
+ return 3 /* FILLED */;
626
+ }
627
+ const now = BigInt(Math.floor(Date.now() / 1e3));
628
+ if (orderParameters.endTime < now) {
629
+ return 1 /* EXPIRED */;
630
+ }
631
+ return 2 /* OPEN */;
632
+ }
633
+ function getTotalConsiderationAmount(parameters) {
634
+ return parameters.consideration.reduce(
635
+ (acc, item) => acc + item.startAmount,
636
+ BigInt(0)
637
+ );
638
+ }
639
+ function formatPrice(priceWei) {
640
+ return parseFloat(viem.formatEther(priceWei));
641
+ }
642
+ async function bulkFetchOrderStatuses(client, chainId, orderHashes) {
643
+ if (orderHashes.length === 0) {
644
+ return [];
645
+ }
646
+ const seaportAddress = getSeaportAddress(chainId);
647
+ const results = await actions.readContract(client, {
648
+ address: BULK_SEAPORT_ORDER_STATUS_FETCHER_ADDRESS,
649
+ abi: BULK_SEAPORT_ORDER_STATUS_FETCHER_ABI,
650
+ functionName: "getOrderStatuses",
651
+ args: [seaportAddress, orderHashes]
652
+ });
653
+ return results.map((r) => ({
654
+ isValidated: r.isValidated,
655
+ isCancelled: r.isCancelled,
656
+ totalFilled: BigInt(r.totalFilled),
657
+ totalSize: BigInt(r.totalSize)
658
+ }));
659
+ }
660
+ async function createOrderStatusMap(client, chainId, orderHashes) {
661
+ const statuses = await bulkFetchOrderStatuses(client, chainId, orderHashes);
662
+ const map = /* @__PURE__ */ new Map();
663
+ orderHashes.forEach((hash, index) => {
664
+ map.set(hash.toLowerCase(), statuses[index]);
665
+ });
666
+ return map;
667
+ }
668
+ async function bulkFetchNftOwners(client, nftAddress, tokenIds) {
669
+ if (tokenIds.length === 0) {
670
+ return [];
671
+ }
672
+ try {
673
+ const owners = await actions.readContract(client, {
674
+ address: ERC721_OWNER_OF_HELPER_ADDRESS,
675
+ abi: ERC721_OWNER_OF_HELPER_ABI,
676
+ functionName: "getTokenOwners",
677
+ args: [nftAddress, tokenIds.map((id) => BigInt(id))]
678
+ });
679
+ return owners.map(
680
+ (owner) => owner === "0x0000000000000000000000000000000000000000" ? null : owner
681
+ );
682
+ } catch {
683
+ return tokenIds.map(() => null);
684
+ }
685
+ }
686
+ async function createOwnershipMap(client, nftAddress, tokenIds) {
687
+ const owners = await bulkFetchNftOwners(client, nftAddress, tokenIds);
688
+ const map = /* @__PURE__ */ new Map();
689
+ tokenIds.forEach((tokenId, index) => {
690
+ map.set(tokenId, owners[index]);
691
+ });
692
+ return map;
693
+ }
694
+ async function bulkFetchErc20Balances(client, tokenAddress, addresses) {
695
+ if (addresses.length === 0) {
696
+ return [];
697
+ }
698
+ try {
699
+ const balances = await actions.readContract(client, {
700
+ address: ERC20_BULK_BALANCE_CHECKER_ADDRESS,
701
+ abi: ERC20_BULK_BALANCE_CHECKER_ABI,
702
+ functionName: "getBalances",
703
+ args: [tokenAddress, addresses]
704
+ });
705
+ return balances.map((b) => BigInt(b));
706
+ } catch {
707
+ return addresses.map(() => BigInt(0));
708
+ }
709
+ }
710
+ async function createBalanceMap(client, tokenAddress, addresses) {
711
+ const balances = await bulkFetchErc20Balances(client, tokenAddress, addresses);
712
+ const map = /* @__PURE__ */ new Map();
713
+ addresses.forEach((address, index) => {
714
+ map.set(address.toLowerCase(), balances[index]);
715
+ });
716
+ return map;
717
+ }
718
+ function isListingValid(orderStatus, expirationDate, sellerAddress, currentOwner) {
719
+ if (orderStatus !== 2 /* OPEN */) {
720
+ return false;
721
+ }
722
+ const now = Math.floor(Date.now() / 1e3);
723
+ if (expirationDate <= now) {
724
+ return false;
725
+ }
726
+ if (!currentOwner || currentOwner.toLowerCase() !== sellerAddress.toLowerCase()) {
727
+ return false;
728
+ }
729
+ return true;
730
+ }
731
+ function isCollectionOfferValid(orderStatus, expirationDate, priceWei, buyerBalance) {
732
+ if (orderStatus !== 2 /* OPEN */) {
733
+ return false;
734
+ }
735
+ const now = Math.floor(Date.now() / 1e3);
736
+ if (expirationDate <= now) {
737
+ return false;
738
+ }
739
+ if (buyerBalance < priceWei) {
740
+ return false;
741
+ }
742
+ return true;
743
+ }
744
+ function isErc20OfferValid(orderStatus, expirationDate, priceWei, buyerWethBalance) {
745
+ if (orderStatus !== 2 /* OPEN */) {
746
+ return false;
747
+ }
748
+ const now = Math.floor(Date.now() / 1e3);
749
+ if (expirationDate <= now) {
750
+ return false;
751
+ }
752
+ if (buyerWethBalance < priceWei) {
753
+ return false;
754
+ }
755
+ return true;
756
+ }
757
+
758
+ // src/utils/parsing.ts
759
+ function parseListingFromMessage(message, chainId) {
760
+ try {
761
+ const submission = decodeSeaportSubmission(message.data);
762
+ const { parameters } = submission;
763
+ const offerItem = parameters.offer[0];
764
+ if (!offerItem) {
765
+ return null;
766
+ }
767
+ if (offerItem.itemType !== 2 /* ERC721 */ && offerItem.itemType !== 3 /* ERC1155 */) {
768
+ return null;
769
+ }
770
+ const priceWei = getTotalConsiderationAmount(parameters);
771
+ const tokenId = offerItem.identifierOrCriteria.toString();
772
+ return {
773
+ maker: parameters.offerer,
774
+ nftAddress: offerItem.token,
775
+ tokenId,
776
+ priceWei,
777
+ price: formatPrice(priceWei),
778
+ currency: getCurrencySymbol(chainId),
779
+ expirationDate: Number(parameters.endTime),
780
+ orderHash: "",
781
+ // Will be computed later
782
+ orderStatus: 2 /* OPEN */,
783
+ // Will be validated later
784
+ messageData: message.data,
785
+ orderComponents: {
786
+ ...parameters,
787
+ counter: submission.counter
788
+ }
789
+ };
790
+ } catch {
791
+ return null;
792
+ }
793
+ }
794
+ function parseCollectionOfferFromMessage(message, chainId) {
795
+ try {
796
+ const submission = decodeSeaportSubmission(message.data);
797
+ const { parameters } = submission;
798
+ if (parameters.zone.toLowerCase() !== NET_SEAPORT_COLLECTION_OFFER_ZONE_ADDRESS.toLowerCase()) {
799
+ return null;
800
+ }
801
+ const offerItem = parameters.offer[0];
802
+ if (!offerItem || offerItem.itemType !== 1 /* ERC20 */) {
803
+ return null;
804
+ }
805
+ const nftConsideration = parameters.consideration.find(
806
+ (item) => item.itemType === 4 /* ERC721_WITH_CRITERIA */ || item.itemType === 5 /* ERC1155_WITH_CRITERIA */
807
+ );
808
+ if (!nftConsideration) {
809
+ return null;
810
+ }
811
+ if (nftConsideration.startAmount !== BigInt(1)) {
812
+ return null;
813
+ }
814
+ const priceWei = offerItem.startAmount;
815
+ return {
816
+ maker: parameters.offerer,
817
+ nftAddress: nftConsideration.token,
818
+ priceWei,
819
+ price: formatPrice(priceWei),
820
+ currency: getCurrencySymbol(chainId),
821
+ expirationDate: Number(parameters.endTime),
822
+ orderHash: "",
823
+ // Will be computed later
824
+ orderStatus: 2 /* OPEN */,
825
+ // Will be validated later
826
+ messageData: message.data,
827
+ orderComponents: {
828
+ ...parameters,
829
+ counter: submission.counter
830
+ }
831
+ };
832
+ } catch {
833
+ return null;
834
+ }
835
+ }
836
+ function getBestListingPerToken(listings) {
837
+ const tokenMap = /* @__PURE__ */ new Map();
838
+ for (const listing of listings) {
839
+ const key = `${listing.nftAddress.toLowerCase()}-${listing.tokenId}`;
840
+ const existing = tokenMap.get(key);
841
+ if (!existing || listing.priceWei < existing.priceWei) {
842
+ tokenMap.set(key, listing);
843
+ }
844
+ }
845
+ return Array.from(tokenMap.values());
846
+ }
847
+ function getBestCollectionOffer(offers) {
848
+ if (offers.length === 0) {
849
+ return null;
850
+ }
851
+ return offers.reduce(
852
+ (best, current) => current.priceWei > best.priceWei ? current : best
853
+ );
854
+ }
855
+ function sortListingsByPrice(listings) {
856
+ return [...listings].sort((a, b) => {
857
+ const diff = a.priceWei - b.priceWei;
858
+ if (diff < BigInt(0)) return -1;
859
+ if (diff > BigInt(0)) return 1;
860
+ return 0;
861
+ });
862
+ }
863
+ function sortOffersByPrice(offers) {
864
+ return [...offers].sort((a, b) => {
865
+ const diff = b.priceWei - a.priceWei;
866
+ if (diff < BigInt(0)) return -1;
867
+ if (diff > BigInt(0)) return 1;
868
+ return 0;
869
+ });
870
+ }
871
+ function parseErc20OfferFromMessage(message, chainId) {
872
+ try {
873
+ const submission = decodeSeaportSubmission(message.data);
874
+ const { parameters } = submission;
875
+ if (parameters.zone.toLowerCase() !== NET_SEAPORT_COLLECTION_OFFER_ZONE_ADDRESS.toLowerCase()) {
876
+ return null;
877
+ }
878
+ const offerItem = parameters.offer[0];
879
+ if (!offerItem || offerItem.itemType !== 1 /* ERC20 */) {
880
+ return null;
881
+ }
882
+ const erc20Consideration = parameters.consideration.find(
883
+ (item) => item.itemType === 1 /* ERC20 */
884
+ );
885
+ if (!erc20Consideration) {
886
+ return null;
887
+ }
888
+ const tokenAmount = erc20Consideration.startAmount;
889
+ if (tokenAmount === BigInt(0)) {
890
+ return null;
891
+ }
892
+ const priceWei = offerItem.startAmount;
893
+ const pricePerTokenWei = priceWei / tokenAmount;
894
+ return {
895
+ maker: parameters.offerer,
896
+ tokenAddress: erc20Consideration.token,
897
+ tokenAmount,
898
+ priceWei,
899
+ pricePerTokenWei,
900
+ price: formatPrice(priceWei),
901
+ pricePerToken: formatPrice(pricePerTokenWei),
902
+ currency: getCurrencySymbol(chainId),
903
+ expirationDate: Number(parameters.endTime),
904
+ orderHash: "0x",
905
+ // Will be computed later
906
+ orderStatus: 2 /* OPEN */,
907
+ // Will be validated later
908
+ messageData: message.data,
909
+ orderComponents: {
910
+ ...parameters,
911
+ counter: submission.counter
912
+ }
913
+ };
914
+ } catch {
915
+ return null;
916
+ }
917
+ }
918
+ function sortErc20OffersByPricePerToken(offers) {
919
+ return [...offers].sort((a, b) => {
920
+ const diff = b.pricePerTokenWei - a.pricePerTokenWei;
921
+ if (diff < BigInt(0)) return -1;
922
+ if (diff > BigInt(0)) return 1;
923
+ return 0;
924
+ });
925
+ }
926
+
927
+ // src/client/BazaarClient.ts
928
+ var CHAIN_RPC_URLS = {
929
+ 8453: ["https://base-mainnet.public.blastapi.io", "https://mainnet.base.org"],
930
+ 84532: ["https://sepolia.base.org"],
931
+ 666666666: ["https://rpc.degen.tips"],
932
+ 5112: ["https://rpc.ham.fun"],
933
+ 57073: ["https://rpc-qnd.inkonchain.com"],
934
+ 130: ["https://mainnet.unichain.org"],
935
+ 999: ["https://rpc.hyperliquid.xyz/evm"],
936
+ 9745: ["https://rpc.plasma.to"],
937
+ 143: ["https://rpc3.monad.xyz"]
938
+ };
939
+ var BazaarClient = class {
940
+ constructor(params) {
941
+ if (!isBazaarSupportedOnChain(params.chainId)) {
942
+ throw new Error(`Bazaar is not supported on chain ${params.chainId}`);
943
+ }
944
+ this.chainId = params.chainId;
945
+ this.rpcUrl = params.rpcUrl || CHAIN_RPC_URLS[params.chainId]?.[0] || "";
946
+ if (!this.rpcUrl) {
947
+ throw new Error(`No RPC URL available for chain ${params.chainId}`);
948
+ }
949
+ const config = getBazaarChainConfig(params.chainId);
950
+ this.client = viem.createPublicClient({
951
+ chain: viem.defineChain({
952
+ id: params.chainId,
953
+ name: `Chain ${params.chainId}`,
954
+ nativeCurrency: {
955
+ name: config.wrappedNativeCurrency.name.replace("Wrapped ", ""),
956
+ symbol: config.currencySymbol.toUpperCase(),
957
+ decimals: 18
958
+ },
959
+ rpcUrls: {
960
+ default: { http: [this.rpcUrl] }
961
+ }
962
+ }),
963
+ transport: viem.http(this.rpcUrl),
964
+ batch: { multicall: true }
965
+ });
966
+ this.netClient = new core.NetClient({
967
+ chainId: params.chainId,
968
+ overrides: params.rpcUrl ? { rpcUrls: [params.rpcUrl] } : void 0
969
+ });
970
+ }
971
+ /**
972
+ * Get valid NFT listings for a collection
973
+ *
974
+ * Returns listings that are:
975
+ * - OPEN status (not filled, cancelled, or expired)
976
+ * - Not expired
977
+ * - Seller still owns the NFT
978
+ *
979
+ * Results are deduplicated (one per token) and sorted by price (lowest first)
980
+ */
981
+ async getListings(options) {
982
+ const { nftAddress, excludeMaker, maxMessages = 200 } = options;
983
+ const bazaarAddress = getBazaarAddress(this.chainId);
984
+ const count = await this.netClient.getMessageCount({
985
+ filter: {
986
+ appAddress: bazaarAddress,
987
+ topic: nftAddress.toLowerCase()
988
+ }
989
+ });
990
+ if (count === 0) {
991
+ return [];
992
+ }
993
+ const startIndex = Math.max(0, count - maxMessages);
994
+ const messages = await this.netClient.getMessages({
995
+ filter: {
996
+ appAddress: bazaarAddress,
997
+ topic: nftAddress.toLowerCase()
998
+ },
999
+ startIndex,
1000
+ endIndex: count
1001
+ });
1002
+ let listings = [];
1003
+ for (const message of messages) {
1004
+ const listing = parseListingFromMessage(message, this.chainId);
1005
+ if (!listing) continue;
1006
+ if (excludeMaker && listing.maker.toLowerCase() === excludeMaker.toLowerCase()) {
1007
+ continue;
1008
+ }
1009
+ listings.push(listing);
1010
+ }
1011
+ if (listings.length === 0) {
1012
+ return [];
1013
+ }
1014
+ const seaport = createSeaportInstance(this.chainId, this.rpcUrl);
1015
+ for (const listing of listings) {
1016
+ const order = getSeaportOrderFromMessageData(listing.messageData);
1017
+ listing.orderHash = computeOrderHash(seaport, order.parameters, order.counter);
1018
+ }
1019
+ const orderHashes = listings.map((l) => l.orderHash);
1020
+ const statusInfos = await bulkFetchOrderStatuses(this.client, this.chainId, orderHashes);
1021
+ listings.forEach((listing, index) => {
1022
+ const statusInfo = statusInfos[index];
1023
+ listing.orderStatus = getOrderStatusFromInfo(listing.orderComponents, statusInfo);
1024
+ });
1025
+ listings = listings.filter(
1026
+ (l) => l.orderStatus === 2 /* OPEN */ && l.expirationDate > Math.floor(Date.now() / 1e3)
1027
+ );
1028
+ if (listings.length === 0) {
1029
+ return [];
1030
+ }
1031
+ const tokenIds = listings.map((l) => l.tokenId);
1032
+ const owners = await bulkFetchNftOwners(this.client, nftAddress, tokenIds);
1033
+ listings = listings.filter((listing, index) => {
1034
+ const owner = owners[index];
1035
+ return isListingValid(
1036
+ listing.orderStatus,
1037
+ listing.expirationDate,
1038
+ listing.maker,
1039
+ owner
1040
+ );
1041
+ });
1042
+ return sortListingsByPrice(getBestListingPerToken(listings));
1043
+ }
1044
+ /**
1045
+ * Get valid collection offers for a collection
1046
+ *
1047
+ * Returns offers that are:
1048
+ * - OPEN status (not filled, cancelled, or expired)
1049
+ * - Not expired
1050
+ * - Buyer has sufficient WETH balance
1051
+ *
1052
+ * Results are sorted by price (highest first)
1053
+ */
1054
+ async getCollectionOffers(options) {
1055
+ const { nftAddress, excludeMaker, maxMessages = 100 } = options;
1056
+ const collectionOffersAddress = getCollectionOffersAddress(this.chainId);
1057
+ const weth = getWrappedNativeCurrency(this.chainId);
1058
+ if (!weth) {
1059
+ return [];
1060
+ }
1061
+ const count = await this.netClient.getMessageCount({
1062
+ filter: {
1063
+ appAddress: collectionOffersAddress,
1064
+ topic: nftAddress.toLowerCase()
1065
+ }
1066
+ });
1067
+ if (count === 0) {
1068
+ return [];
1069
+ }
1070
+ const startIndex = Math.max(0, count - maxMessages);
1071
+ const messages = await this.netClient.getMessages({
1072
+ filter: {
1073
+ appAddress: collectionOffersAddress,
1074
+ topic: nftAddress.toLowerCase()
1075
+ },
1076
+ startIndex,
1077
+ endIndex: count
1078
+ });
1079
+ let offers = [];
1080
+ for (const message of messages) {
1081
+ const offer = parseCollectionOfferFromMessage(message, this.chainId);
1082
+ if (!offer) continue;
1083
+ const order = getSeaportOrderFromMessageData(offer.messageData);
1084
+ const offerToken = order.parameters.offer?.[0]?.token?.toLowerCase();
1085
+ if (offerToken !== weth.address.toLowerCase()) {
1086
+ continue;
1087
+ }
1088
+ if (excludeMaker && offer.maker.toLowerCase() === excludeMaker.toLowerCase()) {
1089
+ continue;
1090
+ }
1091
+ offers.push(offer);
1092
+ }
1093
+ if (offers.length === 0) {
1094
+ return [];
1095
+ }
1096
+ const seaport = createSeaportInstance(this.chainId, this.rpcUrl);
1097
+ for (const offer of offers) {
1098
+ const order = getSeaportOrderFromMessageData(offer.messageData);
1099
+ offer.orderHash = computeOrderHash(seaport, order.parameters, order.counter);
1100
+ }
1101
+ const orderHashes = offers.map((o) => o.orderHash);
1102
+ const statusInfos = await bulkFetchOrderStatuses(this.client, this.chainId, orderHashes);
1103
+ offers.forEach((offer, index) => {
1104
+ const statusInfo = statusInfos[index];
1105
+ offer.orderStatus = getOrderStatusFromInfo(offer.orderComponents, statusInfo);
1106
+ });
1107
+ offers = offers.filter(
1108
+ (o) => o.orderStatus === 2 /* OPEN */ && o.expirationDate > Math.floor(Date.now() / 1e3)
1109
+ );
1110
+ if (offers.length === 0) {
1111
+ return [];
1112
+ }
1113
+ const uniqueMakers = [...new Set(offers.map((o) => o.maker))];
1114
+ const balances = await bulkFetchErc20Balances(this.client, weth.address, uniqueMakers);
1115
+ const balanceMap = /* @__PURE__ */ new Map();
1116
+ uniqueMakers.forEach((maker, index) => {
1117
+ balanceMap.set(maker.toLowerCase(), balances[index]);
1118
+ });
1119
+ offers = offers.filter((offer) => {
1120
+ const balance = balanceMap.get(offer.maker.toLowerCase()) || BigInt(0);
1121
+ return isCollectionOfferValid(
1122
+ offer.orderStatus,
1123
+ offer.expirationDate,
1124
+ offer.priceWei,
1125
+ balance
1126
+ );
1127
+ });
1128
+ return sortOffersByPrice(offers);
1129
+ }
1130
+ /**
1131
+ * Get valid ERC20 offers for a token
1132
+ *
1133
+ * ERC20 offers are only available on Base (8453) and HyperEVM (999).
1134
+ *
1135
+ * Returns offers that are:
1136
+ * - OPEN status (not filled, cancelled, or expired)
1137
+ * - Not expired
1138
+ * - Buyer has sufficient WETH balance
1139
+ *
1140
+ * Results are sorted by price per token (highest first)
1141
+ */
1142
+ async getErc20Offers(options) {
1143
+ const { tokenAddress, excludeMaker, maxMessages = 200 } = options;
1144
+ const erc20OffersAddress = getErc20OffersAddress(this.chainId);
1145
+ const weth = getWrappedNativeCurrency(this.chainId);
1146
+ if (!erc20OffersAddress || !weth) {
1147
+ return [];
1148
+ }
1149
+ const count = await this.netClient.getMessageCount({
1150
+ filter: {
1151
+ appAddress: erc20OffersAddress,
1152
+ topic: tokenAddress.toLowerCase()
1153
+ }
1154
+ });
1155
+ if (count === 0) {
1156
+ return [];
1157
+ }
1158
+ const startIndex = Math.max(0, count - maxMessages);
1159
+ const messages = await this.netClient.getMessages({
1160
+ filter: {
1161
+ appAddress: erc20OffersAddress,
1162
+ topic: tokenAddress.toLowerCase()
1163
+ },
1164
+ startIndex,
1165
+ endIndex: count
1166
+ });
1167
+ let offers = [];
1168
+ for (const message of messages) {
1169
+ const offer = parseErc20OfferFromMessage(message, this.chainId);
1170
+ if (!offer) continue;
1171
+ const order = getSeaportOrderFromMessageData(offer.messageData);
1172
+ const offerToken = order.parameters.offer?.[0]?.token?.toLowerCase();
1173
+ if (offerToken !== weth.address.toLowerCase()) {
1174
+ continue;
1175
+ }
1176
+ if (offer.tokenAddress.toLowerCase() !== tokenAddress.toLowerCase()) {
1177
+ continue;
1178
+ }
1179
+ if (excludeMaker && offer.maker.toLowerCase() === excludeMaker.toLowerCase()) {
1180
+ continue;
1181
+ }
1182
+ offers.push(offer);
1183
+ }
1184
+ if (offers.length === 0) {
1185
+ return [];
1186
+ }
1187
+ const seaport = createSeaportInstance(this.chainId, this.rpcUrl);
1188
+ for (const offer of offers) {
1189
+ const order = getSeaportOrderFromMessageData(offer.messageData);
1190
+ offer.orderHash = computeOrderHash(seaport, order.parameters, order.counter);
1191
+ }
1192
+ const orderHashes = offers.map((o) => o.orderHash);
1193
+ const statusInfos = await bulkFetchOrderStatuses(this.client, this.chainId, orderHashes);
1194
+ offers.forEach((offer, index) => {
1195
+ const statusInfo = statusInfos[index];
1196
+ offer.orderStatus = getOrderStatusFromInfo(offer.orderComponents, statusInfo);
1197
+ });
1198
+ offers = offers.filter(
1199
+ (o) => o.orderStatus === 2 /* OPEN */ && o.expirationDate > Math.floor(Date.now() / 1e3)
1200
+ );
1201
+ if (offers.length === 0) {
1202
+ return [];
1203
+ }
1204
+ const uniqueMakers = [...new Set(offers.map((o) => o.maker))];
1205
+ const balances = await bulkFetchErc20Balances(this.client, weth.address, uniqueMakers);
1206
+ const balanceMap = /* @__PURE__ */ new Map();
1207
+ uniqueMakers.forEach((maker, index) => {
1208
+ balanceMap.set(maker.toLowerCase(), balances[index]);
1209
+ });
1210
+ offers = offers.filter((offer) => {
1211
+ const balance = balanceMap.get(offer.maker.toLowerCase()) || BigInt(0);
1212
+ return isErc20OfferValid(
1213
+ offer.orderStatus,
1214
+ offer.expirationDate,
1215
+ offer.priceWei,
1216
+ balance
1217
+ );
1218
+ });
1219
+ return sortErc20OffersByPricePerToken(offers);
1220
+ }
1221
+ /**
1222
+ * Get the chain ID this client is configured for
1223
+ */
1224
+ getChainId() {
1225
+ return this.chainId;
1226
+ }
1227
+ /**
1228
+ * Get the bazaar contract address for this chain
1229
+ */
1230
+ getBazaarAddress() {
1231
+ return getBazaarAddress(this.chainId);
1232
+ }
1233
+ /**
1234
+ * Get the collection offers contract address for this chain
1235
+ */
1236
+ getCollectionOffersAddress() {
1237
+ return getCollectionOffersAddress(this.chainId);
1238
+ }
1239
+ /**
1240
+ * Get the ERC20 offers contract address for this chain
1241
+ * Only available on Base (8453) and HyperEVM (999)
1242
+ */
1243
+ getErc20OffersAddress() {
1244
+ return getErc20OffersAddress(this.chainId);
1245
+ }
1246
+ /**
1247
+ * Get the Seaport contract address for this chain
1248
+ */
1249
+ getSeaportAddress() {
1250
+ return getSeaportAddress(this.chainId);
1251
+ }
1252
+ /**
1253
+ * Prepare a transaction to cancel a listing
1254
+ *
1255
+ * The listing must have been created by the caller.
1256
+ * Use the orderComponents from the Listing object returned by getListings().
1257
+ */
1258
+ prepareCancelListing(listing) {
1259
+ if (!listing.orderComponents) {
1260
+ throw new Error("Listing does not have order components");
1261
+ }
1262
+ return this.prepareCancelOrder(listing.orderComponents);
1263
+ }
1264
+ /**
1265
+ * Prepare a transaction to cancel a collection offer
1266
+ *
1267
+ * The offer must have been created by the caller.
1268
+ * Use the orderComponents from the CollectionOffer object returned by getCollectionOffers().
1269
+ */
1270
+ prepareCancelCollectionOffer(offer) {
1271
+ if (!offer.orderComponents) {
1272
+ throw new Error("Offer does not have order components");
1273
+ }
1274
+ return this.prepareCancelOrder(offer.orderComponents);
1275
+ }
1276
+ /**
1277
+ * Prepare a transaction to cancel a Seaport order
1278
+ *
1279
+ * This is a low-level method. Prefer prepareCancelListing or prepareCancelCollectionOffer.
1280
+ */
1281
+ prepareCancelOrder(orderComponents) {
1282
+ const seaportAddress = getSeaportAddress(this.chainId);
1283
+ const orderForCancel = {
1284
+ offerer: orderComponents.offerer,
1285
+ zone: orderComponents.zone,
1286
+ offer: orderComponents.offer.map((item) => ({
1287
+ itemType: item.itemType,
1288
+ token: item.token,
1289
+ identifierOrCriteria: item.identifierOrCriteria,
1290
+ startAmount: item.startAmount,
1291
+ endAmount: item.endAmount
1292
+ })),
1293
+ consideration: orderComponents.consideration.map((item) => ({
1294
+ itemType: item.itemType,
1295
+ token: item.token,
1296
+ identifierOrCriteria: item.identifierOrCriteria,
1297
+ startAmount: item.startAmount,
1298
+ endAmount: item.endAmount,
1299
+ recipient: item.recipient
1300
+ })),
1301
+ orderType: orderComponents.orderType,
1302
+ startTime: orderComponents.startTime,
1303
+ endTime: orderComponents.endTime,
1304
+ zoneHash: orderComponents.zoneHash,
1305
+ salt: orderComponents.salt,
1306
+ conduitKey: orderComponents.conduitKey,
1307
+ counter: orderComponents.counter
1308
+ };
1309
+ return {
1310
+ to: seaportAddress,
1311
+ functionName: "cancel",
1312
+ args: [[orderForCancel]],
1313
+ abi: SEAPORT_CANCEL_ABI
1314
+ };
1315
+ }
1316
+ };
1317
+
1318
+ exports.BAZAAR_COLLECTION_OFFERS_ABI = BAZAAR_COLLECTION_OFFERS_ABI;
1319
+ exports.BAZAAR_SUBMISSION_ABI = BAZAAR_SUBMISSION_ABI;
1320
+ exports.BAZAAR_V2_ABI = BAZAAR_V2_ABI;
1321
+ exports.BULK_SEAPORT_ORDER_STATUS_FETCHER_ABI = BULK_SEAPORT_ORDER_STATUS_FETCHER_ABI;
1322
+ exports.BULK_SEAPORT_ORDER_STATUS_FETCHER_ADDRESS = BULK_SEAPORT_ORDER_STATUS_FETCHER_ADDRESS;
1323
+ exports.BazaarClient = BazaarClient;
1324
+ exports.ERC20_BULK_BALANCE_CHECKER_ABI = ERC20_BULK_BALANCE_CHECKER_ABI;
1325
+ exports.ERC20_BULK_BALANCE_CHECKER_ADDRESS = ERC20_BULK_BALANCE_CHECKER_ADDRESS;
1326
+ exports.ERC721_OWNER_OF_HELPER_ABI = ERC721_OWNER_OF_HELPER_ABI;
1327
+ exports.ERC721_OWNER_OF_HELPER_ADDRESS = ERC721_OWNER_OF_HELPER_ADDRESS;
1328
+ exports.ItemType = ItemType;
1329
+ exports.NET_SEAPORT_COLLECTION_OFFER_ZONE_ADDRESS = NET_SEAPORT_COLLECTION_OFFER_ZONE_ADDRESS;
1330
+ exports.NET_SEAPORT_ZONE_ADDRESS = NET_SEAPORT_ZONE_ADDRESS;
1331
+ exports.OrderType = OrderType;
1332
+ exports.SEAPORT_CANCEL_ABI = SEAPORT_CANCEL_ABI;
1333
+ exports.SeaportOrderStatus = SeaportOrderStatus;
1334
+ exports.bulkFetchErc20Balances = bulkFetchErc20Balances;
1335
+ exports.bulkFetchNftOwners = bulkFetchNftOwners;
1336
+ exports.bulkFetchOrderStatuses = bulkFetchOrderStatuses;
1337
+ exports.computeOrderHash = computeOrderHash;
1338
+ exports.createBalanceMap = createBalanceMap;
1339
+ exports.createOrderStatusMap = createOrderStatusMap;
1340
+ exports.createOwnershipMap = createOwnershipMap;
1341
+ exports.createSeaportInstance = createSeaportInstance;
1342
+ exports.decodeSeaportSubmission = decodeSeaportSubmission;
1343
+ exports.formatPrice = formatPrice;
1344
+ exports.getBazaarAddress = getBazaarAddress;
1345
+ exports.getBazaarChainConfig = getBazaarChainConfig;
1346
+ exports.getBazaarSupportedChainIds = getBazaarSupportedChainIds;
1347
+ exports.getBestCollectionOffer = getBestCollectionOffer;
1348
+ exports.getBestListingPerToken = getBestListingPerToken;
1349
+ exports.getCollectionOffersAddress = getCollectionOffersAddress;
1350
+ exports.getCurrencySymbol = getCurrencySymbol;
1351
+ exports.getErc20OffersAddress = getErc20OffersAddress;
1352
+ exports.getFeeCollectorAddress = getFeeCollectorAddress;
1353
+ exports.getHighEthAddress = getHighEthAddress;
1354
+ exports.getNftFeeBps = getNftFeeBps;
1355
+ exports.getOrderStatusFromInfo = getOrderStatusFromInfo;
1356
+ exports.getSeaportAddress = getSeaportAddress;
1357
+ exports.getSeaportOrderFromMessageData = getSeaportOrderFromMessageData;
1358
+ exports.getTotalConsiderationAmount = getTotalConsiderationAmount;
1359
+ exports.getWrappedNativeCurrency = getWrappedNativeCurrency;
1360
+ exports.isBazaarSupportedOnChain = isBazaarSupportedOnChain;
1361
+ exports.isCollectionOfferValid = isCollectionOfferValid;
1362
+ exports.isErc20OfferValid = isErc20OfferValid;
1363
+ exports.isListingValid = isListingValid;
1364
+ exports.parseCollectionOfferFromMessage = parseCollectionOfferFromMessage;
1365
+ exports.parseErc20OfferFromMessage = parseErc20OfferFromMessage;
1366
+ exports.parseListingFromMessage = parseListingFromMessage;
1367
+ exports.sortErc20OffersByPricePerToken = sortErc20OffersByPricePerToken;
1368
+ exports.sortListingsByPrice = sortListingsByPrice;
1369
+ exports.sortOffersByPrice = sortOffersByPrice;
1370
+ //# sourceMappingURL=index.js.map
1371
+ //# sourceMappingURL=index.js.map