meshtrade 0.0.8__py3-none-any.whl → 0.0.11__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.

Potentially problematic release.


This version of meshtrade might be problematic. Click here for more details.

Files changed (157) hide show
  1. buf/validate/validate_pb2.py +450 -0
  2. buf/validate/validate_pb2.pyi +627 -0
  3. meshtrade/common/__init__.py +28 -0
  4. meshtrade/common/config.py +30 -0
  5. meshtrade/common/grpc_client.py +202 -0
  6. meshtrade/compliance/client/v1/__init__.py +65 -7
  7. meshtrade/compliance/client/v1/client_pb2.py +2 -2
  8. meshtrade/compliance/client/v1/client_pb2_grpc.py +4 -0
  9. meshtrade/compliance/client/v1/company_pb2.py +2 -2
  10. meshtrade/compliance/client/v1/company_pb2_grpc.py +4 -0
  11. meshtrade/compliance/client/v1/company_representative_pb2.py +2 -2
  12. meshtrade/compliance/client/v1/company_representative_pb2_grpc.py +4 -0
  13. meshtrade/compliance/client/v1/company_representative_role_pb2.py +2 -2
  14. meshtrade/compliance/client/v1/company_representative_role_pb2_grpc.py +4 -0
  15. meshtrade/compliance/client/v1/fund_pb2.py +2 -2
  16. meshtrade/compliance/client/v1/fund_pb2_grpc.py +4 -0
  17. meshtrade/compliance/client/v1/identification_document_type_pb2.py +2 -2
  18. meshtrade/compliance/client/v1/identification_document_type_pb2_grpc.py +4 -0
  19. meshtrade/compliance/client/v1/industry_classification_pb2.py +2 -2
  20. meshtrade/compliance/client/v1/industry_classification_pb2_grpc.py +4 -0
  21. meshtrade/compliance/client/v1/natural_person_connection_type_pb2.py +2 -2
  22. meshtrade/compliance/client/v1/natural_person_connection_type_pb2_grpc.py +4 -0
  23. meshtrade/compliance/client/v1/natural_person_pb2.py +2 -2
  24. meshtrade/compliance/client/v1/natural_person_pb2_grpc.py +4 -0
  25. meshtrade/compliance/client/v1/pep_status_pb2.py +2 -2
  26. meshtrade/compliance/client/v1/pep_status_pb2_grpc.py +4 -0
  27. meshtrade/compliance/client/v1/service_meshpy.py +186 -0
  28. meshtrade/compliance/client/v1/service_options_meshpy.py +65 -0
  29. meshtrade/compliance/client/v1/service_pb2.py +20 -10
  30. meshtrade/compliance/client/v1/service_pb2.pyi +8 -0
  31. meshtrade/compliance/client/v1/service_pb2_grpc.py +192 -0
  32. meshtrade/compliance/client/v1/source_of_income_and_wealth_pb2.py +2 -2
  33. meshtrade/compliance/client/v1/source_of_income_and_wealth_pb2_grpc.py +4 -0
  34. meshtrade/compliance/client/v1/tax_residency_pb2.py +2 -2
  35. meshtrade/compliance/client/v1/tax_residency_pb2_grpc.py +4 -0
  36. meshtrade/compliance/client/v1/trust_pb2.py +2 -2
  37. meshtrade/compliance/client/v1/trust_pb2_grpc.py +4 -0
  38. meshtrade/compliance/client/v1/verification_status_pb2.py +2 -2
  39. meshtrade/compliance/client/v1/verification_status_pb2_grpc.py +4 -0
  40. meshtrade/iam/api_user/v1/__init__.py +99 -0
  41. meshtrade/iam/api_user/v1/api_credentials.py +156 -0
  42. meshtrade/iam/api_user/v1/api_credentials_pb2.py +42 -0
  43. meshtrade/iam/api_user/v1/api_credentials_pb2.pyi +14 -0
  44. meshtrade/iam/api_user/v1/api_credentials_pb2_grpc.py +4 -0
  45. meshtrade/iam/api_user/v1/api_user_pb2.py +48 -0
  46. meshtrade/iam/api_user/v1/api_user_pb2.pyi +49 -0
  47. meshtrade/iam/api_user/v1/api_user_pb2_grpc.py +4 -0
  48. meshtrade/iam/api_user/v1/service.py +58 -0
  49. meshtrade/iam/api_user/v1/service_meshpy.py +255 -0
  50. meshtrade/iam/api_user/v1/service_options_meshpy.py +65 -0
  51. meshtrade/iam/api_user/v1/service_pb2.py +77 -0
  52. meshtrade/iam/api_user/v1/service_pb2.pyi +63 -0
  53. meshtrade/iam/api_user/v1/service_pb2_grpc.py +458 -0
  54. meshtrade/iam/group/v1/__init__.py +59 -1
  55. meshtrade/iam/group/v1/group_pb2.py +2 -2
  56. meshtrade/iam/group/v1/group_pb2_grpc.py +4 -0
  57. meshtrade/iam/group/v1/service_meshpy.py +187 -0
  58. meshtrade/iam/group/v1/service_options_meshpy.py +65 -0
  59. meshtrade/iam/group/v1/service_pb2.py +22 -6
  60. meshtrade/iam/group/v1/service_pb2.pyi +29 -1
  61. meshtrade/iam/group/v1/service_pb2_grpc.py +170 -0
  62. meshtrade/iam/role/v1/__init__.py +44 -0
  63. meshtrade/iam/role/v1/role.py +23 -0
  64. meshtrade/iam/role/v1/role_pb2.py +40 -0
  65. meshtrade/{option/v1/auth_pb2.pyi → iam/role/v1/role_pb2.pyi} +16 -0
  66. meshtrade/iam/role/v1/role_pb2_grpc.py +4 -0
  67. meshtrade/iam/user/v1/__init__.py +53 -0
  68. meshtrade/iam/user/v1/service_meshpy.py +151 -0
  69. meshtrade/iam/user/v1/service_options_meshpy.py +65 -0
  70. meshtrade/iam/user/v1/service_pb2.py +51 -0
  71. meshtrade/iam/user/v1/service_pb2.pyi +19 -0
  72. meshtrade/iam/user/v1/service_pb2_grpc.py +82 -0
  73. meshtrade/{issuance_hub/instrument/v1/instrument_pb2.py → iam/user/v1/user_pb2.py} +7 -7
  74. meshtrade/iam/user/v1/user_pb2.pyi +15 -0
  75. meshtrade/iam/user/v1/user_pb2_grpc.py +4 -0
  76. meshtrade/ledger/transaction/v1/__init__.py +34 -0
  77. meshtrade/ledger/transaction/v1/transaction_action_pb2.py +2 -2
  78. meshtrade/ledger/transaction/v1/transaction_action_pb2_grpc.py +4 -0
  79. meshtrade/ledger/transaction/v1/transaction_state_pb2.py +2 -2
  80. meshtrade/ledger/transaction/v1/transaction_state_pb2_grpc.py +4 -0
  81. meshtrade/option/v1/__init__.py +36 -4
  82. meshtrade/option/v1/{service_type_pb2.py → method_type_pb2.py} +7 -7
  83. meshtrade/option/v1/method_type_pb2.pyi +17 -0
  84. meshtrade/option/v1/method_type_pb2_grpc.py +4 -0
  85. meshtrade/trading/limit_order/v1/__init__.py +47 -1
  86. meshtrade/trading/limit_order/v1/limit_order_pb2.py +2 -2
  87. meshtrade/trading/limit_order/v1/limit_order_pb2_grpc.py +4 -0
  88. meshtrade/trading/limit_order/v1/service_meshpy.py +151 -0
  89. meshtrade/trading/limit_order/v1/service_options_meshpy.py +65 -0
  90. meshtrade/trading/limit_order/v1/service_pb2.py +10 -6
  91. meshtrade/trading/limit_order/v1/service_pb2.pyi +2 -0
  92. meshtrade/trading/limit_order/v1/service_pb2_grpc.py +78 -0
  93. meshtrade/trading/market_order/v1/__init__.py +53 -0
  94. meshtrade/trading/{direct_order/v1/direct_order_pb2.py → market_order/v1/market_order_pb2.py} +7 -7
  95. meshtrade/trading/{spot/v1/spot_pb2.pyi → market_order/v1/market_order_pb2.pyi} +1 -1
  96. meshtrade/trading/market_order/v1/market_order_pb2_grpc.py +4 -0
  97. meshtrade/trading/market_order/v1/service_meshpy.py +151 -0
  98. meshtrade/trading/market_order/v1/service_options_meshpy.py +65 -0
  99. meshtrade/trading/market_order/v1/service_pb2.py +44 -0
  100. meshtrade/trading/{spot → market_order}/v1/service_pb2.pyi +4 -2
  101. meshtrade/trading/market_order/v1/service_pb2_grpc.py +78 -0
  102. meshtrade/type/v1/__init__.py +91 -50
  103. meshtrade/type/v1/address_pb2.py +2 -2
  104. meshtrade/type/v1/address_pb2_grpc.py +4 -0
  105. meshtrade/type/v1/amount.py +2 -8
  106. meshtrade/type/v1/amount_pb2.py +2 -2
  107. meshtrade/type/v1/amount_pb2_grpc.py +4 -0
  108. meshtrade/type/v1/contact_details_pb2.py +2 -2
  109. meshtrade/type/v1/contact_details_pb2_grpc.py +4 -0
  110. meshtrade/type/v1/date.py +263 -91
  111. meshtrade/type/v1/date_pb2.py +2 -2
  112. meshtrade/type/v1/date_pb2_grpc.py +4 -0
  113. meshtrade/type/v1/decimal_built_in_conversions.py +1 -1
  114. meshtrade/type/v1/decimal_pb2.py +2 -2
  115. meshtrade/type/v1/decimal_pb2_grpc.py +4 -0
  116. meshtrade/type/v1/ledger.py +1 -1
  117. meshtrade/type/v1/ledger_pb2.py +2 -2
  118. meshtrade/type/v1/ledger_pb2_grpc.py +4 -0
  119. meshtrade/{trading/spot/v1/spot_pb2.py → type/v1/sorting_pb2.py} +7 -7
  120. meshtrade/type/v1/sorting_pb2.pyi +14 -0
  121. meshtrade/type/v1/sorting_pb2_grpc.py +4 -0
  122. meshtrade/type/v1/time_of_day.py +52 -87
  123. meshtrade/type/v1/time_of_day_pb2.py +2 -2
  124. meshtrade/type/v1/time_of_day_pb2_grpc.py +4 -0
  125. meshtrade/type/v1/token_pb2.py +2 -2
  126. meshtrade/type/v1/token_pb2_grpc.py +4 -0
  127. meshtrade/wallet/account/v1/__init__.py +46 -0
  128. meshtrade/wallet/account/v1/account_pb2.py +2 -2
  129. meshtrade/wallet/account/v1/account_pb2_grpc.py +4 -0
  130. meshtrade/wallet/account/v1/service_meshpy.py +204 -0
  131. meshtrade/wallet/account/v1/service_options_meshpy.py +65 -0
  132. meshtrade/wallet/account/v1/service_pb2.py +18 -18
  133. meshtrade/wallet/account/v1/service_pb2.pyi +2 -2
  134. meshtrade/wallet/account/v1/service_pb2_grpc.py +222 -0
  135. meshtrade-0.0.11.dist-info/METADATA +95 -0
  136. meshtrade-0.0.11.dist-info/RECORD +176 -0
  137. {meshtrade-0.0.8.dist-info → meshtrade-0.0.11.dist-info}/top_level.txt +1 -0
  138. meshtrade/issuance_hub/__init__.py +0 -0
  139. meshtrade/issuance_hub/instrument/__init__.py +0 -0
  140. meshtrade/issuance_hub/instrument/v1/__init__.py +0 -11
  141. meshtrade/issuance_hub/instrument/v1/instrument_pb2.pyi +0 -11
  142. meshtrade/issuance_hub/instrument/v1/service_pb2.py +0 -49
  143. meshtrade/issuance_hub/instrument/v1/service_pb2.pyi +0 -46
  144. meshtrade/option/v1/auth_pb2.py +0 -40
  145. meshtrade/option/v1/service_type_pb2.pyi +0 -17
  146. meshtrade/trading/direct_order/__init__.py +0 -0
  147. meshtrade/trading/direct_order/v1/__init__.py +0 -7
  148. meshtrade/trading/direct_order/v1/direct_order_pb2.pyi +0 -11
  149. meshtrade/trading/direct_order/v1/service_pb2.py +0 -40
  150. meshtrade/trading/direct_order/v1/service_pb2.pyi +0 -12
  151. meshtrade/trading/spot/__init__.py +0 -0
  152. meshtrade/trading/spot/v1/__init__.py +0 -7
  153. meshtrade/trading/spot/v1/service_pb2.py +0 -40
  154. meshtrade-0.0.8.dist-info/METADATA +0 -35
  155. meshtrade-0.0.8.dist-info/RECORD +0 -113
  156. meshtrade-0.0.8.dist-info/licenses/LICENSE +0 -10
  157. {meshtrade-0.0.8.dist-info → meshtrade-0.0.11.dist-info}/WHEEL +0 -0
meshtrade/type/v1/date.py CHANGED
@@ -3,21 +3,22 @@ This module provides helper functions for working with Date protobuf messages.
3
3
  """
4
4
 
5
5
  from datetime import date as python_date
6
+ from datetime import datetime
6
7
 
7
8
  from .date_pb2 import Date
8
9
 
9
10
 
10
11
  def new_date(year: int, month: int, day: int) -> Date:
11
12
  """Creates a new Date from year, month, and day values.
12
-
13
+
13
14
  Args:
14
- year: Year value (1-9999, or 0 for partial dates)
15
- month: Month value (1-12, or 0 for partial dates)
16
- day: Day value (1-31, or 0 for partial dates)
17
-
15
+ year: Year value (1-9999)
16
+ month: Month value (1-12)
17
+ day: Day value (1-31)
18
+
18
19
  Returns:
19
20
  A Date protobuf message
20
-
21
+
21
22
  Raises:
22
23
  ValueError: If the date values are invalid
23
24
  """
@@ -27,50 +28,59 @@ def new_date(year: int, month: int, day: int) -> Date:
27
28
 
28
29
  def new_date_from_python_date(python_date_obj: python_date) -> Date:
29
30
  """Creates a Date from a Python date object.
30
-
31
+
31
32
  Args:
32
33
  python_date_obj: A Python datetime.date object
33
-
34
+
34
35
  Returns:
35
36
  A Date protobuf message
36
37
  """
37
- return Date(
38
- year=python_date_obj.year,
39
- month=python_date_obj.month,
40
- day=python_date_obj.day
41
- )
38
+ return Date(year=python_date_obj.year, month=python_date_obj.month, day=python_date_obj.day)
39
+
40
+
41
+ def new_date_from_datetime(datetime_obj: datetime) -> Date:
42
+ """Creates a Date from a Python datetime object.
43
+ Only extracts the date components, ignoring the time.
44
+
45
+ Args:
46
+ datetime_obj: A Python datetime.datetime object
47
+
48
+ Returns:
49
+ A Date protobuf message
50
+ """
51
+ return new_date_from_python_date(datetime_obj.date())
42
52
 
43
53
 
44
54
  def date_to_python_date(date_obj: Date) -> python_date:
45
55
  """Converts a Date protobuf message to a Python date object.
46
-
56
+
47
57
  Args:
48
58
  date_obj: A Date protobuf message
49
-
59
+
50
60
  Returns:
51
61
  A Python datetime.date object
52
-
62
+
53
63
  Raises:
54
- ValueError: If the date is incomplete or invalid
64
+ ValueError: If the date is invalid
55
65
  """
56
66
  if not date_obj:
57
67
  raise ValueError("Date object is None")
58
68
 
59
- if not is_complete(date_obj):
60
- raise ValueError(f"Incomplete date: year={date_obj.year}, month={date_obj.month}, day={date_obj.day}")
69
+ if not date_is_valid(date_obj):
70
+ raise ValueError(f"Invalid date: year={date_obj.year}, month={date_obj.month}, day={date_obj.day}")
61
71
 
62
72
  try:
63
73
  return python_date(date_obj.year, date_obj.month, date_obj.day)
64
74
  except ValueError as e:
65
- raise ValueError(f"Invalid date values: {e}")
75
+ raise ValueError(f"Invalid date values: {e}") from e
66
76
 
67
77
 
68
- def is_valid(date_obj: Date | None) -> bool:
78
+ def date_is_valid(date_obj: Date | None) -> bool:
69
79
  """Checks if a Date has valid values according to the protobuf constraints.
70
-
80
+
71
81
  Args:
72
82
  date_obj: A Date protobuf message or None
73
-
83
+
74
84
  Returns:
75
85
  True if the date is valid, False otherwise
76
86
  """
@@ -84,12 +94,13 @@ def is_valid(date_obj: Date | None) -> bool:
84
94
  return False
85
95
 
86
96
 
87
- def is_complete(date_obj: Date | None) -> bool:
97
+ def date_is_complete(date_obj: Date | None) -> bool:
88
98
  """Returns True if the date has non-zero year, month, and day values.
89
-
99
+ Since only full dates are valid, this is equivalent to is_valid().
100
+
90
101
  Args:
91
102
  date_obj: A Date protobuf message or None
92
-
103
+
93
104
  Returns:
94
105
  True if the date is complete, False otherwise
95
106
  """
@@ -98,104 +109,265 @@ def is_complete(date_obj: Date | None) -> bool:
98
109
  return date_obj.year != 0 and date_obj.month != 0 and date_obj.day != 0
99
110
 
100
111
 
101
- def is_year_only(date_obj: Date | None) -> bool:
102
- """Returns True if only the year is specified (month and day are 0).
103
-
112
+ def date_to_string(date_obj: Date | None) -> str:
113
+ """Returns a string representation of the date.
114
+
104
115
  Args:
105
116
  date_obj: A Date protobuf message or None
106
-
117
+
107
118
  Returns:
108
- True if only year is specified, False otherwise
119
+ String representation of the date
109
120
  """
110
121
  if not date_obj:
122
+ return "<undefined>"
123
+
124
+ if date_is_valid(date_obj):
125
+ return f"{date_obj.year:04d}-{date_obj.month:02d}-{date_obj.day:02d}"
126
+ else:
127
+ return f"Date(year={date_obj.year}, month={date_obj.month}, day={date_obj.day}) [INVALID]"
128
+
129
+
130
+ def date_is_before(date1: Date | None, date2: Date | None) -> bool:
131
+ """Returns True if date1 is before date2.
132
+
133
+ Args:
134
+ date1: First Date protobuf message or None
135
+ date2: Second Date protobuf message or None
136
+
137
+ Returns:
138
+ True if date1 is before date2, False otherwise
139
+
140
+ Raises:
141
+ ValueError: If either date is None or incomplete
142
+ """
143
+ if not date1 or not date2:
144
+ raise ValueError("Both dates must be provided")
145
+
146
+ if not date_is_valid(date1) or not date_is_valid(date2):
147
+ raise ValueError("Both dates must be valid for comparison")
148
+
149
+ # Compare year first
150
+ if date1.year != date2.year:
151
+ return date1.year < date2.year
152
+
153
+ # Compare month if years are equal
154
+ if date1.month != date2.month:
155
+ return date1.month < date2.month
156
+
157
+ # Compare day if years and months are equal
158
+ return date1.day < date2.day
159
+
160
+
161
+ def date_is_after(date1: Date | None, date2: Date | None) -> bool:
162
+ """Returns True if date1 is after date2.
163
+
164
+ Args:
165
+ date1: First Date protobuf message or None
166
+ date2: Second Date protobuf message or None
167
+
168
+ Returns:
169
+ True if date1 is after date2, False otherwise
170
+
171
+ Raises:
172
+ ValueError: If either date is None or incomplete
173
+ """
174
+ if not date1 or not date2:
175
+ raise ValueError("Both dates must be provided")
176
+
177
+ if not date_is_valid(date1) or not date_is_valid(date2):
178
+ raise ValueError("Both dates must be valid for comparison")
179
+
180
+ # Compare year first
181
+ if date1.year != date2.year:
182
+ return date1.year > date2.year
183
+
184
+ # Compare month if years are equal
185
+ if date1.month != date2.month:
186
+ return date1.month > date2.month
187
+
188
+ # Compare day if years and months are equal
189
+ return date1.day > date2.day
190
+
191
+
192
+ def date_is_equal(date1: Date | None, date2: Date | None) -> bool:
193
+ """Returns True if date1 is equal to date2.
194
+
195
+ Args:
196
+ date1: First Date protobuf message or None
197
+ date2: Second Date protobuf message or None
198
+
199
+ Returns:
200
+ True if date1 is equal to date2, False otherwise
201
+ """
202
+ if not date1 and not date2:
203
+ return True
204
+
205
+ if not date1 or not date2:
111
206
  return False
112
- return date_obj.year != 0 and date_obj.month == 0 and date_obj.day == 0
207
+
208
+ return date1.year == date2.year and date1.month == date2.month and date1.day == date2.day
113
209
 
114
210
 
115
- def is_year_month(date_obj: Date | None) -> bool:
116
- """Returns True if year and month are specified but day is 0.
117
-
211
+ def date_is_before_or_equal(date1: Date | None, date2: Date | None) -> bool:
212
+ """Returns True if date1 is before or equal to date2.
213
+
118
214
  Args:
119
- date_obj: A Date protobuf message or None
120
-
215
+ date1: First Date protobuf message or None
216
+ date2: Second Date protobuf message or None
217
+
121
218
  Returns:
122
- True if year and month are specified but day is 0, False otherwise
219
+ True if date1 is before or equal to date2, False otherwise
220
+
221
+ Raises:
222
+ ValueError: If either date is None or incomplete
223
+ """
224
+ return date_is_before(date1, date2) or date_is_equal(date1, date2)
225
+
226
+
227
+ def date_is_after_or_equal(date1: Date | None, date2: Date | None) -> bool:
228
+ """Returns True if date1 is after or equal to date2.
229
+
230
+ Args:
231
+ date1: First Date protobuf message or None
232
+ date2: Second Date protobuf message or None
233
+
234
+ Returns:
235
+ True if date1 is after or equal to date2, False otherwise
236
+
237
+ Raises:
238
+ ValueError: If either date is None or incomplete
239
+ """
240
+ return date_is_after(date1, date2) or date_is_equal(date1, date2)
241
+
242
+
243
+ def date_add_days(date_obj: Date, days: int) -> Date:
244
+ """Adds a specified number of days to a date.
245
+
246
+ Args:
247
+ date_obj: A Date protobuf message
248
+ days: Number of days to add (can be negative to subtract)
249
+
250
+ Returns:
251
+ A new Date protobuf message with the days added
252
+
253
+ Raises:
254
+ ValueError: If the date is None or incomplete
123
255
  """
124
256
  if not date_obj:
125
- return False
126
- return date_obj.year != 0 and date_obj.month != 0 and date_obj.day == 0
257
+ raise ValueError("Date object is None")
258
+
259
+ if not date_is_valid(date_obj):
260
+ raise ValueError("Date must be valid to add days")
127
261
 
262
+ # Convert to Python date, add days, then convert back
263
+ py_date = date_to_python_date(date_obj)
264
+ from datetime import timedelta
265
+
266
+ new_py_date = py_date + timedelta(days=days)
267
+
268
+ return new_date_from_python_date(new_py_date)
269
+
270
+
271
+ def date_add_months(date_obj: Date, months: int) -> Date:
272
+ """Adds a specified number of months to a date.
128
273
 
129
- def is_month_day(date_obj: Date | None) -> bool:
130
- """Returns True if month and day are specified but year is 0.
131
-
132
274
  Args:
133
- date_obj: A Date protobuf message or None
134
-
275
+ date_obj: A Date protobuf message
276
+ months: Number of months to add (can be negative to subtract)
277
+
135
278
  Returns:
136
- True if month and day are specified but year is 0, False otherwise
279
+ A new Date protobuf message with the months added
280
+
281
+ Raises:
282
+ ValueError: If the date is None or incomplete, or if the result is invalid
137
283
  """
138
284
  if not date_obj:
139
- return False
140
- return date_obj.year == 0 and date_obj.month != 0 and date_obj.day != 0
285
+ raise ValueError("Date object is None")
141
286
 
287
+ if not date_is_valid(date_obj):
288
+ raise ValueError("Date must be valid to add months")
289
+
290
+ # Calculate new year and month
291
+ total_months = date_obj.year * 12 + date_obj.month - 1 + months
292
+ new_year = total_months // 12
293
+ new_month = (total_months % 12) + 1
294
+
295
+ # Validate that the resulting year is within valid range
296
+ if new_year < 1 or new_year > 9999:
297
+ raise ValueError(f"Resulting year {new_year} is outside valid range [1, 9999]")
298
+
299
+ # Handle day overflow (e.g., Jan 31 + 1 month should be Feb 28/29)
300
+ new_day = date_obj.day
301
+
302
+ # Check if the day is valid for the new month
303
+ import calendar
304
+
305
+ max_day = calendar.monthrange(new_year, new_month)[1]
306
+ if new_day > max_day:
307
+ new_day = max_day
308
+
309
+ return new_date(new_year, new_month, new_day)
310
+
311
+
312
+ def date_add_years(date_obj: Date, years: int) -> Date:
313
+ """Adds a specified number of years to a date.
142
314
 
143
- def date_to_string(date_obj: Date | None) -> str:
144
- """Returns a string representation of the date.
145
-
146
315
  Args:
147
- date_obj: A Date protobuf message or None
148
-
316
+ date_obj: A Date protobuf message
317
+ years: Number of years to add (can be negative to subtract)
318
+
149
319
  Returns:
150
- String representation of the date
320
+ A new Date protobuf message with the years added
321
+
322
+ Raises:
323
+ ValueError: If the date is None or incomplete, or if the result is invalid
151
324
  """
152
325
  if not date_obj:
153
- return "<None>"
326
+ raise ValueError("Date object is None")
154
327
 
155
- if is_complete(date_obj):
156
- return f"{date_obj.year:04d}-{date_obj.month:02d}-{date_obj.day:02d}"
157
- elif is_year_only(date_obj):
158
- return f"{date_obj.year:04d}"
159
- elif is_year_month(date_obj):
160
- return f"{date_obj.year:04d}-{date_obj.month:02d}"
161
- elif is_month_day(date_obj):
162
- return f"--{date_obj.month:02d}-{date_obj.day:02d}"
163
- else:
164
- return f"Date(year={date_obj.year}, month={date_obj.month}, day={date_obj.day})"
328
+ if not date_is_valid(date_obj):
329
+ raise ValueError("Date must be valid to add years")
330
+
331
+ new_year = date_obj.year + years
332
+ new_month = date_obj.month
333
+ new_day = date_obj.day
334
+
335
+ # Handle leap year edge case (Feb 29 + 1 year when next year is not leap)
336
+ if new_month == 2 and new_day == 29:
337
+ import calendar
338
+
339
+ if not calendar.isleap(new_year):
340
+ new_day = 28
341
+
342
+ return new_date(new_year, new_month, new_day)
165
343
 
166
344
 
167
345
  def _validate_date(year: int, month: int, day: int) -> None:
168
346
  """Validates the year, month, and day values according to Date constraints.
169
-
347
+ Only full dates are valid - all fields must be non-zero.
348
+
170
349
  Args:
171
350
  year: Year value
172
351
  month: Month value
173
352
  day: Day value
174
-
353
+
175
354
  Raises:
176
355
  ValueError: If the date values are invalid
177
356
  """
178
- # Year validation
179
- if year != 0 and (year < 1 or year > 9999):
180
- raise ValueError(f"Year must be 0 or between 1 and 9999, got {year}")
181
-
182
- # Month validation
183
- if month != 0 and (month < 1 or month > 12):
184
- raise ValueError(f"Month must be 0 or between 1 and 12, got {month}")
185
-
186
- # Day validation
187
- if day != 0 and (day < 1 or day > 31):
188
- raise ValueError(f"Day must be 0 or between 1 and 31, got {day}")
189
-
190
- # Additional validation for complete dates
191
- if year != 0 and month != 0 and day != 0:
192
- try:
193
- python_date(year, month, day)
194
- except ValueError as e:
195
- raise ValueError(f"Invalid date: {year}-{month:02d}-{day:02d}: {e}")
196
-
197
- # Validate partial date combinations
198
- if year == 0 and month != 0 and day == 0:
199
- raise ValueError("Month cannot be specified without year")
200
- if year == 0 and month == 0 and day != 0:
201
- raise ValueError("Day cannot be specified without month")
357
+ # Year validation - must be non-zero
358
+ if year < 1 or year > 9999:
359
+ raise ValueError(f"Year must be between 1 and 9999, got {year}")
360
+
361
+ # Month validation - must be non-zero
362
+ if month < 1 or month > 12:
363
+ raise ValueError(f"Month must be between 1 and 12, got {month}")
364
+
365
+ # Day validation - must be non-zero
366
+ if day < 1 or day > 31:
367
+ raise ValueError(f"Day must be between 1 and 31, got {day}")
368
+
369
+ # Check if the day is valid for the given month and year
370
+ try:
371
+ python_date(year, month, day)
372
+ except ValueError as e:
373
+ raise ValueError(f"Invalid date: {year}-{month:02d}-{day:02d}: {e}") from e
@@ -24,14 +24,14 @@ _sym_db = _symbol_database.Default()
24
24
 
25
25
 
26
26
 
27
- DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1cmeshtrade/type/v1/date.proto\x12\x11meshtrade.type.v1\"B\n\x04\x44\x61te\x12\x12\n\x04year\x18\x01 \x01(\x05R\x04year\x12\x14\n\x05month\x18\x02 \x01(\x05R\x05month\x12\x10\n\x03\x64\x61y\x18\x03 \x01(\x05R\x03\x64\x61yB,Z*github.com/meshtrade/api/go/type/v1;typev1b\x06proto3')
27
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1cmeshtrade/type/v1/date.proto\x12\x11meshtrade.type.v1\"B\n\x04\x44\x61te\x12\x12\n\x04year\x18\x01 \x01(\x05R\x04year\x12\x14\n\x05month\x18\x02 \x01(\x05R\x05month\x12\x10\n\x03\x64\x61y\x18\x03 \x01(\x05R\x03\x64\x61yBF\n\x18\x63o.meshtrade.api.type.v1Z*github.com/meshtrade/api/go/type/v1;typev1b\x06proto3')
28
28
 
29
29
  _globals = globals()
30
30
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
31
31
  _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtrade.type.v1.date_pb2', _globals)
32
32
  if not _descriptor._USE_C_DESCRIPTORS:
33
33
  _globals['DESCRIPTOR']._loaded_options = None
34
- _globals['DESCRIPTOR']._serialized_options = b'Z*github.com/meshtrade/api/go/type/v1;typev1'
34
+ _globals['DESCRIPTOR']._serialized_options = b'\n\030co.meshtrade.api.type.v1Z*github.com/meshtrade/api/go/type/v1;typev1'
35
35
  _globals['_DATE']._serialized_start=51
36
36
  _globals['_DATE']._serialized_end=117
37
37
  # @@protoc_insertion_point(module_scope)
@@ -0,0 +1,4 @@
1
+ # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
2
+ """Client and server classes corresponding to protobuf-defined services."""
3
+ import grpc
4
+
@@ -26,4 +26,4 @@ def decimal_to_built_in(decimal_value: Decimal) -> decimal.Decimal:
26
26
  :param decimal_value: The decimal_pb2.Decimal object to convert.
27
27
  :return: The converted decimal.Decimal object.
28
28
  """
29
- return decimal.Decimal( decimal_value.value if decimal_value.value != "" else "0" )
29
+ return decimal.Decimal(decimal_value.value if decimal_value.value != "" else "0")
@@ -24,14 +24,14 @@ _sym_db = _symbol_database.Default()
24
24
 
25
25
 
26
26
 
27
- DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fmeshtrade/type/v1/decimal.proto\x12\x11meshtrade.type.v1\"\x1f\n\x07\x44\x65\x63imal\x12\x14\n\x05value\x18\x01 \x01(\tR\x05valueB,Z*github.com/meshtrade/api/go/type/v1;typev1b\x06proto3')
27
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fmeshtrade/type/v1/decimal.proto\x12\x11meshtrade.type.v1\"\x1f\n\x07\x44\x65\x63imal\x12\x14\n\x05value\x18\x01 \x01(\tR\x05valueBF\n\x18\x63o.meshtrade.api.type.v1Z*github.com/meshtrade/api/go/type/v1;typev1b\x06proto3')
28
28
 
29
29
  _globals = globals()
30
30
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
31
31
  _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtrade.type.v1.decimal_pb2', _globals)
32
32
  if not _descriptor._USE_C_DESCRIPTORS:
33
33
  _globals['DESCRIPTOR']._loaded_options = None
34
- _globals['DESCRIPTOR']._serialized_options = b'Z*github.com/meshtrade/api/go/type/v1;typev1'
34
+ _globals['DESCRIPTOR']._serialized_options = b'\n\030co.meshtrade.api.type.v1Z*github.com/meshtrade/api/go/type/v1;typev1'
35
35
  _globals['_DECIMAL']._serialized_start=54
36
36
  _globals['_DECIMAL']._serialized_end=85
37
37
  # @@protoc_insertion_point(module_scope)
@@ -0,0 +1,4 @@
1
+ # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
2
+ """Client and server classes corresponding to protobuf-defined services."""
3
+ import grpc
4
+
@@ -1,4 +1,3 @@
1
-
2
1
  from .ledger_pb2 import Ledger
3
2
 
4
3
  _ledger_decimal_places: dict[Ledger, int] = {
@@ -6,6 +5,7 @@ _ledger_decimal_places: dict[Ledger, int] = {
6
5
  Ledger.LEDGER_SA_STOCK_BROKERS: 2,
7
6
  }
8
7
 
8
+
9
9
  class UnsupportedLedgerError(Exception):
10
10
  """Exception raised for unsupported Ledger values."""
11
11
 
@@ -24,14 +24,14 @@ _sym_db = _symbol_database.Default()
24
24
 
25
25
 
26
26
 
27
- DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1emeshtrade/type/v1/ledger.proto\x12\x11meshtrade.type.v1*\xb0\x01\n\x06Ledger\x12\x16\n\x12LEDGER_UNSPECIFIED\x10\x00\x12\x12\n\x0eLEDGER_STELLAR\x10\x03\x12\x12\n\x0eLEDGER_BITCOIN\x10\x05\x12\x13\n\x0fLEDGER_LITECOIN\x10\x07\x12\x13\n\x0fLEDGER_ETHEREUM\x10\t\x12\x0e\n\nLEDGER_XRP\x10\x0b\x12\x1b\n\x17LEDGER_SA_STOCK_BROKERS\x10\x0f\x12\x0f\n\x0bLEDGER_NULL\x10\x10\x42,Z*github.com/meshtrade/api/go/type/v1;typev1b\x06proto3')
27
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1emeshtrade/type/v1/ledger.proto\x12\x11meshtrade.type.v1*\xb0\x01\n\x06Ledger\x12\x16\n\x12LEDGER_UNSPECIFIED\x10\x00\x12\x12\n\x0eLEDGER_STELLAR\x10\x03\x12\x12\n\x0eLEDGER_BITCOIN\x10\x05\x12\x13\n\x0fLEDGER_LITECOIN\x10\x07\x12\x13\n\x0fLEDGER_ETHEREUM\x10\t\x12\x0e\n\nLEDGER_XRP\x10\x0b\x12\x1b\n\x17LEDGER_SA_STOCK_BROKERS\x10\x0f\x12\x0f\n\x0bLEDGER_NULL\x10\x10\x42\x46\n\x18\x63o.meshtrade.api.type.v1Z*github.com/meshtrade/api/go/type/v1;typev1b\x06proto3')
28
28
 
29
29
  _globals = globals()
30
30
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
31
31
  _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtrade.type.v1.ledger_pb2', _globals)
32
32
  if not _descriptor._USE_C_DESCRIPTORS:
33
33
  _globals['DESCRIPTOR']._loaded_options = None
34
- _globals['DESCRIPTOR']._serialized_options = b'Z*github.com/meshtrade/api/go/type/v1;typev1'
34
+ _globals['DESCRIPTOR']._serialized_options = b'\n\030co.meshtrade.api.type.v1Z*github.com/meshtrade/api/go/type/v1;typev1'
35
35
  _globals['_LEDGER']._serialized_start=54
36
36
  _globals['_LEDGER']._serialized_end=230
37
37
  # @@protoc_insertion_point(module_scope)
@@ -0,0 +1,4 @@
1
+ # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
2
+ """Client and server classes corresponding to protobuf-defined services."""
3
+ import grpc
4
+
@@ -1,7 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  # Generated by the protocol buffer compiler. DO NOT EDIT!
3
3
  # NO CHECKED-IN PROTOBUF GENCODE
4
- # source: meshtrade/trading/spot/v1/spot.proto
4
+ # source: meshtrade/type/v1/sorting.proto
5
5
  # Protobuf Python Version: 6.31.1
6
6
  """Generated protocol buffer code."""
7
7
  from google.protobuf import descriptor as _descriptor
@@ -15,7 +15,7 @@ _runtime_version.ValidateProtobufRuntimeVersion(
15
15
  31,
16
16
  1,
17
17
  '',
18
- 'meshtrade/trading/spot/v1/spot.proto'
18
+ 'meshtrade/type/v1/sorting.proto'
19
19
  )
20
20
  # @@protoc_insertion_point(imports)
21
21
 
@@ -24,14 +24,14 @@ _sym_db = _symbol_database.Default()
24
24
 
25
25
 
26
26
 
27
- DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n$meshtrade/trading/spot/v1/spot.proto\x12\x19meshtrade.trading.spot.v1\"\x1e\n\x04Spot\x12\x16\n\x06number\x18\x01 \x01(\tR\x06numberB4Z2github.com/meshtrade/api/go/trading/spot/v1;spotv1b\x06proto3')
27
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1fmeshtrade/type/v1/sorting.proto\x12\x11meshtrade.type.v1*\\\n\x0cSortingOrder\x12\x1d\n\x19SORTING_ORDER_UNSPECIFIED\x10\x00\x12\x15\n\x11SORTING_ORDER_ASC\x10\x01\x12\x16\n\x12SORTING_ORDER_DESC\x10\x02\x42\x46\n\x18\x63o.meshtrade.api.type.v1Z*github.com/meshtrade/api/go/type/v1;typev1b\x06proto3')
28
28
 
29
29
  _globals = globals()
30
30
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
31
- _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtrade.trading.spot.v1.spot_pb2', _globals)
31
+ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'meshtrade.type.v1.sorting_pb2', _globals)
32
32
  if not _descriptor._USE_C_DESCRIPTORS:
33
33
  _globals['DESCRIPTOR']._loaded_options = None
34
- _globals['DESCRIPTOR']._serialized_options = b'Z2github.com/meshtrade/api/go/trading/spot/v1;spotv1'
35
- _globals['_SPOT']._serialized_start=67
36
- _globals['_SPOT']._serialized_end=97
34
+ _globals['DESCRIPTOR']._serialized_options = b'\n\030co.meshtrade.api.type.v1Z*github.com/meshtrade/api/go/type/v1;typev1'
35
+ _globals['_SORTINGORDER']._serialized_start=54
36
+ _globals['_SORTINGORDER']._serialized_end=146
37
37
  # @@protoc_insertion_point(module_scope)
@@ -0,0 +1,14 @@
1
+ from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper
2
+ from google.protobuf import descriptor as _descriptor
3
+ from typing import ClassVar as _ClassVar
4
+
5
+ DESCRIPTOR: _descriptor.FileDescriptor
6
+
7
+ class SortingOrder(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
8
+ __slots__ = ()
9
+ SORTING_ORDER_UNSPECIFIED: _ClassVar[SortingOrder]
10
+ SORTING_ORDER_ASC: _ClassVar[SortingOrder]
11
+ SORTING_ORDER_DESC: _ClassVar[SortingOrder]
12
+ SORTING_ORDER_UNSPECIFIED: SortingOrder
13
+ SORTING_ORDER_ASC: SortingOrder
14
+ SORTING_ORDER_DESC: SortingOrder
@@ -0,0 +1,4 @@
1
+ # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
2
+ """Client and server classes corresponding to protobuf-defined services."""
3
+ import grpc
4
+