hive-nectar 0.0.6__py3-none-any.whl → 0.0.9__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.6.dist-info → hive_nectar-0.0.9.dist-info}/METADATA +5 -3
- hive_nectar-0.0.9.dist-info/RECORD +91 -0
- nectar/__init__.py +1 -0
- nectar/account.py +44 -48
- nectar/amount.py +6 -11
- nectar/block.py +8 -9
- nectar/blockchain.py +4 -5
- 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 +527 -181
- 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/nodelist.py +83 -7
- nectar/price.py +6 -13
- nectar/rc.py +1 -2
- nectar/steem.py +3 -4
- nectar/storage.py +3 -4
- nectar/transactionbuilder.py +12 -3
- nectar/version.py +1 -1
- nectar/vote.py +8 -9
- nectar/wallet.py +1 -1
- nectarapi/__init__.py +1 -0
- nectarapi/exceptions.py +20 -14
- nectarapi/version.py +1 -1
- nectarbase/__init__.py +1 -0
- 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 +1 -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/operations.py +2 -0
- nectargraphenebase/signedtransactions.py +10 -9
- nectargraphenebase/types.py +9 -19
- nectargraphenebase/unsignedtransactions.py +21 -28
- nectargraphenebase/version.py +1 -1
- nectarstorage/__init__.py +21 -1
- nectarstorage/masterpassword.py +2 -3
- nectarstorage/sqlite.py +1 -1
- hive_nectar-0.0.6.dist-info/RECORD +0 -92
- nectargraphenebase/py23.py +0 -38
- {hive_nectar-0.0.6.dist-info → hive_nectar-0.0.9.dist-info}/WHEEL +0 -0
- {hive_nectar-0.0.6.dist-info → hive_nectar-0.0.9.dist-info}/entry_points.txt +0 -0
- {hive_nectar-0.0.6.dist-info → hive_nectar-0.0.9.dist-info}/licenses/LICENSE.txt +0 -0
nectar/conveyor.py
CHANGED
|
@@ -10,7 +10,6 @@ from datetime import datetime, timezone
|
|
|
10
10
|
import requests
|
|
11
11
|
|
|
12
12
|
from nectargraphenebase.ecdsasig import sign_message
|
|
13
|
-
from nectargraphenebase.py23 import py23_bytes
|
|
14
13
|
|
|
15
14
|
from .account import Account
|
|
16
15
|
from .instance import shared_blockchain_instance
|
|
@@ -64,7 +63,7 @@ class Conveyor(object):
|
|
|
64
63
|
self.id = 0
|
|
65
64
|
self.ENCODING = "utf-8"
|
|
66
65
|
self.TIMEFORMAT = "%Y-%m-%dT%H:%M:%S.%f"
|
|
67
|
-
self.K = hashlib.sha256(
|
|
66
|
+
self.K = hashlib.sha256(bytes("steem_jsonrpc_auth", self.ENCODING)).digest()
|
|
68
67
|
|
|
69
68
|
def prehash_message(self, timestamp, account, method, params, nonce):
|
|
70
69
|
"""Prepare a hash for the Conveyor API request with SHA256 according
|
|
@@ -78,7 +77,7 @@ class Conveyor(object):
|
|
|
78
77
|
:param bytes nonce: random 8 bytes
|
|
79
78
|
|
|
80
79
|
"""
|
|
81
|
-
first = hashlib.sha256(
|
|
80
|
+
first = hashlib.sha256(bytes(timestamp + account + method + params, self.ENCODING))
|
|
82
81
|
return self.K + first.digest() + nonce
|
|
83
82
|
|
|
84
83
|
def _request(self, account, method, params, key):
|
|
@@ -91,7 +90,7 @@ class Conveyor(object):
|
|
|
91
90
|
:param str key: Steem posting key for signing
|
|
92
91
|
|
|
93
92
|
"""
|
|
94
|
-
params_bytes =
|
|
93
|
+
params_bytes = bytes(json.dumps(params), self.ENCODING)
|
|
95
94
|
params_enc = base64.b64encode(params_bytes).decode(self.ENCODING)
|
|
96
95
|
timestamp = datetime.now(timezone.utc).strftime(self.TIMEFORMAT)[:-3] + "Z"
|
|
97
96
|
nonce_int = random.getrandbits(64)
|
nectar/exceptions.py
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
class
|
|
4
|
+
class NectarException(Exception):
|
|
5
|
+
"""Base exception for all Nectar-related errors"""
|
|
6
|
+
|
|
7
|
+
pass
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class WalletExists(NectarException):
|
|
5
11
|
"""A wallet has already been created and requires a password to be
|
|
6
12
|
unlocked by means of :func:`nectar.wallet.Wallet.unlock`.
|
|
7
13
|
"""
|
|
@@ -9,85 +15,85 @@ class WalletExists(Exception):
|
|
|
9
15
|
pass
|
|
10
16
|
|
|
11
17
|
|
|
12
|
-
class RPCConnectionRequired(
|
|
18
|
+
class RPCConnectionRequired(NectarException):
|
|
13
19
|
"""An RPC connection is required"""
|
|
14
20
|
|
|
15
21
|
pass
|
|
16
22
|
|
|
17
23
|
|
|
18
|
-
class InvalidMemoKeyException(
|
|
24
|
+
class InvalidMemoKeyException(NectarException):
|
|
19
25
|
"""Memo key in message is invalid"""
|
|
20
26
|
|
|
21
27
|
pass
|
|
22
28
|
|
|
23
29
|
|
|
24
|
-
class WrongMemoKey(
|
|
30
|
+
class WrongMemoKey(NectarException):
|
|
25
31
|
"""The memo provided is not equal the one on the blockchain"""
|
|
26
32
|
|
|
27
33
|
pass
|
|
28
34
|
|
|
29
35
|
|
|
30
|
-
class OfflineHasNoRPCException(
|
|
36
|
+
class OfflineHasNoRPCException(NectarException):
|
|
31
37
|
"""When in offline mode, we don't have RPC"""
|
|
32
38
|
|
|
33
39
|
pass
|
|
34
40
|
|
|
35
41
|
|
|
36
|
-
class AccountExistsException(
|
|
42
|
+
class AccountExistsException(NectarException):
|
|
37
43
|
"""The requested account already exists"""
|
|
38
44
|
|
|
39
45
|
pass
|
|
40
46
|
|
|
41
47
|
|
|
42
|
-
class AccountDoesNotExistsException(
|
|
48
|
+
class AccountDoesNotExistsException(NectarException):
|
|
43
49
|
"""The account does not exist"""
|
|
44
50
|
|
|
45
51
|
pass
|
|
46
52
|
|
|
47
53
|
|
|
48
|
-
class AssetDoesNotExistsException(
|
|
54
|
+
class AssetDoesNotExistsException(NectarException):
|
|
49
55
|
"""The asset does not exist"""
|
|
50
56
|
|
|
51
57
|
pass
|
|
52
58
|
|
|
53
59
|
|
|
54
|
-
class InvalidAssetException(
|
|
60
|
+
class InvalidAssetException(NectarException):
|
|
55
61
|
"""An invalid asset has been provided"""
|
|
56
62
|
|
|
57
63
|
pass
|
|
58
64
|
|
|
59
65
|
|
|
60
|
-
class InsufficientAuthorityError(
|
|
66
|
+
class InsufficientAuthorityError(NectarException):
|
|
61
67
|
"""The transaction requires signature of a higher authority"""
|
|
62
68
|
|
|
63
69
|
pass
|
|
64
70
|
|
|
65
71
|
|
|
66
|
-
class VotingInvalidOnArchivedPost(
|
|
72
|
+
class VotingInvalidOnArchivedPost(NectarException):
|
|
67
73
|
"""The transaction requires signature of a higher authority"""
|
|
68
74
|
|
|
69
75
|
pass
|
|
70
76
|
|
|
71
77
|
|
|
72
|
-
class MissingKeyError(
|
|
78
|
+
class MissingKeyError(NectarException):
|
|
73
79
|
"""A required key couldn't be found in the wallet"""
|
|
74
80
|
|
|
75
81
|
pass
|
|
76
82
|
|
|
77
83
|
|
|
78
|
-
class InvalidWifError(
|
|
84
|
+
class InvalidWifError(NectarException):
|
|
79
85
|
"""The provided private Key has an invalid format"""
|
|
80
86
|
|
|
81
87
|
pass
|
|
82
88
|
|
|
83
89
|
|
|
84
|
-
class BlockDoesNotExistsException(
|
|
90
|
+
class BlockDoesNotExistsException(NectarException):
|
|
85
91
|
"""The block does not exist"""
|
|
86
92
|
|
|
87
93
|
pass
|
|
88
94
|
|
|
89
95
|
|
|
90
|
-
class NoWalletException(
|
|
96
|
+
class NoWalletException(NectarException):
|
|
91
97
|
"""No Wallet could be found, please use :func:`nectar.wallet.Wallet.create` to
|
|
92
98
|
create a new wallet
|
|
93
99
|
"""
|
|
@@ -95,55 +101,55 @@ class NoWalletException(Exception):
|
|
|
95
101
|
pass
|
|
96
102
|
|
|
97
103
|
|
|
98
|
-
class WitnessDoesNotExistsException(
|
|
104
|
+
class WitnessDoesNotExistsException(NectarException):
|
|
99
105
|
"""The witness does not exist"""
|
|
100
106
|
|
|
101
107
|
pass
|
|
102
108
|
|
|
103
109
|
|
|
104
|
-
class ContentDoesNotExistsException(
|
|
110
|
+
class ContentDoesNotExistsException(NectarException):
|
|
105
111
|
"""The content does not exist"""
|
|
106
112
|
|
|
107
113
|
pass
|
|
108
114
|
|
|
109
115
|
|
|
110
|
-
class VoteDoesNotExistsException(
|
|
116
|
+
class VoteDoesNotExistsException(NectarException):
|
|
111
117
|
"""The vote does not exist"""
|
|
112
118
|
|
|
113
119
|
pass
|
|
114
120
|
|
|
115
121
|
|
|
116
|
-
class WrongMasterPasswordException(
|
|
122
|
+
class WrongMasterPasswordException(NectarException):
|
|
117
123
|
"""The password provided could not properly unlock the wallet"""
|
|
118
124
|
|
|
119
125
|
pass
|
|
120
126
|
|
|
121
127
|
|
|
122
|
-
class VestingBalanceDoesNotExistsException(
|
|
128
|
+
class VestingBalanceDoesNotExistsException(NectarException):
|
|
123
129
|
"""Vesting Balance does not exist"""
|
|
124
130
|
|
|
125
131
|
pass
|
|
126
132
|
|
|
127
133
|
|
|
128
|
-
class InvalidMessageSignature(
|
|
134
|
+
class InvalidMessageSignature(NectarException):
|
|
129
135
|
"""The message signature does not fit the message"""
|
|
130
136
|
|
|
131
137
|
pass
|
|
132
138
|
|
|
133
139
|
|
|
134
|
-
class NoWriteAccess(
|
|
140
|
+
class NoWriteAccess(NectarException):
|
|
135
141
|
"""Cannot store to sqlite3 database due to missing write access"""
|
|
136
142
|
|
|
137
143
|
pass
|
|
138
144
|
|
|
139
145
|
|
|
140
|
-
class BatchedCallsNotSupported(
|
|
146
|
+
class BatchedCallsNotSupported(NectarException):
|
|
141
147
|
"""Batch calls do not work"""
|
|
142
148
|
|
|
143
149
|
pass
|
|
144
150
|
|
|
145
151
|
|
|
146
|
-
class BlockWaitTimeExceeded(
|
|
152
|
+
class BlockWaitTimeExceeded(NectarException):
|
|
147
153
|
"""Wait time for new block exceeded"""
|
|
148
154
|
|
|
149
155
|
pass
|
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/nodelist.py
CHANGED
|
@@ -243,7 +243,12 @@ class NodeList(list):
|
|
|
243
243
|
cnt += 1
|
|
244
244
|
try:
|
|
245
245
|
account = Account("nectarflower", blockchain_instance=steem)
|
|
246
|
-
|
|
246
|
+
# Metadata is stored in the account's json_metadata field (not posting_json_metadata)
|
|
247
|
+
raw_meta = account.get("json_metadata") or ""
|
|
248
|
+
try:
|
|
249
|
+
metadata = json.loads(raw_meta) if raw_meta else None
|
|
250
|
+
except Exception:
|
|
251
|
+
metadata = None
|
|
247
252
|
except Exception as e:
|
|
248
253
|
log.warning(f"Error fetching metadata (attempt {cnt}): {str(e)}")
|
|
249
254
|
steem.rpc.next()
|
|
@@ -257,10 +262,30 @@ class NodeList(list):
|
|
|
257
262
|
report = metadata.get("report", [])
|
|
258
263
|
failing_nodes = metadata.get("failing_nodes", {})
|
|
259
264
|
parameter = metadata.get("parameter", {})
|
|
260
|
-
benchmarks = parameter.get("benchmarks"
|
|
261
|
-
|
|
262
|
-
#
|
|
263
|
-
|
|
265
|
+
benchmarks = parameter.get("benchmarks")
|
|
266
|
+
|
|
267
|
+
# Determine benchmark names. If not explicitly provided in metadata parameters, derive them
|
|
268
|
+
# by inspecting the keys of the report entries and filtering out the non-benchmark fields.
|
|
269
|
+
if benchmarks and isinstance(benchmarks, dict):
|
|
270
|
+
benchmark_names: list[str] = list(benchmarks.keys())
|
|
271
|
+
else:
|
|
272
|
+
benchmark_names = []
|
|
273
|
+
# Common non-benchmark keys present in every report entry
|
|
274
|
+
_skip_keys = {
|
|
275
|
+
"node",
|
|
276
|
+
"version",
|
|
277
|
+
"hive",
|
|
278
|
+
"weighted_score",
|
|
279
|
+
"tests_completed",
|
|
280
|
+
}
|
|
281
|
+
# Collect benchmark names dynamically from the report section
|
|
282
|
+
for _entry in report:
|
|
283
|
+
if isinstance(_entry, dict):
|
|
284
|
+
for _k in _entry.keys():
|
|
285
|
+
if _k not in _skip_keys and _k not in benchmark_names:
|
|
286
|
+
benchmark_names.append(_k)
|
|
287
|
+
# Sort for deterministic ordering
|
|
288
|
+
benchmark_names.sort()
|
|
264
289
|
|
|
265
290
|
if weights is None:
|
|
266
291
|
weights_dict = {}
|
|
@@ -294,6 +319,7 @@ class NodeList(list):
|
|
|
294
319
|
|
|
295
320
|
for node in self:
|
|
296
321
|
new_node = node.copy()
|
|
322
|
+
node_was_updated = False
|
|
297
323
|
|
|
298
324
|
# Check against report data
|
|
299
325
|
for report_node in report:
|
|
@@ -319,17 +345,67 @@ class NodeList(list):
|
|
|
319
345
|
weighted_score = score * weights_dict.get(benchmark, 0)
|
|
320
346
|
scores.append(weighted_score)
|
|
321
347
|
|
|
322
|
-
|
|
323
|
-
|
|
348
|
+
# Prefer the pre-computed weighted_score from the metadata if present; fall back to
|
|
349
|
+
# the locally calculated score otherwise.
|
|
350
|
+
if "weighted_score" in report_node and isinstance(report_node["weighted_score"], (int, float)):
|
|
351
|
+
new_node["score"] = report_node["weighted_score"]
|
|
352
|
+
else:
|
|
353
|
+
sum_score = sum(scores)
|
|
354
|
+
new_node["score"] = sum_score
|
|
355
|
+
node_was_updated = True
|
|
324
356
|
break
|
|
325
357
|
|
|
326
358
|
# Check if node is in failing nodes list
|
|
327
359
|
if node["url"] in failing_nodes:
|
|
328
360
|
failing_count += 1
|
|
329
361
|
new_node["score"] = -1
|
|
362
|
+
elif not node_was_updated:
|
|
363
|
+
# If node wasn't part of the metadata report, reset its score so it
|
|
364
|
+
# doesn't overshadow the authoritative ordering
|
|
365
|
+
new_node["score"] = 0
|
|
330
366
|
|
|
331
367
|
new_nodes.append(new_node)
|
|
332
368
|
|
|
369
|
+
# ------------------------------------------------------------
|
|
370
|
+
# Ensure that all nodes present in the metadata are included
|
|
371
|
+
# in the final list, even if they were not part of the default
|
|
372
|
+
# hard-coded set.
|
|
373
|
+
# ------------------------------------------------------------
|
|
374
|
+
existing_urls: set[str] = {n["url"] for n in new_nodes}
|
|
375
|
+
|
|
376
|
+
# Add nodes found in the report section
|
|
377
|
+
for report_node in report:
|
|
378
|
+
url = report_node.get("node")
|
|
379
|
+
if not url or url in existing_urls:
|
|
380
|
+
continue
|
|
381
|
+
new_entry = {
|
|
382
|
+
"url": url,
|
|
383
|
+
"version": report_node.get("version", "0.0.0"),
|
|
384
|
+
"type": "appbase",
|
|
385
|
+
"owner": report_node.get("owner", "unknown"),
|
|
386
|
+
"hive": report_node.get("hive", True),
|
|
387
|
+
"score": report_node.get("weighted_score", 0),
|
|
388
|
+
}
|
|
389
|
+
new_nodes.append(new_entry)
|
|
390
|
+
existing_urls.add(url)
|
|
391
|
+
|
|
392
|
+
# Add nodes listed as failing but missing
|
|
393
|
+
for url in failing_nodes.keys():
|
|
394
|
+
if url in existing_urls:
|
|
395
|
+
continue
|
|
396
|
+
new_nodes.append(
|
|
397
|
+
{
|
|
398
|
+
"url": url,
|
|
399
|
+
"version": "unknown",
|
|
400
|
+
"type": "appbase",
|
|
401
|
+
"owner": "unknown",
|
|
402
|
+
"hive": True,
|
|
403
|
+
"score": -1,
|
|
404
|
+
}
|
|
405
|
+
)
|
|
406
|
+
existing_urls.add(url)
|
|
407
|
+
|
|
408
|
+
# Re-initialise internal list
|
|
333
409
|
super(NodeList, self).__init__(new_nodes)
|
|
334
410
|
|
|
335
411
|
def get_nodes(
|
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/storage.py
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
2
|
import logging
|
|
3
3
|
|
|
4
|
+
from nectarstorage import SqliteConfigurationStore, SqliteEncryptedKeyStore
|
|
5
|
+
|
|
4
6
|
from .nodelist import NodeList
|
|
5
7
|
|
|
6
8
|
log = logging.getLogger(__name__)
|
|
7
9
|
log.setLevel(logging.DEBUG)
|
|
8
10
|
log.addHandler(logging.StreamHandler())
|
|
9
|
-
|
|
10
|
-
SqliteConfigurationStore,
|
|
11
|
-
SqliteEncryptedKeyStore,
|
|
12
|
-
)
|
|
11
|
+
|
|
13
12
|
|
|
14
13
|
timeformat = "%Y%m%d-%H%M%S"
|
|
15
14
|
|
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
|