pyXRocketAPI 0.2.0__tar.gz → 0.3.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: 0.3.0
4
4
  Summary: Python client for the xRocket Pay API
5
5
  Author: Badiboy
6
6
  License-Expression: MIT
@@ -47,6 +47,40 @@ For integration testing, use the xRocket testnet instead of production:
47
47
  client = xRocketPayAPI(token="testnet-token", testnet=True)
48
48
  ```
49
49
 
50
+ ## Nested request models
51
+
52
+ Known nested API objects are passed as model instances, not dictionaries. The
53
+ same models deserialize API responses and implement `to_dict()` for request
54
+ bodies.
55
+
56
+ ```python
57
+ from pyXRocketAPI import InvoiceCallback, InvoiceCustomer, InvoiceUrl, xRocketPayAPI
58
+
59
+ client = xRocketPayAPI(token="your-pay-api-token")
60
+ invoice = client.create_invoice(
61
+ price_currency="USDT",
62
+ price_amount="10.00",
63
+ callback=InvoiceCallback(
64
+ callbackUrl="https://example.com/webhooks/invoice",
65
+ payload={"order_id": "123"},
66
+ ),
67
+ url=InvoiceUrl(
68
+ successUrl="https://example.com/success",
69
+ cancelUrl="https://example.com/cancel",
70
+ ),
71
+ customer=InvoiceCustomer(
72
+ id="customer-123",
73
+ email="customer@example.com",
74
+ telegramId="123456789",
75
+ ),
76
+ data={"internal_order_id": "123"},
77
+ )
78
+ ```
79
+
80
+ `payload` and `data` remain ordinary dictionaries because xRocket defines them
81
+ as arbitrary JSON objects without a fixed schema. Use `MassPayout` instances
82
+ for every item passed to `create_mass_payouts()`.
83
+
50
84
  ## Safety
51
85
 
52
86
  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, 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,52 @@ 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
+
40
60
  def __init__(
41
61
  self,
42
62
  token: str | None = None,
43
63
  testnet: bool = False,
44
- timeout: float | tuple[float, float] | None = 10,
64
+ timeout: float | tuple[float, float] | None = 30,
45
65
  ) -> None:
46
66
  self.token = token
47
67
  self.timeout = timeout
@@ -113,14 +133,14 @@ class xRocketPayAPI:
113
133
  except ValueError as error:
114
134
  raise xRocketAPIException("xRocket Pay returned invalid JSON.", status=response.status_code) from error
115
135
 
116
- def health_check(self) -> xRocketObject:
136
+ def health_check(self) -> Health:
117
137
  """Run the public health check.
118
138
 
119
139
  API: https://docs.xrocket.exchange/api/pay/reference/http/health-controller-health
120
140
 
121
- :return: ``xRocketObject``.
141
+ :return: ``Health``.
122
142
  """
123
- return xRocketObject.de_json(self._request("GET", "/health", auth_required=False), process_mode=2)
143
+ return Health.de_json(self._request("GET", "/health", auth_required=False))
124
144
 
125
145
  def get_app_info(self) -> App:
126
146
  """Get information about your application.
@@ -150,7 +170,7 @@ class xRocketPayAPI:
150
170
  :return: ``list[Currency]``.
151
171
  """
152
172
  data = self._request(
153
- "GET", "/api/v1/currencies", params=_without_none(kind=kind), auth_required=False
173
+ "GET", "/api/v1/currencies", params=self.__without_none(kind=kind), auth_required=False
154
174
  )
155
175
  return [Currency.de_json(item) for item in data]
156
176
 
@@ -173,17 +193,17 @@ class xRocketPayAPI:
173
193
  def create_invoice(
174
194
  self,
175
195
  price_currency: str,
176
- price_amount: str | None = None,
177
- min_payment: str | None = None,
196
+ price_amount: str | int | float | None = None,
197
+ min_payment: str | int | float | None = None,
178
198
  num_payments: int | None = None,
179
199
  payout_currency: str | None = None,
180
200
  pay_currencies: Iterable[str] | None = None,
181
201
  client_invoice_id: str | None = None,
182
202
  description: str | None = None,
183
203
  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,
204
+ callback: InvoiceCallback | None = None,
205
+ url: InvoiceUrl | None = None,
206
+ customer: InvoiceCustomer | None = None,
187
207
  is_fee_paid_by_user: bool | None = None,
188
208
  data: Mapping[str, Any] | None = None,
189
209
  platform_id: str | None = None,
@@ -193,27 +213,32 @@ class xRocketPayAPI:
193
213
  API: https://docs.xrocket.exchange/api/pay/reference/http/invoice-controller-create-invoice
194
214
 
195
215
  :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).
216
+ :param price_amount: Invoice price amount. A numeric value is encoded as an API string.
217
+ :param min_payment: Minimum payment amount (for open-amount invoices). A numeric value is encoded as an API string.
198
218
  :param num_payments: Num payments for invoice.
199
219
  :param payout_currency: Invoice payout crypto currency.
200
220
  :param pay_currencies: Crypto currencies which can be used to pay the invoice.
201
221
  :param client_invoice_id: Client Invoice ID as assigned by the client.
202
222
  :param description: Description for invoice.
203
223
  :param expires_in: Payment expires in milliseconds.
204
- :param callback: Callback data.
205
- :param url: User redirect urls.
206
- :param customer: Customer info.
224
+ :param callback: Callback data as an ``InvoiceCallback`` instance.
225
+ :param url: User redirect urls as an ``InvoiceUrl`` instance.
226
+ :param customer: Customer info as an ``InvoiceCustomer`` instance.
207
227
  :param is_fee_paid_by_user: If true, the user pays a commission.
208
228
  :param data: Custom user data passed through and returned in callbacks/webhooks (max size 4KB).
209
229
  :param platform_id: Platform identifier.
210
230
  :return: ``Invoice``.
211
231
  """
212
- body = _without_none(
213
- priceCurrency=price_currency, priceAmount=price_amount, minPayment=min_payment, numPayments=num_payments,
232
+ body = self.__without_none(
233
+ priceCurrency=price_currency,
234
+ priceAmount=self.__number_as_string(price_amount, "price_amount"),
235
+ minPayment=self.__number_as_string(min_payment, "min_payment"), numPayments=num_payments,
214
236
  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,
237
+ clientInvoiceId=client_invoice_id, description=description, expiresIn=expires_in,
238
+ callback=self.__request_model(callback, InvoiceCallback, "callback"),
239
+ url=self.__request_model(url, InvoiceUrl, "url"),
240
+ customer=self.__request_model(customer, InvoiceCustomer, "customer"),
241
+ isFeePaidByUser=is_fee_paid_by_user, data=data, platformId=platform_id,
217
242
  )
218
243
  return Invoice.de_json(self._request("POST", "/api/v1/invoices", body=body))
219
244
 
@@ -231,7 +256,7 @@ class xRocketPayAPI:
231
256
  :param limit: No description is provided.
232
257
  :return: ``InvoicesList``.
233
258
  """
234
- params = _without_none(asset=asset, fiat=fiat, ids=list(ids) if ids is not None else None, status=status, cursor=cursor, limit=limit)
259
+ 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
260
  return InvoicesList.de_json(self._request("GET", "/api/v1/invoices", params=params))
236
261
 
237
262
  def get_invoice_info(self, invoice_id: str | None = None, client_invoice_id: str | None = None) -> Invoice:
@@ -244,7 +269,7 @@ class xRocketPayAPI:
244
269
  :param client_invoice_id: Client Invoice ID assigned by the client. Either invoiceId or clientInvoiceId is required.
245
270
  :return: ``Invoice``.
246
271
  """
247
- return Invoice.de_json(self._request("GET", "/api/v1/invoice", params=_identifier("invoiceId", invoice_id, "clientInvoiceId", client_invoice_id)))
272
+ return Invoice.de_json(self._request("GET", "/api/v1/invoice", params=self.__identifier("invoiceId", invoice_id, "clientInvoiceId", client_invoice_id)))
248
273
 
249
274
  def delete_invoice(self, invoice_id: str | None = None, client_invoice_id: str | None = None) -> None:
250
275
  """Delete invoice.
@@ -256,7 +281,7 @@ class xRocketPayAPI:
256
281
  :param client_invoice_id: Client Invoice ID assigned by the client. Either invoiceId or clientInvoiceId is required.
257
282
  :return: ``None``.
258
283
  """
259
- self._request("DELETE", "/api/v1/invoice", params=_identifier("invoiceId", invoice_id, "clientInvoiceId", client_invoice_id))
284
+ self._request("DELETE", "/api/v1/invoice", params=self.__identifier("invoiceId", invoice_id, "clientInvoiceId", client_invoice_id))
260
285
 
261
286
  def get_invoice_payments(self, invoice_id: str | None = None, client_invoice_id: str | None = None,
262
287
  cursor: str | None = None, limit: int | None = None) -> InvoicePaymentsList:
@@ -271,8 +296,8 @@ class xRocketPayAPI:
271
296
  :param limit: No description is provided.
272
297
  :return: ``InvoicePaymentsList``.
273
298
  """
274
- params = _identifier("invoiceId", invoice_id, "clientInvoiceId", client_invoice_id)
275
- params.update(_without_none(cursor=cursor, limit=limit))
299
+ params = self.__identifier("invoiceId", invoice_id, "clientInvoiceId", client_invoice_id)
300
+ params.update(self.__without_none(cursor=cursor, limit=limit))
276
301
  return InvoicePaymentsList.de_json(self._request("GET", "/api/v1/invoice/payments", params=params))
277
302
 
278
303
  def create_invoice_payment_address(self, pay_network: str, invoice_id: str | None = None,
@@ -288,11 +313,11 @@ class xRocketPayAPI:
288
313
  """
289
314
  return InvoicePaymentAddress.de_json(self._request(
290
315
  "POST", "/api/v1/invoices/payments/address",
291
- params=_identifier("invoiceId", invoice_id, "clientInvoiceId", client_invoice_id), body={"payNetwork": pay_network},
316
+ params=self.__identifier("invoiceId", invoice_id, "clientInvoiceId", client_invoice_id), body={"payNetwork": pay_network},
292
317
  ))
293
318
 
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,
319
+ def create_cheque(self, asset: str, amount: str | int | float, client_cheque_id: str | None = None, password: str | None = None,
320
+ description: str | None = None, callback: ChequeCallback | None = None, url: ChequeUrl | None = None,
296
321
  target_type: str | None = None, target: str | None = None) -> Cheque:
297
322
  """Create cheque.
298
323
 
@@ -300,19 +325,20 @@ class xRocketPayAPI:
300
325
  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
326
 
302
327
  :param asset: Currency of transfer.
303
- :param amount: Cheque amount.
328
+ :param amount: Cheque amount. A numeric value is encoded as an API string.
304
329
  :param client_cheque_id: Unique cheque ID in your system to prevent double spends.
305
330
  :param password: Cheque password, the recipient has to enter it to redeem the cheque.
306
331
  :param description: Description for cheque.
307
- :param callback: Webhook settings for cheque activation updates.
308
- :param url: User redirect urls after cheque activation.
332
+ :param callback: Webhook settings for cheque activation updates as a ``ChequeCallback`` instance.
333
+ :param url: User redirect urls after cheque activation as a ``ChequeUrl`` instance.
309
334
  :param target_type: Target type for cheque, has to be passed together with target.
310
335
  :param target: Target for cheque, has to be passed together with targetType.
311
336
  :return: ``Cheque``.
312
337
  """
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,
338
+ return Cheque.de_json(self._request("POST", "/api/v1/cheques", body=self.__without_none(
339
+ asset=asset, amount=self.__number_as_string(amount, "amount"), clientChequeId=client_cheque_id, password=password, description=description,
340
+ callback=self.__request_model(callback, ChequeCallback, "callback"),
341
+ url=self.__request_model(url, ChequeUrl, "url"), targetType=target_type, target=target,
316
342
  )))
317
343
 
318
344
  def get_cheques_list(self, from_date: str | None = None, to_date: str | None = None, target_type: str | None = None,
@@ -331,7 +357,7 @@ class xRocketPayAPI:
331
357
  :param limit: No description is provided.
332
358
  :return: ``ChequesList``.
333
359
  """
334
- return ChequesList.de_json(self._request("GET", "/api/v1/cheques", params=_without_none(
360
+ return ChequesList.de_json(self._request("GET", "/api/v1/cheques", params=self.__without_none(
335
361
  fromDate=from_date, toDate=to_date, targetType=target_type, target=target, state=state, cursor=cursor, limit=limit,
336
362
  )))
337
363
 
@@ -345,7 +371,7 @@ class xRocketPayAPI:
345
371
  :param client_cheque_id: Unique cheque id in your system.
346
372
  :return: ``Cheque``.
347
373
  """
348
- return Cheque.de_json(self._request("GET", "/api/v1/cheque", params=_identifier("chequeId", cheque_id, "clientChequeId", client_cheque_id)))
374
+ return Cheque.de_json(self._request("GET", "/api/v1/cheque", params=self.__identifier("chequeId", cheque_id, "clientChequeId", client_cheque_id)))
349
375
 
350
376
  def update_cheque(self, description: str, cheque_id: str | None = None, client_cheque_id: str | None = None) -> Cheque:
351
377
  """Update cheque.
@@ -358,7 +384,7 @@ class xRocketPayAPI:
358
384
  :param client_cheque_id: Unique cheque id in your system.
359
385
  :return: ``Cheque``.
360
386
  """
361
- return Cheque.de_json(self._request("PUT", "/api/v1/cheques", params=_identifier("chequeId", cheque_id, "clientChequeId", client_cheque_id), body={"description": description}))
387
+ return Cheque.de_json(self._request("PUT", "/api/v1/cheques", params=self.__identifier("chequeId", cheque_id, "clientChequeId", client_cheque_id), body={"description": description}))
362
388
 
363
389
  def delete_cheque(self, cheque_id: str | None = None, client_cheque_id: str | None = None) -> None:
364
390
  """Delete cheque.
@@ -370,10 +396,10 @@ class xRocketPayAPI:
370
396
  :param client_cheque_id: Unique cheque id in your system.
371
397
  :return: ``None``.
372
398
  """
373
- self._request("DELETE", "/api/v1/cheques", params=_identifier("chequeId", cheque_id, "clientChequeId", client_cheque_id))
399
+ self._request("DELETE", "/api/v1/cheques", params=self.__identifier("chequeId", cheque_id, "clientChequeId", client_cheque_id))
374
400
 
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:
401
+ def create_payout(self, target: str, target_type: str, asset: str, amount: str | int | float, client_payout_id: str | None = None,
402
+ description: str | None = None, callback: PayoutCallback | None = None) -> Payout:
377
403
  """Payout funds to user.
378
404
 
379
405
  API: https://docs.xrocket.exchange/api/pay/reference/http/payout-controller-payout
@@ -381,15 +407,15 @@ class xRocketPayAPI:
381
407
  :param target: Target.
382
408
  :param target_type: Target type.
383
409
  :param asset: Asset of transfer.
384
- :param amount: Payout amount.
410
+ :param amount: Payout amount. A numeric value is encoded as an API string.
385
411
  :param client_payout_id: Unique payout ID in your system to prevent double spends.
386
412
  :param description: Payout description.
387
- :param callback: Webhook settings for payout status updates.
413
+ :param callback: Webhook settings for payout status updates as a ``PayoutCallback`` instance.
388
414
  :return: ``Payout``.
389
415
  """
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,
416
+ return Payout.de_json(self._request("POST", "/api/v1/payouts", body=self.__without_none(
417
+ target=target, targetType=target_type, asset=asset, amount=self.__number_as_string(amount, "amount"), clientPayoutId=client_payout_id,
418
+ description=description, callback=self.__request_model(callback, PayoutCallback, "callback"),
393
419
  )))
394
420
 
395
421
  def get_payouts_list(self, from_date: str | None = None, to_date: str | None = None, cursor: str | None = None,
@@ -404,7 +430,7 @@ class xRocketPayAPI:
404
430
  :param limit: No description is provided.
405
431
  :return: ``PayoutsList``.
406
432
  """
407
- return PayoutsList.de_json(self._request("GET", "/api/v1/payouts", params=_without_none(fromDate=from_date, toDate=to_date, cursor=cursor, limit=limit)))
433
+ 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
434
 
409
435
  def get_payout_info(self, payout_id: str | None = None, client_payout_id: str | None = None) -> Payout:
410
436
  """Get payout info.
@@ -415,21 +441,26 @@ class xRocketPayAPI:
415
441
  :param client_payout_id: Unique payout ID in your system to prevent double spends.
416
442
  :return: ``Payout``.
417
443
  """
418
- return Payout.de_json(self._request("GET", "/api/v1/payout", params=_identifier("payoutId", payout_id, "clientPayoutId", client_payout_id)))
444
+ return Payout.de_json(self._request("GET", "/api/v1/payout", params=self.__identifier("payoutId", payout_id, "clientPayoutId", client_payout_id)))
419
445
 
420
- def create_mass_payouts(self, asset: str, payouts: Iterable[Mapping[str, Any]]) -> MassPayouts:
446
+ def create_mass_payouts(self, asset: str, payouts: Iterable[MassPayout]) -> MassPayouts:
421
447
  """Create mass payouts (Telegram users only).
422
448
 
423
449
  API: https://docs.xrocket.exchange/api/pay/reference/http/mass-payouts-controller-create-mass-payouts
424
450
 
425
451
  :param asset: Asset of payouts.
426
- :param payouts: List of payouts to process.
452
+ :param payouts: List of ``MassPayout`` instances to process.
427
453
  :return: ``MassPayouts``.
428
454
  """
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:
455
+ payout_data = []
456
+ for payout in payouts:
457
+ if not isinstance(payout, MassPayout):
458
+ raise TypeError("payouts must contain only MassPayout instances.")
459
+ payout_data.append(payout.to_dict())
460
+ return MassPayouts.de_json(self._request("POST", "/api/v1/mass-payouts", body={"asset": asset, "payouts": payout_data}))
461
+
462
+ def create_withdrawal(self, client_withdrawal_id: str, network: str, address: str, asset: str, amount: str | int | float,
463
+ comment: str | None = None, callback: WithdrawalCallback | None = None) -> Withdrawal:
433
464
  """Withdrawal funds from application to external wallet.
434
465
 
435
466
  API: https://docs.xrocket.exchange/api/pay/reference/http/withdrawal-controller-create-withdrawal
@@ -438,14 +469,14 @@ class xRocketPayAPI:
438
469
  :param network: Network code.
439
470
  :param address: Withdrawal address.
440
471
  :param asset: Asset code.
441
- :param amount: Withdrawal amount.
472
+ :param amount: Withdrawal amount. A numeric value is encoded as an API string.
442
473
  :param comment: Withdrawal comment.
443
- :param callback: Webhook settings for withdrawal status updates.
474
+ :param callback: Webhook settings for withdrawal status updates as a ``WithdrawalCallback`` instance.
444
475
  :return: ``Withdrawal``.
445
476
  """
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,
477
+ return Withdrawal.de_json(self._request("POST", "/api/v1/withdrawals", body=self.__without_none(
478
+ clientWithdrawalId=client_withdrawal_id, network=network, address=address, asset=asset, amount=self.__number_as_string(amount, "amount"),
479
+ comment=comment, callback=self.__request_model(callback, WithdrawalCallback, "callback"),
449
480
  )))
450
481
 
451
482
  def get_withdrawals_list(self, from_date: str | None = None, to_date: str | None = None, status: str | None = None,
@@ -461,7 +492,7 @@ class xRocketPayAPI:
461
492
  :param limit: No description is provided.
462
493
  :return: ``WithdrawalsList``.
463
494
  """
464
- return WithdrawalsList.de_json(self._request("GET", "/api/v1/withdrawals", params=_without_none(
495
+ return WithdrawalsList.de_json(self._request("GET", "/api/v1/withdrawals", params=self.__without_none(
465
496
  fromDate=from_date, toDate=to_date, status=status, cursor=cursor, limit=limit,
466
497
  )))
467
498
 
@@ -474,7 +505,7 @@ class xRocketPayAPI:
474
505
  :param client_withdrawal_id: Unique withdrawal ID in your system to prevent double spends.
475
506
  :return: ``Withdrawal``.
476
507
  """
477
- return Withdrawal.de_json(self._request("GET", "/api/v1/withdrawal", params=_identifier("withdrawalId", withdrawal_id, "clientWithdrawalId", client_withdrawal_id)))
508
+ return Withdrawal.de_json(self._request("GET", "/api/v1/withdrawal", params=self.__identifier("withdrawalId", withdrawal_id, "clientWithdrawalId", client_withdrawal_id)))
478
509
 
479
510
  def get_withdrawal_quotas(self, network: str, asset: str) -> WithdrawalQuotas:
480
511
  """Get application withdrawal quotas.
@@ -487,7 +518,7 @@ class xRocketPayAPI:
487
518
  """
488
519
  return WithdrawalQuotas.de_json(self._request("GET", "/api/v1/withdrawal-quotas", params={"network": network, "asset": asset}))
489
520
 
490
- def create_withdrawal_link(self, network: str, address: str, asset: str, amount: str, comment: str | None = None,
521
+ def create_withdrawal_link(self, network: str, address: str, asset: str, amount: str | int | float, comment: str | None = None,
491
522
  platform: str | None = None) -> WithdrawalLink:
492
523
  """Create withdrawal link.
493
524
 
@@ -496,11 +527,11 @@ class xRocketPayAPI:
496
527
  :param network: Network code.
497
528
  :param address: Withdrawal address.
498
529
  :param asset: Asset code.
499
- :param amount: Withdrawal amount.
530
+ :param amount: Withdrawal amount. A numeric value is encoded as an API string.
500
531
  :param comment: Withdrawal comment.
501
532
  :param platform: Platform identifier (optional, use only if provided by xRocket).
502
533
  :return: ``WithdrawalLink``.
503
534
  """
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,
535
+ return WithdrawalLink.de_json(self._request("POST", "/api/v1/withdrawal-link", body=self.__without_none(
536
+ network=network, address=address, asset=asset, amount=self.__number_as_string(amount, "amount"), comment=comment, platform=platform,
506
537
  )))