@net-protocol/bazaar 0.1.5 → 0.1.7

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/react.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { PublicClient } from 'viem';
2
- import { L as Listing, C as CollectionOffer, E as Erc20Offer, d as Erc20Listing } from './types-CfGfQTJL.mjs';
2
+ import { L as Listing, C as CollectionOffer, E as Erc20Offer, d as Erc20Listing, S as Sale } from './types-5kMf461x.mjs';
3
3
 
4
4
  /**
5
5
  * React hook for fetching NFT listings from Bazaar
@@ -8,8 +8,8 @@ import { L as Listing, C as CollectionOffer, E as Erc20Offer, d as Erc20Listing
8
8
  interface UseBazaarListingsOptions {
9
9
  /** Chain ID to query */
10
10
  chainId: number;
11
- /** NFT collection address */
12
- nftAddress: `0x${string}`;
11
+ /** NFT collection address (optional - if omitted, fetches recent listings across all collections) */
12
+ nftAddress?: `0x${string}`;
13
13
  /** Exclude listings from this address */
14
14
  excludeMaker?: `0x${string}`;
15
15
  /** Only include listings from this address */
@@ -45,7 +45,8 @@ interface UseBazaarListingsResult {
45
45
  * - Not expired
46
46
  * - Seller still owns the NFT
47
47
  *
48
- * Results are deduplicated (one per token) and sorted by price (lowest first)
48
+ * Results are deduplicated (one per token) and sorted by price (lowest first).
49
+ * If `nftAddress` is omitted, fetches recent listings across all collections on the chain.
49
50
  *
50
51
  * @example
51
52
  * ```tsx
@@ -255,4 +256,61 @@ interface UseBazaarErc20ListingsResult {
255
256
  */
256
257
  declare function useBazaarErc20Listings({ chainId, tokenAddress, excludeMaker, maker, maxMessages, startIndex: startIndexOverride, endIndex: endIndexOverride, enabled, publicClient, }: UseBazaarErc20ListingsOptions): UseBazaarErc20ListingsResult;
257
258
 
258
- export { type UseBazaarCollectionOffersOptions, type UseBazaarCollectionOffersResult, type UseBazaarErc20ListingsOptions, type UseBazaarErc20ListingsResult, type UseBazaarErc20OffersOptions, type UseBazaarErc20OffersResult, type UseBazaarListingsOptions, type UseBazaarListingsResult, useBazaarCollectionOffers, useBazaarErc20Listings, useBazaarErc20Offers, useBazaarListings };
259
+ /**
260
+ * React hook for fetching recent sales from Bazaar
261
+ */
262
+
263
+ interface UseBazaarSalesOptions {
264
+ /** Chain ID to query */
265
+ chainId: number;
266
+ /** NFT collection address */
267
+ nftAddress: `0x${string}`;
268
+ /** Maximum number of messages to fetch (default: 100) */
269
+ maxMessages?: number;
270
+ /** Whether the query is enabled (default: true) */
271
+ enabled?: boolean;
272
+ }
273
+ interface UseBazaarSalesResult {
274
+ /** Recent sales (sorted by timestamp, most recent first) */
275
+ sales: Sale[];
276
+ /** Whether the data is loading */
277
+ isLoading: boolean;
278
+ /** Error if any */
279
+ error: Error | undefined;
280
+ /** Refetch function */
281
+ refetch: () => void;
282
+ }
283
+ /**
284
+ * React hook for fetching recent sales from Bazaar
285
+ *
286
+ * Sales data flows differently from listings/offers:
287
+ * - Net messages (appAddress=zone, topic=nftAddress) contain order hashes
288
+ * - Actual sale data is fetched from the bulk storage contract
289
+ *
290
+ * Results are sorted by timestamp (most recent first)
291
+ *
292
+ * @example
293
+ * ```tsx
294
+ * const { sales, isLoading, error } = useBazaarSales({
295
+ * chainId: 8453,
296
+ * nftAddress: "0x...",
297
+ * maxMessages: 100,
298
+ * });
299
+ *
300
+ * if (isLoading) return <div>Loading...</div>;
301
+ * if (error) return <div>Error: {error.message}</div>;
302
+ *
303
+ * return (
304
+ * <ul>
305
+ * {sales.map((sale) => (
306
+ * <li key={sale.orderHash}>
307
+ * Token #{sale.tokenId} - {sale.price} {sale.currency}
308
+ * </li>
309
+ * ))}
310
+ * </ul>
311
+ * );
312
+ * ```
313
+ */
314
+ declare function useBazaarSales({ chainId, nftAddress, maxMessages, enabled, }: UseBazaarSalesOptions): UseBazaarSalesResult;
315
+
316
+ export { type UseBazaarCollectionOffersOptions, type UseBazaarCollectionOffersResult, type UseBazaarErc20ListingsOptions, type UseBazaarErc20ListingsResult, type UseBazaarErc20OffersOptions, type UseBazaarErc20OffersResult, type UseBazaarListingsOptions, type UseBazaarListingsResult, type UseBazaarSalesOptions, type UseBazaarSalesResult, useBazaarCollectionOffers, useBazaarErc20Listings, useBazaarErc20Offers, useBazaarListings, useBazaarSales };
package/dist/react.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { PublicClient } from 'viem';
2
- import { L as Listing, C as CollectionOffer, E as Erc20Offer, d as Erc20Listing } from './types-CfGfQTJL.js';
2
+ import { L as Listing, C as CollectionOffer, E as Erc20Offer, d as Erc20Listing, S as Sale } from './types-5kMf461x.js';
3
3
 
4
4
  /**
5
5
  * React hook for fetching NFT listings from Bazaar
@@ -8,8 +8,8 @@ import { L as Listing, C as CollectionOffer, E as Erc20Offer, d as Erc20Listing
8
8
  interface UseBazaarListingsOptions {
9
9
  /** Chain ID to query */
10
10
  chainId: number;
11
- /** NFT collection address */
12
- nftAddress: `0x${string}`;
11
+ /** NFT collection address (optional - if omitted, fetches recent listings across all collections) */
12
+ nftAddress?: `0x${string}`;
13
13
  /** Exclude listings from this address */
14
14
  excludeMaker?: `0x${string}`;
15
15
  /** Only include listings from this address */
@@ -45,7 +45,8 @@ interface UseBazaarListingsResult {
45
45
  * - Not expired
46
46
  * - Seller still owns the NFT
47
47
  *
48
- * Results are deduplicated (one per token) and sorted by price (lowest first)
48
+ * Results are deduplicated (one per token) and sorted by price (lowest first).
49
+ * If `nftAddress` is omitted, fetches recent listings across all collections on the chain.
49
50
  *
50
51
  * @example
51
52
  * ```tsx
@@ -255,4 +256,61 @@ interface UseBazaarErc20ListingsResult {
255
256
  */
256
257
  declare function useBazaarErc20Listings({ chainId, tokenAddress, excludeMaker, maker, maxMessages, startIndex: startIndexOverride, endIndex: endIndexOverride, enabled, publicClient, }: UseBazaarErc20ListingsOptions): UseBazaarErc20ListingsResult;
257
258
 
258
- export { type UseBazaarCollectionOffersOptions, type UseBazaarCollectionOffersResult, type UseBazaarErc20ListingsOptions, type UseBazaarErc20ListingsResult, type UseBazaarErc20OffersOptions, type UseBazaarErc20OffersResult, type UseBazaarListingsOptions, type UseBazaarListingsResult, useBazaarCollectionOffers, useBazaarErc20Listings, useBazaarErc20Offers, useBazaarListings };
259
+ /**
260
+ * React hook for fetching recent sales from Bazaar
261
+ */
262
+
263
+ interface UseBazaarSalesOptions {
264
+ /** Chain ID to query */
265
+ chainId: number;
266
+ /** NFT collection address */
267
+ nftAddress: `0x${string}`;
268
+ /** Maximum number of messages to fetch (default: 100) */
269
+ maxMessages?: number;
270
+ /** Whether the query is enabled (default: true) */
271
+ enabled?: boolean;
272
+ }
273
+ interface UseBazaarSalesResult {
274
+ /** Recent sales (sorted by timestamp, most recent first) */
275
+ sales: Sale[];
276
+ /** Whether the data is loading */
277
+ isLoading: boolean;
278
+ /** Error if any */
279
+ error: Error | undefined;
280
+ /** Refetch function */
281
+ refetch: () => void;
282
+ }
283
+ /**
284
+ * React hook for fetching recent sales from Bazaar
285
+ *
286
+ * Sales data flows differently from listings/offers:
287
+ * - Net messages (appAddress=zone, topic=nftAddress) contain order hashes
288
+ * - Actual sale data is fetched from the bulk storage contract
289
+ *
290
+ * Results are sorted by timestamp (most recent first)
291
+ *
292
+ * @example
293
+ * ```tsx
294
+ * const { sales, isLoading, error } = useBazaarSales({
295
+ * chainId: 8453,
296
+ * nftAddress: "0x...",
297
+ * maxMessages: 100,
298
+ * });
299
+ *
300
+ * if (isLoading) return <div>Loading...</div>;
301
+ * if (error) return <div>Error: {error.message}</div>;
302
+ *
303
+ * return (
304
+ * <ul>
305
+ * {sales.map((sale) => (
306
+ * <li key={sale.orderHash}>
307
+ * Token #{sale.tokenId} - {sale.price} {sale.currency}
308
+ * </li>
309
+ * ))}
310
+ * </ul>
311
+ * );
312
+ * ```
313
+ */
314
+ declare function useBazaarSales({ chainId, nftAddress, maxMessages, enabled, }: UseBazaarSalesOptions): UseBazaarSalesResult;
315
+
316
+ export { type UseBazaarCollectionOffersOptions, type UseBazaarCollectionOffersResult, type UseBazaarErc20ListingsOptions, type UseBazaarErc20ListingsResult, type UseBazaarErc20OffersOptions, type UseBazaarErc20OffersResult, type UseBazaarListingsOptions, type UseBazaarListingsResult, type UseBazaarSalesOptions, type UseBazaarSalesResult, useBazaarCollectionOffers, useBazaarErc20Listings, useBazaarErc20Offers, useBazaarListings, useBazaarSales };
package/dist/react.js CHANGED
@@ -8,6 +8,7 @@ var core = require('@net-protocol/core');
8
8
  var seaportJs = require('@opensea/seaport-js');
9
9
  var ethers = require('ethers');
10
10
  var actions = require('viem/actions');
11
+ var storage = require('@net-protocol/storage');
11
12
 
12
13
  // src/hooks/useBazaarListings.ts
13
14
 
@@ -185,6 +186,7 @@ var DEFAULT_NFT_FEE_BPS = 500;
185
186
  var BULK_SEAPORT_ORDER_STATUS_FETCHER_ADDRESS = "0x0000009112ABCE652674b4fE3eD9C765B22d11A7";
186
187
  var ERC721_OWNER_OF_HELPER_ADDRESS = "0x00000012E3eb0700925947fAF9cd1440319b4F37";
187
188
  var ERC20_BULK_BALANCE_CHECKER_ADDRESS = "0x000000B50A9f2923F2DB931391824F6D1278f712";
189
+ var NET_SEAPORT_ZONE_ADDRESS = "0x000000007F8c58fbf215bF91Bda7421A806cf3ae";
188
190
  var NET_SEAPORT_COLLECTION_OFFER_ZONE_ADDRESS = "0x000000B799ec6D7aCC1B578f62bFc324c25DFC5A";
189
191
  var NET_SEAPORT_PRIVATE_ORDER_ZONE_ADDRESS = "0x000000bC63761cbb05305632212e2f3AE2BE7a9B";
190
192
  var BAZAAR_CHAIN_CONFIGS = {
@@ -581,8 +583,6 @@ function isErc20ListingValid(orderStatus, expirationDate, tokenAmount, sellerTok
581
583
  }
582
584
  return true;
583
585
  }
584
-
585
- // src/utils/parsing.ts
586
586
  function parseListingFromMessage(message, chainId) {
587
587
  try {
588
588
  const submission = decodeSeaportSubmission(message.data);
@@ -796,8 +796,82 @@ function sortErc20ListingsByPricePerToken(listings) {
796
796
  return 0;
797
797
  });
798
798
  }
799
-
800
- // src/client/BazaarClient.ts
799
+ var ZONE_STORED_SALE_ABI = [
800
+ { type: "uint256" },
801
+ // timestamp
802
+ { type: "uint256" },
803
+ // netTotalMessageLength
804
+ { type: "uint256" },
805
+ // netTotalMessageForAppTopicLength
806
+ {
807
+ name: "zoneParameters",
808
+ type: "tuple",
809
+ internalType: "struct ZoneParameters",
810
+ components: [
811
+ { name: "orderHash", type: "bytes32", internalType: "bytes32" },
812
+ { name: "fulfiller", type: "address", internalType: "address" },
813
+ { name: "offerer", type: "address", internalType: "address" },
814
+ {
815
+ name: "offer",
816
+ type: "tuple[]",
817
+ internalType: "struct SpentItem[]",
818
+ components: [
819
+ { name: "itemType", type: "uint8", internalType: "enum ItemType" },
820
+ { name: "token", type: "address", internalType: "address" },
821
+ { name: "identifier", type: "uint256", internalType: "uint256" },
822
+ { name: "amount", type: "uint256", internalType: "uint256" }
823
+ ]
824
+ },
825
+ {
826
+ name: "consideration",
827
+ type: "tuple[]",
828
+ internalType: "struct ReceivedItem[]",
829
+ components: [
830
+ { name: "itemType", type: "uint8", internalType: "enum ItemType" },
831
+ { name: "token", type: "address", internalType: "address" },
832
+ { name: "identifier", type: "uint256", internalType: "uint256" },
833
+ { name: "amount", type: "uint256", internalType: "uint256" },
834
+ { name: "recipient", type: "address", internalType: "address payable" }
835
+ ]
836
+ },
837
+ { name: "extraData", type: "bytes", internalType: "bytes" },
838
+ { name: "orderHashes", type: "bytes32[]", internalType: "bytes32[]" },
839
+ { name: "startTime", type: "uint256", internalType: "uint256" },
840
+ { name: "endTime", type: "uint256", internalType: "uint256" },
841
+ { name: "zoneHash", type: "bytes32", internalType: "bytes32" }
842
+ ]
843
+ }
844
+ ];
845
+ function parseSaleFromStoredData(storedData, chainId) {
846
+ try {
847
+ const cleanedData = "0x" + (storedData.startsWith("0x") ? storedData.slice(2) : storedData);
848
+ const [timestamp, , , zoneParameters] = viem.decodeAbiParameters(
849
+ ZONE_STORED_SALE_ABI,
850
+ cleanedData
851
+ );
852
+ const offerItem = zoneParameters.offer[0];
853
+ if (!offerItem) return null;
854
+ const totalConsideration = zoneParameters.consideration.reduce(
855
+ (acc, item) => acc + item.amount,
856
+ BigInt(0)
857
+ );
858
+ return {
859
+ seller: zoneParameters.offerer,
860
+ buyer: zoneParameters.fulfiller,
861
+ tokenAddress: offerItem.token,
862
+ tokenId: offerItem.identifier.toString(),
863
+ amount: offerItem.amount,
864
+ itemType: offerItem.itemType,
865
+ priceWei: totalConsideration,
866
+ price: parseFloat(viem.formatEther(totalConsideration)),
867
+ currency: getCurrencySymbol(chainId),
868
+ timestamp: Number(timestamp),
869
+ orderHash: zoneParameters.orderHash
870
+ };
871
+ } catch {
872
+ return null;
873
+ }
874
+ }
801
875
  var CHAIN_RPC_URLS = {
802
876
  8453: ["https://base-mainnet.public.blastapi.io", "https://mainnet.base.org"],
803
877
  84532: ["https://sepolia.base.org"],
@@ -860,7 +934,7 @@ var BazaarClient = class {
860
934
  const bazaarAddress = getBazaarAddress(this.chainId);
861
935
  const filter = {
862
936
  appAddress: bazaarAddress,
863
- topic: nftAddress.toLowerCase(),
937
+ topic: nftAddress?.toLowerCase(),
864
938
  maker
865
939
  };
866
940
  let startIndex;
@@ -933,18 +1007,57 @@ var BazaarClient = class {
933
1007
  }
934
1008
  const openListings = listings.filter((l) => l.orderStatus === 2 /* OPEN */);
935
1009
  const expiredListings = includeExpired ? listings.filter((l) => l.orderStatus === 1 /* EXPIRED */) : [];
936
- const tokenIds = openListings.map((l) => l.tokenId);
937
- const owners = await bulkFetchNftOwners(this.client, nftAddress, tokenIds);
1010
+ let validOpenListings;
938
1011
  const beforeOwnership = openListings.length;
939
- const validOpenListings = openListings.filter((listing, index) => {
940
- const owner = owners[index];
941
- return isListingValid(
942
- listing.orderStatus,
943
- listing.expirationDate,
944
- listing.maker,
945
- owner
1012
+ if (nftAddress) {
1013
+ const tokenIds = openListings.map((l) => l.tokenId);
1014
+ const owners = await bulkFetchNftOwners(this.client, nftAddress, tokenIds);
1015
+ validOpenListings = openListings.filter((listing, index) => {
1016
+ const owner = owners[index];
1017
+ return isListingValid(
1018
+ listing.orderStatus,
1019
+ listing.expirationDate,
1020
+ listing.maker,
1021
+ owner
1022
+ );
1023
+ });
1024
+ } else {
1025
+ const groups = /* @__PURE__ */ new Map();
1026
+ for (const listing of openListings) {
1027
+ const key = listing.nftAddress.toLowerCase();
1028
+ const group = groups.get(key);
1029
+ if (group) {
1030
+ group.push(listing);
1031
+ } else {
1032
+ groups.set(key, [listing]);
1033
+ }
1034
+ }
1035
+ const groupEntries = Array.from(groups.entries());
1036
+ const ownerResults = await Promise.all(
1037
+ groupEntries.map(
1038
+ ([addr, groupListings]) => bulkFetchNftOwners(
1039
+ this.client,
1040
+ addr,
1041
+ groupListings.map((l) => l.tokenId)
1042
+ )
1043
+ )
946
1044
  );
947
- });
1045
+ validOpenListings = [];
1046
+ groupEntries.forEach(([, groupListings], groupIndex) => {
1047
+ const owners = ownerResults[groupIndex];
1048
+ for (let i = 0; i < groupListings.length; i++) {
1049
+ const listing = groupListings[i];
1050
+ if (isListingValid(
1051
+ listing.orderStatus,
1052
+ listing.expirationDate,
1053
+ listing.maker,
1054
+ owners[i]
1055
+ )) {
1056
+ validOpenListings.push(listing);
1057
+ }
1058
+ }
1059
+ });
1060
+ }
948
1061
  console.log(tag, `after ownership filter: ${validOpenListings.length}/${beforeOwnership} (${beforeOwnership - validOpenListings.length} dropped)`);
949
1062
  const dedupedOpen = sortListingsByPrice(getBestListingPerToken(validOpenListings));
950
1063
  const activeTokenKeys = new Set(dedupedOpen.map((l) => `${l.nftAddress.toLowerCase()}-${l.tokenId}`));
@@ -1277,6 +1390,72 @@ var BazaarClient = class {
1277
1390
  console.log(tag, `after balance filter: ${listings.length}/${beforeBalance} (${beforeBalance - listings.length} dropped)`);
1278
1391
  return sortErc20ListingsByPricePerToken(listings);
1279
1392
  }
1393
+ /**
1394
+ * Get recent sales for a collection
1395
+ *
1396
+ * Sales are stored differently from listings: Net messages contain order hashes,
1397
+ * and the actual sale data is fetched from the bulk storage contract.
1398
+ *
1399
+ * Results are sorted by timestamp (most recent first)
1400
+ */
1401
+ async getSales(options) {
1402
+ const { nftAddress, maxMessages = 100 } = options;
1403
+ const filter = {
1404
+ appAddress: NET_SEAPORT_ZONE_ADDRESS,
1405
+ topic: nftAddress.toLowerCase()
1406
+ };
1407
+ const count = await this.netClient.getMessageCount({ filter });
1408
+ if (count === 0) {
1409
+ return [];
1410
+ }
1411
+ const startIndex = Math.max(0, count - maxMessages);
1412
+ const messages = await this.netClient.getMessages({
1413
+ filter,
1414
+ startIndex,
1415
+ endIndex: count
1416
+ });
1417
+ return this.processSalesFromMessages(messages, options);
1418
+ }
1419
+ /**
1420
+ * Process pre-fetched messages into sales.
1421
+ *
1422
+ * Each message's data field contains an order hash. The actual sale data
1423
+ * is fetched from the bulk storage contract using these order hashes.
1424
+ */
1425
+ async processSalesFromMessages(messages, options) {
1426
+ const tag = `[BazaarClient.processSales chain=${this.chainId}]`;
1427
+ if (messages.length === 0) {
1428
+ return [];
1429
+ }
1430
+ const orderHashes = messages.map((m) => m.data);
1431
+ console.log(tag, `fetching ${orderHashes.length} sale details from storage...`);
1432
+ const bulkKeys = orderHashes.map((hash) => ({
1433
+ key: hash,
1434
+ operator: NET_SEAPORT_ZONE_ADDRESS
1435
+ }));
1436
+ let storedResults;
1437
+ try {
1438
+ storedResults = await this.client.readContract({
1439
+ abi: storage.STORAGE_CONTRACT.abi,
1440
+ address: storage.STORAGE_CONTRACT.address,
1441
+ functionName: "bulkGet",
1442
+ args: [bulkKeys]
1443
+ });
1444
+ } catch (err) {
1445
+ console.error(tag, "bulk storage fetch failed:", err);
1446
+ return [];
1447
+ }
1448
+ const sales = [];
1449
+ for (const result of storedResults) {
1450
+ if (!result.value || result.value === "0x") continue;
1451
+ const sale = parseSaleFromStoredData(result.value, this.chainId);
1452
+ if (sale) {
1453
+ sales.push(sale);
1454
+ }
1455
+ }
1456
+ console.log(tag, `parsed ${sales.length}/${storedResults.length} sales`);
1457
+ return sales;
1458
+ }
1280
1459
  /**
1281
1460
  * Get the chain ID this client is configured for
1282
1461
  */
@@ -1423,7 +1602,7 @@ function useBazaarListings({
1423
1602
  const filter = react.useMemo(
1424
1603
  () => ({
1425
1604
  appAddress: bazaarAddress,
1426
- topic: nftAddress.toLowerCase(),
1605
+ topic: nftAddress?.toLowerCase(),
1427
1606
  maker
1428
1607
  }),
1429
1608
  [bazaarAddress, nftAddress, maker]
@@ -1447,7 +1626,7 @@ function useBazaarListings({
1447
1626
  endIndex,
1448
1627
  enabled: enabled && isSupported && (hasRangeOverride || totalCount > 0)
1449
1628
  });
1450
- const TAG = `[useBazaarListings chain=${chainId} nft=${nftAddress.slice(0, 10)}]`;
1629
+ const TAG = `[useBazaarListings chain=${chainId} nft=${nftAddress?.slice(0, 10) ?? "all"}]`;
1451
1630
  react.useEffect(() => {
1452
1631
  console.log(TAG, {
1453
1632
  enabled,
@@ -1863,10 +2042,120 @@ function useBazaarErc20Listings({
1863
2042
  refetch
1864
2043
  };
1865
2044
  }
2045
+ function useBazaarSales({
2046
+ chainId,
2047
+ nftAddress,
2048
+ maxMessages = 100,
2049
+ enabled = true
2050
+ }) {
2051
+ const wagmiClient = wagmi.usePublicClient({ chainId });
2052
+ const [sales, setSales] = react.useState([]);
2053
+ const [isProcessing, setIsProcessing] = react.useState(false);
2054
+ const [processingError, setProcessingError] = react.useState();
2055
+ const [refetchTrigger, setRefetchTrigger] = react.useState(0);
2056
+ const isSupported = react.useMemo(
2057
+ () => isBazaarSupportedOnChain(chainId),
2058
+ [chainId]
2059
+ );
2060
+ const filter = react.useMemo(
2061
+ () => ({
2062
+ appAddress: NET_SEAPORT_ZONE_ADDRESS,
2063
+ topic: nftAddress.toLowerCase()
2064
+ }),
2065
+ [nftAddress]
2066
+ );
2067
+ const { count: totalCount, isLoading: isLoadingCount } = react$1.useNetMessageCount({
2068
+ chainId,
2069
+ filter,
2070
+ enabled: enabled && isSupported
2071
+ });
2072
+ const startIndex = react.useMemo(
2073
+ () => Math.max(0, totalCount - maxMessages),
2074
+ [totalCount, maxMessages]
2075
+ );
2076
+ const {
2077
+ messages,
2078
+ isLoading: isLoadingMessages,
2079
+ error: messagesError,
2080
+ refetch: refetchMessages
2081
+ } = react$1.useNetMessages({
2082
+ chainId,
2083
+ filter,
2084
+ startIndex,
2085
+ endIndex: totalCount,
2086
+ enabled: enabled && isSupported && totalCount > 0
2087
+ });
2088
+ const TAG = `[useBazaarSales chain=${chainId} nft=${nftAddress.slice(0, 10)}]`;
2089
+ react.useEffect(() => {
2090
+ console.log(TAG, {
2091
+ enabled,
2092
+ isSupported,
2093
+ totalCount,
2094
+ isLoadingCount,
2095
+ startIndex,
2096
+ endIndex: totalCount,
2097
+ messagesLength: messages?.length ?? 0,
2098
+ isLoadingMessages,
2099
+ messagesError: messagesError?.message
2100
+ });
2101
+ }, [enabled, isSupported, totalCount, isLoadingCount, startIndex, messages?.length, isLoadingMessages, messagesError]);
2102
+ react.useEffect(() => {
2103
+ if (!isSupported || !enabled) {
2104
+ setSales([]);
2105
+ return;
2106
+ }
2107
+ if (!messages || messages.length === 0) {
2108
+ setSales([]);
2109
+ return;
2110
+ }
2111
+ let cancelled = false;
2112
+ async function processSales() {
2113
+ setIsProcessing(true);
2114
+ setProcessingError(void 0);
2115
+ console.log(TAG, `processing ${messages.length} messages...`);
2116
+ try {
2117
+ const client = new BazaarClient({ chainId, publicClient: wagmiClient });
2118
+ const parsedSales = await client.processSalesFromMessages(
2119
+ messages,
2120
+ { nftAddress }
2121
+ );
2122
+ console.log(TAG, `processed \u2192 ${parsedSales.length} sales`);
2123
+ if (!cancelled) {
2124
+ setSales(parsedSales);
2125
+ }
2126
+ } catch (err) {
2127
+ console.error(TAG, "processing error:", err);
2128
+ if (!cancelled) {
2129
+ setProcessingError(err instanceof Error ? err : new Error(String(err)));
2130
+ setSales([]);
2131
+ }
2132
+ } finally {
2133
+ if (!cancelled) {
2134
+ setIsProcessing(false);
2135
+ }
2136
+ }
2137
+ }
2138
+ processSales();
2139
+ return () => {
2140
+ cancelled = true;
2141
+ };
2142
+ }, [chainId, nftAddress, messages, isSupported, enabled, refetchTrigger]);
2143
+ const refetch = () => {
2144
+ refetchMessages();
2145
+ setRefetchTrigger((t) => t + 1);
2146
+ };
2147
+ return {
2148
+ sales,
2149
+ isLoading: isLoadingCount || isLoadingMessages || isProcessing,
2150
+ error: messagesError || processingError,
2151
+ refetch
2152
+ };
2153
+ }
1866
2154
 
1867
2155
  exports.useBazaarCollectionOffers = useBazaarCollectionOffers;
1868
2156
  exports.useBazaarErc20Listings = useBazaarErc20Listings;
1869
2157
  exports.useBazaarErc20Offers = useBazaarErc20Offers;
1870
2158
  exports.useBazaarListings = useBazaarListings;
2159
+ exports.useBazaarSales = useBazaarSales;
1871
2160
  //# sourceMappingURL=react.js.map
1872
2161
  //# sourceMappingURL=react.js.map