hive-nectar 0.2.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. hive_nectar-0.2.9.dist-info/METADATA +194 -0
  2. hive_nectar-0.2.9.dist-info/RECORD +87 -0
  3. hive_nectar-0.2.9.dist-info/WHEEL +4 -0
  4. hive_nectar-0.2.9.dist-info/entry_points.txt +2 -0
  5. hive_nectar-0.2.9.dist-info/licenses/LICENSE.txt +23 -0
  6. nectar/__init__.py +37 -0
  7. nectar/account.py +5076 -0
  8. nectar/amount.py +553 -0
  9. nectar/asciichart.py +303 -0
  10. nectar/asset.py +122 -0
  11. nectar/block.py +574 -0
  12. nectar/blockchain.py +1242 -0
  13. nectar/blockchaininstance.py +2590 -0
  14. nectar/blockchainobject.py +263 -0
  15. nectar/cli.py +5937 -0
  16. nectar/comment.py +1552 -0
  17. nectar/community.py +854 -0
  18. nectar/constants.py +95 -0
  19. nectar/discussions.py +1437 -0
  20. nectar/exceptions.py +152 -0
  21. nectar/haf.py +381 -0
  22. nectar/hive.py +630 -0
  23. nectar/imageuploader.py +114 -0
  24. nectar/instance.py +113 -0
  25. nectar/market.py +876 -0
  26. nectar/memo.py +542 -0
  27. nectar/message.py +379 -0
  28. nectar/nodelist.py +309 -0
  29. nectar/price.py +603 -0
  30. nectar/profile.py +74 -0
  31. nectar/py.typed +0 -0
  32. nectar/rc.py +333 -0
  33. nectar/snapshot.py +1024 -0
  34. nectar/storage.py +62 -0
  35. nectar/transactionbuilder.py +659 -0
  36. nectar/utils.py +630 -0
  37. nectar/version.py +3 -0
  38. nectar/vote.py +722 -0
  39. nectar/wallet.py +472 -0
  40. nectar/witness.py +728 -0
  41. nectarapi/__init__.py +12 -0
  42. nectarapi/exceptions.py +126 -0
  43. nectarapi/graphenerpc.py +596 -0
  44. nectarapi/node.py +194 -0
  45. nectarapi/noderpc.py +79 -0
  46. nectarapi/openapi.py +107 -0
  47. nectarapi/py.typed +0 -0
  48. nectarapi/rpcutils.py +98 -0
  49. nectarapi/version.py +3 -0
  50. nectarbase/__init__.py +15 -0
  51. nectarbase/ledgertransactions.py +106 -0
  52. nectarbase/memo.py +242 -0
  53. nectarbase/objects.py +521 -0
  54. nectarbase/objecttypes.py +21 -0
  55. nectarbase/operationids.py +102 -0
  56. nectarbase/operations.py +1357 -0
  57. nectarbase/py.typed +0 -0
  58. nectarbase/signedtransactions.py +89 -0
  59. nectarbase/transactions.py +11 -0
  60. nectarbase/version.py +3 -0
  61. nectargraphenebase/__init__.py +27 -0
  62. nectargraphenebase/account.py +1121 -0
  63. nectargraphenebase/aes.py +49 -0
  64. nectargraphenebase/base58.py +197 -0
  65. nectargraphenebase/bip32.py +575 -0
  66. nectargraphenebase/bip38.py +110 -0
  67. nectargraphenebase/chains.py +15 -0
  68. nectargraphenebase/dictionary.py +2 -0
  69. nectargraphenebase/ecdsasig.py +309 -0
  70. nectargraphenebase/objects.py +130 -0
  71. nectargraphenebase/objecttypes.py +8 -0
  72. nectargraphenebase/operationids.py +5 -0
  73. nectargraphenebase/operations.py +25 -0
  74. nectargraphenebase/prefix.py +13 -0
  75. nectargraphenebase/py.typed +0 -0
  76. nectargraphenebase/signedtransactions.py +221 -0
  77. nectargraphenebase/types.py +557 -0
  78. nectargraphenebase/unsignedtransactions.py +288 -0
  79. nectargraphenebase/version.py +3 -0
  80. nectarstorage/__init__.py +57 -0
  81. nectarstorage/base.py +317 -0
  82. nectarstorage/exceptions.py +15 -0
  83. nectarstorage/interfaces.py +244 -0
  84. nectarstorage/masterpassword.py +237 -0
  85. nectarstorage/py.typed +0 -0
  86. nectarstorage/ram.py +27 -0
  87. nectarstorage/sqlite.py +343 -0
@@ -0,0 +1,263 @@
1
+ import json
2
+ import threading
3
+ from datetime import datetime, timedelta, timezone
4
+ from typing import Any, Dict, Optional, Union, cast
5
+
6
+ from nectar.instance import shared_blockchain_instance
7
+
8
+
9
+ class ObjectCache(dict):
10
+ def __init__(
11
+ self,
12
+ initial_data: Optional[Dict[Any, Any]] = None,
13
+ default_expiration: int = 10,
14
+ auto_clean: bool = True,
15
+ ) -> None:
16
+ super().__init__(initial_data or {})
17
+ self.set_expiration(default_expiration)
18
+ self.auto_clean = auto_clean
19
+ self.lock = threading.RLock()
20
+
21
+ def __setitem__(self, key: Any, value: Any) -> None:
22
+ data = {
23
+ "expires": datetime.now(timezone.utc) + timedelta(seconds=self.default_expiration),
24
+ "data": value,
25
+ }
26
+ with self.lock:
27
+ if key in self:
28
+ del self[key]
29
+ dict.__setitem__(self, key, data)
30
+ if self.auto_clean:
31
+ self.clear_expired_items()
32
+
33
+ def __getitem__(self, key: Any) -> Any:
34
+ with self.lock:
35
+ if key in self:
36
+ value = dict.__getitem__(self, key)
37
+ if value is not None:
38
+ return value["data"]
39
+
40
+ def get(self, key: Any, default: Any = None) -> Any:
41
+ with self.lock:
42
+ if key in self:
43
+ if self[key] is not None:
44
+ return self[key]
45
+ else:
46
+ return default
47
+ else:
48
+ return default
49
+
50
+ def clear_expired_items(self) -> None:
51
+ with self.lock:
52
+ del_list = []
53
+ utc_now = datetime.now(timezone.utc)
54
+ for key in self:
55
+ value = dict.__getitem__(self, key)
56
+ if value is None:
57
+ del_list.append(key)
58
+ continue
59
+ if utc_now >= value["expires"]:
60
+ del_list.append(key)
61
+ for key in del_list:
62
+ del self[key]
63
+
64
+ def __contains__(self, key: Any) -> bool:
65
+ with self.lock:
66
+ if dict.__contains__(self, key):
67
+ value = dict.__getitem__(self, key)
68
+ if value is None:
69
+ return False
70
+ if datetime.now(timezone.utc) < value["expires"]:
71
+ return True
72
+ else:
73
+ value["data"] = None
74
+ return False
75
+
76
+ def __str__(self) -> str:
77
+ if self.auto_clean:
78
+ self.clear_expired_items()
79
+ n = 0
80
+ with self.lock:
81
+ n = len(list(self.keys()))
82
+ return f"ObjectCache(n={n}, default_expiration={self.default_expiration})"
83
+
84
+ def set_expiration(self, expiration: int) -> None:
85
+ """Set new default expiration time in seconds (default: 10s)"""
86
+ self.default_expiration = expiration
87
+
88
+
89
+ class BlockchainObject(dict):
90
+ space_id = 1
91
+ type_id = None
92
+ type_ids = []
93
+
94
+ _cache = ObjectCache()
95
+
96
+ def __init__(
97
+ self,
98
+ data: Union[Dict[str, Any], int, str, Any],
99
+ klass: Optional[type] = None,
100
+ space_id: int = 1,
101
+ object_id: Optional[Any] = None,
102
+ lazy: bool = False,
103
+ use_cache: bool = True,
104
+ id_item: Optional[str] = None,
105
+ blockchain_instance: Optional[Any] = None,
106
+ *args,
107
+ **kwargs,
108
+ ) -> None:
109
+ """
110
+ Initialize a BlockchainObject, setting its identifier and optionally loading or caching its data.
111
+
112
+ This constructor accepts a variety of `data` forms:
113
+ - dict or instance of `klass`: uses the mapping directly as the object's data.
114
+ - int: treated as a block number (identifier) and stored under `id_item`.
115
+ - str: treated as an object identifier string and stored under `id_item`.
116
+ - other scalar identifiers: validated with test_valid_objectid and may trigger a lookup.
117
+
118
+ Behavioral notes:
119
+ - If `lazy` is False the constructor may call refresh() to populate the object from the blockchain.
120
+ - If `use_cache` is True and not lazy, the object will be stored in the class-level cache and marked as cached.
121
+ - Raises ValueError if `data` is a list, set, or tuple (these collection types are not supported).
122
+
123
+ Parameters:
124
+ data: dict, instance, int, str, or identifier
125
+ The source for the object's data or its identifier.
126
+ klass (optional): type
127
+ If provided and `data` is an instance of this type, the instance's mapping is used directly.
128
+ space_id (int, optional):
129
+ Numeric namespace for the object type (defaults to 1).
130
+ object_id (optional):
131
+ Explicit object id value — kept for callers that supply it but not otherwise interpreted by the constructor.
132
+ lazy (bool, optional):
133
+ If True, defer loading object contents (do not call refresh()).
134
+ use_cache (bool, optional):
135
+ If True and not lazy, store the constructed object in the class cache.
136
+ id_item (str, optional):
137
+ Key name used to read/write the object's identifier in the underlying mapping (defaults to "id").
138
+
139
+ Raises:
140
+ ValueError: if `data` is a list, set, or tuple.
141
+ """
142
+ self.blockchain = blockchain_instance or shared_blockchain_instance()
143
+ self.cached = False
144
+ self.identifier = None
145
+
146
+ # We don't read lists, sets, or tuples
147
+ if isinstance(data, (list, set, tuple)):
148
+ raise ValueError("Cannot interpret lists! Please load elements individually!")
149
+
150
+ if id_item and isinstance(id_item, str):
151
+ self.id_item = id_item
152
+ else:
153
+ self.id_item = "id"
154
+ if klass and isinstance(data, klass) and hasattr(data, "get"):
155
+ mapping_data = cast(Dict[str, Any], data)
156
+ self.identifier = mapping_data.get(self.id_item)
157
+ super().__init__(mapping_data)
158
+ elif isinstance(data, dict):
159
+ mapping_data = cast(Dict[str, Any], data)
160
+ self.identifier = mapping_data.get(self.id_item)
161
+ super().__init__(mapping_data)
162
+ elif isinstance(data, int):
163
+ # This is only for block number basically
164
+ self.identifier = data
165
+ if not lazy and not self.cached:
166
+ self.refresh()
167
+ # make sure to store the blocknumber for caching
168
+ self[self.id_item] = data
169
+ # Set identifier again as it is overwritten in super() in refresh()
170
+ self.identifier = data
171
+ elif isinstance(data, str):
172
+ self.identifier = data
173
+ if not lazy and not self.cached:
174
+ self.refresh()
175
+ self[self.id_item] = str(data)
176
+ self.identifier = data
177
+ else:
178
+ self.identifier = data
179
+ if self.test_valid_objectid(self.identifier):
180
+ # Here we assume we deal with an id
181
+ self.testid(self.identifier)
182
+ if self.iscached(data):
183
+ super().__init__(self.getcache(data))
184
+ elif not lazy and not self.cached:
185
+ self.refresh()
186
+
187
+ if use_cache and not lazy:
188
+ self.cache()
189
+ self.cached = True
190
+
191
+ def refresh(self) -> None:
192
+ """Refresh the object's data from the API.
193
+
194
+ This method should be overridden by subclasses to implement
195
+ specific refresh logic. The base implementation does nothing.
196
+ """
197
+ pass
198
+
199
+ @staticmethod
200
+ def clear_cache() -> None:
201
+ BlockchainObject._cache = ObjectCache()
202
+
203
+ def test_valid_objectid(self, i: Any) -> bool:
204
+ if isinstance(i, str):
205
+ return True
206
+ elif isinstance(i, int):
207
+ return True
208
+ else:
209
+ return False
210
+
211
+ def testid(self, id: Any) -> None:
212
+ if not self.type_id:
213
+ return
214
+
215
+ if not self.type_ids:
216
+ self.type_ids = [self.type_id]
217
+
218
+ def cache(self) -> None:
219
+ # store in cache
220
+ if dict.__contains__(self, self.id_item):
221
+ BlockchainObject._cache[self.get(self.id_item)] = self
222
+
223
+ def clear_cache_from_expired_items(self) -> None:
224
+ BlockchainObject._cache.clear_expired_items()
225
+
226
+ def set_cache_expiration(self, expiration: int) -> None:
227
+ BlockchainObject._cache.default_expiration = expiration
228
+
229
+ def set_cache_auto_clean(self, auto_clean: bool) -> None:
230
+ BlockchainObject._cache.auto_clean = auto_clean
231
+
232
+ def get_cache_expiration(self) -> int:
233
+ return BlockchainObject._cache.default_expiration
234
+
235
+ def get_cache_auto_clean(self) -> bool:
236
+ return BlockchainObject._cache.auto_clean
237
+
238
+ def iscached(self, id: Any) -> bool:
239
+ return id in BlockchainObject._cache
240
+
241
+ def getcache(self, id: Any) -> Any:
242
+ return BlockchainObject._cache.get(id, None)
243
+
244
+ def __getitem__(self, key: Any) -> Any:
245
+ if not self.cached:
246
+ self.refresh()
247
+ return super().__getitem__(key)
248
+
249
+ def items(self):
250
+ if not self.cached:
251
+ self.refresh()
252
+ return super().items()
253
+
254
+ def __contains__(self, key: Any) -> bool:
255
+ if not self.cached:
256
+ self.refresh()
257
+ return super().__contains__(key)
258
+
259
+ def __repr__(self) -> str:
260
+ return "<{} {}>".format(self.__class__.__name__, str(self.identifier))
261
+
262
+ def json(self) -> Dict[str, Any]:
263
+ return json.loads(str(json.dumps(self)))