-
Notifications
You must be signed in to change notification settings - Fork 10
Spot Trade Busts #48
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Spot Trade Busts #48
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| from __future__ import annotations | ||
| from typing import Any, List, Dict, Optional | ||
| from pydantic import BaseModel, Field | ||
| from sdk.async_api.channel_data_message_type import ChannelDataMessageType | ||
| from sdk.async_api.spot_trade_bust import SpotTradeBust | ||
| class MarketSpotTradeBustUpdatePayload(BaseModel): | ||
| type: ChannelDataMessageType = Field(description='''Message type for channel data updates''') | ||
| timestamp: float = Field(description='''Update timestamp (milliseconds)''') | ||
| channel: str = Field(description='''Channel pattern for market spot trade busts''') | ||
| data: List[SpotTradeBust] = Field() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| from __future__ import annotations | ||
| from typing import Any, Dict, Optional | ||
| from pydantic import model_serializer, model_validator, BaseModel, Field | ||
| from sdk.async_api.side import Side | ||
| class SpotTradeBust(BaseModel): | ||
| symbol: str = Field(description='''Trading symbol (e.g., BTCRUSDPERP, WETHRUSD)''') | ||
| account_id: int = Field(alias='''accountId''') | ||
| counterparty_account_id: int = Field(alias='''counterpartyAccountId''') | ||
| qty: str = Field() | ||
| side: Side = Field(description='''Order side (B = Buy/Bid, A = Ask/Sell)''') | ||
| price: str = Field() | ||
| reason: str = Field(description='''Hex-encoded revert reason bytes''') | ||
| timestamp: int = Field() | ||
| transaction_hash: str = Field(description='''Transaction hash''', alias='''transactionHash''') | ||
| additional_properties: Optional[dict[str, Any]] = Field(default=None, exclude=True) | ||
|
Comment on lines
+3
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # First, let's locate and examine the async spot trade bust file
find . -name "spot_trade_bust.py" -type fRepository: Reya-Labs/reya-python-sdk Length of output: 144 🏁 Script executed: # Now let's examine the async model file to see lines 3-15 and the full file
cat -n sdk/async_api/spot_trade_bust.py | head -50Repository: Reya-Labs/reya-python-sdk Length of output: 2819 🏁 Script executed: # Let's check the OpenAPI counterpart for comparison
cat -n sdk/open_api/models/spot_trade_bust.py | head -80Repository: Reya-Labs/reya-python-sdk Length of output: 3737 🏁 Script executed: # Check if model_config is used elsewhere in the async_api directory
rg "model_config\s*=" sdk/async_api/ -A 2Repository: Reya-Labs/reya-python-sdk Length of output: 51 🏁 Script executed: # Let's verify Pydantic v2 behavior with aliases and populate_by_name
python3 << 'EOF'
from pydantic import BaseModel, Field, ConfigDict
# Test case 1: Without populate_by_name (like the async model)
class ModelWithoutPopulate(BaseModel):
account_id: int = Field(alias='accountId')
# Test case 2: With populate_by_name (like the OpenAPI model)
class ModelWithPopulate(BaseModel):
model_config = ConfigDict(populate_by_name=True)
account_id: int = Field(alias='accountId')
print("Test 1: Without populate_by_name")
try:
m1 = ModelWithoutPopulate(account_id=123)
print(f" Success: {m1}")
except Exception as e:
print(f" Failed: {type(e).__name__}: {e}")
try:
m1 = ModelWithoutPopulate(accountId=123)
print(f" Success with alias: {m1}")
except Exception as e:
print(f" Failed with alias: {type(e).__name__}: {e}")
print("\nTest 2: With populate_by_name")
try:
m2 = ModelWithPopulate(account_id=123)
print(f" Success: {m2}")
except Exception as e:
print(f" Failed: {type(e).__name__}: {e}")
try:
m2 = ModelWithPopulate(accountId=123)
print(f" Success with alias: {m2}")
except Exception as e:
print(f" Failed with alias: {type(e).__name__}: {e}")
EOFRepository: Reya-Labs/reya-python-sdk Length of output: 472 🏁 Script executed: # Check if there are any existing usages of SpotTradeBust in async_api that might reveal the issue
rg "SpotTradeBust" sdk/async_api/ -B 2 -A 5Repository: Reya-Labs/reya-python-sdk Length of output: 2707 🏁 Script executed: # Check line length to verify it complies with the 120 character limit
python3 << 'EOF'
with open('sdk/async_api/spot_trade_bust.py', 'r') as f:
lines = f.readlines()
for i, line in enumerate(lines[2:16], start=3): # lines 3-15
line_len = len(line.rstrip('\n'))
status = "OK" if line_len <= 120 else "EXCEEDS"
print(f"Line {i}: {line_len:3d} chars {status}")
if line_len > 120:
print(f" Content: {line.rstrip()}")
EOFRepository: Reya-Labs/reya-python-sdk Length of output: 369 Add This model has aliased fields ( 🔧 Suggested fix-from pydantic import model_serializer, model_validator, BaseModel, Field
+from pydantic import ConfigDict, model_serializer, model_validator, BaseModel, Field
from sdk.async_api.side import Side
class SpotTradeBust(BaseModel):
+ model_config = ConfigDict(populate_by_name=True)
symbol: str = Field(description='''Trading symbol (e.g., BTCRUSDPERP, WETHRUSD)''')🤖 Prompt for AI Agents |
||
|
|
||
| @model_serializer(mode='wrap') | ||
| def custom_serializer(self, handler): | ||
| serialized_self = handler(self) | ||
| additional_properties = getattr(self, "additional_properties") | ||
| if additional_properties is not None: | ||
| for key, value in additional_properties.items(): | ||
| # Never overwrite existing values, to avoid clashes | ||
| if not key in serialized_self: | ||
| serialized_self[key] = value | ||
|
|
||
| return serialized_self | ||
|
|
||
| @model_validator(mode='before') | ||
| @classmethod | ||
| def unwrap_additional_properties(cls, data): | ||
| if not isinstance(data, dict): | ||
| data = data.model_dump() | ||
| json_properties = list(data.keys()) | ||
| known_object_properties = ['symbol', 'account_id', 'counterparty_account_id', 'qty', 'side', 'price', 'reason', 'timestamp', 'transaction_hash', 'additional_properties'] | ||
| unknown_object_properties = [element for element in json_properties if element not in known_object_properties] | ||
| # Ignore attempts that validate regular models, only when unknown input is used we add unwrap extensions | ||
| if len(unknown_object_properties) == 0: | ||
| return data | ||
|
|
||
| known_json_properties = ['symbol', 'accountId', 'counterpartyAccountId', 'qty', 'side', 'price', 'reason', 'timestamp', 'transactionHash', 'additionalProperties'] | ||
| additional_properties = data.get('additional_properties', {}) | ||
| for obj_key in unknown_object_properties: | ||
| if not known_json_properties.__contains__(obj_key): | ||
| additional_properties[obj_key] = data.pop(obj_key, None) | ||
| data['additional_properties'] = additional_properties | ||
| return data | ||
|
Comment on lines
+29
to
+47
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Guard the pre-validator against non-model inputs.
🔧 Suggested fix `@model_validator`(mode='before')
`@classmethod`
- def unwrap_additional_properties(cls, data):
- if not isinstance(data, dict):
- data = data.model_dump()
+ def unwrap_additional_properties(cls, data: Any) -> Any:
+ if isinstance(data, BaseModel):
+ data = data.model_dump()
+ elif not isinstance(data, dict):
+ return data
json_properties = list(data.keys())
known_object_properties = ['symbol', 'account_id', 'counterparty_account_id', 'qty', 'side', 'price', 'reason', 'timestamp', 'transaction_hash', 'additional_properties']
unknown_object_properties = [element for element in json_properties if element not in known_object_properties]
# Ignore attempts that validate regular models, only when unknown input is used we add unwrap extensions
if len(unknown_object_properties) == 0:
return data
known_json_properties = ['symbol', 'accountId', 'counterpartyAccountId', 'qty', 'side', 'price', 'reason', 'timestamp', 'transactionHash', 'additionalProperties']
- additional_properties = data.get('additional_properties', {})
+ additional_properties = data.get('additional_properties') or {}🧰 Tools🪛 Ruff (0.15.5)[warning] 31-31: Missing return type annotation for classmethod (ANN206) 🤖 Prompt for AI Agents |
||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,10 @@ | ||||||||||||||||||||||||||||||||||||||
| from __future__ import annotations | ||||||||||||||||||||||||||||||||||||||
| from typing import Any, List, Dict, Optional | ||||||||||||||||||||||||||||||||||||||
| from pydantic import BaseModel, Field | ||||||||||||||||||||||||||||||||||||||
| from sdk.async_api.channel_data_message_type import ChannelDataMessageType | ||||||||||||||||||||||||||||||||||||||
| from sdk.async_api.spot_trade_bust import SpotTradeBust | ||||||||||||||||||||||||||||||||||||||
| class WalletSpotTradeBustUpdatePayload(BaseModel): | ||||||||||||||||||||||||||||||||||||||
| type: ChannelDataMessageType = Field(description='''Message type for channel data updates''') | ||||||||||||||||||||||||||||||||||||||
| timestamp: float = Field(description='''Update timestamp (milliseconds)''') | ||||||||||||||||||||||||||||||||||||||
| channel: str = Field(description='''Channel pattern for wallet spot trade busts''') | ||||||||||||||||||||||||||||||||||||||
| data: List[SpotTradeBust] = Field() | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+2
to
+10
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial Use built-in generics in this new payload model. Ruff is already flagging UP035 here. With the repo's Python 3.12 baseline, ♻️ Minimal cleanup-from typing import Any, List, Dict, Optional
from pydantic import BaseModel, Field
from sdk.async_api.channel_data_message_type import ChannelDataMessageType
from sdk.async_api.spot_trade_bust import SpotTradeBust
class WalletSpotTradeBustUpdatePayload(BaseModel):
type: ChannelDataMessageType = Field(description='''Message type for channel data updates''')
timestamp: float = Field(description='''Update timestamp (milliseconds)''')
channel: str = Field(description='''Channel pattern for wallet spot trade busts''')
- data: List[SpotTradeBust] = Field()
+ data: list[SpotTradeBust] = Field()As per coding guidelines, "Require Python 3.12+ for runtime and Python 3.10 for type checking with strict mypy configuration". 📝 Committable suggestion
Suggested change
🧰 Tools🪛 Ruff (0.15.5)[warning] 2-2: (UP035) [warning] 2-2: (UP035) 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Use built-in generics in this new payload model.
Ruff is already flagging UP035 here. With the repo's Python 3.12 baseline,
list[SpotTradeBust]should replaceList[SpotTradeBust]in new code.♻️ Minimal cleanup
As per coding guidelines, "Require Python 3.12+ for runtime and Python 3.10 for type checking with strict mypy configuration".
📝 Committable suggestion
🧰 Tools
🪛 Ruff (0.15.5)
[warning] 2-2:
typing.Listis deprecated, uselistinstead(UP035)
[warning] 2-2:
typing.Dictis deprecated, usedictinstead(UP035)
🤖 Prompt for AI Agents