@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 +51 -3
- package/dist/index.d.ts +51 -3
- package/dist/index.js +174 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +171 -1
- package/dist/index.mjs.map +1 -1
- package/dist/react.d.mts +63 -2
- package/dist/react.d.ts +63 -2
- package/dist/react.js +268 -0
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +268 -1
- package/dist/react.mjs.map +1 -1
- package/dist/{types-CY-6M9Ta.d.mts → types--4_RIuQ5.d.mts} +43 -1
- package/dist/{types-CY-6M9Ta.d.ts → types--4_RIuQ5.d.ts} +43 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -354,6 +354,7 @@ var DEFAULT_SEAPORT_ADDRESS = "0x0000000000000068F116a894984e2DB1123eB395";
|
|
|
354
354
|
var DEFAULT_BAZAAR_ADDRESS = "0x00000000E3dA5fC031282A39759bDDA78ae7fAE5";
|
|
355
355
|
var DEFAULT_COLLECTION_OFFERS_ADDRESS = "0x0000000D43423E0A12CecB307a74591999b32B32";
|
|
356
356
|
var DEFAULT_FEE_COLLECTOR_ADDRESS = "0x32D16C15410248bef498D7aF50D10Db1a546b9E5";
|
|
357
|
+
var DEFAULT_ERC20_BAZAAR_ADDRESS = "0x00000000a2d173a4610c85c7471a25b6bc216a70";
|
|
357
358
|
var DEFAULT_NFT_FEE_BPS = 500;
|
|
358
359
|
var BULK_SEAPORT_ORDER_STATUS_FETCHER_ADDRESS = "0x0000009112ABCE652674b4fE3eD9C765B22d11A7";
|
|
359
360
|
var ERC721_OWNER_OF_HELPER_ADDRESS = "0x000000aa4eFa2e5A4a6002C7F08B6e8Ec8cf1dDa";
|
|
@@ -366,6 +367,7 @@ var BAZAAR_CHAIN_CONFIGS = {
|
|
|
366
367
|
bazaarAddress: "0x000000058f3ade587388daf827174d0e6fc97595",
|
|
367
368
|
collectionOffersAddress: "0x0000000f9c45efcff0f78d8b54aa6a40092d66dc",
|
|
368
369
|
erc20OffersAddress: "0x0000000e23a89aa06f317306aa1ae231d3503082",
|
|
370
|
+
erc20BazaarAddress: "0x00000006557e3629e2fc50bbad0c002b27cac492",
|
|
369
371
|
seaportAddress: DEFAULT_SEAPORT_ADDRESS,
|
|
370
372
|
feeCollectorAddress: "0x66547ff4f7206e291F7BC157b54C026Fc6660961",
|
|
371
373
|
nftFeeBps: 0,
|
|
@@ -455,6 +457,7 @@ var BAZAAR_CHAIN_CONFIGS = {
|
|
|
455
457
|
bazaarAddress: "0x000000058f3ade587388daf827174d0e6fc97595",
|
|
456
458
|
collectionOffersAddress: "0x0000000f9c45efcff0f78d8b54aa6a40092d66dc",
|
|
457
459
|
erc20OffersAddress: "0x0000000e23a89aa06f317306aa1ae231d3503082",
|
|
460
|
+
erc20BazaarAddress: "0x00000006557e3629e2fc50bbad0c002b27cac492",
|
|
458
461
|
seaportAddress: DEFAULT_SEAPORT_ADDRESS,
|
|
459
462
|
feeCollectorAddress: "0x66547ff4f7206e291F7BC157b54C026Fc6660961",
|
|
460
463
|
nftFeeBps: 0,
|
|
@@ -531,6 +534,9 @@ function getHighEthAddress(chainId) {
|
|
|
531
534
|
function getErc20OffersAddress(chainId) {
|
|
532
535
|
return BAZAAR_CHAIN_CONFIGS[chainId]?.erc20OffersAddress;
|
|
533
536
|
}
|
|
537
|
+
function getErc20BazaarAddress(chainId) {
|
|
538
|
+
return BAZAAR_CHAIN_CONFIGS[chainId]?.erc20BazaarAddress ?? DEFAULT_ERC20_BAZAAR_ADDRESS;
|
|
539
|
+
}
|
|
534
540
|
function decodeSeaportSubmission(messageData) {
|
|
535
541
|
const [decoded] = decodeAbiParameters(BAZAAR_SUBMISSION_ABI, messageData);
|
|
536
542
|
return {
|
|
@@ -752,6 +758,19 @@ function isErc20OfferValid(orderStatus, expirationDate, priceWei, buyerWethBalan
|
|
|
752
758
|
}
|
|
753
759
|
return true;
|
|
754
760
|
}
|
|
761
|
+
function isErc20ListingValid(orderStatus, expirationDate, tokenAmount, sellerTokenBalance) {
|
|
762
|
+
if (orderStatus !== 2 /* OPEN */) {
|
|
763
|
+
return false;
|
|
764
|
+
}
|
|
765
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
766
|
+
if (expirationDate <= now) {
|
|
767
|
+
return false;
|
|
768
|
+
}
|
|
769
|
+
if (sellerTokenBalance < tokenAmount) {
|
|
770
|
+
return false;
|
|
771
|
+
}
|
|
772
|
+
return true;
|
|
773
|
+
}
|
|
755
774
|
|
|
756
775
|
// src/utils/parsing.ts
|
|
757
776
|
function parseListingFromMessage(message, chainId) {
|
|
@@ -921,6 +940,58 @@ function sortErc20OffersByPricePerToken(offers) {
|
|
|
921
940
|
return 0;
|
|
922
941
|
});
|
|
923
942
|
}
|
|
943
|
+
function parseErc20ListingFromMessage(message, chainId) {
|
|
944
|
+
try {
|
|
945
|
+
const submission = decodeSeaportSubmission(message.data);
|
|
946
|
+
const { parameters } = submission;
|
|
947
|
+
if (parameters.zone.toLowerCase() === NET_SEAPORT_COLLECTION_OFFER_ZONE_ADDRESS.toLowerCase()) {
|
|
948
|
+
return null;
|
|
949
|
+
}
|
|
950
|
+
const offerItem = parameters.offer[0];
|
|
951
|
+
if (!offerItem || offerItem.itemType !== 1 /* ERC20 */) {
|
|
952
|
+
return null;
|
|
953
|
+
}
|
|
954
|
+
const tokenAmount = offerItem.startAmount;
|
|
955
|
+
if (tokenAmount === BigInt(0)) {
|
|
956
|
+
return null;
|
|
957
|
+
}
|
|
958
|
+
const priceWei = getTotalConsiderationAmount(parameters);
|
|
959
|
+
if (priceWei === BigInt(0)) {
|
|
960
|
+
return null;
|
|
961
|
+
}
|
|
962
|
+
const pricePerTokenWei = priceWei / tokenAmount;
|
|
963
|
+
return {
|
|
964
|
+
maker: parameters.offerer,
|
|
965
|
+
tokenAddress: offerItem.token,
|
|
966
|
+
tokenAmount,
|
|
967
|
+
priceWei,
|
|
968
|
+
pricePerTokenWei,
|
|
969
|
+
price: formatPrice(priceWei),
|
|
970
|
+
pricePerToken: formatPrice(pricePerTokenWei),
|
|
971
|
+
currency: getCurrencySymbol(chainId),
|
|
972
|
+
expirationDate: Number(parameters.endTime),
|
|
973
|
+
orderHash: "0x",
|
|
974
|
+
// Will be computed later
|
|
975
|
+
orderStatus: 2 /* OPEN */,
|
|
976
|
+
// Will be validated later
|
|
977
|
+
messageData: message.data,
|
|
978
|
+
orderComponents: {
|
|
979
|
+
...parameters,
|
|
980
|
+
counter: submission.counter
|
|
981
|
+
}
|
|
982
|
+
};
|
|
983
|
+
} catch {
|
|
984
|
+
return null;
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
function sortErc20ListingsByPricePerToken(listings) {
|
|
988
|
+
return [...listings].sort((a, b) => {
|
|
989
|
+
const diff = a.pricePerTokenWei - b.pricePerTokenWei;
|
|
990
|
+
if (diff < BigInt(0)) return -1;
|
|
991
|
+
if (diff > BigInt(0)) return 1;
|
|
992
|
+
return 0;
|
|
993
|
+
});
|
|
994
|
+
}
|
|
924
995
|
|
|
925
996
|
// src/client/BazaarClient.ts
|
|
926
997
|
var CHAIN_RPC_URLS = {
|
|
@@ -1216,6 +1287,87 @@ var BazaarClient = class {
|
|
|
1216
1287
|
});
|
|
1217
1288
|
return sortErc20OffersByPricePerToken(offers);
|
|
1218
1289
|
}
|
|
1290
|
+
/**
|
|
1291
|
+
* Get valid ERC20 listings for a token
|
|
1292
|
+
*
|
|
1293
|
+
* Returns listings that are:
|
|
1294
|
+
* - OPEN status (not filled, cancelled, or expired)
|
|
1295
|
+
* - Not expired
|
|
1296
|
+
* - Seller has sufficient ERC20 token balance
|
|
1297
|
+
*
|
|
1298
|
+
* Results are sorted by price per token (lowest first). No deduplication —
|
|
1299
|
+
* all valid listings are returned (grouped by maker in the UI).
|
|
1300
|
+
*/
|
|
1301
|
+
async getErc20Listings(options) {
|
|
1302
|
+
const { tokenAddress, excludeMaker, maxMessages = 200 } = options;
|
|
1303
|
+
const erc20BazaarAddress = getErc20BazaarAddress(this.chainId);
|
|
1304
|
+
const count = await this.netClient.getMessageCount({
|
|
1305
|
+
filter: {
|
|
1306
|
+
appAddress: erc20BazaarAddress,
|
|
1307
|
+
topic: tokenAddress.toLowerCase()
|
|
1308
|
+
}
|
|
1309
|
+
});
|
|
1310
|
+
if (count === 0) {
|
|
1311
|
+
return [];
|
|
1312
|
+
}
|
|
1313
|
+
const startIndex = Math.max(0, count - maxMessages);
|
|
1314
|
+
const messages = await this.netClient.getMessages({
|
|
1315
|
+
filter: {
|
|
1316
|
+
appAddress: erc20BazaarAddress,
|
|
1317
|
+
topic: tokenAddress.toLowerCase()
|
|
1318
|
+
},
|
|
1319
|
+
startIndex,
|
|
1320
|
+
endIndex: count
|
|
1321
|
+
});
|
|
1322
|
+
let listings = [];
|
|
1323
|
+
for (const message of messages) {
|
|
1324
|
+
const listing = parseErc20ListingFromMessage(message, this.chainId);
|
|
1325
|
+
if (!listing) continue;
|
|
1326
|
+
if (listing.tokenAddress.toLowerCase() !== tokenAddress.toLowerCase()) {
|
|
1327
|
+
continue;
|
|
1328
|
+
}
|
|
1329
|
+
if (excludeMaker && listing.maker.toLowerCase() === excludeMaker.toLowerCase()) {
|
|
1330
|
+
continue;
|
|
1331
|
+
}
|
|
1332
|
+
listings.push(listing);
|
|
1333
|
+
}
|
|
1334
|
+
if (listings.length === 0) {
|
|
1335
|
+
return [];
|
|
1336
|
+
}
|
|
1337
|
+
const seaport = createSeaportInstance(this.chainId, this.rpcUrl);
|
|
1338
|
+
for (const listing of listings) {
|
|
1339
|
+
const order = getSeaportOrderFromMessageData(listing.messageData);
|
|
1340
|
+
listing.orderHash = computeOrderHash(seaport, order.parameters, order.counter);
|
|
1341
|
+
}
|
|
1342
|
+
const orderHashes = listings.map((l) => l.orderHash);
|
|
1343
|
+
const statusInfos = await bulkFetchOrderStatuses(this.client, this.chainId, orderHashes);
|
|
1344
|
+
listings.forEach((listing, index) => {
|
|
1345
|
+
const statusInfo = statusInfos[index];
|
|
1346
|
+
listing.orderStatus = getOrderStatusFromInfo(listing.orderComponents, statusInfo);
|
|
1347
|
+
});
|
|
1348
|
+
listings = listings.filter(
|
|
1349
|
+
(l) => l.orderStatus === 2 /* OPEN */ && l.expirationDate > Math.floor(Date.now() / 1e3)
|
|
1350
|
+
);
|
|
1351
|
+
if (listings.length === 0) {
|
|
1352
|
+
return [];
|
|
1353
|
+
}
|
|
1354
|
+
const uniqueMakers = [...new Set(listings.map((l) => l.maker))];
|
|
1355
|
+
const balances = await bulkFetchErc20Balances(this.client, tokenAddress, uniqueMakers);
|
|
1356
|
+
const balanceMap = /* @__PURE__ */ new Map();
|
|
1357
|
+
uniqueMakers.forEach((maker, index) => {
|
|
1358
|
+
balanceMap.set(maker.toLowerCase(), balances[index]);
|
|
1359
|
+
});
|
|
1360
|
+
listings = listings.filter((listing) => {
|
|
1361
|
+
const balance = balanceMap.get(listing.maker.toLowerCase()) || BigInt(0);
|
|
1362
|
+
return isErc20ListingValid(
|
|
1363
|
+
listing.orderStatus,
|
|
1364
|
+
listing.expirationDate,
|
|
1365
|
+
listing.tokenAmount,
|
|
1366
|
+
balance
|
|
1367
|
+
);
|
|
1368
|
+
});
|
|
1369
|
+
return sortErc20ListingsByPricePerToken(listings);
|
|
1370
|
+
}
|
|
1219
1371
|
/**
|
|
1220
1372
|
* Get the chain ID this client is configured for
|
|
1221
1373
|
*/
|
|
@@ -1241,6 +1393,12 @@ var BazaarClient = class {
|
|
|
1241
1393
|
getErc20OffersAddress() {
|
|
1242
1394
|
return getErc20OffersAddress(this.chainId);
|
|
1243
1395
|
}
|
|
1396
|
+
/**
|
|
1397
|
+
* Get the ERC20 bazaar (listings) contract address for this chain
|
|
1398
|
+
*/
|
|
1399
|
+
getErc20BazaarAddress() {
|
|
1400
|
+
return getErc20BazaarAddress(this.chainId);
|
|
1401
|
+
}
|
|
1244
1402
|
/**
|
|
1245
1403
|
* Get the Seaport contract address for this chain
|
|
1246
1404
|
*/
|
|
@@ -1271,6 +1429,18 @@ var BazaarClient = class {
|
|
|
1271
1429
|
}
|
|
1272
1430
|
return this.prepareCancelOrder(offer.orderComponents);
|
|
1273
1431
|
}
|
|
1432
|
+
/**
|
|
1433
|
+
* Prepare a transaction to cancel an ERC20 listing
|
|
1434
|
+
*
|
|
1435
|
+
* The listing must have been created by the caller.
|
|
1436
|
+
* Use the orderComponents from the Erc20Listing object returned by getErc20Listings().
|
|
1437
|
+
*/
|
|
1438
|
+
prepareCancelErc20Listing(listing) {
|
|
1439
|
+
if (!listing.orderComponents) {
|
|
1440
|
+
throw new Error("Listing does not have order components");
|
|
1441
|
+
}
|
|
1442
|
+
return this.prepareCancelOrder(listing.orderComponents);
|
|
1443
|
+
}
|
|
1274
1444
|
/**
|
|
1275
1445
|
* Prepare a transaction to cancel a Seaport order
|
|
1276
1446
|
*
|
|
@@ -1313,6 +1483,6 @@ var BazaarClient = class {
|
|
|
1313
1483
|
}
|
|
1314
1484
|
};
|
|
1315
1485
|
|
|
1316
|
-
export { BAZAAR_COLLECTION_OFFERS_ABI, BAZAAR_SUBMISSION_ABI, BAZAAR_V2_ABI, BULK_SEAPORT_ORDER_STATUS_FETCHER_ABI, BULK_SEAPORT_ORDER_STATUS_FETCHER_ADDRESS, BazaarClient, ERC20_BULK_BALANCE_CHECKER_ABI, ERC20_BULK_BALANCE_CHECKER_ADDRESS, ERC721_OWNER_OF_HELPER_ABI, ERC721_OWNER_OF_HELPER_ADDRESS, ItemType, NET_SEAPORT_COLLECTION_OFFER_ZONE_ADDRESS, NET_SEAPORT_ZONE_ADDRESS, OrderType, SEAPORT_CANCEL_ABI, SeaportOrderStatus, 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 };
|
|
1486
|
+
export { BAZAAR_COLLECTION_OFFERS_ABI, BAZAAR_SUBMISSION_ABI, BAZAAR_V2_ABI, BULK_SEAPORT_ORDER_STATUS_FETCHER_ABI, BULK_SEAPORT_ORDER_STATUS_FETCHER_ADDRESS, BazaarClient, ERC20_BULK_BALANCE_CHECKER_ABI, ERC20_BULK_BALANCE_CHECKER_ADDRESS, ERC721_OWNER_OF_HELPER_ABI, ERC721_OWNER_OF_HELPER_ADDRESS, ItemType, NET_SEAPORT_COLLECTION_OFFER_ZONE_ADDRESS, NET_SEAPORT_ZONE_ADDRESS, OrderType, SEAPORT_CANCEL_ABI, SeaportOrderStatus, 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 };
|
|
1317
1487
|
//# sourceMappingURL=index.mjs.map
|
|
1318
1488
|
//# sourceMappingURL=index.mjs.map
|