hive-nectar 0.0.5__py3-none-any.whl → 0.0.7__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.5.dist-info → hive_nectar-0.0.7.dist-info}/METADATA +6 -3
- hive_nectar-0.0.7.dist-info/RECORD +91 -0
- nectar/account.py +43 -47
- nectar/amount.py +6 -11
- nectar/block.py +8 -9
- nectar/blockchain.py +10 -11
- nectar/blockchaininstance.py +4 -4
- nectar/blockchainobject.py +5 -6
- nectar/blurt.py +3 -4
- nectar/cli.py +14 -14
- nectar/comment.py +10 -11
- nectar/community.py +4 -5
- nectar/conveyor.py +3 -4
- nectar/exceptions.py +30 -24
- nectar/hive.py +3 -4
- nectar/hivesigner.py +2 -2
- nectar/imageuploader.py +2 -3
- nectar/price.py +6 -13
- nectar/rc.py +1 -2
- nectar/steem.py +3 -4
- nectar/transactionbuilder.py +12 -3
- nectar/version.py +1 -1
- nectar/vote.py +8 -9
- nectar/wallet.py +1 -1
- nectarapi/exceptions.py +20 -14
- nectarapi/graphenerpc.py +49 -76
- nectarapi/version.py +1 -1
- nectarbase/ledgertransactions.py +2 -3
- nectarbase/memo.py +9 -10
- nectarbase/objects.py +4 -5
- nectarbase/operations.py +3 -7
- nectarbase/version.py +1 -1
- nectargraphenebase/__init__.py +0 -1
- nectargraphenebase/account.py +16 -37
- nectargraphenebase/base58.py +5 -8
- nectargraphenebase/bip32.py +5 -11
- nectargraphenebase/bip38.py +6 -7
- nectargraphenebase/ecdsasig.py +32 -37
- nectargraphenebase/objects.py +6 -7
- nectargraphenebase/signedtransactions.py +10 -9
- nectargraphenebase/types.py +9 -19
- nectargraphenebase/unsignedtransactions.py +21 -28
- nectargraphenebase/version.py +1 -1
- nectarstorage/masterpassword.py +2 -3
- hive_nectar-0.0.5.dist-info/RECORD +0 -92
- nectargraphenebase/py23.py +0 -38
- {hive_nectar-0.0.5.dist-info → hive_nectar-0.0.7.dist-info}/WHEEL +0 -0
- {hive_nectar-0.0.5.dist-info → hive_nectar-0.0.7.dist-info}/entry_points.txt +0 -0
- {hive_nectar-0.0.5.dist-info → hive_nectar-0.0.7.dist-info}/licenses/LICENSE.txt +0 -0
nectar/hive.py
CHANGED
|
@@ -6,7 +6,6 @@ from datetime import date, datetime, timezone
|
|
|
6
6
|
from nectar.blockchaininstance import BlockChainInstance
|
|
7
7
|
from nectar.constants import STEEM_100_PERCENT
|
|
8
8
|
from nectargraphenebase.chains import known_chains
|
|
9
|
-
from nectargraphenebase.py23 import string_types
|
|
10
9
|
|
|
11
10
|
from .amount import Amount
|
|
12
11
|
from .utils import formatToTimeStamp
|
|
@@ -124,7 +123,7 @@ class Hive(BlockChainInstance):
|
|
|
124
123
|
return known_chains["HIVE"]
|
|
125
124
|
try:
|
|
126
125
|
return self.rpc.get_network(props=config)
|
|
127
|
-
except:
|
|
126
|
+
except Exception:
|
|
128
127
|
return known_chains["HIVE"]
|
|
129
128
|
|
|
130
129
|
def rshares_to_token_backed_dollar(
|
|
@@ -362,7 +361,7 @@ class Hive(BlockChainInstance):
|
|
|
362
361
|
"""
|
|
363
362
|
if isinstance(hbd, Amount):
|
|
364
363
|
hbd = Amount(hbd, blockchain_instance=self)
|
|
365
|
-
elif isinstance(hbd,
|
|
364
|
+
elif isinstance(hbd, str):
|
|
366
365
|
hbd = Amount(hbd, blockchain_instance=self)
|
|
367
366
|
else:
|
|
368
367
|
hbd = Amount(hbd, self.hbd_symbol, blockchain_instance=self)
|
|
@@ -486,7 +485,7 @@ class Hive(BlockChainInstance):
|
|
|
486
485
|
"""
|
|
487
486
|
if isinstance(hbd, Amount):
|
|
488
487
|
hbd = Amount(hbd, blockchain_instance=self)
|
|
489
|
-
elif isinstance(hbd,
|
|
488
|
+
elif isinstance(hbd, str):
|
|
490
489
|
hbd = Amount(hbd, blockchain_instance=self)
|
|
491
490
|
else:
|
|
492
491
|
hbd = Amount(hbd, self.hbd_symbol, blockchain_instance=self)
|
nectar/hivesigner.py
CHANGED
|
@@ -33,7 +33,7 @@ class HiveSigner(object):
|
|
|
33
33
|
from nectar import Steem
|
|
34
34
|
from nectar.HiveSigner import HiveSigner
|
|
35
35
|
from nectar.comment import Comment
|
|
36
|
-
hs = HiveSigner(client_id="
|
|
36
|
+
hs = HiveSigner(client_id="nectarflower")
|
|
37
37
|
steem = Steem(HiveSigner=hs)
|
|
38
38
|
steem.wallet.unlock("supersecret-passphrase")
|
|
39
39
|
post = Comment("author/permlink", blockchain_instance=steem)
|
|
@@ -377,7 +377,7 @@ class HiveSigner(object):
|
|
|
377
377
|
try:
|
|
378
378
|
amount = Amount(value, blockchain_instance=self.blockchain)
|
|
379
379
|
params[key] = str(amount)
|
|
380
|
-
except:
|
|
380
|
+
except Exception:
|
|
381
381
|
amount = None
|
|
382
382
|
elif isinstance(value, bool):
|
|
383
383
|
if value:
|
nectar/imageuploader.py
CHANGED
|
@@ -6,7 +6,6 @@ import requests
|
|
|
6
6
|
|
|
7
7
|
from nectar.account import Account
|
|
8
8
|
from nectargraphenebase.ecdsasig import sign_message
|
|
9
|
-
from nectargraphenebase.py23 import py23_bytes, string_types
|
|
10
9
|
|
|
11
10
|
from .instance import shared_blockchain_instance
|
|
12
11
|
|
|
@@ -55,14 +54,14 @@ class ImageUploader(object):
|
|
|
55
54
|
for authority in account["posting"]["key_auths"]:
|
|
56
55
|
posting_wif = self.steem.wallet.getPrivateKeyForPublicKey(authority[0])
|
|
57
56
|
|
|
58
|
-
if isinstance(image,
|
|
57
|
+
if isinstance(image, str):
|
|
59
58
|
image_data = open(image, "rb").read()
|
|
60
59
|
elif isinstance(image, io.BytesIO):
|
|
61
60
|
image_data = image.read()
|
|
62
61
|
else:
|
|
63
62
|
image_data = image
|
|
64
63
|
|
|
65
|
-
message =
|
|
64
|
+
message = bytes(self.challenge, "ascii") + image_data
|
|
66
65
|
signature = sign_message(message, posting_wif)
|
|
67
66
|
signature_in_hex = hexlify(signature).decode("ascii")
|
|
68
67
|
|
nectar/price.py
CHANGED
|
@@ -3,7 +3,6 @@ from decimal import Decimal
|
|
|
3
3
|
from fractions import Fraction
|
|
4
4
|
|
|
5
5
|
from nectar.instance import shared_blockchain_instance
|
|
6
|
-
from nectargraphenebase.py23 import integer_types, string_types
|
|
7
6
|
|
|
8
7
|
from .amount import Amount
|
|
9
8
|
from .asset import Asset
|
|
@@ -97,7 +96,7 @@ class Price(dict):
|
|
|
97
96
|
self.blockchain = blockchain_instance or shared_blockchain_instance()
|
|
98
97
|
if price == "":
|
|
99
98
|
price = None
|
|
100
|
-
if price is not None and isinstance(price,
|
|
99
|
+
if price is not None and isinstance(price, str) and not base and not quote:
|
|
101
100
|
price, assets = price.split(" ")
|
|
102
101
|
base_symbol, quote_symbol = assets_from_string(assets)
|
|
103
102
|
base = Asset(base_symbol, blockchain_instance=self.blockchain)
|
|
@@ -131,9 +130,7 @@ class Price(dict):
|
|
|
131
130
|
amount=frac.numerator, asset=base, blockchain_instance=self.blockchain
|
|
132
131
|
)
|
|
133
132
|
|
|
134
|
-
elif (
|
|
135
|
-
price is not None and isinstance(base, string_types) and isinstance(quote, string_types)
|
|
136
|
-
):
|
|
133
|
+
elif price is not None and isinstance(base, str) and isinstance(quote, str):
|
|
137
134
|
base = Asset(base, blockchain_instance=self.blockchain)
|
|
138
135
|
quote = Asset(quote, blockchain_instance=self.blockchain)
|
|
139
136
|
frac = Fraction(float(price)).limit_denominator(10 ** base["precision"])
|
|
@@ -144,12 +141,10 @@ class Price(dict):
|
|
|
144
141
|
amount=frac.numerator, asset=base, blockchain_instance=self.blockchain
|
|
145
142
|
)
|
|
146
143
|
|
|
147
|
-
elif price is None and isinstance(base,
|
|
144
|
+
elif price is None and isinstance(base, str) and isinstance(quote, str):
|
|
148
145
|
self["quote"] = Amount(quote, blockchain_instance=self.blockchain)
|
|
149
146
|
self["base"] = Amount(base, blockchain_instance=self.blockchain)
|
|
150
|
-
elif (
|
|
151
|
-
price is not None and isinstance(price, string_types) and isinstance(base, string_types)
|
|
152
|
-
):
|
|
147
|
+
elif price is not None and isinstance(price, str) and isinstance(base, str):
|
|
153
148
|
self["quote"] = Amount(price, blockchain_instance=self.blockchain)
|
|
154
149
|
self["base"] = Amount(base, blockchain_instance=self.blockchain)
|
|
155
150
|
# len(args) > 1
|
|
@@ -163,10 +158,8 @@ class Price(dict):
|
|
|
163
158
|
self["base"] = base
|
|
164
159
|
|
|
165
160
|
elif (
|
|
166
|
-
isinstance(price, float)
|
|
167
|
-
|
|
168
|
-
or isinstance(price, Decimal)
|
|
169
|
-
) and isinstance(base, string_types):
|
|
161
|
+
isinstance(price, float) or isinstance(price, int) or isinstance(price, Decimal)
|
|
162
|
+
) and isinstance(base, str):
|
|
170
163
|
base_symbol, quote_symbol = assets_from_string(base)
|
|
171
164
|
base = Asset(base_symbol, blockchain_instance=self.blockchain)
|
|
172
165
|
quote = Asset(quote_symbol, blockchain_instance=self.blockchain)
|
nectar/rc.py
CHANGED
|
@@ -9,7 +9,6 @@ from nectar.constants import (
|
|
|
9
9
|
from nectarbase import operations
|
|
10
10
|
from nectarbase.objects import Operation
|
|
11
11
|
from nectarbase.signedtransactions import Signed_Transaction
|
|
12
|
-
from nectargraphenebase.py23 import py23_bytes
|
|
13
12
|
|
|
14
13
|
from .instance import shared_blockchain_instance
|
|
15
14
|
|
|
@@ -38,7 +37,7 @@ class RC(object):
|
|
|
38
37
|
operations=ops,
|
|
39
38
|
)
|
|
40
39
|
tx = tx.sign([wif], chain=prefix)
|
|
41
|
-
txWire = hexlify(
|
|
40
|
+
txWire = hexlify(bytes(tx)).decode("ascii")
|
|
42
41
|
tx_size = len(txWire)
|
|
43
42
|
return tx_size
|
|
44
43
|
|
nectar/steem.py
CHANGED
|
@@ -6,7 +6,6 @@ from datetime import date, datetime, timezone
|
|
|
6
6
|
from nectar.blockchaininstance import BlockChainInstance
|
|
7
7
|
from nectar.constants import STEEM_100_PERCENT, STEEM_VOTE_REGENERATION_SECONDS
|
|
8
8
|
from nectargraphenebase.chains import known_chains
|
|
9
|
-
from nectargraphenebase.py23 import string_types
|
|
10
9
|
|
|
11
10
|
from .amount import Amount
|
|
12
11
|
from .utils import formatToTimeStamp
|
|
@@ -124,7 +123,7 @@ class Steem(BlockChainInstance):
|
|
|
124
123
|
return known_chains["STEEM"]
|
|
125
124
|
try:
|
|
126
125
|
return self.rpc.get_network(props=config)
|
|
127
|
-
except:
|
|
126
|
+
except Exception:
|
|
128
127
|
return known_chains["STEEM"]
|
|
129
128
|
|
|
130
129
|
def rshares_to_token_backed_dollar(
|
|
@@ -393,7 +392,7 @@ class Steem(BlockChainInstance):
|
|
|
393
392
|
"""
|
|
394
393
|
if isinstance(sbd, Amount):
|
|
395
394
|
sbd = Amount(sbd, blockchain_instance=self)
|
|
396
|
-
elif isinstance(sbd,
|
|
395
|
+
elif isinstance(sbd, str):
|
|
397
396
|
sbd = Amount(sbd, blockchain_instance=self)
|
|
398
397
|
else:
|
|
399
398
|
sbd = Amount(sbd, self.sbd_symbol, blockchain_instance=self)
|
|
@@ -517,7 +516,7 @@ class Steem(BlockChainInstance):
|
|
|
517
516
|
"""
|
|
518
517
|
if isinstance(sbd, Amount):
|
|
519
518
|
sbd = Amount(sbd, blockchain_instance=self)
|
|
520
|
-
elif isinstance(sbd,
|
|
519
|
+
elif isinstance(sbd, str):
|
|
521
520
|
sbd = Amount(sbd, blockchain_instance=self)
|
|
522
521
|
else:
|
|
523
522
|
sbd = Amount(sbd, self.sbd_symbol, blockchain_instance=self)
|
nectar/transactionbuilder.py
CHANGED
|
@@ -279,7 +279,7 @@ class TransactionBuilder(dict):
|
|
|
279
279
|
try:
|
|
280
280
|
PrivateKey(wif, prefix=self.blockchain.prefix)
|
|
281
281
|
self.wifs.add(wif)
|
|
282
|
-
except:
|
|
282
|
+
except Exception:
|
|
283
283
|
raise InvalidWifError
|
|
284
284
|
|
|
285
285
|
def clearWifs(self):
|
|
@@ -427,7 +427,7 @@ class TransactionBuilder(dict):
|
|
|
427
427
|
# try:
|
|
428
428
|
# ledgertx = Ledger_Transaction(**self.json(with_prefix=True))
|
|
429
429
|
# ledgertx.add_custom_chains(self.blockchain.custom_chains)
|
|
430
|
-
# except:
|
|
430
|
+
# except Exception:
|
|
431
431
|
# raise ValueError("Invalid TransactionBuilder Format")
|
|
432
432
|
# ledgertx.sign(self.path, chain=self.blockchain.chain_params)
|
|
433
433
|
self.ledgertx.sign(self.path, chain=self.blockchain.chain_params)
|
|
@@ -438,7 +438,16 @@ class TransactionBuilder(dict):
|
|
|
438
438
|
raise MissingKeyError
|
|
439
439
|
|
|
440
440
|
self.tx.sign(self.wifs, chain=self.blockchain.chain_params)
|
|
441
|
-
self["signatures"]
|
|
441
|
+
# Defensive: ensure self["signatures"] is a list before extend
|
|
442
|
+
if isinstance(self["signatures"], str):
|
|
443
|
+
log.warning(
|
|
444
|
+
"self['signatures'] was a string, converting to list to avoid AttributeError."
|
|
445
|
+
)
|
|
446
|
+
self["signatures"] = [self["signatures"]]
|
|
447
|
+
sigs = self.tx.json().get("signatures")
|
|
448
|
+
if isinstance(sigs, str):
|
|
449
|
+
sigs = [sigs]
|
|
450
|
+
self["signatures"].extend(sigs)
|
|
442
451
|
return self.tx
|
|
443
452
|
|
|
444
453
|
def verify_authority(self):
|
nectar/version.py
CHANGED
nectar/vote.py
CHANGED
|
@@ -5,7 +5,6 @@ from datetime import date, datetime, timezone
|
|
|
5
5
|
from prettytable import PrettyTable
|
|
6
6
|
|
|
7
7
|
from nectarapi.exceptions import InvalidParameters, UnknownKey
|
|
8
|
-
from nectargraphenebase.py23 import integer_types, string_types
|
|
9
8
|
|
|
10
9
|
from .account import Account
|
|
11
10
|
from .blockchainobject import BlockchainObject
|
|
@@ -42,7 +41,7 @@ class Vote(BlockchainObject):
|
|
|
42
41
|
elif kwargs.get("hive_instance"):
|
|
43
42
|
blockchain_instance = kwargs["hive_instance"]
|
|
44
43
|
self.blockchain = blockchain_instance or shared_blockchain_instance()
|
|
45
|
-
if isinstance(voter,
|
|
44
|
+
if isinstance(voter, str) and authorperm is not None:
|
|
46
45
|
[author, permlink] = resolve_authorperm(authorperm)
|
|
47
46
|
self["voter"] = voter
|
|
48
47
|
self["author"] = author
|
|
@@ -138,20 +137,20 @@ class Vote(BlockchainObject):
|
|
|
138
137
|
"reputation",
|
|
139
138
|
]
|
|
140
139
|
for p in parse_int:
|
|
141
|
-
if p in vote and isinstance(vote.get(p),
|
|
140
|
+
if p in vote and isinstance(vote.get(p), str):
|
|
142
141
|
vote[p] = int(vote.get(p, "0"))
|
|
143
142
|
|
|
144
|
-
if "time" in vote and isinstance(vote.get("time"),
|
|
143
|
+
if "time" in vote and isinstance(vote.get("time"), str) and vote.get("time") != "":
|
|
145
144
|
vote["time"] = formatTimeString(vote.get("time", "1970-01-01T00:00:00"))
|
|
146
145
|
elif (
|
|
147
146
|
"timestamp" in vote
|
|
148
|
-
and isinstance(vote.get("timestamp"),
|
|
147
|
+
and isinstance(vote.get("timestamp"), str)
|
|
149
148
|
and vote.get("timestamp") != ""
|
|
150
149
|
):
|
|
151
150
|
vote["time"] = formatTimeString(vote.get("timestamp", "1970-01-01T00:00:00"))
|
|
152
151
|
elif (
|
|
153
152
|
"last_update" in vote
|
|
154
|
-
and isinstance(vote.get("last_update"),
|
|
153
|
+
and isinstance(vote.get("last_update"), str)
|
|
155
154
|
and vote.get("last_update") != ""
|
|
156
155
|
):
|
|
157
156
|
vote["last_update"] = formatTimeString(vote.get("last_update", "1970-01-01T00:00:00"))
|
|
@@ -178,7 +177,7 @@ class Vote(BlockchainObject):
|
|
|
178
177
|
"reputation",
|
|
179
178
|
]
|
|
180
179
|
for p in parse_int:
|
|
181
|
-
if p in output and isinstance(output[p],
|
|
180
|
+
if p in output and isinstance(output[p], int):
|
|
182
181
|
output[p] = str(output[p])
|
|
183
182
|
return json.loads(str(json.dumps(output)))
|
|
184
183
|
|
|
@@ -456,7 +455,7 @@ class ActiveVotes(VotesObject):
|
|
|
456
455
|
authorperm["author"], authorperm["permlink"], api="condenser"
|
|
457
456
|
)
|
|
458
457
|
authorperm = authorperm["authorperm"]
|
|
459
|
-
elif isinstance(authorperm,
|
|
458
|
+
elif isinstance(authorperm, str):
|
|
460
459
|
[author, permlink] = resolve_authorperm(authorperm)
|
|
461
460
|
if self.blockchain.rpc.get_use_appbase():
|
|
462
461
|
self.blockchain.rpc.set_next_node_on_empty_reply(False)
|
|
@@ -534,7 +533,7 @@ class AccountVotes(VotesObject):
|
|
|
534
533
|
time = x.get("last_update", "")
|
|
535
534
|
if time != "":
|
|
536
535
|
x["time"] = time
|
|
537
|
-
if time != "" and isinstance(time,
|
|
536
|
+
if time != "" and isinstance(time, str):
|
|
538
537
|
d_time = formatTimeString(time)
|
|
539
538
|
elif isinstance(time, datetime):
|
|
540
539
|
d_time = time
|
nectar/wallet.py
CHANGED
nectarapi/exceptions.py
CHANGED
|
@@ -19,37 +19,43 @@ def decodeRPCErrorMsg(e):
|
|
|
19
19
|
return str(e)
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
class
|
|
22
|
+
class NectarApiException(Exception):
|
|
23
|
+
"""NectarApiException base Exception."""
|
|
24
|
+
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class UnauthorizedError(NectarApiException):
|
|
23
29
|
"""UnauthorizedError Exception."""
|
|
24
30
|
|
|
25
31
|
pass
|
|
26
32
|
|
|
27
33
|
|
|
28
|
-
class RPCConnection(
|
|
34
|
+
class RPCConnection(NectarApiException):
|
|
29
35
|
"""RPCConnection Exception."""
|
|
30
36
|
|
|
31
37
|
pass
|
|
32
38
|
|
|
33
39
|
|
|
34
|
-
class RPCError(
|
|
40
|
+
class RPCError(NectarApiException):
|
|
35
41
|
"""RPCError Exception."""
|
|
36
42
|
|
|
37
43
|
pass
|
|
38
44
|
|
|
39
45
|
|
|
40
|
-
class RPCErrorDoRetry(
|
|
46
|
+
class RPCErrorDoRetry(NectarApiException):
|
|
41
47
|
"""RPCErrorDoRetry Exception."""
|
|
42
48
|
|
|
43
49
|
pass
|
|
44
50
|
|
|
45
51
|
|
|
46
|
-
class NumRetriesReached(
|
|
52
|
+
class NumRetriesReached(NectarApiException):
|
|
47
53
|
"""NumRetriesReached Exception."""
|
|
48
54
|
|
|
49
55
|
pass
|
|
50
56
|
|
|
51
57
|
|
|
52
|
-
class CallRetriesReached(
|
|
58
|
+
class CallRetriesReached(NectarApiException):
|
|
53
59
|
"""CallRetriesReached Exception. Only for internal use"""
|
|
54
60
|
|
|
55
61
|
pass
|
|
@@ -91,33 +97,33 @@ class FilteredItemNotFound(RPCError):
|
|
|
91
97
|
pass
|
|
92
98
|
|
|
93
99
|
|
|
94
|
-
class InvalidEndpointUrl(
|
|
100
|
+
class InvalidEndpointUrl(NectarApiException):
|
|
95
101
|
pass
|
|
96
102
|
|
|
97
103
|
|
|
98
|
-
class InvalidParameters(
|
|
104
|
+
class InvalidParameters(NectarApiException):
|
|
99
105
|
pass
|
|
100
106
|
|
|
101
107
|
|
|
102
|
-
class SupportedByHivemind(
|
|
108
|
+
class SupportedByHivemind(NectarApiException):
|
|
103
109
|
pass
|
|
104
110
|
|
|
105
111
|
|
|
106
|
-
class UnnecessarySignatureDetected(
|
|
112
|
+
class UnnecessarySignatureDetected(NectarApiException):
|
|
107
113
|
pass
|
|
108
114
|
|
|
109
115
|
|
|
110
|
-
class WorkingNodeMissing(
|
|
116
|
+
class WorkingNodeMissing(NectarApiException):
|
|
111
117
|
pass
|
|
112
118
|
|
|
113
119
|
|
|
114
|
-
class TimeoutException(
|
|
120
|
+
class TimeoutException(NectarApiException):
|
|
115
121
|
pass
|
|
116
122
|
|
|
117
123
|
|
|
118
|
-
class VotedBeforeWaitTimeReached(
|
|
124
|
+
class VotedBeforeWaitTimeReached(NectarApiException):
|
|
119
125
|
pass
|
|
120
126
|
|
|
121
127
|
|
|
122
|
-
class UnknownTransaction(
|
|
128
|
+
class UnknownTransaction(NectarApiException):
|
|
123
129
|
pass
|
nectarapi/graphenerpc.py
CHANGED
|
@@ -46,7 +46,7 @@ log = logging.getLogger(__name__)
|
|
|
46
46
|
|
|
47
47
|
|
|
48
48
|
class SessionInstance(object):
|
|
49
|
-
"""
|
|
49
|
+
"""Singleton for the Session Instance"""
|
|
50
50
|
|
|
51
51
|
instance = None
|
|
52
52
|
|
|
@@ -59,7 +59,7 @@ def set_session_instance(instance):
|
|
|
59
59
|
def shared_session_instance():
|
|
60
60
|
"""Get session instance"""
|
|
61
61
|
if REQUEST_MODULE is None:
|
|
62
|
-
raise Exception()
|
|
62
|
+
raise Exception("Requests module is not available.")
|
|
63
63
|
if not SessionInstance.instance:
|
|
64
64
|
SessionInstance.instance = requests.Session()
|
|
65
65
|
return SessionInstance.instance
|
|
@@ -68,7 +68,7 @@ def shared_session_instance():
|
|
|
68
68
|
def create_ws_instance(use_ssl=True, enable_multithread=True):
|
|
69
69
|
"""Get websocket instance"""
|
|
70
70
|
if WEBSOCKET_MODULE is None:
|
|
71
|
-
raise Exception()
|
|
71
|
+
raise Exception("WebSocket module is not available.")
|
|
72
72
|
if use_ssl:
|
|
73
73
|
ssl_defaults = ssl.get_default_verify_paths()
|
|
74
74
|
sslopt_ca_certs = {"ca_certs": ssl_defaults.cafile}
|
|
@@ -79,47 +79,24 @@ def create_ws_instance(use_ssl=True, enable_multithread=True):
|
|
|
79
79
|
|
|
80
80
|
class GrapheneRPC(object):
|
|
81
81
|
"""
|
|
82
|
-
This class allows
|
|
82
|
+
This class allows calling API methods synchronously, without callbacks.
|
|
83
83
|
|
|
84
84
|
It logs warnings and errors.
|
|
85
85
|
|
|
86
86
|
:param str urls: Either a single Websocket/Http URL, or a list of URLs
|
|
87
87
|
:param str user: Username for Authentication
|
|
88
88
|
:param str password: Password for Authentication
|
|
89
|
-
:param int num_retries:
|
|
90
|
-
:param int num_retries_call:
|
|
91
|
-
:param int timeout: Timeout setting for
|
|
92
|
-
:param bool autoconnect:
|
|
93
|
-
:param bool use_condenser: Use the old condenser_api
|
|
94
|
-
|
|
95
|
-
:param
|
|
96
|
-
:param dict custom_chains: custom chain which should be added to the known chains
|
|
97
|
-
|
|
98
|
-
Available APIs:
|
|
99
|
-
|
|
100
|
-
* database
|
|
101
|
-
* network_node
|
|
102
|
-
* network_broadcast
|
|
103
|
-
|
|
104
|
-
Usage:
|
|
105
|
-
|
|
106
|
-
.. code-block:: python
|
|
107
|
-
|
|
108
|
-
from nectarapi.graphenerpc import GrapheneRPC
|
|
109
|
-
ws = GrapheneRPC("wss://steemd.pevo.science","","")
|
|
110
|
-
print(ws.get_account_count())
|
|
111
|
-
|
|
112
|
-
ws = GrapheneRPC("https://api.steemit.com","","")
|
|
113
|
-
print(ws.get_account_count())
|
|
114
|
-
|
|
115
|
-
.. note:: This class allows to call methods available via
|
|
116
|
-
websocket. If you want to use the notification
|
|
117
|
-
subsystem, please use ``GrapheneWebsocket`` instead.
|
|
118
|
-
|
|
89
|
+
:param int num_retries: Number of retries for node connection (default is 100)
|
|
90
|
+
:param int num_retries_call: Number of retries for RPC calls on node error (default is 5)
|
|
91
|
+
:param int timeout: Timeout setting for HTTP nodes (default is 60)
|
|
92
|
+
:param bool autoconnect: Automatically connect on initialization (default is True)
|
|
93
|
+
:param bool use_condenser: Use the old condenser_api RPC protocol
|
|
94
|
+
:param bool use_tor: Use Tor proxy for connections
|
|
95
|
+
:param dict custom_chains: Custom chains to add to known chains
|
|
119
96
|
"""
|
|
120
97
|
|
|
121
98
|
def __init__(self, urls, user=None, password=None, **kwargs):
|
|
122
|
-
"""
|
|
99
|
+
"""Initialize the RPC client."""
|
|
123
100
|
self.rpc_methods = {"offline": -1, "ws": 0, "jsonrpc": 1, "wsappbase": 2, "appbase": 3}
|
|
124
101
|
self.current_rpc = self.rpc_methods["ws"]
|
|
125
102
|
self._request_id = 0
|
|
@@ -454,11 +431,12 @@ class GrapheneRPC(object):
|
|
|
454
431
|
:raises ValueError: if the server does not respond in proper JSON format
|
|
455
432
|
:raises RPCError: if the server returns an error
|
|
456
433
|
"""
|
|
457
|
-
log.debug(json.dumps(payload))
|
|
434
|
+
log.debug(f"Payload: {json.dumps(payload)}")
|
|
458
435
|
if self.nodes.working_nodes_count == 0:
|
|
459
|
-
raise WorkingNodeMissing
|
|
436
|
+
raise WorkingNodeMissing("No working nodes available.")
|
|
460
437
|
if self.url is None:
|
|
461
438
|
raise RPCConnection("RPC is not connected!")
|
|
439
|
+
|
|
462
440
|
reply = {}
|
|
463
441
|
response = None
|
|
464
442
|
while True:
|
|
@@ -488,13 +466,9 @@ class GrapheneRPC(object):
|
|
|
488
466
|
except KeyboardInterrupt:
|
|
489
467
|
raise
|
|
490
468
|
except WebSocketConnectionClosedException as e:
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
self.rpcconnect()
|
|
495
|
-
else:
|
|
496
|
-
# self.nodes.sleep_and_check_retries(str(e), sleep=True, call_retry=True)
|
|
497
|
-
self.rpcconnect(next_url=False)
|
|
469
|
+
self.nodes.increase_error_cnt()
|
|
470
|
+
self.nodes.sleep_and_check_retries(str(e), sleep=False, call_retry=False)
|
|
471
|
+
self.rpcconnect()
|
|
498
472
|
except ConnectionError as e:
|
|
499
473
|
self.nodes.increase_error_cnt()
|
|
500
474
|
self.nodes.sleep_and_check_retries(str(e), sleep=False, call_retry=False)
|
|
@@ -508,48 +482,47 @@ class GrapheneRPC(object):
|
|
|
508
482
|
self.nodes.sleep_and_check_retries(str(e), sleep=False, call_retry=False)
|
|
509
483
|
self.rpcconnect()
|
|
510
484
|
|
|
511
|
-
ret = {}
|
|
512
485
|
try:
|
|
513
486
|
if response is None:
|
|
514
|
-
|
|
487
|
+
try:
|
|
488
|
+
ret = json.loads(reply, strict=False)
|
|
489
|
+
except ValueError:
|
|
490
|
+
log.error(f"Non-JSON response: {reply} Node: {self.url}")
|
|
491
|
+
self._check_for_server_error(reply)
|
|
492
|
+
raise RPCError("Invalid response format")
|
|
515
493
|
else:
|
|
516
494
|
ret = response.json()
|
|
517
495
|
except ValueError:
|
|
518
496
|
self._check_for_server_error(reply)
|
|
519
497
|
|
|
520
|
-
log.debug(json.dumps(reply))
|
|
498
|
+
log.debug(f"Reply: {json.dumps(reply)}")
|
|
521
499
|
|
|
522
500
|
if isinstance(ret, dict) and "error" in ret:
|
|
523
|
-
if
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
raise RPCError(ret["error"]["message"])
|
|
527
|
-
else:
|
|
528
|
-
if isinstance(ret, list):
|
|
529
|
-
ret_list = []
|
|
530
|
-
for r in ret:
|
|
531
|
-
if isinstance(r, dict) and "error" in r:
|
|
532
|
-
if "detail" in r["error"]:
|
|
533
|
-
raise RPCError(r["error"]["detail"])
|
|
534
|
-
else:
|
|
535
|
-
raise RPCError(r["error"]["message"])
|
|
536
|
-
elif isinstance(r, dict) and "result" in r:
|
|
537
|
-
ret_list.append(r["result"])
|
|
538
|
-
else:
|
|
539
|
-
ret_list.append(r)
|
|
540
|
-
self.nodes.reset_error_cnt_call()
|
|
541
|
-
return ret_list
|
|
542
|
-
elif isinstance(ret, dict) and "result" in ret:
|
|
543
|
-
self.nodes.reset_error_cnt_call()
|
|
544
|
-
return ret["result"]
|
|
545
|
-
elif isinstance(ret, int):
|
|
546
|
-
raise RPCError(
|
|
547
|
-
"Client returned invalid format. Expected JSON! Output: %s" % (str(ret))
|
|
501
|
+
if isinstance(ret["error"], dict):
|
|
502
|
+
error_message = ret["error"].get(
|
|
503
|
+
"detail", ret["error"].get("message", "Unknown error")
|
|
548
504
|
)
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
505
|
+
raise RPCError(error_message)
|
|
506
|
+
elif isinstance(ret, list):
|
|
507
|
+
ret_list = []
|
|
508
|
+
for r in ret:
|
|
509
|
+
if isinstance(r, dict) and "error" in r:
|
|
510
|
+
error_message = r["error"].get(
|
|
511
|
+
"detail", r["error"].get("message", "Unknown error")
|
|
512
|
+
)
|
|
513
|
+
raise RPCError(error_message)
|
|
514
|
+
elif isinstance(r, dict) and "result" in r:
|
|
515
|
+
ret_list.append(r["result"])
|
|
516
|
+
else:
|
|
517
|
+
ret_list.append(r)
|
|
518
|
+
self.nodes.reset_error_cnt_call()
|
|
519
|
+
return ret_list
|
|
520
|
+
elif isinstance(ret, dict) and "result" in ret:
|
|
521
|
+
self.nodes.reset_error_cnt_call()
|
|
522
|
+
return ret["result"]
|
|
523
|
+
else:
|
|
524
|
+
log.error(f"Unexpected response format: {ret} Node: {self.url}")
|
|
525
|
+
raise RPCError(f"Unexpected response format: {ret}")
|
|
553
526
|
|
|
554
527
|
# End of Deprecated methods
|
|
555
528
|
####################################################################
|
nectarapi/version.py
CHANGED
nectarbase/ledgertransactions.py
CHANGED
|
@@ -3,7 +3,6 @@ import logging
|
|
|
3
3
|
|
|
4
4
|
from nectargraphenebase.account import PublicKey
|
|
5
5
|
from nectargraphenebase.chains import known_chains
|
|
6
|
-
from nectargraphenebase.py23 import py23_bytes
|
|
7
6
|
from nectargraphenebase.types import (
|
|
8
7
|
Array,
|
|
9
8
|
Signature,
|
|
@@ -54,7 +53,7 @@ class Ledger_Transaction(GrapheneUnsigned_Transaction):
|
|
|
54
53
|
dongle = getDongle(True)
|
|
55
54
|
apdu_list = self.build_apdu(path, chain)
|
|
56
55
|
for apdu in apdu_list:
|
|
57
|
-
result = dongle.exchange(
|
|
56
|
+
result = dongle.exchange(bytes(apdu))
|
|
58
57
|
dongle.close()
|
|
59
58
|
sigs = []
|
|
60
59
|
signature = result
|
|
@@ -67,7 +66,7 @@ class Ledger_Transaction(GrapheneUnsigned_Transaction):
|
|
|
67
66
|
|
|
68
67
|
dongle = getDongle(True)
|
|
69
68
|
apdu = self.build_apdu_pubkey(path, request_screen_approval)
|
|
70
|
-
result = dongle.exchange(
|
|
69
|
+
result = dongle.exchange(bytes(apdu))
|
|
71
70
|
dongle.close()
|
|
72
71
|
offset = 1 + result[0]
|
|
73
72
|
address = result[offset + 1 : offset + 1 + result[offset]]
|