library LibSignature {
    enum SignatureMethod {ETH_SIGN, EIP712}

    struct OrderSignature {
        bytes32 config;
        bytes32 r;
        bytes32 s;
    }

    /**
     * Validate a signature given a hash calculated from the order data, the signer, and the
     * signature data passed in with the order.
     *
     * This function will revert the transaction if the signature method is invalid.
     *
     * @param signature The signature data passed along with the order to validate against
     * @param hash Hash bytes calculated by taking the hash of the passed order data
     * @param signerAddress The address of the signer
     * @return True if the calculated signature matches the order signature data, false otherwise.
     */
    function isValidSignature(OrderSignature memory signature, bytes32 hash, address signerAddress)
        internal
        pure
        returns (bool)
    {
        uint8 method = uint8(signature.config[1]);
        address recovered;
        uint8 v = uint8(signature.config[0]);

        if (method == uint8(SignatureMethod.ETH_SIGN)) {
            recovered = recover(
                keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)),
                v,
                signature.r,
                signature.s
            );
        } else if (method == uint8(SignatureMethod.EIP712)) {
            recovered = recover(hash, v, signature.r, signature.s);
        } else {
            revert("invalid sign method");
        }

        return signerAddress == recovered;
    }

    // see "@openzeppelin/contracts/cryptography/ECDSA.sol"
    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            revert("ECDSA: invalid signature 's' value");
        }

        if (v != 27 && v != 28) {
            revert("ECDSA: invalid signature 'v' value");
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        require(signer != address(0), "ECDSA: invalid signature");

        return signer;
    }
}
function isValidSignature(OrderSignature memory signature, bytes32 hash, address signerAddress)
    internal
    pure
    returns (bool)
{
    uint8 method = uint8(signature.config[1]);
    address recovered;
    uint8 v = uint8(signature.config[0]);

    if (method == uint8(SignatureMethod.ETH_SIGN)) {
        recovered = recover(
            keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)),
            v,
            signature.r,
            signature.s
        );
    } else if (method == uint8(SignatureMethod.EIP712)) {
        recovered = recover(hash, v, signature.r, signature.s);
    } else {
        revert("invalid sign method");
    }

    return signerAddress == recovered;
}

/**
 * Validate a signature given a hash calculated from the order data, the signer, and the
 * signature data passed in with the order.
 *
 * This function will revert the transaction if the signature method is invalid.
 *
 * @param signature The signature data passed along with the order to validate against
 * @param hash Hash bytes calculated by taking the hash of the passed order data
 * @param signerAddress The address of the signer
 * @return True if the calculated signature matches the order signature data, false otherwise.
 */