contract ERC721BulkTransfer is IERC721BulkTransfer {
    /// @inheritdoc     IERC721BulkTransfer
    function transfer(
        address collection,
        address recipient,
        uint256[] calldata tokenIds
    ) external {
        require(tokenIds.length > 0, "Invalid token ids amount");

        for (uint256 i = 0; i < tokenIds.length; i++) {
            uint256 tokenId = tokenIds[i];
            IERC721(collection).transferFrom(msg.sender, recipient, tokenId);
        }
    }

    /// @inheritdoc     IERC721BulkTransfer
    function transfer(address collection, ToRecipient[] calldata recipientsData)
        external
    {
        require(recipientsData.length > 0, "Empty recipients data");

        for (uint256 i = 0; i < recipientsData.length; i++) {
            uint256 tokenId = recipientsData[i].tokenId;
            address recipient = recipientsData[i].recipient;

            IERC721(collection).transferFrom(msg.sender, recipient, tokenId);
        }
    }

    /// @inheritdoc     IERC721BulkTransfer
    function transfer(
        FromCollection[] calldata collectionsData,
        address recipient
    ) external {
        require(collectionsData.length > 0, "Empty collections data");

        for (uint256 i = 0; i < collectionsData.length; i++) {
            uint256 tokenId = collectionsData[i].tokenId;
            address collection = collectionsData[i].collection;

            IERC721(collection).transferFrom(msg.sender, recipient, tokenId);
        }
    }

    /// @inheritdoc     IERC721BulkTransfer
    function transfer(FromCollectionToRecipient[] calldata transferData)
        external
    {
        require(transferData.length > 0, "Empty transfer data");

        for (uint256 i = 0; i < transferData.length; i++) {
            uint256 tokenId = transferData[i].tokenId;
            address collection = transferData[i].collection;
            address recipient = transferData[i].recipient;

            IERC721(collection).transferFrom(msg.sender, recipient, tokenId);
        }
    }
}
/// @title ERC721 tokens bulk transfer
/// @author https://github.com/gnkz
/// @notice This smart contract allows to transfer multiple ERC721 tokens at once
/// @dev The contract needs approvals for the tokens that are going to be transferred
function transfer(
    FromCollection[] calldata collectionsData,
    address recipient
) external {
    require(collectionsData.length > 0, "Empty collections data");

    for (uint256 i = 0; i < collectionsData.length; i++) {
        uint256 tokenId = collectionsData[i].tokenId;
        address collection = collectionsData[i].collection;

        IERC721(collection).transferFrom(msg.sender, recipient, tokenId);
    }
}

/// @inheritdoc     IERC721BulkTransfer