diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 4b95e9e..34b7ff1 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,6 +17,9 @@ jobs: with: python-version: '3.11' + - name: Install Python dependencies + run: pip install jsonschema + - name: Run wallet validation tests run: python tests/test_wallet_validation.py @@ -30,4 +33,7 @@ jobs: run: python scripts/proxy_urls.py - name: Run wallet validation tests on proxy file - run: WALLET_FILE=wallets-v2.proxy.json python tests/test_wallet_validation.py \ No newline at end of file + run: WALLET_FILE=wallets-v2.proxy.json python tests/test_wallet_validation.py + + - name: Run Json Schema validate test + run: python tests/test_jsonschema.py --wallets-file=wallets-v2.json --json-schema-file=wallets-v2.schema.json diff --git a/tests/test_jsonschema.py b/tests/test_jsonschema.py new file mode 100644 index 0000000..bbe67e6 --- /dev/null +++ b/tests/test_jsonschema.py @@ -0,0 +1,65 @@ +import argparse +import json +import sys +from pathlib import Path + +import jsonschema +from jsonschema import Draft7Validator + + +class JsonSchemaNamespace(argparse.Namespace): + wallets_file: Path + json_schema_file: Path + + +def create_argument_parser() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser( + description="Checking a json file using json-schema", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +Examples: + python test_jsonschema.py --wallets-file=wallets-v2.json --json-schema-file=wallets-v2.schema.json + """.strip(), + ) + + parser.add_argument( + "--wallets-file", + type=Path, + required=True, + help="Path to the 'wallets-v2.json' file", + ) + + parser.add_argument( + "--json-schema-file", + type=Path, + required=True, + help="Path to the 'wallets-v2.json' schema file", + ) + + return parser + + +def main() -> None: + parser = create_argument_parser() + args = parser.parse_args(namespace=JsonSchemaNamespace()) + + wallets = json.loads(args.wallets_file.read_bytes()) + json_schema = json.loads(args.json_schema_file.read_bytes()) + + error_message: str | None = None + try: + jsonschema.validate(instance=wallets, schema=json_schema, cls=Draft7Validator) + except jsonschema.exceptions.ValidationError as e: + error_message = str(e) + + if error_message is None: + print("ALL TESTS PASSED") + sys.exit(0) + else: + print("TESTS FAILED:\n") + print(error_message) + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/wallets-v2.schema.json b/wallets-v2.schema.json new file mode 100644 index 0000000..2161dc2 --- /dev/null +++ b/wallets-v2.schema.json @@ -0,0 +1,183 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "app_name": { + "type": "string", + "description": "ID of your wallet", + "minLength": 1 + }, + "name": { + "type": "string", + "description": "Name of your wallet", + "minLength": 1 + }, + "image": { + "type": "string", + "description": "URL to the icon of your wallet", + "pattern": "^https://.+png$" + }, + "tondns": { + "type": "string", + "pattern": ".+ton$" + }, + "about_url": { + "type": "string", + "description": "Info or landing page of your wallet", + "pattern": "^https://.+" + }, + "universal_url": { + "type": "string", + "description": "Base part of your wallet universal url", + "pattern": "^https://.+" + }, + "deepLink": { + "type": "string", + "minLength": 1 + }, + "bridge": { + "type": "array", + "minItems": 1, + "maxItems": 2, + "items": { + "anyOf": [ + { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "js" + ] + }, + "key": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "type", + "key" + ] + }, + { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string", + "enum": [ + "sse" + ] + }, + "url": { + "type": "string", + "pattern": "^https://.+" + } + }, + "required": [ + "type", + "url" + ] + } + ] + } + }, + "platforms": { + "type": "array", + "description": "List of platforms on which your wallet works", + "minItems": 1, + "uniqueItems": true, + "items": { + "type": "string", + "enum": [ + "ios", + "android", + "chrome", + "firefox", + "safari", + "macos", + "windows", + "linux" + ] + } + }, + "features": { + "type": "array", + "description": "List of supported TON Connect features and their capabilities", + "minItems": 1, + "items": { + "anyOf": [ + { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "enum": [ + "SendTransaction" + ] + }, + "maxMessages": { + "type": "integer", + "minimum": 0 + }, + "extraCurrencySupported": { + "type": "boolean" + } + }, + "required": [ + "name", + "maxMessages", + "extraCurrencySupported" + ] + }, + { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "enum": [ + "SignData" + ] + }, + "types": { + "type": "array", + "minItems": 1, + "uniqueItems": true, + "items": { + "type": "string", + "enum": [ + "text", + "binary", + "cell" + ] + } + } + }, + "required": [ + "name", + "types" + ] + } + ] + } + } + }, + "required": [ + "app_name", + "name", + "image", + "about_url", + "bridge", + "platforms", + "features" + ] + } +}