crypticorn 2.1.2__py3-none-any.whl → 2.1.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. crypticorn/common/auth.py +0 -28
  2. crypticorn/common/auth_client.py +14 -18
  3. crypticorn/common/errors.py +216 -253
  4. crypticorn/common/sorter.py +36 -0
  5. crypticorn/pay/client/__init__.py +1 -0
  6. crypticorn/pay/client/api/now_payments_api.py +3 -16
  7. crypticorn/pay/client/api/payments_api.py +0 -42
  8. crypticorn/pay/client/api/products_api.py +18 -57
  9. crypticorn/pay/client/configuration.py +2 -1
  10. crypticorn/pay/client/models/__init__.py +1 -0
  11. crypticorn/pay/client/models/body_create_now_invoice.py +98 -0
  12. crypticorn/pay/client/models/body_create_product.py +98 -0
  13. crypticorn/pay/client/models/body_get_products.py +87 -0
  14. crypticorn/pay/client/models/body_handle_now_webhook.py +98 -0
  15. crypticorn/pay/client/models/body_update_product.py +98 -0
  16. crypticorn/pay/client/models/now_webhook_payload.py +1 -1
  17. crypticorn/pay/client/models/product_model.py +9 -0
  18. crypticorn/pay/client/models/scope.py +56 -0
  19. crypticorn/trade/client/api/api_keys_api.py +5 -70
  20. crypticorn/trade/client/api/bots_api.py +4 -56
  21. crypticorn/trade/client/api/exchanges_api.py +2 -19
  22. crypticorn/trade/client/api/futures_trading_panel_api.py +6 -74
  23. crypticorn/trade/client/api/notifications_api.py +6 -87
  24. crypticorn/trade/client/api/orders_api.py +2 -15
  25. crypticorn/trade/client/api/strategies_api.py +4 -56
  26. crypticorn/trade/client/api/trading_actions_api.py +1 -14
  27. crypticorn/trade/client/configuration.py +2 -1
  28. crypticorn/trade/client/models/api_error_identifier.py +4 -0
  29. {crypticorn-2.1.2.dist-info → crypticorn-2.1.4.dist-info}/METADATA +1 -1
  30. {crypticorn-2.1.2.dist-info → crypticorn-2.1.4.dist-info}/RECORD +32 -25
  31. {crypticorn-2.1.2.dist-info → crypticorn-2.1.4.dist-info}/WHEEL +0 -0
  32. {crypticorn-2.1.2.dist-info → crypticorn-2.1.4.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,98 @@
1
+ # coding: utf-8
2
+
3
+ """
4
+ Payment API
5
+
6
+ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
7
+
8
+ The version of the OpenAPI document: 0.1.0
9
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
10
+
11
+ Do not edit the class manually.
12
+ """ # noqa: E501
13
+
14
+
15
+ from __future__ import annotations
16
+ import pprint
17
+ import re # noqa: F401
18
+ import json
19
+
20
+ from pydantic import BaseModel, ConfigDict
21
+ from typing import Any, ClassVar, Dict, List, Optional
22
+ from crypticorn.pay.client.models.now_create_invoice_req import NowCreateInvoiceReq
23
+ from crypticorn.pay.client.models.scope import Scope
24
+ from typing import Optional, Set
25
+ from typing_extensions import Self
26
+
27
+
28
+ class BodyCreateNowInvoice(BaseModel):
29
+ """
30
+ BodyCreateNowInvoice
31
+ """ # noqa: E501
32
+
33
+ body: NowCreateInvoiceReq
34
+ scopes: Optional[List[Scope]] = None
35
+ __properties: ClassVar[List[str]] = ["body", "scopes"]
36
+
37
+ model_config = ConfigDict(
38
+ populate_by_name=True,
39
+ validate_assignment=True,
40
+ protected_namespaces=(),
41
+ )
42
+
43
+ def to_str(self) -> str:
44
+ """Returns the string representation of the model using alias"""
45
+ return pprint.pformat(self.model_dump(by_alias=True))
46
+
47
+ def to_json(self) -> str:
48
+ """Returns the JSON representation of the model using alias"""
49
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
50
+ return json.dumps(self.to_dict())
51
+
52
+ @classmethod
53
+ def from_json(cls, json_str: str) -> Optional[Self]:
54
+ """Create an instance of BodyCreateNowInvoice from a JSON string"""
55
+ return cls.from_dict(json.loads(json_str))
56
+
57
+ def to_dict(self) -> Dict[str, Any]:
58
+ """Return the dictionary representation of the model using alias.
59
+
60
+ This has the following differences from calling pydantic's
61
+ `self.model_dump(by_alias=True)`:
62
+
63
+ * `None` is only added to the output dict for nullable fields that
64
+ were set at model initialization. Other fields with value `None`
65
+ are ignored.
66
+ """
67
+ excluded_fields: Set[str] = set([])
68
+
69
+ _dict = self.model_dump(
70
+ by_alias=True,
71
+ exclude=excluded_fields,
72
+ exclude_none=True,
73
+ )
74
+ # override the default output from pydantic by calling `to_dict()` of body
75
+ if self.body:
76
+ _dict["body"] = self.body.to_dict()
77
+ return _dict
78
+
79
+ @classmethod
80
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
81
+ """Create an instance of BodyCreateNowInvoice from a dict"""
82
+ if obj is None:
83
+ return None
84
+
85
+ if not isinstance(obj, dict):
86
+ return cls.model_validate(obj)
87
+
88
+ _obj = cls.model_validate(
89
+ {
90
+ "body": (
91
+ NowCreateInvoiceReq.from_dict(obj["body"])
92
+ if obj.get("body") is not None
93
+ else None
94
+ ),
95
+ "scopes": obj.get("scopes"),
96
+ }
97
+ )
98
+ return _obj
@@ -0,0 +1,98 @@
1
+ # coding: utf-8
2
+
3
+ """
4
+ Payment API
5
+
6
+ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
7
+
8
+ The version of the OpenAPI document: 0.1.0
9
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
10
+
11
+ Do not edit the class manually.
12
+ """ # noqa: E501
13
+
14
+
15
+ from __future__ import annotations
16
+ import pprint
17
+ import re # noqa: F401
18
+ import json
19
+
20
+ from pydantic import BaseModel, ConfigDict
21
+ from typing import Any, ClassVar, Dict, List, Optional
22
+ from crypticorn.pay.client.models.product_model import ProductModel
23
+ from crypticorn.pay.client.models.scope import Scope
24
+ from typing import Optional, Set
25
+ from typing_extensions import Self
26
+
27
+
28
+ class BodyCreateProduct(BaseModel):
29
+ """
30
+ BodyCreateProduct
31
+ """ # noqa: E501
32
+
33
+ product: ProductModel
34
+ scopes: Optional[List[Scope]] = None
35
+ __properties: ClassVar[List[str]] = ["product", "scopes"]
36
+
37
+ model_config = ConfigDict(
38
+ populate_by_name=True,
39
+ validate_assignment=True,
40
+ protected_namespaces=(),
41
+ )
42
+
43
+ def to_str(self) -> str:
44
+ """Returns the string representation of the model using alias"""
45
+ return pprint.pformat(self.model_dump(by_alias=True))
46
+
47
+ def to_json(self) -> str:
48
+ """Returns the JSON representation of the model using alias"""
49
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
50
+ return json.dumps(self.to_dict())
51
+
52
+ @classmethod
53
+ def from_json(cls, json_str: str) -> Optional[Self]:
54
+ """Create an instance of BodyCreateProduct from a JSON string"""
55
+ return cls.from_dict(json.loads(json_str))
56
+
57
+ def to_dict(self) -> Dict[str, Any]:
58
+ """Return the dictionary representation of the model using alias.
59
+
60
+ This has the following differences from calling pydantic's
61
+ `self.model_dump(by_alias=True)`:
62
+
63
+ * `None` is only added to the output dict for nullable fields that
64
+ were set at model initialization. Other fields with value `None`
65
+ are ignored.
66
+ """
67
+ excluded_fields: Set[str] = set([])
68
+
69
+ _dict = self.model_dump(
70
+ by_alias=True,
71
+ exclude=excluded_fields,
72
+ exclude_none=True,
73
+ )
74
+ # override the default output from pydantic by calling `to_dict()` of product
75
+ if self.product:
76
+ _dict["product"] = self.product.to_dict()
77
+ return _dict
78
+
79
+ @classmethod
80
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
81
+ """Create an instance of BodyCreateProduct from a dict"""
82
+ if obj is None:
83
+ return None
84
+
85
+ if not isinstance(obj, dict):
86
+ return cls.model_validate(obj)
87
+
88
+ _obj = cls.model_validate(
89
+ {
90
+ "product": (
91
+ ProductModel.from_dict(obj["product"])
92
+ if obj.get("product") is not None
93
+ else None
94
+ ),
95
+ "scopes": obj.get("scopes"),
96
+ }
97
+ )
98
+ return _obj
@@ -0,0 +1,87 @@
1
+ # coding: utf-8
2
+
3
+ """
4
+ Payment API
5
+
6
+ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
7
+
8
+ The version of the OpenAPI document: 0.1.0
9
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
10
+
11
+ Do not edit the class manually.
12
+ """ # noqa: E501
13
+
14
+
15
+ from __future__ import annotations
16
+ import pprint
17
+ import re # noqa: F401
18
+ import json
19
+
20
+ from pydantic import BaseModel, ConfigDict
21
+ from typing import Any, ClassVar, Dict, List, Optional
22
+ from crypticorn.pay.client.models.scope import Scope
23
+ from typing import Optional, Set
24
+ from typing_extensions import Self
25
+
26
+
27
+ class BodyGetProducts(BaseModel):
28
+ """
29
+ BodyGetProducts
30
+ """ # noqa: E501
31
+
32
+ query: Optional[Dict[str, Any]] = None
33
+ scopes: Optional[List[Scope]] = None
34
+ __properties: ClassVar[List[str]] = ["query", "scopes"]
35
+
36
+ model_config = ConfigDict(
37
+ populate_by_name=True,
38
+ validate_assignment=True,
39
+ protected_namespaces=(),
40
+ )
41
+
42
+ def to_str(self) -> str:
43
+ """Returns the string representation of the model using alias"""
44
+ return pprint.pformat(self.model_dump(by_alias=True))
45
+
46
+ def to_json(self) -> str:
47
+ """Returns the JSON representation of the model using alias"""
48
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
49
+ return json.dumps(self.to_dict())
50
+
51
+ @classmethod
52
+ def from_json(cls, json_str: str) -> Optional[Self]:
53
+ """Create an instance of BodyGetProducts from a JSON string"""
54
+ return cls.from_dict(json.loads(json_str))
55
+
56
+ def to_dict(self) -> Dict[str, Any]:
57
+ """Return the dictionary representation of the model using alias.
58
+
59
+ This has the following differences from calling pydantic's
60
+ `self.model_dump(by_alias=True)`:
61
+
62
+ * `None` is only added to the output dict for nullable fields that
63
+ were set at model initialization. Other fields with value `None`
64
+ are ignored.
65
+ """
66
+ excluded_fields: Set[str] = set([])
67
+
68
+ _dict = self.model_dump(
69
+ by_alias=True,
70
+ exclude=excluded_fields,
71
+ exclude_none=True,
72
+ )
73
+ return _dict
74
+
75
+ @classmethod
76
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
77
+ """Create an instance of BodyGetProducts from a dict"""
78
+ if obj is None:
79
+ return None
80
+
81
+ if not isinstance(obj, dict):
82
+ return cls.model_validate(obj)
83
+
84
+ _obj = cls.model_validate(
85
+ {"query": obj.get("query"), "scopes": obj.get("scopes")}
86
+ )
87
+ return _obj
@@ -0,0 +1,98 @@
1
+ # coding: utf-8
2
+
3
+ """
4
+ Payment API
5
+
6
+ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
7
+
8
+ The version of the OpenAPI document: 0.1.0
9
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
10
+
11
+ Do not edit the class manually.
12
+ """ # noqa: E501
13
+
14
+
15
+ from __future__ import annotations
16
+ import pprint
17
+ import re # noqa: F401
18
+ import json
19
+
20
+ from pydantic import BaseModel, ConfigDict
21
+ from typing import Any, ClassVar, Dict, List, Optional
22
+ from crypticorn.pay.client.models.now_webhook_payload import NowWebhookPayload
23
+ from crypticorn.pay.client.models.scope import Scope
24
+ from typing import Optional, Set
25
+ from typing_extensions import Self
26
+
27
+
28
+ class BodyHandleNowWebhook(BaseModel):
29
+ """
30
+ BodyHandleNowWebhook
31
+ """ # noqa: E501
32
+
33
+ body: NowWebhookPayload
34
+ scopes: Optional[List[Scope]] = None
35
+ __properties: ClassVar[List[str]] = ["body", "scopes"]
36
+
37
+ model_config = ConfigDict(
38
+ populate_by_name=True,
39
+ validate_assignment=True,
40
+ protected_namespaces=(),
41
+ )
42
+
43
+ def to_str(self) -> str:
44
+ """Returns the string representation of the model using alias"""
45
+ return pprint.pformat(self.model_dump(by_alias=True))
46
+
47
+ def to_json(self) -> str:
48
+ """Returns the JSON representation of the model using alias"""
49
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
50
+ return json.dumps(self.to_dict())
51
+
52
+ @classmethod
53
+ def from_json(cls, json_str: str) -> Optional[Self]:
54
+ """Create an instance of BodyHandleNowWebhook from a JSON string"""
55
+ return cls.from_dict(json.loads(json_str))
56
+
57
+ def to_dict(self) -> Dict[str, Any]:
58
+ """Return the dictionary representation of the model using alias.
59
+
60
+ This has the following differences from calling pydantic's
61
+ `self.model_dump(by_alias=True)`:
62
+
63
+ * `None` is only added to the output dict for nullable fields that
64
+ were set at model initialization. Other fields with value `None`
65
+ are ignored.
66
+ """
67
+ excluded_fields: Set[str] = set([])
68
+
69
+ _dict = self.model_dump(
70
+ by_alias=True,
71
+ exclude=excluded_fields,
72
+ exclude_none=True,
73
+ )
74
+ # override the default output from pydantic by calling `to_dict()` of body
75
+ if self.body:
76
+ _dict["body"] = self.body.to_dict()
77
+ return _dict
78
+
79
+ @classmethod
80
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
81
+ """Create an instance of BodyHandleNowWebhook from a dict"""
82
+ if obj is None:
83
+ return None
84
+
85
+ if not isinstance(obj, dict):
86
+ return cls.model_validate(obj)
87
+
88
+ _obj = cls.model_validate(
89
+ {
90
+ "body": (
91
+ NowWebhookPayload.from_dict(obj["body"])
92
+ if obj.get("body") is not None
93
+ else None
94
+ ),
95
+ "scopes": obj.get("scopes"),
96
+ }
97
+ )
98
+ return _obj
@@ -0,0 +1,98 @@
1
+ # coding: utf-8
2
+
3
+ """
4
+ Payment API
5
+
6
+ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
7
+
8
+ The version of the OpenAPI document: 0.1.0
9
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
10
+
11
+ Do not edit the class manually.
12
+ """ # noqa: E501
13
+
14
+
15
+ from __future__ import annotations
16
+ import pprint
17
+ import re # noqa: F401
18
+ import json
19
+
20
+ from pydantic import BaseModel, ConfigDict
21
+ from typing import Any, ClassVar, Dict, List, Optional
22
+ from crypticorn.pay.client.models.product_model import ProductModel
23
+ from crypticorn.pay.client.models.scope import Scope
24
+ from typing import Optional, Set
25
+ from typing_extensions import Self
26
+
27
+
28
+ class BodyUpdateProduct(BaseModel):
29
+ """
30
+ BodyUpdateProduct
31
+ """ # noqa: E501
32
+
33
+ product: ProductModel
34
+ scopes: Optional[List[Scope]] = None
35
+ __properties: ClassVar[List[str]] = ["product", "scopes"]
36
+
37
+ model_config = ConfigDict(
38
+ populate_by_name=True,
39
+ validate_assignment=True,
40
+ protected_namespaces=(),
41
+ )
42
+
43
+ def to_str(self) -> str:
44
+ """Returns the string representation of the model using alias"""
45
+ return pprint.pformat(self.model_dump(by_alias=True))
46
+
47
+ def to_json(self) -> str:
48
+ """Returns the JSON representation of the model using alias"""
49
+ # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead
50
+ return json.dumps(self.to_dict())
51
+
52
+ @classmethod
53
+ def from_json(cls, json_str: str) -> Optional[Self]:
54
+ """Create an instance of BodyUpdateProduct from a JSON string"""
55
+ return cls.from_dict(json.loads(json_str))
56
+
57
+ def to_dict(self) -> Dict[str, Any]:
58
+ """Return the dictionary representation of the model using alias.
59
+
60
+ This has the following differences from calling pydantic's
61
+ `self.model_dump(by_alias=True)`:
62
+
63
+ * `None` is only added to the output dict for nullable fields that
64
+ were set at model initialization. Other fields with value `None`
65
+ are ignored.
66
+ """
67
+ excluded_fields: Set[str] = set([])
68
+
69
+ _dict = self.model_dump(
70
+ by_alias=True,
71
+ exclude=excluded_fields,
72
+ exclude_none=True,
73
+ )
74
+ # override the default output from pydantic by calling `to_dict()` of product
75
+ if self.product:
76
+ _dict["product"] = self.product.to_dict()
77
+ return _dict
78
+
79
+ @classmethod
80
+ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]:
81
+ """Create an instance of BodyUpdateProduct from a dict"""
82
+ if obj is None:
83
+ return None
84
+
85
+ if not isinstance(obj, dict):
86
+ return cls.model_validate(obj)
87
+
88
+ _obj = cls.model_validate(
89
+ {
90
+ "product": (
91
+ ProductModel.from_dict(obj["product"])
92
+ if obj.get("product") is not None
93
+ else None
94
+ ),
95
+ "scopes": obj.get("scopes"),
96
+ }
97
+ )
98
+ return _obj
@@ -36,7 +36,7 @@ class NowWebhookPayload(BaseModel):
36
36
  actually_paid_at_fiat: Union[StrictFloat, StrictInt] = Field(
37
37
  description="Actually paid amount in fiat currency"
38
38
  )
39
- fee: NowFeeStructure = Field(description="Fee structure for the payment")
39
+ fee: NowFeeStructure
40
40
  invoice_id: StrictInt = Field(description="Associated invoice ID")
41
41
  order_description: StrictStr = Field(description="Order description")
42
42
  order_id: StrictStr = Field(description="Internal order ID")
@@ -27,6 +27,7 @@ from pydantic import (
27
27
  StrictStr,
28
28
  )
29
29
  from typing import Any, ClassVar, Dict, List, Optional, Union
30
+ from crypticorn.pay.client.models.scope import Scope
30
31
  from typing import Optional, Set
31
32
  from typing_extensions import Self
32
33
 
@@ -39,6 +40,7 @@ class ProductModel(BaseModel):
39
40
  id: Optional[StrictStr] = None
40
41
  name: StrictStr = Field(description="Product name")
41
42
  price: Union[StrictFloat, StrictInt] = Field(description="Product price")
43
+ scopes: Optional[List[Scope]] = None
42
44
  duration: StrictInt = Field(
43
45
  description="Product duration in days. 0 means unlimited."
44
46
  )
@@ -48,6 +50,7 @@ class ProductModel(BaseModel):
48
50
  "id",
49
51
  "name",
50
52
  "price",
53
+ "scopes",
51
54
  "duration",
52
55
  "description",
53
56
  "is_active",
@@ -95,6 +98,11 @@ class ProductModel(BaseModel):
95
98
  if self.id is None and "id" in self.model_fields_set:
96
99
  _dict["id"] = None
97
100
 
101
+ # set to None if scopes (nullable) is None
102
+ # and model_fields_set contains the field
103
+ if self.scopes is None and "scopes" in self.model_fields_set:
104
+ _dict["scopes"] = None
105
+
98
106
  return _dict
99
107
 
100
108
  @classmethod
@@ -111,6 +119,7 @@ class ProductModel(BaseModel):
111
119
  "id": obj.get("id"),
112
120
  "name": obj.get("name"),
113
121
  "price": obj.get("price"),
122
+ "scopes": obj.get("scopes"),
114
123
  "duration": obj.get("duration"),
115
124
  "description": obj.get("description"),
116
125
  "is_active": obj.get("is_active"),
@@ -0,0 +1,56 @@
1
+ # coding: utf-8
2
+
3
+ """
4
+ Payment API
5
+
6
+ No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
7
+
8
+ The version of the OpenAPI document: 0.1.0
9
+ Generated by OpenAPI Generator (https://openapi-generator.tech)
10
+
11
+ Do not edit the class manually.
12
+ """ # noqa: E501
13
+
14
+
15
+ from __future__ import annotations
16
+ import json
17
+ from enum import Enum
18
+ from typing_extensions import Self
19
+
20
+
21
+ class Scope(str, Enum):
22
+ """
23
+ The permission scopes for the API.
24
+ """
25
+
26
+ """
27
+ allowed enum values
28
+ """
29
+ READ_COLON_HIVE_COLON_MODEL = "read:hive:model"
30
+ READ_COLON_HIVE_COLON_DATA = "read:hive:data"
31
+ WRITE_COLON_HIVE_COLON_MODEL = "write:hive:model"
32
+ READ_COLON_TRADE_COLON_BOTS = "read:trade:bots"
33
+ WRITE_COLON_TRADE_COLON_BOTS = "write:trade:bots"
34
+ READ_COLON_TRADE_COLON_API_KEYS = "read:trade:api_keys"
35
+ WRITE_COLON_TRADE_COLON_API_KEYS = "write:trade:api_keys"
36
+ READ_COLON_TRADE_COLON_ORDERS = "read:trade:orders"
37
+ READ_COLON_TRADE_COLON_ACTIONS = "read:trade:actions"
38
+ WRITE_COLON_TRADE_COLON_ACTIONS = "write:trade:actions"
39
+ READ_COLON_TRADE_COLON_EXCHANGES = "read:trade:exchanges"
40
+ READ_COLON_TRADE_COLON_FUTURES = "read:trade:futures"
41
+ WRITE_COLON_TRADE_COLON_FUTURES = "write:trade:futures"
42
+ READ_COLON_TRADE_COLON_NOTIFICATIONS = "read:trade:notifications"
43
+ WRITE_COLON_TRADE_COLON_NOTIFICATIONS = "write:trade:notifications"
44
+ READ_COLON_TRADE_COLON_STRATEGIES = "read:trade:strategies"
45
+ WRITE_COLON_TRADE_COLON_STRATEGIES = "write:trade:strategies"
46
+ READ_COLON_PAY_COLON_PAYMENTS = "read:pay:payments"
47
+ READ_COLON_PAY_COLON_PRODUCTS = "read:pay:products"
48
+ WRITE_COLON_PAY_COLON_PRODUCTS = "write:pay:products"
49
+ READ_COLON_PAY_COLON_NOW = "read:pay:now"
50
+ WRITE_COLON_PAY_COLON_NOW = "write:pay:now"
51
+ READ_COLON_PREDICTIONS = "read:predictions"
52
+
53
+ @classmethod
54
+ def from_json(cls, json_str: str) -> Self:
55
+ """Create an instance of Scope from a JSON string"""
56
+ return cls(json.loads(json_str))