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/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
|