hive-nectar 0.0.2__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.
Potentially problematic release.
This version of hive-nectar might be problematic. Click here for more details.
- hive_nectar-0.0.2.dist-info/METADATA +182 -0
- hive_nectar-0.0.2.dist-info/RECORD +86 -0
- hive_nectar-0.0.2.dist-info/WHEEL +4 -0
- hive_nectar-0.0.2.dist-info/entry_points.txt +2 -0
- hive_nectar-0.0.2.dist-info/licenses/LICENSE.txt +23 -0
- nectar/__init__.py +32 -0
- nectar/account.py +4371 -0
- nectar/amount.py +475 -0
- nectar/asciichart.py +270 -0
- nectar/asset.py +82 -0
- nectar/block.py +446 -0
- nectar/blockchain.py +1178 -0
- nectar/blockchaininstance.py +2284 -0
- nectar/blockchainobject.py +221 -0
- nectar/blurt.py +563 -0
- nectar/cli.py +6285 -0
- nectar/comment.py +1217 -0
- nectar/community.py +513 -0
- nectar/constants.py +111 -0
- nectar/conveyor.py +309 -0
- nectar/discussions.py +1709 -0
- nectar/exceptions.py +149 -0
- nectar/hive.py +546 -0
- nectar/hivesigner.py +420 -0
- nectar/imageuploader.py +72 -0
- nectar/instance.py +129 -0
- nectar/market.py +1013 -0
- nectar/memo.py +449 -0
- nectar/message.py +357 -0
- nectar/nodelist.py +444 -0
- nectar/price.py +557 -0
- nectar/profile.py +65 -0
- nectar/rc.py +308 -0
- nectar/snapshot.py +726 -0
- nectar/steem.py +582 -0
- nectar/storage.py +53 -0
- nectar/transactionbuilder.py +622 -0
- nectar/utils.py +545 -0
- nectar/version.py +2 -0
- nectar/vote.py +557 -0
- nectar/wallet.py +472 -0
- nectar/witness.py +617 -0
- nectarapi/__init__.py +11 -0
- nectarapi/exceptions.py +123 -0
- nectarapi/graphenerpc.py +589 -0
- nectarapi/node.py +178 -0
- nectarapi/noderpc.py +229 -0
- nectarapi/rpcutils.py +97 -0
- nectarapi/version.py +2 -0
- nectarbase/__init__.py +14 -0
- nectarbase/ledgertransactions.py +75 -0
- nectarbase/memo.py +243 -0
- nectarbase/objects.py +429 -0
- nectarbase/objecttypes.py +22 -0
- nectarbase/operationids.py +102 -0
- nectarbase/operations.py +1297 -0
- nectarbase/signedtransactions.py +48 -0
- nectarbase/transactions.py +11 -0
- nectarbase/version.py +2 -0
- nectargrapheneapi/__init__.py +6 -0
- nectargraphenebase/__init__.py +27 -0
- nectargraphenebase/account.py +846 -0
- nectargraphenebase/aes.py +52 -0
- nectargraphenebase/base58.py +192 -0
- nectargraphenebase/bip32.py +494 -0
- nectargraphenebase/bip38.py +134 -0
- nectargraphenebase/chains.py +149 -0
- nectargraphenebase/dictionary.py +3 -0
- nectargraphenebase/ecdsasig.py +326 -0
- nectargraphenebase/objects.py +123 -0
- nectargraphenebase/objecttypes.py +6 -0
- nectargraphenebase/operationids.py +3 -0
- nectargraphenebase/operations.py +23 -0
- nectargraphenebase/prefix.py +11 -0
- nectargraphenebase/py23.py +38 -0
- nectargraphenebase/signedtransactions.py +201 -0
- nectargraphenebase/types.py +419 -0
- nectargraphenebase/unsignedtransactions.py +283 -0
- nectargraphenebase/version.py +2 -0
- nectarstorage/__init__.py +38 -0
- nectarstorage/base.py +306 -0
- nectarstorage/exceptions.py +16 -0
- nectarstorage/interfaces.py +237 -0
- nectarstorage/masterpassword.py +239 -0
- nectarstorage/ram.py +30 -0
- nectarstorage/sqlite.py +334 -0
nectar/block.py
ADDED
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
import json
|
|
3
|
+
from datetime import date, datetime
|
|
4
|
+
|
|
5
|
+
from nectar.instance import shared_blockchain_instance
|
|
6
|
+
from nectarapi.exceptions import ApiNotSupported
|
|
7
|
+
from nectargraphenebase.py23 import string_types
|
|
8
|
+
|
|
9
|
+
from .blockchainobject import BlockchainObject
|
|
10
|
+
from .exceptions import BlockDoesNotExistsException
|
|
11
|
+
from .utils import formatTimeString
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Block(BlockchainObject):
|
|
15
|
+
"""Read a single block from the chain
|
|
16
|
+
|
|
17
|
+
:param int block: block number
|
|
18
|
+
:param Steem steem_instance: Steem
|
|
19
|
+
instance
|
|
20
|
+
:param bool lazy: Use lazy loading
|
|
21
|
+
:param bool only_ops: Includes only operations, when set to True (default: False)
|
|
22
|
+
:param bool only_virtual_ops: Includes only virtual operations (default: False)
|
|
23
|
+
|
|
24
|
+
Instances of this class are dictionaries that come with additional
|
|
25
|
+
methods (see below) that allow dealing with a block and its
|
|
26
|
+
corresponding functions.
|
|
27
|
+
|
|
28
|
+
When only_virtual_ops is set to True, only_ops is always set to True.
|
|
29
|
+
|
|
30
|
+
In addition to the block data, the block number is stored as self["id"] or self.identifier.
|
|
31
|
+
|
|
32
|
+
.. code-block:: python
|
|
33
|
+
|
|
34
|
+
>>> from nectar.block import Block
|
|
35
|
+
>>> block = Block(1)
|
|
36
|
+
>>> print(block)
|
|
37
|
+
<Block 1>
|
|
38
|
+
|
|
39
|
+
.. note:: This class comes with its own caching function to reduce the
|
|
40
|
+
load on the API server. Instances of this class can be
|
|
41
|
+
refreshed with ``Account.refresh()``.
|
|
42
|
+
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
def __init__(
|
|
46
|
+
self,
|
|
47
|
+
block,
|
|
48
|
+
only_ops=False,
|
|
49
|
+
only_virtual_ops=False,
|
|
50
|
+
full=True,
|
|
51
|
+
lazy=False,
|
|
52
|
+
blockchain_instance=None,
|
|
53
|
+
**kwargs,
|
|
54
|
+
):
|
|
55
|
+
"""Initilize a block
|
|
56
|
+
|
|
57
|
+
:param int block: block number
|
|
58
|
+
:param Steem steem_instance: Steem
|
|
59
|
+
instance
|
|
60
|
+
:param bool lazy: Use lazy loading
|
|
61
|
+
:param bool only_ops: Includes only operations, when set to True (default: False)
|
|
62
|
+
:param bool only_virtual_ops: Includes only virtual operations (default: False)
|
|
63
|
+
|
|
64
|
+
"""
|
|
65
|
+
self.full = full
|
|
66
|
+
self.lazy = lazy
|
|
67
|
+
self.only_ops = only_ops
|
|
68
|
+
self.only_virtual_ops = only_virtual_ops
|
|
69
|
+
if isinstance(block, float):
|
|
70
|
+
block = int(block)
|
|
71
|
+
elif isinstance(block, dict):
|
|
72
|
+
block = self._parse_json_data(block)
|
|
73
|
+
super(Block, self).__init__(
|
|
74
|
+
block, lazy=lazy, full=full, blockchain_instance=blockchain_instance, **kwargs
|
|
75
|
+
)
|
|
76
|
+
if self.identifier is None:
|
|
77
|
+
self.identifier = self.block_num
|
|
78
|
+
|
|
79
|
+
def _parse_json_data(self, block):
|
|
80
|
+
parse_times = [
|
|
81
|
+
"timestamp",
|
|
82
|
+
]
|
|
83
|
+
for p in parse_times:
|
|
84
|
+
if p in block and isinstance(block.get(p), string_types):
|
|
85
|
+
block[p] = formatTimeString(block.get(p, "1970-01-01T00:00:00"))
|
|
86
|
+
if "transactions" in block:
|
|
87
|
+
for i in range(len(block["transactions"])):
|
|
88
|
+
if "expiration" in block["transactions"][i] and isinstance(
|
|
89
|
+
block["transactions"][i]["expiration"], string_types
|
|
90
|
+
):
|
|
91
|
+
block["transactions"][i]["expiration"] = formatTimeString(
|
|
92
|
+
block["transactions"][i]["expiration"]
|
|
93
|
+
)
|
|
94
|
+
elif "operations" in block:
|
|
95
|
+
for i in range(len(block["operations"])):
|
|
96
|
+
if "timestamp" in block["operations"][i] and isinstance(
|
|
97
|
+
block["operations"][i]["timestamp"], string_types
|
|
98
|
+
):
|
|
99
|
+
block["operations"][i]["timestamp"] = formatTimeString(
|
|
100
|
+
block["operations"][i]["timestamp"]
|
|
101
|
+
)
|
|
102
|
+
return block
|
|
103
|
+
|
|
104
|
+
def json(self):
|
|
105
|
+
output = self.copy()
|
|
106
|
+
parse_times = [
|
|
107
|
+
"timestamp",
|
|
108
|
+
]
|
|
109
|
+
for p in parse_times:
|
|
110
|
+
if p in output:
|
|
111
|
+
p_date = output.get(p, datetime(1970, 1, 1, 0, 0))
|
|
112
|
+
if isinstance(p_date, (datetime, date)):
|
|
113
|
+
output[p] = formatTimeString(p_date)
|
|
114
|
+
else:
|
|
115
|
+
output[p] = p_date
|
|
116
|
+
|
|
117
|
+
if "transactions" in output:
|
|
118
|
+
for i in range(len(output["transactions"])):
|
|
119
|
+
if "expiration" in output["transactions"][i] and isinstance(
|
|
120
|
+
output["transactions"][i]["expiration"], (datetime, date)
|
|
121
|
+
):
|
|
122
|
+
output["transactions"][i]["expiration"] = formatTimeString(
|
|
123
|
+
output["transactions"][i]["expiration"]
|
|
124
|
+
)
|
|
125
|
+
elif "operations" in output:
|
|
126
|
+
for i in range(len(output["operations"])):
|
|
127
|
+
if "timestamp" in output["operations"][i] and isinstance(
|
|
128
|
+
output["operations"][i]["timestamp"], (datetime, date)
|
|
129
|
+
):
|
|
130
|
+
output["operations"][i]["timestamp"] = formatTimeString(
|
|
131
|
+
output["operations"][i]["timestamp"]
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
ret = json.loads(str(json.dumps(output)))
|
|
135
|
+
output = self._parse_json_data(output)
|
|
136
|
+
return ret
|
|
137
|
+
|
|
138
|
+
def refresh(self):
|
|
139
|
+
"""Even though blocks never change, you freshly obtain its contents
|
|
140
|
+
from an API with this method
|
|
141
|
+
"""
|
|
142
|
+
if self.identifier is None:
|
|
143
|
+
return
|
|
144
|
+
if not self.blockchain.is_connected():
|
|
145
|
+
return
|
|
146
|
+
self.blockchain.rpc.set_next_node_on_empty_reply(False)
|
|
147
|
+
if self.only_ops or self.only_virtual_ops:
|
|
148
|
+
if self.blockchain.rpc.get_use_appbase():
|
|
149
|
+
try:
|
|
150
|
+
ops_ops = self.blockchain.rpc.get_ops_in_block(
|
|
151
|
+
{"block_num": self.identifier, "only_virtual": self.only_virtual_ops},
|
|
152
|
+
api="account_history",
|
|
153
|
+
)
|
|
154
|
+
if ops_ops is None:
|
|
155
|
+
ops = None
|
|
156
|
+
else:
|
|
157
|
+
ops = ops_ops["ops"]
|
|
158
|
+
except ApiNotSupported:
|
|
159
|
+
ops = self.blockchain.rpc.get_ops_in_block(
|
|
160
|
+
self.identifier, self.only_virtual_ops, api="condenser"
|
|
161
|
+
)
|
|
162
|
+
else:
|
|
163
|
+
ops = self.blockchain.rpc.get_ops_in_block(self.identifier, self.only_virtual_ops)
|
|
164
|
+
if bool(ops):
|
|
165
|
+
block = {
|
|
166
|
+
"block": ops[0]["block"],
|
|
167
|
+
"timestamp": ops[0]["timestamp"],
|
|
168
|
+
"operations": ops,
|
|
169
|
+
}
|
|
170
|
+
else:
|
|
171
|
+
block = {
|
|
172
|
+
"block": self.identifier,
|
|
173
|
+
"timestamp": "1970-01-01T00:00:00",
|
|
174
|
+
"operations": [],
|
|
175
|
+
}
|
|
176
|
+
else:
|
|
177
|
+
if self.blockchain.rpc.get_use_appbase():
|
|
178
|
+
try:
|
|
179
|
+
block = self.blockchain.rpc.get_block(
|
|
180
|
+
{"block_num": self.identifier}, api="block"
|
|
181
|
+
)
|
|
182
|
+
if block and "block" in block:
|
|
183
|
+
block = block["block"]
|
|
184
|
+
except ApiNotSupported:
|
|
185
|
+
block = self.blockchain.rpc.get_block(self.identifier, api="condenser")
|
|
186
|
+
else:
|
|
187
|
+
block = self.blockchain.rpc.get_block(self.identifier)
|
|
188
|
+
if not block:
|
|
189
|
+
raise BlockDoesNotExistsException(
|
|
190
|
+
"output: %s of identifier %s" % (str(block), str(self.identifier))
|
|
191
|
+
)
|
|
192
|
+
block = self._parse_json_data(block)
|
|
193
|
+
super(Block, self).__init__(
|
|
194
|
+
block, lazy=self.lazy, full=self.full, blockchain_instance=self.blockchain
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
@property
|
|
198
|
+
def block_num(self):
|
|
199
|
+
"""Returns the block number"""
|
|
200
|
+
if "block_id" in self:
|
|
201
|
+
return int(self["block_id"][:8], base=16)
|
|
202
|
+
elif "block" in self:
|
|
203
|
+
return int(self["block"])
|
|
204
|
+
else:
|
|
205
|
+
return None
|
|
206
|
+
|
|
207
|
+
def time(self):
|
|
208
|
+
"""Return a datetime instance for the timestamp of this block"""
|
|
209
|
+
return self["timestamp"]
|
|
210
|
+
|
|
211
|
+
@property
|
|
212
|
+
def transactions(self):
|
|
213
|
+
"""Returns all transactions as list"""
|
|
214
|
+
if self.only_ops or self.only_virtual_ops:
|
|
215
|
+
return list()
|
|
216
|
+
trxs = []
|
|
217
|
+
if "transactions" not in self:
|
|
218
|
+
return []
|
|
219
|
+
trx_id = 0
|
|
220
|
+
for trx in self["transactions"]:
|
|
221
|
+
trx_new = {"transaction_id": self["transaction_ids"][trx_id]}
|
|
222
|
+
trx_new.update(trx.copy())
|
|
223
|
+
trx_new.update({"block_num": self.block_num, "transaction_num": trx_id})
|
|
224
|
+
trxs.append(trx_new)
|
|
225
|
+
trx_id += 1
|
|
226
|
+
return trxs
|
|
227
|
+
|
|
228
|
+
@property
|
|
229
|
+
def operations(self):
|
|
230
|
+
"""Returns all block operations as list"""
|
|
231
|
+
if self.only_ops or self.only_virtual_ops:
|
|
232
|
+
return self["operations"]
|
|
233
|
+
ops = []
|
|
234
|
+
trxs = []
|
|
235
|
+
if "transactions" in self:
|
|
236
|
+
trxs = self["transactions"]
|
|
237
|
+
for tx in trxs:
|
|
238
|
+
if "operations" not in tx:
|
|
239
|
+
continue
|
|
240
|
+
for op in tx["operations"]:
|
|
241
|
+
# Replace opid by op name
|
|
242
|
+
# op[0] = getOperationNameForId(op[0])
|
|
243
|
+
if isinstance(op, list):
|
|
244
|
+
ops.append(list(op))
|
|
245
|
+
else:
|
|
246
|
+
ops.append(op.copy())
|
|
247
|
+
return ops
|
|
248
|
+
|
|
249
|
+
@property
|
|
250
|
+
def json_transactions(self):
|
|
251
|
+
"""Returns all transactions as list, all dates are strings."""
|
|
252
|
+
if self.only_ops or self.only_virtual_ops:
|
|
253
|
+
return list()
|
|
254
|
+
trxs = []
|
|
255
|
+
if "transactions" not in self:
|
|
256
|
+
return []
|
|
257
|
+
trx_id = 0
|
|
258
|
+
for trx in self["transactions"]:
|
|
259
|
+
trx_new = {"transaction_id": self["transaction_ids"][trx_id]}
|
|
260
|
+
trx_new.update(trx.copy())
|
|
261
|
+
trx_new.update({"block_num": self.block_num, "transaction_num": trx_id})
|
|
262
|
+
if "expiration" in trx:
|
|
263
|
+
p_date = trx.get("expiration", datetime(1970, 1, 1, 0, 0))
|
|
264
|
+
if isinstance(p_date, (datetime, date)):
|
|
265
|
+
trx_new.update({"expiration": formatTimeString(p_date)})
|
|
266
|
+
|
|
267
|
+
trxs.append(trx_new)
|
|
268
|
+
trx_id += 1
|
|
269
|
+
return trxs
|
|
270
|
+
|
|
271
|
+
@property
|
|
272
|
+
def json_operations(self):
|
|
273
|
+
"""Returns all block operations as list, all dates are strings."""
|
|
274
|
+
if self.only_ops or self.only_virtual_ops:
|
|
275
|
+
return self["operations"]
|
|
276
|
+
ops = []
|
|
277
|
+
for tx in self["transactions"]:
|
|
278
|
+
for op in tx["operations"]:
|
|
279
|
+
if "operations" not in tx:
|
|
280
|
+
continue
|
|
281
|
+
# Replace opid by op name
|
|
282
|
+
# op[0] = getOperationNameForId(op[0])
|
|
283
|
+
if isinstance(op, list):
|
|
284
|
+
op_new = list(op)
|
|
285
|
+
else:
|
|
286
|
+
op_new = op.copy()
|
|
287
|
+
if "timestamp" in op:
|
|
288
|
+
p_date = op.get("timestamp", datetime(1970, 1, 1, 0, 0))
|
|
289
|
+
if isinstance(p_date, (datetime, date)):
|
|
290
|
+
op_new.update({"timestamp": formatTimeString(p_date)})
|
|
291
|
+
ops.append(op_new)
|
|
292
|
+
return ops
|
|
293
|
+
|
|
294
|
+
def ops_statistics(self, add_to_ops_stat=None):
|
|
295
|
+
"""Returns a statistic with the occurrence of the different operation types"""
|
|
296
|
+
if add_to_ops_stat is None:
|
|
297
|
+
import nectarbase.operationids
|
|
298
|
+
|
|
299
|
+
ops_stat = nectarbase.operationids.operations.copy()
|
|
300
|
+
for key in ops_stat:
|
|
301
|
+
ops_stat[key] = 0
|
|
302
|
+
else:
|
|
303
|
+
ops_stat = add_to_ops_stat.copy()
|
|
304
|
+
for op in self.operations:
|
|
305
|
+
if "op" in op:
|
|
306
|
+
op = op["op"]
|
|
307
|
+
if isinstance(op, dict) and "type" in op:
|
|
308
|
+
op_type = op["type"]
|
|
309
|
+
if len(op_type) > 10 and op_type[len(op_type) - 10 :] == "_operation":
|
|
310
|
+
op_type = op_type[:-10]
|
|
311
|
+
else:
|
|
312
|
+
op_type = op[0]
|
|
313
|
+
ops_stat[op_type] += 1
|
|
314
|
+
return ops_stat
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
class BlockHeader(BlockchainObject):
|
|
318
|
+
"""Read a single block header from the chain
|
|
319
|
+
|
|
320
|
+
:param int block: block number
|
|
321
|
+
:param Steem steem_instance: Steem
|
|
322
|
+
instance
|
|
323
|
+
:param bool lazy: Use lazy loading
|
|
324
|
+
|
|
325
|
+
In addition to the block data, the block number is stored as self["id"] or self.identifier.
|
|
326
|
+
|
|
327
|
+
.. code-block:: python
|
|
328
|
+
|
|
329
|
+
>>> from nectar.block import BlockHeader
|
|
330
|
+
>>> block = BlockHeader(1)
|
|
331
|
+
>>> print(block)
|
|
332
|
+
<BlockHeader 1>
|
|
333
|
+
|
|
334
|
+
"""
|
|
335
|
+
|
|
336
|
+
def __init__(self, block, full=True, lazy=False, blockchain_instance=None, **kwargs):
|
|
337
|
+
"""Initilize a block
|
|
338
|
+
|
|
339
|
+
:param int block: block number
|
|
340
|
+
:param Steem steem_instance: Steem
|
|
341
|
+
instance
|
|
342
|
+
:param bool lazy: Use lazy loading
|
|
343
|
+
|
|
344
|
+
"""
|
|
345
|
+
self.full = full
|
|
346
|
+
self.lazy = lazy
|
|
347
|
+
if isinstance(block, float):
|
|
348
|
+
block = int(block)
|
|
349
|
+
super(BlockHeader, self).__init__(
|
|
350
|
+
block, lazy=lazy, full=full, blockchain_instance=blockchain_instance, **kwargs
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
def refresh(self):
|
|
354
|
+
"""Even though blocks never change, you freshly obtain its contents
|
|
355
|
+
from an API with this method
|
|
356
|
+
"""
|
|
357
|
+
if not self.blockchain.is_connected():
|
|
358
|
+
return None
|
|
359
|
+
self.blockchain.rpc.set_next_node_on_empty_reply(False)
|
|
360
|
+
if self.blockchain.rpc.get_use_appbase():
|
|
361
|
+
block = self.blockchain.rpc.get_block_header(
|
|
362
|
+
{"block_num": self.identifier}, api="block"
|
|
363
|
+
)
|
|
364
|
+
if block is not None and "header" in block:
|
|
365
|
+
block = block["header"]
|
|
366
|
+
else:
|
|
367
|
+
block = self.blockchain.rpc.get_block_header(self.identifier)
|
|
368
|
+
if not block:
|
|
369
|
+
raise BlockDoesNotExistsException(str(self.identifier))
|
|
370
|
+
block = self._parse_json_data(block)
|
|
371
|
+
super(BlockHeader, self).__init__(
|
|
372
|
+
block, lazy=self.lazy, full=self.full, blockchain_instance=self.blockchain
|
|
373
|
+
)
|
|
374
|
+
|
|
375
|
+
def time(self):
|
|
376
|
+
"""Return a datetime instance for the timestamp of this block"""
|
|
377
|
+
return self["timestamp"]
|
|
378
|
+
|
|
379
|
+
@property
|
|
380
|
+
def block_num(self):
|
|
381
|
+
"""Returns the block number"""
|
|
382
|
+
return self.identifier
|
|
383
|
+
|
|
384
|
+
def _parse_json_data(self, block):
|
|
385
|
+
parse_times = [
|
|
386
|
+
"timestamp",
|
|
387
|
+
]
|
|
388
|
+
for p in parse_times:
|
|
389
|
+
if p in block and isinstance(block.get(p), string_types):
|
|
390
|
+
block[p] = formatTimeString(block.get(p, "1970-01-01T00:00:00"))
|
|
391
|
+
return block
|
|
392
|
+
|
|
393
|
+
def json(self):
|
|
394
|
+
output = self.copy()
|
|
395
|
+
parse_times = [
|
|
396
|
+
"timestamp",
|
|
397
|
+
]
|
|
398
|
+
for p in parse_times:
|
|
399
|
+
if p in output:
|
|
400
|
+
p_date = output.get(p, datetime(1970, 1, 1, 0, 0))
|
|
401
|
+
if isinstance(p_date, (datetime, date)):
|
|
402
|
+
output[p] = formatTimeString(p_date)
|
|
403
|
+
else:
|
|
404
|
+
output[p] = p_date
|
|
405
|
+
return json.loads(str(json.dumps(output)))
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
class Blocks(list):
|
|
409
|
+
"""Obtain a list of blocks
|
|
410
|
+
|
|
411
|
+
:param list name_list: list of accounts to fetch
|
|
412
|
+
:param int count: (optional) maximum number of accounts
|
|
413
|
+
to fetch per call, defaults to 100
|
|
414
|
+
:param Steem/Hive blockchain_instance: Steem() or Hive() instance to use when
|
|
415
|
+
accessing a RPCcreator = Account(creator, blockchain_instance=self)
|
|
416
|
+
"""
|
|
417
|
+
|
|
418
|
+
def __init__(
|
|
419
|
+
self,
|
|
420
|
+
starting_block_num,
|
|
421
|
+
count=1000,
|
|
422
|
+
lazy=False,
|
|
423
|
+
full=True,
|
|
424
|
+
blockchain_instance=None,
|
|
425
|
+
**kwargs,
|
|
426
|
+
):
|
|
427
|
+
if blockchain_instance is None:
|
|
428
|
+
if kwargs.get("steem_instance"):
|
|
429
|
+
blockchain_instance = kwargs["steem_instance"]
|
|
430
|
+
elif kwargs.get("hive_instance"):
|
|
431
|
+
blockchain_instance = kwargs["hive_instance"]
|
|
432
|
+
self.blockchain = blockchain_instance or shared_blockchain_instance()
|
|
433
|
+
|
|
434
|
+
if not self.blockchain.is_connected():
|
|
435
|
+
return
|
|
436
|
+
blocks = []
|
|
437
|
+
|
|
438
|
+
self.blockchain.rpc.set_next_node_on_empty_reply(False)
|
|
439
|
+
|
|
440
|
+
blocks = self.blockchain.rpc.get_block_range(
|
|
441
|
+
{"starting_block_num": starting_block_num, "count": count}, api="block"
|
|
442
|
+
)["blocks"]
|
|
443
|
+
|
|
444
|
+
super(Blocks, self).__init__(
|
|
445
|
+
[Block(x, lazy=lazy, full=full, blockchain_instance=self.blockchain) for x in blocks]
|
|
446
|
+
)
|