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.

Files changed (86) hide show
  1. hive_nectar-0.0.2.dist-info/METADATA +182 -0
  2. hive_nectar-0.0.2.dist-info/RECORD +86 -0
  3. hive_nectar-0.0.2.dist-info/WHEEL +4 -0
  4. hive_nectar-0.0.2.dist-info/entry_points.txt +2 -0
  5. hive_nectar-0.0.2.dist-info/licenses/LICENSE.txt +23 -0
  6. nectar/__init__.py +32 -0
  7. nectar/account.py +4371 -0
  8. nectar/amount.py +475 -0
  9. nectar/asciichart.py +270 -0
  10. nectar/asset.py +82 -0
  11. nectar/block.py +446 -0
  12. nectar/blockchain.py +1178 -0
  13. nectar/blockchaininstance.py +2284 -0
  14. nectar/blockchainobject.py +221 -0
  15. nectar/blurt.py +563 -0
  16. nectar/cli.py +6285 -0
  17. nectar/comment.py +1217 -0
  18. nectar/community.py +513 -0
  19. nectar/constants.py +111 -0
  20. nectar/conveyor.py +309 -0
  21. nectar/discussions.py +1709 -0
  22. nectar/exceptions.py +149 -0
  23. nectar/hive.py +546 -0
  24. nectar/hivesigner.py +420 -0
  25. nectar/imageuploader.py +72 -0
  26. nectar/instance.py +129 -0
  27. nectar/market.py +1013 -0
  28. nectar/memo.py +449 -0
  29. nectar/message.py +357 -0
  30. nectar/nodelist.py +444 -0
  31. nectar/price.py +557 -0
  32. nectar/profile.py +65 -0
  33. nectar/rc.py +308 -0
  34. nectar/snapshot.py +726 -0
  35. nectar/steem.py +582 -0
  36. nectar/storage.py +53 -0
  37. nectar/transactionbuilder.py +622 -0
  38. nectar/utils.py +545 -0
  39. nectar/version.py +2 -0
  40. nectar/vote.py +557 -0
  41. nectar/wallet.py +472 -0
  42. nectar/witness.py +617 -0
  43. nectarapi/__init__.py +11 -0
  44. nectarapi/exceptions.py +123 -0
  45. nectarapi/graphenerpc.py +589 -0
  46. nectarapi/node.py +178 -0
  47. nectarapi/noderpc.py +229 -0
  48. nectarapi/rpcutils.py +97 -0
  49. nectarapi/version.py +2 -0
  50. nectarbase/__init__.py +14 -0
  51. nectarbase/ledgertransactions.py +75 -0
  52. nectarbase/memo.py +243 -0
  53. nectarbase/objects.py +429 -0
  54. nectarbase/objecttypes.py +22 -0
  55. nectarbase/operationids.py +102 -0
  56. nectarbase/operations.py +1297 -0
  57. nectarbase/signedtransactions.py +48 -0
  58. nectarbase/transactions.py +11 -0
  59. nectarbase/version.py +2 -0
  60. nectargrapheneapi/__init__.py +6 -0
  61. nectargraphenebase/__init__.py +27 -0
  62. nectargraphenebase/account.py +846 -0
  63. nectargraphenebase/aes.py +52 -0
  64. nectargraphenebase/base58.py +192 -0
  65. nectargraphenebase/bip32.py +494 -0
  66. nectargraphenebase/bip38.py +134 -0
  67. nectargraphenebase/chains.py +149 -0
  68. nectargraphenebase/dictionary.py +3 -0
  69. nectargraphenebase/ecdsasig.py +326 -0
  70. nectargraphenebase/objects.py +123 -0
  71. nectargraphenebase/objecttypes.py +6 -0
  72. nectargraphenebase/operationids.py +3 -0
  73. nectargraphenebase/operations.py +23 -0
  74. nectargraphenebase/prefix.py +11 -0
  75. nectargraphenebase/py23.py +38 -0
  76. nectargraphenebase/signedtransactions.py +201 -0
  77. nectargraphenebase/types.py +419 -0
  78. nectargraphenebase/unsignedtransactions.py +283 -0
  79. nectargraphenebase/version.py +2 -0
  80. nectarstorage/__init__.py +38 -0
  81. nectarstorage/base.py +306 -0
  82. nectarstorage/exceptions.py +16 -0
  83. nectarstorage/interfaces.py +237 -0
  84. nectarstorage/masterpassword.py +239 -0
  85. nectarstorage/ram.py +30 -0
  86. nectarstorage/sqlite.py +334 -0
nectar/snapshot.py ADDED
@@ -0,0 +1,726 @@
1
+ # -*- coding: utf-8 -*-
2
+ import json
3
+ import logging
4
+ import re
5
+ from bisect import bisect_left
6
+ from datetime import date, datetime, time, timedelta, timezone
7
+
8
+ from nectar.account import Account
9
+ from nectar.amount import Amount
10
+ from nectar.constants import STEEM_100_PERCENT, STEEM_VOTE_REGENERATION_SECONDS
11
+ from nectar.instance import shared_blockchain_instance
12
+ from nectar.utils import (
13
+ addTzInfo,
14
+ formatTimeString,
15
+ parse_time,
16
+ reputation_to_score,
17
+ )
18
+ from nectar.vote import Vote
19
+
20
+ log = logging.getLogger(__name__)
21
+
22
+
23
+ class AccountSnapshot(list):
24
+ """This class allows to easily access Account history
25
+
26
+ :param str account_name: Name of the account
27
+ :param Steem blockchain_instance: Steem
28
+ instance
29
+ """
30
+
31
+ def __init__(self, account, account_history=[], blockchain_instance=None, **kwargs):
32
+ if blockchain_instance is None:
33
+ if kwargs.get("steem_instance"):
34
+ blockchain_instance = kwargs["steem_instance"]
35
+ elif kwargs.get("hive_instance"):
36
+ blockchain_instance = kwargs["hive_instance"]
37
+ self.blockchain = blockchain_instance or shared_blockchain_instance()
38
+ self.account = Account(account, blockchain_instance=self.blockchain)
39
+ self.reset()
40
+ super(AccountSnapshot, self).__init__(account_history)
41
+
42
+ def reset(self):
43
+ """Resets the arrays not the stored account history"""
44
+ self.own_vests = [
45
+ Amount(0, self.blockchain.vest_token_symbol, blockchain_instance=self.blockchain)
46
+ ]
47
+ self.own_steem = [
48
+ Amount(0, self.blockchain.token_symbol, blockchain_instance=self.blockchain)
49
+ ]
50
+ self.own_sbd = [
51
+ Amount(0, self.blockchain.backed_token_symbol, blockchain_instance=self.blockchain)
52
+ ]
53
+ self.delegated_vests_in = [{}]
54
+ self.delegated_vests_out = [{}]
55
+ self.timestamps = [addTzInfo(datetime(1970, 1, 1, 0, 0, 0, 0))]
56
+ self.ops_statistics = {}
57
+ for key in self.blockchain.get_operation_names():
58
+ self.ops_statistics[key] = 0
59
+ self.reward_timestamps = []
60
+ self.author_rewards = []
61
+ self.curation_rewards = []
62
+ self.curation_per_1000_SP_timestamp = []
63
+ self.curation_per_1000_SP = []
64
+ self.out_vote_timestamp = []
65
+ self.out_vote_weight = []
66
+ self.in_vote_timestamp = []
67
+ self.in_vote_weight = []
68
+ self.in_vote_rep = []
69
+ self.in_vote_rshares = []
70
+ self.vp = []
71
+ self.vp_timestamp = []
72
+ self.downvote_vp = []
73
+ self.downvote_vp_timestamp = []
74
+ self.rep = []
75
+ self.rep_timestamp = []
76
+
77
+ def search(self, search_str, start=None, stop=None, use_block_num=True):
78
+ """Returns ops in the given range"""
79
+ ops = []
80
+ if start is not None:
81
+ start = addTzInfo(start)
82
+ if stop is not None:
83
+ stop = addTzInfo(stop)
84
+ for op in self:
85
+ if use_block_num and start is not None and isinstance(start, int):
86
+ if op["block"] < start:
87
+ continue
88
+ elif not use_block_num and start is not None and isinstance(start, int):
89
+ if op["index"] < start:
90
+ continue
91
+ elif start is not None and isinstance(start, (datetime, date, time)):
92
+ if start > formatTimeString(op["timestamp"]):
93
+ continue
94
+ if use_block_num and stop is not None and isinstance(stop, int):
95
+ if op["block"] > stop:
96
+ continue
97
+ elif not use_block_num and stop is not None and isinstance(stop, int):
98
+ if op["index"] > stop:
99
+ continue
100
+ elif stop is not None and isinstance(stop, (datetime, date, time)):
101
+ if stop < formatTimeString(op["timestamp"]):
102
+ continue
103
+ op_string = json.dumps(list(op.values()))
104
+ if re.search(search_str, op_string):
105
+ ops.append(op)
106
+ return ops
107
+
108
+ def get_ops(self, start=None, stop=None, use_block_num=True, only_ops=[], exclude_ops=[]):
109
+ """Returns ops in the given range"""
110
+ if start is not None:
111
+ start = addTzInfo(start)
112
+ if stop is not None:
113
+ stop = addTzInfo(stop)
114
+ for op in self:
115
+ if use_block_num and start is not None and isinstance(start, int):
116
+ if op["block"] < start:
117
+ continue
118
+ elif not use_block_num and start is not None and isinstance(start, int):
119
+ if op["index"] < start:
120
+ continue
121
+ elif start is not None and isinstance(start, (datetime, date, time)):
122
+ if start > formatTimeString(op["timestamp"]):
123
+ continue
124
+ if use_block_num and stop is not None and isinstance(stop, int):
125
+ if op["block"] > stop:
126
+ continue
127
+ elif not use_block_num and stop is not None and isinstance(stop, int):
128
+ if op["index"] > stop:
129
+ continue
130
+ elif stop is not None and isinstance(stop, (datetime, date, time)):
131
+ if stop < formatTimeString(op["timestamp"]):
132
+ continue
133
+ if exclude_ops and op["type"] in exclude_ops:
134
+ continue
135
+ if not only_ops or op["type"] in only_ops:
136
+ yield op
137
+
138
+ def get_data(self, timestamp=None, index=0):
139
+ """Returns snapshot for given timestamp"""
140
+ if timestamp is None:
141
+ timestamp = datetime.now(timezone.utc)
142
+ timestamp = addTzInfo(timestamp)
143
+ # Find rightmost value less than x
144
+ i = bisect_left(self.timestamps, timestamp)
145
+ if i:
146
+ index = i - 1
147
+ else:
148
+ return {}
149
+ ts = self.timestamps[index]
150
+ own = self.own_vests[index]
151
+ din = self.delegated_vests_in[index]
152
+ dout = self.delegated_vests_out[index]
153
+ steem = self.own_steem[index]
154
+ sbd = self.own_sbd[index]
155
+ sum_in = sum([din[key].amount for key in din])
156
+ sum_out = sum([dout[key].amount for key in dout])
157
+ from nectar import Steem
158
+
159
+ if isinstance(self.blockchain, Steem):
160
+ sp_in = self.blockchain.vests_to_sp(sum_in, timestamp=ts)
161
+ sp_out = self.blockchain.vests_to_sp(sum_out, timestamp=ts)
162
+ sp_own = self.blockchain.vests_to_sp(own, timestamp=ts)
163
+ else:
164
+ sp_in = self.blockchain.vests_to_hp(sum_in, timestamp=ts)
165
+ sp_out = self.blockchain.vests_to_hp(sum_out, timestamp=ts)
166
+ sp_own = self.blockchain.vests_to_hp(own, timestamp=ts)
167
+ sp_eff = sp_own + sp_in - sp_out
168
+ return {
169
+ "timestamp": ts,
170
+ "vests": own,
171
+ "delegated_vests_in": din,
172
+ "delegated_vests_out": dout,
173
+ "sp_own": sp_own,
174
+ "sp_eff": sp_eff,
175
+ "steem": steem,
176
+ "sbd": sbd,
177
+ "index": index,
178
+ }
179
+
180
+ def get_account_history(self, start=None, stop=None, use_block_num=True):
181
+ """Uses account history to fetch all related ops
182
+
183
+ :param start: start number/date of transactions to
184
+ return (*optional*)
185
+ :type start: int, datetime
186
+ :param stop: stop number/date of transactions to
187
+ return (*optional*)
188
+ :type stop: int, datetime
189
+ :param bool use_block_num: if true, start and stop are block numbers,
190
+ otherwise virtual OP count numbers.
191
+
192
+ """
193
+ super(AccountSnapshot, self).__init__(
194
+ [h for h in self.account.history(start=start, stop=stop, use_block_num=use_block_num)]
195
+ )
196
+
197
+ def update_rewards(self, timestamp, curation_reward, author_vests, author_steem, author_sbd):
198
+ self.reward_timestamps.append(timestamp)
199
+ self.curation_rewards.append(curation_reward)
200
+ self.author_rewards.append(
201
+ {"vests": author_vests, "steem": author_steem, "sbd": author_sbd}
202
+ )
203
+
204
+ def update_out_vote(self, timestamp, weight):
205
+ self.out_vote_timestamp.append(timestamp)
206
+ self.out_vote_weight.append(weight)
207
+
208
+ def update_in_vote(self, timestamp, weight, op):
209
+ v = Vote(op)
210
+ try:
211
+ v.refresh()
212
+ self.in_vote_timestamp.append(timestamp)
213
+ self.in_vote_weight.append(weight)
214
+ self.in_vote_rep.append(int(v["reputation"]))
215
+ self.in_vote_rshares.append(int(v["rshares"]))
216
+ except Exception:
217
+ print("Could not find: %s" % v)
218
+ return
219
+
220
+ def update(self, timestamp, own, delegated_in=None, delegated_out=None, steem=0, sbd=0):
221
+ """Updates the internal state arrays
222
+
223
+ :param datetime timestamp: datetime of the update
224
+ :param own: vests
225
+ :type own: amount.Amount, float
226
+ :param dict delegated_in: Incoming delegation
227
+ :param dict delegated_out: Outgoing delegation
228
+ :param steem: steem
229
+ :type steem: amount.Amount, float
230
+ :param sbd: sbd
231
+ :type sbd: amount.Amount, float
232
+
233
+ """
234
+ self.timestamps.append(timestamp - timedelta(seconds=1))
235
+ self.own_vests.append(self.own_vests[-1])
236
+ self.own_steem.append(self.own_steem[-1])
237
+ self.own_sbd.append(self.own_sbd[-1])
238
+ self.delegated_vests_in.append(self.delegated_vests_in[-1])
239
+ self.delegated_vests_out.append(self.delegated_vests_out[-1])
240
+
241
+ self.timestamps.append(timestamp)
242
+ self.own_vests.append(self.own_vests[-1] + own)
243
+ self.own_steem.append(self.own_steem[-1] + steem)
244
+ self.own_sbd.append(self.own_sbd[-1] + sbd)
245
+
246
+ new_deleg = dict(self.delegated_vests_in[-1])
247
+ if delegated_in is not None and delegated_in:
248
+ if delegated_in["amount"] == 0:
249
+ del new_deleg[delegated_in["account"]]
250
+ else:
251
+ new_deleg[delegated_in["account"]] = delegated_in["amount"]
252
+ self.delegated_vests_in.append(new_deleg)
253
+
254
+ new_deleg = dict(self.delegated_vests_out[-1])
255
+ if delegated_out is not None and delegated_out:
256
+ if delegated_out["account"] is None:
257
+ # return_vesting_delegation
258
+ for delegatee in new_deleg:
259
+ if new_deleg[delegatee]["amount"] == delegated_out["amount"]:
260
+ del new_deleg[delegatee]
261
+ break
262
+
263
+ elif delegated_out["amount"] != 0:
264
+ # new or updated non-zero delegation
265
+ new_deleg[delegated_out["account"]] = delegated_out["amount"]
266
+ # TODO
267
+ # skip undelegations here, wait for 'return_vesting_delegation'
268
+ # del new_deleg[delegated_out['account']]
269
+
270
+ self.delegated_vests_out.append(new_deleg)
271
+
272
+ def build(
273
+ self,
274
+ only_ops=[],
275
+ exclude_ops=[],
276
+ enable_rewards=False,
277
+ enable_out_votes=False,
278
+ enable_in_votes=False,
279
+ ):
280
+ """Builds the account history based on all account operations
281
+
282
+ :param array only_ops: Limit generator by these
283
+ operations (*optional*)
284
+ :param array exclude_ops: Exclude these operations from
285
+ generator (*optional*)
286
+
287
+ """
288
+ if len(self.timestamps) > 0:
289
+ start_timestamp = self.timestamps[-1]
290
+ else:
291
+ start_timestamp = None
292
+ for op in sorted(self, key=lambda k: k["timestamp"]):
293
+ ts = parse_time(op["timestamp"])
294
+ if start_timestamp is not None and start_timestamp > ts:
295
+ continue
296
+ if op["type"] in exclude_ops:
297
+ continue
298
+ if len(only_ops) > 0 and op["type"] not in only_ops:
299
+ continue
300
+ self.ops_statistics[op["type"]] += 1
301
+ self.parse_op(
302
+ op,
303
+ only_ops=only_ops,
304
+ enable_rewards=enable_rewards,
305
+ enable_out_votes=enable_out_votes,
306
+ enable_in_votes=enable_in_votes,
307
+ )
308
+
309
+ def parse_op(
310
+ self, op, only_ops=[], enable_rewards=False, enable_out_votes=False, enable_in_votes=False
311
+ ):
312
+ """Parse account history operation"""
313
+ ts = parse_time(op["timestamp"])
314
+
315
+ if op["type"] == "account_create":
316
+ fee_steem = Amount(op["fee"], blockchain_instance=self.blockchain).amount
317
+ fee_vests = self.blockchain.sp_to_vests(
318
+ Amount(op["fee"], blockchain_instance=self.blockchain).amount, timestamp=ts
319
+ )
320
+ if op["new_account_name"] == self.account["name"]:
321
+ self.update(ts, fee_vests, 0, 0)
322
+ return
323
+ if op["creator"] == self.account["name"]:
324
+ self.update(ts, 0, 0, 0, fee_steem * (-1), 0)
325
+ return
326
+
327
+ elif op["type"] == "account_create_with_delegation":
328
+ fee_steem = Amount(op["fee"], blockchain_instance=self.blockchain).amount
329
+ from nectar import Steem
330
+
331
+ if isinstance(self.blockchain, Steem):
332
+ fee_vests = self.blockchain.sp_to_vests(
333
+ Amount(op["fee"], blockchain_instance=self.blockchain).amount, timestamp=ts
334
+ )
335
+ else:
336
+ fee_vests = self.blockchain.hp_to_vests(
337
+ Amount(op["fee"], blockchain_instance=self.blockchain).amount, timestamp=ts
338
+ )
339
+ if op["new_account_name"] == self.account["name"]:
340
+ if Amount(op["delegation"], blockchain_instance=self.blockchain).amount > 0:
341
+ delegation = {
342
+ "account": op["creator"],
343
+ "amount": Amount(op["delegation"], blockchain_instance=self.blockchain),
344
+ }
345
+ else:
346
+ delegation = None
347
+ self.update(ts, fee_vests, delegation, 0)
348
+ return
349
+
350
+ if op["creator"] == self.account["name"]:
351
+ delegation = {
352
+ "account": op["new_account_name"],
353
+ "amount": Amount(op["delegation"], blockchain_instance=self.blockchain),
354
+ }
355
+ self.update(ts, 0, 0, delegation, fee_steem * (-1), 0)
356
+ return
357
+
358
+ elif op["type"] == "delegate_vesting_shares":
359
+ vests = Amount(op["vesting_shares"], blockchain_instance=self.blockchain)
360
+ if op["delegator"] == self.account["name"]:
361
+ delegation = {"account": op["delegatee"], "amount": vests}
362
+ self.update(ts, 0, 0, delegation)
363
+ return
364
+ if op["delegatee"] == self.account["name"]:
365
+ delegation = {"account": op["delegator"], "amount": vests}
366
+ self.update(ts, 0, delegation, 0)
367
+ return
368
+
369
+ elif op["type"] == "transfer":
370
+ amount = Amount(op["amount"], blockchain_instance=self.blockchain)
371
+ if op["from"] == self.account["name"]:
372
+ if amount.symbol == self.blockchain.blockchain_symbol:
373
+ self.update(ts, 0, 0, 0, amount * (-1), 0)
374
+ elif amount.symbol == self.blockchain.backed_token_symbol:
375
+ self.update(ts, 0, 0, 0, 0, amount * (-1))
376
+ if op["to"] == self.account["name"]:
377
+ if amount.symbol == self.blockchain.blockchain_symbol:
378
+ self.update(ts, 0, 0, 0, amount, 0)
379
+ elif amount.symbol == self.blockchain.backed_token_symbol:
380
+ self.update(ts, 0, 0, 0, 0, amount)
381
+ return
382
+
383
+ elif op["type"] == "fill_order":
384
+ current_pays = Amount(op["current_pays"], blockchain_instance=self.blockchain)
385
+ open_pays = Amount(op["open_pays"], blockchain_instance=self.blockchain)
386
+ if op["current_owner"] == self.account["name"]:
387
+ if current_pays.symbol == self.blockchain.token_symbol:
388
+ self.update(ts, 0, 0, 0, current_pays * (-1), open_pays)
389
+ elif current_pays.symbol == self.blockchain.backed_token_symbol:
390
+ self.update(ts, 0, 0, 0, open_pays, current_pays * (-1))
391
+ if op["open_owner"] == self.account["name"]:
392
+ if current_pays.symbol == self.blockchain.token_symbol:
393
+ self.update(ts, 0, 0, 0, current_pays, open_pays * (-1))
394
+ elif current_pays.symbol == self.blockchain.backed_token_symbol:
395
+ self.update(ts, 0, 0, 0, open_pays * (-1), current_pays)
396
+ return
397
+
398
+ elif op["type"] == "transfer_to_vesting":
399
+ steem = Amount(op["amount"], blockchain_instance=self.blockchain)
400
+ from nectar import Steem
401
+
402
+ if isinstance(self.blockchain, Steem):
403
+ vests = self.blockchain.sp_to_vests(steem.amount, timestamp=ts)
404
+ else:
405
+ vests = self.blockchain.hp_to_vests(steem.amount, timestamp=ts)
406
+ if op["from"] == self.account["name"] and op["to"] == self.account["name"]:
407
+ self.update(ts, vests, 0, 0, steem * (-1), 0) # power up from and to given account
408
+ elif op["from"] != self.account["name"] and op["to"] == self.account["name"]:
409
+ self.update(ts, vests, 0, 0, 0, 0) # power up from another account
410
+ else: # op['from'] == self.account["name"] and op['to'] != self.account["name"]
411
+ self.update(ts, 0, 0, 0, steem * (-1), 0) # power up to another account
412
+ return
413
+
414
+ elif op["type"] == "fill_vesting_withdraw":
415
+ vests = Amount(op["withdrawn"], blockchain_instance=self.blockchain)
416
+ self.update(ts, vests * (-1), 0, 0)
417
+ return
418
+
419
+ elif op["type"] == "return_vesting_delegation":
420
+ delegation = {
421
+ "account": None,
422
+ "amount": Amount(op["vesting_shares"], blockchain_instance=self.blockchain),
423
+ }
424
+ self.update(ts, 0, 0, delegation)
425
+ return
426
+
427
+ elif op["type"] == "claim_reward_balance":
428
+ vests = Amount(op["reward_vests"], blockchain_instance=self.blockchain)
429
+ steem = Amount(op["reward_steem"], blockchain_instance=self.blockchain)
430
+ sbd = Amount(op["reward_sbd"], blockchain_instance=self.blockchain)
431
+ self.update(ts, vests, 0, 0, steem, sbd)
432
+ return
433
+
434
+ elif op["type"] == "curation_reward":
435
+ if "curation_reward" in only_ops or enable_rewards:
436
+ vests = Amount(op["reward"], blockchain_instance=self.blockchain)
437
+ if "curation_reward" in only_ops:
438
+ self.update(ts, vests, 0, 0)
439
+ if enable_rewards:
440
+ self.update_rewards(ts, vests, 0, 0, 0)
441
+ return
442
+
443
+ elif op["type"] == "author_reward":
444
+ if "author_reward" in only_ops or enable_rewards:
445
+ vests = Amount(op["vesting_payout"], blockchain_instance=self.blockchain)
446
+ steem = Amount(op["steem_payout"], blockchain_instance=self.blockchain)
447
+ sbd = Amount(op["sbd_payout"], blockchain_instance=self.blockchain)
448
+ if "author_reward" in only_ops:
449
+ self.update(ts, vests, 0, 0, steem, sbd)
450
+ if enable_rewards:
451
+ self.update_rewards(ts, 0, vests, steem, sbd)
452
+ return
453
+
454
+ elif op["type"] == "producer_reward":
455
+ vests = Amount(op["vesting_shares"], blockchain_instance=self.blockchain)
456
+ self.update(ts, vests, 0, 0)
457
+ return
458
+
459
+ elif op["type"] == "comment_benefactor_reward":
460
+ if op["benefactor"] == self.account["name"]:
461
+ if "reward" in op:
462
+ vests = Amount(op["reward"], blockchain_instance=self.blockchain)
463
+ self.update(ts, vests, 0, 0)
464
+ else:
465
+ vests = Amount(op["vesting_payout"], blockchain_instance=self.blockchain)
466
+ steem = Amount(op["steem_payout"], blockchain_instance=self.blockchain)
467
+ sbd = Amount(op["sbd_payout"], blockchain_instance=self.blockchain)
468
+ self.update(ts, vests, 0, 0, steem, sbd)
469
+ return
470
+ else:
471
+ return
472
+
473
+ elif op["type"] == "fill_convert_request":
474
+ amount_in = Amount(op["amount_in"], blockchain_instance=self.blockchain)
475
+ amount_out = Amount(op["amount_out"], blockchain_instance=self.blockchain)
476
+ if op["owner"] == self.account["name"]:
477
+ self.update(ts, 0, 0, 0, amount_out, amount_in * (-1))
478
+ return
479
+
480
+ elif op["type"] == "interest":
481
+ interest = Amount(op["interest"], blockchain_instance=self.blockchain)
482
+ self.update(ts, 0, 0, 0, 0, interest)
483
+ return
484
+
485
+ elif op["type"] == "vote":
486
+ if "vote" in only_ops or enable_out_votes:
487
+ weight = int(op["weight"])
488
+ if op["voter"] == self.account["name"]:
489
+ self.update_out_vote(ts, weight)
490
+ if "vote" in only_ops or enable_in_votes and op["author"] == self.account["name"]:
491
+ weight = int(op["weight"])
492
+ self.update_in_vote(ts, weight, op)
493
+ return
494
+
495
+ elif op["type"] == "hardfork_hive":
496
+ vests = Amount(op["vests_converted"])
497
+ hbd = Amount(op["steem_transferred"])
498
+ hive = Amount(op["sbd_transferred"])
499
+ self.update(ts, vests * (-1), 0, 0, hive * (-1), hbd * (-1))
500
+
501
+ elif op["type"] in [
502
+ "comment",
503
+ "feed_publish",
504
+ "shutdown_witness",
505
+ "account_witness_vote",
506
+ "witness_update",
507
+ "custom_json",
508
+ "limit_order_create",
509
+ "account_update",
510
+ "account_witness_proxy",
511
+ "limit_order_cancel",
512
+ "comment_options",
513
+ "delete_comment",
514
+ "interest",
515
+ "recover_account",
516
+ "pow",
517
+ "fill_convert_request",
518
+ "convert",
519
+ "request_account_recovery",
520
+ "update_proposal_votes",
521
+ ]:
522
+ return
523
+
524
+ def build_sp_arrays(self):
525
+ """Builds the own_sp and eff_sp array"""
526
+ self.own_sp = []
527
+ self.eff_sp = []
528
+ for ts, own, din, dout in zip(
529
+ self.timestamps, self.own_vests, self.delegated_vests_in, self.delegated_vests_out
530
+ ):
531
+ sum_in = sum([din[key].amount for key in din])
532
+ sum_out = sum([dout[key].amount for key in dout])
533
+ from nectar import Steem
534
+
535
+ if isinstance(self.blockchain, Steem):
536
+ sp_in = self.blockchain.vests_to_sp(sum_in, timestamp=ts)
537
+ sp_out = self.blockchain.vests_to_sp(sum_out, timestamp=ts)
538
+ sp_own = self.blockchain.vests_to_sp(own, timestamp=ts)
539
+ else:
540
+ sp_in = self.blockchain.vests_to_hp(sum_in, timestamp=ts)
541
+ sp_out = self.blockchain.vests_to_hp(sum_out, timestamp=ts)
542
+ sp_own = self.blockchain.vests_to_hp(own, timestamp=ts)
543
+
544
+ sp_eff = sp_own + sp_in - sp_out
545
+ self.own_sp.append(sp_own)
546
+ self.eff_sp.append(sp_eff)
547
+
548
+ def build_rep_arrays(self):
549
+ """Build reputation arrays"""
550
+ self.rep_timestamp = [self.timestamps[1]]
551
+ self.rep = [reputation_to_score(0)]
552
+ current_reputation = 0
553
+ for ts, rshares, rep in zip(self.in_vote_timestamp, self.in_vote_rshares, self.in_vote_rep):
554
+ if rep > 0:
555
+ if rshares > 0 or (rshares < 0 and rep > current_reputation):
556
+ current_reputation += rshares >> 6
557
+ self.rep.append(reputation_to_score(current_reputation))
558
+ self.rep_timestamp.append(ts)
559
+
560
+ def build_vp_arrays(self):
561
+ """Build vote power arrays"""
562
+ self.vp_timestamp = [self.timestamps[1]]
563
+ self.vp = [STEEM_100_PERCENT]
564
+ HF_21 = datetime(2019, 8, 27, 15, tzinfo=timezone.utc)
565
+ if self.timestamps[1] > HF_21:
566
+ self.downvote_vp_timestamp = [self.timestamps[1]]
567
+ else:
568
+ self.downvote_vp_timestamp = [HF_21]
569
+ self.downvote_vp = [STEEM_100_PERCENT]
570
+
571
+ for ts, weight in zip(self.out_vote_timestamp, self.out_vote_weight):
572
+ regenerated_vp = 0
573
+ if ts > HF_21 and weight < 0:
574
+ self.downvote_vp.append(self.downvote_vp[-1])
575
+ if self.downvote_vp[-1] < STEEM_100_PERCENT:
576
+ regenerated_vp = (
577
+ ((ts - self.downvote_vp_timestamp[-1]).total_seconds())
578
+ * STEEM_100_PERCENT
579
+ / STEEM_VOTE_REGENERATION_SECONDS
580
+ )
581
+ self.downvote_vp[-1] += int(regenerated_vp)
582
+
583
+ if self.downvote_vp[-1] > STEEM_100_PERCENT:
584
+ self.downvote_vp[-1] = STEEM_100_PERCENT
585
+ recharge_time = self.account.get_manabar_recharge_timedelta(
586
+ {"current_mana_pct": self.downvote_vp[-2] / 100}
587
+ )
588
+ # Add full downvote VP once fully charged
589
+ self.downvote_vp_timestamp.append(
590
+ self.downvote_vp_timestamp[-1] + recharge_time
591
+ )
592
+ self.downvote_vp.append(STEEM_100_PERCENT)
593
+
594
+ # Add charged downvote VP just before new Vote
595
+ self.downvote_vp_timestamp.append(ts - timedelta(seconds=1))
596
+ self.downvote_vp.append(
597
+ min([STEEM_100_PERCENT, self.downvote_vp[-1] + regenerated_vp])
598
+ )
599
+
600
+ self.downvote_vp[-1] -= (
601
+ self.blockchain._calc_resulting_vote(STEEM_100_PERCENT, weight) * 4
602
+ )
603
+ # Downvote mana pool is 1/4th of the upvote mana pool, so it gets drained 4 times as quick
604
+ if self.downvote_vp[-1] < 0:
605
+ # There's most likely a better solution to this that what I did here
606
+ self.vp.append(self.vp[-1])
607
+
608
+ if self.vp[-1] < STEEM_100_PERCENT:
609
+ regenerated_vp = (
610
+ ((ts - self.vp_timestamp[-1]).total_seconds())
611
+ * STEEM_100_PERCENT
612
+ / STEEM_VOTE_REGENERATION_SECONDS
613
+ )
614
+ self.vp[-1] += int(regenerated_vp)
615
+
616
+ if self.vp[-1] > STEEM_100_PERCENT:
617
+ self.vp[-1] = STEEM_100_PERCENT
618
+ recharge_time = self.account.get_manabar_recharge_timedelta(
619
+ {"current_mana_pct": self.vp[-2] / 100}
620
+ )
621
+ # Add full VP once fully charged
622
+ self.vp_timestamp.append(self.vp_timestamp[-1] + recharge_time)
623
+ self.vp.append(STEEM_100_PERCENT)
624
+ if self.vp[-1] == STEEM_100_PERCENT and ts - self.vp_timestamp[-1] > timedelta(
625
+ seconds=1
626
+ ):
627
+ # Add charged VP just before new Vote
628
+ self.vp_timestamp.append(ts - timedelta(seconds=1))
629
+ self.vp.append(min([STEEM_100_PERCENT, self.vp[-1] + regenerated_vp]))
630
+ self.vp[-1] += self.downvote_vp[-1] / 4
631
+ if self.vp[-1] < 0:
632
+ self.vp[-1] = 0
633
+
634
+ self.vp_timestamp.append(ts)
635
+ self.downvote_vp[-1] = 0
636
+ self.downvote_vp_timestamp.append(ts)
637
+
638
+ else:
639
+ self.vp.append(self.vp[-1])
640
+
641
+ if self.vp[-1] < STEEM_100_PERCENT:
642
+ regenerated_vp = (
643
+ ((ts - self.vp_timestamp[-1]).total_seconds())
644
+ * STEEM_100_PERCENT
645
+ / STEEM_VOTE_REGENERATION_SECONDS
646
+ )
647
+ self.vp[-1] += int(regenerated_vp)
648
+
649
+ if self.vp[-1] > STEEM_100_PERCENT:
650
+ self.vp[-1] = STEEM_100_PERCENT
651
+ recharge_time = self.account.get_manabar_recharge_timedelta(
652
+ {"current_mana_pct": self.vp[-2] / 100}
653
+ )
654
+ # Add full VP once fully charged
655
+ self.vp_timestamp.append(self.vp_timestamp[-1] + recharge_time)
656
+ self.vp.append(STEEM_100_PERCENT)
657
+ if self.vp[-1] == STEEM_100_PERCENT and ts - self.vp_timestamp[-1] > timedelta(
658
+ seconds=1
659
+ ):
660
+ # Add charged VP just before new Vote
661
+ self.vp_timestamp.append(ts - timedelta(seconds=1))
662
+ self.vp.append(min([STEEM_100_PERCENT, self.vp[-1] + regenerated_vp]))
663
+ self.vp[-1] -= self.blockchain._calc_resulting_vote(self.vp[-1], weight)
664
+ if self.vp[-1] < 0:
665
+ self.vp[-1] = 0
666
+
667
+ self.vp_timestamp.append(ts)
668
+
669
+ if self.account.get_voting_power() == 100:
670
+ self.vp.append(10000)
671
+ recharge_time = self.account.get_manabar_recharge_timedelta(
672
+ {"current_mana_pct": self.vp[-2] / 100}
673
+ )
674
+ self.vp_timestamp.append(self.vp_timestamp[-1] + recharge_time)
675
+
676
+ if self.account.get_downvoting_power() == 100:
677
+ self.downvote_vp.append(10000)
678
+ recharge_time = self.account.get_manabar_recharge_timedelta(
679
+ {"current_mana_pct": self.downvote_vp[-2] / 100}
680
+ )
681
+ self.downvote_vp_timestamp.append(self.vp_timestamp[-1] + recharge_time)
682
+
683
+ self.vp.append(self.account.get_voting_power() * 100)
684
+ self.downvote_vp.append(self.account.get_downvoting_power() * 100)
685
+ self.downvote_vp_timestamp.append(datetime.now(timezone.utc))
686
+ self.vp_timestamp.append(datetime.now(timezone.utc))
687
+
688
+ def build_curation_arrays(self, end_date=None, sum_days=7):
689
+ """Build curation arrays"""
690
+ self.curation_per_1000_SP_timestamp = []
691
+ self.curation_per_1000_SP = []
692
+ if sum_days <= 0:
693
+ raise ValueError("sum_days must be greater than 0")
694
+ index = 0
695
+ curation_sum = 0
696
+ days = (self.reward_timestamps[-1] - self.reward_timestamps[0]).days // sum_days * sum_days
697
+ if end_date is None:
698
+ end_date = self.reward_timestamps[-1] - timedelta(days=days)
699
+ for ts, vests in zip(self.reward_timestamps, self.curation_rewards):
700
+ if vests == 0:
701
+ continue
702
+ from nectar import Steem
703
+
704
+ if isinstance(self.blockchain, Steem):
705
+ sp = self.blockchain.vests_to_sp(vests, timestamp=ts)
706
+ else:
707
+ sp = self.blockchain.vests_to_hp(vests, timestamp=ts)
708
+ data = self.get_data(timestamp=ts, index=index)
709
+ index = data["index"]
710
+ if "sp_eff" in data and data["sp_eff"] > 0:
711
+ curation_1k_sp = sp / data["sp_eff"] * 1000 / sum_days * 7
712
+ else:
713
+ curation_1k_sp = 0
714
+ if ts < end_date:
715
+ curation_sum += curation_1k_sp
716
+ else:
717
+ self.curation_per_1000_SP_timestamp.append(end_date)
718
+ self.curation_per_1000_SP.append(curation_sum)
719
+ end_date = end_date + timedelta(days=sum_days)
720
+ curation_sum = 0
721
+
722
+ def __str__(self):
723
+ return self.__repr__()
724
+
725
+ def __repr__(self):
726
+ return "<%s %s>" % (self.__class__.__name__, str(self.account["name"]))