@net-protocol/bazaar 0.1.0 → 0.1.1

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.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { G as GetListingsOptions, L as Listing, a as GetCollectionOffersOptions, C as CollectionOffer, b as GetErc20OffersOptions, E as Erc20Offer, W as WriteTransactionConfig, S as SeaportOrderComponents, c as SeaportSubmission, d as SeaportOrderParameters, e as SeaportOrderStatusInfo, f as SeaportOrderStatus } from './types-CY-6M9Ta.mjs';
2
- export { h as ConsiderationItem, j as CreateCollectionOfferParams, i as CreateListingParams, I as ItemType, g as OfferItem, O as OrderType } from './types-CY-6M9Ta.mjs';
1
+ import { G as GetListingsOptions, L as Listing, a as GetCollectionOffersOptions, C as CollectionOffer, b as GetErc20OffersOptions, E as Erc20Offer, c as GetErc20ListingsOptions, d as Erc20Listing, W as WriteTransactionConfig, S as SeaportOrderComponents, e as SeaportSubmission, f as SeaportOrderParameters, g as SeaportOrderStatusInfo, h as SeaportOrderStatus } from './types--4_RIuQ5.mjs';
2
+ export { j as ConsiderationItem, l as CreateCollectionOfferParams, k as CreateListingParams, I as ItemType, i as OfferItem, O as OrderType } from './types--4_RIuQ5.mjs';
3
3
  import { Seaport } from '@opensea/seaport-js';
4
4
  import { PublicClient } from 'viem';
5
5
  import { NetMessage } from '@net-protocol/core';
@@ -56,6 +56,18 @@ declare class BazaarClient {
56
56
  * Results are sorted by price per token (highest first)
57
57
  */
58
58
  getErc20Offers(options: GetErc20OffersOptions): Promise<Erc20Offer[]>;
59
+ /**
60
+ * Get valid ERC20 listings for a token
61
+ *
62
+ * Returns listings that are:
63
+ * - OPEN status (not filled, cancelled, or expired)
64
+ * - Not expired
65
+ * - Seller has sufficient ERC20 token balance
66
+ *
67
+ * Results are sorted by price per token (lowest first). No deduplication —
68
+ * all valid listings are returned (grouped by maker in the UI).
69
+ */
70
+ getErc20Listings(options: GetErc20ListingsOptions): Promise<Erc20Listing[]>;
59
71
  /**
60
72
  * Get the chain ID this client is configured for
61
73
  */
@@ -73,6 +85,10 @@ declare class BazaarClient {
73
85
  * Only available on Base (8453) and HyperEVM (999)
74
86
  */
75
87
  getErc20OffersAddress(): `0x${string}` | undefined;
88
+ /**
89
+ * Get the ERC20 bazaar (listings) contract address for this chain
90
+ */
91
+ getErc20BazaarAddress(): `0x${string}`;
76
92
  /**
77
93
  * Get the Seaport contract address for this chain
78
94
  */
@@ -91,6 +107,13 @@ declare class BazaarClient {
91
107
  * Use the orderComponents from the CollectionOffer object returned by getCollectionOffers().
92
108
  */
93
109
  prepareCancelCollectionOffer(offer: CollectionOffer): WriteTransactionConfig;
110
+ /**
111
+ * Prepare a transaction to cancel an ERC20 listing
112
+ *
113
+ * The listing must have been created by the caller.
114
+ * Use the orderComponents from the Erc20Listing object returned by getErc20Listings().
115
+ */
116
+ prepareCancelErc20Listing(listing: Erc20Listing): WriteTransactionConfig;
94
117
  /**
95
118
  * Prepare a transaction to cancel a Seaport order
96
119
  *
@@ -116,6 +139,8 @@ interface BazaarChainConfig {
116
139
  collectionOffersAddress: `0x${string}`;
117
140
  /** ERC20 offers contract (only on Base and HyperEVM) */
118
141
  erc20OffersAddress?: `0x${string}`;
142
+ /** ERC20 listings contract */
143
+ erc20BazaarAddress?: `0x${string}`;
119
144
  /** Seaport contract address */
120
145
  seaportAddress: `0x${string}`;
121
146
  /** Fee collector address */
@@ -183,6 +208,10 @@ declare function getHighEthAddress(chainId: number): `0x${string}` | undefined;
183
208
  * Only deployed on Base (8453) and HyperEVM (999)
184
209
  */
185
210
  declare function getErc20OffersAddress(chainId: number): `0x${string}` | undefined;
211
+ /**
212
+ * Get ERC20 bazaar (listings) contract address for a chain
213
+ */
214
+ declare function getErc20BazaarAddress(chainId: number): `0x${string}`;
186
215
 
187
216
  declare const BAZAAR_V2_ABI: readonly [{
188
217
  readonly type: "function";
@@ -880,6 +909,13 @@ declare function isCollectionOfferValid(orderStatus: SeaportOrderStatus, expirat
880
909
  * - Buyer has sufficient WETH balance
881
910
  */
882
911
  declare function isErc20OfferValid(orderStatus: SeaportOrderStatus, expirationDate: number, priceWei: bigint, buyerWethBalance: bigint): boolean;
912
+ /**
913
+ * Validate that an ERC20 listing is still valid:
914
+ * - Order is OPEN
915
+ * - Not expired
916
+ * - Seller has sufficient ERC20 token balance
917
+ */
918
+ declare function isErc20ListingValid(orderStatus: SeaportOrderStatus, expirationDate: number, tokenAmount: bigint, sellerTokenBalance: bigint): boolean;
883
919
 
884
920
  /**
885
921
  * Utilities for parsing Net messages into listings and offers
@@ -917,5 +953,17 @@ declare function parseErc20OfferFromMessage(message: NetMessage, chainId: number
917
953
  * Sort ERC20 offers by price per token (highest first)
918
954
  */
919
955
  declare function sortErc20OffersByPricePerToken(offers: Erc20Offer[]): Erc20Offer[];
956
+ /**
957
+ * Parse a Net message into an ERC20 listing
958
+ *
959
+ * ERC20 listings have the ERC20 token in the offer array (seller is offering tokens)
960
+ * and native currency payments in the consideration array.
961
+ * They do NOT use the collection offer zone (that would be an offer, not a listing).
962
+ */
963
+ declare function parseErc20ListingFromMessage(message: NetMessage, chainId: number): Erc20Listing | null;
964
+ /**
965
+ * Sort ERC20 listings by price per token (lowest first)
966
+ */
967
+ declare function sortErc20ListingsByPricePerToken(listings: Erc20Listing[]): Erc20Listing[];
920
968
 
921
- export { BAZAAR_COLLECTION_OFFERS_ABI, BAZAAR_SUBMISSION_ABI, BAZAAR_V2_ABI, BULK_SEAPORT_ORDER_STATUS_FETCHER_ABI, BULK_SEAPORT_ORDER_STATUS_FETCHER_ADDRESS, type BazaarChainConfig, BazaarClient, CollectionOffer, ERC20_BULK_BALANCE_CHECKER_ABI, ERC20_BULK_BALANCE_CHECKER_ADDRESS, ERC721_OWNER_OF_HELPER_ABI, ERC721_OWNER_OF_HELPER_ADDRESS, Erc20Offer, GetCollectionOffersOptions, GetErc20OffersOptions, GetListingsOptions, Listing, NET_SEAPORT_COLLECTION_OFFER_ZONE_ADDRESS, NET_SEAPORT_ZONE_ADDRESS, SEAPORT_CANCEL_ABI, SeaportOrderComponents, SeaportOrderParameters, SeaportOrderStatus, SeaportOrderStatusInfo, SeaportSubmission, type WrappedNativeCurrency, WriteTransactionConfig, bulkFetchErc20Balances, bulkFetchNftOwners, bulkFetchOrderStatuses, computeOrderHash, createBalanceMap, createOrderStatusMap, createOwnershipMap, createSeaportInstance, decodeSeaportSubmission, formatPrice, getBazaarAddress, getBazaarChainConfig, getBazaarSupportedChainIds, getBestCollectionOffer, getBestListingPerToken, getCollectionOffersAddress, getCurrencySymbol, getErc20OffersAddress, getFeeCollectorAddress, getHighEthAddress, getNftFeeBps, getOrderStatusFromInfo, getSeaportAddress, getSeaportOrderFromMessageData, getTotalConsiderationAmount, getWrappedNativeCurrency, isBazaarSupportedOnChain, isCollectionOfferValid, isErc20OfferValid, isListingValid, parseCollectionOfferFromMessage, parseErc20OfferFromMessage, parseListingFromMessage, sortErc20OffersByPricePerToken, sortListingsByPrice, sortOffersByPrice };
969
+ export { BAZAAR_COLLECTION_OFFERS_ABI, BAZAAR_SUBMISSION_ABI, BAZAAR_V2_ABI, BULK_SEAPORT_ORDER_STATUS_FETCHER_ABI, BULK_SEAPORT_ORDER_STATUS_FETCHER_ADDRESS, type BazaarChainConfig, BazaarClient, CollectionOffer, ERC20_BULK_BALANCE_CHECKER_ABI, ERC20_BULK_BALANCE_CHECKER_ADDRESS, ERC721_OWNER_OF_HELPER_ABI, ERC721_OWNER_OF_HELPER_ADDRESS, Erc20Listing, Erc20Offer, GetCollectionOffersOptions, GetErc20ListingsOptions, GetErc20OffersOptions, GetListingsOptions, Listing, NET_SEAPORT_COLLECTION_OFFER_ZONE_ADDRESS, NET_SEAPORT_ZONE_ADDRESS, SEAPORT_CANCEL_ABI, SeaportOrderComponents, SeaportOrderParameters, SeaportOrderStatus, SeaportOrderStatusInfo, SeaportSubmission, type WrappedNativeCurrency, WriteTransactionConfig, bulkFetchErc20Balances, bulkFetchNftOwners, bulkFetchOrderStatuses, computeOrderHash, createBalanceMap, createOrderStatusMap, createOwnershipMap, createSeaportInstance, decodeSeaportSubmission, formatPrice, getBazaarAddress, getBazaarChainConfig, getBazaarSupportedChainIds, getBestCollectionOffer, getBestListingPerToken, getCollectionOffersAddress, getCurrencySymbol, getErc20BazaarAddress, getErc20OffersAddress, getFeeCollectorAddress, getHighEthAddress, getNftFeeBps, getOrderStatusFromInfo, getSeaportAddress, getSeaportOrderFromMessageData, getTotalConsiderationAmount, getWrappedNativeCurrency, isBazaarSupportedOnChain, isCollectionOfferValid, isErc20ListingValid, isErc20OfferValid, isListingValid, parseCollectionOfferFromMessage, parseErc20ListingFromMessage, parseErc20OfferFromMessage, parseListingFromMessage, sortErc20ListingsByPricePerToken, sortErc20OffersByPricePerToken, sortListingsByPrice, sortOffersByPrice };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { G as GetListingsOptions, L as Listing, a as GetCollectionOffersOptions, C as CollectionOffer, b as GetErc20OffersOptions, E as Erc20Offer, W as WriteTransactionConfig, S as SeaportOrderComponents, c as SeaportSubmission, d as SeaportOrderParameters, e as SeaportOrderStatusInfo, f as SeaportOrderStatus } from './types-CY-6M9Ta.js';
2
- export { h as ConsiderationItem, j as CreateCollectionOfferParams, i as CreateListingParams, I as ItemType, g as OfferItem, O as OrderType } from './types-CY-6M9Ta.js';
1
+ import { G as GetListingsOptions, L as Listing, a as GetCollectionOffersOptions, C as CollectionOffer, b as GetErc20OffersOptions, E as Erc20Offer, c as GetErc20ListingsOptions, d as Erc20Listing, W as WriteTransactionConfig, S as SeaportOrderComponents, e as SeaportSubmission, f as SeaportOrderParameters, g as SeaportOrderStatusInfo, h as SeaportOrderStatus } from './types--4_RIuQ5.js';
2
+ export { j as ConsiderationItem, l as CreateCollectionOfferParams, k as CreateListingParams, I as ItemType, i as OfferItem, O as OrderType } from './types--4_RIuQ5.js';
3
3
  import { Seaport } from '@opensea/seaport-js';
4
4
  import { PublicClient } from 'viem';
5
5
  import { NetMessage } from '@net-protocol/core';
@@ -56,6 +56,18 @@ declare class BazaarClient {
56
56
  * Results are sorted by price per token (highest first)
57
57
  */
58
58
  getErc20Offers(options: GetErc20OffersOptions): Promise<Erc20Offer[]>;
59
+ /**
60
+ * Get valid ERC20 listings for a token
61
+ *
62
+ * Returns listings that are:
63
+ * - OPEN status (not filled, cancelled, or expired)
64
+ * - Not expired
65
+ * - Seller has sufficient ERC20 token balance
66
+ *
67
+ * Results are sorted by price per token (lowest first). No deduplication —
68
+ * all valid listings are returned (grouped by maker in the UI).
69
+ */
70
+ getErc20Listings(options: GetErc20ListingsOptions): Promise<Erc20Listing[]>;
59
71
  /**
60
72
  * Get the chain ID this client is configured for
61
73
  */
@@ -73,6 +85,10 @@ declare class BazaarClient {
73
85
  * Only available on Base (8453) and HyperEVM (999)
74
86
  */
75
87
  getErc20OffersAddress(): `0x${string}` | undefined;
88
+ /**
89
+ * Get the ERC20 bazaar (listings) contract address for this chain
90
+ */
91
+ getErc20BazaarAddress(): `0x${string}`;
76
92
  /**
77
93
  * Get the Seaport contract address for this chain
78
94
  */
@@ -91,6 +107,13 @@ declare class BazaarClient {
91
107
  * Use the orderComponents from the CollectionOffer object returned by getCollectionOffers().
92
108
  */
93
109
  prepareCancelCollectionOffer(offer: CollectionOffer): WriteTransactionConfig;
110
+ /**
111
+ * Prepare a transaction to cancel an ERC20 listing
112
+ *
113
+ * The listing must have been created by the caller.
114
+ * Use the orderComponents from the Erc20Listing object returned by getErc20Listings().
115
+ */
116
+ prepareCancelErc20Listing(listing: Erc20Listing): WriteTransactionConfig;
94
117
  /**
95
118
  * Prepare a transaction to cancel a Seaport order
96
119
  *
@@ -116,6 +139,8 @@ interface BazaarChainConfig {
116
139
  collectionOffersAddress: `0x${string}`;
117
140
  /** ERC20 offers contract (only on Base and HyperEVM) */
118
141
  erc20OffersAddress?: `0x${string}`;
142
+ /** ERC20 listings contract */
143
+ erc20BazaarAddress?: `0x${string}`;
119
144
  /** Seaport contract address */
120
145
  seaportAddress: `0x${string}`;
121
146
  /** Fee collector address */
@@ -183,6 +208,10 @@ declare function getHighEthAddress(chainId: number): `0x${string}` | undefined;
183
208
  * Only deployed on Base (8453) and HyperEVM (999)
184
209
  */
185
210
  declare function getErc20OffersAddress(chainId: number): `0x${string}` | undefined;
211
+ /**
212
+ * Get ERC20 bazaar (listings) contract address for a chain
213
+ */
214
+ declare function getErc20BazaarAddress(chainId: number): `0x${string}`;
186
215
 
187
216
  declare const BAZAAR_V2_ABI: readonly [{
188
217
  readonly type: "function";
@@ -880,6 +909,13 @@ declare function isCollectionOfferValid(orderStatus: SeaportOrderStatus, expirat
880
909
  * - Buyer has sufficient WETH balance
881
910
  */
882
911
  declare function isErc20OfferValid(orderStatus: SeaportOrderStatus, expirationDate: number, priceWei: bigint, buyerWethBalance: bigint): boolean;
912
+ /**
913
+ * Validate that an ERC20 listing is still valid:
914
+ * - Order is OPEN
915
+ * - Not expired
916
+ * - Seller has sufficient ERC20 token balance
917
+ */
918
+ declare function isErc20ListingValid(orderStatus: SeaportOrderStatus, expirationDate: number, tokenAmount: bigint, sellerTokenBalance: bigint): boolean;
883
919
 
884
920
  /**
885
921
  * Utilities for parsing Net messages into listings and offers
@@ -917,5 +953,17 @@ declare function parseErc20OfferFromMessage(message: NetMessage, chainId: number
917
953
  * Sort ERC20 offers by price per token (highest first)
918
954
  */
919
955
  declare function sortErc20OffersByPricePerToken(offers: Erc20Offer[]): Erc20Offer[];
956
+ /**
957
+ * Parse a Net message into an ERC20 listing
958
+ *
959
+ * ERC20 listings have the ERC20 token in the offer array (seller is offering tokens)
960
+ * and native currency payments in the consideration array.
961
+ * They do NOT use the collection offer zone (that would be an offer, not a listing).
962
+ */
963
+ declare function parseErc20ListingFromMessage(message: NetMessage, chainId: number): Erc20Listing | null;
964
+ /**
965
+ * Sort ERC20 listings by price per token (lowest first)
966
+ */
967
+ declare function sortErc20ListingsByPricePerToken(listings: Erc20Listing[]): Erc20Listing[];
920
968
 
921
- export { BAZAAR_COLLECTION_OFFERS_ABI, BAZAAR_SUBMISSION_ABI, BAZAAR_V2_ABI, BULK_SEAPORT_ORDER_STATUS_FETCHER_ABI, BULK_SEAPORT_ORDER_STATUS_FETCHER_ADDRESS, type BazaarChainConfig, BazaarClient, CollectionOffer, ERC20_BULK_BALANCE_CHECKER_ABI, ERC20_BULK_BALANCE_CHECKER_ADDRESS, ERC721_OWNER_OF_HELPER_ABI, ERC721_OWNER_OF_HELPER_ADDRESS, Erc20Offer, GetCollectionOffersOptions, GetErc20OffersOptions, GetListingsOptions, Listing, NET_SEAPORT_COLLECTION_OFFER_ZONE_ADDRESS, NET_SEAPORT_ZONE_ADDRESS, SEAPORT_CANCEL_ABI, SeaportOrderComponents, SeaportOrderParameters, SeaportOrderStatus, SeaportOrderStatusInfo, SeaportSubmission, type WrappedNativeCurrency, WriteTransactionConfig, bulkFetchErc20Balances, bulkFetchNftOwners, bulkFetchOrderStatuses, computeOrderHash, createBalanceMap, createOrderStatusMap, createOwnershipMap, createSeaportInstance, decodeSeaportSubmission, formatPrice, getBazaarAddress, getBazaarChainConfig, getBazaarSupportedChainIds, getBestCollectionOffer, getBestListingPerToken, getCollectionOffersAddress, getCurrencySymbol, getErc20OffersAddress, getFeeCollectorAddress, getHighEthAddress, getNftFeeBps, getOrderStatusFromInfo, getSeaportAddress, getSeaportOrderFromMessageData, getTotalConsiderationAmount, getWrappedNativeCurrency, isBazaarSupportedOnChain, isCollectionOfferValid, isErc20OfferValid, isListingValid, parseCollectionOfferFromMessage, parseErc20OfferFromMessage, parseListingFromMessage, sortErc20OffersByPricePerToken, sortListingsByPrice, sortOffersByPrice };
969
+ export { BAZAAR_COLLECTION_OFFERS_ABI, BAZAAR_SUBMISSION_ABI, BAZAAR_V2_ABI, BULK_SEAPORT_ORDER_STATUS_FETCHER_ABI, BULK_SEAPORT_ORDER_STATUS_FETCHER_ADDRESS, type BazaarChainConfig, BazaarClient, CollectionOffer, ERC20_BULK_BALANCE_CHECKER_ABI, ERC20_BULK_BALANCE_CHECKER_ADDRESS, ERC721_OWNER_OF_HELPER_ABI, ERC721_OWNER_OF_HELPER_ADDRESS, Erc20Listing, Erc20Offer, GetCollectionOffersOptions, GetErc20ListingsOptions, GetErc20OffersOptions, GetListingsOptions, Listing, NET_SEAPORT_COLLECTION_OFFER_ZONE_ADDRESS, NET_SEAPORT_ZONE_ADDRESS, SEAPORT_CANCEL_ABI, SeaportOrderComponents, SeaportOrderParameters, SeaportOrderStatus, SeaportOrderStatusInfo, SeaportSubmission, type WrappedNativeCurrency, WriteTransactionConfig, bulkFetchErc20Balances, bulkFetchNftOwners, bulkFetchOrderStatuses, computeOrderHash, createBalanceMap, createOrderStatusMap, createOwnershipMap, createSeaportInstance, decodeSeaportSubmission, formatPrice, getBazaarAddress, getBazaarChainConfig, getBazaarSupportedChainIds, getBestCollectionOffer, getBestListingPerToken, getCollectionOffersAddress, getCurrencySymbol, getErc20BazaarAddress, getErc20OffersAddress, getFeeCollectorAddress, getHighEthAddress, getNftFeeBps, getOrderStatusFromInfo, getSeaportAddress, getSeaportOrderFromMessageData, getTotalConsiderationAmount, getWrappedNativeCurrency, isBazaarSupportedOnChain, isCollectionOfferValid, isErc20ListingValid, isErc20OfferValid, isListingValid, parseCollectionOfferFromMessage, parseErc20ListingFromMessage, parseErc20OfferFromMessage, parseListingFromMessage, sortErc20ListingsByPricePerToken, sortErc20OffersByPricePerToken, sortListingsByPrice, sortOffersByPrice };
package/dist/index.js CHANGED
@@ -356,6 +356,7 @@ var DEFAULT_SEAPORT_ADDRESS = "0x0000000000000068F116a894984e2DB1123eB395";
356
356
  var DEFAULT_BAZAAR_ADDRESS = "0x00000000E3dA5fC031282A39759bDDA78ae7fAE5";
357
357
  var DEFAULT_COLLECTION_OFFERS_ADDRESS = "0x0000000D43423E0A12CecB307a74591999b32B32";
358
358
  var DEFAULT_FEE_COLLECTOR_ADDRESS = "0x32D16C15410248bef498D7aF50D10Db1a546b9E5";
359
+ var DEFAULT_ERC20_BAZAAR_ADDRESS = "0x00000000a2d173a4610c85c7471a25b6bc216a70";
359
360
  var DEFAULT_NFT_FEE_BPS = 500;
360
361
  var BULK_SEAPORT_ORDER_STATUS_FETCHER_ADDRESS = "0x0000009112ABCE652674b4fE3eD9C765B22d11A7";
361
362
  var ERC721_OWNER_OF_HELPER_ADDRESS = "0x000000aa4eFa2e5A4a6002C7F08B6e8Ec8cf1dDa";
@@ -368,6 +369,7 @@ var BAZAAR_CHAIN_CONFIGS = {
368
369
  bazaarAddress: "0x000000058f3ade587388daf827174d0e6fc97595",
369
370
  collectionOffersAddress: "0x0000000f9c45efcff0f78d8b54aa6a40092d66dc",
370
371
  erc20OffersAddress: "0x0000000e23a89aa06f317306aa1ae231d3503082",
372
+ erc20BazaarAddress: "0x00000006557e3629e2fc50bbad0c002b27cac492",
371
373
  seaportAddress: DEFAULT_SEAPORT_ADDRESS,
372
374
  feeCollectorAddress: "0x66547ff4f7206e291F7BC157b54C026Fc6660961",
373
375
  nftFeeBps: 0,
@@ -457,6 +459,7 @@ var BAZAAR_CHAIN_CONFIGS = {
457
459
  bazaarAddress: "0x000000058f3ade587388daf827174d0e6fc97595",
458
460
  collectionOffersAddress: "0x0000000f9c45efcff0f78d8b54aa6a40092d66dc",
459
461
  erc20OffersAddress: "0x0000000e23a89aa06f317306aa1ae231d3503082",
462
+ erc20BazaarAddress: "0x00000006557e3629e2fc50bbad0c002b27cac492",
460
463
  seaportAddress: DEFAULT_SEAPORT_ADDRESS,
461
464
  feeCollectorAddress: "0x66547ff4f7206e291F7BC157b54C026Fc6660961",
462
465
  nftFeeBps: 0,
@@ -533,6 +536,9 @@ function getHighEthAddress(chainId) {
533
536
  function getErc20OffersAddress(chainId) {
534
537
  return BAZAAR_CHAIN_CONFIGS[chainId]?.erc20OffersAddress;
535
538
  }
539
+ function getErc20BazaarAddress(chainId) {
540
+ return BAZAAR_CHAIN_CONFIGS[chainId]?.erc20BazaarAddress ?? DEFAULT_ERC20_BAZAAR_ADDRESS;
541
+ }
536
542
  function decodeSeaportSubmission(messageData) {
537
543
  const [decoded] = viem.decodeAbiParameters(BAZAAR_SUBMISSION_ABI, messageData);
538
544
  return {
@@ -754,6 +760,19 @@ function isErc20OfferValid(orderStatus, expirationDate, priceWei, buyerWethBalan
754
760
  }
755
761
  return true;
756
762
  }
763
+ function isErc20ListingValid(orderStatus, expirationDate, tokenAmount, sellerTokenBalance) {
764
+ if (orderStatus !== 2 /* OPEN */) {
765
+ return false;
766
+ }
767
+ const now = Math.floor(Date.now() / 1e3);
768
+ if (expirationDate <= now) {
769
+ return false;
770
+ }
771
+ if (sellerTokenBalance < tokenAmount) {
772
+ return false;
773
+ }
774
+ return true;
775
+ }
757
776
 
758
777
  // src/utils/parsing.ts
759
778
  function parseListingFromMessage(message, chainId) {
@@ -923,6 +942,58 @@ function sortErc20OffersByPricePerToken(offers) {
923
942
  return 0;
924
943
  });
925
944
  }
945
+ function parseErc20ListingFromMessage(message, chainId) {
946
+ try {
947
+ const submission = decodeSeaportSubmission(message.data);
948
+ const { parameters } = submission;
949
+ if (parameters.zone.toLowerCase() === NET_SEAPORT_COLLECTION_OFFER_ZONE_ADDRESS.toLowerCase()) {
950
+ return null;
951
+ }
952
+ const offerItem = parameters.offer[0];
953
+ if (!offerItem || offerItem.itemType !== 1 /* ERC20 */) {
954
+ return null;
955
+ }
956
+ const tokenAmount = offerItem.startAmount;
957
+ if (tokenAmount === BigInt(0)) {
958
+ return null;
959
+ }
960
+ const priceWei = getTotalConsiderationAmount(parameters);
961
+ if (priceWei === BigInt(0)) {
962
+ return null;
963
+ }
964
+ const pricePerTokenWei = priceWei / tokenAmount;
965
+ return {
966
+ maker: parameters.offerer,
967
+ tokenAddress: offerItem.token,
968
+ tokenAmount,
969
+ priceWei,
970
+ pricePerTokenWei,
971
+ price: formatPrice(priceWei),
972
+ pricePerToken: formatPrice(pricePerTokenWei),
973
+ currency: getCurrencySymbol(chainId),
974
+ expirationDate: Number(parameters.endTime),
975
+ orderHash: "0x",
976
+ // Will be computed later
977
+ orderStatus: 2 /* OPEN */,
978
+ // Will be validated later
979
+ messageData: message.data,
980
+ orderComponents: {
981
+ ...parameters,
982
+ counter: submission.counter
983
+ }
984
+ };
985
+ } catch {
986
+ return null;
987
+ }
988
+ }
989
+ function sortErc20ListingsByPricePerToken(listings) {
990
+ return [...listings].sort((a, b) => {
991
+ const diff = a.pricePerTokenWei - b.pricePerTokenWei;
992
+ if (diff < BigInt(0)) return -1;
993
+ if (diff > BigInt(0)) return 1;
994
+ return 0;
995
+ });
996
+ }
926
997
 
927
998
  // src/client/BazaarClient.ts
928
999
  var CHAIN_RPC_URLS = {
@@ -1218,6 +1289,87 @@ var BazaarClient = class {
1218
1289
  });
1219
1290
  return sortErc20OffersByPricePerToken(offers);
1220
1291
  }
1292
+ /**
1293
+ * Get valid ERC20 listings for a token
1294
+ *
1295
+ * Returns listings that are:
1296
+ * - OPEN status (not filled, cancelled, or expired)
1297
+ * - Not expired
1298
+ * - Seller has sufficient ERC20 token balance
1299
+ *
1300
+ * Results are sorted by price per token (lowest first). No deduplication —
1301
+ * all valid listings are returned (grouped by maker in the UI).
1302
+ */
1303
+ async getErc20Listings(options) {
1304
+ const { tokenAddress, excludeMaker, maxMessages = 200 } = options;
1305
+ const erc20BazaarAddress = getErc20BazaarAddress(this.chainId);
1306
+ const count = await this.netClient.getMessageCount({
1307
+ filter: {
1308
+ appAddress: erc20BazaarAddress,
1309
+ topic: tokenAddress.toLowerCase()
1310
+ }
1311
+ });
1312
+ if (count === 0) {
1313
+ return [];
1314
+ }
1315
+ const startIndex = Math.max(0, count - maxMessages);
1316
+ const messages = await this.netClient.getMessages({
1317
+ filter: {
1318
+ appAddress: erc20BazaarAddress,
1319
+ topic: tokenAddress.toLowerCase()
1320
+ },
1321
+ startIndex,
1322
+ endIndex: count
1323
+ });
1324
+ let listings = [];
1325
+ for (const message of messages) {
1326
+ const listing = parseErc20ListingFromMessage(message, this.chainId);
1327
+ if (!listing) continue;
1328
+ if (listing.tokenAddress.toLowerCase() !== tokenAddress.toLowerCase()) {
1329
+ continue;
1330
+ }
1331
+ if (excludeMaker && listing.maker.toLowerCase() === excludeMaker.toLowerCase()) {
1332
+ continue;
1333
+ }
1334
+ listings.push(listing);
1335
+ }
1336
+ if (listings.length === 0) {
1337
+ return [];
1338
+ }
1339
+ const seaport = createSeaportInstance(this.chainId, this.rpcUrl);
1340
+ for (const listing of listings) {
1341
+ const order = getSeaportOrderFromMessageData(listing.messageData);
1342
+ listing.orderHash = computeOrderHash(seaport, order.parameters, order.counter);
1343
+ }
1344
+ const orderHashes = listings.map((l) => l.orderHash);
1345
+ const statusInfos = await bulkFetchOrderStatuses(this.client, this.chainId, orderHashes);
1346
+ listings.forEach((listing, index) => {
1347
+ const statusInfo = statusInfos[index];
1348
+ listing.orderStatus = getOrderStatusFromInfo(listing.orderComponents, statusInfo);
1349
+ });
1350
+ listings = listings.filter(
1351
+ (l) => l.orderStatus === 2 /* OPEN */ && l.expirationDate > Math.floor(Date.now() / 1e3)
1352
+ );
1353
+ if (listings.length === 0) {
1354
+ return [];
1355
+ }
1356
+ const uniqueMakers = [...new Set(listings.map((l) => l.maker))];
1357
+ const balances = await bulkFetchErc20Balances(this.client, tokenAddress, uniqueMakers);
1358
+ const balanceMap = /* @__PURE__ */ new Map();
1359
+ uniqueMakers.forEach((maker, index) => {
1360
+ balanceMap.set(maker.toLowerCase(), balances[index]);
1361
+ });
1362
+ listings = listings.filter((listing) => {
1363
+ const balance = balanceMap.get(listing.maker.toLowerCase()) || BigInt(0);
1364
+ return isErc20ListingValid(
1365
+ listing.orderStatus,
1366
+ listing.expirationDate,
1367
+ listing.tokenAmount,
1368
+ balance
1369
+ );
1370
+ });
1371
+ return sortErc20ListingsByPricePerToken(listings);
1372
+ }
1221
1373
  /**
1222
1374
  * Get the chain ID this client is configured for
1223
1375
  */
@@ -1243,6 +1395,12 @@ var BazaarClient = class {
1243
1395
  getErc20OffersAddress() {
1244
1396
  return getErc20OffersAddress(this.chainId);
1245
1397
  }
1398
+ /**
1399
+ * Get the ERC20 bazaar (listings) contract address for this chain
1400
+ */
1401
+ getErc20BazaarAddress() {
1402
+ return getErc20BazaarAddress(this.chainId);
1403
+ }
1246
1404
  /**
1247
1405
  * Get the Seaport contract address for this chain
1248
1406
  */
@@ -1273,6 +1431,18 @@ var BazaarClient = class {
1273
1431
  }
1274
1432
  return this.prepareCancelOrder(offer.orderComponents);
1275
1433
  }
1434
+ /**
1435
+ * Prepare a transaction to cancel an ERC20 listing
1436
+ *
1437
+ * The listing must have been created by the caller.
1438
+ * Use the orderComponents from the Erc20Listing object returned by getErc20Listings().
1439
+ */
1440
+ prepareCancelErc20Listing(listing) {
1441
+ if (!listing.orderComponents) {
1442
+ throw new Error("Listing does not have order components");
1443
+ }
1444
+ return this.prepareCancelOrder(listing.orderComponents);
1445
+ }
1276
1446
  /**
1277
1447
  * Prepare a transaction to cancel a Seaport order
1278
1448
  *
@@ -1348,6 +1518,7 @@ exports.getBestCollectionOffer = getBestCollectionOffer;
1348
1518
  exports.getBestListingPerToken = getBestListingPerToken;
1349
1519
  exports.getCollectionOffersAddress = getCollectionOffersAddress;
1350
1520
  exports.getCurrencySymbol = getCurrencySymbol;
1521
+ exports.getErc20BazaarAddress = getErc20BazaarAddress;
1351
1522
  exports.getErc20OffersAddress = getErc20OffersAddress;
1352
1523
  exports.getFeeCollectorAddress = getFeeCollectorAddress;
1353
1524
  exports.getHighEthAddress = getHighEthAddress;
@@ -1359,11 +1530,14 @@ exports.getTotalConsiderationAmount = getTotalConsiderationAmount;
1359
1530
  exports.getWrappedNativeCurrency = getWrappedNativeCurrency;
1360
1531
  exports.isBazaarSupportedOnChain = isBazaarSupportedOnChain;
1361
1532
  exports.isCollectionOfferValid = isCollectionOfferValid;
1533
+ exports.isErc20ListingValid = isErc20ListingValid;
1362
1534
  exports.isErc20OfferValid = isErc20OfferValid;
1363
1535
  exports.isListingValid = isListingValid;
1364
1536
  exports.parseCollectionOfferFromMessage = parseCollectionOfferFromMessage;
1537
+ exports.parseErc20ListingFromMessage = parseErc20ListingFromMessage;
1365
1538
  exports.parseErc20OfferFromMessage = parseErc20OfferFromMessage;
1366
1539
  exports.parseListingFromMessage = parseListingFromMessage;
1540
+ exports.sortErc20ListingsByPricePerToken = sortErc20ListingsByPricePerToken;
1367
1541
  exports.sortErc20OffersByPricePerToken = sortErc20OffersByPricePerToken;
1368
1542
  exports.sortListingsByPrice = sortListingsByPrice;
1369
1543
  exports.sortOffersByPrice = sortOffersByPrice;