hive-nectar 0.0.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of hive-nectar might be problematic. Click here for more details.

Files changed (86) hide show
  1. hive_nectar-0.0.2.dist-info/METADATA +182 -0
  2. hive_nectar-0.0.2.dist-info/RECORD +86 -0
  3. hive_nectar-0.0.2.dist-info/WHEEL +4 -0
  4. hive_nectar-0.0.2.dist-info/entry_points.txt +2 -0
  5. hive_nectar-0.0.2.dist-info/licenses/LICENSE.txt +23 -0
  6. nectar/__init__.py +32 -0
  7. nectar/account.py +4371 -0
  8. nectar/amount.py +475 -0
  9. nectar/asciichart.py +270 -0
  10. nectar/asset.py +82 -0
  11. nectar/block.py +446 -0
  12. nectar/blockchain.py +1178 -0
  13. nectar/blockchaininstance.py +2284 -0
  14. nectar/blockchainobject.py +221 -0
  15. nectar/blurt.py +563 -0
  16. nectar/cli.py +6285 -0
  17. nectar/comment.py +1217 -0
  18. nectar/community.py +513 -0
  19. nectar/constants.py +111 -0
  20. nectar/conveyor.py +309 -0
  21. nectar/discussions.py +1709 -0
  22. nectar/exceptions.py +149 -0
  23. nectar/hive.py +546 -0
  24. nectar/hivesigner.py +420 -0
  25. nectar/imageuploader.py +72 -0
  26. nectar/instance.py +129 -0
  27. nectar/market.py +1013 -0
  28. nectar/memo.py +449 -0
  29. nectar/message.py +357 -0
  30. nectar/nodelist.py +444 -0
  31. nectar/price.py +557 -0
  32. nectar/profile.py +65 -0
  33. nectar/rc.py +308 -0
  34. nectar/snapshot.py +726 -0
  35. nectar/steem.py +582 -0
  36. nectar/storage.py +53 -0
  37. nectar/transactionbuilder.py +622 -0
  38. nectar/utils.py +545 -0
  39. nectar/version.py +2 -0
  40. nectar/vote.py +557 -0
  41. nectar/wallet.py +472 -0
  42. nectar/witness.py +617 -0
  43. nectarapi/__init__.py +11 -0
  44. nectarapi/exceptions.py +123 -0
  45. nectarapi/graphenerpc.py +589 -0
  46. nectarapi/node.py +178 -0
  47. nectarapi/noderpc.py +229 -0
  48. nectarapi/rpcutils.py +97 -0
  49. nectarapi/version.py +2 -0
  50. nectarbase/__init__.py +14 -0
  51. nectarbase/ledgertransactions.py +75 -0
  52. nectarbase/memo.py +243 -0
  53. nectarbase/objects.py +429 -0
  54. nectarbase/objecttypes.py +22 -0
  55. nectarbase/operationids.py +102 -0
  56. nectarbase/operations.py +1297 -0
  57. nectarbase/signedtransactions.py +48 -0
  58. nectarbase/transactions.py +11 -0
  59. nectarbase/version.py +2 -0
  60. nectargrapheneapi/__init__.py +6 -0
  61. nectargraphenebase/__init__.py +27 -0
  62. nectargraphenebase/account.py +846 -0
  63. nectargraphenebase/aes.py +52 -0
  64. nectargraphenebase/base58.py +192 -0
  65. nectargraphenebase/bip32.py +494 -0
  66. nectargraphenebase/bip38.py +134 -0
  67. nectargraphenebase/chains.py +149 -0
  68. nectargraphenebase/dictionary.py +3 -0
  69. nectargraphenebase/ecdsasig.py +326 -0
  70. nectargraphenebase/objects.py +123 -0
  71. nectargraphenebase/objecttypes.py +6 -0
  72. nectargraphenebase/operationids.py +3 -0
  73. nectargraphenebase/operations.py +23 -0
  74. nectargraphenebase/prefix.py +11 -0
  75. nectargraphenebase/py23.py +38 -0
  76. nectargraphenebase/signedtransactions.py +201 -0
  77. nectargraphenebase/types.py +419 -0
  78. nectargraphenebase/unsignedtransactions.py +283 -0
  79. nectargraphenebase/version.py +2 -0
  80. nectarstorage/__init__.py +38 -0
  81. nectarstorage/base.py +306 -0
  82. nectarstorage/exceptions.py +16 -0
  83. nectarstorage/interfaces.py +237 -0
  84. nectarstorage/masterpassword.py +239 -0
  85. nectarstorage/ram.py +30 -0
  86. nectarstorage/sqlite.py +334 -0
nectar/conveyor.py ADDED
@@ -0,0 +1,309 @@
1
+ # -*- coding: utf-8 -*-
2
+ import base64
3
+ import hashlib
4
+ import json
5
+ import random
6
+ import struct
7
+ from binascii import hexlify
8
+ from datetime import datetime, timezone
9
+
10
+ import requests
11
+
12
+ from nectargraphenebase.ecdsasig import sign_message
13
+ from nectargraphenebase.py23 import py23_bytes
14
+
15
+ from .account import Account
16
+ from .instance import shared_blockchain_instance
17
+
18
+ try:
19
+ from urllib.parse import urljoin
20
+ except ImportError:
21
+ from urlparse import urljoin
22
+
23
+
24
+ class Conveyor(object):
25
+ """Class to access Steemit Conveyor instances:
26
+ https://github.com/steemit/conveyor
27
+
28
+ Description from the official documentation:
29
+
30
+ * Feature flags: "Feature flags allows our apps (condenser mainly) to
31
+ hide certain features behind flags."
32
+ * User data: "Conveyor is the central point for storing sensitive user
33
+ data (email, phone, etc). No other services should store this data
34
+ and should instead query for it here every time."
35
+ * User tags: "Tagging mechanism for other services, allows defining and
36
+ assigning tags to accounts (or other identifiers) and querying for
37
+ them."
38
+
39
+ Not contained in the documentation, but implemented and working:
40
+
41
+ * Draft handling: saving, listing and removing post drafts
42
+ consisting of a post title and a body.
43
+
44
+ The underlying RPC authentication and request signing procedure is
45
+ described here: https://github.com/steemit/rpc-auth
46
+
47
+ """
48
+
49
+ def __init__(self, url="https://conveyor.steemit.com", blockchain_instance=None, **kwargs):
50
+ """Initialize a Conveyor instance
51
+ :param str url: (optional) URL to the Conveyor API, defaults to
52
+ https://conveyor.steemit.com
53
+ :param nectar.steem.Steem blockchain_instance: Steem instance
54
+
55
+ """
56
+
57
+ self.url = url
58
+ if blockchain_instance is None:
59
+ if kwargs.get("steem_instance"):
60
+ blockchain_instance = kwargs["steem_instance"]
61
+ elif kwargs.get("hive_instance"):
62
+ blockchain_instance = kwargs["hive_instance"]
63
+ self.steem = blockchain_instance or shared_blockchain_instance()
64
+ self.id = 0
65
+ self.ENCODING = "utf-8"
66
+ self.TIMEFORMAT = "%Y-%m-%dT%H:%M:%S.%f"
67
+ self.K = hashlib.sha256(py23_bytes("steem_jsonrpc_auth", self.ENCODING)).digest()
68
+
69
+ def prehash_message(self, timestamp, account, method, params, nonce):
70
+ """Prepare a hash for the Conveyor API request with SHA256 according
71
+ to https://github.com/steemit/rpc-auth
72
+ Hashing of `second` is then done inside `ecdsasig.sign_message()`.
73
+
74
+ :param str timestamp: valid iso8601 datetime ending in "Z"
75
+ :param str account: valid steem blockchain account name
76
+ :param str method: Conveyor method name to be called
77
+ :param bytes param: base64 encoded request parameters
78
+ :param bytes nonce: random 8 bytes
79
+
80
+ """
81
+ first = hashlib.sha256(py23_bytes(timestamp + account + method + params, self.ENCODING))
82
+ return self.K + first.digest() + nonce
83
+
84
+ def _request(self, account, method, params, key):
85
+ """Assemble the request, hash it, sign it and send it to the Conveyor
86
+ instance. Returns the server response as JSON.
87
+
88
+ :param str account: account name
89
+ :param str method: Conveyor method name to be called
90
+ :param dict params: request parameters as `dict`
91
+ :param str key: Steem posting key for signing
92
+
93
+ """
94
+ params_bytes = py23_bytes(json.dumps(params), self.ENCODING)
95
+ params_enc = base64.b64encode(params_bytes).decode(self.ENCODING)
96
+ timestamp = datetime.now(timezone.utc).strftime(self.TIMEFORMAT)[:-3] + "Z"
97
+ nonce_int = random.getrandbits(64)
98
+ nonce_bytes = struct.pack(">Q", nonce_int) # 64bit ULL, big endian
99
+ nonce_str = "%016x" % (nonce_int)
100
+
101
+ message = self.prehash_message(timestamp, account, method, params_enc, nonce_bytes)
102
+ signature = sign_message(message, key)
103
+ signature_hex = hexlify(signature).decode(self.ENCODING)
104
+
105
+ request = {
106
+ "jsonrpc": "2.0",
107
+ "id": self.id,
108
+ "method": method,
109
+ "params": {
110
+ "__signed": {
111
+ "account": account,
112
+ "nonce": nonce_str,
113
+ "params": params_enc,
114
+ "signatures": [signature_hex],
115
+ "timestamp": timestamp,
116
+ }
117
+ },
118
+ }
119
+ r = requests.post(self.url, data=json.dumps(request))
120
+ self.id += 1
121
+ return r.json()
122
+
123
+ def _conveyor_method(self, account, signing_account, method, params):
124
+ """Wrapper function to handle account and key lookups
125
+
126
+ :param str account: name of the addressed account
127
+ :param str signing_account: name of the account to sign the request
128
+ :param method: Conveyor method name to be called
129
+ :params dict params: request parameters as `dict`
130
+
131
+ """
132
+ account = Account(account, blockchain_instance=self.steem)
133
+ if signing_account is None:
134
+ signer = account
135
+ else:
136
+ signer = Account(signing_account, blockchain_instance=self.steem)
137
+ if "posting" not in signer:
138
+ signer.refresh()
139
+ if "posting" not in signer:
140
+ raise AssertionError("Could not access posting permission")
141
+ for authority in signer["posting"]["key_auths"]:
142
+ posting_wif = self.steem.wallet.getPrivateKeyForPublicKey(authority[0])
143
+ return self._request(account["name"], method, params, posting_wif)
144
+
145
+ def get_user_data(self, account, signing_account=None):
146
+ """Get the account's email address and phone number. The request has to be
147
+ signed by the requested account or an admin account.
148
+
149
+ :param str account: requested account
150
+ :param str signing_account: (optional) account to sign the
151
+ request. If unset, `account` is used.
152
+
153
+ Example:
154
+
155
+ .. code-block:: python
156
+
157
+ from nectar import Steem
158
+ from nectar.conveyor import Conveyor
159
+ s = Steem(keys=["5JPOSTINGKEY"])
160
+ c = Conveyor(blockchain_instance=s)
161
+ print(c.get_user_data('accountname'))
162
+
163
+ """
164
+ account = Account(account, blockchain_instance=self.steem)
165
+ user_data = self._conveyor_method(
166
+ account, signing_account, "conveyor.get_user_data", [account["name"]]
167
+ )
168
+ if "result" in user_data:
169
+ return user_data["result"]
170
+ else:
171
+ return user_data
172
+
173
+ def set_user_data(self, account, params, signing_account=None):
174
+ """Set the account's email address and phone number. The request has to be
175
+ signed by an admin account.
176
+
177
+ :param str account: requested account
178
+ :param dict param: user data to be set
179
+ :param str signing_account: (optional) account to sign the
180
+ request. If unset, `account` is used.
181
+
182
+ Example:
183
+
184
+ .. code-block:: python
185
+
186
+ from nectar import Steem
187
+ from nectar.conveyor import Conveyor
188
+ s = Steem(keys=["5JADMINPOSTINGKEY"])
189
+ c = Conveyor(blockchain_instance=s)
190
+ userdata = {'email': 'foo@bar.com', 'phone':'+123456789'}
191
+ c.set_user_data('accountname', userdata, 'adminaccountname')
192
+
193
+ """
194
+ return self._conveyor_method(account, signing_account, "conveyor.set_user_data", [params])
195
+
196
+ def get_feature_flags(self, account, signing_account=None):
197
+ """Get the account's feature flags. The request has to be signed by the
198
+ requested account or an admin account.
199
+
200
+ :param str account: requested account
201
+ :param str signing_account: (optional) account to sign the
202
+ request. If unset, `account` is used.
203
+
204
+ Example:
205
+
206
+ .. code-block:: python
207
+
208
+ from nectar import Steem
209
+ from nectar.conveyor import Conveyor
210
+ s = Steem(keys=["5JPOSTINGKEY"])
211
+ c = Conveyor(blockchain_instance=s)
212
+ print(c.get_feature_flags('accountname'))
213
+
214
+ """
215
+ account = Account(account, blockchain_instance=self.steem)
216
+ feature_flags = self._conveyor_method(
217
+ account, signing_account, "conveyor.get_feature_flags", [account["name"]]
218
+ )
219
+ if "result" in feature_flags:
220
+ return feature_flags["result"]
221
+ else:
222
+ return feature_flags
223
+
224
+ def get_feature_flag(self, account, flag, signing_account=None):
225
+ """Test if a specific feature flag is set for an account. The request
226
+ has to be signed by the requested account or an admin account.
227
+
228
+ :param str account: requested account
229
+ :param str flag: flag to be tested
230
+ :param str signing_account: (optional) account to sign the
231
+ request. If unset, `account` is used.
232
+
233
+ Example:
234
+
235
+ .. code-block:: python
236
+
237
+ from nectar import Steem
238
+ from nectar.conveyor import Conveyor
239
+ s = Steem(keys=["5JPOSTINGKEY"])
240
+ c = Conveyor(blockchain_instance=s)
241
+ print(c.get_feature_flag('accountname', 'accepted_tos'))
242
+
243
+ """
244
+ account = Account(account, blockchain_instance=self.steem)
245
+ return self._conveyor_method(
246
+ account, signing_account, "conveyor.get_feature_flag", [account["name"], flag]
247
+ )
248
+
249
+ def save_draft(self, account, title, body):
250
+ """Save a draft in the Conveyor database
251
+
252
+ :param str account: requested account
253
+ :param str title: draft post title
254
+ :param str body: draft post body
255
+
256
+ """
257
+ account = Account(account, blockchain_instance=self.steem)
258
+ draft = {"title": title, "body": body}
259
+ return self._conveyor_method(account, None, "conveyor.save_draft", [account["name"], draft])
260
+
261
+ def list_drafts(self, account):
262
+ """List all saved drafts from `account`
263
+
264
+ :param str account: requested account
265
+
266
+ Sample output:
267
+
268
+ .. code-block:: js
269
+
270
+ {
271
+ 'jsonrpc': '2.0', 'id': 2, 'result': [
272
+ {'title': 'draft-title', 'body': 'draft-body',
273
+ 'uuid': '06497e1e-ac30-48cb-a069-27e1672924c9'}
274
+ ]
275
+ }
276
+
277
+ """
278
+ account = Account(account, blockchain_instance=self.steem)
279
+ return self._conveyor_method(account, None, "conveyor.list_drafts", [account["name"]])
280
+
281
+ def remove_draft(self, account, uuid):
282
+ """Remove a draft from the Conveyor database
283
+
284
+ :param str account: requested account
285
+ :param str uuid: draft identifier as returned from
286
+ `list_drafts`
287
+
288
+ """
289
+ account = Account(account, blockchain_instance=self.steem)
290
+ return self._conveyor_method(
291
+ account, None, "conveyor.remove_draft", [account["name"], uuid]
292
+ )
293
+
294
+ def healthcheck(self):
295
+ """Get the Conveyor status
296
+
297
+ Sample output:
298
+
299
+ .. code-block:: js
300
+
301
+ {
302
+ 'ok': True, 'version': '1.1.1-4d28e36-1528725174',
303
+ 'date': '2018-07-21T12:12:25.502Z'
304
+ }
305
+
306
+ """
307
+ url = urljoin(self.url, "/.well-known/healthcheck.json")
308
+ r = requests.get(url)
309
+ return r.json()