hive-nectar 0.0.10__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.10.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 +317 -182
- 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 +118 -82
- 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.10.dist-info/RECORD +0 -91
- nectar/blurt.py +0 -562
- nectar/conveyor.py +0 -308
- nectar/steem.py +0 -581
- {hive_nectar-0.0.10.dist-info → hive_nectar-0.1.0.dist-info}/WHEEL +0 -0
- {hive_nectar-0.0.10.dist-info → hive_nectar-0.1.0.dist-info}/entry_points.txt +0 -0
- {hive_nectar-0.0.10.dist-info → hive_nectar-0.1.0.dist-info}/licenses/LICENSE.txt +0 -0
nectar/hive.py
CHANGED
|
@@ -4,7 +4,7 @@ import math
|
|
|
4
4
|
from datetime import date, datetime, timezone
|
|
5
5
|
|
|
6
6
|
from nectar.blockchaininstance import BlockChainInstance
|
|
7
|
-
from nectar.constants import
|
|
7
|
+
from nectar.constants import HIVE_100_PERCENT
|
|
8
8
|
from nectargraphenebase.chains import known_chains
|
|
9
9
|
|
|
10
10
|
from .amount import Amount
|
|
@@ -59,7 +59,7 @@ class Hive(BlockChainInstance):
|
|
|
59
59
|
* **Providing Keys**: Here, you can provide the keys for
|
|
60
60
|
your accounts manually. All you need to do is add the wif
|
|
61
61
|
keys for the accounts you want to use as a simple array
|
|
62
|
-
using the ``keys`` parameter to ``
|
|
62
|
+
using the ``keys`` parameter to ``Hive()``.
|
|
63
63
|
* **Force keys**: This more is for advanced users and
|
|
64
64
|
requires that you know what you are doing. Here, the
|
|
65
65
|
``keys`` parameter is a dictionary that overwrite the
|
|
@@ -94,9 +94,9 @@ class Hive(BlockChainInstance):
|
|
|
94
94
|
.. code-block:: python
|
|
95
95
|
|
|
96
96
|
from nectar import Hive
|
|
97
|
-
|
|
97
|
+
hv = Hive(node=["https://mytstnet.com"], custom_chains={"MYTESTNET":
|
|
98
98
|
{'chain_assets': [{'asset': 'HBD', 'id': 0, 'precision': 3, 'symbol': 'HBD'},
|
|
99
|
-
{'asset': '
|
|
99
|
+
{'asset': 'HIVE', 'id': 1, 'precision': 3, 'symbol': 'HIVE'},
|
|
100
100
|
{'asset': 'VESTS', 'id': 2, 'precision': 6, 'symbol': 'VESTS'}],
|
|
101
101
|
'chain_id': '79276aea5d4877d9a25892eaa01b0adf019d3e5cb12a97478df3298ccdd01674',
|
|
102
102
|
'min_version': '0.0.0',
|
|
@@ -220,11 +220,25 @@ class Hive(BlockChainInstance):
|
|
|
220
220
|
self,
|
|
221
221
|
token_power,
|
|
222
222
|
post_rshares=0,
|
|
223
|
-
voting_power=
|
|
224
|
-
vote_pct=
|
|
223
|
+
voting_power=HIVE_100_PERCENT,
|
|
224
|
+
vote_pct=HIVE_100_PERCENT,
|
|
225
225
|
not_broadcasted_vote=True,
|
|
226
226
|
use_stored_data=True,
|
|
227
227
|
):
|
|
228
|
+
"""
|
|
229
|
+
Convert token power (Hive Power) to its token-backed dollar equivalent (HBD).
|
|
230
|
+
|
|
231
|
+
Parameters:
|
|
232
|
+
token_power: Hive Power amount (numeric or Amount-like) to convert.
|
|
233
|
+
post_rshares (int): Optional existing rshares on the post to include when estimating payout.
|
|
234
|
+
voting_power (int): Voter's current voting power (use HIVE_100_PERCENT for full power).
|
|
235
|
+
vote_pct (int): Vote weight to apply (use HIVE_100_PERCENT for 100%).
|
|
236
|
+
not_broadcasted_vote (bool): If True, include the vote as not-yet-broadcasted when computing reward pool effects.
|
|
237
|
+
use_stored_data (bool): If True, prefer cached chain data when available.
|
|
238
|
+
|
|
239
|
+
Returns:
|
|
240
|
+
The estimated HBD value (token-backed dollar) corresponding to the provided token power.
|
|
241
|
+
"""
|
|
228
242
|
return self.hp_to_hbd(
|
|
229
243
|
token_power,
|
|
230
244
|
post_rshares=post_rshares,
|
|
@@ -238,21 +252,24 @@ class Hive(BlockChainInstance):
|
|
|
238
252
|
self,
|
|
239
253
|
hp,
|
|
240
254
|
post_rshares=0,
|
|
241
|
-
voting_power=
|
|
242
|
-
vote_pct=
|
|
255
|
+
voting_power=HIVE_100_PERCENT,
|
|
256
|
+
vote_pct=HIVE_100_PERCENT,
|
|
243
257
|
not_broadcasted_vote=True,
|
|
244
258
|
use_stored_data=True,
|
|
245
259
|
):
|
|
246
|
-
"""
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
:
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
260
|
+
"""
|
|
261
|
+
Convert Hive Power (HP) to the estimated HBD payout this vote would produce.
|
|
262
|
+
|
|
263
|
+
Parameters:
|
|
264
|
+
hp (number): Amount of Hive Power to convert.
|
|
265
|
+
post_rshares (int): Current post rshares to include when computing marginal effect of this vote.
|
|
266
|
+
voting_power (int): Voter's current voting power (100% = 10000).
|
|
267
|
+
vote_pct (int): Vote percentage to apply (100% = 10000).
|
|
268
|
+
not_broadcasted_vote (bool): If True, treat the vote as not yet broadcast — the function will account for the vote reducing the available reward pool when applicable.
|
|
269
|
+
use_stored_data (bool): If True, use cached chain/state data when available.
|
|
270
|
+
|
|
271
|
+
Returns:
|
|
272
|
+
HBD value corresponding to the provided HP under the current reward pool and price conditions (same type/format as the library's Amount/HBD results).
|
|
256
273
|
"""
|
|
257
274
|
vesting_shares = int(self.hp_to_vests(hp, use_stored_data=use_stored_data))
|
|
258
275
|
return self.vests_to_hbd(
|
|
@@ -268,21 +285,28 @@ class Hive(BlockChainInstance):
|
|
|
268
285
|
self,
|
|
269
286
|
vests,
|
|
270
287
|
post_rshares=0,
|
|
271
|
-
voting_power=
|
|
272
|
-
vote_pct=
|
|
288
|
+
voting_power=HIVE_100_PERCENT,
|
|
289
|
+
vote_pct=HIVE_100_PERCENT,
|
|
273
290
|
not_broadcasted_vote=True,
|
|
274
291
|
use_stored_data=True,
|
|
275
292
|
):
|
|
276
|
-
"""
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
:
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
293
|
+
"""
|
|
294
|
+
Convert vesting shares to their equivalent HBD payout for a single vote.
|
|
295
|
+
|
|
296
|
+
Given vesting shares, computes the vote's r-shares (taking into account post r-shares,
|
|
297
|
+
voter power and percentage) and converts that r-shares value to an HBD payout.
|
|
298
|
+
|
|
299
|
+
Parameters:
|
|
300
|
+
vests: Vesting shares to use for the vote (number or Amount-like).
|
|
301
|
+
post_rshares (int): Existing r-shares of the post being voted on; affects the r-shares calculation.
|
|
302
|
+
voting_power (int): Voter's current voting power (units where 100% == HIVE_100_PERCENT).
|
|
303
|
+
vote_pct (int): Vote percentage to apply (units where 100% == HIVE_100_PERCENT).
|
|
304
|
+
not_broadcasted_vote (bool): If True, treat this as a not-yet-broadcast vote (it reduces the effective reward pool);
|
|
305
|
+
if False, treat as already-applied (affects conversion math for very large votes).
|
|
306
|
+
use_stored_data (bool): Whether to use cached chain parameters/reward state or query fresh data.
|
|
307
|
+
|
|
308
|
+
Returns:
|
|
309
|
+
The estimated HBD value (same type returned by rshares_to_hbd) for the vote.
|
|
286
310
|
"""
|
|
287
311
|
vote_rshares = self.vests_to_rshares(
|
|
288
312
|
vests, post_rshares=post_rshares, voting_power=voting_power, vote_pct=vote_pct
|
|
@@ -295,17 +319,24 @@ class Hive(BlockChainInstance):
|
|
|
295
319
|
self,
|
|
296
320
|
hive_power,
|
|
297
321
|
post_rshares=0,
|
|
298
|
-
voting_power=
|
|
299
|
-
vote_pct=
|
|
322
|
+
voting_power=HIVE_100_PERCENT,
|
|
323
|
+
vote_pct=HIVE_100_PERCENT,
|
|
300
324
|
use_stored_data=True,
|
|
301
325
|
):
|
|
302
|
-
"""
|
|
326
|
+
"""
|
|
327
|
+
Convert Hive Power (HP) to r-shares used for voting.
|
|
328
|
+
|
|
329
|
+
Given a Hive Power amount, computes the equivalent vesting shares and then the r-shares that a vote with the specified voting_power and vote_pct would produce against a post that currently has post_rshares. `voting_power` and `vote_pct` use the chain-normalized scale (100% == HIVE_100_PERCENT).
|
|
303
330
|
|
|
304
|
-
:
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
331
|
+
Parameters:
|
|
332
|
+
hive_power (number): Hive Power (HP) value to convert.
|
|
333
|
+
post_rshares (int, optional): Current r-shares of the post being voted on; used to adjust the resulting r-shares. Defaults to 0.
|
|
334
|
+
voting_power (int, optional): Voter's current voting power on the HIVE_100_PERCENT scale. Defaults to HIVE_100_PERCENT.
|
|
335
|
+
vote_pct (int, optional): Vote percentage to apply on the HIVE_100_PERCENT scale. Defaults to HIVE_100_PERCENT.
|
|
336
|
+
use_stored_data (bool, optional): Whether to use cached chain data when performing conversions. Defaults to True.
|
|
308
337
|
|
|
338
|
+
Returns:
|
|
339
|
+
int: The computed r-shares produced by the specified vote.
|
|
309
340
|
"""
|
|
310
341
|
# calculate our account voting shares (from vests)
|
|
311
342
|
vesting_shares = int(self.hp_to_vests(hive_power, use_stored_data=use_stored_data))
|
|
@@ -322,24 +353,36 @@ class Hive(BlockChainInstance):
|
|
|
322
353
|
self,
|
|
323
354
|
vests,
|
|
324
355
|
post_rshares=0,
|
|
325
|
-
voting_power=
|
|
326
|
-
vote_pct=
|
|
356
|
+
voting_power=HIVE_100_PERCENT,
|
|
357
|
+
vote_pct=HIVE_100_PERCENT,
|
|
327
358
|
subtract_dust_threshold=True,
|
|
328
359
|
use_stored_data=True,
|
|
329
360
|
):
|
|
330
|
-
"""
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
361
|
+
"""
|
|
362
|
+
Convert vesting shares to vote r-shares.
|
|
363
|
+
|
|
364
|
+
Detailed behavior:
|
|
365
|
+
- `vests` is the voter's vesting amount in VESTS (not in micro-vests); the implementation multiplies this value by 1e6 internally.
|
|
366
|
+
- Computes the effective voting power using `voting_power` and `vote_pct`, applies Hive's normalization (HIVE_100_PERCENT), and returns the signed r-shares for that vote.
|
|
367
|
+
- If `subtract_dust_threshold` is True, results at or below the chain dust threshold return 0; otherwise the threshold is subtracted from the computed r-shares.
|
|
368
|
+
- The final r-shares are adjusted by `post_rshares` using the chain's vote-claim logic before being returned.
|
|
369
|
+
|
|
370
|
+
Parameters:
|
|
371
|
+
vests (int|float|Amount): Vesting shares in VESTS.
|
|
372
|
+
post_rshares (int): Current r-shares on the post being voted (used to compute claim adjustment).
|
|
373
|
+
voting_power (int): Voter's current voting power (100% == HIVE_100_PERCENT).
|
|
374
|
+
vote_pct (int): Vote percentage to apply (100% == HIVE_100_PERCENT); sign of this value determines vote direction.
|
|
375
|
+
subtract_dust_threshold (bool): If True, apply/subtract the chain dust threshold from the computed r-shares.
|
|
376
|
+
use_stored_data (bool): Whether to use cached chain data for thresholds and calculations.
|
|
377
|
+
|
|
378
|
+
Returns:
|
|
379
|
+
int: Signed r-shares resulting from the provided vesting shares and vote parameters.
|
|
337
380
|
"""
|
|
338
381
|
used_power = self._calc_resulting_vote(
|
|
339
382
|
voting_power=voting_power, vote_pct=vote_pct, use_stored_data=use_stored_data
|
|
340
383
|
)
|
|
341
384
|
# calculate vote rshares
|
|
342
|
-
rshares = int(math.copysign(vests * 1e6 * used_power /
|
|
385
|
+
rshares = int(math.copysign(vests * 1e6 * used_power / HIVE_100_PERCENT, vote_pct))
|
|
343
386
|
if subtract_dust_threshold:
|
|
344
387
|
if abs(rshares) <= self.get_dust_threshold(use_stored_data=use_stored_data):
|
|
345
388
|
return 0
|
|
@@ -404,22 +447,36 @@ class Hive(BlockChainInstance):
|
|
|
404
447
|
post_rshares=0,
|
|
405
448
|
hive_power=None,
|
|
406
449
|
vests=None,
|
|
407
|
-
voting_power=
|
|
450
|
+
voting_power=HIVE_100_PERCENT,
|
|
408
451
|
use_stored_data=True,
|
|
409
452
|
):
|
|
410
|
-
"""
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
:
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
453
|
+
"""
|
|
454
|
+
Compute the voting percentage required to achieve a target r-shares value.
|
|
455
|
+
|
|
456
|
+
Given a desired r-shares (positive for upvotes, negative for downvotes) and either
|
|
457
|
+
hive_power or vests (exactly one must be provided), return the voting percentage
|
|
458
|
+
where 100% = 10000. The calculation accounts for post-vote r-shares adjustments,
|
|
459
|
+
current dust-threshold behavior (post-hardfork), and the configured voting power.
|
|
460
|
+
|
|
461
|
+
Parameters:
|
|
462
|
+
rshares (int | float): Target r-shares value (signed).
|
|
463
|
+
post_rshares (int, optional): R-shares already present on the post (positive
|
|
464
|
+
for existing upvotes, negative for downvotes). Defaults to 0.
|
|
465
|
+
hive_power (float, optional): Hive Power to use for the calculation. Provide
|
|
466
|
+
this or `vests`, not both. If given, it is converted to vesting shares.
|
|
467
|
+
vests (int, optional): Vesting shares (in micro-vests, i.e., vest*1e6). Provide
|
|
468
|
+
this or `hive_power`, not both.
|
|
469
|
+
voting_power (int, optional): Voter's current voting power where 100% = 10000.
|
|
470
|
+
Defaults to HIVE_100_PERCENT.
|
|
471
|
+
use_stored_data (bool, optional): Whether to use cached chain properties when
|
|
472
|
+
available. Defaults to True.
|
|
473
|
+
|
|
474
|
+
Returns:
|
|
475
|
+
int: Signed voting percentage required (100% = 10000). The sign matches the
|
|
476
|
+
sign of `rshares`.
|
|
477
|
+
|
|
478
|
+
Raises:
|
|
479
|
+
ValueError: If neither or both of `hive_power` and `vests` are provided.
|
|
423
480
|
"""
|
|
424
481
|
if hive_power is None and vests is None:
|
|
425
482
|
raise ValueError("Either hive_power or vests has to be set!")
|
|
@@ -450,10 +507,10 @@ class Hive(BlockChainInstance):
|
|
|
450
507
|
|
|
451
508
|
max_vote_denom = self._max_vote_denom(use_stored_data=use_stored_data)
|
|
452
509
|
|
|
453
|
-
used_power = int(math.ceil(abs(rshares) *
|
|
510
|
+
used_power = int(math.ceil(abs(rshares) * HIVE_100_PERCENT / vests))
|
|
454
511
|
used_power = used_power * max_vote_denom
|
|
455
512
|
|
|
456
|
-
vote_pct = used_power *
|
|
513
|
+
vote_pct = used_power * HIVE_100_PERCENT / (60 * 60 * 24) / voting_power
|
|
457
514
|
return int(math.copysign(vote_pct, rshares))
|
|
458
515
|
|
|
459
516
|
def hbd_to_vote_pct(
|
|
@@ -462,26 +519,29 @@ class Hive(BlockChainInstance):
|
|
|
462
519
|
post_rshares=0,
|
|
463
520
|
hive_power=None,
|
|
464
521
|
vests=None,
|
|
465
|
-
voting_power=
|
|
522
|
+
voting_power=HIVE_100_PERCENT,
|
|
466
523
|
not_broadcasted_vote=True,
|
|
467
524
|
use_stored_data=True,
|
|
468
525
|
):
|
|
469
|
-
"""
|
|
470
|
-
|
|
471
|
-
Give either Hive Power or vests, not both.
|
|
472
|
-
When the output is greater than 10000 or smaller than -10000,
|
|
473
|
-
the HBD value is too high.
|
|
526
|
+
"""
|
|
527
|
+
Calculate the voting percentage required to achieve a target HBD payout for a given voting power and stake.
|
|
474
528
|
|
|
475
|
-
|
|
529
|
+
Given a desired HBD amount, this returns the vote percentage (100% == 10000) that, when applied from the provided Hive Power or vesting shares, would produce approximately that payout. Exactly one of `hive_power` or `vests` must be provided.
|
|
476
530
|
|
|
477
|
-
:
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
531
|
+
Parameters:
|
|
532
|
+
hbd (str|int|Amount): Desired HBD payout. Accepts an Amount, numeric value, or asset string; will be converted to an Amount in the chain's HBD symbol.
|
|
533
|
+
hive_power (number, optional): Voter's Hive Power. Mutually exclusive with `vests`.
|
|
534
|
+
vests (number, optional): Voter's vesting shares. Mutually exclusive with `hive_power`.
|
|
535
|
+
voting_power (int, optional): Current voting power normalization constant (default HIVE_100_PERCENT).
|
|
536
|
+
not_broadcasted_vote (bool, optional): If True, treat the vote as not yet broadcast; this slightly changes calculations for very large HBD amounts because an unbroadcasted vote reduces the available reward pool.
|
|
537
|
+
post_rshares (int, optional): rshares already present on the post (used when calculating required vote to reach a target).
|
|
538
|
+
use_stored_data (bool, optional): Use cached chain properties when available.
|
|
539
|
+
|
|
540
|
+
Returns:
|
|
541
|
+
int: Required vote percentage where 100% == 10000. Values >10000 or < -10000 indicate the requested HBD is too large for a single vote.
|
|
484
542
|
|
|
543
|
+
Raises:
|
|
544
|
+
AssertionError: If the provided `hbd` cannot be interpreted as the chain's HBD asset.
|
|
485
545
|
"""
|
|
486
546
|
if isinstance(hbd, Amount):
|
|
487
547
|
hbd = Amount(hbd, blockchain_instance=self)
|
nectar/hivesigner.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import json
|
|
3
3
|
|
|
4
4
|
try:
|
|
5
|
-
from urllib.parse import urlencode, urljoin
|
|
5
|
+
from urllib.parse import urlencode, urljoin
|
|
6
6
|
except ImportError:
|
|
7
7
|
from urllib import urlencode
|
|
8
8
|
|
|
@@ -29,27 +29,27 @@ class HiveSigner(object):
|
|
|
29
29
|
|
|
30
30
|
.. code-block:: python
|
|
31
31
|
|
|
32
|
-
# Run the login_app in examples and login with
|
|
33
|
-
from nectar import
|
|
34
|
-
from nectar.
|
|
32
|
+
# Run the login_app in examples and login with an account
|
|
33
|
+
from nectar import Hive
|
|
34
|
+
from nectar.hivesigner import HiveSigner
|
|
35
35
|
from nectar.comment import Comment
|
|
36
36
|
hs = HiveSigner(client_id="nectarflower")
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
post = Comment("author/permlink", blockchain_instance=
|
|
37
|
+
hive = Hive(HiveSigner=hs)
|
|
38
|
+
hive.wallet.unlock("supersecret-passphrase")
|
|
39
|
+
post = Comment("author/permlink", blockchain_instance=hive)
|
|
40
40
|
post.upvote(voter="test") # replace "test" with your account
|
|
41
41
|
|
|
42
42
|
Examples for creating HiveSigner urls for broadcasting in browser:
|
|
43
43
|
|
|
44
44
|
.. testoutput::
|
|
45
45
|
|
|
46
|
-
from nectar import
|
|
46
|
+
from nectar import Hive
|
|
47
47
|
from nectar.account import Account
|
|
48
|
-
from nectar.
|
|
48
|
+
from nectar.hivesigner import HiveSigner
|
|
49
49
|
from pprint import pprint
|
|
50
|
-
|
|
51
|
-
hs = HiveSigner(blockchain_instance=
|
|
52
|
-
acc = Account("test", blockchain_instance=
|
|
50
|
+
hive = Hive(nobroadcast=True, unsigned=True)
|
|
51
|
+
hs = HiveSigner(blockchain_instance=hive)
|
|
52
|
+
acc = Account("test", blockchain_instance=hive)
|
|
53
53
|
pprint(hs.url_from_tx(acc.transfer("test1", 1, "HIVE", "test")))
|
|
54
54
|
|
|
55
55
|
.. testcode::
|
|
@@ -58,14 +58,14 @@ class HiveSigner(object):
|
|
|
58
58
|
|
|
59
59
|
.. testoutput::
|
|
60
60
|
|
|
61
|
-
from nectar import
|
|
61
|
+
from nectar import Hive
|
|
62
62
|
from nectar.transactionbuilder import TransactionBuilder
|
|
63
63
|
from nectarbase import operations
|
|
64
|
-
from nectar.
|
|
64
|
+
from nectar.hivesigner import HiveSigner
|
|
65
65
|
from pprint import pprint
|
|
66
|
-
|
|
67
|
-
hs = HiveSigner(blockchain_instance=
|
|
68
|
-
tx = TransactionBuilder(blockchain_instance=
|
|
66
|
+
hive = Hive(nobroadcast=True, unsigned=True)
|
|
67
|
+
hs = HiveSigner(blockchain_instance=hive)
|
|
68
|
+
tx = TransactionBuilder(blockchain_instance=hive)
|
|
69
69
|
op = operations.Transfer(**{"from": 'test',
|
|
70
70
|
"to": 'test1',
|
|
71
71
|
"amount": '1.000 HIVE',
|
|
@@ -80,11 +80,20 @@ class HiveSigner(object):
|
|
|
80
80
|
"""
|
|
81
81
|
|
|
82
82
|
def __init__(self, blockchain_instance=None, *args, **kwargs):
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
83
|
+
"""
|
|
84
|
+
Initialize HiveSigner integration.
|
|
85
|
+
|
|
86
|
+
Sets up the blockchain client (uses provided instance or the shared global), OAuth/client configuration, and the token store.
|
|
87
|
+
|
|
88
|
+
Detailed behavior:
|
|
89
|
+
- Resolves self.blockchain from blockchain_instance or shared_blockchain_instance().
|
|
90
|
+
- Reads defaults from blockchain config for client_id, scope, OAuth base URL, API URL, and hot-sign redirect URI.
|
|
91
|
+
- Normalizes hot_sign_redirect_uri to None if an empty string is provided.
|
|
92
|
+
- Stores get_refresh_token, client_id, scope, hs_oauth_base_url, and hs_api_url on the instance.
|
|
93
|
+
- Token handling:
|
|
94
|
+
- If a non-empty "token" is provided in kwargs, an in-memory token store is created, the access token is set, the associated username is fetched via me(), and the token is stored under that username.
|
|
95
|
+
- Otherwise a persistent token store is used: either the token_store passed in kwargs or a SqliteEncryptedTokenStore initialized with the blockchain config and kwargs.
|
|
96
|
+
"""
|
|
88
97
|
self.blockchain = blockchain_instance or shared_blockchain_instance()
|
|
89
98
|
self.access_token = None
|
|
90
99
|
config = self.blockchain.config
|
|
@@ -120,11 +129,25 @@ class HiveSigner(object):
|
|
|
120
129
|
|
|
121
130
|
@property
|
|
122
131
|
def headers(self):
|
|
132
|
+
"""
|
|
133
|
+
Return the HTTP Authorization headers for the current access token.
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
dict: A headers dictionary with the "Authorization" key set to the current access token (may be None if no token is set).
|
|
137
|
+
"""
|
|
123
138
|
return {"Authorization": self.access_token}
|
|
124
139
|
|
|
125
140
|
def setToken(self, loadtoken):
|
|
126
|
-
"""
|
|
127
|
-
|
|
141
|
+
"""
|
|
142
|
+
Force-add tokens into the token store from an in-memory mapping.
|
|
143
|
+
|
|
144
|
+
Accepts a mapping of public-name -> token and stores each entry into the configured token store. Intended for use when tokens are provided directly (e.g., via a `token` argument) and should be loaded into the in-memory store.
|
|
145
|
+
|
|
146
|
+
Parameters:
|
|
147
|
+
loadtoken (dict): Mapping where keys are public names and values are the corresponding private token strings.
|
|
148
|
+
|
|
149
|
+
Raises:
|
|
150
|
+
ValueError: If `loadtoken` is not a dict.
|
|
128
151
|
"""
|
|
129
152
|
log.debug("Force setting of private token. Not using the wallet database!")
|
|
130
153
|
if not isinstance(loadtoken, (dict)):
|
|
@@ -255,15 +278,16 @@ class HiveSigner(object):
|
|
|
255
278
|
return r.json()
|
|
256
279
|
|
|
257
280
|
def me(self, username=None):
|
|
258
|
-
"""
|
|
281
|
+
"""
|
|
282
|
+
Retrieve the current user's information from HiveSigner.
|
|
259
283
|
|
|
260
|
-
|
|
284
|
+
If a username is provided, sets the access token for that username (via set_username) before calling the HiveSigner "me" endpoint. Performs an authenticated POST to the HiveSigner me endpoint and returns the parsed JSON response.
|
|
261
285
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
hs.steem.wallet.unlock("supersecret-passphrase")
|
|
265
|
-
hs.me(username="test")
|
|
286
|
+
Parameters:
|
|
287
|
+
username (str, optional): Public account name whose token should be used for the request. If omitted, the currently configured access token is used.
|
|
266
288
|
|
|
289
|
+
Returns:
|
|
290
|
+
dict: Parsed JSON response from the HiveSigner me endpoint.
|
|
267
291
|
"""
|
|
268
292
|
if username:
|
|
269
293
|
self.set_username(username)
|
|
@@ -285,23 +309,17 @@ class HiveSigner(object):
|
|
|
285
309
|
self.access_token = self.getTokenForAccountName(username)
|
|
286
310
|
|
|
287
311
|
def broadcast(self, operations, username=None):
|
|
288
|
-
"""
|
|
289
|
-
|
|
290
|
-
Sample operations:
|
|
312
|
+
"""
|
|
313
|
+
Broadcast a list of Hive operations via the HiveSigner API.
|
|
291
314
|
|
|
292
|
-
|
|
315
|
+
Sends a POST request to the HiveSigner broadcast endpoint with the provided operations. If `username` is given, the method will set the access token for that user before sending the request.
|
|
293
316
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
'voter': 'gandalf',
|
|
298
|
-
'author': 'gtg',
|
|
299
|
-
'permlink': 'steem-pressure-4-need-for-speed',
|
|
300
|
-
'weight': 10000
|
|
301
|
-
}
|
|
302
|
-
]
|
|
303
|
-
]
|
|
317
|
+
Parameters:
|
|
318
|
+
operations (list): A list of operations in the form [[operation_name, operation_payload], ...].
|
|
319
|
+
username (str, optional): Public account name whose stored token should be used for authorization.
|
|
304
320
|
|
|
321
|
+
Returns:
|
|
322
|
+
dict or bytes: The parsed JSON response from the API, or raw response content if the body is not valid JSON.
|
|
305
323
|
"""
|
|
306
324
|
url = urljoin(self.hs_api_url, "broadcast/")
|
|
307
325
|
data = {
|
|
@@ -357,10 +375,19 @@ class HiveSigner(object):
|
|
|
357
375
|
return r.json()
|
|
358
376
|
|
|
359
377
|
def url_from_tx(self, tx, redirect_uri=None):
|
|
360
|
-
"""
|
|
378
|
+
"""
|
|
379
|
+
Generate HiveSigner hot-sign URLs for each operation in a transaction.
|
|
380
|
+
|
|
381
|
+
Given a transaction dict (or an object with a .json() method returning such a dict), produce a HiveSigner "hot sign" URL for each operation. If the transaction has no operations an empty string is returned. For each operation the function normalizes parameter values before building the URL:
|
|
382
|
+
- 3-element lists are treated as amounts and converted to the blockchain's Amount string when possible.
|
|
383
|
+
- booleans are converted to 1 (True) or 0 (False).
|
|
384
|
+
- other values are left as-is.
|
|
361
385
|
|
|
362
|
-
|
|
363
|
-
|
|
386
|
+
Returns either a single URL string when the transaction contains one operation, a list of URL strings for multiple operations, or an empty string when there are no operations.
|
|
387
|
+
|
|
388
|
+
Parameters:
|
|
389
|
+
tx (dict | object): Transaction data or an object implementing .json() that returns a dict with an "operations" list.
|
|
390
|
+
redirect_uri (str, optional): If provided, included in each generated hot-sign URL as the post-sign redirect target.
|
|
364
391
|
"""
|
|
365
392
|
if not isinstance(tx, dict):
|
|
366
393
|
tx = tx.json()
|
|
@@ -390,31 +417,42 @@ class HiveSigner(object):
|
|
|
390
417
|
else:
|
|
391
418
|
return urls
|
|
392
419
|
|
|
393
|
-
def
|
|
394
|
-
"""
|
|
420
|
+
def sign(self, tx):
|
|
421
|
+
"""
|
|
422
|
+
Create a transaction shaped as if signed by HiveSigner.
|
|
423
|
+
|
|
424
|
+
This method does not perform real cryptographic signing locally; instead it validates
|
|
425
|
+
the transaction structure and returns a copy containing a mock signature entry so
|
|
426
|
+
callers that expect a "signed" transaction can proceed (actual signing is performed
|
|
427
|
+
server-side by HiveSigner during broadcasting).
|
|
428
|
+
|
|
429
|
+
Parameters:
|
|
430
|
+
tx (dict): Transaction object that must include a non-empty "operations" list.
|
|
431
|
+
|
|
432
|
+
Returns:
|
|
433
|
+
dict: A copy of `tx` with a "signatures" list containing a mock HiveSigner signature.
|
|
395
434
|
|
|
396
|
-
:
|
|
397
|
-
|
|
398
|
-
:param str redirect_uri: Redirects to this uri, when set
|
|
435
|
+
Raises:
|
|
436
|
+
ValueError: If `tx` is not a dict or if it lacks a non-empty "operations" list.
|
|
399
437
|
"""
|
|
438
|
+
if not isinstance(tx, dict):
|
|
439
|
+
raise ValueError("Transaction must be a dictionary")
|
|
400
440
|
|
|
401
|
-
if not
|
|
402
|
-
raise ValueError("
|
|
441
|
+
if "operations" not in tx or not tx["operations"]:
|
|
442
|
+
raise ValueError("Transaction must contain operations")
|
|
403
443
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
444
|
+
# For HiveSigner, we don't actually sign locally - the signing happens
|
|
445
|
+
# server-side when broadcast() is called. However, we need to return
|
|
446
|
+
# a transaction that looks signed for compatibility.
|
|
407
447
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
if redirect_uri is not None:
|
|
411
|
-
params.update({"redirect_uri": redirect_uri})
|
|
448
|
+
# Create a copy of the transaction
|
|
449
|
+
signed_tx = tx.copy()
|
|
412
450
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
url += "?" + params
|
|
451
|
+
# Add a mock signature to indicate this was processed by HiveSigner
|
|
452
|
+
# In a real implementation, this would be replaced with actual signatures
|
|
453
|
+
# from the HiveSigner API response
|
|
454
|
+
mock_signature = "hivesigner_signature_placeholder"
|
|
455
|
+
signed_tx["signatures"] = [mock_signature]
|
|
419
456
|
|
|
420
|
-
|
|
457
|
+
log.debug(f"HiveSigner sign: processed transaction with {len(tx['operations'])} operations")
|
|
458
|
+
return signed_tx
|