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/steem.py ADDED
@@ -0,0 +1,582 @@
1
+ # -*- coding: utf-8 -*-
2
+ import logging
3
+ import math
4
+ from datetime import date, datetime, timezone
5
+
6
+ from nectar.blockchaininstance import BlockChainInstance
7
+ from nectar.constants import STEEM_100_PERCENT, STEEM_VOTE_REGENERATION_SECONDS
8
+ from nectargraphenebase.chains import known_chains
9
+ from nectargraphenebase.py23 import string_types
10
+
11
+ from .amount import Amount
12
+ from .utils import formatToTimeStamp
13
+
14
+ log = logging.getLogger(__name__)
15
+
16
+
17
+ class Steem(BlockChainInstance):
18
+ """Connect to the Steem network.
19
+
20
+ :param str node: Node to connect to *(optional)*
21
+ :param str rpcuser: RPC user *(optional)*
22
+ :param str rpcpassword: RPC password *(optional)*
23
+ :param bool nobroadcast: Do **not** broadcast a transaction!
24
+ *(optional)*
25
+ :param bool unsigned: Do **not** sign a transaction! *(optional)*
26
+ :param bool debug: Enable Debugging *(optional)*
27
+ :param keys: Predefine the wif keys to shortcut the
28
+ wallet database *(optional)*
29
+ :type keys: array, dict, string
30
+ :param wif: Predefine the wif keys to shortcut the
31
+ wallet database *(optional)*
32
+ :type wif: array, dict, string
33
+ :param bool offline: Boolean to prevent connecting to network (defaults
34
+ to ``False``) *(optional)*
35
+ :param int expiration: Delay in seconds until transactions are supposed
36
+ to expire *(optional)* (default is 30)
37
+ :param str blocking: Wait for broadcasted transactions to be included
38
+ in a block and return full transaction (can be "head" or
39
+ "irreversible")
40
+ :param bool bundle: Do not broadcast transactions right away, but allow
41
+ to bundle operations. It is not possible to send out more than one
42
+ vote operation and more than one comment operation in a single broadcast *(optional)*
43
+ :param bool appbase: Use the new appbase rpc protocol on nodes with version
44
+ 0.19.4 or higher. The settings has no effect on nodes with version of 0.19.3 or lower.
45
+ :param int num_retries: Set the maximum number of reconnects to the nodes before
46
+ NumRetriesReached is raised. Disabled for -1. (default is -1)
47
+ :param int num_retries_call: Repeat num_retries_call times a rpc call on node error (default is 5)
48
+ :param int timeout: Timeout setting for https nodes (default is 60)
49
+ :param bool use_sc2: When True, a steemconnect object is created. Can be used for
50
+ broadcast posting op or creating hot_links (default is False)
51
+ :param SteemConnect steemconnect: A SteemConnect object can be set manually, set use_sc2 to True
52
+ :param dict custom_chains: custom chain which should be added to the known chains
53
+
54
+ Three wallet operation modes are possible:
55
+
56
+ * **Wallet Database**: Here, the steemlibs load the keys from the
57
+ locally stored wallet SQLite database (see ``storage.py``).
58
+ To use this mode, simply call ``Steem()`` without the
59
+ ``keys`` parameter
60
+ * **Providing Keys**: Here, you can provide the keys for
61
+ your accounts manually. All you need to do is add the wif
62
+ keys for the accounts you want to use as a simple array
63
+ using the ``keys`` parameter to ``Steem()``.
64
+ * **Force keys**: This more is for advanced users and
65
+ requires that you know what you are doing. Here, the
66
+ ``keys`` parameter is a dictionary that overwrite the
67
+ ``active``, ``owner``, ``posting`` or ``memo`` keys for
68
+ any account. This mode is only used for *foreign*
69
+ signatures!
70
+
71
+ If no node is provided, it will connect to default nodes of
72
+ http://geo.steem.pl. Default settings can be changed with:
73
+
74
+ .. code-block:: python
75
+
76
+ steem = Steem(<host>)
77
+
78
+ where ``<host>`` starts with ``https://``, ``ws://`` or ``wss://``.
79
+
80
+ The purpose of this class it to simplify interaction with
81
+ Steem.
82
+
83
+ The idea is to have a class that allows to do this:
84
+
85
+ .. code-block:: python
86
+
87
+ >>> from nectar import Steem
88
+ >>> steem = Steem()
89
+ >>> print(steem.get_blockchain_version()) # doctest: +SKIP
90
+
91
+ This class also deals with edits, votes and reading content.
92
+
93
+ Example for adding a custom chain:
94
+
95
+ .. code-block:: python
96
+
97
+ from nectar import Steem
98
+ stm = Steem(node=["https://mytstnet.com"], custom_chains={"MYTESTNET":
99
+ {'chain_assets': [{'asset': 'SBD', 'id': 0, 'precision': 3, 'symbol': 'SBD'},
100
+ {'asset': 'STEEM', 'id': 1, 'precision': 3, 'symbol': 'STEEM'},
101
+ {'asset': 'VESTS', 'id': 2, 'precision': 6, 'symbol': 'VESTS'}],
102
+ 'chain_id': '79276aea5d4877d9a25892eaa01b0adf019d3e5cb12a97478df3298ccdd01674',
103
+ 'min_version': '0.0.0',
104
+ 'prefix': 'MTN'}
105
+ }
106
+ )
107
+
108
+ """
109
+
110
+ def get_network(self, use_stored_data=True, config=None):
111
+ """Identify the network
112
+
113
+ :param bool use_stored_data: if True, stored data will be returned. If stored data are
114
+ empty or old, refresh_data() is used.
115
+
116
+ :returns: Network parameters
117
+ :rtype: dictionary
118
+ """
119
+ if use_stored_data:
120
+ self.refresh_data("config")
121
+ return self.data["network"]
122
+
123
+ if self.rpc is None:
124
+ return known_chains["STEEM"]
125
+ try:
126
+ return self.rpc.get_network(props=config)
127
+ except:
128
+ return known_chains["STEEM"]
129
+
130
+ def rshares_to_token_backed_dollar(
131
+ self, rshares, not_broadcasted_vote=False, use_stored_data=True
132
+ ):
133
+ return self.rshares_to_sbd(
134
+ rshares, not_broadcasted_vote=not_broadcasted_vote, use_stored_data=use_stored_data
135
+ )
136
+
137
+ def rshares_to_sbd(self, rshares, not_broadcasted_vote=False, use_stored_data=True):
138
+ """Calculates the current SBD value of a vote"""
139
+ payout = float(rshares) * self.get_sbd_per_rshares(
140
+ use_stored_data=use_stored_data,
141
+ not_broadcasted_vote_rshares=rshares if not_broadcasted_vote else 0,
142
+ )
143
+ return payout
144
+
145
+ def get_sbd_per_rshares(self, not_broadcasted_vote_rshares=0, use_stored_data=True):
146
+ """Returns the current rshares to SBD ratio"""
147
+ reward_fund = self.get_reward_funds(use_stored_data=use_stored_data)
148
+ reward_balance = float(Amount(reward_fund["reward_balance"], blockchain_instance=self))
149
+ recent_claims = float(reward_fund["recent_claims"]) + not_broadcasted_vote_rshares
150
+ if recent_claims == 0:
151
+ return 0
152
+ fund_per_share = reward_balance / (recent_claims)
153
+ median_price = self.get_median_price(use_stored_data=use_stored_data)
154
+ if median_price is None:
155
+ return 0
156
+ SBD_price = float(median_price * (Amount(1, self.steem_symbol, blockchain_instance=self)))
157
+ return fund_per_share * SBD_price
158
+
159
+ def get_steem_per_mvest(self, time_stamp=None, use_stored_data=True):
160
+ """Returns the MVEST to STEEM ratio
161
+
162
+ :param int time_stamp: (optional) if set, return an estimated
163
+ STEEM per MVEST ratio for the given time stamp. If unset the
164
+ current ratio is returned (default). (can also be a datetime object)
165
+ """
166
+ if self.offline and time_stamp is None:
167
+ time_stamp = datetime.now(timezone.utc)
168
+
169
+ if time_stamp is not None:
170
+ if isinstance(time_stamp, (datetime, date)):
171
+ time_stamp = formatToTimeStamp(time_stamp)
172
+ a = 2.1325476281078992e-05
173
+ b = -31099.685481490847
174
+ a2 = 2.9019227739473682e-07
175
+ b2 = 48.41432402074669
176
+
177
+ if time_stamp < (b2 - b) / (a - a2):
178
+ return a * time_stamp + b
179
+ else:
180
+ return a2 * time_stamp + b2
181
+ global_properties = self.get_dynamic_global_properties(use_stored_data=use_stored_data)
182
+
183
+ if "total_vesting_fund_steem" in global_properties:
184
+ return float(
185
+ Amount(global_properties["total_vesting_fund_steem"], blockchain_instance=self)
186
+ ) / (
187
+ float(Amount(global_properties["total_vesting_shares"], blockchain_instance=self))
188
+ / 1e6
189
+ )
190
+ else:
191
+ for key in global_properties:
192
+ if "total_vesting_fund_" in key:
193
+ return float(Amount(global_properties[key], blockchain_instance=self)) / (
194
+ float(
195
+ Amount(
196
+ global_properties["total_vesting_shares"], blockchain_instance=self
197
+ )
198
+ )
199
+ / 1e6
200
+ )
201
+
202
+ def vests_to_sp(self, vests, timestamp=None, use_stored_data=True):
203
+ """Converts vests to SP
204
+
205
+ :param amount.Amount vests/float vests: Vests to convert
206
+ :param int timestamp: (Optional) Can be used to calculate
207
+ the conversion rate from the past
208
+
209
+ """
210
+ if isinstance(vests, Amount):
211
+ vests = float(vests)
212
+ return (
213
+ float(vests)
214
+ / 1e6
215
+ * self.get_steem_per_mvest(timestamp, use_stored_data=use_stored_data)
216
+ )
217
+
218
+ def sp_to_vests(self, sp, timestamp=None, use_stored_data=True):
219
+ """Converts SP to vests
220
+
221
+ :param float sp: Steem power to convert
222
+ :param datetime timestamp: (Optional) Can be used to calculate
223
+ the conversion rate from the past
224
+ """
225
+ return sp * 1e6 / self.get_steem_per_mvest(timestamp, use_stored_data=use_stored_data)
226
+
227
+ def vests_to_token_power(self, vests, timestamp=None, use_stored_data=True):
228
+ return self.vests_to_sp(vests, timestamp=timestamp, use_stored_data=use_stored_data)
229
+
230
+ def token_power_to_vests(self, token_power, timestamp=None, use_stored_data=True):
231
+ return self.sp_to_vests(token_power, timestamp=timestamp, use_stored_data=use_stored_data)
232
+
233
+ def get_token_per_mvest(self, time_stamp=None, use_stored_data=True):
234
+ return self.get_steem_per_mvest(time_stamp=time_stamp, use_stored_data=use_stored_data)
235
+
236
+ def token_power_to_token_backed_dollar(
237
+ self,
238
+ token_power,
239
+ post_rshares=0,
240
+ voting_power=STEEM_100_PERCENT,
241
+ vote_pct=STEEM_100_PERCENT,
242
+ not_broadcasted_vote=True,
243
+ use_stored_data=True,
244
+ ):
245
+ return self.sp_to_sbd(
246
+ token_power,
247
+ post_rshares=post_rshares,
248
+ voting_power=voting_power,
249
+ vote_pct=vote_pct,
250
+ not_broadcasted_vote=not_broadcasted_vote,
251
+ use_stored_data=use_stored_data,
252
+ )
253
+
254
+ def sp_to_sbd(
255
+ self,
256
+ sp,
257
+ post_rshares=0,
258
+ voting_power=STEEM_100_PERCENT,
259
+ vote_pct=STEEM_100_PERCENT,
260
+ not_broadcasted_vote=True,
261
+ use_stored_data=True,
262
+ ):
263
+ """Obtain the resulting SBD vote value from Steem power
264
+
265
+ :param number steem_power: Steem Power
266
+ :param int post_rshares: rshares of post which is voted
267
+ :param int voting_power: voting power (100% = 10000)
268
+ :param int vote_pct: voting percentage (100% = 10000)
269
+ :param bool not_broadcasted_vote: not_broadcasted or already broadcasted vote (True = not_broadcasted vote).
270
+
271
+ Only impactful for very big votes. Slight modification to the value calculation, as the not_broadcasted
272
+ vote rshares decreases the reward pool.
273
+ """
274
+ vesting_shares = int(self.sp_to_vests(sp, use_stored_data=use_stored_data))
275
+ return self.vests_to_sbd(
276
+ vesting_shares,
277
+ post_rshares=post_rshares,
278
+ voting_power=voting_power,
279
+ vote_pct=vote_pct,
280
+ not_broadcasted_vote=not_broadcasted_vote,
281
+ use_stored_data=use_stored_data,
282
+ )
283
+
284
+ def vests_to_sbd(
285
+ self,
286
+ vests,
287
+ post_rshares=0,
288
+ voting_power=STEEM_100_PERCENT,
289
+ vote_pct=STEEM_100_PERCENT,
290
+ not_broadcasted_vote=True,
291
+ use_stored_data=True,
292
+ ):
293
+ """Obtain the resulting SBD vote value from vests
294
+
295
+ :param number vests: vesting shares
296
+ :param int post_rshares: rshares of post which is voted
297
+ :param int voting_power: voting power (100% = 10000)
298
+ :param int vote_pct: voting percentage (100% = 10000)
299
+ :param bool not_broadcasted_vote: not_broadcasted or already broadcasted vote (True = not_broadcasted vote).
300
+
301
+ Only impactful for very big votes. Slight modification to the value calculation, as the not_broadcasted
302
+ vote rshares decreases the reward pool.
303
+ """
304
+ vote_rshares = self.vests_to_rshares(
305
+ vests, post_rshares=post_rshares, voting_power=voting_power, vote_pct=vote_pct
306
+ )
307
+ return self.rshares_to_sbd(
308
+ vote_rshares, not_broadcasted_vote=not_broadcasted_vote, use_stored_data=use_stored_data
309
+ )
310
+
311
+ def _max_vote_denom(self, use_stored_data=True):
312
+ # get props
313
+ global_properties = self.get_dynamic_global_properties(use_stored_data=use_stored_data)
314
+ vote_power_reserve_rate = global_properties["vote_power_reserve_rate"]
315
+ max_vote_denom = vote_power_reserve_rate * STEEM_VOTE_REGENERATION_SECONDS
316
+ return max_vote_denom
317
+
318
+ def _calc_resulting_vote(
319
+ self, voting_power=STEEM_100_PERCENT, vote_pct=STEEM_100_PERCENT, use_stored_data=True
320
+ ):
321
+ # determine voting power used
322
+ used_power = int((voting_power * abs(vote_pct)) / STEEM_100_PERCENT * (60 * 60 * 24))
323
+ max_vote_denom = self._max_vote_denom(use_stored_data=use_stored_data)
324
+ used_power = int((used_power + max_vote_denom - 1) / max_vote_denom)
325
+ return used_power
326
+
327
+ def sp_to_rshares(
328
+ self,
329
+ steem_power,
330
+ post_rshares=0,
331
+ voting_power=STEEM_100_PERCENT,
332
+ vote_pct=STEEM_100_PERCENT,
333
+ use_stored_data=True,
334
+ ):
335
+ """Obtain the r-shares from Steem power
336
+
337
+ :param number steem_power: Steem Power
338
+ :param int post_rshares: rshares of post which is voted
339
+ :param int voting_power: voting power (100% = 10000)
340
+ :param int vote_pct: voting percentage (100% = 10000)
341
+
342
+ """
343
+ # calculate our account voting shares (from vests)
344
+ vesting_shares = int(self.sp_to_vests(steem_power, use_stored_data=use_stored_data))
345
+ return self.vests_to_rshares(
346
+ vesting_shares,
347
+ post_rshares=post_rshares,
348
+ voting_power=voting_power,
349
+ vote_pct=vote_pct,
350
+ use_stored_data=use_stored_data,
351
+ )
352
+
353
+ def vests_to_rshares(
354
+ self,
355
+ vests,
356
+ post_rshares=0,
357
+ voting_power=STEEM_100_PERCENT,
358
+ vote_pct=STEEM_100_PERCENT,
359
+ subtract_dust_threshold=True,
360
+ use_stored_data=True,
361
+ ):
362
+ """Obtain the r-shares from vests
363
+
364
+ :param number vests: vesting shares
365
+ :param int post_rshares: rshares of post which is voted
366
+ :param int voting_power: voting power (100% = 10000)
367
+ :param int vote_pct: voting percentage (100% = 10000)
368
+
369
+ """
370
+ used_power = self._calc_resulting_vote(
371
+ voting_power=voting_power, vote_pct=vote_pct, use_stored_data=use_stored_data
372
+ )
373
+ # calculate vote rshares
374
+ rshares = int(math.copysign(vests * 1e6 * used_power / STEEM_100_PERCENT, vote_pct))
375
+ if subtract_dust_threshold:
376
+ if abs(rshares) <= self.get_dust_threshold(use_stored_data=use_stored_data):
377
+ return 0
378
+ rshares -= math.copysign(
379
+ self.get_dust_threshold(use_stored_data=use_stored_data), vote_pct
380
+ )
381
+ rshares = self._calc_vote_claim(rshares, post_rshares)
382
+ return rshares
383
+
384
+ def sbd_to_rshares(self, sbd, not_broadcasted_vote=False, use_stored_data=True):
385
+ """Obtain the r-shares from SBD
386
+
387
+ :param sbd: SBD
388
+ :type sbd: str, int, amount.Amount
389
+ :param bool not_broadcasted_vote: not_broadcasted or already broadcasted vote (True = not_broadcasted vote).
390
+ Only impactful for very high amounts of SBD. Slight modification to the value calculation, as the not_broadcasted
391
+ vote rshares decreases the reward pool.
392
+
393
+ """
394
+ if isinstance(sbd, Amount):
395
+ sbd = Amount(sbd, blockchain_instance=self)
396
+ elif isinstance(sbd, string_types):
397
+ sbd = Amount(sbd, blockchain_instance=self)
398
+ else:
399
+ sbd = Amount(sbd, self.sbd_symbol, blockchain_instance=self)
400
+ if sbd["symbol"] != self.sbd_symbol:
401
+ raise AssertionError("Should input SBD, not any other asset!")
402
+
403
+ # If the vote was already broadcasted we can assume the blockchain values to be true
404
+ if not not_broadcasted_vote:
405
+ return int(float(sbd) / self.get_sbd_per_rshares(use_stored_data=use_stored_data))
406
+
407
+ # If the vote wasn't broadcasted (yet), we have to calculate the rshares while considering
408
+ # the change our vote is causing to the recent_claims. This is more important for really
409
+ # big votes which have a significant impact on the recent_claims.
410
+ reward_fund = self.get_reward_funds(use_stored_data=use_stored_data)
411
+ median_price = self.get_median_price(use_stored_data=use_stored_data)
412
+ recent_claims = int(reward_fund["recent_claims"])
413
+ reward_balance = Amount(reward_fund["reward_balance"], blockchain_instance=self)
414
+ reward_pool_sbd = median_price * reward_balance
415
+ if sbd > reward_pool_sbd:
416
+ raise ValueError("Provided more SBD than available in the reward pool.")
417
+
418
+ # This is the formula we can use to determine the "true" rshares.
419
+ # We get this formula by some math magic using the previous used formulas
420
+ # FundsPerShare = (balance / (claims + newShares)) * Price
421
+ # newShares = amount / FundsPerShare
422
+ # We can now resolve both formulas for FundsPerShare and set the formulas to be equal
423
+ # (balance / (claims + newShares)) * price = amount / newShares
424
+ # Now we resolve for newShares resulting in:
425
+ # newShares = claims * amount / (balance * price - amount)
426
+ rshares = (
427
+ recent_claims
428
+ * float(sbd)
429
+ / ((float(reward_balance) * float(median_price)) - float(sbd))
430
+ )
431
+ return int(rshares)
432
+
433
+ def rshares_to_vote_pct(
434
+ self,
435
+ rshares,
436
+ post_rshares=0,
437
+ steem_power=None,
438
+ vests=None,
439
+ voting_power=STEEM_100_PERCENT,
440
+ use_stored_data=True,
441
+ ):
442
+ """Obtain the voting percentage for a desired rshares value
443
+ for a given Steem Power or vesting shares and voting_power
444
+ Give either steem_power or vests, not both.
445
+ When the output is greater than 10000 or less than -10000,
446
+ the given absolute rshares are too high
447
+
448
+ Returns the required voting percentage (100% = 10000)
449
+
450
+ :param number rshares: desired rshares value
451
+ :param number steem_power: Steem Power
452
+ :param number vests: vesting shares
453
+ :param int voting_power: voting power (100% = 10000)
454
+
455
+ """
456
+ if steem_power is None and vests is None:
457
+ raise ValueError("Either steem_power or vests has to be set!")
458
+ if steem_power is not None and vests is not None:
459
+ raise ValueError("Either steem_power or vests has to be set. Not both!")
460
+ if steem_power is not None:
461
+ vests = int(self.sp_to_vests(steem_power, use_stored_data=use_stored_data) * 1e6)
462
+
463
+ if self.hardfork >= 20:
464
+ rshares += math.copysign(
465
+ self.get_dust_threshold(use_stored_data=use_stored_data), rshares
466
+ )
467
+
468
+ if post_rshares >= 0 and rshares > 0:
469
+ rshares = math.copysign(
470
+ self._calc_revert_vote_claim(abs(rshares), post_rshares), rshares
471
+ )
472
+ elif post_rshares < 0 and rshares < 0:
473
+ rshares = math.copysign(
474
+ self._calc_revert_vote_claim(abs(rshares), abs(post_rshares)), rshares
475
+ )
476
+ elif post_rshares < 0 and rshares > 0:
477
+ rshares = math.copysign(self._calc_revert_vote_claim(abs(rshares), 0), rshares)
478
+ elif post_rshares > 0 and rshares < 0:
479
+ rshares = math.copysign(
480
+ self._calc_revert_vote_claim(abs(rshares), post_rshares), rshares
481
+ )
482
+
483
+ max_vote_denom = self._max_vote_denom(use_stored_data=use_stored_data)
484
+
485
+ used_power = int(math.ceil(abs(rshares) * STEEM_100_PERCENT / vests))
486
+ used_power = used_power * max_vote_denom
487
+
488
+ vote_pct = used_power * STEEM_100_PERCENT / (60 * 60 * 24) / voting_power
489
+ return int(math.copysign(vote_pct, rshares))
490
+
491
+ def sbd_to_vote_pct(
492
+ self,
493
+ sbd,
494
+ post_rshares=0,
495
+ steem_power=None,
496
+ vests=None,
497
+ voting_power=STEEM_100_PERCENT,
498
+ not_broadcasted_vote=True,
499
+ use_stored_data=True,
500
+ ):
501
+ """Obtain the voting percentage for a desired SBD value
502
+ for a given Steem Power or vesting shares and voting power
503
+ Give either Steem Power or vests, not both.
504
+ When the output is greater than 10000 or smaller than -10000,
505
+ the SBD value is too high.
506
+
507
+ Returns the required voting percentage (100% = 10000)
508
+
509
+ :param sbd: desired SBD value
510
+ :type sbd: str, int, amount.Amount
511
+ :param number steem_power: Steem Power
512
+ :param number vests: vesting shares
513
+ :param bool not_broadcasted_vote: not_broadcasted or already broadcasted vote (True = not_broadcasted vote).
514
+ Only impactful for very high amounts of SBD. Slight modification to the value calculation, as the not_broadcasted
515
+ vote rshares decreases the reward pool.
516
+
517
+ """
518
+ if isinstance(sbd, Amount):
519
+ sbd = Amount(sbd, blockchain_instance=self)
520
+ elif isinstance(sbd, string_types):
521
+ sbd = Amount(sbd, blockchain_instance=self)
522
+ else:
523
+ sbd = Amount(sbd, self.sbd_symbol, blockchain_instance=self)
524
+ if sbd["symbol"] != self.sbd_symbol:
525
+ raise AssertionError()
526
+ rshares = self.sbd_to_rshares(
527
+ sbd, not_broadcasted_vote=not_broadcasted_vote, use_stored_data=use_stored_data
528
+ )
529
+ return self.rshares_to_vote_pct(
530
+ rshares,
531
+ post_rshares=post_rshares,
532
+ steem_power=steem_power,
533
+ vests=vests,
534
+ voting_power=voting_power,
535
+ use_stored_data=use_stored_data,
536
+ )
537
+
538
+ @property
539
+ def chain_params(self):
540
+ if self.offline or self.rpc is None:
541
+ return known_chains["STEEM"]
542
+ else:
543
+ return self.get_network()
544
+
545
+ @property
546
+ def hardfork(self):
547
+ if self.offline or self.rpc is None:
548
+ versions = known_chains["STEEM"]["min_version"]
549
+ else:
550
+ hf_prop = self.get_hardfork_properties()
551
+ if "current_hardfork_version" in hf_prop:
552
+ versions = hf_prop["current_hardfork_version"]
553
+ else:
554
+ versions = self.get_blockchain_version()
555
+ return int(versions.split(".")[1])
556
+
557
+ @property
558
+ def is_steem(self):
559
+ config = self.get_config()
560
+ if config is None:
561
+ return True
562
+ return "STEEM_CHAIN_ID" in self.get_config()
563
+
564
+ @property
565
+ def sbd_symbol(self):
566
+ """get the current chains symbol for SBD (e.g. "TBD" on testnet)"""
567
+ # some networks (e.g. whaleshares) do not have SBD
568
+ try:
569
+ symbol = self._get_asset_symbol(0)
570
+ except KeyError:
571
+ symbol = self._get_asset_symbol(1)
572
+ return symbol
573
+
574
+ @property
575
+ def steem_symbol(self):
576
+ """get the current chains symbol for STEEM (e.g. "TESTS" on testnet)"""
577
+ return self._get_asset_symbol(1)
578
+
579
+ @property
580
+ def vests_symbol(self):
581
+ """get the current chains symbol for VESTS"""
582
+ return self._get_asset_symbol(2)
nectar/storage.py ADDED
@@ -0,0 +1,53 @@
1
+ # -*- coding: utf-8 -*-
2
+ import logging
3
+
4
+ from .nodelist import NodeList
5
+
6
+ log = logging.getLogger(__name__)
7
+ log.setLevel(logging.DEBUG)
8
+ log.addHandler(logging.StreamHandler())
9
+ from nectarstorage import (
10
+ SqliteConfigurationStore,
11
+ SqliteEncryptedKeyStore,
12
+ )
13
+
14
+ timeformat = "%Y%m%d-%H%M%S"
15
+
16
+
17
+ def generate_config_store(config, blockchain="hive"):
18
+ #: Default configuration
19
+ nodelist = NodeList()
20
+ if blockchain == "hive":
21
+ nodes = nodelist.get_hive_nodes(testnet=False)
22
+ elif blockchain == "steem":
23
+ nodes = nodelist.get_steem_nodes(testnet=False)
24
+ else:
25
+ nodes = []
26
+
27
+ config.setdefault("node", nodes)
28
+ config.setdefault("default_chain", blockchain)
29
+ config.setdefault("password_storage", "environment")
30
+ config.setdefault("rpcpassword", "")
31
+ config.setdefault("rpcuser", "")
32
+ config.setdefault("order-expiration", 7 * 24 * 60 * 60)
33
+ config.setdefault("client_id", "")
34
+ config.setdefault("sc2_client_id", None)
35
+ config.setdefault("hs_client_id", None)
36
+ config.setdefault("hot_sign_redirect_uri", None)
37
+ config.setdefault("sc2_api_url", "https://api.steemconnect.com/api/")
38
+ config.setdefault("oauth_base_url", "https://api.steemconnect.com/oauth2/")
39
+ config.setdefault("hs_api_url", "https://hivesigner.com/api/")
40
+ config.setdefault("hs_oauth_base_url", "https://hivesigner.com/oauth2/")
41
+ config.setdefault("default_canonical_url", "https://hive.blog")
42
+ config.setdefault("default_path", "48'/13'/0'/0'/0'")
43
+ config.setdefault("use_condenser", True)
44
+ config.setdefault("use_tor", False)
45
+ return config
46
+
47
+
48
+ def get_default_config_store(*args, **kwargs):
49
+ return generate_config_store(SqliteConfigurationStore, blockchain="hive")(*args, **kwargs)
50
+
51
+
52
+ def get_default_key_store(config, *args, **kwargs):
53
+ return SqliteEncryptedKeyStore(config=config, **kwargs)