aboutsummaryrefslogtreecommitdiffstats
path: root/python-packages/order_utils/src/zero_ex/json_schemas/__init__.py
blob: a76a2fa3b2b51cc40057c11aa41e180e021f2414 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
"""JSON schemas and associated utilities."""

from os import path
import json
from typing import Mapping

from pkg_resources import resource_string
import jsonschema


class _LocalRefResolver(jsonschema.RefResolver):
    """Resolve package-local JSON schema id's."""

    def __init__(self):
        """Initialize a new instance."""
        self.ref_to_file = {
            "/addressSchema": "address_schema.json",
            "/hexSchema": "hex_schema.json",
            "/orderSchema": "order_schema.json",
            "/wholeNumberSchema": "whole_number_schema.json",
            "/ECSignature": "ec_signature_schema.json",
            "/signedOrderSchema": "signed_order_schema.json",
            "/ecSignatureParameterSchema": (
                "ec_signature_parameter_schema.json" + ""
            ),
        }
        jsonschema.RefResolver.__init__(self, "", "")

    def resolve_from_url(self, url: str) -> str:
        """Resolve the given URL.

        :param url: a string representing the URL of the JSON schema to fetch.
        :returns: a string representing the deserialized JSON schema
        :raises jsonschema.ValidationError: when the resource associated with
                   `url` does not exist.
        """
        ref = url.replace("file://", "")
        if ref in self.ref_to_file:
            return json.loads(
                resource_string(
                    "zero_ex.json_schemas", f"schemas/{self.ref_to_file[ref]}"
                )
            )
        raise jsonschema.ValidationError(
            f"Unknown ref '{ref}'. "
            + f"Known refs: {list(self.ref_to_file.keys())}."
        )


# Instantiate the `_LocalRefResolver()` only once so that `assert_valid()` can
# perform multiple schema validations without reading from disk the schema
# every time.
_LOCAL_RESOLVER = _LocalRefResolver()


def assert_valid(data: Mapping, schema_id: str) -> None:
    """Validate the given `data` against the specified `schema`.

    :param data: Python dictionary to be validated as a JSON object.
    :param schema_id: id property of the JSON schema to validate against.  Must
        be one of those listed in `the 0x JSON schema files
        <https://github.com/0xProject/0x-monorepo/tree/development/packages/json-schemas/schemas>`_.

    Raises an exception if validation fails.

    >>> assert_valid(
    ...     {'v': 27, 'r': '0x'+'f'*64, 's': '0x'+'f'*64},
    ...     '/ECSignature',
    ... )
    """
    # noqa

    _, schema = _LOCAL_RESOLVER.resolve(schema_id)
    jsonschema.validate(data, schema, resolver=_LOCAL_RESOLVER)