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,309 @@
1
+ import hashlib
2
+ import logging
3
+ import struct
4
+ from binascii import hexlify
5
+ from typing import Any, Callable, Optional, Union
6
+
7
+ import ecdsa
8
+ from cryptography.hazmat.backends import default_backend
9
+ from cryptography.hazmat.primitives import hashes
10
+ from cryptography.hazmat.primitives.asymmetric import ec
11
+ from cryptography.hazmat.primitives.asymmetric.utils import (
12
+ Prehashed,
13
+ decode_dss_signature,
14
+ encode_dss_signature,
15
+ )
16
+ from ecdsa.ellipticcurve import Point
17
+ from ecdsa.numbertheory import inverse_mod, square_root_mod_prime
18
+ from ecdsa.util import number_to_string, sigdecode_string, sigencode_string, string_to_number
19
+
20
+ from .account import PrivateKey, PublicKey
21
+
22
+ log = logging.getLogger(__name__)
23
+
24
+
25
+ def _is_canonical(sig: Union[bytes, bytearray]) -> bool:
26
+ """
27
+ Return True if a 64-byte ECDSA signature (R || S) is in canonical form.
28
+
29
+ A canonical signature here means:
30
+ - Neither R nor S has its highest bit set (no negative integers when interpreted as signed big-endian).
31
+ - Neither R nor S has unnecessary leading zero bytes (no extra 0x00 padding before a non-negative highest byte).
32
+
33
+ Parameters:
34
+ sig (bytes or bytearray): 64-byte concatenation of R (32 bytes) followed by S (32 bytes).
35
+
36
+ Returns:
37
+ bool: True if signature is canonical, False otherwise.
38
+ """
39
+ sig = bytearray(sig)
40
+ return (
41
+ not (int(sig[0]) & 0x80)
42
+ and not (sig[0] == 0 and not (int(sig[1]) & 0x80))
43
+ and not (int(sig[32]) & 0x80)
44
+ and not (sig[32] == 0 and not (int(sig[33]) & 0x80))
45
+ )
46
+
47
+
48
+ def compressedPubkey(pk: Union[ecdsa.keys.VerifyingKey, Any]) -> bytes:
49
+ """
50
+ Return the 33-byte compressed secp256k1 public key for the given public-key object.
51
+
52
+ Accepts either an ecdsa.keys.VerifyingKey or an object exposing public_numbers().x and .y
53
+ (such as a cryptography EllipticCurvePublicKey). The output is 1 byte (0x02 if y is even,
54
+ 0x03 if y is odd) followed by the 32-byte big-endian X coordinate.
55
+
56
+ Parameters:
57
+ pk: Public-key object (ecdsa.VerifyingKey or object with public_numbers().x and .y).
58
+
59
+ Returns:
60
+ bytes: 33-byte compressed public key (prefix + 32-byte X).
61
+ """
62
+ if isinstance(pk, ecdsa.keys.VerifyingKey):
63
+ order = ecdsa.SECP256k1.order
64
+ # Get the curve point from VerifyingKey
65
+ point = pk.pubkey.point # type: ignore[attr-defined]
66
+ x = int(point.x())
67
+ y = int(point.y())
68
+ elif isinstance(pk, PublicKey):
69
+ # Handle account.PublicKey type
70
+ order = ecdsa.SECP256k1.order
71
+ point = pk.point()
72
+ x = int(point.x())
73
+ y = int(point.y())
74
+ else:
75
+ order = ecdsa.SECP256k1.order
76
+ x = int(pk.public_numbers().x)
77
+ y = int(pk.public_numbers().y)
78
+ x_str = number_to_string(x, order)
79
+ return bytes(chr(2 + (y & 1)), "ascii") + x_str
80
+
81
+
82
+ def recover_public_key(
83
+ digest: bytes, signature: bytes, i: int, message: Optional[bytes] = None
84
+ ) -> Union[ecdsa.keys.VerifyingKey, ec.EllipticCurvePublicKey, None]:
85
+ """
86
+ Recover the secp256k1 public key from an ECDSA signature and message hash.
87
+
88
+ If `message` is provided the function will construct a cryptography EllipticCurvePublicKey
89
+ from the recovered point and verify the signature against the message; on success it
90
+ returns that cryptography public key. If `message` is None the function returns an
91
+ ecdsa.VerifyingKey built from the recovered point after verifying the signature
92
+ against the provided digest. If verification fails, returns None (when `message` is None)
93
+ or raises a verification exception (when `message` is provided).
94
+
95
+ Parameters:
96
+ digest (bytes): The message hash (big-endian) used when signing.
97
+ signature (bytes): 64-byte signature consisting of r||s (raw concatenation).
98
+ i (int): Recovery identifier (0..3) selecting which of the possible curve points to use.
99
+ message (bytes or str, optional): Original message to verify against; if a str it is
100
+ encoded as UTF-8. When provided the function returns a cryptography public key
101
+ and performs verification using ECDSA-SHA256.
102
+
103
+ Returns:
104
+ cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey
105
+ when `message` is provided and verification succeeds;
106
+ ecdsa.keys.VerifyingKey
107
+ when `message` is None and digest-based verification succeeds;
108
+ None
109
+ when `message` is None and verification fails.
110
+
111
+ Raises:
112
+ cryptography.exceptions.InvalidSignature: If `message` is provided and signature verification fails.
113
+ """
114
+
115
+ # See http: //www.secg.org/download/aid-780/sec1-v2.pdf section 4.1.6 primarily
116
+ curve = ecdsa.SECP256k1.curve
117
+ G = ecdsa.SECP256k1.generator
118
+ order = ecdsa.SECP256k1.order
119
+ yp = i % 2
120
+ r, s = sigdecode_string(signature, order)
121
+ # 1.1
122
+ x = r + (i // 2) * order
123
+ # 1.3. This actually calculates for either effectively 02||X or 03||X depending on 'k' instead of always for 02||X as specified.
124
+ # This substitutes for the lack of reversing R later on. -R actually is defined to be just flipping the y-coordinate in the elliptic curve.
125
+ alpha = ((x * x * x) + (curve.a() * x) + curve.b()) % curve.p()
126
+ beta = square_root_mod_prime(alpha, curve.p())
127
+ y = beta if (beta - yp) % 2 == 0 else curve.p() - beta
128
+ # 1.4 Constructor of Point is supposed to check if nR is at infinity.
129
+ R = Point(curve, x, y, order)
130
+ # 1.5 Compute e
131
+ e = string_to_number(digest)
132
+ # 1.6 Compute Q = r^-1(sR - eG)
133
+ Q = inverse_mod(r, order) * (s * R + (-e % order) * G)
134
+
135
+ if message is not None:
136
+ if not isinstance(message, bytes):
137
+ message = bytes(message, "utf-8")
138
+ sigder = encode_dss_signature(r, s)
139
+ Q_point = Q.to_affine() # type: ignore[attr-defined]
140
+ public_key = ec.EllipticCurvePublicNumbers(
141
+ int(Q_point.x()), int(Q_point.y()), ec.SECP256K1()
142
+ ).public_key(default_backend())
143
+ public_key.verify(sigder, message, ec.ECDSA(hashes.SHA256()))
144
+ return public_key
145
+ else:
146
+ # Not strictly necessary, but let's verify the message for paranoia's sake.
147
+ if not ecdsa.VerifyingKey.from_public_point(Q, curve=ecdsa.SECP256k1).verify_digest(
148
+ signature, digest, sigdecode=sigdecode_string
149
+ ):
150
+ return None
151
+ return ecdsa.VerifyingKey.from_public_point(Q, curve=ecdsa.SECP256k1)
152
+
153
+
154
+ def recoverPubkeyParameter(
155
+ message: Optional[Union[str, bytes]],
156
+ digest: bytes,
157
+ signature: bytes,
158
+ pubkey: Union[PublicKey, ec.EllipticCurvePublicKey],
159
+ ) -> Optional[int]:
160
+ """
161
+ Determine the ECDSA recovery parameter (0–3) that, when used with the given digest and 64-byte signature (R||S), reproduces the provided public key.
162
+
163
+ Attempts each recovery index i in 0..3, recovers a candidate public key, and compares its compressed form to the compressed form of the supplied pubkey. If a match is found returns the matching index; otherwise returns None.
164
+
165
+ Parameters that need clarification:
166
+ - message: the original message (will be encoded as UTF-8 if not bytes) and is used when recovering a cryptography public key variant.
167
+ - digest: the message hash used for recovery.
168
+ - signature: 64-byte R||S signature (bytes-like).
169
+ - pubkey: the expected public key to match; may be a cryptography/ec or ecdsa-like public key object.
170
+
171
+ Returns:
172
+ int: matching recovery parameter in 0..3, or None if no match is found.
173
+ """
174
+ if not isinstance(message, bytes):
175
+ if message is None:
176
+ message = b""
177
+ else:
178
+ message = bytes(message, "utf-8")
179
+ for i in range(0, 4):
180
+ if not isinstance(pubkey, PublicKey):
181
+ p = recover_public_key(digest, signature, i, message)
182
+ p_comp = hexlify(compressedPubkey(p))
183
+ pubkey_comp = hexlify(compressedPubkey(pubkey))
184
+ if p_comp == pubkey_comp:
185
+ return i
186
+ else: # pragma: no cover
187
+ p = recover_public_key(digest, signature, i)
188
+ if p is None:
189
+ continue
190
+ p_comp = hexlify(compressedPubkey(p))
191
+ p_string = hexlify(p.to_string()) # type: ignore[attr-defined]
192
+ if isinstance(pubkey, PublicKey):
193
+ pubkey_string = bytes(repr(pubkey), "latin")
194
+ else: # pragma: no cover
195
+ pubkey_string = hexlify(pubkey.to_string()) # type: ignore[attr-defined]
196
+ if p_string == pubkey_string or p_comp == pubkey_string:
197
+ return i
198
+ return None
199
+
200
+
201
+ def sign_message(message: Union[str, bytes], wif: str, hashfn: Callable = hashlib.sha256) -> bytes:
202
+ """
203
+ Sign a message using a private key in Wallet Import Format (WIF) and return a compact, canonical ECDSA signature.
204
+
205
+ Signs the provided message with secp256k1 ECDSA-SHA256 using the private key derived from the given WIF. The function repeats signing as needed until it produces a canonical 64-byte R||S signature (both R and S encoded as 32 bytes). It also computes the recovery parameter for the signature and encodes it into the first byte of the returned blob.
206
+
207
+ Parameters:
208
+ message (bytes or str): Message to sign. If a str is provided it is encoded as UTF-8 before hashing.
209
+ wif (str): Private key in Wallet Import Format (WIF).
210
+ hashfn (callable, optional): Hash function to apply to the message prior to recovery-parameter computation; defaults to hashlib.sha256.
211
+
212
+ Returns:
213
+ bytes: 65-byte compact signature: 1-byte recovery/version prefix (recovery parameter adjusted for compact/compressed form) followed by the 64-byte R||S sequence.
214
+ """
215
+
216
+ if not isinstance(message, bytes):
217
+ message = bytes(message, "utf-8")
218
+
219
+ # Detect if message is already a digest
220
+ prehashed = len(message) == hashfn().digest_size
221
+
222
+ if prehashed:
223
+ digest = message
224
+ message_for_signing = message # the digest
225
+ algorithm_for_signing = ec.ECDSA(Prehashed(hashes.SHA256()))
226
+ message_for_recovery = None
227
+ else:
228
+ digest = hashfn(message).digest()
229
+ message_for_signing = message
230
+ algorithm_for_signing = ec.ECDSA(hashes.SHA256())
231
+ message_for_recovery = message
232
+
233
+ priv_key = PrivateKey(wif)
234
+ cnt = 0
235
+ private_key = ec.derive_private_key(int(repr(priv_key), 16), ec.SECP256K1(), default_backend())
236
+ public_key = private_key.public_key()
237
+ while True:
238
+ cnt += 1
239
+ if not cnt % 20:
240
+ log.info("Still searching for a canonical signature. Tried %d times already!" % cnt)
241
+ order = ecdsa.SECP256k1.order
242
+ sigder = private_key.sign(message_for_signing, algorithm_for_signing)
243
+ r, s = decode_dss_signature(sigder)
244
+ signature = sigencode_string(r, s, order)
245
+ # Make sure signature is canonical!
246
+ #
247
+ sigder = bytearray(sigder)
248
+ lenR = sigder[3]
249
+ lenS = sigder[5 + lenR]
250
+ if lenR == 32 and lenS == 32 and _is_canonical(signature):
251
+ # Derive the recovery parameter
252
+ #
253
+ i = recoverPubkeyParameter(message_for_recovery, digest, signature, public_key)
254
+ if i is None:
255
+ continue
256
+ i += 4 # compressed
257
+ i += 27 # compact
258
+ break
259
+
260
+ # pack signature
261
+ #
262
+ sigstr = struct.pack("<B", i)
263
+ sigstr += signature
264
+
265
+ return sigstr
266
+
267
+
268
+ def verify_message(
269
+ message: Union[str, bytes],
270
+ signature: Union[str, bytes],
271
+ hashfn: Callable = hashlib.sha256,
272
+ recover_parameter: Optional[int] = None,
273
+ ) -> Optional[bytes]:
274
+ """
275
+ Verify an ECDSA secp256k1 signature against a message and return the signer's compressed public key.
276
+
277
+ Parameters:
278
+ message (bytes or str): The message to verify. If a str, it will be UTF-8 encoded.
279
+ signature (bytes or str): 65-byte compact signature where the first byte encodes the recovery parameter/version and the remaining 64 bytes are R||S. If a str, it will be UTF-8 encoded.
280
+ hashfn (callable): Hash function constructor used to compute the digest of the message (default: hashlib.sha256). Note: The actual verification uses SHA256 regardless of this parameter.
281
+ recover_parameter (int, optional): Explicit recovery parameter (0–3). If omitted, it is extracted from the signature's first byte.
282
+
283
+ Returns:
284
+ bytes: The 33-byte compressed public key of the recovered signer on successful verification.
285
+
286
+ Notes:
287
+ - The function computes the digest of `message` with `hashfn`, recovers the public key using the recovery parameter, converts the 64-byte R||S into DER form, and verifies the signature with ECDSA-SHA256.
288
+ - If the recovery parameter cannot be determined from the signature, None is returned.
289
+ - Cryptographic verification errors (e.g., invalid signature) will propagate as raised exceptions.
290
+ """
291
+ if not isinstance(message, bytes):
292
+ message = bytes(message, "utf-8")
293
+ if not isinstance(signature, bytes):
294
+ signature = bytes(signature, "utf-8")
295
+ digest = hashfn(message).digest()
296
+ sig = signature[1:]
297
+ if recover_parameter is None:
298
+ recover_parameter = bytearray(signature)[0] - 4 - 27 # recover parameter only
299
+ if recover_parameter < 0:
300
+ log.info("Could not recover parameter")
301
+ return None
302
+
303
+ p = recover_public_key(digest, sig, recover_parameter, message)
304
+ order = ecdsa.SECP256k1.order
305
+ r, s = sigdecode_string(sig, order)
306
+ sigder = encode_dss_signature(r, s)
307
+ p.verify(sigder, digest, ec.ECDSA(Prehashed(hashes.SHA256()))) # type: ignore[attr-defined]
308
+ phex = compressedPubkey(p)
309
+ return phex
@@ -0,0 +1,130 @@
1
+ import json
2
+ from typing import Any, Dict, List, Union
3
+
4
+ from nectargraphenebase.types import Id, JsonObj, Optional, String
5
+
6
+ from .operationids import operations
7
+
8
+
9
+ class Operation:
10
+ def __init__(self, op: Union[List[Any], Dict[str, Any], Any]) -> None:
11
+ if isinstance(op, list) and len(op) == 2:
12
+ if isinstance(op[0], int):
13
+ self.opId = op[0]
14
+ name = self.getOperationNameForId(self.opId)
15
+ else:
16
+ self.opId = self.operations().get(op[0], None)
17
+ name = op[0]
18
+ if self.opId is None:
19
+ raise ValueError("Unknown operation")
20
+ self.name = name[0].upper() + name[1:] # klassname
21
+ try:
22
+ klass = self._getklass(self.name)
23
+ except Exception:
24
+ raise NotImplementedError("Unimplemented Operation %s" % self.name)
25
+ self.op = klass(op[1])
26
+ self.appbase = False
27
+ elif isinstance(op, dict):
28
+ if len(op["type"]) > 10 and op["type"][-9:] == "operation":
29
+ name = op["type"][:-10]
30
+ else:
31
+ name = op["type"]
32
+ self.opId = self.operations().get(name, None)
33
+ if self.opId is None:
34
+ raise ValueError("Unknown operation")
35
+ self.name = name[0].upper() + name[1:] # klassname
36
+ try:
37
+ klass = self._getklass(self.name)
38
+ except Exception:
39
+ raise NotImplementedError("Unimplemented Operation %s" % self.name)
40
+ self.op = klass(op["value"])
41
+ self.appbase = True
42
+ else:
43
+ self.op = op
44
+ self.name = type(self.op).__name__.lower() # also store name
45
+ self.opId = self.operations()[self.name]
46
+
47
+ def operations(self) -> Dict[str, int]:
48
+ return operations
49
+
50
+ def getOperationNameForId(self, i: int) -> str:
51
+ """Convert an operation id into the corresponding string"""
52
+ for key in self.operations():
53
+ if int(self.operations()[key]) is int(i):
54
+ return key
55
+ return "Unknown Operation ID %d" % i
56
+
57
+ def _getklass(self, name: str) -> type:
58
+ module = __import__("graphenebase.operations", fromlist=["operations"])
59
+ class_ = getattr(module, name)
60
+ return class_
61
+
62
+ def __bytes__(self) -> bytes:
63
+ if self.opId is None:
64
+ raise ValueError("Operation ID is None, cannot serialize operation")
65
+ return bytes(Id(self.opId)) + bytes(self.op)
66
+
67
+ def __str__(self) -> str:
68
+ # Try to get JSON data from operation, fallback to raw object if toJson not available
69
+ # This handles both GrapheneObject instances (with toJson) and raw data
70
+ try:
71
+ op_data = self.op.toJson() # type: ignore[attr-defined]
72
+ except (AttributeError, TypeError):
73
+ op_data = self.op
74
+ return json.dumps([self.opId, op_data])
75
+
76
+
77
+ class GrapheneObject:
78
+ """Core abstraction class
79
+
80
+ This class is used for any JSON reflected object in Graphene.
81
+
82
+ * ``instance.__json__()``: encodes data into json format
83
+ * ``bytes(instance)``: encodes data into wire format
84
+ * ``str(instances)``: dumps json object as string
85
+
86
+ """
87
+
88
+ def __init__(self, data: Any = None) -> None:
89
+ self.data = data
90
+
91
+ def __bytes__(self) -> bytes:
92
+ if self.data is None:
93
+ return b""
94
+ b = b""
95
+ for name, value in list(self.data.items()):
96
+ if isinstance(value, str):
97
+ b += bytes(value, "utf-8")
98
+ else:
99
+ b += bytes(value)
100
+ return b
101
+
102
+ def __json__(self) -> Dict[str, Any]:
103
+ if self.data is None:
104
+ return {}
105
+ d = {} # JSON output is *not* ordered
106
+ for name, value in list(self.data.items()):
107
+ if isinstance(value, Optional) and value.isempty():
108
+ continue
109
+
110
+ if isinstance(value, String):
111
+ d.update({name: str(value)})
112
+ else:
113
+ try:
114
+ d.update({name: JsonObj(value)})
115
+ except Exception:
116
+ d.update({name: value.__str__()})
117
+ return d
118
+
119
+ def __str__(self) -> str:
120
+ return json.dumps(self.__json__())
121
+
122
+ def toJson(self) -> Dict[str, Any]:
123
+ return self.__json__()
124
+
125
+ def json(self) -> Dict[str, Any]:
126
+ return self.__json__()
127
+
128
+
129
+ def isArgsThisClass(self: Any, args: tuple) -> bool:
130
+ return len(args) == 1 and type(args[0]).__name__ == type(self).__name__
@@ -0,0 +1,8 @@
1
+ #: Object types for object ids
2
+ from typing import Dict
3
+
4
+ object_type: Dict[str, int] = {}
5
+ object_type["null"] = 0
6
+ object_type["base"] = 1
7
+ object_type["account"] = 2
8
+ object_type["OBJECT_TYPE_COUNT"] = 3
@@ -0,0 +1,5 @@
1
+ #: Operation ids
2
+ from typing import Dict
3
+
4
+ operations: Dict[str, int] = {}
5
+ operations["demo_operation"] = 0
@@ -0,0 +1,25 @@
1
+ from collections import OrderedDict
2
+ from typing import Any
3
+
4
+ from .objects import GrapheneObject, isArgsThisClass
5
+ from .types import (
6
+ Set,
7
+ String,
8
+ )
9
+
10
+
11
+ class Demooepration(GrapheneObject):
12
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
13
+ if isArgsThisClass(self, args):
14
+ self.data = args[0].data
15
+ else:
16
+ if len(args) == 1 and len(kwargs) == 0:
17
+ kwargs = args[0]
18
+ super().__init__(
19
+ OrderedDict(
20
+ [
21
+ ("string", String(kwargs["string"])),
22
+ ("extensions", Set([])),
23
+ ]
24
+ )
25
+ )
@@ -0,0 +1,13 @@
1
+ from typing import Optional
2
+
3
+
4
+ class Prefix:
5
+ """This class is meant to allow changing the prefix.
6
+ The prefix is used to link a public key to a specific blockchain.
7
+ """
8
+
9
+ prefix: str = "STM"
10
+
11
+ def set_prefix(self, prefix: Optional[str]) -> None:
12
+ if prefix:
13
+ self.prefix = prefix
File without changes