@net-protocol/bazaar 0.1.1 → 0.1.3

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.js CHANGED
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var react = require('react');
4
+ var wagmi = require('wagmi');
4
5
  var react$1 = require('@net-protocol/core/react');
5
6
  var viem = require('viem');
6
7
  var core = require('@net-protocol/core');
@@ -182,9 +183,10 @@ var DEFAULT_FEE_COLLECTOR_ADDRESS = "0x32D16C15410248bef498D7aF50D10Db1a546b9E5"
182
183
  var DEFAULT_ERC20_BAZAAR_ADDRESS = "0x00000000a2d173a4610c85c7471a25b6bc216a70";
183
184
  var DEFAULT_NFT_FEE_BPS = 500;
184
185
  var BULK_SEAPORT_ORDER_STATUS_FETCHER_ADDRESS = "0x0000009112ABCE652674b4fE3eD9C765B22d11A7";
185
- var ERC721_OWNER_OF_HELPER_ADDRESS = "0x000000aa4eFa2e5A4a6002C7F08B6e8Ec8cf1dDa";
186
- var ERC20_BULK_BALANCE_CHECKER_ADDRESS = "0x000000b50a9f2923f2db931391824f6d1278f712";
186
+ var ERC721_OWNER_OF_HELPER_ADDRESS = "0x00000012E3eb0700925947fAF9cd1440319b4F37";
187
+ var ERC20_BULK_BALANCE_CHECKER_ADDRESS = "0x000000B50A9f2923F2DB931391824F6D1278f712";
187
188
  var NET_SEAPORT_COLLECTION_OFFER_ZONE_ADDRESS = "0x000000B799ec6D7aCC1B578f62bFc324c25DFC5A";
189
+ var NET_SEAPORT_PRIVATE_ORDER_ZONE_ADDRESS = "0x000000bC63761cbb05305632212e2f3AE2BE7a9B";
188
190
  var BAZAAR_CHAIN_CONFIGS = {
189
191
  // Base Mainnet
190
192
  8453: {
@@ -463,34 +465,47 @@ async function bulkFetchOrderStatuses(client, chainId, orderHashes) {
463
465
  return [];
464
466
  }
465
467
  const seaportAddress = getSeaportAddress(chainId);
466
- const results = await actions.readContract(client, {
467
- address: BULK_SEAPORT_ORDER_STATUS_FETCHER_ADDRESS,
468
- abi: BULK_SEAPORT_ORDER_STATUS_FETCHER_ABI,
469
- functionName: "getOrderStatuses",
470
- args: [seaportAddress, orderHashes]
471
- });
472
- return results.map((r) => ({
473
- isValidated: r.isValidated,
474
- isCancelled: r.isCancelled,
475
- totalFilled: BigInt(r.totalFilled),
476
- totalSize: BigInt(r.totalSize)
477
- }));
468
+ try {
469
+ console.log(`[bulkFetchOrderStatuses] fetching ${orderHashes.length} statuses via ${BULK_SEAPORT_ORDER_STATUS_FETCHER_ADDRESS}`);
470
+ const results = await actions.readContract(client, {
471
+ address: BULK_SEAPORT_ORDER_STATUS_FETCHER_ADDRESS,
472
+ abi: BULK_SEAPORT_ORDER_STATUS_FETCHER_ABI,
473
+ functionName: "getOrderStatuses",
474
+ args: [seaportAddress, orderHashes]
475
+ });
476
+ const statuses = results.map((r) => ({
477
+ isValidated: r.isValidated,
478
+ isCancelled: r.isCancelled,
479
+ totalFilled: BigInt(r.totalFilled),
480
+ totalSize: BigInt(r.totalSize)
481
+ }));
482
+ console.log(`[bulkFetchOrderStatuses] success: ${statuses.length} statuses`);
483
+ return statuses;
484
+ } catch (err) {
485
+ console.error(`[bulkFetchOrderStatuses] FAILED for ${orderHashes.length} hashes:`, err);
486
+ throw err;
487
+ }
478
488
  }
479
489
  async function bulkFetchNftOwners(client, nftAddress, tokenIds) {
480
490
  if (tokenIds.length === 0) {
481
491
  return [];
482
492
  }
483
493
  try {
494
+ console.log(`[bulkFetchNftOwners] fetching ${tokenIds.length} owners for ${nftAddress.slice(0, 10)} via ${ERC721_OWNER_OF_HELPER_ADDRESS}`);
484
495
  const owners = await actions.readContract(client, {
485
496
  address: ERC721_OWNER_OF_HELPER_ADDRESS,
486
497
  abi: ERC721_OWNER_OF_HELPER_ABI,
487
498
  functionName: "getTokenOwners",
488
499
  args: [nftAddress, tokenIds.map((id) => BigInt(id))]
489
500
  });
490
- return owners.map(
501
+ const result = owners.map(
491
502
  (owner) => owner === "0x0000000000000000000000000000000000000000" ? null : owner
492
503
  );
493
- } catch {
504
+ const validCount = result.filter((o) => o !== null).length;
505
+ console.log(`[bulkFetchNftOwners] success: ${validCount}/${tokenIds.length} have owners`);
506
+ return result;
507
+ } catch (err) {
508
+ console.error(`[bulkFetchNftOwners] FAILED for ${tokenIds.length} tokens \u2014 returning all null:`, err);
494
509
  return tokenIds.map(() => null);
495
510
  }
496
511
  }
@@ -499,14 +514,18 @@ async function bulkFetchErc20Balances(client, tokenAddress, addresses) {
499
514
  return [];
500
515
  }
501
516
  try {
517
+ console.log(`[bulkFetchErc20Balances] fetching ${addresses.length} balances for ${tokenAddress.slice(0, 10)}`);
502
518
  const balances = await actions.readContract(client, {
503
519
  address: ERC20_BULK_BALANCE_CHECKER_ADDRESS,
504
520
  abi: ERC20_BULK_BALANCE_CHECKER_ABI,
505
521
  functionName: "getBalances",
506
522
  args: [tokenAddress, addresses]
507
523
  });
508
- return balances.map((b) => BigInt(b));
509
- } catch {
524
+ const result = balances.map((b) => BigInt(b));
525
+ console.log(`[bulkFetchErc20Balances] success: ${result.length} balances`);
526
+ return result;
527
+ } catch (err) {
528
+ console.error(`[bulkFetchErc20Balances] FAILED for ${addresses.length} addresses \u2014 returning all zero:`, err);
510
529
  return addresses.map(() => BigInt(0));
511
530
  }
512
531
  }
@@ -577,6 +596,7 @@ function parseListingFromMessage(message, chainId) {
577
596
  }
578
597
  const priceWei = getTotalConsiderationAmount(parameters);
579
598
  const tokenId = offerItem.identifierOrCriteria.toString();
599
+ const targetFulfiller = parameters.zone.toLowerCase() === NET_SEAPORT_PRIVATE_ORDER_ZONE_ADDRESS.toLowerCase() && parameters.zoneHash !== "0x0000000000000000000000000000000000000000000000000000000000000000" ? parameters.zoneHash : void 0;
580
600
  return {
581
601
  maker: parameters.offerer,
582
602
  nftAddress: offerItem.token,
@@ -593,7 +613,8 @@ function parseListingFromMessage(message, chainId) {
593
613
  orderComponents: {
594
614
  ...parameters,
595
615
  counter: submission.counter
596
- }
616
+ },
617
+ targetFulfiller
597
618
  };
598
619
  } catch {
599
620
  return null;
@@ -795,26 +816,30 @@ var BazaarClient = class {
795
816
  }
796
817
  this.chainId = params.chainId;
797
818
  this.rpcUrl = params.rpcUrl || CHAIN_RPC_URLS[params.chainId]?.[0] || "";
798
- if (!this.rpcUrl) {
799
- throw new Error(`No RPC URL available for chain ${params.chainId}`);
819
+ if (params.publicClient) {
820
+ this.client = params.publicClient;
821
+ } else {
822
+ if (!this.rpcUrl) {
823
+ throw new Error(`No RPC URL available for chain ${params.chainId}`);
824
+ }
825
+ const config = getBazaarChainConfig(params.chainId);
826
+ this.client = viem.createPublicClient({
827
+ chain: viem.defineChain({
828
+ id: params.chainId,
829
+ name: `Chain ${params.chainId}`,
830
+ nativeCurrency: {
831
+ name: config.wrappedNativeCurrency.name.replace("Wrapped ", ""),
832
+ symbol: config.currencySymbol.toUpperCase(),
833
+ decimals: 18
834
+ },
835
+ rpcUrls: {
836
+ default: { http: [this.rpcUrl] }
837
+ }
838
+ }),
839
+ transport: viem.http(this.rpcUrl),
840
+ batch: { multicall: true }
841
+ });
800
842
  }
801
- const config = getBazaarChainConfig(params.chainId);
802
- this.client = viem.createPublicClient({
803
- chain: viem.defineChain({
804
- id: params.chainId,
805
- name: `Chain ${params.chainId}`,
806
- nativeCurrency: {
807
- name: config.wrappedNativeCurrency.name.replace("Wrapped ", ""),
808
- symbol: config.currencySymbol.toUpperCase(),
809
- decimals: 18
810
- },
811
- rpcUrls: {
812
- default: { http: [this.rpcUrl] }
813
- }
814
- }),
815
- transport: viem.http(this.rpcUrl),
816
- batch: { multicall: true }
817
- });
818
843
  this.netClient = new core.NetClient({
819
844
  chainId: params.chainId,
820
845
  overrides: params.rpcUrl ? { rpcUrls: [params.rpcUrl] } : void 0
@@ -831,26 +856,42 @@ var BazaarClient = class {
831
856
  * Results are deduplicated (one per token) and sorted by price (lowest first)
832
857
  */
833
858
  async getListings(options) {
834
- const { nftAddress, excludeMaker, maxMessages = 200 } = options;
859
+ const { nftAddress, excludeMaker, maker, maxMessages = 200 } = options;
835
860
  const bazaarAddress = getBazaarAddress(this.chainId);
836
- const count = await this.netClient.getMessageCount({
837
- filter: {
838
- appAddress: bazaarAddress,
839
- topic: nftAddress.toLowerCase()
861
+ const filter = {
862
+ appAddress: bazaarAddress,
863
+ topic: nftAddress.toLowerCase(),
864
+ maker
865
+ };
866
+ let startIndex;
867
+ let endIndex;
868
+ if (options.startIndex != null && options.endIndex != null) {
869
+ startIndex = options.startIndex;
870
+ endIndex = options.endIndex;
871
+ } else {
872
+ const count = await this.netClient.getMessageCount({ filter });
873
+ if (count === 0) {
874
+ return [];
840
875
  }
841
- });
842
- if (count === 0) {
843
- return [];
876
+ startIndex = Math.max(0, count - maxMessages);
877
+ endIndex = count;
844
878
  }
845
- const startIndex = Math.max(0, count - maxMessages);
846
879
  const messages = await this.netClient.getMessages({
847
- filter: {
848
- appAddress: bazaarAddress,
849
- topic: nftAddress.toLowerCase()
850
- },
880
+ filter,
851
881
  startIndex,
852
- endIndex: count
882
+ endIndex
853
883
  });
884
+ return this.processListingsFromMessages(messages, options);
885
+ }
886
+ /**
887
+ * Process pre-fetched messages into valid NFT listings.
888
+ *
889
+ * Use this when messages have already been fetched (e.g. via useNetMessages)
890
+ * to avoid redundant RPC calls.
891
+ */
892
+ async processListingsFromMessages(messages, options) {
893
+ const { nftAddress, excludeMaker, includeExpired = false } = options;
894
+ const tag = `[BazaarClient.processListings chain=${this.chainId}]`;
854
895
  let listings = [];
855
896
  for (const message of messages) {
856
897
  const listing = parseListingFromMessage(message, this.chainId);
@@ -860,6 +901,7 @@ var BazaarClient = class {
860
901
  }
861
902
  listings.push(listing);
862
903
  }
904
+ console.log(tag, `parsed ${listings.length}/${messages.length} messages into listings`);
863
905
  if (listings.length === 0) {
864
906
  return [];
865
907
  }
@@ -874,15 +916,27 @@ var BazaarClient = class {
874
916
  const statusInfo = statusInfos[index];
875
917
  listing.orderStatus = getOrderStatusFromInfo(listing.orderComponents, statusInfo);
876
918
  });
919
+ const statusCounts = {};
920
+ const now = Math.floor(Date.now() / 1e3);
921
+ let expiredCount = 0;
922
+ for (const l of listings) {
923
+ statusCounts[l.orderStatus] = (statusCounts[l.orderStatus] || 0) + 1;
924
+ if (l.expirationDate <= now) expiredCount++;
925
+ }
926
+ console.log(tag, `order statuses:`, statusCounts, `expired: ${expiredCount}`);
877
927
  listings = listings.filter(
878
- (l) => l.orderStatus === 2 /* OPEN */ && l.expirationDate > Math.floor(Date.now() / 1e3)
928
+ (l) => l.orderStatus === 2 /* OPEN */ && l.expirationDate > now || includeExpired && l.orderStatus === 1 /* EXPIRED */
879
929
  );
930
+ console.log(tag, `after status filter: ${listings.length} (OPEN${includeExpired ? " + EXPIRED" : ""})`);
880
931
  if (listings.length === 0) {
881
932
  return [];
882
933
  }
883
- const tokenIds = listings.map((l) => l.tokenId);
934
+ const openListings = listings.filter((l) => l.orderStatus === 2 /* OPEN */);
935
+ const expiredListings = includeExpired ? listings.filter((l) => l.orderStatus === 1 /* EXPIRED */) : [];
936
+ const tokenIds = openListings.map((l) => l.tokenId);
884
937
  const owners = await bulkFetchNftOwners(this.client, nftAddress, tokenIds);
885
- listings = listings.filter((listing, index) => {
938
+ const beforeOwnership = openListings.length;
939
+ const validOpenListings = openListings.filter((listing, index) => {
886
940
  const owner = owners[index];
887
941
  return isListingValid(
888
942
  listing.orderStatus,
@@ -891,7 +945,16 @@ var BazaarClient = class {
891
945
  owner
892
946
  );
893
947
  });
894
- return sortListingsByPrice(getBestListingPerToken(listings));
948
+ console.log(tag, `after ownership filter: ${validOpenListings.length}/${beforeOwnership} (${beforeOwnership - validOpenListings.length} dropped)`);
949
+ const dedupedOpen = sortListingsByPrice(getBestListingPerToken(validOpenListings));
950
+ const activeTokenKeys = new Set(dedupedOpen.map((l) => `${l.nftAddress.toLowerCase()}-${l.tokenId}`));
951
+ const uniqueExpired = getBestListingPerToken(
952
+ expiredListings.filter((l) => !activeTokenKeys.has(`${l.nftAddress.toLowerCase()}-${l.tokenId}`))
953
+ );
954
+ const sortedExpired = sortListingsByPrice(uniqueExpired);
955
+ const result = [...dedupedOpen, ...sortedExpired];
956
+ console.log(tag, `final: ${result.length} listings (${dedupedOpen.length} open, ${sortedExpired.length} expired)`);
957
+ return result;
895
958
  }
896
959
  /**
897
960
  * Get valid collection offers for a collection
@@ -906,10 +969,6 @@ var BazaarClient = class {
906
969
  async getCollectionOffers(options) {
907
970
  const { nftAddress, excludeMaker, maxMessages = 100 } = options;
908
971
  const collectionOffersAddress = getCollectionOffersAddress(this.chainId);
909
- const weth = getWrappedNativeCurrency(this.chainId);
910
- if (!weth) {
911
- return [];
912
- }
913
972
  const count = await this.netClient.getMessageCount({
914
973
  filter: {
915
974
  appAddress: collectionOffersAddress,
@@ -928,6 +987,21 @@ var BazaarClient = class {
928
987
  startIndex,
929
988
  endIndex: count
930
989
  });
990
+ return this.processCollectionOffersFromMessages(messages, options);
991
+ }
992
+ /**
993
+ * Process pre-fetched messages into valid collection offers.
994
+ *
995
+ * Use this when messages have already been fetched (e.g. via useNetMessages)
996
+ * to avoid redundant RPC calls.
997
+ */
998
+ async processCollectionOffersFromMessages(messages, options) {
999
+ const { nftAddress, excludeMaker } = options;
1000
+ const tag = `[BazaarClient.processCollectionOffers chain=${this.chainId}]`;
1001
+ const weth = getWrappedNativeCurrency(this.chainId);
1002
+ if (!weth) {
1003
+ return [];
1004
+ }
931
1005
  let offers = [];
932
1006
  for (const message of messages) {
933
1007
  const offer = parseCollectionOfferFromMessage(message, this.chainId);
@@ -942,6 +1016,7 @@ var BazaarClient = class {
942
1016
  }
943
1017
  offers.push(offer);
944
1018
  }
1019
+ console.log(tag, `parsed ${offers.length}/${messages.length} messages into offers`);
945
1020
  if (offers.length === 0) {
946
1021
  return [];
947
1022
  }
@@ -956,9 +1031,11 @@ var BazaarClient = class {
956
1031
  const statusInfo = statusInfos[index];
957
1032
  offer.orderStatus = getOrderStatusFromInfo(offer.orderComponents, statusInfo);
958
1033
  });
1034
+ const now = Math.floor(Date.now() / 1e3);
959
1035
  offers = offers.filter(
960
- (o) => o.orderStatus === 2 /* OPEN */ && o.expirationDate > Math.floor(Date.now() / 1e3)
1036
+ (o) => o.orderStatus === 2 /* OPEN */ && o.expirationDate > now
961
1037
  );
1038
+ console.log(tag, `after status filter: ${offers.length} OPEN & not expired`);
962
1039
  if (offers.length === 0) {
963
1040
  return [];
964
1041
  }
@@ -968,6 +1045,7 @@ var BazaarClient = class {
968
1045
  uniqueMakers.forEach((maker, index) => {
969
1046
  balanceMap.set(maker.toLowerCase(), balances[index]);
970
1047
  });
1048
+ const beforeBalance = offers.length;
971
1049
  offers = offers.filter((offer) => {
972
1050
  const balance = balanceMap.get(offer.maker.toLowerCase()) || BigInt(0);
973
1051
  return isCollectionOfferValid(
@@ -977,6 +1055,7 @@ var BazaarClient = class {
977
1055
  balance
978
1056
  );
979
1057
  });
1058
+ console.log(tag, `after balance filter: ${offers.length}/${beforeBalance} (${beforeBalance - offers.length} dropped)`);
980
1059
  return sortOffersByPrice(offers);
981
1060
  }
982
1061
  /**
@@ -994,8 +1073,7 @@ var BazaarClient = class {
994
1073
  async getErc20Offers(options) {
995
1074
  const { tokenAddress, excludeMaker, maxMessages = 200 } = options;
996
1075
  const erc20OffersAddress = getErc20OffersAddress(this.chainId);
997
- const weth = getWrappedNativeCurrency(this.chainId);
998
- if (!erc20OffersAddress || !weth) {
1076
+ if (!erc20OffersAddress) {
999
1077
  return [];
1000
1078
  }
1001
1079
  const count = await this.netClient.getMessageCount({
@@ -1016,6 +1094,21 @@ var BazaarClient = class {
1016
1094
  startIndex,
1017
1095
  endIndex: count
1018
1096
  });
1097
+ return this.processErc20OffersFromMessages(messages, options);
1098
+ }
1099
+ /**
1100
+ * Process pre-fetched messages into valid ERC20 offers.
1101
+ *
1102
+ * Use this when messages have already been fetched (e.g. via useNetMessages)
1103
+ * to avoid redundant RPC calls.
1104
+ */
1105
+ async processErc20OffersFromMessages(messages, options) {
1106
+ const { tokenAddress, excludeMaker } = options;
1107
+ const tag = `[BazaarClient.processErc20Offers chain=${this.chainId}]`;
1108
+ const weth = getWrappedNativeCurrency(this.chainId);
1109
+ if (!weth) {
1110
+ return [];
1111
+ }
1019
1112
  let offers = [];
1020
1113
  for (const message of messages) {
1021
1114
  const offer = parseErc20OfferFromMessage(message, this.chainId);
@@ -1033,6 +1126,7 @@ var BazaarClient = class {
1033
1126
  }
1034
1127
  offers.push(offer);
1035
1128
  }
1129
+ console.log(tag, `parsed ${offers.length}/${messages.length} messages into offers`);
1036
1130
  if (offers.length === 0) {
1037
1131
  return [];
1038
1132
  }
@@ -1047,9 +1141,11 @@ var BazaarClient = class {
1047
1141
  const statusInfo = statusInfos[index];
1048
1142
  offer.orderStatus = getOrderStatusFromInfo(offer.orderComponents, statusInfo);
1049
1143
  });
1144
+ const now = Math.floor(Date.now() / 1e3);
1050
1145
  offers = offers.filter(
1051
- (o) => o.orderStatus === 2 /* OPEN */ && o.expirationDate > Math.floor(Date.now() / 1e3)
1146
+ (o) => o.orderStatus === 2 /* OPEN */ && o.expirationDate > now
1052
1147
  );
1148
+ console.log(tag, `after status filter: ${offers.length} OPEN & not expired`);
1053
1149
  if (offers.length === 0) {
1054
1150
  return [];
1055
1151
  }
@@ -1059,6 +1155,7 @@ var BazaarClient = class {
1059
1155
  uniqueMakers.forEach((maker, index) => {
1060
1156
  balanceMap.set(maker.toLowerCase(), balances[index]);
1061
1157
  });
1158
+ const beforeBalance = offers.length;
1062
1159
  offers = offers.filter((offer) => {
1063
1160
  const balance = balanceMap.get(offer.maker.toLowerCase()) || BigInt(0);
1064
1161
  return isErc20OfferValid(
@@ -1068,6 +1165,7 @@ var BazaarClient = class {
1068
1165
  balance
1069
1166
  );
1070
1167
  });
1168
+ console.log(tag, `after balance filter: ${offers.length}/${beforeBalance} (${beforeBalance - offers.length} dropped)`);
1071
1169
  return sortErc20OffersByPricePerToken(offers);
1072
1170
  }
1073
1171
  /**
@@ -1082,26 +1180,42 @@ var BazaarClient = class {
1082
1180
  * all valid listings are returned (grouped by maker in the UI).
1083
1181
  */
1084
1182
  async getErc20Listings(options) {
1085
- const { tokenAddress, excludeMaker, maxMessages = 200 } = options;
1183
+ const { tokenAddress, excludeMaker, maker, maxMessages = 200 } = options;
1086
1184
  const erc20BazaarAddress = getErc20BazaarAddress(this.chainId);
1087
- const count = await this.netClient.getMessageCount({
1088
- filter: {
1089
- appAddress: erc20BazaarAddress,
1090
- topic: tokenAddress.toLowerCase()
1185
+ const filter = {
1186
+ appAddress: erc20BazaarAddress,
1187
+ topic: tokenAddress.toLowerCase(),
1188
+ maker
1189
+ };
1190
+ let startIndex;
1191
+ let endIndex;
1192
+ if (options.startIndex != null && options.endIndex != null) {
1193
+ startIndex = options.startIndex;
1194
+ endIndex = options.endIndex;
1195
+ } else {
1196
+ const count = await this.netClient.getMessageCount({ filter });
1197
+ if (count === 0) {
1198
+ return [];
1091
1199
  }
1092
- });
1093
- if (count === 0) {
1094
- return [];
1200
+ startIndex = Math.max(0, count - maxMessages);
1201
+ endIndex = count;
1095
1202
  }
1096
- const startIndex = Math.max(0, count - maxMessages);
1097
1203
  const messages = await this.netClient.getMessages({
1098
- filter: {
1099
- appAddress: erc20BazaarAddress,
1100
- topic: tokenAddress.toLowerCase()
1101
- },
1204
+ filter,
1102
1205
  startIndex,
1103
- endIndex: count
1206
+ endIndex
1104
1207
  });
1208
+ return this.processErc20ListingsFromMessages(messages, options);
1209
+ }
1210
+ /**
1211
+ * Process pre-fetched messages into valid ERC20 listings.
1212
+ *
1213
+ * Use this when messages have already been fetched (e.g. via useNetMessages)
1214
+ * to avoid redundant RPC calls.
1215
+ */
1216
+ async processErc20ListingsFromMessages(messages, options) {
1217
+ const { tokenAddress, excludeMaker } = options;
1218
+ const tag = `[BazaarClient.processErc20Listings chain=${this.chainId}]`;
1105
1219
  let listings = [];
1106
1220
  for (const message of messages) {
1107
1221
  const listing = parseErc20ListingFromMessage(message, this.chainId);
@@ -1114,6 +1228,7 @@ var BazaarClient = class {
1114
1228
  }
1115
1229
  listings.push(listing);
1116
1230
  }
1231
+ console.log(tag, `parsed ${listings.length}/${messages.length} messages into listings`);
1117
1232
  if (listings.length === 0) {
1118
1233
  return [];
1119
1234
  }
@@ -1128,9 +1243,18 @@ var BazaarClient = class {
1128
1243
  const statusInfo = statusInfos[index];
1129
1244
  listing.orderStatus = getOrderStatusFromInfo(listing.orderComponents, statusInfo);
1130
1245
  });
1246
+ const statusCounts = {};
1247
+ const now = Math.floor(Date.now() / 1e3);
1248
+ let expiredCount = 0;
1249
+ for (const l of listings) {
1250
+ statusCounts[l.orderStatus] = (statusCounts[l.orderStatus] || 0) + 1;
1251
+ if (l.expirationDate <= now) expiredCount++;
1252
+ }
1253
+ console.log(tag, `order statuses:`, statusCounts, `expired: ${expiredCount}`);
1131
1254
  listings = listings.filter(
1132
- (l) => l.orderStatus === 2 /* OPEN */ && l.expirationDate > Math.floor(Date.now() / 1e3)
1255
+ (l) => l.orderStatus === 2 /* OPEN */ && l.expirationDate > now
1133
1256
  );
1257
+ console.log(tag, `after status filter: ${listings.length} OPEN & not expired`);
1134
1258
  if (listings.length === 0) {
1135
1259
  return [];
1136
1260
  }
@@ -1140,6 +1264,7 @@ var BazaarClient = class {
1140
1264
  uniqueMakers.forEach((maker, index) => {
1141
1265
  balanceMap.set(maker.toLowerCase(), balances[index]);
1142
1266
  });
1267
+ const beforeBalance = listings.length;
1143
1268
  listings = listings.filter((listing) => {
1144
1269
  const balance = balanceMap.get(listing.maker.toLowerCase()) || BigInt(0);
1145
1270
  return isErc20ListingValid(
@@ -1149,6 +1274,7 @@ var BazaarClient = class {
1149
1274
  balance
1150
1275
  );
1151
1276
  });
1277
+ console.log(tag, `after balance filter: ${listings.length}/${beforeBalance} (${beforeBalance - listings.length} dropped)`);
1152
1278
  return sortErc20ListingsByPricePerToken(listings);
1153
1279
  }
1154
1280
  /**
@@ -1271,13 +1397,21 @@ function useBazaarListings({
1271
1397
  chainId,
1272
1398
  nftAddress,
1273
1399
  excludeMaker,
1400
+ maker,
1274
1401
  maxMessages = 200,
1275
- enabled = true
1402
+ startIndex: startIndexOverride,
1403
+ endIndex: endIndexOverride,
1404
+ includeExpired = false,
1405
+ enabled = true,
1406
+ publicClient
1276
1407
  }) {
1408
+ const wagmiClient = wagmi.usePublicClient({ chainId });
1409
+ const resolvedClient = publicClient ?? wagmiClient;
1277
1410
  const [listings, setListings] = react.useState([]);
1278
1411
  const [isProcessing, setIsProcessing] = react.useState(false);
1279
1412
  const [processingError, setProcessingError] = react.useState();
1280
1413
  const [refetchTrigger, setRefetchTrigger] = react.useState(0);
1414
+ const hasRangeOverride = startIndexOverride != null && endIndexOverride != null;
1281
1415
  const isSupported = react.useMemo(
1282
1416
  () => isBazaarSupportedOnChain(chainId),
1283
1417
  [chainId]
@@ -1289,19 +1423,18 @@ function useBazaarListings({
1289
1423
  const filter = react.useMemo(
1290
1424
  () => ({
1291
1425
  appAddress: bazaarAddress,
1292
- topic: nftAddress.toLowerCase()
1426
+ topic: nftAddress.toLowerCase(),
1427
+ maker
1293
1428
  }),
1294
- [bazaarAddress, nftAddress]
1429
+ [bazaarAddress, nftAddress, maker]
1295
1430
  );
1296
1431
  const { count: totalCount, isLoading: isLoadingCount } = react$1.useNetMessageCount({
1297
1432
  chainId,
1298
1433
  filter,
1299
- enabled: enabled && isSupported
1434
+ enabled: enabled && isSupported && !hasRangeOverride
1300
1435
  });
1301
- const startIndex = react.useMemo(
1302
- () => Math.max(0, totalCount - maxMessages),
1303
- [totalCount, maxMessages]
1304
- );
1436
+ const startIndex = hasRangeOverride ? startIndexOverride : Math.max(0, totalCount - maxMessages);
1437
+ const endIndex = hasRangeOverride ? endIndexOverride : totalCount;
1305
1438
  const {
1306
1439
  messages,
1307
1440
  isLoading: isLoadingMessages,
@@ -1311,9 +1444,24 @@ function useBazaarListings({
1311
1444
  chainId,
1312
1445
  filter,
1313
1446
  startIndex,
1314
- endIndex: totalCount,
1315
- enabled: enabled && isSupported && totalCount > 0
1447
+ endIndex,
1448
+ enabled: enabled && isSupported && (hasRangeOverride || totalCount > 0)
1316
1449
  });
1450
+ const TAG = `[useBazaarListings chain=${chainId} nft=${nftAddress.slice(0, 10)}]`;
1451
+ react.useEffect(() => {
1452
+ console.log(TAG, {
1453
+ enabled,
1454
+ isSupported,
1455
+ hasRangeOverride,
1456
+ totalCount,
1457
+ isLoadingCount,
1458
+ startIndex,
1459
+ endIndex,
1460
+ messagesLength: messages?.length ?? 0,
1461
+ isLoadingMessages,
1462
+ messagesError: messagesError?.message
1463
+ });
1464
+ }, [enabled, isSupported, hasRangeOverride, totalCount, isLoadingCount, startIndex, endIndex, messages?.length, isLoadingMessages, messagesError]);
1317
1465
  react.useEffect(() => {
1318
1466
  if (!isSupported || !enabled) {
1319
1467
  setListings([]);
@@ -1327,17 +1475,19 @@ function useBazaarListings({
1327
1475
  async function processListings() {
1328
1476
  setIsProcessing(true);
1329
1477
  setProcessingError(void 0);
1478
+ console.log(TAG, `processing ${messages.length} messages...`);
1330
1479
  try {
1331
- const client = new BazaarClient({ chainId });
1332
- const validListings = await client.getListings({
1333
- nftAddress,
1334
- excludeMaker,
1335
- maxMessages
1336
- });
1480
+ const client = new BazaarClient({ chainId, publicClient: resolvedClient });
1481
+ const validListings = await client.processListingsFromMessages(
1482
+ messages,
1483
+ { nftAddress, excludeMaker, includeExpired }
1484
+ );
1485
+ console.log(TAG, `processed \u2192 ${validListings.length} valid listings`);
1337
1486
  if (!cancelled) {
1338
1487
  setListings(validListings);
1339
1488
  }
1340
1489
  } catch (err) {
1490
+ console.error(TAG, "processing error:", err);
1341
1491
  if (!cancelled) {
1342
1492
  setProcessingError(err instanceof Error ? err : new Error(String(err)));
1343
1493
  setListings([]);
@@ -1352,14 +1502,14 @@ function useBazaarListings({
1352
1502
  return () => {
1353
1503
  cancelled = true;
1354
1504
  };
1355
- }, [chainId, nftAddress, excludeMaker, maxMessages, messages, isSupported, enabled, refetchTrigger]);
1505
+ }, [chainId, nftAddress, excludeMaker, includeExpired, messages, isSupported, enabled, refetchTrigger]);
1356
1506
  const refetch = () => {
1357
1507
  refetchMessages();
1358
1508
  setRefetchTrigger((t) => t + 1);
1359
1509
  };
1360
1510
  return {
1361
1511
  listings,
1362
- isLoading: isLoadingCount || isLoadingMessages || isProcessing,
1512
+ isLoading: (hasRangeOverride ? false : isLoadingCount) || isLoadingMessages || isProcessing,
1363
1513
  error: messagesError || processingError,
1364
1514
  refetch
1365
1515
  };
@@ -1371,6 +1521,7 @@ function useBazaarCollectionOffers({
1371
1521
  maxMessages = 100,
1372
1522
  enabled = true
1373
1523
  }) {
1524
+ const wagmiClient = wagmi.usePublicClient({ chainId });
1374
1525
  const [offers, setOffers] = react.useState([]);
1375
1526
  const [isProcessing, setIsProcessing] = react.useState(false);
1376
1527
  const [processingError, setProcessingError] = react.useState();
@@ -1411,6 +1562,20 @@ function useBazaarCollectionOffers({
1411
1562
  endIndex: totalCount,
1412
1563
  enabled: enabled && isSupported && totalCount > 0
1413
1564
  });
1565
+ const TAG = `[useBazaarCollectionOffers chain=${chainId} nft=${nftAddress.slice(0, 10)}]`;
1566
+ react.useEffect(() => {
1567
+ console.log(TAG, {
1568
+ enabled,
1569
+ isSupported,
1570
+ totalCount,
1571
+ isLoadingCount,
1572
+ startIndex,
1573
+ endIndex: totalCount,
1574
+ messagesLength: messages?.length ?? 0,
1575
+ isLoadingMessages,
1576
+ messagesError: messagesError?.message
1577
+ });
1578
+ }, [enabled, isSupported, totalCount, isLoadingCount, startIndex, messages?.length, isLoadingMessages, messagesError]);
1414
1579
  react.useEffect(() => {
1415
1580
  if (!isSupported || !enabled) {
1416
1581
  setOffers([]);
@@ -1424,17 +1589,19 @@ function useBazaarCollectionOffers({
1424
1589
  async function processOffers() {
1425
1590
  setIsProcessing(true);
1426
1591
  setProcessingError(void 0);
1592
+ console.log(TAG, `processing ${messages.length} messages...`);
1427
1593
  try {
1428
- const client = new BazaarClient({ chainId });
1429
- const validOffers = await client.getCollectionOffers({
1430
- nftAddress,
1431
- excludeMaker,
1432
- maxMessages
1433
- });
1594
+ const client = new BazaarClient({ chainId, publicClient: wagmiClient });
1595
+ const validOffers = await client.processCollectionOffersFromMessages(
1596
+ messages,
1597
+ { nftAddress, excludeMaker }
1598
+ );
1599
+ console.log(TAG, `processed \u2192 ${validOffers.length} valid offers`);
1434
1600
  if (!cancelled) {
1435
1601
  setOffers(validOffers);
1436
1602
  }
1437
1603
  } catch (err) {
1604
+ console.error(TAG, "processing error:", err);
1438
1605
  if (!cancelled) {
1439
1606
  setProcessingError(err instanceof Error ? err : new Error(String(err)));
1440
1607
  setOffers([]);
@@ -1449,7 +1616,7 @@ function useBazaarCollectionOffers({
1449
1616
  return () => {
1450
1617
  cancelled = true;
1451
1618
  };
1452
- }, [chainId, nftAddress, excludeMaker, maxMessages, messages, isSupported, enabled, refetchTrigger]);
1619
+ }, [chainId, nftAddress, excludeMaker, messages, isSupported, enabled, refetchTrigger]);
1453
1620
  const refetch = () => {
1454
1621
  refetchMessages();
1455
1622
  setRefetchTrigger((t) => t + 1);
@@ -1468,6 +1635,7 @@ function useBazaarErc20Offers({
1468
1635
  maxMessages = 200,
1469
1636
  enabled = true
1470
1637
  }) {
1638
+ const wagmiClient = wagmi.usePublicClient({ chainId });
1471
1639
  const [offers, setOffers] = react.useState([]);
1472
1640
  const [isProcessing, setIsProcessing] = react.useState(false);
1473
1641
  const [processingError, setProcessingError] = react.useState();
@@ -1509,6 +1677,20 @@ function useBazaarErc20Offers({
1509
1677
  endIndex: totalCount,
1510
1678
  enabled: enabled && hasErc20Offers && totalCount > 0
1511
1679
  });
1680
+ const TAG = `[useBazaarErc20Offers chain=${chainId} token=${tokenAddress.slice(0, 10)}]`;
1681
+ react.useEffect(() => {
1682
+ console.log(TAG, {
1683
+ enabled,
1684
+ hasErc20Offers,
1685
+ totalCount,
1686
+ isLoadingCount,
1687
+ startIndex,
1688
+ endIndex: totalCount,
1689
+ messagesLength: messages?.length ?? 0,
1690
+ isLoadingMessages,
1691
+ messagesError: messagesError?.message
1692
+ });
1693
+ }, [enabled, hasErc20Offers, totalCount, isLoadingCount, startIndex, messages?.length, isLoadingMessages, messagesError]);
1512
1694
  react.useEffect(() => {
1513
1695
  if (!hasErc20Offers || !enabled) {
1514
1696
  setOffers([]);
@@ -1522,17 +1704,19 @@ function useBazaarErc20Offers({
1522
1704
  async function processOffers() {
1523
1705
  setIsProcessing(true);
1524
1706
  setProcessingError(void 0);
1707
+ console.log(TAG, `processing ${messages.length} messages...`);
1525
1708
  try {
1526
- const client = new BazaarClient({ chainId });
1527
- const validOffers = await client.getErc20Offers({
1528
- tokenAddress,
1529
- excludeMaker,
1530
- maxMessages
1531
- });
1709
+ const client = new BazaarClient({ chainId, publicClient: wagmiClient });
1710
+ const validOffers = await client.processErc20OffersFromMessages(
1711
+ messages,
1712
+ { tokenAddress, excludeMaker }
1713
+ );
1714
+ console.log(TAG, `processed \u2192 ${validOffers.length} valid offers`);
1532
1715
  if (!cancelled) {
1533
1716
  setOffers(validOffers);
1534
1717
  }
1535
1718
  } catch (err) {
1719
+ console.error(TAG, "processing error:", err);
1536
1720
  if (!cancelled) {
1537
1721
  setProcessingError(err instanceof Error ? err : new Error(String(err)));
1538
1722
  setOffers([]);
@@ -1547,7 +1731,7 @@ function useBazaarErc20Offers({
1547
1731
  return () => {
1548
1732
  cancelled = true;
1549
1733
  };
1550
- }, [chainId, tokenAddress, excludeMaker, maxMessages, messages, hasErc20Offers, enabled, refetchTrigger]);
1734
+ }, [chainId, tokenAddress, excludeMaker, messages, hasErc20Offers, enabled, refetchTrigger]);
1551
1735
  const refetch = () => {
1552
1736
  refetchMessages();
1553
1737
  setRefetchTrigger((t) => t + 1);
@@ -1563,13 +1747,20 @@ function useBazaarErc20Listings({
1563
1747
  chainId,
1564
1748
  tokenAddress,
1565
1749
  excludeMaker,
1750
+ maker,
1566
1751
  maxMessages = 200,
1567
- enabled = true
1752
+ startIndex: startIndexOverride,
1753
+ endIndex: endIndexOverride,
1754
+ enabled = true,
1755
+ publicClient
1568
1756
  }) {
1757
+ const wagmiClient = wagmi.usePublicClient({ chainId });
1758
+ const resolvedClient = publicClient ?? wagmiClient;
1569
1759
  const [listings, setListings] = react.useState([]);
1570
1760
  const [isProcessing, setIsProcessing] = react.useState(false);
1571
1761
  const [processingError, setProcessingError] = react.useState();
1572
1762
  const [refetchTrigger, setRefetchTrigger] = react.useState(0);
1763
+ const hasRangeOverride = startIndexOverride != null && endIndexOverride != null;
1573
1764
  const isSupported = react.useMemo(
1574
1765
  () => isBazaarSupportedOnChain(chainId),
1575
1766
  [chainId]
@@ -1581,19 +1772,18 @@ function useBazaarErc20Listings({
1581
1772
  const filter = react.useMemo(
1582
1773
  () => ({
1583
1774
  appAddress: erc20BazaarAddress,
1584
- topic: tokenAddress.toLowerCase()
1775
+ topic: tokenAddress.toLowerCase(),
1776
+ maker
1585
1777
  }),
1586
- [erc20BazaarAddress, tokenAddress]
1778
+ [erc20BazaarAddress, tokenAddress, maker]
1587
1779
  );
1588
1780
  const { count: totalCount, isLoading: isLoadingCount } = react$1.useNetMessageCount({
1589
1781
  chainId,
1590
1782
  filter,
1591
- enabled: enabled && isSupported
1783
+ enabled: enabled && isSupported && !hasRangeOverride
1592
1784
  });
1593
- const startIndex = react.useMemo(
1594
- () => Math.max(0, totalCount - maxMessages),
1595
- [totalCount, maxMessages]
1596
- );
1785
+ const startIndex = hasRangeOverride ? startIndexOverride : Math.max(0, totalCount - maxMessages);
1786
+ const endIndex = hasRangeOverride ? endIndexOverride : totalCount;
1597
1787
  const {
1598
1788
  messages,
1599
1789
  isLoading: isLoadingMessages,
@@ -1603,9 +1793,24 @@ function useBazaarErc20Listings({
1603
1793
  chainId,
1604
1794
  filter,
1605
1795
  startIndex,
1606
- endIndex: totalCount,
1607
- enabled: enabled && isSupported && totalCount > 0
1796
+ endIndex,
1797
+ enabled: enabled && isSupported && (hasRangeOverride || totalCount > 0)
1608
1798
  });
1799
+ const TAG = `[useBazaarErc20Listings chain=${chainId} token=${tokenAddress.slice(0, 10)}]`;
1800
+ react.useEffect(() => {
1801
+ console.log(TAG, {
1802
+ enabled,
1803
+ isSupported,
1804
+ hasRangeOverride,
1805
+ totalCount,
1806
+ isLoadingCount,
1807
+ startIndex,
1808
+ endIndex,
1809
+ messagesLength: messages?.length ?? 0,
1810
+ isLoadingMessages,
1811
+ messagesError: messagesError?.message
1812
+ });
1813
+ }, [enabled, isSupported, hasRangeOverride, totalCount, isLoadingCount, startIndex, endIndex, messages?.length, isLoadingMessages, messagesError]);
1609
1814
  react.useEffect(() => {
1610
1815
  if (!isSupported || !enabled) {
1611
1816
  setListings([]);
@@ -1619,17 +1824,19 @@ function useBazaarErc20Listings({
1619
1824
  async function processListings() {
1620
1825
  setIsProcessing(true);
1621
1826
  setProcessingError(void 0);
1827
+ console.log(TAG, `processing ${messages.length} messages...`);
1622
1828
  try {
1623
- const client = new BazaarClient({ chainId });
1624
- const validListings = await client.getErc20Listings({
1625
- tokenAddress,
1626
- excludeMaker,
1627
- maxMessages
1628
- });
1829
+ const client = new BazaarClient({ chainId, publicClient: resolvedClient });
1830
+ const validListings = await client.processErc20ListingsFromMessages(
1831
+ messages,
1832
+ { tokenAddress, excludeMaker }
1833
+ );
1834
+ console.log(TAG, `processed \u2192 ${validListings.length} valid listings`);
1629
1835
  if (!cancelled) {
1630
1836
  setListings(validListings);
1631
1837
  }
1632
1838
  } catch (err) {
1839
+ console.error(TAG, "processing error:", err);
1633
1840
  if (!cancelled) {
1634
1841
  setProcessingError(err instanceof Error ? err : new Error(String(err)));
1635
1842
  setListings([]);
@@ -1644,14 +1851,14 @@ function useBazaarErc20Listings({
1644
1851
  return () => {
1645
1852
  cancelled = true;
1646
1853
  };
1647
- }, [chainId, tokenAddress, excludeMaker, maxMessages, messages, isSupported, enabled, refetchTrigger]);
1854
+ }, [chainId, tokenAddress, excludeMaker, messages, isSupported, enabled, refetchTrigger]);
1648
1855
  const refetch = () => {
1649
1856
  refetchMessages();
1650
1857
  setRefetchTrigger((t) => t + 1);
1651
1858
  };
1652
1859
  return {
1653
1860
  listings,
1654
- isLoading: isLoadingCount || isLoadingMessages || isProcessing,
1861
+ isLoading: (hasRangeOverride ? false : isLoadingCount) || isLoadingMessages || isProcessing,
1655
1862
  error: messagesError || processingError,
1656
1863
  refetch
1657
1864
  };