cryptochief-crypto-processing-python 0.2.0__tar.gz → 0.4.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.
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/PKG-INFO +35 -2
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/README.md +34 -1
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/__init__.py +18 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/_version.py +1 -1
- cryptochief_crypto_processing_python-0.4.0/src/cryptochief/sentinels.py +38 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/services/payins.py +32 -0
- cryptochief_crypto_processing_python-0.4.0/src/cryptochief/services/sweeps.py +282 -0
- cryptochief_crypto_processing_python-0.2.0/src/cryptochief/services/sweeps.py +0 -85
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/.gitignore +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/LICENSE +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/pyproject.toml +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/_models.py +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/amount.py +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/assets.py +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/chains.py +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/client.py +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/contract/__init__.py +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/contract/base58.py +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/contract/borsh.py +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/contract/evm_abi.py +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/contract/keccak.py +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/contract/tron_address.py +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/errors.py +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/pagination.py +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/poll.py +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/rsa.py +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/services/__init__.py +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/services/base.py +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/services/blockchain.py +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/services/credits.py +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/services/currencies.py +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/services/payouts.py +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/services/static_deposits.py +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/services/transactions.py +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/services/wallets.py +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/services/withdrawals.py +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/sign.py +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/ton/__init__.py +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/ton/address.py +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/ton/messages.py +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/ton/rpc.py +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/transport.py +0 -0
- {cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/src/cryptochief/webhook.py +0 -0
{cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: cryptochief-crypto-processing-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Official async Python SDK for the Crypto Chief crypto payment gateway and crypto processing API. Accept crypto payments, send single and mass crypto payouts, sign on-chain transactions and smart-contract calls, manage wallets, convert fiat to crypto, and verify webhooks across Ethereum, BNB Smart Chain, Polygon, Tron, TON, Solana, Bitcoin, XRP and 20+ blockchains. USDT and USDC stablecoin support with int-precise amounts and asyncio/httpx.
|
|
5
5
|
Project-URL: Homepage, https://crypto-chief.com/processing/
|
|
6
6
|
Project-URL: Documentation, https://docs-sdk.crypto-chief.com/processing/python
|
|
@@ -121,7 +121,7 @@ Both credentials come from the Dashboard -> Project.
|
|
|
121
121
|
| TON contract calls (Jetton / NFT / text) | `client.transactions` | `jetton_transfer`, `nft_transfer`, `send_ton_comment`, `sign_ton_call` |
|
|
122
122
|
| Accept incoming payments | `client.pay_ins` | `create`, `select_asset`, `reset_asset`, `cancel`, `info`, `history`, `wait_for` |
|
|
123
123
|
| Wallet management + RSA decrypt | `client.wallets` | `generate`, `list`, `info`, `freeze`, `decrypt_private_key` |
|
|
124
|
-
| Treasury sweeps | `client.sweeps` | `force`, `history`, `wallet_history` |
|
|
124
|
+
| Treasury sweeps | `client.sweeps` | `force`, `history`, `wallet_history`, `settings`, `update_settings` |
|
|
125
125
|
| Withdrawals (read-only) | `client.withdrawals` | `info`, `history` |
|
|
126
126
|
| Static-deposit history | `client.static_deposits` | `info`, `history` |
|
|
127
127
|
| On-chain queries | `client.blockchain` | `contracts_available`, `wallet_balance`, `transaction_status` |
|
|
@@ -335,6 +335,39 @@ priv = client.wallets.decrypt_private_key(wallet.private_key_encrypted)
|
|
|
335
335
|
- **How do I do a crypto swap?** A swap is a payout with `auto_convert=True`.
|
|
336
336
|
- **How do I call a smart contract?** `client.transactions.sign_evm_call` /
|
|
337
337
|
`sign_anchor_call` / `jetton_transfer`, then `transactions.execute`.
|
|
338
|
+
- **How do I control when a deposit wallet is swept?**
|
|
339
|
+
`client.sweeps.settings(...)` reads the policy in force for one wallet and
|
|
340
|
+
`client.sweeps.update_settings(...)` changes it - sweep on arrival
|
|
341
|
+
(`SweepPolicyMode.MOMENTUM`), sweep once the balance reaches an amount
|
|
342
|
+
(`SweepPolicyMode.THRESHOLD` plus `threshold_amount_usd`), or never on its own
|
|
343
|
+
(`SweepPolicyMode.OFF`, force still works). The read comes back in three
|
|
344
|
+
layers - what will happen, what this wallet overrides, and what it inherits
|
|
345
|
+
from the project - so a value of your own is distinguishable from an inherited
|
|
346
|
+
one:
|
|
347
|
+
|
|
348
|
+
```python
|
|
349
|
+
s = await client.sweeps.update_settings(
|
|
350
|
+
deposit_address,
|
|
351
|
+
type_work=SweepPolicyMode.THRESHOLD,
|
|
352
|
+
threshold_amount_usd="250",
|
|
353
|
+
)
|
|
354
|
+
# s.effective is the resolved policy; s.effective.source names the layer it came from.
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
Inheritance is per field: overriding the mode leaves the fee mode inherited.
|
|
358
|
+
To stop overriding a field, pass `CLEAR` - `None` already means "leave this
|
|
359
|
+
field alone", so it cannot also mean "reset it".
|
|
360
|
+
- **How do I know a sweep actually settled?** Check `status`.
|
|
361
|
+
`SweepStatus.BROADCASTED` means the transaction is out and not yet confirmed;
|
|
362
|
+
`SweepStatus.COMPLETED` means confirmed, with `sweep_confirmations` and
|
|
363
|
+
`completed_at` filled in. Earlier platform versions reported `completed` at
|
|
364
|
+
broadcast, so a sweep could read as settled while its transaction was still
|
|
365
|
+
unconfirmed.
|
|
366
|
+
- **How do I keep test payments off real chains?** Set `environment` on
|
|
367
|
+
`CreatePayInRequest` to `Environment.TESTNET` or `Environment.MAINNET`. It
|
|
368
|
+
constrains the asset the platform picks when you have not named a concrete
|
|
369
|
+
network - fiat mode and `ANY` - so an unconstrained pick cannot put a real
|
|
370
|
+
payment on a test chain. Omit it to use the project's default.
|
|
338
371
|
|
|
339
372
|
## Documentation
|
|
340
373
|
|
{cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/README.md
RENAMED
|
@@ -82,7 +82,7 @@ Both credentials come from the Dashboard -> Project.
|
|
|
82
82
|
| TON contract calls (Jetton / NFT / text) | `client.transactions` | `jetton_transfer`, `nft_transfer`, `send_ton_comment`, `sign_ton_call` |
|
|
83
83
|
| Accept incoming payments | `client.pay_ins` | `create`, `select_asset`, `reset_asset`, `cancel`, `info`, `history`, `wait_for` |
|
|
84
84
|
| Wallet management + RSA decrypt | `client.wallets` | `generate`, `list`, `info`, `freeze`, `decrypt_private_key` |
|
|
85
|
-
| Treasury sweeps | `client.sweeps` | `force`, `history`, `wallet_history` |
|
|
85
|
+
| Treasury sweeps | `client.sweeps` | `force`, `history`, `wallet_history`, `settings`, `update_settings` |
|
|
86
86
|
| Withdrawals (read-only) | `client.withdrawals` | `info`, `history` |
|
|
87
87
|
| Static-deposit history | `client.static_deposits` | `info`, `history` |
|
|
88
88
|
| On-chain queries | `client.blockchain` | `contracts_available`, `wallet_balance`, `transaction_status` |
|
|
@@ -296,6 +296,39 @@ priv = client.wallets.decrypt_private_key(wallet.private_key_encrypted)
|
|
|
296
296
|
- **How do I do a crypto swap?** A swap is a payout with `auto_convert=True`.
|
|
297
297
|
- **How do I call a smart contract?** `client.transactions.sign_evm_call` /
|
|
298
298
|
`sign_anchor_call` / `jetton_transfer`, then `transactions.execute`.
|
|
299
|
+
- **How do I control when a deposit wallet is swept?**
|
|
300
|
+
`client.sweeps.settings(...)` reads the policy in force for one wallet and
|
|
301
|
+
`client.sweeps.update_settings(...)` changes it - sweep on arrival
|
|
302
|
+
(`SweepPolicyMode.MOMENTUM`), sweep once the balance reaches an amount
|
|
303
|
+
(`SweepPolicyMode.THRESHOLD` plus `threshold_amount_usd`), or never on its own
|
|
304
|
+
(`SweepPolicyMode.OFF`, force still works). The read comes back in three
|
|
305
|
+
layers - what will happen, what this wallet overrides, and what it inherits
|
|
306
|
+
from the project - so a value of your own is distinguishable from an inherited
|
|
307
|
+
one:
|
|
308
|
+
|
|
309
|
+
```python
|
|
310
|
+
s = await client.sweeps.update_settings(
|
|
311
|
+
deposit_address,
|
|
312
|
+
type_work=SweepPolicyMode.THRESHOLD,
|
|
313
|
+
threshold_amount_usd="250",
|
|
314
|
+
)
|
|
315
|
+
# s.effective is the resolved policy; s.effective.source names the layer it came from.
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
Inheritance is per field: overriding the mode leaves the fee mode inherited.
|
|
319
|
+
To stop overriding a field, pass `CLEAR` - `None` already means "leave this
|
|
320
|
+
field alone", so it cannot also mean "reset it".
|
|
321
|
+
- **How do I know a sweep actually settled?** Check `status`.
|
|
322
|
+
`SweepStatus.BROADCASTED` means the transaction is out and not yet confirmed;
|
|
323
|
+
`SweepStatus.COMPLETED` means confirmed, with `sweep_confirmations` and
|
|
324
|
+
`completed_at` filled in. Earlier platform versions reported `completed` at
|
|
325
|
+
broadcast, so a sweep could read as settled while its transaction was still
|
|
326
|
+
unconfirmed.
|
|
327
|
+
- **How do I keep test payments off real chains?** Set `environment` on
|
|
328
|
+
`CreatePayInRequest` to `Environment.TESTNET` or `Environment.MAINNET`. It
|
|
329
|
+
constrains the asset the platform picks when you have not named a concrete
|
|
330
|
+
network - fiat mode and `ANY` - so an unconstrained pick cannot put a real
|
|
331
|
+
payment on a test chain. Omit it to use the project's default.
|
|
299
332
|
|
|
300
333
|
## Documentation
|
|
301
334
|
|
|
@@ -80,6 +80,7 @@ from .services.currencies import ConvertRequest, ConvertResponse, CurrenciesServ
|
|
|
80
80
|
from .services.payins import (
|
|
81
81
|
CoinOption,
|
|
82
82
|
CreatePayInRequest,
|
|
83
|
+
Environment,
|
|
83
84
|
PayIn,
|
|
84
85
|
PayInHistoryResponse,
|
|
85
86
|
PayInMode,
|
|
@@ -110,13 +111,20 @@ from .services.static_deposits import (
|
|
|
110
111
|
StaticDepositsService,
|
|
111
112
|
StaticDepositStatus,
|
|
112
113
|
)
|
|
114
|
+
from .sentinels import CLEAR, Clear
|
|
113
115
|
from .services.sweeps import (
|
|
114
116
|
ForceSweepResponse,
|
|
115
117
|
Sweep,
|
|
118
|
+
SweepFeeMode,
|
|
116
119
|
SweepHistoryQuery,
|
|
117
120
|
SweepHistoryResponse,
|
|
118
121
|
SweepMode,
|
|
122
|
+
SweepOverride,
|
|
123
|
+
SweepPolicy,
|
|
124
|
+
SweepPolicyMode,
|
|
125
|
+
SweepSettings,
|
|
119
126
|
SweepsService,
|
|
127
|
+
SweepStatus,
|
|
120
128
|
)
|
|
121
129
|
from .services.transactions import (
|
|
122
130
|
AnchorCallRequest,
|
|
@@ -171,6 +179,10 @@ from .webhook import (
|
|
|
171
179
|
|
|
172
180
|
__all__ = [
|
|
173
181
|
"__version__",
|
|
182
|
+
# Sentinels
|
|
183
|
+
"CLEAR",
|
|
184
|
+
"Clear",
|
|
185
|
+
"Environment",
|
|
174
186
|
# Client
|
|
175
187
|
"CryptoChiefClient",
|
|
176
188
|
"VERSION",
|
|
@@ -278,10 +290,16 @@ __all__ = [
|
|
|
278
290
|
"WalletType",
|
|
279
291
|
# Sweep types
|
|
280
292
|
"Sweep",
|
|
293
|
+
"SweepFeeMode",
|
|
281
294
|
"SweepHistoryQuery",
|
|
282
295
|
"SweepHistoryResponse",
|
|
283
296
|
"ForceSweepResponse",
|
|
284
297
|
"SweepMode",
|
|
298
|
+
"SweepOverride",
|
|
299
|
+
"SweepPolicy",
|
|
300
|
+
"SweepPolicyMode",
|
|
301
|
+
"SweepSettings",
|
|
302
|
+
"SweepStatus",
|
|
285
303
|
# Withdrawal types
|
|
286
304
|
"Withdrawal",
|
|
287
305
|
"WithdrawalHistoryResponse",
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""Sentinels for values that ``None`` cannot express.
|
|
2
|
+
|
|
3
|
+
Python has one "absent" value and some APIs need two. Where an argument
|
|
4
|
+
distinguishes "not supplied" from "supplied as nothing", ``None`` takes the
|
|
5
|
+
first meaning and a sentinel from this module takes the second.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Clear:
|
|
12
|
+
"""Stop overriding a field and go back to inheriting it.
|
|
13
|
+
|
|
14
|
+
Used with :meth:`cryptochief.SweepsService.update_settings`, where the API
|
|
15
|
+
expresses "inherit this again" by naming a field and sending no value for
|
|
16
|
+
it. ``None`` already means "leave this field alone", so it cannot also mean
|
|
17
|
+
"reset it".
|
|
18
|
+
|
|
19
|
+
Use the :data:`CLEAR` singleton rather than constructing this.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
_instance: "Clear | None" = None
|
|
23
|
+
|
|
24
|
+
def __new__(cls) -> "Clear":
|
|
25
|
+
if cls._instance is None:
|
|
26
|
+
cls._instance = super().__new__(cls)
|
|
27
|
+
return cls._instance
|
|
28
|
+
|
|
29
|
+
def __repr__(self) -> str:
|
|
30
|
+
return "CLEAR"
|
|
31
|
+
|
|
32
|
+
def __bool__(self) -> bool:
|
|
33
|
+
# Truthy: `if value:` on a CLEAR must not read as "nothing was passed".
|
|
34
|
+
return True
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
#: The singleton :class:`Clear`.
|
|
38
|
+
CLEAR = Clear()
|
|
@@ -38,12 +38,40 @@ def is_payin_terminal(status: str) -> bool:
|
|
|
38
38
|
return status in _PAYIN_TERMINAL
|
|
39
39
|
|
|
40
40
|
|
|
41
|
+
class Environment(str, Enum):
|
|
42
|
+
"""The two environments an order can belong to.
|
|
43
|
+
|
|
44
|
+
A project may be allowed one or both; asking for testnet on a project that
|
|
45
|
+
does not permit it is refused with ``TESTNET_NOT_ALLOWED`` rather than
|
|
46
|
+
quietly served on mainnet, and a value that is neither is
|
|
47
|
+
``ENVIRONMENT_INVALID`` rather than a silent fallback.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
MAINNET = "mainnet"
|
|
51
|
+
TESTNET = "testnet"
|
|
52
|
+
|
|
53
|
+
|
|
41
54
|
@dataclass(kw_only=True)
|
|
42
55
|
class CreatePayInRequest:
|
|
43
56
|
order_id: str
|
|
44
57
|
user_id: str
|
|
45
58
|
mode: str
|
|
46
59
|
to_address: Optional[str] = None
|
|
60
|
+
#: Pin the transit deposit wallet of THIS order to the given master wallet of
|
|
61
|
+
#: the project - the address the funds are swept to. The order's
|
|
62
|
+
#: asset/network chain family must match the master wallet's; a foreign or
|
|
63
|
+
#: mismatched address is rejected with 400. Omit for the project-default
|
|
64
|
+
#: behaviour.
|
|
65
|
+
master_wallet_address: Optional[str] = None
|
|
66
|
+
#: Constrain the asset the platform PICKS for this order to the real chains
|
|
67
|
+
#: or the test ones - ``Environment.MAINNET`` or ``Environment.TESTNET``.
|
|
68
|
+
#: Omit to use the project's own default.
|
|
69
|
+
#:
|
|
70
|
+
#: It changes nothing when ``asset`` names a concrete network - that is the
|
|
71
|
+
#: caller's choice. It matters in fiat mode and when the network is ``ANY``,
|
|
72
|
+
#: where the platform selects the asset and an unconstrained pick could put
|
|
73
|
+
#: a real payment on a test network.
|
|
74
|
+
environment: Optional[str] = None
|
|
47
75
|
lifetime_sec: Optional[int] = None
|
|
48
76
|
url_callback: Optional[str] = None
|
|
49
77
|
url_success: Optional[str] = None
|
|
@@ -105,6 +133,10 @@ class SelectAssetRequest:
|
|
|
105
133
|
uuid: str
|
|
106
134
|
coin: str
|
|
107
135
|
network: str
|
|
136
|
+
#: Pin the order's transit deposit wallet to the given project master
|
|
137
|
+
#: wallet; see :class:`CreatePayInRequest`. A value here overrides one
|
|
138
|
+
#: supplied at order create.
|
|
139
|
+
master_wallet_address: Optional[str] = None
|
|
108
140
|
|
|
109
141
|
|
|
110
142
|
class PayInsService(BaseService):
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
"""Treasury sweeps (transit -> master)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from enum import Enum
|
|
7
|
+
from typing import Any, List, Optional, Union
|
|
8
|
+
|
|
9
|
+
from .._models import from_dict
|
|
10
|
+
from ..sentinels import Clear
|
|
11
|
+
from ..pagination import HistoryMeta
|
|
12
|
+
from .base import BaseService
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class SweepMode(str, Enum):
|
|
16
|
+
AUTO = "auto"
|
|
17
|
+
FORCE = "force"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass(kw_only=True)
|
|
21
|
+
class SweepHistoryQuery:
|
|
22
|
+
mode: Optional[str] = None
|
|
23
|
+
page: Optional[int] = None
|
|
24
|
+
page_size: Optional[int] = None
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class SweepStatus(str, Enum):
|
|
28
|
+
"""A sweep is broadcast first and confirmed after.
|
|
29
|
+
|
|
30
|
+
``BROADCASTED`` means the transaction is out and not yet confirmed;
|
|
31
|
+
``COMPLETED`` means the chain confirmed it. The platform used to report
|
|
32
|
+
``completed`` at broadcast, so a sweep could read as settled while its
|
|
33
|
+
transaction was still unconfirmed or had been dropped.
|
|
34
|
+
|
|
35
|
+
``SKIPPED`` is a sweep the platform decided against - almost always a
|
|
36
|
+
balance below the wallet's threshold. A normal outcome, not a failure.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
PENDING = "pending"
|
|
40
|
+
WAITING_GAS = "waiting_gas"
|
|
41
|
+
BROADCASTED = "broadcasted"
|
|
42
|
+
COMPLETED = "completed"
|
|
43
|
+
FAILED = "failed"
|
|
44
|
+
SKIPPED = "skipped"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class SweepPolicyMode(str, Enum):
|
|
48
|
+
"""Auto-sweep modes.
|
|
49
|
+
|
|
50
|
+
``OFF`` is never swept on its own (:meth:`SweepsService.force` still works),
|
|
51
|
+
``MOMENTUM`` sweeps as soon as funds arrive, and ``THRESHOLD`` sweeps once
|
|
52
|
+
the balance reaches ``threshold_amount_usd``. A held balance is re-checked
|
|
53
|
+
periodically, so a wallet that crosses the threshold through price movement
|
|
54
|
+
alone is still swept.
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
OFF = "turned_off"
|
|
58
|
+
MOMENTUM = "momentum"
|
|
59
|
+
THRESHOLD = "threshold"
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class SweepFeeMode(str, Enum):
|
|
63
|
+
"""Who pays the gas for a sweep.
|
|
64
|
+
|
|
65
|
+
``CLIENT`` takes it from the swept wallet, ``SERVICE`` from the platform's
|
|
66
|
+
service wallet, and ``MIX`` funds the gas from the service wallet and
|
|
67
|
+
reclaims the cost from the sweep.
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
CLIENT = "client"
|
|
71
|
+
SERVICE = "service"
|
|
72
|
+
MIX = "mix"
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@dataclass(kw_only=True)
|
|
76
|
+
class Sweep:
|
|
77
|
+
task_id: str = ""
|
|
78
|
+
status: str = ""
|
|
79
|
+
sweep_tx_hash: Optional[str] = None
|
|
80
|
+
gas_pump_tx_hash: Optional[str] = None
|
|
81
|
+
wallet_address: Optional[str] = None
|
|
82
|
+
chain: Optional[str] = None
|
|
83
|
+
chain_family: Optional[str] = None
|
|
84
|
+
asset_symbol: Optional[str] = None
|
|
85
|
+
asset_type: Optional[str] = None
|
|
86
|
+
amount_human: Optional[str] = None
|
|
87
|
+
#: What triggered this sweep: momentum, threshold or force.
|
|
88
|
+
type_work: Optional[str] = None
|
|
89
|
+
|
|
90
|
+
#: Confirmations seen on the sweep transaction, and when it reached the
|
|
91
|
+
#: network's confirmation target. Read them with ``status``:
|
|
92
|
+
#: ``completed_at`` is absent while the sweep is still in flight.
|
|
93
|
+
sweep_confirmations: Optional[int] = None
|
|
94
|
+
completed_at: Optional[str] = None
|
|
95
|
+
|
|
96
|
+
#: Fees. ``total_fee_usd`` is the whole cost of the sweep; the gas-pump half
|
|
97
|
+
#: is the funding transfer that pays for it on chains needing one. The
|
|
98
|
+
#: ``real_*`` figures are what the chain actually charged, filled in once the
|
|
99
|
+
#: transaction settles; the others are the estimate made up front.
|
|
100
|
+
total_fee_usd: Optional[str] = None
|
|
101
|
+
gas_pump_source: Optional[str] = None
|
|
102
|
+
gas_pump_fee_human: Optional[str] = None
|
|
103
|
+
gas_pump_fee_usd: Optional[str] = None
|
|
104
|
+
sweep_fee_human: Optional[str] = None
|
|
105
|
+
sweep_fee_usd: Optional[str] = None
|
|
106
|
+
real_gas_pump_fee_human: Optional[str] = None
|
|
107
|
+
real_gas_pump_fee_usd: Optional[str] = None
|
|
108
|
+
real_sweep_fee_human: Optional[str] = None
|
|
109
|
+
real_sweep_fee_usd: Optional[str] = None
|
|
110
|
+
|
|
111
|
+
created_at: Optional[str] = None
|
|
112
|
+
|
|
113
|
+
#: Deprecated: never populated. The API reports fees under the names above;
|
|
114
|
+
#: these were guesses at a shape it does not send.
|
|
115
|
+
gas_fee_human: Optional[str] = None
|
|
116
|
+
gas_fee_fiat: Optional[str] = None
|
|
117
|
+
service_fee_fiat: Optional[str] = None
|
|
118
|
+
#: Deprecated: never populated - sweeps carry ``created_at`` and
|
|
119
|
+
#: ``completed_at``.
|
|
120
|
+
updated_at: Optional[str] = None
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
@dataclass(kw_only=True)
|
|
124
|
+
class SweepPolicy:
|
|
125
|
+
"""A resolved set of sweep rules."""
|
|
126
|
+
|
|
127
|
+
type_work: str = ""
|
|
128
|
+
#: Meaningful only when ``type_work`` is ``threshold``.
|
|
129
|
+
threshold_amount_usd: Optional[str] = None
|
|
130
|
+
fee_mode: str = ""
|
|
131
|
+
#: Which layer the mode came from: ``wallet_network``, ``wallet``,
|
|
132
|
+
#: ``project`` or ``default``. Present on the effective policy, where the
|
|
133
|
+
#: question arises.
|
|
134
|
+
source: Optional[str] = None
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
@dataclass(kw_only=True)
|
|
138
|
+
class SweepOverride:
|
|
139
|
+
"""What one wallet decides for itself.
|
|
140
|
+
|
|
141
|
+
A field of ``None`` is not overridden - it is inherited, which no ordinary
|
|
142
|
+
value can express.
|
|
143
|
+
"""
|
|
144
|
+
|
|
145
|
+
#: Empty covers the address on every network it exists on; set, it covers
|
|
146
|
+
#: that one network and takes precedence over the address-wide override.
|
|
147
|
+
network_code: Optional[str] = None
|
|
148
|
+
type_work: Optional[str] = None
|
|
149
|
+
threshold_amount_usd: Optional[str] = None
|
|
150
|
+
fee_mode: Optional[str] = None
|
|
151
|
+
#: Who wrote it: ``merchant`` or ``operator``.
|
|
152
|
+
source: Optional[str] = None
|
|
153
|
+
#: An operator pinned this policy. While it is set, a merchant write answers
|
|
154
|
+
#: ``SWEEP_SETTINGS_LOCKED`` and changes nothing.
|
|
155
|
+
locked: bool = False
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
@dataclass(kw_only=True)
|
|
159
|
+
class SweepSettings:
|
|
160
|
+
"""Three layers, on purpose.
|
|
161
|
+
|
|
162
|
+
``effective`` is what will actually happen, ``override`` is what this wallet
|
|
163
|
+
decides for itself (``None`` if it decides nothing), and ``project_default``
|
|
164
|
+
is what it falls back to. Only the three together answer "is this value mine
|
|
165
|
+
or inherited" - the difference between changing it here and changing it on
|
|
166
|
+
the project. Inheritance is per field: a wallet can override the mode and
|
|
167
|
+
keep inheriting the fee mode.
|
|
168
|
+
"""
|
|
169
|
+
|
|
170
|
+
wallet_address: Optional[str] = None
|
|
171
|
+
network_code: Optional[str] = None
|
|
172
|
+
effective: Optional[SweepPolicy] = None
|
|
173
|
+
override: Optional[SweepOverride] = None
|
|
174
|
+
project_default: Optional[SweepPolicy] = None
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
@dataclass(kw_only=True)
|
|
178
|
+
class SweepHistoryResponse:
|
|
179
|
+
items: Optional[List[Sweep]] = None
|
|
180
|
+
meta: Optional[HistoryMeta] = None
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
@dataclass(kw_only=True)
|
|
184
|
+
class ForceSweepResponse:
|
|
185
|
+
status: str = ""
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
class SweepsService(BaseService):
|
|
189
|
+
async def force(self, address: str, network: str) -> ForceSweepResponse:
|
|
190
|
+
"""Trigger an immediate transit->master sweep for one address.
|
|
191
|
+
|
|
192
|
+
The status acknowledges acceptance; the resulting :class:`Sweep` record
|
|
193
|
+
appears via :meth:`wallet_history` once the on-chain tx is built.
|
|
194
|
+
"""
|
|
195
|
+
return from_dict(
|
|
196
|
+
ForceSweepResponse,
|
|
197
|
+
await self._post("/v1/sweeps/force", {"address": address, "network_code": network}),
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
async def history(self, query: Optional[SweepHistoryQuery] = None) -> SweepHistoryResponse:
|
|
201
|
+
"""Recent sweeps across the whole project."""
|
|
202
|
+
return from_dict(
|
|
203
|
+
SweepHistoryResponse, await self._post("/v1/sweeps/history", query or SweepHistoryQuery())
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
async def wallet_history(
|
|
207
|
+
self, address: str, query: Optional[SweepHistoryQuery] = None
|
|
208
|
+
) -> SweepHistoryResponse:
|
|
209
|
+
"""Recent sweeps scoped to one wallet."""
|
|
210
|
+
body: dict[str, Any] = {"address": address}
|
|
211
|
+
if query is not None:
|
|
212
|
+
if query.mode is not None:
|
|
213
|
+
body["mode"] = query.mode
|
|
214
|
+
if query.page is not None:
|
|
215
|
+
body["page"] = query.page
|
|
216
|
+
if query.page_size is not None:
|
|
217
|
+
body["page_size"] = query.page_size
|
|
218
|
+
return from_dict(SweepHistoryResponse, await self._post("/v1/sweeps/wallet/history", body))
|
|
219
|
+
|
|
220
|
+
async def settings(
|
|
221
|
+
self, address: Optional[str] = None, network_code: Optional[str] = None
|
|
222
|
+
) -> SweepSettings:
|
|
223
|
+
"""The auto-sweep policy in force for one wallet.
|
|
224
|
+
|
|
225
|
+
Returns what will happen, what the wallet overrides, and what it
|
|
226
|
+
inherits. Omitting ``address`` asks for the project's own default rather
|
|
227
|
+
than any wallet's policy.
|
|
228
|
+
|
|
229
|
+
Scoped to the caller's own wallets: an address that is not the project's
|
|
230
|
+
answers ``WALLET_NOT_FOUND``.
|
|
231
|
+
"""
|
|
232
|
+
body: dict[str, Any] = {}
|
|
233
|
+
if address:
|
|
234
|
+
body["address"] = address
|
|
235
|
+
if network_code:
|
|
236
|
+
body["network_code"] = network_code
|
|
237
|
+
return from_dict(SweepSettings, await self._post("/v1/sweeps/settings", body))
|
|
238
|
+
|
|
239
|
+
async def update_settings(
|
|
240
|
+
self,
|
|
241
|
+
address: str,
|
|
242
|
+
*,
|
|
243
|
+
network_code: Optional[str] = None,
|
|
244
|
+
type_work: Union[str, Clear, None] = None,
|
|
245
|
+
threshold_amount_usd: Union[str, Clear, None] = None,
|
|
246
|
+
fee_mode: Union[str, Clear, None] = None,
|
|
247
|
+
) -> SweepSettings:
|
|
248
|
+
"""Write a wallet's auto-sweep policy.
|
|
249
|
+
|
|
250
|
+
Returns the settings as they stand afterwards, so the caller sees what
|
|
251
|
+
the write resolved to without asking again.
|
|
252
|
+
|
|
253
|
+
``None`` leaves a field alone. :data:`~cryptochief.CLEAR` stops
|
|
254
|
+
overriding it and goes back to inheriting - the only way to drop one
|
|
255
|
+
field while keeping the others. The API expresses that by naming the
|
|
256
|
+
field with no value, which ``None`` cannot say in Python because it
|
|
257
|
+
already means "not supplied".
|
|
258
|
+
|
|
259
|
+
Refusals are named: ``TYPE_WORK_INVALID``, ``FEE_MODE_INVALID``,
|
|
260
|
+
``THRESHOLD_INVALID``, ``THRESHOLD_MUST_BE_POSITIVE``,
|
|
261
|
+
``THRESHOLD_REQUIRED_FOR_THRESHOLD_MODE``, and
|
|
262
|
+
``SWEEP_SETTINGS_LOCKED`` when an operator has pinned the policy.
|
|
263
|
+
"""
|
|
264
|
+
body: dict[str, Any] = {"address": address}
|
|
265
|
+
if network_code:
|
|
266
|
+
body["network_code"] = network_code
|
|
267
|
+
|
|
268
|
+
fields: List[str] = []
|
|
269
|
+
for name, value in (
|
|
270
|
+
("type_work", type_work),
|
|
271
|
+
("threshold_amount_usd", threshold_amount_usd),
|
|
272
|
+
("fee_mode", fee_mode),
|
|
273
|
+
):
|
|
274
|
+
if value is None:
|
|
275
|
+
continue
|
|
276
|
+
fields.append(name)
|
|
277
|
+
if not isinstance(value, Clear):
|
|
278
|
+
body[name] = value.value if isinstance(value, Enum) else value
|
|
279
|
+
if fields:
|
|
280
|
+
body["fields"] = fields
|
|
281
|
+
|
|
282
|
+
return from_dict(SweepSettings, await self._post("/v1/sweeps/settings/update", body))
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
"""Treasury sweeps (transit -> master)."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
from dataclasses import dataclass
|
|
6
|
-
from enum import Enum
|
|
7
|
-
from typing import Any, List, Optional
|
|
8
|
-
|
|
9
|
-
from .._models import from_dict
|
|
10
|
-
from ..pagination import HistoryMeta
|
|
11
|
-
from .base import BaseService
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class SweepMode(str, Enum):
|
|
15
|
-
AUTO = "auto"
|
|
16
|
-
FORCE = "force"
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
@dataclass(kw_only=True)
|
|
20
|
-
class SweepHistoryQuery:
|
|
21
|
-
mode: Optional[str] = None
|
|
22
|
-
page: Optional[int] = None
|
|
23
|
-
page_size: Optional[int] = None
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
@dataclass(kw_only=True)
|
|
27
|
-
class Sweep:
|
|
28
|
-
task_id: str = ""
|
|
29
|
-
status: str = ""
|
|
30
|
-
sweep_tx_hash: Optional[str] = None
|
|
31
|
-
wallet_address: Optional[str] = None
|
|
32
|
-
chain: Optional[str] = None
|
|
33
|
-
chain_family: Optional[str] = None
|
|
34
|
-
asset_symbol: Optional[str] = None
|
|
35
|
-
asset_type: Optional[str] = None
|
|
36
|
-
amount_human: Optional[str] = None
|
|
37
|
-
gas_fee_human: Optional[str] = None
|
|
38
|
-
gas_fee_fiat: Optional[str] = None
|
|
39
|
-
service_fee_fiat: Optional[str] = None
|
|
40
|
-
created_at: Optional[str] = None
|
|
41
|
-
updated_at: Optional[str] = None
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
@dataclass(kw_only=True)
|
|
45
|
-
class SweepHistoryResponse:
|
|
46
|
-
items: Optional[List[Sweep]] = None
|
|
47
|
-
meta: Optional[HistoryMeta] = None
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
@dataclass(kw_only=True)
|
|
51
|
-
class ForceSweepResponse:
|
|
52
|
-
status: str = ""
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
class SweepsService(BaseService):
|
|
56
|
-
async def force(self, address: str, network: str) -> ForceSweepResponse:
|
|
57
|
-
"""Trigger an immediate transit->master sweep for one address.
|
|
58
|
-
|
|
59
|
-
The status acknowledges acceptance; the resulting :class:`Sweep` record
|
|
60
|
-
appears via :meth:`wallet_history` once the on-chain tx is built.
|
|
61
|
-
"""
|
|
62
|
-
return from_dict(
|
|
63
|
-
ForceSweepResponse,
|
|
64
|
-
await self._post("/v1/sweeps/force", {"address": address, "network_code": network}),
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
async def history(self, query: Optional[SweepHistoryQuery] = None) -> SweepHistoryResponse:
|
|
68
|
-
"""Recent sweeps across the whole project."""
|
|
69
|
-
return from_dict(
|
|
70
|
-
SweepHistoryResponse, await self._post("/v1/sweeps/history", query or SweepHistoryQuery())
|
|
71
|
-
)
|
|
72
|
-
|
|
73
|
-
async def wallet_history(
|
|
74
|
-
self, address: str, query: Optional[SweepHistoryQuery] = None
|
|
75
|
-
) -> SweepHistoryResponse:
|
|
76
|
-
"""Recent sweeps scoped to one wallet."""
|
|
77
|
-
body: dict[str, Any] = {"address": address}
|
|
78
|
-
if query is not None:
|
|
79
|
-
if query.mode is not None:
|
|
80
|
-
body["mode"] = query.mode
|
|
81
|
-
if query.page is not None:
|
|
82
|
-
body["page"] = query.page
|
|
83
|
-
if query.page_size is not None:
|
|
84
|
-
body["page_size"] = query.page_size
|
|
85
|
-
return from_dict(SweepHistoryResponse, await self._post("/v1/sweeps/wallet/history", body))
|
{cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/.gitignore
RENAMED
|
File without changes
|
{cryptochief_crypto_processing_python-0.2.0 → cryptochief_crypto_processing_python-0.4.0}/LICENSE
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|