library TribeOneHelper {
    enum TokenType {
        ERC721,
        ERC1155
    }

    function safeApprove(
        address token,
        address to,
        uint256 value
    ) internal {
        // bytes4(keccak256(bytes('approve(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper::safeApprove: approve failed");
    }

    function safeTransfer(
        address token,
        address to,
        uint256 value
    ) internal {
        // bytes4(keccak256(bytes('transfer(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), "TribeOneHelper::safeTransfer: transfer failed");
    }

    function safeTransferFrom(
        address token,
        address from,
        address to,
        uint256 value
    ) internal {
        // bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), "TribeOneHelper::transferFrom: transferFrom failed");
    }

    function safeTransferETH(address to, uint256 value) internal {
        (bool success, ) = to.call{value: value}(new bytes(0));
        require(success, "TribeOneHelper::safeTransferETH: ETH transfer failed");
    }

    function safeTransferAsset(
        address token,
        address to,
        uint256 value
    ) internal {
        if (token == address(0)) {
            safeTransferETH(to, value);
        } else {
            safeTransfer(token, to, value);
        }
    }

    function safeTransferNFT(
        address _nft,
        address _from,
        address _to,
        TokenType _type,
        uint256 _tokenId
    ) internal {
        if (_type == TokenType.ERC721) {
            IERC721(_nft).safeTransferFrom(_from, _to, _tokenId);
        } else {
            IERC1155(_nft).safeTransferFrom(_from, _to, _tokenId, 1, "0x00");
        }
    }

    /**
     * @dev this function calculates expected price of NFT based on created LTV and fund amount,
     * LTV: 10000 = 100%; _slippage: 10000 = 100%
     */
    function getExpectedPrice(
        uint256 _fundAmount,
        uint256 _LTV,
        uint256 _slippage
    ) internal pure returns (uint256) {
        require(_LTV != 0, "TribeOneHelper: LTV should not be 0");
        return (_fundAmount * (10000 + _slippage)) / _LTV;
    }
}
function getExpectedPrice(
    uint256 _fundAmount,
    uint256 _LTV,
    uint256 _slippage
) internal pure returns (uint256) {
    require(_LTV != 0, "TribeOneHelper: LTV should not be 0");
    return (_fundAmount * (10000 + _slippage)) / _LTV;
}

/**
 * @dev this function calculates expected price of NFT based on created LTV and fund amount,
 * LTV: 10000 = 100%; _slippage: 10000 = 100%
 */