hive-nectar 0.2.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.
Files changed (87) hide show
  1. hive_nectar-0.2.9.dist-info/METADATA +194 -0
  2. hive_nectar-0.2.9.dist-info/RECORD +87 -0
  3. hive_nectar-0.2.9.dist-info/WHEEL +4 -0
  4. hive_nectar-0.2.9.dist-info/entry_points.txt +2 -0
  5. hive_nectar-0.2.9.dist-info/licenses/LICENSE.txt +23 -0
  6. nectar/__init__.py +37 -0
  7. nectar/account.py +5076 -0
  8. nectar/amount.py +553 -0
  9. nectar/asciichart.py +303 -0
  10. nectar/asset.py +122 -0
  11. nectar/block.py +574 -0
  12. nectar/blockchain.py +1242 -0
  13. nectar/blockchaininstance.py +2590 -0
  14. nectar/blockchainobject.py +263 -0
  15. nectar/cli.py +5937 -0
  16. nectar/comment.py +1552 -0
  17. nectar/community.py +854 -0
  18. nectar/constants.py +95 -0
  19. nectar/discussions.py +1437 -0
  20. nectar/exceptions.py +152 -0
  21. nectar/haf.py +381 -0
  22. nectar/hive.py +630 -0
  23. nectar/imageuploader.py +114 -0
  24. nectar/instance.py +113 -0
  25. nectar/market.py +876 -0
  26. nectar/memo.py +542 -0
  27. nectar/message.py +379 -0
  28. nectar/nodelist.py +309 -0
  29. nectar/price.py +603 -0
  30. nectar/profile.py +74 -0
  31. nectar/py.typed +0 -0
  32. nectar/rc.py +333 -0
  33. nectar/snapshot.py +1024 -0
  34. nectar/storage.py +62 -0
  35. nectar/transactionbuilder.py +659 -0
  36. nectar/utils.py +630 -0
  37. nectar/version.py +3 -0
  38. nectar/vote.py +722 -0
  39. nectar/wallet.py +472 -0
  40. nectar/witness.py +728 -0
  41. nectarapi/__init__.py +12 -0
  42. nectarapi/exceptions.py +126 -0
  43. nectarapi/graphenerpc.py +596 -0
  44. nectarapi/node.py +194 -0
  45. nectarapi/noderpc.py +79 -0
  46. nectarapi/openapi.py +107 -0
  47. nectarapi/py.typed +0 -0
  48. nectarapi/rpcutils.py +98 -0
  49. nectarapi/version.py +3 -0
  50. nectarbase/__init__.py +15 -0
  51. nectarbase/ledgertransactions.py +106 -0
  52. nectarbase/memo.py +242 -0
  53. nectarbase/objects.py +521 -0
  54. nectarbase/objecttypes.py +21 -0
  55. nectarbase/operationids.py +102 -0
  56. nectarbase/operations.py +1357 -0
  57. nectarbase/py.typed +0 -0
  58. nectarbase/signedtransactions.py +89 -0
  59. nectarbase/transactions.py +11 -0
  60. nectarbase/version.py +3 -0
  61. nectargraphenebase/__init__.py +27 -0
  62. nectargraphenebase/account.py +1121 -0
  63. nectargraphenebase/aes.py +49 -0
  64. nectargraphenebase/base58.py +197 -0
  65. nectargraphenebase/bip32.py +575 -0
  66. nectargraphenebase/bip38.py +110 -0
  67. nectargraphenebase/chains.py +15 -0
  68. nectargraphenebase/dictionary.py +2 -0
  69. nectargraphenebase/ecdsasig.py +309 -0
  70. nectargraphenebase/objects.py +130 -0
  71. nectargraphenebase/objecttypes.py +8 -0
  72. nectargraphenebase/operationids.py +5 -0
  73. nectargraphenebase/operations.py +25 -0
  74. nectargraphenebase/prefix.py +13 -0
  75. nectargraphenebase/py.typed +0 -0
  76. nectargraphenebase/signedtransactions.py +221 -0
  77. nectargraphenebase/types.py +557 -0
  78. nectargraphenebase/unsignedtransactions.py +288 -0
  79. nectargraphenebase/version.py +3 -0
  80. nectarstorage/__init__.py +57 -0
  81. nectarstorage/base.py +317 -0
  82. nectarstorage/exceptions.py +15 -0
  83. nectarstorage/interfaces.py +244 -0
  84. nectarstorage/masterpassword.py +237 -0
  85. nectarstorage/py.typed +0 -0
  86. nectarstorage/ram.py +27 -0
  87. nectarstorage/sqlite.py +343 -0
@@ -0,0 +1,114 @@
1
+ import io
2
+ from binascii import hexlify
3
+ from typing import Any, Dict, Optional, Union
4
+
5
+ import httpx
6
+ from httpx import ConnectError, HTTPStatusError, RequestError, TimeoutException
7
+
8
+ from nectar.account import Account
9
+ from nectar.exceptions import MissingKeyError
10
+ from nectargraphenebase.ecdsasig import sign_message
11
+
12
+ from .instance import shared_blockchain_instance
13
+
14
+
15
+ class ImageUploader:
16
+ def __init__(
17
+ self,
18
+ base_url: str = "https://images.hive.blog",
19
+ challenge: str = "ImageSigningChallenge",
20
+ blockchain_instance: Optional[Any] = None,
21
+ ) -> None:
22
+ """
23
+ Initialize the ImageUploader.
24
+
25
+ Parameters:
26
+ base_url (str): Base URL of the image upload service (default: "https://images.hive.blog").
27
+ challenge (str): ASCII string prepended to the image bytes when constructing the signing message; ensures signatures are bound to this uploader's purpose.
28
+
29
+ Notes:
30
+ blockchain_instance is an optional blockchain client; if not provided a shared instance is used.
31
+ """
32
+ self.challenge = challenge
33
+ self.base_url = base_url
34
+ self.blockchain = blockchain_instance or shared_blockchain_instance()
35
+
36
+ def upload(
37
+ self,
38
+ image: Union[str, bytes, io.BytesIO],
39
+ account: Union[str, Account],
40
+ image_name: Optional[str] = None,
41
+ ) -> Dict[str, Any]:
42
+ """
43
+ Upload an image to the configured image service, signing the upload with the account's posting key.
44
+
45
+ The function accepts a filesystem path (str), raw bytes, or an io.BytesIO for the image. It locates the account's posting private key from the blockchain wallet, signs the image data together with the uploader's challenge string, and POSTs the image under the key `image_name` (defaults to "image") to: <base_url>/<account_name>/<signature_hex>.
46
+
47
+ Parameters:
48
+ image (str | bytes | io.BytesIO): Path to an image file, raw image bytes, or an in-memory bytes buffer.
49
+ account (str | Account): Account identifier (must have posting permission); used to select the signing key.
50
+ image_name (str, optional): Form field name for the uploaded image (defaults to "image").
51
+
52
+ Returns:
53
+ dict: Parsed JSON response from the image service.
54
+
55
+ Raises:
56
+ AssertionError: If the account's posting permission (and therefore a posting key) cannot be accessed.
57
+ """
58
+ account = Account(account, blockchain_instance=self.blockchain)
59
+ if "posting" not in account:
60
+ account.refresh()
61
+ if "posting" not in account:
62
+ raise AssertionError("Could not access posting permission")
63
+ posting_wif = None
64
+ for authority in account["posting"]["key_auths"]:
65
+ try:
66
+ posting_wif = self.blockchain.wallet.getPrivateKeyForPublicKey(authority[0])
67
+ break
68
+ except MissingKeyError:
69
+ continue
70
+ if not posting_wif:
71
+ raise AssertionError("No local private posting key available to sign the image.")
72
+
73
+ if isinstance(image, str):
74
+ with open(image, "rb") as f:
75
+ image_data = f.read()
76
+ elif isinstance(image, io.BytesIO):
77
+ image_data = image.read()
78
+ else:
79
+ image_data = image
80
+
81
+ message = bytes(self.challenge, "ascii") + image_data
82
+ signature = sign_message(message, posting_wif)
83
+ signature_in_hex = hexlify(signature).decode("ascii")
84
+
85
+ # Prepare files for httpx
86
+ # We want to send the file with the field name "image" (expected by images.hive.blog)
87
+ # and the filename specified by image_name.
88
+ # If image_name is not provided, we default to "image".
89
+ filename = image_name or "image"
90
+ # files = {'field_name': ('filename', file_data)}
91
+ files = {"image": (filename, image_data)}
92
+ url = "{}/{}/{}".format(self.base_url, account["name"], signature_in_hex)
93
+
94
+ retries = 3
95
+ timeout = 60
96
+
97
+ with httpx.Client(timeout=timeout) as client:
98
+ for i in range(retries + 1):
99
+ try:
100
+ r = client.post(url, files=files)
101
+ r.raise_for_status()
102
+ return r.json()
103
+ except (
104
+ ConnectError,
105
+ RequestError,
106
+ TimeoutException,
107
+ HTTPStatusError,
108
+ ) as e:
109
+ if i < retries:
110
+ continue
111
+ raise AssertionError(f"Upload failed after {retries} retries: {str(e)}") from e
112
+
113
+ # Should be unreachable if loop works correctly
114
+ raise AssertionError("Upload failed")
nectar/instance.py ADDED
@@ -0,0 +1,113 @@
1
+ from typing import Any, Dict
2
+
3
+ # Track shared httpx client alongside the shared Hive instance so callers that
4
+ # construct Hive directly (e.g., Hive(keys=[...])) still reuse the same pool.
5
+ _shared_transport: Dict[str, Any] = {}
6
+
7
+
8
+ class SharedInstance:
9
+ """Singleton for the shared Blockchain Instance (Hive-only)."""
10
+
11
+ instance = None
12
+ config = {}
13
+
14
+
15
+ def shared_blockchain_instance() -> Any:
16
+ """Initialize and return the shared Hive instance.
17
+
18
+ Hive-only: this always returns a `nectar.Hive` instance, regardless of any
19
+ legacy configuration that may have referenced other chains.
20
+ """
21
+ if not SharedInstance.instance:
22
+ clear_cache()
23
+ SharedInstance.instance = _build_hive(**SharedInstance.config)
24
+ return SharedInstance.instance
25
+
26
+
27
+ def set_shared_blockchain_instance(blockchain_instance: Any) -> None:
28
+ """
29
+ Override the shared Hive instance used by the module and clear related caches.
30
+
31
+ This sets SharedInstance.instance to the provided blockchain instance and calls clear_cache()
32
+ to invalidate any cached blockchain objects so consumers observe the new instance immediately.
33
+ """
34
+ clear_cache()
35
+ SharedInstance.instance = blockchain_instance
36
+ if hasattr(blockchain_instance, "rpc") and getattr(blockchain_instance, "rpc", None):
37
+ _shared_transport["rpc"] = blockchain_instance.rpc
38
+
39
+
40
+ def shared_hive_instance() -> Any:
41
+ """Initialize (if needed) and return the shared Hive instance."""
42
+ return shared_blockchain_instance()
43
+
44
+
45
+ def set_shared_hive_instance(hive_instance: Any) -> None:
46
+ """
47
+ Override the global shared Hive instance used by the module.
48
+
49
+ Replaces the current SharedInstance.instance with the provided hive_instance and clears related caches so subsequent calls return the new instance.
50
+
51
+ Parameters:
52
+ hive_instance: The nectar.Hive instance to set as the shared global instance.
53
+ """
54
+ set_shared_blockchain_instance(hive_instance)
55
+
56
+
57
+ def clear_cache() -> None:
58
+ """
59
+ Clear cached blockchain object state.
60
+
61
+ Performs a lazy import of BlockchainObject and calls its clear_cache() method to purge any in-memory caches of blockchain objects (used when the shared Hive instance or configuration changes).
62
+ """
63
+ from .blockchainobject import BlockchainObject
64
+
65
+ BlockchainObject.clear_cache()
66
+
67
+
68
+ def set_shared_config(config: Dict[str, Any]) -> None:
69
+ """
70
+ Set configuration for the shared Hive instance without creating the instance.
71
+
72
+ Updates the global SharedInstance.config with the provided mapping. If a shared instance already exists, clears internal caches and resets the shared instance to None so the new configuration will take effect on next access.
73
+
74
+ Parameters:
75
+ config (dict): Configuration options to merge into the shared instance configuration.
76
+
77
+ Raises:
78
+ AssertionError: If `config` is not a dict.
79
+ """
80
+ if not isinstance(config, dict):
81
+ raise AssertionError()
82
+ SharedInstance.config.update(config)
83
+ # if one is already set, delete
84
+ if SharedInstance.instance:
85
+ clear_cache()
86
+ SharedInstance.instance = None
87
+
88
+
89
+ def _build_hive(**config: Any) -> Any:
90
+ """Internal helper to build a Hive instance while reusing shared transports."""
91
+ from .hive import Hive
92
+
93
+ hive = Hive(**config)
94
+ stored_rpc = _shared_transport.get("rpc")
95
+ configured_nodes = config.get("node", [])
96
+ if isinstance(configured_nodes, str):
97
+ configured_nodes = [configured_nodes]
98
+
99
+ def _rpc_matches_config(rpc_obj: Any) -> bool:
100
+ if not configured_nodes or rpc_obj is None:
101
+ return True
102
+ return getattr(rpc_obj, "url", None) in configured_nodes
103
+
104
+ if stored_rpc and getattr(stored_rpc, "url", None) and _rpc_matches_config(stored_rpc):
105
+ hive.rpc = stored_rpc
106
+ else:
107
+ rpc_obj = getattr(hive, "rpc", None)
108
+ if rpc_obj is not None:
109
+ current_url = getattr(rpc_obj, "url", None)
110
+ if not current_url and hasattr(rpc_obj, "rpcconnect"):
111
+ rpc_obj.rpcconnect()
112
+ _shared_transport["rpc"] = getattr(hive, "rpc", None)
113
+ return hive