hive-nectar 0.0.11__py3-none-any.whl → 0.1.0__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.11.dist-info → hive_nectar-0.1.0.dist-info}/METADATA +10 -11
- hive_nectar-0.1.0.dist-info/RECORD +88 -0
- nectar/__init__.py +1 -4
- nectar/account.py +791 -685
- nectar/amount.py +82 -21
- nectar/asset.py +1 -2
- nectar/block.py +34 -22
- nectar/blockchain.py +111 -143
- nectar/blockchaininstance.py +396 -247
- nectar/blockchainobject.py +33 -5
- nectar/cli.py +1058 -1349
- nectar/comment.py +313 -181
- nectar/community.py +39 -43
- nectar/constants.py +1 -14
- nectar/discussions.py +793 -139
- nectar/hive.py +137 -77
- nectar/hivesigner.py +106 -68
- nectar/imageuploader.py +33 -23
- nectar/instance.py +31 -79
- nectar/market.py +128 -264
- nectar/memo.py +40 -13
- nectar/message.py +23 -10
- nectar/nodelist.py +115 -81
- nectar/price.py +80 -61
- nectar/profile.py +6 -3
- nectar/rc.py +45 -25
- nectar/snapshot.py +285 -163
- nectar/storage.py +16 -5
- nectar/transactionbuilder.py +132 -41
- nectar/utils.py +37 -17
- nectar/version.py +1 -1
- nectar/vote.py +171 -30
- nectar/wallet.py +26 -19
- nectar/witness.py +153 -54
- nectarapi/graphenerpc.py +147 -133
- nectarapi/noderpc.py +12 -6
- nectarapi/rpcutils.py +12 -6
- nectarapi/version.py +1 -1
- nectarbase/ledgertransactions.py +24 -1
- nectarbase/objects.py +17 -6
- nectarbase/operations.py +160 -90
- nectarbase/signedtransactions.py +38 -2
- nectarbase/version.py +1 -1
- nectargraphenebase/account.py +295 -17
- nectargraphenebase/chains.py +0 -135
- nectargraphenebase/ecdsasig.py +152 -176
- nectargraphenebase/types.py +18 -4
- nectargraphenebase/unsignedtransactions.py +1 -1
- nectargraphenebase/version.py +1 -1
- hive_nectar-0.0.11.dist-info/RECORD +0 -91
- nectar/blurt.py +0 -562
- nectar/conveyor.py +0 -308
- nectar/steem.py +0 -581
- {hive_nectar-0.0.11.dist-info → hive_nectar-0.1.0.dist-info}/WHEEL +0 -0
- {hive_nectar-0.0.11.dist-info → hive_nectar-0.1.0.dist-info}/entry_points.txt +0 -0
- {hive_nectar-0.0.11.dist-info → hive_nectar-0.1.0.dist-info}/licenses/LICENSE.txt +0 -0
nectar/blockchaininstance.py
CHANGED
|
@@ -10,11 +10,11 @@ from datetime import datetime, timezone
|
|
|
10
10
|
from nectar.constants import (
|
|
11
11
|
CURVE_CONSTANT,
|
|
12
12
|
CURVE_CONSTANT_X4,
|
|
13
|
+
HIVE_1_PERCENT,
|
|
14
|
+
HIVE_100_PERCENT,
|
|
15
|
+
HIVE_RC_REGEN_TIME,
|
|
16
|
+
HIVE_VOTE_REGENERATION_SECONDS,
|
|
13
17
|
SQUARED_CURVE_CONSTANT,
|
|
14
|
-
STEEM_1_PERCENT,
|
|
15
|
-
STEEM_100_PERCENT,
|
|
16
|
-
STEEM_RC_REGEN_TIME,
|
|
17
|
-
STEEM_VOTE_REGENERATION_SECONDS,
|
|
18
18
|
)
|
|
19
19
|
from nectarapi.noderpc import NodeRPC
|
|
20
20
|
from nectarbase import operations
|
|
@@ -72,21 +72,21 @@ class BlockChainInstance(object):
|
|
|
72
72
|
NumRetriesReached is raised. Disabled for -1. (default is -1)
|
|
73
73
|
:param int num_retries_call: Repeat num_retries_call times a rpc call on node error (default is 5)
|
|
74
74
|
:param int timeout: Timeout setting for https nodes (default is 60)
|
|
75
|
-
:param bool
|
|
75
|
+
:param bool use_hs: When True, a HiveSigner object is created. Can be used for
|
|
76
76
|
broadcast posting op or creating hot_links (default is False)
|
|
77
|
-
:param
|
|
77
|
+
:param HiveSigner hivesigner: A HiveSigner object can be set manually, set use_hs to True
|
|
78
78
|
:param dict custom_chains: custom chain which should be added to the known chains
|
|
79
79
|
|
|
80
80
|
Three wallet operation modes are possible:
|
|
81
81
|
|
|
82
|
-
* **Wallet Database**: Here, the
|
|
82
|
+
* **Wallet Database**: Here, the nectar libraries load the keys from the
|
|
83
83
|
locally stored wallet SQLite database (see ``storage.py``).
|
|
84
|
-
To use this mode, simply call ``
|
|
84
|
+
To use this mode, simply call ``Hive()`` without the
|
|
85
85
|
``keys`` parameter
|
|
86
86
|
* **Providing Keys**: Here, you can provide the keys for
|
|
87
87
|
your accounts manually. All you need to do is add the wif
|
|
88
88
|
keys for the accounts you want to use as a simple array
|
|
89
|
-
using the ``keys`` parameter to ``
|
|
89
|
+
using the ``keys`` parameter to ``Hive()``.
|
|
90
90
|
* **Force keys**: This more is for advanced users and
|
|
91
91
|
requires that you know what you are doing. Here, the
|
|
92
92
|
``keys`` parameter is a dictionary that overwrite the
|
|
@@ -94,25 +94,25 @@ class BlockChainInstance(object):
|
|
|
94
94
|
any account. This mode is only used for *foreign*
|
|
95
95
|
signatures!
|
|
96
96
|
|
|
97
|
-
If no node is provided, it will connect to default nodes
|
|
98
|
-
|
|
97
|
+
If no node is provided, it will connect to the default Hive nodes.
|
|
98
|
+
Default settings can be changed with:
|
|
99
99
|
|
|
100
100
|
.. code-block:: python
|
|
101
101
|
|
|
102
|
-
|
|
102
|
+
hive = Hive(<host>)
|
|
103
103
|
|
|
104
104
|
where ``<host>`` starts with ``https://``, ``ws://`` or ``wss://``.
|
|
105
105
|
|
|
106
|
-
The purpose of this class
|
|
107
|
-
|
|
106
|
+
The purpose of this class is to simplify interaction with
|
|
107
|
+
Hive.
|
|
108
108
|
|
|
109
109
|
The idea is to have a class that allows to do this:
|
|
110
110
|
|
|
111
111
|
.. code-block:: python
|
|
112
112
|
|
|
113
|
-
>>> from nectar import
|
|
114
|
-
>>>
|
|
115
|
-
>>> print(
|
|
113
|
+
>>> from nectar import Hive
|
|
114
|
+
>>> hive = Hive()
|
|
115
|
+
>>> print(hive.get_blockchain_version()) # doctest: +SKIP
|
|
116
116
|
|
|
117
117
|
This class also deals with edits, votes and reading content.
|
|
118
118
|
|
|
@@ -120,10 +120,10 @@ class BlockChainInstance(object):
|
|
|
120
120
|
|
|
121
121
|
.. code-block:: python
|
|
122
122
|
|
|
123
|
-
from nectar import
|
|
124
|
-
|
|
125
|
-
{'chain_assets': [{'asset': '
|
|
126
|
-
{'asset': '
|
|
123
|
+
from nectar import Hive
|
|
124
|
+
hv = Hive(node=["https://mytstnet.com"], custom_chains={"MYTESTNET":
|
|
125
|
+
{'chain_assets': [{'asset': 'HBD', 'id': 0, 'precision': 3, 'symbol': 'HBD'},
|
|
126
|
+
{'asset': 'HIVE', 'id': 1, 'precision': 3, 'symbol': 'HIVE'},
|
|
127
127
|
{'asset': 'VESTS', 'id': 2, 'precision': 6, 'symbol': 'VESTS'}],
|
|
128
128
|
'chain_id': '79276aea5d4877d9a25892eaa01b0adf019d3e5cb12a97478df3298ccdd01674',
|
|
129
129
|
'min_version': '0.0.0',
|
|
@@ -142,38 +142,30 @@ class BlockChainInstance(object):
|
|
|
142
142
|
data_refresh_time_seconds=900,
|
|
143
143
|
**kwargs,
|
|
144
144
|
):
|
|
145
|
-
"""
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
:
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
:
|
|
168
|
-
|
|
169
|
-
:param int num_retries_call: Repeat num_retries_call times a rpc call on node error (default is 5)
|
|
170
|
-
:param int timeout: Timeout setting for https nodes (default is 60)
|
|
171
|
-
:param bool use_sc2: When True, a steemconnect object is created. Can be used for broadcast
|
|
172
|
-
posting op or creating hot_links (default is False)
|
|
173
|
-
:param SteemConnect steemconnect: A SteemConnect object can be set manually, set use_sc2 to True
|
|
174
|
-
:param bool use_ledger: When True, a ledger Nano S is used for signing
|
|
175
|
-
:param str path: bip32 path from which the pubkey is derived, when use_ledger is True
|
|
176
|
-
|
|
145
|
+
"""
|
|
146
|
+
Initialize the BlockChainInstance, set up connection (unless offline), load configuration, initialize caches and transaction buffers, and create the Wallet and optional HiveSigner/ledger signing support.
|
|
147
|
+
|
|
148
|
+
Parameters:
|
|
149
|
+
node (str): RPC node URL to connect to (optional; ignored if offline).
|
|
150
|
+
rpcuser (str), rpcpassword (str): Optional RPC credentials for the node.
|
|
151
|
+
data_refresh_time_seconds (int): Default cache refresh interval in seconds.
|
|
152
|
+
debug (bool): Enable debug mode.
|
|
153
|
+
**kwargs: Additional options (commonly used keys)
|
|
154
|
+
- offline (bool): If True, skip connecting to a node.
|
|
155
|
+
- nobroadcast (bool): If True, do not broadcast transactions.
|
|
156
|
+
- unsigned (bool): If True, do not sign transactions.
|
|
157
|
+
- expiration (int): Transaction expiration delay in seconds.
|
|
158
|
+
- bundle (bool): If True, enable bundling of operations instead of immediate broadcast.
|
|
159
|
+
- blocking (str|bool): Wait mode for broadcasts ("head" or "irreversible").
|
|
160
|
+
- custom_chains (dict): Custom chain definitions.
|
|
161
|
+
- use_hs (bool): If True, create and enable a HiveSigner instance.
|
|
162
|
+
- hivesigner (HiveSigner): Provide an existing HiveSigner instance (must be a HiveSigner).
|
|
163
|
+
- use_ledger (bool): If True, enable Ledger Nano signing.
|
|
164
|
+
- path (str): BIP32 path to derive pubkey from when using Ledger.
|
|
165
|
+
- config_store: Configuration store object (defaults to the global default).
|
|
166
|
+
|
|
167
|
+
Raises:
|
|
168
|
+
ValueError: If a provided `hivesigner` is not an instance of HiveSigner.
|
|
177
169
|
"""
|
|
178
170
|
|
|
179
171
|
self.rpc = None
|
|
@@ -184,8 +176,6 @@ class BlockChainInstance(object):
|
|
|
184
176
|
self.unsigned = bool(kwargs.get("unsigned", False))
|
|
185
177
|
self.expiration = int(kwargs.get("expiration", 30))
|
|
186
178
|
self.bundle = bool(kwargs.get("bundle", False))
|
|
187
|
-
self.steemconnect = kwargs.get("steemconnect", None)
|
|
188
|
-
self.use_sc2 = bool(kwargs.get("use_sc2", False))
|
|
189
179
|
self.hivesigner = kwargs.get("hivesigner", None)
|
|
190
180
|
self.use_hs = bool(kwargs.get("use_hs", False))
|
|
191
181
|
self.blocking = kwargs.get("blocking", False)
|
|
@@ -210,14 +200,10 @@ class BlockChainInstance(object):
|
|
|
210
200
|
|
|
211
201
|
self.wallet = Wallet(blockchain_instance=self, **kwargs)
|
|
212
202
|
|
|
213
|
-
# set
|
|
214
|
-
if self.steemconnect is not None and not isinstance(self.steemconnect, (HiveSigner)):
|
|
215
|
-
raise ValueError("steemconnect musst be SteemConnect object")
|
|
203
|
+
# set hivesigner
|
|
216
204
|
if self.hivesigner is not None and not isinstance(self.hivesigner, (HiveSigner)):
|
|
217
205
|
raise ValueError("hivesigner musst be HiveSigner object")
|
|
218
|
-
if self.
|
|
219
|
-
self.use_sc2 = True
|
|
220
|
-
elif self.hivesigner is None and self.use_hs:
|
|
206
|
+
if self.hivesigner is None and self.use_hs:
|
|
221
207
|
self.hivesigner = HiveSigner(blockchain_instance=self, **kwargs)
|
|
222
208
|
elif self.hivesigner is not None and not self.use_hs:
|
|
223
209
|
self.use_hs = True
|
|
@@ -226,7 +212,21 @@ class BlockChainInstance(object):
|
|
|
226
212
|
# Basic Calls
|
|
227
213
|
# -------------------------------------------------------------------------
|
|
228
214
|
def connect(self, node="", rpcuser="", rpcpassword="", **kwargs):
|
|
229
|
-
"""
|
|
215
|
+
"""
|
|
216
|
+
Connect to a Hive node and initialize the internal RPC client.
|
|
217
|
+
|
|
218
|
+
If node is empty, the method will attempt to use the configured default nodes; if none are available a ValueError is raised.
|
|
219
|
+
If rpcuser or rpcpassword are not provided, values are read from self.config when present. The config key "use_tor" (if set) will be used to enable Tor for the connection.
|
|
220
|
+
Any additional keyword arguments are forwarded to the NodeRPC constructor.
|
|
221
|
+
|
|
222
|
+
Parameters:
|
|
223
|
+
node (str | list): Node URL or list of node URLs to connect to. If omitted, default nodes are used.
|
|
224
|
+
rpcuser (str): Optional RPC username; falls back to self.config["rpcuser"] when not supplied.
|
|
225
|
+
rpcpassword (str): Optional RPC password; falls back to self.config["rpcpassword"] when not supplied.
|
|
226
|
+
|
|
227
|
+
Raises:
|
|
228
|
+
ValueError: If no node is provided and no default nodes are configured.
|
|
229
|
+
"""
|
|
230
230
|
if not node:
|
|
231
231
|
node = self.get_default_nodes()
|
|
232
232
|
if not bool(node):
|
|
@@ -262,7 +262,13 @@ class BlockChainInstance(object):
|
|
|
262
262
|
return "<%s, nobroadcast=%s>" % (self.__class__.__name__, str(self.nobroadcast))
|
|
263
263
|
|
|
264
264
|
def clear_data(self):
|
|
265
|
-
"""
|
|
265
|
+
"""
|
|
266
|
+
Reset the internal cache of blockchain-derived data.
|
|
267
|
+
|
|
268
|
+
This clears stored values used to cache node-dependent blockchain parameters (dynamic global properties, feed history,
|
|
269
|
+
hardfork properties, network info, witness schedule, config, reward funds) and their per-key refresh timestamps. It does
|
|
270
|
+
not affect network connection, wallet state, transaction buffers, or other non-cache attributes.
|
|
271
|
+
"""
|
|
266
272
|
self.data = {
|
|
267
273
|
"last_refresh": None,
|
|
268
274
|
"last_node": None,
|
|
@@ -284,12 +290,24 @@ class BlockChainInstance(object):
|
|
|
284
290
|
}
|
|
285
291
|
|
|
286
292
|
def refresh_data(self, chain_property, force_refresh=False, data_refresh_time_seconds=None):
|
|
287
|
-
"""
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
+
"""
|
|
294
|
+
Refresh and cache a specific blockchain data category in self.data.
|
|
295
|
+
|
|
296
|
+
This updates the cached value for the given chain_property (one of:
|
|
297
|
+
"dynamic_global_properties", "feed_history", "hardfork_properties",
|
|
298
|
+
"witness_schedule", "config", "reward_funds"). If the cached value was
|
|
299
|
+
refreshed recently (within self.data_refresh_time_seconds) and force_refresh
|
|
300
|
+
is False, the method will skip the RPC call. When online, timestamps
|
|
301
|
+
(last_refresh_*) and last_node are updated to reflect the refresh.
|
|
302
|
+
|
|
303
|
+
Parameters:
|
|
304
|
+
chain_property (str): The cache key to refresh; must be one of the supported properties.
|
|
305
|
+
force_refresh (bool): If True, bypass the time-based refresh guard and force an update.
|
|
306
|
+
data_refresh_time_seconds (float | None): If provided, set a new minimal refresh interval
|
|
307
|
+
(in seconds) before evaluating whether to skip refreshing.
|
|
308
|
+
|
|
309
|
+
Raises:
|
|
310
|
+
ValueError: If chain_property is not one of the supported keys.
|
|
293
311
|
"""
|
|
294
312
|
# if self.offline:
|
|
295
313
|
# return
|
|
@@ -611,12 +629,22 @@ class BlockChainInstance(object):
|
|
|
611
629
|
return self.rpc.get_resource_pool(api="rc")["resource_pool"]
|
|
612
630
|
|
|
613
631
|
def get_rc_cost(self, resource_count):
|
|
614
|
-
"""
|
|
632
|
+
"""
|
|
633
|
+
Compute the total Resource Credits (RC) cost for a set of resource usages.
|
|
634
|
+
|
|
635
|
+
This queries the current resource pool, price curve parameters, and dynamic global properties to compute the RC cost for each resource type in `resource_count` and returns their sum. If the RC regeneration rate is zero, returns 0.
|
|
636
|
+
|
|
637
|
+
Parameters:
|
|
638
|
+
resource_count (dict): Mapping of resource type keys to requested usage counts. Counts are interpreted in resource-specific units and will be scaled by the resource's `resource_unit` parameter.
|
|
639
|
+
|
|
640
|
+
Returns:
|
|
641
|
+
int: Total RC cost (rounded as produced by internal cost calculation).
|
|
642
|
+
"""
|
|
615
643
|
pools = self.get_resource_pool()
|
|
616
644
|
params = self.get_resource_params()
|
|
617
645
|
dyn_param = self.get_dynamic_global_properties()
|
|
618
646
|
rc_regen = int(Amount(dyn_param["total_vesting_shares"], blockchain_instance=self)) / (
|
|
619
|
-
|
|
647
|
+
HIVE_RC_REGEN_TIME / self.get_block_interval()
|
|
620
648
|
)
|
|
621
649
|
total_cost = 0
|
|
622
650
|
if rc_regen == 0:
|
|
@@ -645,16 +673,44 @@ class BlockChainInstance(object):
|
|
|
645
673
|
|
|
646
674
|
def _max_vote_denom(self, use_stored_data=True):
|
|
647
675
|
# get props
|
|
676
|
+
"""
|
|
677
|
+
Compute the maximum vote denominator used to scale voting power consumption.
|
|
678
|
+
|
|
679
|
+
This reads the current `vote_power_reserve_rate` from dynamic global properties
|
|
680
|
+
(and may use cached data when `use_stored_data` is True) and multiplies it by
|
|
681
|
+
HIVE_VOTE_REGENERATION_SECONDS to produce the denominator used in vote power
|
|
682
|
+
calculations.
|
|
683
|
+
|
|
684
|
+
Parameters:
|
|
685
|
+
use_stored_data (bool): If True, allow using cached dynamic global properties
|
|
686
|
+
rather than fetching fresh values from the node.
|
|
687
|
+
|
|
688
|
+
Returns:
|
|
689
|
+
int: The computed maximum vote denominator.
|
|
690
|
+
"""
|
|
648
691
|
global_properties = self.get_dynamic_global_properties(use_stored_data=use_stored_data)
|
|
649
692
|
vote_power_reserve_rate = global_properties["vote_power_reserve_rate"]
|
|
650
|
-
max_vote_denom = vote_power_reserve_rate *
|
|
693
|
+
max_vote_denom = vote_power_reserve_rate * HIVE_VOTE_REGENERATION_SECONDS
|
|
651
694
|
return max_vote_denom
|
|
652
695
|
|
|
653
696
|
def _calc_resulting_vote(
|
|
654
|
-
self, voting_power=
|
|
697
|
+
self, voting_power=HIVE_100_PERCENT, vote_pct=HIVE_100_PERCENT, use_stored_data=True
|
|
655
698
|
):
|
|
656
699
|
# determine voting power used
|
|
657
|
-
|
|
700
|
+
"""
|
|
701
|
+
Calculate the internal "used power" for a vote given current voting power and vote percentage.
|
|
702
|
+
|
|
703
|
+
This converts a voter's remaining voting_power and a requested vote_pct (both expressed on the same internal scale where HIVE_100_PERCENT represents 100%) into the integer unit the chain uses for vote consumption. The computation uses the absolute value of vote_pct, scales by a 24-hour factor (60*60*24), then normalizes by the chain's maximum vote denominator (retrieved via _max_vote_denom) with upward rounding.
|
|
704
|
+
|
|
705
|
+
Parameters:
|
|
706
|
+
voting_power (int): Current voting power expressed in the node's internal units (HIVE_100_PERCENT == full power).
|
|
707
|
+
vote_pct (int): Requested vote percentage on the same scale as voting_power (can be negative for downvotes).
|
|
708
|
+
use_stored_data (bool): If True, allow using cached chain parameters when determining the max vote denominator.
|
|
709
|
+
|
|
710
|
+
Returns:
|
|
711
|
+
int: The computed used voting power in the chain's internal units.
|
|
712
|
+
"""
|
|
713
|
+
used_power = int((voting_power * abs(vote_pct)) / HIVE_100_PERCENT * (60 * 60 * 24))
|
|
658
714
|
max_vote_denom = self._max_vote_denom(use_stored_data=use_stored_data)
|
|
659
715
|
used_power = int((used_power + max_vote_denom - 1) / max_vote_denom)
|
|
660
716
|
return used_power
|
|
@@ -696,23 +752,31 @@ class BlockChainInstance(object):
|
|
|
696
752
|
def vests_to_rshares(
|
|
697
753
|
self,
|
|
698
754
|
vests,
|
|
699
|
-
voting_power=
|
|
700
|
-
vote_pct=
|
|
755
|
+
voting_power=HIVE_100_PERCENT,
|
|
756
|
+
vote_pct=HIVE_100_PERCENT,
|
|
701
757
|
subtract_dust_threshold=True,
|
|
702
758
|
use_stored_data=True,
|
|
703
759
|
):
|
|
704
|
-
"""
|
|
760
|
+
"""
|
|
761
|
+
Convert vesting shares to reward r-shares used for voting.
|
|
705
762
|
|
|
706
|
-
|
|
707
|
-
:param int voting_power: voting power (100% = 10000)
|
|
708
|
-
:param int vote_pct: voting percentage (100% = 10000)
|
|
763
|
+
Calculates the signed r-shares produced by a vote from a given amount of vesting shares, taking into account current voting power and vote percentage. Optionally subtracts the chain's dust threshold so small votes become zero.
|
|
709
764
|
|
|
765
|
+
Parameters:
|
|
766
|
+
vests (float|int): Vesting shares (in VESTS units) to convert.
|
|
767
|
+
voting_power (int, optional): Voter's current voting power, where 100% == 10000. Defaults to HIVE_100_PERCENT.
|
|
768
|
+
vote_pct (int, optional): Intended vote strength, where 100% == 10000. Can be negative for downvotes. Defaults to HIVE_100_PERCENT.
|
|
769
|
+
subtract_dust_threshold (bool, optional): If True, subtract the chain's dust threshold from the absolute r-shares and return 0 when the result is at-or-below the threshold. Defaults to True.
|
|
770
|
+
use_stored_data (bool, optional): If True, prefer cached chain parameters when computing vote cost; otherwise fetch fresh values from the node. Defaults to True.
|
|
771
|
+
|
|
772
|
+
Returns:
|
|
773
|
+
int: Signed r-shares corresponding to the provided vesting shares and vote parameters. Returns 0 if the computed r-shares are at-or-below the dust threshold when subtraction is enabled.
|
|
710
774
|
"""
|
|
711
775
|
used_power = self._calc_resulting_vote(
|
|
712
776
|
voting_power=voting_power, vote_pct=vote_pct, use_stored_data=use_stored_data
|
|
713
777
|
)
|
|
714
778
|
# calculate vote rshares
|
|
715
|
-
rshares = int(math.copysign(vests * 1e6 * used_power /
|
|
779
|
+
rshares = int(math.copysign(vests * 1e6 * used_power / HIVE_100_PERCENT, vote_pct))
|
|
716
780
|
if subtract_dust_threshold:
|
|
717
781
|
if abs(rshares) <= self.get_dust_threshold(use_stored_data=use_stored_data):
|
|
718
782
|
return 0
|
|
@@ -759,35 +823,53 @@ class BlockChainInstance(object):
|
|
|
759
823
|
self,
|
|
760
824
|
token_power,
|
|
761
825
|
post_rshares=0,
|
|
762
|
-
voting_power=
|
|
763
|
-
vote_pct=
|
|
826
|
+
voting_power=HIVE_100_PERCENT,
|
|
827
|
+
vote_pct=HIVE_100_PERCENT,
|
|
764
828
|
not_broadcasted_vote=True,
|
|
765
829
|
use_stored_data=True,
|
|
766
830
|
):
|
|
767
|
-
"""
|
|
831
|
+
"""
|
|
832
|
+
Estimate the token-backed-dollar (HBD-like) value that a vote from the given token power would yield.
|
|
768
833
|
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
:param int vote_pct: voting percentage (100% = 10000)
|
|
773
|
-
:param bool not_broadcasted_vote: not_broadcasted or already broadcasted vote (True = not_broadcasted vote).
|
|
834
|
+
Calculates the expected payout (in the blockchain's backed token units) that a vote of `vote_pct` from an account
|
|
835
|
+
with `voting_power` and `token_power` would contribute to a post with `post_rshares`. The estimate accounts for
|
|
836
|
+
the vote rshares mechanics and the reduction of the reward pool when a not-yet-broadcast vote is included.
|
|
774
837
|
|
|
775
|
-
|
|
776
|
-
|
|
838
|
+
Parameters:
|
|
839
|
+
token_power (float): Voter's token power (in vest/token-equivalent units used by the chain).
|
|
840
|
+
post_rshares (int, optional): Current rshares of the post being voted on. Defaults to 0.
|
|
841
|
+
voting_power (int, optional): Voter's current voting power where 100% == HIVE_100_PERCENT (default full power).
|
|
842
|
+
vote_pct (int, optional): Vote percentage where 100% == HIVE_100_PERCENT (default full vote).
|
|
843
|
+
not_broadcasted_vote (bool, optional): If True, treat the vote as not yet broadcast (reduces available reward pool accordingly).
|
|
844
|
+
use_stored_data (bool, optional): If True, prefer cached chain parameters; otherwise fetch fresh values.
|
|
845
|
+
|
|
846
|
+
Returns:
|
|
847
|
+
float: Estimated payout denominated in the backed token (e.g., HBD).
|
|
848
|
+
|
|
849
|
+
Raises:
|
|
850
|
+
Exception: Not implemented (function is a placeholder).
|
|
777
851
|
"""
|
|
778
852
|
raise Exception("not implemented")
|
|
779
853
|
|
|
780
854
|
def get_chain_properties(self, use_stored_data=True):
|
|
781
|
-
"""
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
855
|
+
"""
|
|
856
|
+
Return the witness-elected chain properties (median_props) used by the network.
|
|
857
|
+
|
|
858
|
+
When cached data is allowed (use_stored_data=True) this reads from the instance cache
|
|
859
|
+
(populated by refresh_data). Otherwise it fetches the latest witness schedule and
|
|
860
|
+
returns its `median_props` object.
|
|
861
|
+
|
|
862
|
+
Parameters:
|
|
863
|
+
use_stored_data (bool): If True, return cached properties when available; if False,
|
|
864
|
+
force fetching the current witness schedule.
|
|
865
|
+
|
|
866
|
+
Returns:
|
|
867
|
+
dict: The `median_props` mapping, e.g.:
|
|
868
|
+
{
|
|
869
|
+
'account_creation_fee': '30.000 HIVE',
|
|
870
|
+
'maximum_block_size': 65536,
|
|
871
|
+
'hbd_interest_rate': 250
|
|
872
|
+
}
|
|
791
873
|
"""
|
|
792
874
|
if use_stored_data:
|
|
793
875
|
self.refresh_data("witness_schedule")
|
|
@@ -846,31 +928,50 @@ class BlockChainInstance(object):
|
|
|
846
928
|
|
|
847
929
|
@property
|
|
848
930
|
def is_hive(self):
|
|
849
|
-
|
|
850
|
-
if
|
|
851
|
-
return False
|
|
852
|
-
return "HIVE_CHAIN_ID" in config
|
|
931
|
+
"""
|
|
932
|
+
Return True if the connected chain appears to be Hive.
|
|
853
933
|
|
|
854
|
-
|
|
855
|
-
|
|
934
|
+
Checks the cached chain configuration and returns True when the key "HIVE_CHAIN_ID"
|
|
935
|
+
is present; returns False if configuration is unavailable or the key is absent.
|
|
936
|
+
"""
|
|
856
937
|
config = self.get_config(use_stored_data=True)
|
|
857
938
|
if config is None:
|
|
858
939
|
return False
|
|
859
|
-
return "
|
|
940
|
+
return "HIVE_CHAIN_ID" in config
|
|
860
941
|
|
|
861
942
|
def set_default_account(self, account):
|
|
862
|
-
"""
|
|
943
|
+
"""
|
|
944
|
+
Set the instance default account.
|
|
945
|
+
|
|
946
|
+
If given an account name or an Account object, validate/resolve it (an Account is
|
|
947
|
+
constructed with this blockchain instance) and store the account identifier in
|
|
948
|
+
the instance configuration under "default_account". This makes the account the
|
|
949
|
+
implicit default for subsequent operations that omit an explicit account.
|
|
950
|
+
|
|
951
|
+
Parameters:
|
|
952
|
+
account (str | Account): Account name or Account object to set as default.
|
|
953
|
+
|
|
954
|
+
Notes:
|
|
955
|
+
The Account constructor is invoked for validation; errors from account
|
|
956
|
+
resolution/lookup may propagate.
|
|
957
|
+
"""
|
|
863
958
|
Account(account, blockchain_instance=self)
|
|
864
959
|
self.config["default_account"] = account
|
|
865
960
|
|
|
866
961
|
def switch_blockchain(self, blockchain, update_nodes=False):
|
|
867
|
-
"""
|
|
962
|
+
"""
|
|
963
|
+
Switch the instance to the specified blockchain (Hive only).
|
|
868
964
|
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
965
|
+
If the requested blockchain is already the configured default and update_nodes is False, this is a no-op.
|
|
966
|
+
When update_nodes is True, the node list is refreshed via NodeList.update_nodes() and the default nodes
|
|
967
|
+
are replaced with the Hive node list. The instance's config["default_chain"] is updated and, if the
|
|
968
|
+
instance is not offline, a reconnect is attempted.
|
|
969
|
+
|
|
970
|
+
Parameters:
|
|
971
|
+
blockchain (str): Target blockchain; must be "hive".
|
|
972
|
+
update_nodes (bool): If True, refresh and replace the known node list before switching.
|
|
872
973
|
"""
|
|
873
|
-
assert blockchain in ["hive"
|
|
974
|
+
assert blockchain in ["hive"]
|
|
874
975
|
if blockchain == self.config["default_chain"] and not update_nodes:
|
|
875
976
|
return
|
|
876
977
|
from nectar.nodelist import NodeList
|
|
@@ -880,8 +981,6 @@ class BlockChainInstance(object):
|
|
|
880
981
|
nodelist.update_nodes()
|
|
881
982
|
if blockchain == "hive":
|
|
882
983
|
self.set_default_nodes(nodelist.get_hive_nodes())
|
|
883
|
-
else:
|
|
884
|
-
self.set_default_nodes(nodelist.get_steem_nodes())
|
|
885
984
|
self.config["default_chain"] = blockchain
|
|
886
985
|
if not self.offline:
|
|
887
986
|
self.connect(node="")
|
|
@@ -1015,19 +1114,18 @@ class BlockChainInstance(object):
|
|
|
1015
1114
|
return ret
|
|
1016
1115
|
|
|
1017
1116
|
def sign(self, tx=None, wifs=[], reconstruct_tx=True):
|
|
1018
|
-
"""
|
|
1117
|
+
"""
|
|
1118
|
+
Sign a transaction using provided WIFs or the wallet's missing signatures and return the signed transaction.
|
|
1019
1119
|
|
|
1020
|
-
|
|
1021
|
-
:param string wifs: One or many wif keys to use for signing
|
|
1022
|
-
a transaction. If not present, the keys will be loaded
|
|
1023
|
-
from the wallet as defined in "missing_signatures" key
|
|
1024
|
-
of the transactions.
|
|
1025
|
-
:param bool reconstruct_tx: when set to False and tx
|
|
1026
|
-
is already contructed, it will not reconstructed
|
|
1027
|
-
and already added signatures remain
|
|
1120
|
+
If tx is provided, it is wrapped in a TransactionBuilder; otherwise the instance's current txbuffer is used. Provided wifs (single string or list) are appended before missing required signatures are added. If reconstruct_tx is False and the transaction already contains signatures, it will not be reconstructed.
|
|
1028
1121
|
|
|
1029
|
-
|
|
1122
|
+
Parameters:
|
|
1123
|
+
tx (dict, optional): A transaction object to sign. If omitted, the active txbuffer is used.
|
|
1124
|
+
wifs (str | list[str], optional): One or more WIF private keys to use for signing. If not provided, keys from the wallet for any missing signatures are used.
|
|
1125
|
+
reconstruct_tx (bool, optional): If False, do not reconstruct an already-built transaction; existing signatures are preserved. Defaults to True.
|
|
1030
1126
|
|
|
1127
|
+
Returns:
|
|
1128
|
+
dict: The signed transaction JSON with an added "trx_id" field containing the transaction id.
|
|
1031
1129
|
"""
|
|
1032
1130
|
if tx:
|
|
1033
1131
|
txbuffer = TransactionBuilder(tx, blockchain_instance=self)
|
|
@@ -1041,7 +1139,7 @@ class BlockChainInstance(object):
|
|
|
1041
1139
|
return ret
|
|
1042
1140
|
|
|
1043
1141
|
def broadcast(self, tx=None, trx_id=True):
|
|
1044
|
-
"""Broadcast a transaction to the Hive
|
|
1142
|
+
"""Broadcast a transaction to the Hive network
|
|
1045
1143
|
|
|
1046
1144
|
:param tx tx: Signed transaction to broadcast
|
|
1047
1145
|
:param bool trx_id: when True, the trx_id will be included into the return dict.
|
|
@@ -1108,15 +1206,22 @@ class BlockChainInstance(object):
|
|
|
1108
1206
|
# Account related calls
|
|
1109
1207
|
# -------------------------------------------------------------------------
|
|
1110
1208
|
def claim_account(self, creator, fee=None, **kwargs):
|
|
1111
|
-
"""
|
|
1209
|
+
"""
|
|
1210
|
+
Claim a subsidized account slot or pay the account-creation fee.
|
|
1112
1211
|
|
|
1113
|
-
When fee is 0
|
|
1114
|
-
later
|
|
1115
|
-
|
|
1212
|
+
When `fee` is "0 <TOKEN>" (default), the claim consumes an account slot paid from RC (resource credits)
|
|
1213
|
+
allowing a later call to `create_claimed_account` to create the account. Supplying a nonzero `fee`
|
|
1214
|
+
will pay the registration fee in the chain token (e.g., HIVE).
|
|
1116
1215
|
|
|
1117
|
-
:
|
|
1118
|
-
|
|
1119
|
-
|
|
1216
|
+
Parameters:
|
|
1217
|
+
creator (str): Account that will pay or consume the claim (defaults to configured `default_account`).
|
|
1218
|
+
fee (str, optional): Fee as a string with asset symbol (e.g., "0 HIVE" or "3.000 HIVE"). If omitted, defaults to "0 <token_symbol>".
|
|
1219
|
+
|
|
1220
|
+
Returns:
|
|
1221
|
+
The result of finalizeOp for the submitted Claim_account operation (signed/broadcast transaction or unsigned/buffered result, depending on instance configuration).
|
|
1222
|
+
|
|
1223
|
+
Raises:
|
|
1224
|
+
ValueError: If no `creator` is provided and no `default_account` is configured.
|
|
1120
1225
|
"""
|
|
1121
1226
|
fee = fee if fee is not None else "0 %s" % (self.token_symbol)
|
|
1122
1227
|
if not creator and self.config["default_account"]:
|
|
@@ -1158,7 +1263,7 @@ class BlockChainInstance(object):
|
|
|
1158
1263
|
fee=None,
|
|
1159
1264
|
**kwargs,
|
|
1160
1265
|
):
|
|
1161
|
-
"""Create new claimed account on
|
|
1266
|
+
"""Create new claimed account on Hive
|
|
1162
1267
|
|
|
1163
1268
|
The brainkey/password can be used to recover all generated keys
|
|
1164
1269
|
(see :class:`nectargraphenebase.account` for more details.
|
|
@@ -1360,7 +1465,7 @@ class BlockChainInstance(object):
|
|
|
1360
1465
|
json_meta=None,
|
|
1361
1466
|
**kwargs,
|
|
1362
1467
|
):
|
|
1363
|
-
"""Create new account on Hive
|
|
1468
|
+
"""Create new account on Hive
|
|
1364
1469
|
|
|
1365
1470
|
The brainkey/password can be used to recover all generated keys
|
|
1366
1471
|
(see :class:`nectargraphenebase.account` for more details.
|
|
@@ -1499,13 +1604,11 @@ class BlockChainInstance(object):
|
|
|
1499
1604
|
|
|
1500
1605
|
props = self.get_chain_properties()
|
|
1501
1606
|
if self.hardfork >= 20:
|
|
1502
|
-
|
|
1607
|
+
required_fee = Amount(props["account_creation_fee"], blockchain_instance=self)
|
|
1503
1608
|
else:
|
|
1504
|
-
|
|
1505
|
-
Amount(props["account_creation_fee"], blockchain_instance=self) * 30
|
|
1506
|
-
)
|
|
1609
|
+
required_fee = Amount(props["account_creation_fee"], blockchain_instance=self) * 30
|
|
1507
1610
|
op = {
|
|
1508
|
-
"fee":
|
|
1611
|
+
"fee": required_fee,
|
|
1509
1612
|
"creator": creator["name"],
|
|
1510
1613
|
"new_account_name": account_name,
|
|
1511
1614
|
"owner": {
|
|
@@ -1752,21 +1855,29 @@ class BlockChainInstance(object):
|
|
|
1752
1855
|
return tb.broadcast()
|
|
1753
1856
|
|
|
1754
1857
|
def witness_update(self, signing_key, url, props, account=None, **kwargs):
|
|
1755
|
-
"""
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
:
|
|
1858
|
+
"""
|
|
1859
|
+
Create or update a witness (register or modify a block producer).
|
|
1860
|
+
|
|
1861
|
+
Creates a Witness_update operation for the given account with the provided signing key, node URL, and witness properties, then finalizes (signs/broadcasts or returns) the operation via the transaction pipeline.
|
|
1862
|
+
|
|
1863
|
+
Parameters:
|
|
1864
|
+
signing_key (str): Witness block signing public key (must be valid for the chain prefix).
|
|
1865
|
+
url (str): URL for the witness (website or endpoint).
|
|
1866
|
+
props (dict): Witness properties, e.g.:
|
|
1867
|
+
{
|
|
1868
|
+
"account_creation_fee": "3.000 HIVE",
|
|
1869
|
+
"maximum_block_size": 65536,
|
|
1870
|
+
"hbd_interest_rate": 0,
|
|
1871
|
+
}
|
|
1872
|
+
The "account_creation_fee" value will be converted to an Amount if present.
|
|
1873
|
+
account (str, optional): Witness account name. If omitted, the instance default_account config is used.
|
|
1761
1874
|
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
{
|
|
1765
|
-
"account_creation_fee": "3.000 STEEM",
|
|
1766
|
-
"maximum_block_size": 65536,
|
|
1767
|
-
"sbd_interest_rate": 0,
|
|
1768
|
-
}
|
|
1875
|
+
Returns:
|
|
1876
|
+
The value returned by finalizeOp (typically a transaction/broadcast result or a transaction builder when unsigned/bundled).
|
|
1769
1877
|
|
|
1878
|
+
Raises:
|
|
1879
|
+
ValueError: If no account is provided or resolvable.
|
|
1880
|
+
Exception: If the signing_key is not a valid public key for the chain prefix (propagates the underlying PublicKey error).
|
|
1770
1881
|
"""
|
|
1771
1882
|
if not account and self.config["default_account"]:
|
|
1772
1883
|
account = self.config["default_account"]
|
|
@@ -1842,23 +1953,20 @@ class BlockChainInstance(object):
|
|
|
1842
1953
|
raise ValueError("Cannot have threshold of 0")
|
|
1843
1954
|
|
|
1844
1955
|
def custom_json(self, id, json_data, required_auths=[], required_posting_auths=[], **kwargs):
|
|
1845
|
-
"""
|
|
1846
|
-
|
|
1847
|
-
:param str id: identifier for the custom json (max length 32 bytes)
|
|
1848
|
-
:param json json_data: the json data to put into the custom_json
|
|
1849
|
-
operation
|
|
1850
|
-
:param list required_auths: (optional) required auths
|
|
1851
|
-
:param list required_posting_auths: (optional) posting auths
|
|
1852
|
-
|
|
1853
|
-
.. note:: While reqired auths and required_posting_auths are both
|
|
1854
|
-
optional, one of the two are needed in order to send the custom
|
|
1855
|
-
json.
|
|
1956
|
+
"""
|
|
1957
|
+
Create and submit a Custom_json operation.
|
|
1856
1958
|
|
|
1857
|
-
|
|
1959
|
+
Parameters:
|
|
1960
|
+
id (str): Identifier for the custom JSON (max 32 bytes).
|
|
1961
|
+
json_data: JSON-serializable payload to include in the operation.
|
|
1962
|
+
required_auths (list): Accounts that must authorize with active permission. If non-empty, the operation will be finalized using active permission.
|
|
1963
|
+
required_posting_auths (list): Accounts that must authorize with posting permission. Used when `required_auths` is empty.
|
|
1858
1964
|
|
|
1859
|
-
|
|
1860
|
-
|
|
1965
|
+
Returns:
|
|
1966
|
+
The result returned by finalizeOp (signed and/or broadcast transaction), which may vary based on the instance configuration (e.g., unsigned, nobroadcast, bundle).
|
|
1861
1967
|
|
|
1968
|
+
Raises:
|
|
1969
|
+
Exception: If neither `required_auths` nor `required_posting_auths` contains an account.
|
|
1862
1970
|
"""
|
|
1863
1971
|
account = None
|
|
1864
1972
|
if len(required_auths):
|
|
@@ -1924,8 +2032,8 @@ class BlockChainInstance(object):
|
|
|
1924
2032
|
Example::
|
|
1925
2033
|
|
|
1926
2034
|
comment_options = {
|
|
1927
|
-
'max_accepted_payout': '1000000.000
|
|
1928
|
-
'
|
|
2035
|
+
'max_accepted_payout': '1000000.000 HBD',
|
|
2036
|
+
'percent_hbd': 10000,
|
|
1929
2037
|
'allow_votes': True,
|
|
1930
2038
|
'allow_curation_rewards': True,
|
|
1931
2039
|
'extensions': [[0, {
|
|
@@ -1998,9 +2106,21 @@ class BlockChainInstance(object):
|
|
|
1998
2106
|
return list(dict.fromkeys(urls))
|
|
1999
2107
|
|
|
2000
2108
|
def get_users(mdstring):
|
|
2109
|
+
"""
|
|
2110
|
+
Extract usernames mentioned in a Markdown string.
|
|
2111
|
+
|
|
2112
|
+
Searches mdstring for @-mentions (ASCII @ or fullwidth @) and returns the usernames found in order of appearance.
|
|
2113
|
+
Usernames must start with a lowercase ASCII letter, may contain lowercase letters, digits, hyphens, dots (including fullwidth dot), and must end with a letter or digit.
|
|
2114
|
+
|
|
2115
|
+
Parameters:
|
|
2116
|
+
mdstring (str): Text to scan for @-mentions.
|
|
2117
|
+
|
|
2118
|
+
Returns:
|
|
2119
|
+
list[str]: List of matched username strings in the order they were found (may contain duplicates).
|
|
2120
|
+
"""
|
|
2001
2121
|
users = []
|
|
2002
2122
|
for u in re.findall(
|
|
2003
|
-
r"(^|[^a-zA-Z0-9_
|
|
2123
|
+
r"(^|[^a-zA-Z0-9_!#$%&*@@/]|(^|[^a-zA-Z0-9_+~.-/#]))[@@]([a-z][-.a-z\d]+[a-z\d])",
|
|
2004
2124
|
mdstring,
|
|
2005
2125
|
):
|
|
2006
2126
|
users.append(list(u)[-1])
|
|
@@ -2095,7 +2215,7 @@ class BlockChainInstance(object):
|
|
|
2095
2215
|
"voter": account["name"],
|
|
2096
2216
|
"author": account["name"],
|
|
2097
2217
|
"permlink": permlink,
|
|
2098
|
-
"weight":
|
|
2218
|
+
"weight": HIVE_100_PERCENT,
|
|
2099
2219
|
}
|
|
2100
2220
|
)
|
|
2101
2221
|
ops.append(vote_op)
|
|
@@ -2103,15 +2223,21 @@ class BlockChainInstance(object):
|
|
|
2103
2223
|
return self.finalizeOp(ops, account, "posting", **kwargs)
|
|
2104
2224
|
|
|
2105
2225
|
def vote(self, weight, identifier, account=None, **kwargs):
|
|
2106
|
-
"""
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
:
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2226
|
+
"""
|
|
2227
|
+
Cast a vote on a post.
|
|
2228
|
+
|
|
2229
|
+
Parameters:
|
|
2230
|
+
weight (float): Vote weight in percent, range -100.0 to 100.0. This is
|
|
2231
|
+
converted to the chain's internal weight units (multiplied by
|
|
2232
|
+
HIVE_1_PERCENT) and clamped to the allowed range.
|
|
2233
|
+
identifier (str): Post identifier in the form "@author/permlink".
|
|
2234
|
+
account (str, optional): Name of the account to use for voting. If not
|
|
2235
|
+
provided, the instance's `default_account` from config is used. A
|
|
2236
|
+
ValueError is raised if no account can be determined.
|
|
2237
|
+
|
|
2238
|
+
Returns:
|
|
2239
|
+
The result from finalizeOp (operation signing/broadcast buffer or broadcast
|
|
2240
|
+
response) after creating a Vote operation using posting permission.
|
|
2115
2241
|
"""
|
|
2116
2242
|
if not account:
|
|
2117
2243
|
if "default_account" in self.config:
|
|
@@ -2122,11 +2248,11 @@ class BlockChainInstance(object):
|
|
|
2122
2248
|
|
|
2123
2249
|
[post_author, post_permlink] = resolve_authorperm(identifier)
|
|
2124
2250
|
|
|
2125
|
-
vote_weight = int(float(weight) *
|
|
2126
|
-
if vote_weight >
|
|
2127
|
-
vote_weight =
|
|
2128
|
-
if vote_weight < -
|
|
2129
|
-
vote_weight = -
|
|
2251
|
+
vote_weight = int(float(weight) * HIVE_1_PERCENT)
|
|
2252
|
+
if vote_weight > HIVE_100_PERCENT:
|
|
2253
|
+
vote_weight = HIVE_100_PERCENT
|
|
2254
|
+
if vote_weight < -HIVE_100_PERCENT:
|
|
2255
|
+
vote_weight = -HIVE_100_PERCENT
|
|
2130
2256
|
|
|
2131
2257
|
op = operations.Vote(
|
|
2132
2258
|
**{
|
|
@@ -2140,25 +2266,26 @@ class BlockChainInstance(object):
|
|
|
2140
2266
|
return self.finalizeOp(op, account, "posting", **kwargs)
|
|
2141
2267
|
|
|
2142
2268
|
def comment_options(self, options, identifier, beneficiaries=[], account=None, **kwargs):
|
|
2143
|
-
"""
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
:
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2269
|
+
"""
|
|
2270
|
+
Set comment/post options for a post (Comment_options operation) and submit the operation.
|
|
2271
|
+
|
|
2272
|
+
Parameters:
|
|
2273
|
+
options (dict): Comment options to set. Common keys include:
|
|
2274
|
+
- max_accepted_payout (str): e.g. "1000000.000 HBD"
|
|
2275
|
+
- percent_hbd (int): e.g. 10000 for 100%
|
|
2276
|
+
- allow_votes (bool)
|
|
2277
|
+
- allow_curation_rewards (bool)
|
|
2278
|
+
Other valid keys accepted by the chain's Comment_options operation are supported.
|
|
2279
|
+
identifier (str): Post identifier in the form "author/permlink" or a permlink for the default author.
|
|
2280
|
+
beneficiaries (list): Optional list of beneficiaries (each entry typically a dict with `account` and `weight`).
|
|
2281
|
+
account (str): Account that authorizes this operation; defaults to the instance's `default_account` if not provided.
|
|
2282
|
+
**kwargs: Additional keyword arguments forwarded to finalizeOp (e.g., broadcast/signing options).
|
|
2283
|
+
|
|
2284
|
+
Returns:
|
|
2285
|
+
The result of finalizeOp for the created Comment_options operation (signed/broadcasted transaction or unsigned buffer), depending on instance configuration.
|
|
2286
|
+
|
|
2287
|
+
Raises:
|
|
2288
|
+
ValueError: If no account is provided and no default account is configured.
|
|
2162
2289
|
"""
|
|
2163
2290
|
if not account and self.config["default_account"]:
|
|
2164
2291
|
account = self.config["default_account"]
|
|
@@ -2170,11 +2297,31 @@ class BlockChainInstance(object):
|
|
|
2170
2297
|
return self.finalizeOp(op, account, "posting", **kwargs)
|
|
2171
2298
|
|
|
2172
2299
|
def _build_comment_options_op(self, author, permlink, options, beneficiaries):
|
|
2300
|
+
"""
|
|
2301
|
+
Build and return a Comment_options operation for a post, validating and normalizing provided options and beneficiaries.
|
|
2302
|
+
|
|
2303
|
+
Parameters:
|
|
2304
|
+
author (str): The post author's account name.
|
|
2305
|
+
permlink (str): The permlink of the post to set options for.
|
|
2306
|
+
options (dict): Optional comment options; supported keys include
|
|
2307
|
+
"max_accepted_payout", "percent_hbd", "allow_votes",
|
|
2308
|
+
"allow_curation_rewards", and "extensions". Keys not listed are removed.
|
|
2309
|
+
beneficiaries (list): Optional list of beneficiary dicts, each with
|
|
2310
|
+
"account" (str) and optional "weight" (int, 1..HIVE_100_PERCENT). If provided,
|
|
2311
|
+
beneficiaries override any beneficiaries in `options`.
|
|
2312
|
+
|
|
2313
|
+
Returns:
|
|
2314
|
+
operations.Comment_options: A Comment_options operation ready to be appended to a transaction.
|
|
2315
|
+
|
|
2316
|
+
Raises:
|
|
2317
|
+
ValueError: If a beneficiary is missing the "account" field, has an account name
|
|
2318
|
+
longer than 16 characters, has an invalid weight (not in 1..HIVE_100_PERCENT),
|
|
2319
|
+
or if the sum of beneficiary weights exceeds HIVE_100_PERCENT.
|
|
2320
|
+
"""
|
|
2173
2321
|
options = remove_from_dict(
|
|
2174
2322
|
options or {},
|
|
2175
2323
|
[
|
|
2176
2324
|
"max_accepted_payout",
|
|
2177
|
-
"percent_steem_dollars",
|
|
2178
2325
|
"percent_hbd",
|
|
2179
2326
|
"allow_votes",
|
|
2180
2327
|
"allow_curation_rewards",
|
|
@@ -2192,53 +2339,41 @@ class BlockChainInstance(object):
|
|
|
2192
2339
|
if "account" not in b:
|
|
2193
2340
|
raise ValueError("beneficiaries need an account field!")
|
|
2194
2341
|
if "weight" not in b:
|
|
2195
|
-
b["weight"] =
|
|
2342
|
+
b["weight"] = HIVE_100_PERCENT
|
|
2196
2343
|
if len(b["account"]) > 16:
|
|
2197
2344
|
raise ValueError("beneficiaries error, account name length >16!")
|
|
2198
|
-
if b["weight"] < 1 or b["weight"] >
|
|
2199
|
-
raise ValueError("beneficiaries error, 1<=weight<=%s!" % (
|
|
2345
|
+
if b["weight"] < 1 or b["weight"] > HIVE_100_PERCENT:
|
|
2346
|
+
raise ValueError("beneficiaries error, 1<=weight<=%s!" % (HIVE_100_PERCENT))
|
|
2200
2347
|
weight_sum += b["weight"]
|
|
2201
2348
|
|
|
2202
|
-
if weight_sum >
|
|
2203
|
-
raise ValueError("beneficiaries exceed total weight limit %s" %
|
|
2349
|
+
if weight_sum > HIVE_100_PERCENT:
|
|
2350
|
+
raise ValueError("beneficiaries exceed total weight limit %s" % HIVE_100_PERCENT)
|
|
2204
2351
|
|
|
2205
2352
|
options["beneficiaries"] = beneficiaries
|
|
2206
2353
|
|
|
2207
2354
|
default_max_payout = "1000000.000 %s" % (self.backed_token_symbol)
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
)
|
|
2222
|
-
else:
|
|
2223
|
-
comment_op = operations.Comment_options(
|
|
2224
|
-
**{
|
|
2225
|
-
"author": author,
|
|
2226
|
-
"permlink": permlink,
|
|
2227
|
-
"max_accepted_payout": options.get("max_accepted_payout", default_max_payout),
|
|
2228
|
-
"percent_steem_dollars": int(
|
|
2229
|
-
options.get("percent_steem_dollars", STEEM_100_PERCENT)
|
|
2230
|
-
),
|
|
2231
|
-
"allow_votes": options.get("allow_votes", True),
|
|
2232
|
-
"allow_curation_rewards": options.get("allow_curation_rewards", True),
|
|
2233
|
-
"extensions": options.get("extensions", []),
|
|
2234
|
-
"beneficiaries": options.get("beneficiaries", []),
|
|
2235
|
-
"prefix": self.prefix,
|
|
2236
|
-
}
|
|
2237
|
-
)
|
|
2355
|
+
comment_op = operations.Comment_options(
|
|
2356
|
+
**{
|
|
2357
|
+
"author": author,
|
|
2358
|
+
"permlink": permlink,
|
|
2359
|
+
"max_accepted_payout": options.get("max_accepted_payout", default_max_payout),
|
|
2360
|
+
"percent_hbd": int(options.get("percent_hbd", HIVE_100_PERCENT)),
|
|
2361
|
+
"allow_votes": options.get("allow_votes", True),
|
|
2362
|
+
"allow_curation_rewards": options.get("allow_curation_rewards", True),
|
|
2363
|
+
"extensions": options.get("extensions", []),
|
|
2364
|
+
"beneficiaries": options.get("beneficiaries", []),
|
|
2365
|
+
"prefix": self.prefix,
|
|
2366
|
+
}
|
|
2367
|
+
)
|
|
2238
2368
|
return comment_op
|
|
2239
2369
|
|
|
2240
2370
|
def get_api_methods(self):
|
|
2241
|
-
"""
|
|
2371
|
+
"""
|
|
2372
|
+
Return the list of all JSON-RPC API methods supported by the connected node.
|
|
2373
|
+
|
|
2374
|
+
Returns:
|
|
2375
|
+
list: Method names (strings) provided by the node's JSON-RPC API.
|
|
2376
|
+
"""
|
|
2242
2377
|
return self.rpc.get_methods(api="jsonrpc")
|
|
2243
2378
|
|
|
2244
2379
|
def get_apis(self):
|
|
@@ -2252,10 +2387,20 @@ class BlockChainInstance(object):
|
|
|
2252
2387
|
return api_list
|
|
2253
2388
|
|
|
2254
2389
|
def _get_asset_symbol(self, asset_id):
|
|
2255
|
-
"""
|
|
2390
|
+
"""
|
|
2391
|
+
Return the asset symbol for a given asset id.
|
|
2392
|
+
|
|
2393
|
+
Asset ids are looked up in self.chain_params["chain_assets"]. Common mappings include
|
|
2394
|
+
0 -> HBD, 1 -> HIVE, 2 -> VESTS.
|
|
2395
|
+
|
|
2396
|
+
Parameters:
|
|
2397
|
+
asset_id (int): Numeric asset id as used in chain_params.
|
|
2256
2398
|
|
|
2257
|
-
|
|
2399
|
+
Returns:
|
|
2400
|
+
str: The asset symbol for the provided id.
|
|
2258
2401
|
|
|
2402
|
+
Raises:
|
|
2403
|
+
KeyError: If the asset id is not present in self.chain_params["chain_assets"].
|
|
2259
2404
|
"""
|
|
2260
2405
|
for asset in self.chain_params["chain_assets"]:
|
|
2261
2406
|
if asset["id"] == asset_id:
|
|
@@ -2265,8 +2410,12 @@ class BlockChainInstance(object):
|
|
|
2265
2410
|
|
|
2266
2411
|
@property
|
|
2267
2412
|
def backed_token_symbol(self):
|
|
2268
|
-
"""
|
|
2269
|
-
|
|
2413
|
+
"""
|
|
2414
|
+
Return the symbol for the chain's backed asset (HBD-like).
|
|
2415
|
+
|
|
2416
|
+
Attempts to read the asset symbol at asset id 0 (typical HBD). If that key is missing, falls back to asset id 1 (main token) and returns that symbol. Returns a string (e.g., "HBD", "TBD", or the chain's main token symbol). May propagate KeyError if neither asset id is available.
|
|
2417
|
+
"""
|
|
2418
|
+
# some networks (e.g. whaleshares) do not have HBD
|
|
2270
2419
|
try:
|
|
2271
2420
|
symbol = self._get_asset_symbol(0)
|
|
2272
2421
|
except KeyError:
|
|
@@ -2275,7 +2424,7 @@ class BlockChainInstance(object):
|
|
|
2275
2424
|
|
|
2276
2425
|
@property
|
|
2277
2426
|
def token_symbol(self):
|
|
2278
|
-
"""get the current chains symbol for
|
|
2427
|
+
"""get the current chains symbol for HIVE (e.g. "TESTS" on testnet)"""
|
|
2279
2428
|
return self._get_asset_symbol(1)
|
|
2280
2429
|
|
|
2281
2430
|
@property
|