@net-protocol/bazaar 0.1.6 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  'use strict';
2
2
 
3
3
  var viem = require('viem');
4
+ var actions = require('viem/actions');
4
5
  var core = require('@net-protocol/core');
5
6
  var seaportJs = require('@opensea/seaport-js');
6
7
  var ethers = require('ethers');
7
- var actions = require('viem/actions');
8
8
  var storage = require('@net-protocol/storage');
9
9
 
10
10
  // src/client/BazaarClient.ts
@@ -187,6 +187,66 @@ var BAZAAR_COLLECTION_OFFERS_ABI = [
187
187
  { type: "error", name: "InvalidFee", inputs: [] },
188
188
  { type: "error", name: "OfferItemsMustContainOneItem", inputs: [] }
189
189
  ];
190
+ var BAZAAR_ERC20_OFFERS_ABI = [
191
+ {
192
+ type: "function",
193
+ name: "submit",
194
+ inputs: [
195
+ {
196
+ name: "submission",
197
+ type: "tuple",
198
+ internalType: "struct BazaarV2CollectionOffers.Submission",
199
+ components: [
200
+ {
201
+ name: "parameters",
202
+ type: "tuple",
203
+ internalType: "struct OrderParameters",
204
+ components: [
205
+ { name: "offerer", type: "address", internalType: "address" },
206
+ { name: "zone", type: "address", internalType: "address" },
207
+ {
208
+ name: "offer",
209
+ type: "tuple[]",
210
+ internalType: "struct OfferItem[]",
211
+ components: [
212
+ { name: "itemType", type: "uint8", internalType: "enum ItemType" },
213
+ { name: "token", type: "address", internalType: "address" },
214
+ { name: "identifierOrCriteria", type: "uint256", internalType: "uint256" },
215
+ { name: "startAmount", type: "uint256", internalType: "uint256" },
216
+ { name: "endAmount", type: "uint256", internalType: "uint256" }
217
+ ]
218
+ },
219
+ {
220
+ name: "consideration",
221
+ type: "tuple[]",
222
+ internalType: "struct ConsiderationItem[]",
223
+ components: [
224
+ { name: "itemType", type: "uint8", internalType: "enum ItemType" },
225
+ { name: "token", type: "address", internalType: "address" },
226
+ { name: "identifierOrCriteria", type: "uint256", internalType: "uint256" },
227
+ { name: "startAmount", type: "uint256", internalType: "uint256" },
228
+ { name: "endAmount", type: "uint256", internalType: "uint256" },
229
+ { name: "recipient", type: "address", internalType: "address payable" }
230
+ ]
231
+ },
232
+ { name: "orderType", type: "uint8", internalType: "enum OrderType" },
233
+ { name: "startTime", type: "uint256", internalType: "uint256" },
234
+ { name: "endTime", type: "uint256", internalType: "uint256" },
235
+ { name: "zoneHash", type: "bytes32", internalType: "bytes32" },
236
+ { name: "salt", type: "uint256", internalType: "uint256" },
237
+ { name: "conduitKey", type: "bytes32", internalType: "bytes32" },
238
+ { name: "totalOriginalConsiderationItems", type: "uint256", internalType: "uint256" }
239
+ ]
240
+ },
241
+ { name: "counter", type: "uint256", internalType: "uint256" },
242
+ { name: "signature", type: "bytes", internalType: "bytes" }
243
+ ]
244
+ }
245
+ ],
246
+ outputs: [],
247
+ stateMutability: "nonpayable"
248
+ }
249
+ ];
190
250
 
191
251
  // src/abis/helpers.ts
192
252
  var BULK_SEAPORT_ORDER_STATUS_FETCHER_ABI = [
@@ -297,6 +357,161 @@ var SEAPORT_CANCEL_ABI = [
297
357
  type: "function"
298
358
  }
299
359
  ];
360
+ var ORDER_PARAMETERS_COMPONENTS = [
361
+ { internalType: "address", name: "offerer", type: "address" },
362
+ { internalType: "address", name: "zone", type: "address" },
363
+ {
364
+ components: [
365
+ { internalType: "enum ItemType", name: "itemType", type: "uint8" },
366
+ { internalType: "address", name: "token", type: "address" },
367
+ { internalType: "uint256", name: "identifierOrCriteria", type: "uint256" },
368
+ { internalType: "uint256", name: "startAmount", type: "uint256" },
369
+ { internalType: "uint256", name: "endAmount", type: "uint256" }
370
+ ],
371
+ internalType: "struct OfferItem[]",
372
+ name: "offer",
373
+ type: "tuple[]"
374
+ },
375
+ {
376
+ components: [
377
+ { internalType: "enum ItemType", name: "itemType", type: "uint8" },
378
+ { internalType: "address", name: "token", type: "address" },
379
+ { internalType: "uint256", name: "identifierOrCriteria", type: "uint256" },
380
+ { internalType: "uint256", name: "startAmount", type: "uint256" },
381
+ { internalType: "uint256", name: "endAmount", type: "uint256" },
382
+ { internalType: "address payable", name: "recipient", type: "address" }
383
+ ],
384
+ internalType: "struct ConsiderationItem[]",
385
+ name: "consideration",
386
+ type: "tuple[]"
387
+ },
388
+ { internalType: "enum OrderType", name: "orderType", type: "uint8" },
389
+ { internalType: "uint256", name: "startTime", type: "uint256" },
390
+ { internalType: "uint256", name: "endTime", type: "uint256" },
391
+ { internalType: "bytes32", name: "zoneHash", type: "bytes32" },
392
+ { internalType: "uint256", name: "salt", type: "uint256" },
393
+ { internalType: "bytes32", name: "conduitKey", type: "bytes32" },
394
+ { internalType: "uint256", name: "totalOriginalConsiderationItems", type: "uint256" }
395
+ ];
396
+ var SEAPORT_FULFILL_ORDER_ABI = [
397
+ {
398
+ inputs: [
399
+ {
400
+ components: [
401
+ {
402
+ components: ORDER_PARAMETERS_COMPONENTS,
403
+ internalType: "struct OrderParameters",
404
+ name: "parameters",
405
+ type: "tuple"
406
+ },
407
+ { internalType: "bytes", name: "signature", type: "bytes" }
408
+ ],
409
+ internalType: "struct Order",
410
+ name: "",
411
+ type: "tuple"
412
+ },
413
+ { internalType: "bytes32", name: "fulfillerConduitKey", type: "bytes32" }
414
+ ],
415
+ name: "fulfillOrder",
416
+ outputs: [{ internalType: "bool", name: "fulfilled", type: "bool" }],
417
+ stateMutability: "payable",
418
+ type: "function"
419
+ }
420
+ ];
421
+ var SEAPORT_FULFILL_ADVANCED_ORDER_ABI = [
422
+ {
423
+ inputs: [
424
+ {
425
+ components: [
426
+ {
427
+ components: ORDER_PARAMETERS_COMPONENTS,
428
+ internalType: "struct OrderParameters",
429
+ name: "parameters",
430
+ type: "tuple"
431
+ },
432
+ { internalType: "uint120", name: "numerator", type: "uint120" },
433
+ { internalType: "uint120", name: "denominator", type: "uint120" },
434
+ { internalType: "bytes", name: "signature", type: "bytes" },
435
+ { internalType: "bytes", name: "extraData", type: "bytes" }
436
+ ],
437
+ internalType: "struct AdvancedOrder",
438
+ name: "",
439
+ type: "tuple"
440
+ },
441
+ {
442
+ components: [
443
+ { internalType: "uint256", name: "orderIndex", type: "uint256" },
444
+ { internalType: "enum Side", name: "side", type: "uint8" },
445
+ { internalType: "uint256", name: "index", type: "uint256" },
446
+ { internalType: "uint256", name: "identifier", type: "uint256" },
447
+ { internalType: "bytes32[]", name: "criteriaProof", type: "bytes32[]" }
448
+ ],
449
+ internalType: "struct CriteriaResolver[]",
450
+ name: "",
451
+ type: "tuple[]"
452
+ },
453
+ { internalType: "bytes32", name: "fulfillerConduitKey", type: "bytes32" },
454
+ { internalType: "address", name: "recipient", type: "address" }
455
+ ],
456
+ name: "fulfillAdvancedOrder",
457
+ outputs: [{ internalType: "bool", name: "fulfilled", type: "bool" }],
458
+ stateMutability: "payable",
459
+ type: "function"
460
+ }
461
+ ];
462
+ var SEAPORT_GET_COUNTER_ABI = [
463
+ {
464
+ inputs: [{ internalType: "address", name: "offerer", type: "address" }],
465
+ name: "getCounter",
466
+ outputs: [{ internalType: "uint256", name: "counter", type: "uint256" }],
467
+ stateMutability: "view",
468
+ type: "function"
469
+ }
470
+ ];
471
+ var ERC721_APPROVAL_ABI = [
472
+ {
473
+ inputs: [
474
+ { internalType: "address", name: "owner", type: "address" },
475
+ { internalType: "address", name: "operator", type: "address" }
476
+ ],
477
+ name: "isApprovedForAll",
478
+ outputs: [{ internalType: "bool", name: "", type: "bool" }],
479
+ stateMutability: "view",
480
+ type: "function"
481
+ },
482
+ {
483
+ inputs: [
484
+ { internalType: "address", name: "operator", type: "address" },
485
+ { internalType: "bool", name: "approved", type: "bool" }
486
+ ],
487
+ name: "setApprovalForAll",
488
+ outputs: [],
489
+ stateMutability: "nonpayable",
490
+ type: "function"
491
+ }
492
+ ];
493
+ var ERC20_APPROVAL_ABI = [
494
+ {
495
+ inputs: [
496
+ { internalType: "address", name: "owner", type: "address" },
497
+ { internalType: "address", name: "spender", type: "address" }
498
+ ],
499
+ name: "allowance",
500
+ outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
501
+ stateMutability: "view",
502
+ type: "function"
503
+ },
504
+ {
505
+ inputs: [
506
+ { internalType: "address", name: "spender", type: "address" },
507
+ { internalType: "uint256", name: "amount", type: "uint256" }
508
+ ],
509
+ name: "approve",
510
+ outputs: [{ internalType: "bool", name: "", type: "bool" }],
511
+ stateMutability: "nonpayable",
512
+ type: "function"
513
+ }
514
+ ];
300
515
 
301
516
  // src/abis/index.ts
302
517
  var BAZAAR_SUBMISSION_ABI = [
@@ -1092,6 +1307,528 @@ function parseSaleFromStoredData(storedData, chainId) {
1092
1307
  function sortSalesByTimestamp(sales) {
1093
1308
  return [...sales].sort((a, b) => b.timestamp - a.timestamp);
1094
1309
  }
1310
+ var MAX_UINT256 = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
1311
+ async function checkErc721Approval(client, nftAddress, owner, spender) {
1312
+ const isApproved = await actions.readContract(client, {
1313
+ address: nftAddress,
1314
+ abi: ERC721_APPROVAL_ABI,
1315
+ functionName: "isApprovedForAll",
1316
+ args: [owner, spender]
1317
+ });
1318
+ if (isApproved) {
1319
+ return null;
1320
+ }
1321
+ return {
1322
+ to: nftAddress,
1323
+ functionName: "setApprovalForAll",
1324
+ args: [spender, true],
1325
+ abi: ERC721_APPROVAL_ABI
1326
+ };
1327
+ }
1328
+ async function checkErc20Approval(client, tokenAddress, owner, spender, amount) {
1329
+ const allowance = await actions.readContract(client, {
1330
+ address: tokenAddress,
1331
+ abi: ERC20_APPROVAL_ABI,
1332
+ functionName: "allowance",
1333
+ args: [owner, spender]
1334
+ });
1335
+ if (allowance >= amount) {
1336
+ return null;
1337
+ }
1338
+ return {
1339
+ to: tokenAddress,
1340
+ functionName: "approve",
1341
+ args: [spender, MAX_UINT256],
1342
+ abi: ERC20_APPROVAL_ABI
1343
+ };
1344
+ }
1345
+
1346
+ // src/utils/fulfillment.ts
1347
+ var ZERO_BYTES32 = "0x0000000000000000000000000000000000000000000000000000000000000000";
1348
+ function formatOrderParameters(params) {
1349
+ return {
1350
+ offerer: params.offerer,
1351
+ zone: params.zone,
1352
+ offer: params.offer.map((item) => ({
1353
+ itemType: item.itemType,
1354
+ token: item.token,
1355
+ identifierOrCriteria: item.identifierOrCriteria,
1356
+ startAmount: item.startAmount,
1357
+ endAmount: item.endAmount
1358
+ })),
1359
+ consideration: params.consideration.map((item) => ({
1360
+ itemType: item.itemType,
1361
+ token: item.token,
1362
+ identifierOrCriteria: item.identifierOrCriteria,
1363
+ startAmount: item.startAmount,
1364
+ endAmount: item.endAmount,
1365
+ recipient: item.recipient
1366
+ })),
1367
+ orderType: params.orderType,
1368
+ startTime: params.startTime,
1369
+ endTime: params.endTime,
1370
+ zoneHash: params.zoneHash,
1371
+ salt: params.salt,
1372
+ conduitKey: params.conduitKey,
1373
+ totalOriginalConsiderationItems: params.totalOriginalConsiderationItems
1374
+ };
1375
+ }
1376
+ function getNativeConsiderationValue(params) {
1377
+ return params.consideration.reduce((acc, item) => {
1378
+ if (item.itemType === 0 /* NATIVE */) {
1379
+ return acc + item.startAmount;
1380
+ }
1381
+ return acc;
1382
+ }, BigInt(0));
1383
+ }
1384
+ function buildFulfillListingTx(submission, recipient, seaportAddress) {
1385
+ const advancedOrder = {
1386
+ parameters: formatOrderParameters(submission.parameters),
1387
+ numerator: BigInt(1),
1388
+ denominator: BigInt(1),
1389
+ signature: submission.signature,
1390
+ extraData: "0x"
1391
+ };
1392
+ return {
1393
+ to: seaportAddress,
1394
+ functionName: "fulfillAdvancedOrder",
1395
+ args: [advancedOrder, [], ZERO_BYTES32, recipient],
1396
+ abi: SEAPORT_FULFILL_ADVANCED_ORDER_ABI,
1397
+ value: getNativeConsiderationValue(submission.parameters)
1398
+ };
1399
+ }
1400
+ function buildFulfillCollectionOfferTx(submission, tokenId, recipient, seaportAddress) {
1401
+ const advancedOrder = {
1402
+ parameters: formatOrderParameters(submission.parameters),
1403
+ numerator: BigInt(1),
1404
+ denominator: BigInt(1),
1405
+ signature: submission.signature,
1406
+ extraData: "0x"
1407
+ };
1408
+ const criteriaResolvers = [
1409
+ {
1410
+ orderIndex: BigInt(0),
1411
+ side: 1,
1412
+ // Consideration side
1413
+ index: BigInt(0),
1414
+ // First consideration item (the NFT)
1415
+ identifier: tokenId,
1416
+ criteriaProof: []
1417
+ }
1418
+ ];
1419
+ return {
1420
+ to: seaportAddress,
1421
+ functionName: "fulfillAdvancedOrder",
1422
+ args: [advancedOrder, criteriaResolvers, ZERO_BYTES32, recipient],
1423
+ abi: SEAPORT_FULFILL_ADVANCED_ORDER_ABI,
1424
+ value: BigInt(0)
1425
+ };
1426
+ }
1427
+ function buildFulfillErc20OfferTx(submission, seaportAddress) {
1428
+ const order = {
1429
+ parameters: formatOrderParameters(submission.parameters),
1430
+ signature: submission.signature
1431
+ };
1432
+ return {
1433
+ to: seaportAddress,
1434
+ functionName: "fulfillOrder",
1435
+ args: [order, ZERO_BYTES32],
1436
+ abi: SEAPORT_FULFILL_ORDER_ABI,
1437
+ value: BigInt(0)
1438
+ };
1439
+ }
1440
+ function buildFulfillErc20ListingTx(submission, recipient, seaportAddress) {
1441
+ const advancedOrder = {
1442
+ parameters: formatOrderParameters(submission.parameters),
1443
+ numerator: BigInt(1),
1444
+ denominator: BigInt(1),
1445
+ signature: submission.signature,
1446
+ extraData: "0x"
1447
+ };
1448
+ return {
1449
+ to: seaportAddress,
1450
+ functionName: "fulfillAdvancedOrder",
1451
+ args: [advancedOrder, [], ZERO_BYTES32, recipient],
1452
+ abi: SEAPORT_FULFILL_ADVANCED_ORDER_ABI,
1453
+ value: getNativeConsiderationValue(submission.parameters)
1454
+ };
1455
+ }
1456
+ var SEAPORT_EIP712_DOMAIN_NAME = "Seaport";
1457
+ var SEAPORT_EIP712_DOMAIN_VERSION = "1.6";
1458
+ var ZERO_BYTES322 = "0x0000000000000000000000000000000000000000000000000000000000000000";
1459
+ var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
1460
+ var SEAPORT_ORDER_EIP712_TYPES = {
1461
+ OrderComponents: [
1462
+ { name: "offerer", type: "address" },
1463
+ { name: "zone", type: "address" },
1464
+ { name: "offer", type: "OfferItem[]" },
1465
+ { name: "consideration", type: "ConsiderationItem[]" },
1466
+ { name: "orderType", type: "uint8" },
1467
+ { name: "startTime", type: "uint256" },
1468
+ { name: "endTime", type: "uint256" },
1469
+ { name: "zoneHash", type: "bytes32" },
1470
+ { name: "salt", type: "uint256" },
1471
+ { name: "conduitKey", type: "bytes32" },
1472
+ { name: "counter", type: "uint256" }
1473
+ ],
1474
+ OfferItem: [
1475
+ { name: "itemType", type: "uint8" },
1476
+ { name: "token", type: "address" },
1477
+ { name: "identifierOrCriteria", type: "uint256" },
1478
+ { name: "startAmount", type: "uint256" },
1479
+ { name: "endAmount", type: "uint256" }
1480
+ ],
1481
+ ConsiderationItem: [
1482
+ { name: "itemType", type: "uint8" },
1483
+ { name: "token", type: "address" },
1484
+ { name: "identifierOrCriteria", type: "uint256" },
1485
+ { name: "startAmount", type: "uint256" },
1486
+ { name: "endAmount", type: "uint256" },
1487
+ { name: "recipient", type: "address" }
1488
+ ]
1489
+ };
1490
+ function calculateFee(price, feeBps, useCeilingDivision) {
1491
+ if (feeBps === 0) return BigInt(0);
1492
+ const fee = price * BigInt(feeBps);
1493
+ if (useCeilingDivision) {
1494
+ return (fee + BigInt(9999)) / BigInt(1e4);
1495
+ }
1496
+ return fee / BigInt(1e4);
1497
+ }
1498
+ function generateSalt() {
1499
+ const bytes = new Uint8Array(32);
1500
+ if (typeof globalThis.crypto !== "undefined" && globalThis.crypto.getRandomValues) {
1501
+ globalThis.crypto.getRandomValues(bytes);
1502
+ } else {
1503
+ for (let i = 0; i < 32; i++) {
1504
+ bytes[i] = Math.floor(Math.random() * 256);
1505
+ }
1506
+ }
1507
+ let hex = "0x";
1508
+ for (const b of bytes) {
1509
+ hex += b.toString(16).padStart(2, "0");
1510
+ }
1511
+ return BigInt(hex);
1512
+ }
1513
+ function getDefaultExpiration() {
1514
+ return Math.floor(Date.now() / 1e3) + 86400;
1515
+ }
1516
+ function buildListingOrderComponents(params, chainId, counter) {
1517
+ const feeBps = getNftFeeBps(chainId);
1518
+ const feeAmount = calculateFee(params.priceWei, feeBps, false);
1519
+ const sellerAmount = params.priceWei - feeAmount;
1520
+ const endTime = BigInt(params.expirationDate ?? getDefaultExpiration());
1521
+ const feeCollector = getFeeCollectorAddress(chainId);
1522
+ const consideration = [
1523
+ {
1524
+ itemType: 0 /* NATIVE */,
1525
+ token: ZERO_ADDRESS,
1526
+ identifierOrCriteria: BigInt(0),
1527
+ startAmount: sellerAmount,
1528
+ endAmount: sellerAmount,
1529
+ recipient: params.offerer
1530
+ }
1531
+ ];
1532
+ if (feeAmount > BigInt(0)) {
1533
+ consideration.push({
1534
+ itemType: 0 /* NATIVE */,
1535
+ token: ZERO_ADDRESS,
1536
+ identifierOrCriteria: BigInt(0),
1537
+ startAmount: feeAmount,
1538
+ endAmount: feeAmount,
1539
+ recipient: feeCollector
1540
+ });
1541
+ }
1542
+ let zone;
1543
+ let zoneHash;
1544
+ if (params.targetFulfiller) {
1545
+ zone = NET_SEAPORT_PRIVATE_ORDER_ZONE_ADDRESS;
1546
+ zoneHash = viem.keccak256(viem.toBytes(params.targetFulfiller));
1547
+ } else {
1548
+ zone = NET_SEAPORT_ZONE_ADDRESS;
1549
+ zoneHash = ZERO_BYTES322;
1550
+ }
1551
+ const orderParameters = {
1552
+ offerer: params.offerer,
1553
+ zone,
1554
+ offer: [
1555
+ {
1556
+ itemType: 2 /* ERC721 */,
1557
+ token: params.nftAddress,
1558
+ identifierOrCriteria: BigInt(params.tokenId),
1559
+ startAmount: BigInt(1),
1560
+ endAmount: BigInt(1)
1561
+ }
1562
+ ],
1563
+ consideration,
1564
+ orderType: 2 /* FULL_RESTRICTED */,
1565
+ startTime: BigInt(0),
1566
+ endTime,
1567
+ zoneHash,
1568
+ salt: generateSalt(),
1569
+ conduitKey: ZERO_BYTES322,
1570
+ totalOriginalConsiderationItems: BigInt(consideration.length)
1571
+ };
1572
+ return { orderParameters, counter };
1573
+ }
1574
+ function buildCollectionOfferOrderComponents(params, chainId, counter) {
1575
+ const weth = getWrappedNativeCurrency(chainId);
1576
+ if (!weth) {
1577
+ throw new Error(`No wrapped native currency configured for chain ${chainId}`);
1578
+ }
1579
+ const feeBps = getNftFeeBps(chainId);
1580
+ const feeAmount = calculateFee(params.priceWei, feeBps, false);
1581
+ const endTime = BigInt(params.expirationDate ?? getDefaultExpiration());
1582
+ const feeCollector = getFeeCollectorAddress(chainId);
1583
+ const consideration = [
1584
+ {
1585
+ itemType: 4 /* ERC721_WITH_CRITERIA */,
1586
+ token: params.nftAddress,
1587
+ identifierOrCriteria: BigInt(0),
1588
+ // Any token in the collection
1589
+ startAmount: BigInt(1),
1590
+ endAmount: BigInt(1),
1591
+ recipient: params.offerer
1592
+ }
1593
+ ];
1594
+ if (feeAmount > BigInt(0)) {
1595
+ consideration.push({
1596
+ itemType: 1 /* ERC20 */,
1597
+ token: weth.address,
1598
+ identifierOrCriteria: BigInt(0),
1599
+ startAmount: feeAmount,
1600
+ endAmount: feeAmount,
1601
+ recipient: feeCollector
1602
+ });
1603
+ }
1604
+ const orderParameters = {
1605
+ offerer: params.offerer,
1606
+ zone: NET_SEAPORT_COLLECTION_OFFER_ZONE_ADDRESS,
1607
+ offer: [
1608
+ {
1609
+ itemType: 1 /* ERC20 */,
1610
+ token: weth.address,
1611
+ identifierOrCriteria: BigInt(0),
1612
+ startAmount: params.priceWei,
1613
+ endAmount: params.priceWei
1614
+ }
1615
+ ],
1616
+ consideration,
1617
+ orderType: 2 /* FULL_RESTRICTED */,
1618
+ startTime: BigInt(0),
1619
+ endTime,
1620
+ zoneHash: ZERO_BYTES322,
1621
+ salt: generateSalt(),
1622
+ conduitKey: ZERO_BYTES322,
1623
+ totalOriginalConsiderationItems: BigInt(consideration.length)
1624
+ };
1625
+ return { orderParameters, counter };
1626
+ }
1627
+ function buildErc20OfferOrderComponents(params, chainId, counter) {
1628
+ const weth = getWrappedNativeCurrency(chainId);
1629
+ if (!weth) {
1630
+ throw new Error(`No wrapped native currency configured for chain ${chainId}`);
1631
+ }
1632
+ const feeBps = getNftFeeBps(chainId);
1633
+ const feeAmount = calculateFee(params.priceWei, feeBps, true);
1634
+ const endTime = BigInt(params.expirationDate ?? getDefaultExpiration());
1635
+ const feeCollector = getFeeCollectorAddress(chainId);
1636
+ const consideration = [
1637
+ {
1638
+ itemType: 1 /* ERC20 */,
1639
+ token: params.tokenAddress,
1640
+ identifierOrCriteria: BigInt(0),
1641
+ startAmount: params.tokenAmount,
1642
+ endAmount: params.tokenAmount,
1643
+ recipient: params.offerer
1644
+ }
1645
+ ];
1646
+ if (feeAmount > BigInt(0)) {
1647
+ consideration.push({
1648
+ itemType: 1 /* ERC20 */,
1649
+ token: weth.address,
1650
+ identifierOrCriteria: BigInt(0),
1651
+ startAmount: feeAmount,
1652
+ endAmount: feeAmount,
1653
+ recipient: feeCollector
1654
+ });
1655
+ }
1656
+ const orderParameters = {
1657
+ offerer: params.offerer,
1658
+ zone: NET_SEAPORT_COLLECTION_OFFER_ZONE_ADDRESS,
1659
+ offer: [
1660
+ {
1661
+ itemType: 1 /* ERC20 */,
1662
+ token: weth.address,
1663
+ identifierOrCriteria: BigInt(0),
1664
+ startAmount: params.priceWei,
1665
+ endAmount: params.priceWei
1666
+ }
1667
+ ],
1668
+ consideration,
1669
+ orderType: 2 /* FULL_RESTRICTED */,
1670
+ startTime: BigInt(0),
1671
+ endTime,
1672
+ zoneHash: ZERO_BYTES322,
1673
+ salt: generateSalt(),
1674
+ conduitKey: ZERO_BYTES322,
1675
+ totalOriginalConsiderationItems: BigInt(consideration.length)
1676
+ };
1677
+ return { orderParameters, counter };
1678
+ }
1679
+ function buildErc20ListingOrderComponents(params, chainId, counter) {
1680
+ const feeBps = getNftFeeBps(chainId);
1681
+ const feeAmount = calculateFee(params.priceWei, feeBps, true);
1682
+ const sellerAmount = params.priceWei - feeAmount;
1683
+ const endTime = BigInt(params.expirationDate ?? getDefaultExpiration());
1684
+ const feeCollector = getFeeCollectorAddress(chainId);
1685
+ const consideration = [
1686
+ {
1687
+ itemType: 0 /* NATIVE */,
1688
+ token: ZERO_ADDRESS,
1689
+ identifierOrCriteria: BigInt(0),
1690
+ startAmount: sellerAmount,
1691
+ endAmount: sellerAmount,
1692
+ recipient: params.offerer
1693
+ }
1694
+ ];
1695
+ if (feeAmount > BigInt(0)) {
1696
+ consideration.push({
1697
+ itemType: 0 /* NATIVE */,
1698
+ token: ZERO_ADDRESS,
1699
+ identifierOrCriteria: BigInt(0),
1700
+ startAmount: feeAmount,
1701
+ endAmount: feeAmount,
1702
+ recipient: feeCollector
1703
+ });
1704
+ }
1705
+ let zone;
1706
+ let zoneHash;
1707
+ if (params.targetFulfiller) {
1708
+ zone = NET_SEAPORT_PRIVATE_ORDER_ZONE_ADDRESS;
1709
+ zoneHash = viem.keccak256(viem.toBytes(params.targetFulfiller));
1710
+ } else {
1711
+ zone = NET_SEAPORT_ZONE_ADDRESS;
1712
+ zoneHash = ZERO_BYTES322;
1713
+ }
1714
+ const orderParameters = {
1715
+ offerer: params.offerer,
1716
+ zone,
1717
+ offer: [
1718
+ {
1719
+ itemType: 1 /* ERC20 */,
1720
+ token: params.tokenAddress,
1721
+ identifierOrCriteria: BigInt(0),
1722
+ startAmount: params.tokenAmount,
1723
+ endAmount: params.tokenAmount
1724
+ }
1725
+ ],
1726
+ consideration,
1727
+ orderType: 2 /* FULL_RESTRICTED */,
1728
+ startTime: BigInt(0),
1729
+ endTime,
1730
+ zoneHash,
1731
+ salt: generateSalt(),
1732
+ conduitKey: ZERO_BYTES322,
1733
+ totalOriginalConsiderationItems: BigInt(consideration.length)
1734
+ };
1735
+ return { orderParameters, counter };
1736
+ }
1737
+ function buildEIP712OrderData(orderParameters, counter, chainId, seaportAddress) {
1738
+ const message = {
1739
+ offerer: orderParameters.offerer,
1740
+ zone: orderParameters.zone,
1741
+ offer: orderParameters.offer.map((item) => ({
1742
+ itemType: item.itemType,
1743
+ token: item.token,
1744
+ identifierOrCriteria: item.identifierOrCriteria,
1745
+ startAmount: item.startAmount,
1746
+ endAmount: item.endAmount
1747
+ })),
1748
+ consideration: orderParameters.consideration.map((item) => ({
1749
+ itemType: item.itemType,
1750
+ token: item.token,
1751
+ identifierOrCriteria: item.identifierOrCriteria,
1752
+ startAmount: item.startAmount,
1753
+ endAmount: item.endAmount,
1754
+ recipient: item.recipient
1755
+ })),
1756
+ orderType: orderParameters.orderType,
1757
+ startTime: orderParameters.startTime,
1758
+ endTime: orderParameters.endTime,
1759
+ zoneHash: orderParameters.zoneHash,
1760
+ salt: orderParameters.salt,
1761
+ conduitKey: orderParameters.conduitKey,
1762
+ counter
1763
+ };
1764
+ return {
1765
+ domain: {
1766
+ name: SEAPORT_EIP712_DOMAIN_NAME,
1767
+ version: SEAPORT_EIP712_DOMAIN_VERSION,
1768
+ chainId,
1769
+ verifyingContract: seaportAddress
1770
+ },
1771
+ types: SEAPORT_ORDER_EIP712_TYPES,
1772
+ primaryType: "OrderComponents",
1773
+ message,
1774
+ orderParameters,
1775
+ counter
1776
+ };
1777
+ }
1778
+ function buildSubmitOrderTx(contractAddress, abi, orderParameters, counter, signature) {
1779
+ const submission = {
1780
+ parameters: {
1781
+ offerer: orderParameters.offerer,
1782
+ zone: orderParameters.zone,
1783
+ offer: orderParameters.offer.map((item) => ({
1784
+ itemType: item.itemType,
1785
+ token: item.token,
1786
+ identifierOrCriteria: item.identifierOrCriteria,
1787
+ startAmount: item.startAmount,
1788
+ endAmount: item.endAmount
1789
+ })),
1790
+ consideration: orderParameters.consideration.map((item) => ({
1791
+ itemType: item.itemType,
1792
+ token: item.token,
1793
+ identifierOrCriteria: item.identifierOrCriteria,
1794
+ startAmount: item.startAmount,
1795
+ endAmount: item.endAmount,
1796
+ recipient: item.recipient
1797
+ })),
1798
+ orderType: orderParameters.orderType,
1799
+ startTime: orderParameters.startTime,
1800
+ endTime: orderParameters.endTime,
1801
+ zoneHash: orderParameters.zoneHash,
1802
+ salt: orderParameters.salt,
1803
+ conduitKey: orderParameters.conduitKey,
1804
+ totalOriginalConsiderationItems: orderParameters.totalOriginalConsiderationItems
1805
+ },
1806
+ counter,
1807
+ signature
1808
+ };
1809
+ return {
1810
+ to: contractAddress,
1811
+ functionName: "submit",
1812
+ args: [submission],
1813
+ abi
1814
+ };
1815
+ }
1816
+ var ERC721_TOKEN_OWNER_RANGE_HELPER_ADDRESS = "0x00000000f4ec2016d6e856b0cb14d635949bfd3f";
1817
+ var ERC721_TOKEN_OWNER_RANGE_HELPER_ABI = [
1818
+ {
1819
+ inputs: [
1820
+ { name: "nftContract", type: "address" },
1821
+ { name: "user", type: "address" },
1822
+ { name: "startTokenId", type: "uint256" },
1823
+ { name: "endTokenId", type: "uint256" }
1824
+ ],
1825
+ name: "getOwnedTokensInRange",
1826
+ outputs: [{ name: "", type: "uint256[]" }],
1827
+ stateMutability: "view",
1828
+ type: "function"
1829
+ }
1830
+ ];
1831
+ var OWNED_TOKENS_BATCH_SIZE = 5000n;
1095
1832
  var CHAIN_RPC_URLS = {
1096
1833
  8453: ["https://base-mainnet.public.blastapi.io", "https://mainnet.base.org"],
1097
1834
  84532: ["https://sepolia.base.org"],
@@ -1154,7 +1891,7 @@ var BazaarClient = class {
1154
1891
  const bazaarAddress = getBazaarAddress(this.chainId);
1155
1892
  const filter = {
1156
1893
  appAddress: bazaarAddress,
1157
- topic: nftAddress.toLowerCase(),
1894
+ topic: nftAddress?.toLowerCase(),
1158
1895
  maker
1159
1896
  };
1160
1897
  let startIndex;
@@ -1227,18 +1964,57 @@ var BazaarClient = class {
1227
1964
  }
1228
1965
  const openListings = listings.filter((l) => l.orderStatus === 2 /* OPEN */);
1229
1966
  const expiredListings = includeExpired ? listings.filter((l) => l.orderStatus === 1 /* EXPIRED */) : [];
1230
- const tokenIds = openListings.map((l) => l.tokenId);
1231
- const owners = await bulkFetchNftOwners(this.client, nftAddress, tokenIds);
1967
+ let validOpenListings;
1232
1968
  const beforeOwnership = openListings.length;
1233
- const validOpenListings = openListings.filter((listing, index) => {
1234
- const owner = owners[index];
1235
- return isListingValid(
1236
- listing.orderStatus,
1237
- listing.expirationDate,
1238
- listing.maker,
1239
- owner
1969
+ if (nftAddress) {
1970
+ const tokenIds = openListings.map((l) => l.tokenId);
1971
+ const owners = await bulkFetchNftOwners(this.client, nftAddress, tokenIds);
1972
+ validOpenListings = openListings.filter((listing, index) => {
1973
+ const owner = owners[index];
1974
+ return isListingValid(
1975
+ listing.orderStatus,
1976
+ listing.expirationDate,
1977
+ listing.maker,
1978
+ owner
1979
+ );
1980
+ });
1981
+ } else {
1982
+ const groups = /* @__PURE__ */ new Map();
1983
+ for (const listing of openListings) {
1984
+ const key = listing.nftAddress.toLowerCase();
1985
+ const group = groups.get(key);
1986
+ if (group) {
1987
+ group.push(listing);
1988
+ } else {
1989
+ groups.set(key, [listing]);
1990
+ }
1991
+ }
1992
+ const groupEntries = Array.from(groups.entries());
1993
+ const ownerResults = await Promise.all(
1994
+ groupEntries.map(
1995
+ ([addr, groupListings]) => bulkFetchNftOwners(
1996
+ this.client,
1997
+ addr,
1998
+ groupListings.map((l) => l.tokenId)
1999
+ )
2000
+ )
1240
2001
  );
1241
- });
2002
+ validOpenListings = [];
2003
+ groupEntries.forEach(([, groupListings], groupIndex) => {
2004
+ const owners = ownerResults[groupIndex];
2005
+ for (let i = 0; i < groupListings.length; i++) {
2006
+ const listing = groupListings[i];
2007
+ if (isListingValid(
2008
+ listing.orderStatus,
2009
+ listing.expirationDate,
2010
+ listing.maker,
2011
+ owners[i]
2012
+ )) {
2013
+ validOpenListings.push(listing);
2014
+ }
2015
+ }
2016
+ });
2017
+ }
1242
2018
  console.log(tag, `after ownership filter: ${validOpenListings.length}/${beforeOwnership} (${beforeOwnership - validOpenListings.length} dropped)`);
1243
2019
  const dedupedOpen = sortListingsByPrice(getBestListingPerToken(validOpenListings));
1244
2020
  const activeTokenKeys = new Set(dedupedOpen.map((l) => `${l.nftAddress.toLowerCase()}-${l.tokenId}`));
@@ -1750,16 +2526,303 @@ var BazaarClient = class {
1750
2526
  abi: SEAPORT_CANCEL_ABI
1751
2527
  };
1752
2528
  }
2529
+ // ─── Fulfillment Methods ───────────────────────────────────────────
2530
+ /**
2531
+ * Prepare a fulfillment for an NFT listing (buy an NFT).
2532
+ *
2533
+ * Returns approval transactions (if the listing requires ERC20 payment) and
2534
+ * the Seaport `fulfillAdvancedOrder` transaction with the correct native currency value.
2535
+ */
2536
+ async prepareFulfillListing(listing, fulfillerAddress) {
2537
+ const submission = decodeSeaportSubmission(listing.messageData);
2538
+ const seaportAddress = getSeaportAddress(this.chainId);
2539
+ const fulfillment = buildFulfillListingTx(submission, fulfillerAddress, seaportAddress);
2540
+ return { approvals: [], fulfillment };
2541
+ }
2542
+ /**
2543
+ * Prepare a fulfillment for a collection offer (sell your NFT into an offer).
2544
+ *
2545
+ * Returns ERC721 approval transaction (if the NFT isn't approved for Seaport)
2546
+ * and the Seaport `fulfillAdvancedOrder` transaction.
2547
+ */
2548
+ async prepareFulfillCollectionOffer(offer, tokenId, fulfillerAddress) {
2549
+ const submission = decodeSeaportSubmission(offer.messageData);
2550
+ const seaportAddress = getSeaportAddress(this.chainId);
2551
+ const approvals = [];
2552
+ const nftApproval = await checkErc721Approval(
2553
+ this.client,
2554
+ offer.nftAddress,
2555
+ fulfillerAddress,
2556
+ seaportAddress
2557
+ );
2558
+ if (nftApproval) {
2559
+ approvals.push(nftApproval);
2560
+ }
2561
+ const fulfillment = buildFulfillCollectionOfferTx(
2562
+ submission,
2563
+ BigInt(tokenId),
2564
+ fulfillerAddress,
2565
+ seaportAddress
2566
+ );
2567
+ return { approvals, fulfillment };
2568
+ }
2569
+ /**
2570
+ * Prepare a fulfillment for an ERC20 offer (sell your ERC20 tokens into an offer).
2571
+ *
2572
+ * Returns ERC20 approval transaction (if the token isn't approved for Seaport)
2573
+ * and the Seaport `fulfillOrder` transaction.
2574
+ */
2575
+ async prepareFulfillErc20Offer(offer, fulfillerAddress) {
2576
+ const submission = decodeSeaportSubmission(offer.messageData);
2577
+ const seaportAddress = getSeaportAddress(this.chainId);
2578
+ const approvals = [];
2579
+ const tokenApproval = await checkErc20Approval(
2580
+ this.client,
2581
+ offer.tokenAddress,
2582
+ fulfillerAddress,
2583
+ seaportAddress,
2584
+ offer.tokenAmount
2585
+ );
2586
+ if (tokenApproval) {
2587
+ approvals.push(tokenApproval);
2588
+ }
2589
+ const fulfillment = buildFulfillErc20OfferTx(submission, seaportAddress);
2590
+ return { approvals, fulfillment };
2591
+ }
2592
+ /**
2593
+ * Prepare a fulfillment for an ERC20 listing (buy ERC20 tokens with native currency).
2594
+ *
2595
+ * Returns the Seaport `fulfillAdvancedOrder` transaction with the correct native currency value.
2596
+ * No approvals needed since the buyer pays in native currency.
2597
+ */
2598
+ async prepareFulfillErc20Listing(listing, fulfillerAddress) {
2599
+ const submission = decodeSeaportSubmission(listing.messageData);
2600
+ const seaportAddress = getSeaportAddress(this.chainId);
2601
+ const fulfillment = buildFulfillErc20ListingTx(submission, fulfillerAddress, seaportAddress);
2602
+ return { approvals: [], fulfillment };
2603
+ }
2604
+ // ─── Order Creation Methods (Step 1: Build EIP-712 data) ──────────
2605
+ /**
2606
+ * Fetch the Seaport counter for an address
2607
+ */
2608
+ async getSeaportCounter(offerer) {
2609
+ const seaportAddress = getSeaportAddress(this.chainId);
2610
+ const counter = await actions.readContract(this.client, {
2611
+ address: seaportAddress,
2612
+ abi: SEAPORT_GET_COUNTER_ABI,
2613
+ functionName: "getCounter",
2614
+ args: [offerer]
2615
+ });
2616
+ return BigInt(counter);
2617
+ }
2618
+ /**
2619
+ * Prepare an NFT listing order for signing.
2620
+ *
2621
+ * Returns EIP-712 typed data for the caller to sign, plus any maker approvals needed
2622
+ * (ERC721 `setApprovalForAll` for Seaport).
2623
+ */
2624
+ async prepareCreateListing(params) {
2625
+ const seaportAddress = getSeaportAddress(this.chainId);
2626
+ const counter = await this.getSeaportCounter(params.offerer);
2627
+ const { orderParameters } = buildListingOrderComponents(params, this.chainId, counter);
2628
+ const eip712 = buildEIP712OrderData(orderParameters, counter, this.chainId, seaportAddress);
2629
+ const approvals = [];
2630
+ const nftApproval = await checkErc721Approval(
2631
+ this.client,
2632
+ params.nftAddress,
2633
+ params.offerer,
2634
+ seaportAddress
2635
+ );
2636
+ if (nftApproval) {
2637
+ approvals.push(nftApproval);
2638
+ }
2639
+ return { eip712, approvals };
2640
+ }
2641
+ /**
2642
+ * Prepare a collection offer order for signing.
2643
+ *
2644
+ * Returns EIP-712 typed data for the caller to sign, plus any maker approvals needed
2645
+ * (WETH `approve` for Seaport).
2646
+ */
2647
+ async prepareCreateCollectionOffer(params) {
2648
+ const seaportAddress = getSeaportAddress(this.chainId);
2649
+ const weth = getWrappedNativeCurrency(this.chainId);
2650
+ if (!weth) {
2651
+ throw new Error(`No wrapped native currency configured for chain ${this.chainId}`);
2652
+ }
2653
+ const counter = await this.getSeaportCounter(params.offerer);
2654
+ const { orderParameters } = buildCollectionOfferOrderComponents(params, this.chainId, counter);
2655
+ const eip712 = buildEIP712OrderData(orderParameters, counter, this.chainId, seaportAddress);
2656
+ const approvals = [];
2657
+ const wethApproval = await checkErc20Approval(
2658
+ this.client,
2659
+ weth.address,
2660
+ params.offerer,
2661
+ seaportAddress,
2662
+ params.priceWei
2663
+ );
2664
+ if (wethApproval) {
2665
+ approvals.push(wethApproval);
2666
+ }
2667
+ return { eip712, approvals };
2668
+ }
2669
+ /**
2670
+ * Prepare an ERC20 offer order for signing.
2671
+ *
2672
+ * Returns EIP-712 typed data for the caller to sign, plus any maker approvals needed
2673
+ * (WETH `approve` for Seaport).
2674
+ */
2675
+ async prepareCreateErc20Offer(params) {
2676
+ const seaportAddress = getSeaportAddress(this.chainId);
2677
+ const weth = getWrappedNativeCurrency(this.chainId);
2678
+ if (!weth) {
2679
+ throw new Error(`No wrapped native currency configured for chain ${this.chainId}`);
2680
+ }
2681
+ const counter = await this.getSeaportCounter(params.offerer);
2682
+ const { orderParameters } = buildErc20OfferOrderComponents(params, this.chainId, counter);
2683
+ const eip712 = buildEIP712OrderData(orderParameters, counter, this.chainId, seaportAddress);
2684
+ const approvals = [];
2685
+ const wethApproval = await checkErc20Approval(
2686
+ this.client,
2687
+ weth.address,
2688
+ params.offerer,
2689
+ seaportAddress,
2690
+ params.priceWei
2691
+ );
2692
+ if (wethApproval) {
2693
+ approvals.push(wethApproval);
2694
+ }
2695
+ return { eip712, approvals };
2696
+ }
2697
+ /**
2698
+ * Prepare an ERC20 listing order for signing.
2699
+ *
2700
+ * Returns EIP-712 typed data for the caller to sign, plus any maker approvals needed
2701
+ * (ERC20 `approve` for Seaport).
2702
+ */
2703
+ async prepareCreateErc20Listing(params) {
2704
+ const seaportAddress = getSeaportAddress(this.chainId);
2705
+ const counter = await this.getSeaportCounter(params.offerer);
2706
+ const { orderParameters } = buildErc20ListingOrderComponents(params, this.chainId, counter);
2707
+ const eip712 = buildEIP712OrderData(orderParameters, counter, this.chainId, seaportAddress);
2708
+ const approvals = [];
2709
+ const tokenApproval = await checkErc20Approval(
2710
+ this.client,
2711
+ params.tokenAddress,
2712
+ params.offerer,
2713
+ seaportAddress,
2714
+ params.tokenAmount
2715
+ );
2716
+ if (tokenApproval) {
2717
+ approvals.push(tokenApproval);
2718
+ }
2719
+ return { eip712, approvals };
2720
+ }
2721
+ // ─── Order Creation Methods (Step 2: Submit signed order) ─────────
2722
+ /**
2723
+ * Prepare a submit transaction for an NFT listing.
2724
+ *
2725
+ * Call this after the user has signed the EIP-712 data from prepareCreateListing().
2726
+ */
2727
+ prepareSubmitListing(orderParameters, counter, signature) {
2728
+ return buildSubmitOrderTx(
2729
+ getBazaarAddress(this.chainId),
2730
+ BAZAAR_V2_ABI,
2731
+ orderParameters,
2732
+ counter,
2733
+ signature
2734
+ );
2735
+ }
2736
+ /**
2737
+ * Prepare a submit transaction for a collection offer.
2738
+ *
2739
+ * Call this after the user has signed the EIP-712 data from prepareCreateCollectionOffer().
2740
+ */
2741
+ prepareSubmitCollectionOffer(orderParameters, counter, signature) {
2742
+ return buildSubmitOrderTx(
2743
+ getCollectionOffersAddress(this.chainId),
2744
+ BAZAAR_COLLECTION_OFFERS_ABI,
2745
+ orderParameters,
2746
+ counter,
2747
+ signature
2748
+ );
2749
+ }
2750
+ /**
2751
+ * Prepare a submit transaction for an ERC20 offer.
2752
+ *
2753
+ * Call this after the user has signed the EIP-712 data from prepareCreateErc20Offer().
2754
+ */
2755
+ prepareSubmitErc20Offer(orderParameters, counter, signature) {
2756
+ const erc20OffersAddress = getErc20OffersAddress(this.chainId);
2757
+ if (!erc20OffersAddress) {
2758
+ throw new Error(`ERC20 offers not available on chain ${this.chainId}`);
2759
+ }
2760
+ return buildSubmitOrderTx(
2761
+ erc20OffersAddress,
2762
+ BAZAAR_ERC20_OFFERS_ABI,
2763
+ orderParameters,
2764
+ counter,
2765
+ signature
2766
+ );
2767
+ }
2768
+ /**
2769
+ * Prepare a submit transaction for an ERC20 listing.
2770
+ *
2771
+ * Call this after the user has signed the EIP-712 data from prepareCreateErc20Listing().
2772
+ */
2773
+ prepareSubmitErc20Listing(orderParameters, counter, signature) {
2774
+ return buildSubmitOrderTx(
2775
+ getErc20BazaarAddress(this.chainId),
2776
+ BAZAAR_V2_ABI,
2777
+ orderParameters,
2778
+ counter,
2779
+ signature
2780
+ );
2781
+ }
2782
+ // ─── Owned Tokens Query ─────────────────────────────────────────────
2783
+ /**
2784
+ * Get token IDs owned by an address for an ERC721 collection.
2785
+ *
2786
+ * Uses the on-chain ERC721TokenOwnerRangeHelper contract, batching
2787
+ * large ranges into 5000-token chunks to avoid RPC limits.
2788
+ */
2789
+ async getOwnedTokens(params) {
2790
+ const { nftAddress, ownerAddress } = params;
2791
+ const startTokenId = params.startTokenId ?? 0n;
2792
+ const endTokenId = params.endTokenId ?? 10000n;
2793
+ const ownedTokens = [];
2794
+ let current = startTokenId;
2795
+ while (current < endTokenId) {
2796
+ const batchEnd = current + OWNED_TOKENS_BATCH_SIZE < endTokenId ? current + OWNED_TOKENS_BATCH_SIZE : endTokenId;
2797
+ try {
2798
+ const result = await actions.readContract(this.client, {
2799
+ address: ERC721_TOKEN_OWNER_RANGE_HELPER_ADDRESS,
2800
+ abi: ERC721_TOKEN_OWNER_RANGE_HELPER_ABI,
2801
+ functionName: "getOwnedTokensInRange",
2802
+ args: [nftAddress, ownerAddress, current, batchEnd]
2803
+ });
2804
+ for (const tokenId of result) {
2805
+ ownedTokens.push(tokenId);
2806
+ }
2807
+ } catch {
2808
+ }
2809
+ current = batchEnd;
2810
+ }
2811
+ return ownedTokens;
2812
+ }
1753
2813
  };
1754
2814
 
1755
2815
  exports.BAZAAR_COLLECTION_OFFERS_ABI = BAZAAR_COLLECTION_OFFERS_ABI;
2816
+ exports.BAZAAR_ERC20_OFFERS_ABI = BAZAAR_ERC20_OFFERS_ABI;
1756
2817
  exports.BAZAAR_SUBMISSION_ABI = BAZAAR_SUBMISSION_ABI;
1757
2818
  exports.BAZAAR_V2_ABI = BAZAAR_V2_ABI;
1758
2819
  exports.BULK_SEAPORT_ORDER_STATUS_FETCHER_ABI = BULK_SEAPORT_ORDER_STATUS_FETCHER_ABI;
1759
2820
  exports.BULK_SEAPORT_ORDER_STATUS_FETCHER_ADDRESS = BULK_SEAPORT_ORDER_STATUS_FETCHER_ADDRESS;
1760
2821
  exports.BazaarClient = BazaarClient;
2822
+ exports.ERC20_APPROVAL_ABI = ERC20_APPROVAL_ABI;
1761
2823
  exports.ERC20_BULK_BALANCE_CHECKER_ABI = ERC20_BULK_BALANCE_CHECKER_ABI;
1762
2824
  exports.ERC20_BULK_BALANCE_CHECKER_ADDRESS = ERC20_BULK_BALANCE_CHECKER_ADDRESS;
2825
+ exports.ERC721_APPROVAL_ABI = ERC721_APPROVAL_ABI;
1763
2826
  exports.ERC721_OWNER_OF_HELPER_ABI = ERC721_OWNER_OF_HELPER_ABI;
1764
2827
  exports.ERC721_OWNER_OF_HELPER_ADDRESS = ERC721_OWNER_OF_HELPER_ADDRESS;
1765
2828
  exports.ItemType = ItemType;
@@ -1768,10 +2831,26 @@ exports.NET_SEAPORT_PRIVATE_ORDER_ZONE_ADDRESS = NET_SEAPORT_PRIVATE_ORDER_ZONE_
1768
2831
  exports.NET_SEAPORT_ZONE_ADDRESS = NET_SEAPORT_ZONE_ADDRESS;
1769
2832
  exports.OrderType = OrderType;
1770
2833
  exports.SEAPORT_CANCEL_ABI = SEAPORT_CANCEL_ABI;
2834
+ exports.SEAPORT_FULFILL_ADVANCED_ORDER_ABI = SEAPORT_FULFILL_ADVANCED_ORDER_ABI;
2835
+ exports.SEAPORT_FULFILL_ORDER_ABI = SEAPORT_FULFILL_ORDER_ABI;
2836
+ exports.SEAPORT_GET_COUNTER_ABI = SEAPORT_GET_COUNTER_ABI;
1771
2837
  exports.SeaportOrderStatus = SeaportOrderStatus;
2838
+ exports.buildCollectionOfferOrderComponents = buildCollectionOfferOrderComponents;
2839
+ exports.buildEIP712OrderData = buildEIP712OrderData;
2840
+ exports.buildErc20ListingOrderComponents = buildErc20ListingOrderComponents;
2841
+ exports.buildErc20OfferOrderComponents = buildErc20OfferOrderComponents;
2842
+ exports.buildFulfillCollectionOfferTx = buildFulfillCollectionOfferTx;
2843
+ exports.buildFulfillErc20ListingTx = buildFulfillErc20ListingTx;
2844
+ exports.buildFulfillErc20OfferTx = buildFulfillErc20OfferTx;
2845
+ exports.buildFulfillListingTx = buildFulfillListingTx;
2846
+ exports.buildListingOrderComponents = buildListingOrderComponents;
2847
+ exports.buildSubmitOrderTx = buildSubmitOrderTx;
1772
2848
  exports.bulkFetchErc20Balances = bulkFetchErc20Balances;
1773
2849
  exports.bulkFetchNftOwners = bulkFetchNftOwners;
1774
2850
  exports.bulkFetchOrderStatuses = bulkFetchOrderStatuses;
2851
+ exports.calculateFee = calculateFee;
2852
+ exports.checkErc20Approval = checkErc20Approval;
2853
+ exports.checkErc721Approval = checkErc721Approval;
1775
2854
  exports.computeOrderHash = computeOrderHash;
1776
2855
  exports.createBalanceMap = createBalanceMap;
1777
2856
  exports.createOrderStatusMap = createOrderStatusMap;
@@ -1779,6 +2858,7 @@ exports.createOwnershipMap = createOwnershipMap;
1779
2858
  exports.createSeaportInstance = createSeaportInstance;
1780
2859
  exports.decodeSeaportSubmission = decodeSeaportSubmission;
1781
2860
  exports.formatPrice = formatPrice;
2861
+ exports.generateSalt = generateSalt;
1782
2862
  exports.getBazaarAddress = getBazaarAddress;
1783
2863
  exports.getBazaarChainConfig = getBazaarChainConfig;
1784
2864
  exports.getBazaarSupportedChainIds = getBazaarSupportedChainIds;
@@ -1786,6 +2866,7 @@ exports.getBestCollectionOffer = getBestCollectionOffer;
1786
2866
  exports.getBestListingPerToken = getBestListingPerToken;
1787
2867
  exports.getCollectionOffersAddress = getCollectionOffersAddress;
1788
2868
  exports.getCurrencySymbol = getCurrencySymbol;
2869
+ exports.getDefaultExpiration = getDefaultExpiration;
1789
2870
  exports.getErc20BazaarAddress = getErc20BazaarAddress;
1790
2871
  exports.getErc20OffersAddress = getErc20OffersAddress;
1791
2872
  exports.getFeeCollectorAddress = getFeeCollectorAddress;