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/hivesigner.py ADDED
@@ -0,0 +1,420 @@
1
+ # -*- coding: utf-8 -*-
2
+ import json
3
+
4
+ try:
5
+ from urllib.parse import urlencode, urljoin, urlparse
6
+ except ImportError:
7
+ from urllib import urlencode
8
+
9
+ from urlparse import urljoin
10
+ import logging
11
+
12
+ import requests
13
+ from six import PY2
14
+
15
+ from nectar.amount import Amount
16
+ from nectar.exceptions import MissingKeyError, WalletExists
17
+ from nectar.instance import shared_blockchain_instance
18
+ from nectarstorage.exceptions import KeyAlreadyInStoreException
19
+
20
+ log = logging.getLogger(__name__)
21
+
22
+
23
+ class HiveSigner(object):
24
+ """HiveSigner
25
+
26
+ :param str scope: comma separated string with scopes
27
+ login,offline,vote,comment,delete_comment,comment_options,custom_json,claim_reward_balance
28
+
29
+
30
+ .. code-block:: python
31
+
32
+ # Run the login_app in examples and login with a account
33
+ from nectar import Steem
34
+ from nectar.HiveSigner import HiveSigner
35
+ from nectar.comment import Comment
36
+ hs = HiveSigner(client_id="nectar.app")
37
+ steem = Steem(HiveSigner=hs)
38
+ steem.wallet.unlock("supersecret-passphrase")
39
+ post = Comment("author/permlink", blockchain_instance=steem)
40
+ post.upvote(voter="test") # replace "test" with your account
41
+
42
+ Examples for creating HiveSigner urls for broadcasting in browser:
43
+
44
+ .. testoutput::
45
+
46
+ from nectar import Steem
47
+ from nectar.account import Account
48
+ from nectar.HiveSigner import HiveSigner
49
+ from pprint import pprint
50
+ steem = Steem(nobroadcast=True, unsigned=True)
51
+ hs = HiveSigner(blockchain_instance=steem)
52
+ acc = Account("test", blockchain_instance=steem)
53
+ pprint(hs.url_from_tx(acc.transfer("test1", 1, "HIVE", "test")))
54
+
55
+ .. testcode::
56
+
57
+ 'https://hivesigner.com/sign/transfer?from=test&to=test1&amount=1.000+HIVE&memo=test'
58
+
59
+ .. testoutput::
60
+
61
+ from nectar import Steem
62
+ from nectar.transactionbuilder import TransactionBuilder
63
+ from nectarbase import operations
64
+ from nectar.HiveSigner import HiveSigner
65
+ from pprint import pprint
66
+ stm = Steem(nobroadcast=True, unsigned=True)
67
+ hs = HiveSigner(blockchain_instance=stm)
68
+ tx = TransactionBuilder(blockchain_instance=stm)
69
+ op = operations.Transfer(**{"from": 'test',
70
+ "to": 'test1',
71
+ "amount": '1.000 HIVE',
72
+ "memo": 'test'})
73
+ tx.appendOps(op)
74
+ pprint(hs.url_from_tx(tx.json()))
75
+
76
+ .. testcode::
77
+
78
+ 'https://hivesigner.com/sign/transfer?from=test&to=test1&amount=1.000+HIVE&memo=test'
79
+
80
+ """
81
+
82
+ def __init__(self, blockchain_instance=None, *args, **kwargs):
83
+ if blockchain_instance is None:
84
+ if kwargs.get("steem_instance"):
85
+ blockchain_instance = kwargs["steem_instance"]
86
+ elif kwargs.get("hive_instance"):
87
+ blockchain_instance = kwargs["hive_instance"]
88
+ self.blockchain = blockchain_instance or shared_blockchain_instance()
89
+ self.access_token = None
90
+ config = self.blockchain.config
91
+ self.get_refresh_token = kwargs.get("get_refresh_token", False)
92
+ self.hot_sign_redirect_uri = kwargs.get(
93
+ "hot_sign_redirect_uri", config["hot_sign_redirect_uri"]
94
+ )
95
+ if self.hot_sign_redirect_uri == "":
96
+ self.hot_sign_redirect_uri = None
97
+ self.client_id = kwargs.get("client_id", config["hs_client_id"])
98
+ self.scope = kwargs.get("scope", "login")
99
+ self.hs_oauth_base_url = kwargs.get("hs_oauth_base_url", config["hs_oauth_base_url"])
100
+ self.hs_api_url = kwargs.get("hs_api_url", config["hs_api_url"])
101
+
102
+ if "token" in kwargs and len(kwargs["token"]) > 0:
103
+ from nectarstorage import InRamPlainTokenStore
104
+
105
+ self.store = InRamPlainTokenStore()
106
+ token = kwargs["token"]
107
+ self.set_access_token(token)
108
+ name = self.me()["user"]
109
+ self.setToken({name: token})
110
+ else:
111
+ """ If no keys are provided manually we load the SQLite
112
+ keyStorage
113
+ """
114
+ from nectarstorage import SqliteEncryptedTokenStore
115
+
116
+ self.store = kwargs.get(
117
+ "token_store",
118
+ SqliteEncryptedTokenStore(config=config, **kwargs),
119
+ )
120
+
121
+ @property
122
+ def headers(self):
123
+ return {"Authorization": self.access_token}
124
+
125
+ def setToken(self, loadtoken):
126
+ """This method is strictly only for in memory token that are
127
+ passed to Wallet/Steem with the ``token`` argument
128
+ """
129
+ log.debug("Force setting of private token. Not using the wallet database!")
130
+ if not isinstance(loadtoken, (dict)):
131
+ raise ValueError("token must be a dict variable!")
132
+ for name in loadtoken:
133
+ self.store.add(loadtoken[name], name)
134
+
135
+ def is_encrypted(self):
136
+ """Is the key store encrypted?"""
137
+ return self.store.is_encrypted()
138
+
139
+ def unlock(self, pwd):
140
+ """Unlock the wallet database"""
141
+ unlock_ok = None
142
+ if self.store.is_encrypted():
143
+ unlock_ok = self.store.unlock(pwd)
144
+ return unlock_ok
145
+
146
+ def lock(self):
147
+ """Lock the wallet database"""
148
+ lock_ok = False
149
+ if self.store.is_encrypted():
150
+ lock_ok = self.store.lock()
151
+ return lock_ok
152
+
153
+ def unlocked(self):
154
+ """Is the wallet database unlocked?"""
155
+ unlocked = True
156
+ if self.store.is_encrypted():
157
+ unlocked = not self.store.locked()
158
+ return unlocked
159
+
160
+ def locked(self):
161
+ """Is the wallet database locked?"""
162
+ if self.store.is_encrypted():
163
+ return self.store.locked()
164
+ else:
165
+ return False
166
+
167
+ def changePassphrase(self, new_pwd):
168
+ """Change the passphrase for the wallet database"""
169
+ self.store.change_password(new_pwd)
170
+
171
+ def created(self):
172
+ """Do we have a wallet database already?"""
173
+ if len(self.store.getPublicKeys()):
174
+ # Already keys installed
175
+ return True
176
+ else:
177
+ return False
178
+
179
+ def create(self, pwd):
180
+ """Alias for :func:`newWallet`
181
+
182
+ :param str pwd: Passphrase for the created wallet
183
+ """
184
+ self.newWallet(pwd)
185
+
186
+ def newWallet(self, pwd):
187
+ """Create a new wallet database
188
+
189
+ :param str pwd: Passphrase for the created wallet
190
+ """
191
+ if self.created():
192
+ raise WalletExists("You already have created a wallet!")
193
+ self.store.unlock(pwd)
194
+
195
+ def addToken(self, name, token):
196
+ if str(name) in self.store:
197
+ raise KeyAlreadyInStoreException("Token already in the store")
198
+ self.store.add(str(token), str(name))
199
+
200
+ def getTokenForAccountName(self, name):
201
+ """Obtain the private token for a given public name
202
+
203
+ :param str name: Public name
204
+ """
205
+ if str(name) not in self.store:
206
+ raise MissingKeyError
207
+ return self.store.getPrivateKeyForPublicKey(str(name))
208
+
209
+ def removeTokenFromPublicName(self, name):
210
+ """Remove a token from the wallet database
211
+
212
+ :param str name: token to be removed
213
+ """
214
+ self.store.delete(str(name))
215
+
216
+ def getPublicNames(self):
217
+ """Return all installed public token"""
218
+ if self.store is None:
219
+ return
220
+ return self.store.getPublicNames()
221
+
222
+ def get_login_url(self, redirect_uri, **kwargs):
223
+ """Returns a login url for receiving token from HiveSigner"""
224
+ client_id = kwargs.get("client_id", self.client_id)
225
+ scope = kwargs.get("scope", self.scope)
226
+ get_refresh_token = kwargs.get("get_refresh_token", self.get_refresh_token)
227
+ params = {
228
+ "client_id": client_id,
229
+ "redirect_uri": redirect_uri,
230
+ "scope": scope,
231
+ }
232
+ if get_refresh_token:
233
+ params.update(
234
+ {
235
+ "response_type": "code",
236
+ }
237
+ )
238
+ if PY2:
239
+ return urljoin(
240
+ self.hs_oauth_base_url, "authorize?" + urlencode(params).replace("%2C", ",")
241
+ )
242
+ else:
243
+ return urljoin(self.hs_oauth_base_url, "authorize?" + urlencode(params, safe=","))
244
+
245
+ def get_access_token(self, code):
246
+ post_data = {
247
+ "grant_type": "authorization_code",
248
+ "code": code,
249
+ "client_id": self.client_id,
250
+ "client_secret": self.getTokenForAccountName(self.client_id),
251
+ }
252
+
253
+ r = requests.post(urljoin(self.hs_api_url, "oauth2/token/"), data=post_data)
254
+
255
+ return r.json()
256
+
257
+ def me(self, username=None):
258
+ """Calls the me function from HiveSigner
259
+
260
+ .. code-block:: python
261
+
262
+ from nectar.HiveSigner import HiveSigner
263
+ hs = HiveSigner()
264
+ hs.steem.wallet.unlock("supersecret-passphrase")
265
+ hs.me(username="test")
266
+
267
+ """
268
+ if username:
269
+ self.set_username(username)
270
+ url = urljoin(self.hs_api_url, "me/")
271
+ r = requests.post(url, headers=self.headers)
272
+ return r.json()
273
+
274
+ def set_access_token(self, access_token):
275
+ """Is needed for :func:`broadcast` and :func:`me`"""
276
+ self.access_token = access_token
277
+
278
+ def set_username(self, username, permission="posting"):
279
+ """Set a username for the next :func:`broadcast` or :func:`me` operation.
280
+ The necessary token is fetched from the wallet
281
+ """
282
+ if permission != "posting":
283
+ self.access_token = None
284
+ return
285
+ self.access_token = self.getTokenForAccountName(username)
286
+
287
+ def broadcast(self, operations, username=None):
288
+ """Broadcast an operation
289
+
290
+ Sample operations:
291
+
292
+ .. code-block:: js
293
+
294
+ [
295
+ [
296
+ 'vote', {
297
+ 'voter': 'gandalf',
298
+ 'author': 'gtg',
299
+ 'permlink': 'steem-pressure-4-need-for-speed',
300
+ 'weight': 10000
301
+ }
302
+ ]
303
+ ]
304
+
305
+ """
306
+ url = urljoin(self.hs_api_url, "broadcast/")
307
+ data = {
308
+ "operations": operations,
309
+ }
310
+ if username:
311
+ self.set_username(username)
312
+ headers = self.headers.copy()
313
+ headers.update(
314
+ {
315
+ "Content-Type": "application/json; charset=utf-8",
316
+ "Accept": "application/json",
317
+ }
318
+ )
319
+
320
+ r = requests.post(url, headers=headers, data=json.dumps(data))
321
+ try:
322
+ return r.json()
323
+ except ValueError:
324
+ return r.content
325
+
326
+ def refresh_access_token(self, code, scope):
327
+ post_data = {
328
+ "grant_type": "refresh_token",
329
+ "refresh_token": code,
330
+ "client_id": self.client_id,
331
+ "client_secret": self.getTokenForAccountName(self.client_id),
332
+ "scope": scope,
333
+ }
334
+
335
+ r = requests.post(
336
+ urljoin(self.hs_api_url, "oauth2/token/"),
337
+ data=post_data,
338
+ )
339
+
340
+ return r.json()
341
+
342
+ def revoke_token(self, access_token):
343
+ post_data = {
344
+ "access_token": access_token,
345
+ }
346
+
347
+ r = requests.post(urljoin(self.hs_api_url, "oauth2/token/revoke"), data=post_data)
348
+
349
+ return r.json()
350
+
351
+ def update_user_metadata(self, metadata):
352
+ put_data = {
353
+ "user_metadata": metadata,
354
+ }
355
+ r = requests.put(urljoin(self.hs_api_url, "me/"), data=put_data, headers=self.headers)
356
+
357
+ return r.json()
358
+
359
+ def url_from_tx(self, tx, redirect_uri=None):
360
+ """Creates a link for broadcasting an operation
361
+
362
+ :param dict tx: includes the operation, which should be broadcast
363
+ :param str redirect_uri: Redirects to this uri, when set
364
+ """
365
+ if not isinstance(tx, dict):
366
+ tx = tx.json()
367
+ if "operations" not in tx or not tx["operations"]:
368
+ return ""
369
+ urls = []
370
+ operations = tx["operations"]
371
+ for op in operations:
372
+ operation = op[0]
373
+ params = op[1]
374
+ for key in params:
375
+ value = params[key]
376
+ if isinstance(value, list) and len(value) == 3:
377
+ try:
378
+ amount = Amount(value, blockchain_instance=self.blockchain)
379
+ params[key] = str(amount)
380
+ except:
381
+ amount = None
382
+ elif isinstance(value, bool):
383
+ if value:
384
+ params[key] = 1
385
+ else:
386
+ params[key] = 0
387
+ urls.append(self.create_hot_sign_url(operation, params, redirect_uri=redirect_uri))
388
+ if len(urls) == 1:
389
+ return urls[0]
390
+ else:
391
+ return urls
392
+
393
+ def create_hot_sign_url(self, operation, params, redirect_uri=None):
394
+ """Creates a link for broadcasting an operation
395
+
396
+ :param str operation: operation name (e.g.: vote)
397
+ :param dict params: operation dict params
398
+ :param str redirect_uri: Redirects to this uri, when set
399
+ """
400
+
401
+ if not isinstance(operation, str) or not isinstance(params, dict):
402
+ raise ValueError("Invalid Request.")
403
+
404
+ base_url = self.hs_api_url.replace("https://api.", "https://").replace("/api", "")
405
+ if redirect_uri == "":
406
+ redirect_uri = None
407
+
408
+ if redirect_uri is None and self.hot_sign_redirect_uri is not None:
409
+ redirect_uri = self.hot_sign_redirect_uri
410
+ if redirect_uri is not None:
411
+ params.update({"redirect_uri": redirect_uri})
412
+
413
+ for key in params:
414
+ if isinstance(params[key], list):
415
+ params[key] = json.dumps(params[key])
416
+ params = urlencode(params)
417
+ url = urljoin(base_url, "sign/%s" % operation)
418
+ url += "?" + params
419
+
420
+ return url
@@ -0,0 +1,72 @@
1
+ # -*- coding: utf-8 -*-
2
+ import io
3
+ from binascii import hexlify
4
+
5
+ import requests
6
+
7
+ from nectar.account import Account
8
+ from nectargraphenebase.ecdsasig import sign_message
9
+ from nectargraphenebase.py23 import py23_bytes, string_types
10
+
11
+ from .instance import shared_blockchain_instance
12
+
13
+
14
+ class ImageUploader(object):
15
+ def __init__(
16
+ self,
17
+ base_url="https://steemitimages.com",
18
+ challenge="ImageSigningChallenge",
19
+ blockchain_instance=None,
20
+ **kwargs,
21
+ ):
22
+ self.challenge = challenge
23
+ self.base_url = base_url
24
+ if blockchain_instance is None:
25
+ if kwargs.get("steem_instance"):
26
+ blockchain_instance = kwargs["steem_instance"]
27
+ elif kwargs.get("hive_instance"):
28
+ blockchain_instance = kwargs["hive_instance"]
29
+ self.steem = blockchain_instance or shared_blockchain_instance()
30
+ if self.steem.is_hive and base_url == "https://steemitimages.com":
31
+ self.base_url = "https://images.hive.blog"
32
+
33
+ def upload(self, image, account, image_name=None):
34
+ """Uploads an image
35
+
36
+ :param image: path to the image or image in bytes representation which should be uploaded
37
+ :type image: str, bytes
38
+ :param str account: Account which is used to upload. A posting key must be provided.
39
+ :param str image_name: optional
40
+
41
+ .. code-block:: python
42
+
43
+ from nectar import Steem
44
+ from nectar.imageuploader import ImageUploader
45
+ stm = Steem(keys=["5xxx"]) # private posting key
46
+ iu = ImageUploader(blockchain_instance=stm)
47
+ iu.upload("path/to/image.png", "account_name") # "private posting key belongs to account_name
48
+
49
+ """
50
+ account = Account(account, blockchain_instance=self.steem)
51
+ if "posting" not in account:
52
+ account.refresh()
53
+ if "posting" not in account:
54
+ raise AssertionError("Could not access posting permission")
55
+ for authority in account["posting"]["key_auths"]:
56
+ posting_wif = self.steem.wallet.getPrivateKeyForPublicKey(authority[0])
57
+
58
+ if isinstance(image, string_types):
59
+ image_data = open(image, "rb").read()
60
+ elif isinstance(image, io.BytesIO):
61
+ image_data = image.read()
62
+ else:
63
+ image_data = image
64
+
65
+ message = py23_bytes(self.challenge, "ascii") + image_data
66
+ signature = sign_message(message, posting_wif)
67
+ signature_in_hex = hexlify(signature).decode("ascii")
68
+
69
+ files = {image_name or "image": image_data}
70
+ url = "%s/%s/%s" % (self.base_url, account["name"], signature_in_hex)
71
+ r = requests.post(url, files=files)
72
+ return r.json()
nectar/instance.py ADDED
@@ -0,0 +1,129 @@
1
+ # -*- coding: utf-8 -*-
2
+ import nectar
3
+
4
+
5
+ class SharedInstance(object):
6
+ """Singelton for the Steem Instance"""
7
+
8
+ instance = None
9
+ config = {}
10
+
11
+
12
+ def shared_blockchain_instance():
13
+ """This method will initialize ``SharedInstance.instance`` and return it.
14
+ The purpose of this method is to have offer single default
15
+ steem instance that can be reused by multiple classes.
16
+
17
+ .. code-block:: python
18
+
19
+ from nectar.account import Account
20
+ from nectar.instance import shared_steem_instance
21
+
22
+ account = Account("test")
23
+ # is equivalent with
24
+ account = Account("test", blockchain_instance=shared_steem_instance())
25
+
26
+ """
27
+ if not SharedInstance.instance:
28
+ clear_cache()
29
+ from nectar.storage import get_default_config_store
30
+
31
+ default_chain = get_default_config_store()["default_chain"]
32
+ if default_chain == "steem":
33
+ SharedInstance.instance = nectar.Steem(**SharedInstance.config)
34
+ else:
35
+ SharedInstance.instance = nectar.Hive(**SharedInstance.config)
36
+ return SharedInstance.instance
37
+
38
+
39
+ def set_shared_blockchain_instance(blockchain_instance):
40
+ """This method allows us to override default steem instance for all users of
41
+ ``SharedInstance.instance``.
42
+
43
+ :param Steem blockchain_instance: Steem instance
44
+ """
45
+ clear_cache()
46
+ SharedInstance.instance = blockchain_instance
47
+
48
+
49
+ def shared_steem_instance():
50
+ """This method will initialize ``SharedInstance.instance`` and return it.
51
+ The purpose of this method is to have offer single default
52
+ steem instance that can be reused by multiple classes.
53
+
54
+ .. code-block:: python
55
+
56
+ from nectar.account import Account
57
+ from nectar.instance import shared_steem_instance
58
+
59
+ account = Account("test")
60
+ # is equivalent with
61
+ account = Account("test", blockchain_instance=shared_steem_instance())
62
+
63
+ """
64
+ if not SharedInstance.instance:
65
+ clear_cache()
66
+ SharedInstance.instance = nectar.Steem(**SharedInstance.config)
67
+ return SharedInstance.instance
68
+
69
+
70
+ def set_shared_steem_instance(steem_instance):
71
+ """This method allows us to override default steem instance for all users of
72
+ ``SharedInstance.instance``.
73
+
74
+ :param Steem steem_instance: Steem instance
75
+ """
76
+ clear_cache()
77
+ SharedInstance.instance = steem_instance
78
+
79
+
80
+ def shared_hive_instance():
81
+ """This method will initialize ``SharedInstance.instance`` and return it.
82
+ The purpose of this method is to have offer single default
83
+ steem instance that can be reused by multiple classes.
84
+
85
+ .. code-block:: python
86
+
87
+ from nectar.account import Account
88
+ from nectar.instance import shared_hive_instance
89
+
90
+ account = Account("test")
91
+ # is equivalent with
92
+ account = Account("test", blockchain_instance=shared_hive_instance())
93
+
94
+ """
95
+ if not SharedInstance.instance:
96
+ clear_cache()
97
+ SharedInstance.instance = nectar.Hive(**SharedInstance.config)
98
+ return SharedInstance.instance
99
+
100
+
101
+ def set_shared_hive_instance(hive_instance):
102
+ """This method allows us to override default steem instance for all users of
103
+ ``SharedInstance.instance``.
104
+
105
+ :param Hive hive_instance: Hive instance
106
+ """
107
+ clear_cache()
108
+ SharedInstance.instance = hive_instance
109
+
110
+
111
+ def clear_cache():
112
+ """Clear Caches"""
113
+ from .blockchainobject import BlockchainObject
114
+
115
+ BlockchainObject.clear_cache()
116
+
117
+
118
+ def set_shared_config(config):
119
+ """This allows to set a config that will be used when calling
120
+ ``shared_steem_instance`` and allows to define the configuration
121
+ without requiring to actually create an instance
122
+ """
123
+ if not isinstance(config, dict):
124
+ raise AssertionError()
125
+ SharedInstance.config.update(config)
126
+ # if one is already set, delete
127
+ if SharedInstance.instance:
128
+ clear_cache()
129
+ SharedInstance.instance = None