@@ -3,6 +3,8 @@ pragma solidity 0.8.23;
3
3
4
4
import { ERC20 } from "solady/src/tokens/ERC20.sol " ;
5
5
import "@openzeppelin/contracts/utils/Address.sol " ;
6
+ import "@openzeppelin/contracts/token/ERC721/IERC721.sol " ;
7
+ import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol " ;
6
8
import "@airswap/swap/contracts/interfaces/ISwap.sol " ;
7
9
import "@airswap/swap-erc20/contracts/interfaces/ISwapERC20.sol " ;
8
10
import "@airswap/registry/contracts/interfaces/IRegistry.sol " ;
@@ -311,4 +313,167 @@ contract BatchCall {
311
313
}
312
314
return tokensSupported;
313
315
}
316
+
317
+ /**
318
+ * @notice Batch check ERC721 balances for multiple NFTs
319
+ * @param userAddress address The user to check balances for
320
+ * @param contractAddresses address[] Array of ERC721 contract addresses
321
+ * @param tokenIds uint256[] Array of token IDs
322
+ * @return uint256[] Array of balances (1 or 0) corresponding to each NFT
323
+ */
324
+ function walletBalancesERC721 (
325
+ address userAddress ,
326
+ address [] calldata contractAddresses ,
327
+ uint256 [] calldata tokenIds
328
+ ) external view returns (uint256 [] memory ) {
329
+ if (
330
+ contractAddresses.length == 0 ||
331
+ contractAddresses.length != tokenIds.length
332
+ ) revert ArgumentInvalid ();
333
+
334
+ uint256 [] memory balances = new uint256 [](contractAddresses.length );
335
+
336
+ for (uint256 i; i < contractAddresses.length ; ) {
337
+ if (contractAddresses[i].isContract ()) {
338
+ IERC721 nft = IERC721 (contractAddresses[i]);
339
+ try nft.ownerOf (tokenIds[i]) returns (address owner ) {
340
+ balances[i] = owner == userAddress ? 1 : 0 ;
341
+ } catch {
342
+ balances[i] = 0 ;
343
+ }
344
+ } else {
345
+ balances[i] = 0 ;
346
+ }
347
+ unchecked {
348
+ ++ i;
349
+ }
350
+ }
351
+
352
+ return balances;
353
+ }
354
+
355
+ /**
356
+ * @notice Batch check ERC1155 balances for multiple NFTs
357
+ * @param userAddress address The user to check balances for
358
+ * @param contractAddresses address[] Array of ERC1155 contract addresses
359
+ * @param tokenIds uint256[] Array of token IDs
360
+ * @return uint256[] Array of balances corresponding to each NFT
361
+ */
362
+ function walletBalancesERC1155 (
363
+ address userAddress ,
364
+ address [] calldata contractAddresses ,
365
+ uint256 [] calldata tokenIds
366
+ ) external view returns (uint256 [] memory ) {
367
+ if (
368
+ contractAddresses.length == 0 ||
369
+ contractAddresses.length != tokenIds.length
370
+ ) revert ArgumentInvalid ();
371
+
372
+ uint256 [] memory balances = new uint256 [](contractAddresses.length );
373
+
374
+ for (uint256 i; i < contractAddresses.length ; ) {
375
+ if (contractAddresses[i].isContract ()) {
376
+ IERC1155 nft = IERC1155 (contractAddresses[i]);
377
+ try nft.balanceOf (userAddress, tokenIds[i]) returns (uint256 balance ) {
378
+ balances[i] = balance;
379
+ } catch {
380
+ balances[i] = 0 ;
381
+ }
382
+ } else {
383
+ balances[i] = 0 ;
384
+ }
385
+ unchecked {
386
+ ++ i;
387
+ }
388
+ }
389
+
390
+ return balances;
391
+ }
392
+
393
+ /**
394
+ * @notice Batch check ERC721 allowances for multiple NFTs
395
+ * @param userAddress address The user who granted the approval
396
+ * @param operatorAddress address The operator to check approval for
397
+ * @param contractAddresses address[] Array of ERC721 contract addresses
398
+ * @param tokenIds uint256[] Array of token IDs
399
+ * @return bool[] Array of allowance states corresponding to each NFT
400
+ */
401
+ function walletAllowancesERC721 (
402
+ address userAddress ,
403
+ address operatorAddress ,
404
+ address [] calldata contractAddresses ,
405
+ uint256 [] calldata tokenIds
406
+ ) external view returns (bool [] memory ) {
407
+ if (
408
+ contractAddresses.length == 0 ||
409
+ contractAddresses.length != tokenIds.length
410
+ ) revert ArgumentInvalid ();
411
+
412
+ bool [] memory allowances = new bool [](contractAddresses.length );
413
+
414
+ for (uint256 i; i < contractAddresses.length ; ) {
415
+ if (contractAddresses[i].isContract ()) {
416
+ IERC721 nft = IERC721 (contractAddresses[i]);
417
+ try nft.isApprovedForAll (userAddress, operatorAddress) returns (
418
+ bool isApproved
419
+ ) {
420
+ if (isApproved) {
421
+ allowances[i] = true ;
422
+ } else {
423
+ try nft.getApproved (tokenIds[i]) returns (address approved ) {
424
+ allowances[i] = approved == operatorAddress;
425
+ } catch {
426
+ allowances[i] = false ;
427
+ }
428
+ }
429
+ } catch {
430
+ allowances[i] = false ;
431
+ }
432
+ } else {
433
+ allowances[i] = false ;
434
+ }
435
+ unchecked {
436
+ ++ i;
437
+ }
438
+ }
439
+
440
+ return allowances;
441
+ }
442
+
443
+ /**
444
+ * @notice Batch check ERC1155 allowances for multiple NFTs
445
+ * @param userAddress address The user who granted the approval
446
+ * @param operatorAddress address The operator to check approval for
447
+ * @param contractAddresses address[] Array of ERC1155 contract addresses
448
+ * @return bool[] Array of allowance states corresponding to each NFT
449
+ */
450
+ function walletAllowancesERC1155 (
451
+ address userAddress ,
452
+ address operatorAddress ,
453
+ address [] calldata contractAddresses
454
+ ) external view returns (bool [] memory ) {
455
+ if (contractAddresses.length == 0 ) revert ArgumentInvalid ();
456
+
457
+ bool [] memory allowances = new bool [](contractAddresses.length );
458
+
459
+ for (uint256 i; i < contractAddresses.length ; ) {
460
+ if (contractAddresses[i].isContract ()) {
461
+ IERC1155 nft = IERC1155 (contractAddresses[i]);
462
+ try nft.isApprovedForAll (userAddress, operatorAddress) returns (
463
+ bool approved
464
+ ) {
465
+ allowances[i] = approved;
466
+ } catch {
467
+ allowances[i] = false ;
468
+ }
469
+ } else {
470
+ allowances[i] = false ;
471
+ }
472
+ unchecked {
473
+ ++ i;
474
+ }
475
+ }
476
+
477
+ return allowances;
478
+ }
314
479
}
0 commit comments