-
Notifications
You must be signed in to change notification settings - Fork 81
/
response.py
120 lines (96 loc) · 3.53 KB
/
response.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
"""
The base class for all network response types.
Represents fields common to all response types.
"""
from __future__ import annotations
import warnings
from dataclasses import dataclass
from enum import Enum
from typing import Any, Dict, Optional, Union
from xrpl.models.base_model import BaseModel
from xrpl.models.required import REQUIRED
from xrpl.models.transactions import PaymentFlag
from xrpl.models.transactions.types import TransactionType
from xrpl.models.utils import require_kwargs_on_init
class ResponseStatus(str, Enum):
"""Represents the different status possibilities."""
SUCCESS = "success"
ERROR = "error"
class ResponseType(str, Enum):
"""Represents the different response types a Response can have."""
RESPONSE = "response"
LEDGER_CLOSED = "ledgerClosed"
TRANSACTION = "transaction"
@require_kwargs_on_init
@dataclass(frozen=True)
class Response(BaseModel):
"""
The base class for all network response types.
Represents fields common to all response types.
"""
status: ResponseStatus = REQUIRED # type: ignore
"""
This field is required.
:meta hide-value:
"""
result: Dict[str, Any] = REQUIRED # type: ignore
"""
This field is required.
:meta hide-value:
"""
id: Optional[Union[int, str]] = None
type: Optional[ResponseType] = None
def __post_init__(self: Response) -> None:
"""Called by dataclasses immediately after __init__."""
super().__post_init__()
if self.contains_partial_payment():
warnings.warn(
"""This response contains a partial payment. Please confirm
the delivered amount is correct""",
stacklevel=2,
)
def is_successful(self: Response) -> bool:
"""
Returns whether the request was successfully received and understood by the
server.
Returns:
Whether the request was successfully received and understood by the server.
"""
return self.status == ResponseStatus.SUCCESS
def contains_partial_payment(self: Response) -> bool:
"""
Returns whether the request contains at least one transactions with
the partial payment flag set.
Returns:
True if at least one transaction in this Response has the partial
payment flag set. False otherwise.
"""
return self._do_contains_partial_payment(self.result)
def _do_contains_partial_payment(self: Response, val: Any) -> bool:
flagged = []
if isinstance(val, dict):
formatted = {key.strip().lower(): value for key, value in val.items()}
if (
"transactiontype" in formatted
and formatted["transactiontype"] == TransactionType.PAYMENT
):
flagged = [
True
for key, value in val.items()
if self._is_partial_payment(key, value)
]
if isinstance(val, list):
flagged = [
True for sub_val in val if self._do_contains_partial_payment(sub_val)
]
return len(flagged) > 0
def _is_partial_payment(self: Response, key: str, val: Any) -> bool:
if isinstance(val, dict):
return self._do_contains_partial_payment(val)
try:
int_val = int(val)
except (TypeError, ValueError):
return False
return key.strip().lower() == "flags" and (
int_val & PaymentFlag.TF_PARTIAL_PAYMENT != 0
)