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/exceptions.py ADDED
@@ -0,0 +1,149 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+
4
+ class WalletExists(Exception):
5
+ """A wallet has already been created and requires a password to be
6
+ unlocked by means of :func:`nectar.wallet.Wallet.unlock`.
7
+ """
8
+
9
+ pass
10
+
11
+
12
+ class RPCConnectionRequired(Exception):
13
+ """An RPC connection is required"""
14
+
15
+ pass
16
+
17
+
18
+ class InvalidMemoKeyException(Exception):
19
+ """Memo key in message is invalid"""
20
+
21
+ pass
22
+
23
+
24
+ class WrongMemoKey(Exception):
25
+ """The memo provided is not equal the one on the blockchain"""
26
+
27
+ pass
28
+
29
+
30
+ class OfflineHasNoRPCException(Exception):
31
+ """When in offline mode, we don't have RPC"""
32
+
33
+ pass
34
+
35
+
36
+ class AccountExistsException(Exception):
37
+ """The requested account already exists"""
38
+
39
+ pass
40
+
41
+
42
+ class AccountDoesNotExistsException(Exception):
43
+ """The account does not exist"""
44
+
45
+ pass
46
+
47
+
48
+ class AssetDoesNotExistsException(Exception):
49
+ """The asset does not exist"""
50
+
51
+ pass
52
+
53
+
54
+ class InvalidAssetException(Exception):
55
+ """An invalid asset has been provided"""
56
+
57
+ pass
58
+
59
+
60
+ class InsufficientAuthorityError(Exception):
61
+ """The transaction requires signature of a higher authority"""
62
+
63
+ pass
64
+
65
+
66
+ class VotingInvalidOnArchivedPost(Exception):
67
+ """The transaction requires signature of a higher authority"""
68
+
69
+ pass
70
+
71
+
72
+ class MissingKeyError(Exception):
73
+ """A required key couldn't be found in the wallet"""
74
+
75
+ pass
76
+
77
+
78
+ class InvalidWifError(Exception):
79
+ """The provided private Key has an invalid format"""
80
+
81
+ pass
82
+
83
+
84
+ class BlockDoesNotExistsException(Exception):
85
+ """The block does not exist"""
86
+
87
+ pass
88
+
89
+
90
+ class NoWalletException(Exception):
91
+ """No Wallet could be found, please use :func:`nectar.wallet.Wallet.create` to
92
+ create a new wallet
93
+ """
94
+
95
+ pass
96
+
97
+
98
+ class WitnessDoesNotExistsException(Exception):
99
+ """The witness does not exist"""
100
+
101
+ pass
102
+
103
+
104
+ class ContentDoesNotExistsException(Exception):
105
+ """The content does not exist"""
106
+
107
+ pass
108
+
109
+
110
+ class VoteDoesNotExistsException(Exception):
111
+ """The vote does not exist"""
112
+
113
+ pass
114
+
115
+
116
+ class WrongMasterPasswordException(Exception):
117
+ """The password provided could not properly unlock the wallet"""
118
+
119
+ pass
120
+
121
+
122
+ class VestingBalanceDoesNotExistsException(Exception):
123
+ """Vesting Balance does not exist"""
124
+
125
+ pass
126
+
127
+
128
+ class InvalidMessageSignature(Exception):
129
+ """The message signature does not fit the message"""
130
+
131
+ pass
132
+
133
+
134
+ class NoWriteAccess(Exception):
135
+ """Cannot store to sqlite3 database due to missing write access"""
136
+
137
+ pass
138
+
139
+
140
+ class BatchedCallsNotSupported(Exception):
141
+ """Batch calls do not work"""
142
+
143
+ pass
144
+
145
+
146
+ class BlockWaitTimeExceeded(Exception):
147
+ """Wait time for new block exceeded"""
148
+
149
+ pass
nectar/hive.py ADDED
@@ -0,0 +1,546 @@
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
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 Hive(BlockChainInstance):
18
+ """Connect to the Hive 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_hs: When True, a hivesigner object is created. Can be used for
50
+ broadcast posting op or creating hot_links (default is False)
51
+ :param HiveSigner hivesigner: A HiveSigner object can be set manually, set use_hs 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 nectarlibs load the keys from the
57
+ locally stored wallet SQLite database (see ``storage.py``).
58
+ To use this mode, simply call ``Hive()`` 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 from
72
+ nectar.NodeList. Default settings can be changed with:
73
+
74
+ .. code-block:: python
75
+
76
+ hive = Hive(<host>)
77
+
78
+ where ``<host>`` starts with ``https://``, ``ws://`` or ``wss://``.
79
+
80
+ The purpose of this class it to simplify interaction with
81
+ Hive.
82
+
83
+ The idea is to have a class that allows to do this:
84
+
85
+ .. code-block:: python
86
+
87
+ >>> from nectar import Hive
88
+ >>> hive = Hive()
89
+ >>> print(hive.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 Hive
98
+ stm = Hive(node=["https://mytstnet.com"], custom_chains={"MYTESTNET":
99
+ {'chain_assets': [{'asset': 'HBD', 'id': 0, 'precision': 3, 'symbol': 'HBD'},
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["HIVE"]
125
+ try:
126
+ return self.rpc.get_network(props=config)
127
+ except:
128
+ return known_chains["HIVE"]
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_hbd(
134
+ rshares, not_broadcasted_vote=not_broadcasted_vote, use_stored_data=use_stored_data
135
+ )
136
+
137
+ def rshares_to_hbd(self, rshares, not_broadcasted_vote=False, use_stored_data=True):
138
+ """Calculates the current HBD value of a vote"""
139
+ payout = float(rshares) * self.get_hbd_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_hbd_per_rshares(self, not_broadcasted_vote_rshares=0, use_stored_data=True):
146
+ """Returns the current rshares to HBD 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
+ HBD_price = float(median_price * (Amount(1, self.hive_symbol, blockchain_instance=self)))
157
+ return fund_per_share * HBD_price
158
+
159
+ def get_token_per_mvest(self, time_stamp=None, use_stored_data=True):
160
+ return self.get_hive_per_mvest(time_stamp=time_stamp, use_stored_data=use_stored_data)
161
+
162
+ def get_hive_per_mvest(self, time_stamp=None, use_stored_data=True):
163
+ """Returns the MVEST to HIVE ratio
164
+
165
+ :param int time_stamp: (optional) if set, return an estimated
166
+ HIVE per MVEST ratio for the given time stamp. If unset the
167
+ current ratio is returned (default). (can also be a datetime object)
168
+ """
169
+ if self.offline and time_stamp is None:
170
+ time_stamp = datetime.now(timezone.utc)
171
+
172
+ if time_stamp is not None:
173
+ if isinstance(time_stamp, (datetime, date)):
174
+ time_stamp = formatToTimeStamp(time_stamp)
175
+ a = 2.1325476281078992e-05
176
+ b = -31099.685481490847
177
+ a2 = 2.9019227739473682e-07
178
+ b2 = 48.41432402074669
179
+
180
+ if time_stamp < (b2 - b) / (a - a2):
181
+ return a * time_stamp + b
182
+ else:
183
+ return a2 * time_stamp + b2
184
+ global_properties = self.get_dynamic_global_properties(use_stored_data=use_stored_data)
185
+ return float(
186
+ Amount(global_properties["total_vesting_fund_hive"], blockchain_instance=self)
187
+ ) / (
188
+ float(Amount(global_properties["total_vesting_shares"], blockchain_instance=self)) / 1e6
189
+ )
190
+
191
+ def vests_to_hp(self, vests, timestamp=None, use_stored_data=True):
192
+ """Converts vests to HP
193
+
194
+ :param amount.Amount vests/float vests: Vests to convert
195
+ :param int timestamp: (Optional) Can be used to calculate
196
+ the conversion rate from the past
197
+
198
+ """
199
+ if isinstance(vests, Amount):
200
+ vests = float(vests)
201
+ return (
202
+ float(vests) / 1e6 * self.get_hive_per_mvest(timestamp, use_stored_data=use_stored_data)
203
+ )
204
+
205
+ def vests_to_token_power(self, vests, timestamp=None, use_stored_data=True):
206
+ return self.vests_to_hp(vests, timestamp=timestamp, use_stored_data=use_stored_data)
207
+
208
+ def hp_to_vests(self, hp, timestamp=None, use_stored_data=True):
209
+ """Converts HP to vests
210
+
211
+ :param float hp: Hive power to convert
212
+ :param datetime timestamp: (Optional) Can be used to calculate
213
+ the conversion rate from the past
214
+ """
215
+ return hp * 1e6 / self.get_hive_per_mvest(timestamp, use_stored_data=use_stored_data)
216
+
217
+ def token_power_to_vests(self, token_power, timestamp=None, use_stored_data=True):
218
+ return self.hp_to_vests(token_power, timestamp=timestamp, use_stored_data=use_stored_data)
219
+
220
+ def token_power_to_token_backed_dollar(
221
+ self,
222
+ token_power,
223
+ post_rshares=0,
224
+ voting_power=STEEM_100_PERCENT,
225
+ vote_pct=STEEM_100_PERCENT,
226
+ not_broadcasted_vote=True,
227
+ use_stored_data=True,
228
+ ):
229
+ return self.hp_to_hbd(
230
+ token_power,
231
+ post_rshares=post_rshares,
232
+ voting_power=voting_power,
233
+ vote_pct=vote_pct,
234
+ not_broadcasted_vote=not_broadcasted_vote,
235
+ use_stored_data=use_stored_data,
236
+ )
237
+
238
+ def hp_to_hbd(
239
+ self,
240
+ hp,
241
+ post_rshares=0,
242
+ voting_power=STEEM_100_PERCENT,
243
+ vote_pct=STEEM_100_PERCENT,
244
+ not_broadcasted_vote=True,
245
+ use_stored_data=True,
246
+ ):
247
+ """Obtain the resulting HBD vote value from Hive power
248
+
249
+ :param number hive_power: Hive Power
250
+ :param int post_rshares: rshares of post which is voted
251
+ :param int voting_power: voting power (100% = 10000)
252
+ :param int vote_pct: voting percentage (100% = 10000)
253
+ :param bool not_broadcasted_vote: not_broadcasted or already broadcasted vote (True = not_broadcasted vote).
254
+
255
+ Only impactful for very big votes. Slight modification to the value calculation, as the not_broadcasted
256
+ vote rshares decreases the reward pool.
257
+ """
258
+ vesting_shares = int(self.hp_to_vests(hp, use_stored_data=use_stored_data))
259
+ return self.vests_to_hbd(
260
+ vesting_shares,
261
+ post_rshares=post_rshares,
262
+ voting_power=voting_power,
263
+ vote_pct=vote_pct,
264
+ not_broadcasted_vote=not_broadcasted_vote,
265
+ use_stored_data=use_stored_data,
266
+ )
267
+
268
+ def vests_to_hbd(
269
+ self,
270
+ vests,
271
+ post_rshares=0,
272
+ voting_power=STEEM_100_PERCENT,
273
+ vote_pct=STEEM_100_PERCENT,
274
+ not_broadcasted_vote=True,
275
+ use_stored_data=True,
276
+ ):
277
+ """Obtain the resulting HBD vote value from vests
278
+
279
+ :param number vests: vesting shares
280
+ :param int post_rshares: rshares of post which is voted
281
+ :param int voting_power: voting power (100% = 10000)
282
+ :param int vote_pct: voting percentage (100% = 10000)
283
+ :param bool not_broadcasted_vote: not_broadcasted or already broadcasted vote (True = not_broadcasted vote).
284
+
285
+ Only impactful for very big votes. Slight modification to the value calculation, as the not_broadcasted
286
+ vote rshares decreases the reward pool.
287
+ """
288
+ vote_rshares = self.vests_to_rshares(
289
+ vests, post_rshares=post_rshares, voting_power=voting_power, vote_pct=vote_pct
290
+ )
291
+ return self.rshares_to_hbd(
292
+ vote_rshares, not_broadcasted_vote=not_broadcasted_vote, use_stored_data=use_stored_data
293
+ )
294
+
295
+ def hp_to_rshares(
296
+ self,
297
+ hive_power,
298
+ post_rshares=0,
299
+ voting_power=STEEM_100_PERCENT,
300
+ vote_pct=STEEM_100_PERCENT,
301
+ use_stored_data=True,
302
+ ):
303
+ """Obtain the r-shares from Hive power
304
+
305
+ :param number hive_power: Hive Power
306
+ :param int post_rshares: rshares of post which is voted
307
+ :param int voting_power: voting power (100% = 10000)
308
+ :param int vote_pct: voting percentage (100% = 10000)
309
+
310
+ """
311
+ # calculate our account voting shares (from vests)
312
+ vesting_shares = int(self.hp_to_vests(hive_power, use_stored_data=use_stored_data))
313
+ rshares = self.vests_to_rshares(
314
+ vesting_shares,
315
+ post_rshares=post_rshares,
316
+ voting_power=voting_power,
317
+ vote_pct=vote_pct,
318
+ use_stored_data=use_stored_data,
319
+ )
320
+ return rshares
321
+
322
+ def vests_to_rshares(
323
+ self,
324
+ vests,
325
+ post_rshares=0,
326
+ voting_power=STEEM_100_PERCENT,
327
+ vote_pct=STEEM_100_PERCENT,
328
+ subtract_dust_threshold=True,
329
+ use_stored_data=True,
330
+ ):
331
+ """Obtain the r-shares from vests
332
+
333
+ :param number vests: vesting shares
334
+ :param int post_rshares: rshares of post which is voted
335
+ :param int voting_power: voting power (100% = 10000)
336
+ :param int vote_pct: voting percentage (100% = 10000)
337
+
338
+ """
339
+ used_power = self._calc_resulting_vote(
340
+ voting_power=voting_power, vote_pct=vote_pct, use_stored_data=use_stored_data
341
+ )
342
+ # calculate vote rshares
343
+ rshares = int(math.copysign(vests * 1e6 * used_power / STEEM_100_PERCENT, vote_pct))
344
+ if subtract_dust_threshold:
345
+ if abs(rshares) <= self.get_dust_threshold(use_stored_data=use_stored_data):
346
+ return 0
347
+ rshares -= math.copysign(
348
+ self.get_dust_threshold(use_stored_data=use_stored_data), vote_pct
349
+ )
350
+ rshares = self._calc_vote_claim(rshares, post_rshares)
351
+ return rshares
352
+
353
+ def hbd_to_rshares(self, hbd, not_broadcasted_vote=False, use_stored_data=True):
354
+ """Obtain the r-shares from HBD
355
+
356
+ :param hbd: HBD
357
+ :type hbd: str, int, amount.Amount
358
+ :param bool not_broadcasted_vote: not_broadcasted or already broadcasted vote (True = not_broadcasted vote).
359
+ Only impactful for very high amounts of HBD. Slight modification to the value calculation, as the not_broadcasted
360
+ vote rshares decreases the reward pool.
361
+
362
+ """
363
+ if isinstance(hbd, Amount):
364
+ hbd = Amount(hbd, blockchain_instance=self)
365
+ elif isinstance(hbd, string_types):
366
+ hbd = Amount(hbd, blockchain_instance=self)
367
+ else:
368
+ hbd = Amount(hbd, self.hbd_symbol, blockchain_instance=self)
369
+ if hbd["symbol"] != self.hbd_symbol:
370
+ raise AssertionError("Should input HBD, not any other asset!")
371
+
372
+ # If the vote was already broadcasted we can assume the blockchain values to be true
373
+ if not not_broadcasted_vote:
374
+ return int(float(hbd) / self.get_hbd_per_rshares(use_stored_data=use_stored_data))
375
+
376
+ # If the vote wasn't broadcasted (yet), we have to calculate the rshares while considering
377
+ # the change our vote is causing to the recent_claims. This is more important for really
378
+ # big votes which have a significant impact on the recent_claims.
379
+ reward_fund = self.get_reward_funds(use_stored_data=use_stored_data)
380
+ median_price = self.get_median_price(use_stored_data=use_stored_data)
381
+ recent_claims = int(reward_fund["recent_claims"])
382
+ reward_balance = Amount(reward_fund["reward_balance"], blockchain_instance=self)
383
+ reward_pool_hbd = median_price * reward_balance
384
+ if hbd > reward_pool_hbd:
385
+ raise ValueError("Provided more HBD than available in the reward pool.")
386
+
387
+ # This is the formula we can use to determine the "true" rshares.
388
+ # We get this formula by some math magic using the previous used formulas
389
+ # FundsPerShare = (balance / (claims + newShares)) * Price
390
+ # newShares = amount / FundsPerShare
391
+ # We can now resolve both formulas for FundsPerShare and set the formulas to be equal
392
+ # (balance / (claims + newShares)) * price = amount / newShares
393
+ # Now we resolve for newShares resulting in:
394
+ # newShares = claims * amount / (balance * price - amount)
395
+ rshares = (
396
+ recent_claims
397
+ * float(hbd)
398
+ / ((float(reward_balance) * float(median_price)) - float(hbd))
399
+ )
400
+ return int(rshares)
401
+
402
+ def rshares_to_vote_pct(
403
+ self,
404
+ rshares,
405
+ post_rshares=0,
406
+ hive_power=None,
407
+ vests=None,
408
+ voting_power=STEEM_100_PERCENT,
409
+ use_stored_data=True,
410
+ ):
411
+ """Obtain the voting percentage for a desired rshares value
412
+ for a given Hive Power or vesting shares and voting_power
413
+ Give either hive_power or vests, not both.
414
+ When the output is greater than 10000 or less than -10000,
415
+ the given absolute rshares are too high
416
+
417
+ Returns the required voting percentage (100% = 10000)
418
+
419
+ :param number rshares: desired rshares value
420
+ :param number hive_power: Hive Power
421
+ :param number vests: vesting shares
422
+ :param int voting_power: voting power (100% = 10000)
423
+
424
+ """
425
+ if hive_power is None and vests is None:
426
+ raise ValueError("Either hive_power or vests has to be set!")
427
+ if hive_power is not None and vests is not None:
428
+ raise ValueError("Either hive_power or vests has to be set. Not both!")
429
+ if hive_power is not None:
430
+ vests = int(self.hp_to_vests(hive_power, use_stored_data=use_stored_data) * 1e6)
431
+
432
+ if self.hardfork >= 20:
433
+ rshares += math.copysign(
434
+ self.get_dust_threshold(use_stored_data=use_stored_data), rshares
435
+ )
436
+
437
+ if post_rshares >= 0 and rshares > 0:
438
+ rshares = math.copysign(
439
+ self._calc_revert_vote_claim(abs(rshares), post_rshares), rshares
440
+ )
441
+ elif post_rshares < 0 and rshares < 0:
442
+ rshares = math.copysign(
443
+ self._calc_revert_vote_claim(abs(rshares), abs(post_rshares)), rshares
444
+ )
445
+ elif post_rshares < 0 and rshares > 0:
446
+ rshares = math.copysign(self._calc_revert_vote_claim(abs(rshares), 0), rshares)
447
+ elif post_rshares > 0 and rshares < 0:
448
+ rshares = math.copysign(
449
+ self._calc_revert_vote_claim(abs(rshares), post_rshares), rshares
450
+ )
451
+
452
+ max_vote_denom = self._max_vote_denom(use_stored_data=use_stored_data)
453
+
454
+ used_power = int(math.ceil(abs(rshares) * STEEM_100_PERCENT / vests))
455
+ used_power = used_power * max_vote_denom
456
+
457
+ vote_pct = used_power * STEEM_100_PERCENT / (60 * 60 * 24) / voting_power
458
+ return int(math.copysign(vote_pct, rshares))
459
+
460
+ def hbd_to_vote_pct(
461
+ self,
462
+ hbd,
463
+ post_rshares=0,
464
+ hive_power=None,
465
+ vests=None,
466
+ voting_power=STEEM_100_PERCENT,
467
+ not_broadcasted_vote=True,
468
+ use_stored_data=True,
469
+ ):
470
+ """Obtain the voting percentage for a desired HBD value
471
+ for a given Hive Power or vesting shares and voting power
472
+ Give either Hive Power or vests, not both.
473
+ When the output is greater than 10000 or smaller than -10000,
474
+ the HBD value is too high.
475
+
476
+ Returns the required voting percentage (100% = 10000)
477
+
478
+ :param hbd: desired HBD value
479
+ :type hbd: str, int, amount.Amount
480
+ :param number hive_power: Hive Power
481
+ :param number vests: vesting shares
482
+ :param bool not_broadcasted_vote: not_broadcasted or already broadcasted vote (True = not_broadcasted vote).
483
+ Only impactful for very high amounts of HBD. Slight modification to the value calculation, as the not_broadcasted
484
+ vote rshares decreases the reward pool.
485
+
486
+ """
487
+ if isinstance(hbd, Amount):
488
+ hbd = Amount(hbd, blockchain_instance=self)
489
+ elif isinstance(hbd, string_types):
490
+ hbd = Amount(hbd, blockchain_instance=self)
491
+ else:
492
+ hbd = Amount(hbd, self.hbd_symbol, blockchain_instance=self)
493
+ if hbd["symbol"] != self.hbd_symbol:
494
+ raise AssertionError()
495
+ rshares = self.hbd_to_rshares(
496
+ hbd, not_broadcasted_vote=not_broadcasted_vote, use_stored_data=use_stored_data
497
+ )
498
+ return self.rshares_to_vote_pct(
499
+ rshares,
500
+ post_rshares=post_rshares,
501
+ hive_power=hive_power,
502
+ vests=vests,
503
+ voting_power=voting_power,
504
+ use_stored_data=use_stored_data,
505
+ )
506
+
507
+ @property
508
+ def chain_params(self):
509
+ if self.offline or self.rpc is None:
510
+ return known_chains["HIVE"]
511
+ else:
512
+ return self.get_network()
513
+
514
+ @property
515
+ def hardfork(self):
516
+ if self.offline or self.rpc is None:
517
+ versions = known_chains["HIVE"]["min_version"]
518
+ else:
519
+ hf_prop = self.get_hardfork_properties()
520
+ if "current_hardfork_version" in hf_prop:
521
+ versions = hf_prop["current_hardfork_version"]
522
+ else:
523
+ versions = self.get_blockchain_version()
524
+ return int(versions.split(".")[1])
525
+
526
+ @property
527
+ def is_hive(self):
528
+ config = self.get_config()
529
+ if config is None:
530
+ return True
531
+ return "HIVE_CHAIN_ID" in self.get_config()
532
+
533
+ @property
534
+ def hbd_symbol(self):
535
+ """get the current chains symbol for HBD (e.g. "TBD" on testnet)"""
536
+ return self.backed_token_symbol
537
+
538
+ @property
539
+ def hive_symbol(self):
540
+ """get the current chains symbol for HIVE (e.g. "TESTS" on testnet)"""
541
+ return self.token_symbol
542
+
543
+ @property
544
+ def vests_symbol(self):
545
+ """get the current chains symbol for VESTS"""
546
+ return self.vest_token_symbol