pyXRocketAPI 0.2.0__tar.gz → 1.0.0__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyXRocketAPI
3
- Version: 0.2.0
3
+ Version: 1.0.0
4
4
  Summary: Python client for the xRocket Pay API
5
5
  Author: Badiboy
6
6
  License-Expression: MIT
@@ -8,10 +8,9 @@ Project-URL: Homepage, https://github.com/Badiboy/pyXRocketAPI
8
8
  Project-URL: Documentation, https://docs.xrocket.exchange/api/pay/pay-api-overview
9
9
  Project-URL: Repository, https://github.com/Badiboy/pyXRocketAPI
10
10
  Keywords: xrocket,pay,crypto,payments,api
11
- Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Development Status :: 5 - Production/Stable
12
12
  Classifier: Programming Language :: Python :: 3
13
- Classifier: Programming Language :: Python :: 3 :: Only
14
- Requires-Python: >=3.10
13
+ Requires-Python: >=3.11
15
14
  Description-Content-Type: text/markdown
16
15
  License-File: LICENSE
17
16
  Requires-Dist: requests>=2.28
@@ -47,6 +46,40 @@ For integration testing, use the xRocket testnet instead of production:
47
46
  client = xRocketPayAPI(token="testnet-token", testnet=True)
48
47
  ```
49
48
 
49
+ ## Nested request models
50
+
51
+ Known nested API objects are passed as model instances, not dictionaries. The
52
+ same models deserialize API responses and implement `to_dict()` for request
53
+ bodies.
54
+
55
+ ```python
56
+ from pyXRocketAPI import InvoiceCallback, InvoiceCustomer, InvoiceUrl, xRocketPayAPI
57
+
58
+ client = xRocketPayAPI(token="your-pay-api-token")
59
+ invoice = client.create_invoice(
60
+ price_currency="USDT",
61
+ price_amount="10.00",
62
+ callback=InvoiceCallback(
63
+ callbackUrl="https://example.com/webhooks/invoice",
64
+ payload={"order_id": "123"},
65
+ ),
66
+ url=InvoiceUrl(
67
+ successUrl="https://example.com/success",
68
+ cancelUrl="https://example.com/cancel",
69
+ ),
70
+ customer=InvoiceCustomer(
71
+ id="customer-123",
72
+ email="customer@example.com",
73
+ telegramId="123456789",
74
+ ),
75
+ data={"internal_order_id": "123"},
76
+ )
77
+ ```
78
+
79
+ `payload` and `data` remain ordinary dictionaries because xRocket defines them
80
+ as arbitrary JSON objects without a fixed schema. Use `MassPayout` instances
81
+ for every item passed to `create_mass_payouts()`.
82
+
50
83
  ## Safety
51
84
 
52
85
  The token grants access to the application and must not be committed to source control. Financial POST operations are not retried automatically. Supply and retain the relevant client identifier (`client_invoice_id`, `client_payout_id`, `client_cheque_id`, or `client_withdrawal_id`) so that a timed-out operation can be reconciled safely.
@@ -28,6 +28,40 @@ For integration testing, use the xRocket testnet instead of production:
28
28
  client = xRocketPayAPI(token="testnet-token", testnet=True)
29
29
  ```
30
30
 
31
+ ## Nested request models
32
+
33
+ Known nested API objects are passed as model instances, not dictionaries. The
34
+ same models deserialize API responses and implement `to_dict()` for request
35
+ bodies.
36
+
37
+ ```python
38
+ from pyXRocketAPI import InvoiceCallback, InvoiceCustomer, InvoiceUrl, xRocketPayAPI
39
+
40
+ client = xRocketPayAPI(token="your-pay-api-token")
41
+ invoice = client.create_invoice(
42
+ price_currency="USDT",
43
+ price_amount="10.00",
44
+ callback=InvoiceCallback(
45
+ callbackUrl="https://example.com/webhooks/invoice",
46
+ payload={"order_id": "123"},
47
+ ),
48
+ url=InvoiceUrl(
49
+ successUrl="https://example.com/success",
50
+ cancelUrl="https://example.com/cancel",
51
+ ),
52
+ customer=InvoiceCustomer(
53
+ id="customer-123",
54
+ email="customer@example.com",
55
+ telegramId="123456789",
56
+ ),
57
+ data={"internal_order_id": "123"},
58
+ )
59
+ ```
60
+
61
+ `payload` and `data` remain ordinary dictionaries because xRocket defines them
62
+ as arbitrary JSON objects without a fixed schema. Use `MassPayout` instances
63
+ for every item passed to `create_mass_payouts()`.
64
+
31
65
  ## Safety
32
66
 
33
67
  The token grants access to the application and must not be committed to source control. Financial POST operations are not retried automatically. Supply and retain the relevant client identifier (`client_invoice_id`, `client_payout_id`, `client_cheque_id`, or `client_withdrawal_id`) so that a timed-out operation can be reconciled safely.
@@ -4,23 +4,11 @@ from typing import Any
4
4
  import requests
5
5
 
6
6
  from .exceptions import xRocketAPIException
7
- from .models import App, Balance, Cheque, ChequesList, Currency, Invoice, InvoicePaymentAddress, InvoicePaymentsList, InvoicesList, MassPayouts, xPage, Payout, PayoutsList, Rate, Withdrawal, WithdrawalLink, WithdrawalQuotas, WithdrawalsList, xRocketObject
7
+ from .models import App, Balance, Cheque, ChequeCallback, ChequeUrl, ChequesList, Currency, Health, Invoice, InvoiceCallback, InvoiceCustomer, InvoicePaymentAddress, InvoicePaymentsList, InvoiceUrl, InvoicesList, MassPayout, MassPayouts, Payout, PayoutCallback, PayoutsList, Rate, Swap, SwapAsset, SwapEstimate, SwapRoute, SwapsList, Withdrawal, WithdrawalCallback, WithdrawalLink, WithdrawalQuotas, WithdrawalsList, xPage, xRocketObject
8
8
 
9
9
  PRODUCTION_API_URL = "https://pay.api.xrocket.exchange"
10
10
  TESTNET_API_URL = "https://pay.api.testnet.xrocket.exchange"
11
11
 
12
-
13
- def _without_none(**values: Any) -> dict[str, Any]:
14
- """Keep valid falsey API values while omitting arguments not supplied."""
15
- return {key: value for key, value in values.items() if value is not None}
16
-
17
-
18
- def _identifier(first_name: str, first_value: str | None, second_name: str, second_value: str | None) -> dict[str, str]:
19
- if first_value is None and second_value is None:
20
- raise ValueError(f"Specify {first_name} or {second_name}.")
21
- return _without_none(**{first_name: first_value, second_name: second_value})
22
-
23
-
24
12
  class xRocketPayAPI:
25
13
  """Client for the current xRocket Pay API.
26
14
 
@@ -28,20 +16,64 @@ class xRocketPayAPI:
28
16
  ----------
29
17
  token:
30
18
  App-specific Pay API Bearer token. Public calls such as
31
- ``health_check()`` and ``get_available_currencies()`` do not require
32
- one.
19
+ ``health_check()`` and ``get_available_currencies()`` do not require one.
33
20
  testnet:
34
21
  Select the xRocket Pay testnet URL. A testnet token is required.
35
22
  timeout:
36
- Timeout passed to every request, in seconds. ``None`` uses requests'
37
- default behaviour.
23
+ Timeout passed to every request, in seconds.
24
+ ``None`` uses requests' default behaviour.
25
+ Default is 30 seconds.
26
+ A tuple of ``(connect, read)`` timeouts can be passed to override the default for each phase.
38
27
  """
39
28
 
29
+ @staticmethod
30
+ def __without_none(**values: Any) -> dict[str, Any]:
31
+ """Keep valid falsey API values while omitting arguments not supplied."""
32
+ return {key: value for key, value in values.items() if value is not None}
33
+
34
+ @staticmethod
35
+ def __identifier(first_name: str, first_value: str | None,
36
+ second_name: str, second_value: str | None) -> dict[str, str]:
37
+ """Return identifier query parameters after validating their presence."""
38
+ if first_value is None and second_value is None:
39
+ raise ValueError(f"Specify {first_name} or {second_name}.")
40
+ return xRocketPayAPI.__without_none(**{first_name: first_value, second_name: second_value})
41
+
42
+ @staticmethod
43
+ def __request_model(value: Any, model_type: type, parameter_name: str) -> dict[str, Any] | None:
44
+ """Serialize one known nested request model or reject a plain mapping."""
45
+ if value is None:
46
+ return None
47
+ if not isinstance(value, model_type):
48
+ raise TypeError("{} must be an instance of {}.".format(parameter_name, model_type.__name__))
49
+ return value.to_dict()
50
+
51
+ @staticmethod
52
+ def __number_as_string(value: str | int | float | None, parameter_name: str) -> str | None:
53
+ """Encode one numeric API field whose wire type is string."""
54
+ if value is None:
55
+ return None
56
+ if isinstance(value, bool):
57
+ raise TypeError("{} must be a string or number, not bool.".format(parameter_name))
58
+ return str(value)
59
+
60
+ @staticmethod
61
+ def __swap_amount_mode(
62
+ amount: str | int | float | None, receive_amount: str | int | float | None
63
+ ) -> dict[str, str]:
64
+ """Validate and serialize one exact-in or exact-out swap amount."""
65
+ if (amount is None) == (receive_amount is None):
66
+ raise ValueError("Specify exactly one of amount or receive_amount.")
67
+ return xRocketPayAPI.__without_none(
68
+ amount=xRocketPayAPI.__number_as_string(amount, "amount"),
69
+ receiveAmount=xRocketPayAPI.__number_as_string(receive_amount, "receive_amount"),
70
+ )
71
+
40
72
  def __init__(
41
73
  self,
42
74
  token: str | None = None,
43
75
  testnet: bool = False,
44
- timeout: float | tuple[float, float] | None = 10,
76
+ timeout: float | tuple[float, float] | None = 30,
45
77
  ) -> None:
46
78
  self.token = token
47
79
  self.timeout = timeout
@@ -113,14 +145,14 @@ class xRocketPayAPI:
113
145
  except ValueError as error:
114
146
  raise xRocketAPIException("xRocket Pay returned invalid JSON.", status=response.status_code) from error
115
147
 
116
- def health_check(self) -> xRocketObject:
148
+ def health_check(self) -> Health:
117
149
  """Run the public health check.
118
150
 
119
151
  API: https://docs.xrocket.exchange/api/pay/reference/http/health-controller-health
120
152
 
121
- :return: ``xRocketObject``.
153
+ :return: ``Health``.
122
154
  """
123
- return xRocketObject.de_json(self._request("GET", "/health", auth_required=False), process_mode=2)
155
+ return Health.de_json(self._request("GET", "/health", auth_required=False))
124
156
 
125
157
  def get_app_info(self) -> App:
126
158
  """Get information about your application.
@@ -150,7 +182,7 @@ class xRocketPayAPI:
150
182
  :return: ``list[Currency]``.
151
183
  """
152
184
  data = self._request(
153
- "GET", "/api/v1/currencies", params=_without_none(kind=kind), auth_required=False
185
+ "GET", "/api/v1/currencies", params=self.__without_none(kind=kind), auth_required=False
154
186
  )
155
187
  return [Currency.de_json(item) for item in data]
156
188
 
@@ -170,21 +202,124 @@ class xRocketPayAPI:
170
202
  )
171
203
  return [Rate.de_json(item) for item in data]
172
204
 
205
+ def create_swap(
206
+ self, from_asset: str, to_asset: str, client_order_id: str,
207
+ amount: str | int | float | None = None, receive_amount: str | int | float | None = None,
208
+ ) -> Swap:
209
+ """Create swap.
210
+
211
+ API: https://docs.xrocket.exchange/api/pay/reference/http/swap-controller-create-swap
212
+
213
+ :param from_asset: Asset to swap from.
214
+ :param to_asset: Asset to swap to.
215
+ :param client_order_id: Merchant-provided idempotency key. Re-using a
216
+ value returns a conflict.
217
+ :param amount: Exact-in amount: how much of ``from_asset`` to spend.
218
+ Provide exactly one of ``amount`` or ``receive_amount``. A numeric
219
+ value is encoded as an API string.
220
+ :param receive_amount: Exact-out amount: how much of ``to_asset`` to
221
+ receive. Provide exactly one of ``amount`` or ``receive_amount``.
222
+ A numeric value is encoded as an API string.
223
+ :return: ``Swap``.
224
+ """
225
+ body = {"fromAsset": from_asset, "toAsset": to_asset, "clientOrderId": client_order_id}
226
+ body.update(self.__swap_amount_mode(amount, receive_amount))
227
+ return Swap.de_json(self._request("POST", "/api/v1/swap", body=body))
228
+
229
+ def estimate_swap(
230
+ self, from_asset: str, to_asset: str,
231
+ amount: str | int | float | None = None, receive_amount: str | int | float | None = None,
232
+ ) -> SwapEstimate:
233
+ """Estimate swap amounts and rate without creating it.
234
+
235
+ API: https://docs.xrocket.exchange/api/pay/reference/http/swap-controller-estimate
236
+
237
+ :param from_asset: Asset to swap from.
238
+ :param to_asset: Asset to swap to.
239
+ :param amount: Exact-in amount: how much of ``from_asset`` to spend.
240
+ Provide exactly one of ``amount`` or ``receive_amount``. A numeric
241
+ value is encoded as an API string.
242
+ :param receive_amount: Exact-out amount: how much of ``to_asset`` to
243
+ receive. Provide exactly one of ``amount`` or ``receive_amount``.
244
+ A numeric value is encoded as an API string.
245
+ :return: ``SwapEstimate``.
246
+ """
247
+ body = {"fromAsset": from_asset, "toAsset": to_asset}
248
+ body.update(self.__swap_amount_mode(amount, receive_amount))
249
+ return SwapEstimate.de_json(self._request("POST", "/api/v1/swap/estimate", body=body))
250
+
251
+ def get_swaps_list(self, cursor: str | None = None, limit: int | None = None) -> SwapsList:
252
+ """Get application swaps.
253
+
254
+ API: https://docs.xrocket.exchange/api/pay/reference/http/swap-controller-get-swaps
255
+
256
+ :param cursor: Cursor for pagination.
257
+ :param limit: No description is provided.
258
+ :return: ``SwapsList``.
259
+ """
260
+ return SwapsList.de_json(self._request(
261
+ "GET", "/api/v1/swaps", params=self.__without_none(cursor=cursor, limit=limit)
262
+ ))
263
+
264
+ def get_swap_info(self, swap_id: str) -> Swap:
265
+ """Get application swap info by id.
266
+
267
+ API: https://docs.xrocket.exchange/api/pay/reference/http/swap-controller-get-swap
268
+
269
+ :param swap_id: Swap id (track id).
270
+ :return: ``Swap``.
271
+ """
272
+ return Swap.de_json(self._request("GET", "/api/v1/swap/{}".format(swap_id)))
273
+
274
+ def get_swap_input_assets(self, asset_out: str | None = None) -> list[SwapAsset]:
275
+ """Get available input assets, optionally filtered by a target asset.
276
+
277
+ API: https://docs.xrocket.exchange/api/pay/reference/http/swap-controller-get-assets-in
278
+
279
+ :param asset_out: Target asset used to filter the result.
280
+ :return: ``list[SwapAsset]``.
281
+ """
282
+ data = self._request("GET", "/api/v1/swap/assets-in", params=self.__without_none(assetOut=asset_out))
283
+ return [SwapAsset.de_json(item) for item in data.get("items", [])]
284
+
285
+ def get_swap_output_assets(self, asset_in: str | None = None) -> list[SwapAsset]:
286
+ """Get available output assets, optionally filtered by a source asset.
287
+
288
+ API: https://docs.xrocket.exchange/api/pay/reference/http/swap-controller-get-assets-out
289
+
290
+ :param asset_in: Source asset used to filter the result.
291
+ :return: ``list[SwapAsset]``.
292
+ """
293
+ data = self._request("GET", "/api/v1/swap/assets-out", params=self.__without_none(assetIn=asset_in))
294
+ return [SwapAsset.de_json(item) for item in data.get("items", [])]
295
+
296
+ def get_swap_route_params(self, asset_in: str, asset_out: str) -> SwapRoute:
297
+ """Get swap route params (min/max amounts) for an asset pair.
298
+
299
+ API: https://docs.xrocket.exchange/api/pay/reference/http/swap-controller-get-params
300
+
301
+ :param asset_in: Source asset.
302
+ :param asset_out: Target asset.
303
+ :return: ``SwapRoute``.
304
+ """
305
+ return SwapRoute.de_json(self._request(
306
+ "GET", "/api/v1/swap/params", params={"assetIn": asset_in, "assetOut": asset_out}
307
+ ))
308
+
173
309
  def create_invoice(
174
310
  self,
175
311
  price_currency: str,
176
- price_amount: str | None = None,
177
- min_payment: str | None = None,
312
+ price_amount: str | int | float | None = None,
313
+ min_payment: str | int | float | None = None,
178
314
  num_payments: int | None = None,
179
315
  payout_currency: str | None = None,
180
316
  pay_currencies: Iterable[str] | None = None,
181
317
  client_invoice_id: str | None = None,
182
318
  description: str | None = None,
183
319
  expires_in: int | None = None,
184
- callback: Mapping[str, Any] | None = None,
185
- url: Mapping[str, Any] | None = None,
186
- customer: Mapping[str, Any] | None = None,
187
- is_fee_paid_by_user: bool | None = None,
320
+ callback: InvoiceCallback | None = None,
321
+ url: InvoiceUrl | None = None,
322
+ customer: InvoiceCustomer | None = None,
188
323
  data: Mapping[str, Any] | None = None,
189
324
  platform_id: str | None = None,
190
325
  ) -> Invoice:
@@ -193,27 +328,31 @@ class xRocketPayAPI:
193
328
  API: https://docs.xrocket.exchange/api/pay/reference/http/invoice-controller-create-invoice
194
329
 
195
330
  :param price_currency: Invoice price currency (crypto or fiat).
196
- :param price_amount: Invoice price amount.
197
- :param min_payment: Minimum payment amount (for open-amount invoices).
331
+ :param price_amount: Invoice price amount. A numeric value is encoded as an API string.
332
+ :param min_payment: Minimum payment amount (for open-amount invoices). A numeric value is encoded as an API string.
198
333
  :param num_payments: Num payments for invoice.
199
334
  :param payout_currency: Invoice payout crypto currency.
200
335
  :param pay_currencies: Crypto currencies which can be used to pay the invoice.
201
336
  :param client_invoice_id: Client Invoice ID as assigned by the client.
202
337
  :param description: Description for invoice.
203
338
  :param expires_in: Payment expires in milliseconds.
204
- :param callback: Callback data.
205
- :param url: User redirect urls.
206
- :param customer: Customer info.
207
- :param is_fee_paid_by_user: If true, the user pays a commission.
339
+ :param callback: Callback data as an ``InvoiceCallback`` instance.
340
+ :param url: User redirect urls as an ``InvoiceUrl`` instance.
341
+ :param customer: Customer info as an ``InvoiceCustomer`` instance.
208
342
  :param data: Custom user data passed through and returned in callbacks/webhooks (max size 4KB).
209
343
  :param platform_id: Platform identifier.
210
344
  :return: ``Invoice``.
211
345
  """
212
- body = _without_none(
213
- priceCurrency=price_currency, priceAmount=price_amount, minPayment=min_payment, numPayments=num_payments,
346
+ body = self.__without_none(
347
+ priceCurrency=price_currency,
348
+ priceAmount=self.__number_as_string(price_amount, "price_amount"),
349
+ minPayment=self.__number_as_string(min_payment, "min_payment"), numPayments=num_payments,
214
350
  payoutCurrency=payout_currency, payCurrencies=list(pay_currencies) if pay_currencies is not None else None,
215
- clientInvoiceId=client_invoice_id, description=description, expiresIn=expires_in, callback=callback, url=url,
216
- customer=customer, isFeePaidByUser=is_fee_paid_by_user, data=data, platformId=platform_id,
351
+ clientInvoiceId=client_invoice_id, description=description, expiresIn=expires_in,
352
+ callback=self.__request_model(callback, InvoiceCallback, "callback"),
353
+ url=self.__request_model(url, InvoiceUrl, "url"),
354
+ customer=self.__request_model(customer, InvoiceCustomer, "customer"),
355
+ data=data, platformId=platform_id,
217
356
  )
218
357
  return Invoice.de_json(self._request("POST", "/api/v1/invoices", body=body))
219
358
 
@@ -231,7 +370,7 @@ class xRocketPayAPI:
231
370
  :param limit: No description is provided.
232
371
  :return: ``InvoicesList``.
233
372
  """
234
- params = _without_none(asset=asset, fiat=fiat, ids=list(ids) if ids is not None else None, status=status, cursor=cursor, limit=limit)
373
+ params = self.__without_none(asset=asset, fiat=fiat, ids=list(ids) if ids is not None else None, status=status, cursor=cursor, limit=limit)
235
374
  return InvoicesList.de_json(self._request("GET", "/api/v1/invoices", params=params))
236
375
 
237
376
  def get_invoice_info(self, invoice_id: str | None = None, client_invoice_id: str | None = None) -> Invoice:
@@ -244,7 +383,7 @@ class xRocketPayAPI:
244
383
  :param client_invoice_id: Client Invoice ID assigned by the client. Either invoiceId or clientInvoiceId is required.
245
384
  :return: ``Invoice``.
246
385
  """
247
- return Invoice.de_json(self._request("GET", "/api/v1/invoice", params=_identifier("invoiceId", invoice_id, "clientInvoiceId", client_invoice_id)))
386
+ return Invoice.de_json(self._request("GET", "/api/v1/invoice", params=self.__identifier("invoiceId", invoice_id, "clientInvoiceId", client_invoice_id)))
248
387
 
249
388
  def delete_invoice(self, invoice_id: str | None = None, client_invoice_id: str | None = None) -> None:
250
389
  """Delete invoice.
@@ -256,7 +395,7 @@ class xRocketPayAPI:
256
395
  :param client_invoice_id: Client Invoice ID assigned by the client. Either invoiceId or clientInvoiceId is required.
257
396
  :return: ``None``.
258
397
  """
259
- self._request("DELETE", "/api/v1/invoice", params=_identifier("invoiceId", invoice_id, "clientInvoiceId", client_invoice_id))
398
+ self._request("DELETE", "/api/v1/invoice", params=self.__identifier("invoiceId", invoice_id, "clientInvoiceId", client_invoice_id))
260
399
 
261
400
  def get_invoice_payments(self, invoice_id: str | None = None, client_invoice_id: str | None = None,
262
401
  cursor: str | None = None, limit: int | None = None) -> InvoicePaymentsList:
@@ -271,8 +410,8 @@ class xRocketPayAPI:
271
410
  :param limit: No description is provided.
272
411
  :return: ``InvoicePaymentsList``.
273
412
  """
274
- params = _identifier("invoiceId", invoice_id, "clientInvoiceId", client_invoice_id)
275
- params.update(_without_none(cursor=cursor, limit=limit))
413
+ params = self.__identifier("invoiceId", invoice_id, "clientInvoiceId", client_invoice_id)
414
+ params.update(self.__without_none(cursor=cursor, limit=limit))
276
415
  return InvoicePaymentsList.de_json(self._request("GET", "/api/v1/invoice/payments", params=params))
277
416
 
278
417
  def create_invoice_payment_address(self, pay_network: str, invoice_id: str | None = None,
@@ -288,11 +427,11 @@ class xRocketPayAPI:
288
427
  """
289
428
  return InvoicePaymentAddress.de_json(self._request(
290
429
  "POST", "/api/v1/invoices/payments/address",
291
- params=_identifier("invoiceId", invoice_id, "clientInvoiceId", client_invoice_id), body={"payNetwork": pay_network},
430
+ params=self.__identifier("invoiceId", invoice_id, "clientInvoiceId", client_invoice_id), body={"payNetwork": pay_network},
292
431
  ))
293
432
 
294
- def create_cheque(self, asset: str, amount: str, client_cheque_id: str | None = None, password: str | None = None,
295
- description: str | None = None, callback: Mapping[str, Any] | None = None, url: Mapping[str, Any] | None = None,
433
+ def create_cheque(self, asset: str, amount: str | int | float, client_cheque_id: str | None = None, password: str | None = None,
434
+ description: str | None = None, callback: ChequeCallback | None = None, url: ChequeUrl | None = None,
296
435
  target_type: str | None = None, target: str | None = None) -> Cheque:
297
436
  """Create cheque.
298
437
 
@@ -300,19 +439,20 @@ class xRocketPayAPI:
300
439
  Issue a personal cheque to perform an accept-type payout. The amount is reserved from the application balance and can be redeemed by the recipient or cancelled before redemption. When targetType and target are set, only the addressed user is allowed to redeem the cheque.
301
440
 
302
441
  :param asset: Currency of transfer.
303
- :param amount: Cheque amount.
442
+ :param amount: Cheque amount. A numeric value is encoded as an API string.
304
443
  :param client_cheque_id: Unique cheque ID in your system to prevent double spends.
305
444
  :param password: Cheque password, the recipient has to enter it to redeem the cheque.
306
445
  :param description: Description for cheque.
307
- :param callback: Webhook settings for cheque activation updates.
308
- :param url: User redirect urls after cheque activation.
446
+ :param callback: Webhook settings for cheque activation updates as a ``ChequeCallback`` instance.
447
+ :param url: User redirect urls after cheque activation as a ``ChequeUrl`` instance.
309
448
  :param target_type: Target type for cheque, has to be passed together with target.
310
449
  :param target: Target for cheque, has to be passed together with targetType.
311
450
  :return: ``Cheque``.
312
451
  """
313
- return Cheque.de_json(self._request("POST", "/api/v1/cheques", body=_without_none(
314
- asset=asset, amount=str(amount), clientChequeId=client_cheque_id, password=password, description=description,
315
- callback=callback, url=url, targetType=target_type, target=target,
452
+ return Cheque.de_json(self._request("POST", "/api/v1/cheques", body=self.__without_none(
453
+ asset=asset, amount=self.__number_as_string(amount, "amount"), clientChequeId=client_cheque_id, password=password, description=description,
454
+ callback=self.__request_model(callback, ChequeCallback, "callback"),
455
+ url=self.__request_model(url, ChequeUrl, "url"), targetType=target_type, target=target,
316
456
  )))
317
457
 
318
458
  def get_cheques_list(self, from_date: str | None = None, to_date: str | None = None, target_type: str | None = None,
@@ -331,7 +471,7 @@ class xRocketPayAPI:
331
471
  :param limit: No description is provided.
332
472
  :return: ``ChequesList``.
333
473
  """
334
- return ChequesList.de_json(self._request("GET", "/api/v1/cheques", params=_without_none(
474
+ return ChequesList.de_json(self._request("GET", "/api/v1/cheques", params=self.__without_none(
335
475
  fromDate=from_date, toDate=to_date, targetType=target_type, target=target, state=state, cursor=cursor, limit=limit,
336
476
  )))
337
477
 
@@ -345,7 +485,7 @@ class xRocketPayAPI:
345
485
  :param client_cheque_id: Unique cheque id in your system.
346
486
  :return: ``Cheque``.
347
487
  """
348
- return Cheque.de_json(self._request("GET", "/api/v1/cheque", params=_identifier("chequeId", cheque_id, "clientChequeId", client_cheque_id)))
488
+ return Cheque.de_json(self._request("GET", "/api/v1/cheque", params=self.__identifier("chequeId", cheque_id, "clientChequeId", client_cheque_id)))
349
489
 
350
490
  def update_cheque(self, description: str, cheque_id: str | None = None, client_cheque_id: str | None = None) -> Cheque:
351
491
  """Update cheque.
@@ -358,7 +498,7 @@ class xRocketPayAPI:
358
498
  :param client_cheque_id: Unique cheque id in your system.
359
499
  :return: ``Cheque``.
360
500
  """
361
- return Cheque.de_json(self._request("PUT", "/api/v1/cheques", params=_identifier("chequeId", cheque_id, "clientChequeId", client_cheque_id), body={"description": description}))
501
+ return Cheque.de_json(self._request("PUT", "/api/v1/cheques", params=self.__identifier("chequeId", cheque_id, "clientChequeId", client_cheque_id), body={"description": description}))
362
502
 
363
503
  def delete_cheque(self, cheque_id: str | None = None, client_cheque_id: str | None = None) -> None:
364
504
  """Delete cheque.
@@ -370,10 +510,10 @@ class xRocketPayAPI:
370
510
  :param client_cheque_id: Unique cheque id in your system.
371
511
  :return: ``None``.
372
512
  """
373
- self._request("DELETE", "/api/v1/cheques", params=_identifier("chequeId", cheque_id, "clientChequeId", client_cheque_id))
513
+ self._request("DELETE", "/api/v1/cheques", params=self.__identifier("chequeId", cheque_id, "clientChequeId", client_cheque_id))
374
514
 
375
- def payout_funds_to_user(self, target: str, target_type: str, asset: str, amount: str, client_payout_id: str | None = None,
376
- description: str | None = None, callback: Mapping[str, Any] | None = None) -> Payout:
515
+ def create_payout(self, target: str, target_type: str, asset: str, amount: str | int | float, client_payout_id: str | None = None,
516
+ description: str | None = None, callback: PayoutCallback | None = None) -> Payout:
377
517
  """Payout funds to user.
378
518
 
379
519
  API: https://docs.xrocket.exchange/api/pay/reference/http/payout-controller-payout
@@ -381,15 +521,15 @@ class xRocketPayAPI:
381
521
  :param target: Target.
382
522
  :param target_type: Target type.
383
523
  :param asset: Asset of transfer.
384
- :param amount: Payout amount.
524
+ :param amount: Payout amount. A numeric value is encoded as an API string.
385
525
  :param client_payout_id: Unique payout ID in your system to prevent double spends.
386
526
  :param description: Payout description.
387
- :param callback: Webhook settings for payout status updates.
527
+ :param callback: Webhook settings for payout status updates as a ``PayoutCallback`` instance.
388
528
  :return: ``Payout``.
389
529
  """
390
- return Payout.de_json(self._request("POST", "/api/v1/payouts", body=_without_none(
391
- target=target, targetType=target_type, asset=asset, amount=str(amount), clientPayoutId=client_payout_id,
392
- description=description, callback=callback,
530
+ return Payout.de_json(self._request("POST", "/api/v1/payouts", body=self.__without_none(
531
+ target=target, targetType=target_type, asset=asset, amount=self.__number_as_string(amount, "amount"), clientPayoutId=client_payout_id,
532
+ description=description, callback=self.__request_model(callback, PayoutCallback, "callback"),
393
533
  )))
394
534
 
395
535
  def get_payouts_list(self, from_date: str | None = None, to_date: str | None = None, cursor: str | None = None,
@@ -404,7 +544,7 @@ class xRocketPayAPI:
404
544
  :param limit: No description is provided.
405
545
  :return: ``PayoutsList``.
406
546
  """
407
- return PayoutsList.de_json(self._request("GET", "/api/v1/payouts", params=_without_none(fromDate=from_date, toDate=to_date, cursor=cursor, limit=limit)))
547
+ return PayoutsList.de_json(self._request("GET", "/api/v1/payouts", params=self.__without_none(fromDate=from_date, toDate=to_date, cursor=cursor, limit=limit)))
408
548
 
409
549
  def get_payout_info(self, payout_id: str | None = None, client_payout_id: str | None = None) -> Payout:
410
550
  """Get payout info.
@@ -415,21 +555,26 @@ class xRocketPayAPI:
415
555
  :param client_payout_id: Unique payout ID in your system to prevent double spends.
416
556
  :return: ``Payout``.
417
557
  """
418
- return Payout.de_json(self._request("GET", "/api/v1/payout", params=_identifier("payoutId", payout_id, "clientPayoutId", client_payout_id)))
558
+ return Payout.de_json(self._request("GET", "/api/v1/payout", params=self.__identifier("payoutId", payout_id, "clientPayoutId", client_payout_id)))
419
559
 
420
- def create_mass_payouts(self, asset: str, payouts: Iterable[Mapping[str, Any]]) -> MassPayouts:
560
+ def create_mass_payouts(self, asset: str, payouts: Iterable[MassPayout]) -> MassPayouts:
421
561
  """Create mass payouts (Telegram users only).
422
562
 
423
563
  API: https://docs.xrocket.exchange/api/pay/reference/http/mass-payouts-controller-create-mass-payouts
424
564
 
425
565
  :param asset: Asset of payouts.
426
- :param payouts: List of payouts to process.
566
+ :param payouts: List of ``MassPayout`` instances to process.
427
567
  :return: ``MassPayouts``.
428
568
  """
429
- return MassPayouts.de_json(self._request("POST", "/api/v1/mass-payouts", body={"asset": asset, "payouts": list(payouts)}))
430
-
431
- def withdrawal_funds(self, client_withdrawal_id: str, network: str, address: str, asset: str, amount: str,
432
- comment: str | None = None, callback: Mapping[str, Any] | None = None) -> Withdrawal:
569
+ payout_data = []
570
+ for payout in payouts:
571
+ if not isinstance(payout, MassPayout):
572
+ raise TypeError("payouts must contain only MassPayout instances.")
573
+ payout_data.append(payout.to_dict())
574
+ return MassPayouts.de_json(self._request("POST", "/api/v1/mass-payouts", body={"asset": asset, "payouts": payout_data}))
575
+
576
+ def create_withdrawal(self, client_withdrawal_id: str, network: str, address: str, asset: str, amount: str | int | float,
577
+ comment: str | None = None, callback: WithdrawalCallback | None = None) -> Withdrawal:
433
578
  """Withdrawal funds from application to external wallet.
434
579
 
435
580
  API: https://docs.xrocket.exchange/api/pay/reference/http/withdrawal-controller-create-withdrawal
@@ -438,14 +583,14 @@ class xRocketPayAPI:
438
583
  :param network: Network code.
439
584
  :param address: Withdrawal address.
440
585
  :param asset: Asset code.
441
- :param amount: Withdrawal amount.
586
+ :param amount: Withdrawal amount. A numeric value is encoded as an API string.
442
587
  :param comment: Withdrawal comment.
443
- :param callback: Webhook settings for withdrawal status updates.
588
+ :param callback: Webhook settings for withdrawal status updates as a ``WithdrawalCallback`` instance.
444
589
  :return: ``Withdrawal``.
445
590
  """
446
- return Withdrawal.de_json(self._request("POST", "/api/v1/withdrawals", body=_without_none(
447
- clientWithdrawalId=client_withdrawal_id, network=network, address=address, asset=asset, amount=str(amount),
448
- comment=comment, callback=callback,
591
+ return Withdrawal.de_json(self._request("POST", "/api/v1/withdrawals", body=self.__without_none(
592
+ clientWithdrawalId=client_withdrawal_id, network=network, address=address, asset=asset, amount=self.__number_as_string(amount, "amount"),
593
+ comment=comment, callback=self.__request_model(callback, WithdrawalCallback, "callback"),
449
594
  )))
450
595
 
451
596
  def get_withdrawals_list(self, from_date: str | None = None, to_date: str | None = None, status: str | None = None,
@@ -461,7 +606,7 @@ class xRocketPayAPI:
461
606
  :param limit: No description is provided.
462
607
  :return: ``WithdrawalsList``.
463
608
  """
464
- return WithdrawalsList.de_json(self._request("GET", "/api/v1/withdrawals", params=_without_none(
609
+ return WithdrawalsList.de_json(self._request("GET", "/api/v1/withdrawals", params=self.__without_none(
465
610
  fromDate=from_date, toDate=to_date, status=status, cursor=cursor, limit=limit,
466
611
  )))
467
612
 
@@ -474,7 +619,7 @@ class xRocketPayAPI:
474
619
  :param client_withdrawal_id: Unique withdrawal ID in your system to prevent double spends.
475
620
  :return: ``Withdrawal``.
476
621
  """
477
- return Withdrawal.de_json(self._request("GET", "/api/v1/withdrawal", params=_identifier("withdrawalId", withdrawal_id, "clientWithdrawalId", client_withdrawal_id)))
622
+ return Withdrawal.de_json(self._request("GET", "/api/v1/withdrawal", params=self.__identifier("withdrawalId", withdrawal_id, "clientWithdrawalId", client_withdrawal_id)))
478
623
 
479
624
  def get_withdrawal_quotas(self, network: str, asset: str) -> WithdrawalQuotas:
480
625
  """Get application withdrawal quotas.
@@ -487,7 +632,7 @@ class xRocketPayAPI:
487
632
  """
488
633
  return WithdrawalQuotas.de_json(self._request("GET", "/api/v1/withdrawal-quotas", params={"network": network, "asset": asset}))
489
634
 
490
- def create_withdrawal_link(self, network: str, address: str, asset: str, amount: str, comment: str | None = None,
635
+ def create_withdrawal_link(self, network: str, address: str, asset: str, amount: str | int | float, comment: str | None = None,
491
636
  platform: str | None = None) -> WithdrawalLink:
492
637
  """Create withdrawal link.
493
638
 
@@ -496,11 +641,11 @@ class xRocketPayAPI:
496
641
  :param network: Network code.
497
642
  :param address: Withdrawal address.
498
643
  :param asset: Asset code.
499
- :param amount: Withdrawal amount.
644
+ :param amount: Withdrawal amount. A numeric value is encoded as an API string.
500
645
  :param comment: Withdrawal comment.
501
646
  :param platform: Platform identifier (optional, use only if provided by xRocket).
502
647
  :return: ``WithdrawalLink``.
503
648
  """
504
- return WithdrawalLink.de_json(self._request("POST", "/api/v1/withdrawal-link", body=_without_none(
505
- network=network, address=address, asset=asset, amount=str(amount), comment=comment, platform=platform,
649
+ return WithdrawalLink.de_json(self._request("POST", "/api/v1/withdrawal-link", body=self.__without_none(
650
+ network=network, address=address, asset=asset, amount=self.__number_as_string(amount, "amount"), comment=comment, platform=platform,
506
651
  )))