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
nectarbase/memo.py ADDED
@@ -0,0 +1,243 @@
1
+ # -*- coding: utf-8 -*-
2
+ import hashlib
3
+ from binascii import hexlify, unhexlify
4
+
5
+ from nectargraphenebase.base58 import base58decode, base58encode
6
+ from nectargraphenebase.py23 import py23_bytes
7
+ from nectargraphenebase.types import varintdecode
8
+
9
+ try:
10
+ from Cryptodome.Cipher import AES
11
+ except ImportError:
12
+ try:
13
+ from Crypto.Cipher import AES
14
+ except ImportError:
15
+ raise ImportError("Missing dependency: pyCryptodome")
16
+ import struct
17
+
18
+ from nectargraphenebase.account import PublicKey
19
+
20
+ from .objects import Memo
21
+
22
+ default_prefix = "STM"
23
+
24
+
25
+ def get_shared_secret(priv, pub):
26
+ """Derive the share secret between ``priv`` and ``pub``
27
+ :param `Base58` priv: Private Key
28
+ :param `Base58` pub: Public Key
29
+ :return: Shared secret
30
+ :rtype: hex
31
+ The shared secret is generated such that::
32
+ Pub(Alice) * Priv(Bob) = Pub(Bob) * Priv(Alice)
33
+ """
34
+ pub_point = pub.point()
35
+ priv_point = int(repr(priv), 16)
36
+ res = pub_point * priv_point
37
+ res_hex = "%032x" % res.x()
38
+ # Zero padding
39
+ res_hex = "0" * (64 - len(res_hex)) + res_hex
40
+ return res_hex
41
+
42
+
43
+ def init_aes(shared_secret, nonce):
44
+ """Initialize AES instance
45
+ :param hex shared_secret: Shared Secret to use as encryption key
46
+ :param int nonce: Random nonce
47
+ :return: AES instance
48
+ :rtype: AES
49
+ """
50
+ " Shared Secret "
51
+ ss = hashlib.sha512(unhexlify(shared_secret)).digest()
52
+ " Seed "
53
+ seed = py23_bytes(str(nonce), "ascii") + hexlify(ss)
54
+ seed_digest = hexlify(hashlib.sha512(seed).digest()).decode("ascii")
55
+ " AES "
56
+ key = unhexlify(seed_digest[0:64])
57
+ iv = unhexlify(seed_digest[64:96])
58
+ return AES.new(key, AES.MODE_CBC, iv)
59
+
60
+
61
+ def init_aes_bts(shared_secret, nonce):
62
+ """Initialize AES instance
63
+ :param hex shared_secret: Shared Secret to use as encryption key
64
+ :param int nonce: Random nonce
65
+ :return: AES instance
66
+ :rtype: AES
67
+ """
68
+ " Shared Secret "
69
+ ss = hashlib.sha512(unhexlify(shared_secret)).digest()
70
+ " Seed "
71
+ seed = bytes(str(nonce), "ascii") + hexlify(ss)
72
+ seed_digest = hexlify(hashlib.sha512(seed).digest()).decode("ascii")
73
+ " AES "
74
+ key = unhexlify(seed_digest[0:64])
75
+ iv = unhexlify(seed_digest[64:96])
76
+ return AES.new(key, AES.MODE_CBC, iv)
77
+
78
+
79
+ def init_aes(shared_secret, nonce):
80
+ """Initialize AES instance
81
+ :param hex shared_secret: Shared Secret to use as encryption key
82
+ :param int nonce: Random nonce
83
+ """
84
+ shared_secret = hashlib.sha512(unhexlify(shared_secret)).hexdigest()
85
+ # Seed
86
+ ss = unhexlify(shared_secret)
87
+ n = struct.pack("<Q", int(nonce))
88
+ encryption_key = hashlib.sha512(n + ss).hexdigest()
89
+ # Check'sum'
90
+ check = hashlib.sha256(unhexlify(encryption_key)).digest()
91
+ check = struct.unpack_from("<I", check[:4])[0]
92
+ # AES
93
+ key = unhexlify(encryption_key[0:64])
94
+ iv = unhexlify(encryption_key[64:96])
95
+ return AES.new(key, AES.MODE_CBC, iv), check
96
+
97
+
98
+ def _pad(s, BS):
99
+ numBytes = BS - len(s) % BS
100
+ return s + numBytes * struct.pack("B", numBytes)
101
+
102
+
103
+ def _unpad(s, BS):
104
+ count = s[-1]
105
+ if s[-count::] == count * struct.pack("B", count):
106
+ return s[:-count]
107
+ return s
108
+
109
+
110
+ def encode_memo_bts(priv, pub, nonce, message):
111
+ """Encode a message with a shared secret between Alice and Bob
112
+
113
+ :param PrivateKey priv: Private Key (of Alice)
114
+ :param PublicKey pub: Public Key (of Bob)
115
+ :param int nonce: Random nonce
116
+ :param str message: Memo message
117
+ :return: Encrypted message
118
+ :rtype: hex
119
+
120
+ """
121
+ shared_secret = get_shared_secret(priv, pub)
122
+ aes = init_aes_bts(shared_secret, nonce)
123
+ " Checksum "
124
+ raw = py23_bytes(message, "utf8")
125
+ checksum = hashlib.sha256(raw).digest()
126
+ raw = checksum[0:4] + raw
127
+ " Padding "
128
+ raw = _pad(raw, 16)
129
+ " Encryption "
130
+ return hexlify(aes.encrypt(raw)).decode("ascii")
131
+
132
+
133
+ def decode_memo_bts(priv, pub, nonce, message):
134
+ """Decode a message with a shared secret between Alice and Bob
135
+
136
+ :param PrivateKey priv: Private Key (of Bob)
137
+ :param PublicKey pub: Public Key (of Alice)
138
+ :param int nonce: Nonce used for Encryption
139
+ :param bytes message: Encrypted Memo message
140
+ :return: Decrypted message
141
+ :rtype: str
142
+ :raise ValueError: if message cannot be decoded as valid UTF-8
143
+ string
144
+
145
+ """
146
+ shared_secret = get_shared_secret(priv, pub)
147
+ aes = init_aes_bts(shared_secret, nonce)
148
+ " Encryption "
149
+ raw = py23_bytes(message, "ascii")
150
+ cleartext = aes.decrypt(unhexlify(raw))
151
+ " Checksum "
152
+ checksum = cleartext[0:4]
153
+ message = cleartext[4:]
154
+ message = _unpad(message, 16)
155
+ " Verify checksum "
156
+ check = hashlib.sha256(message).digest()[0:4]
157
+ if check != checksum: # pragma: no cover
158
+ raise ValueError("checksum verification failure")
159
+ return message.decode("utf8")
160
+
161
+
162
+ def encode_memo(priv, pub, nonce, message, **kwargs):
163
+ """Encode a message with a shared secret between Alice and Bob
164
+
165
+ :param PrivateKey priv: Private Key (of Alice)
166
+ :param PublicKey pub: Public Key (of Bob)
167
+ :param int nonce: Random nonce
168
+ :param str message: Memo message
169
+ :return: Encrypted message
170
+ :rtype: hex
171
+ """
172
+ shared_secret = get_shared_secret(priv, pub)
173
+ aes, check = init_aes(shared_secret, nonce)
174
+ " Padding "
175
+ raw = py23_bytes(message, "utf8")
176
+ raw = _pad(raw, 16)
177
+ " Encryption "
178
+ cipher = hexlify(aes.encrypt(raw)).decode("ascii")
179
+ prefix = kwargs.pop("prefix", default_prefix)
180
+ s = {
181
+ "from": format(priv.pubkey, prefix),
182
+ "to": format(pub, prefix),
183
+ "nonce": nonce,
184
+ "check": check,
185
+ "encrypted": cipher,
186
+ "prefix": prefix,
187
+ }
188
+ tx = Memo(**s)
189
+ return "#" + base58encode(hexlify(py23_bytes(tx)).decode("ascii"))
190
+
191
+
192
+ def extract_memo_data(message):
193
+ """Returns the stored pubkey keys, nonce, checksum and encrypted message of a memo"""
194
+ raw = base58decode(message[1:])
195
+ from_key = PublicKey(raw[:66])
196
+ raw = raw[66:]
197
+ to_key = PublicKey(raw[:66])
198
+ raw = raw[66:]
199
+ nonce = str(struct.unpack_from("<Q", unhexlify(raw[:16]))[0])
200
+ raw = raw[16:]
201
+ check = struct.unpack_from("<I", unhexlify(raw[:8]))[0]
202
+ raw = raw[8:]
203
+ cipher = raw
204
+ return from_key, to_key, nonce, check, cipher
205
+
206
+
207
+ def decode_memo(priv, message):
208
+ """Decode a message with a shared secret between Alice and Bob
209
+
210
+ :param PrivateKey priv: Private Key (of Bob)
211
+ :param base58encoded message: Encrypted Memo message
212
+ :return: Decrypted message
213
+ :rtype: str
214
+ :raise ValueError: if message cannot be decoded as valid UTF-8
215
+ string
216
+ """
217
+ # decode structure
218
+ from_key, to_key, nonce, check, cipher = extract_memo_data(message)
219
+
220
+ if repr(to_key) == repr(priv.pubkey):
221
+ shared_secret = get_shared_secret(priv, from_key)
222
+ elif repr(from_key) == repr(priv.pubkey):
223
+ shared_secret = get_shared_secret(priv, to_key)
224
+ else:
225
+ raise ValueError("Incorrect PrivateKey")
226
+
227
+ # Init encryption
228
+ aes, checksum = init_aes(shared_secret, nonce)
229
+ # Check
230
+ if not check == checksum:
231
+ raise AssertionError("Checksum failure")
232
+ # Encryption
233
+ # remove the varint prefix (FIXME, long messages!)
234
+ numBytes = 16 - len(cipher) % 16
235
+ n = 16 - numBytes
236
+ message = cipher[n:]
237
+ message = aes.decrypt(unhexlify(py23_bytes(message, "ascii")))
238
+ message = _unpad(message, 16)
239
+ n = varintdecode(message)
240
+ if (len(message) - n) > 0 and (len(message) - n) < 8:
241
+ return "#" + message[len(message) - n :].decode("utf8")
242
+ else:
243
+ return "#" + message.decode("utf8")
nectarbase/objects.py ADDED
@@ -0,0 +1,429 @@
1
+ # -*- coding: utf-8 -*-
2
+ import decimal
3
+ import json
4
+ import struct
5
+ from collections import OrderedDict
6
+
7
+ from nectargraphenebase.account import PublicKey
8
+ from nectargraphenebase.chains import known_chains
9
+ from nectargraphenebase.objects import GrapheneObject, isArgsThisClass
10
+ from nectargraphenebase.objects import Operation as GPHOperation
11
+ from nectargraphenebase.py23 import py23_bytes, string_types
12
+ from nectargraphenebase.types import (
13
+ Array,
14
+ Bytes,
15
+ Id,
16
+ Int16,
17
+ Map,
18
+ PointInTime,
19
+ Static_variant,
20
+ String,
21
+ Uint16,
22
+ Uint32,
23
+ Uint64,
24
+ )
25
+
26
+ from .operationids import operations
27
+
28
+ default_prefix = "STM"
29
+
30
+
31
+ def value_to_decimal(value, decimal_places):
32
+ decimal.getcontext().rounding = decimal.ROUND_DOWN # define rounding method
33
+ return decimal.Decimal(str(float(value))).quantize(
34
+ decimal.Decimal("1e-{}".format(decimal_places))
35
+ )
36
+
37
+
38
+ class Amount(object):
39
+ def __init__(self, d, prefix=default_prefix, json_str=False):
40
+ self.json_str = json_str
41
+ if isinstance(d, string_types):
42
+ self.amount, self.symbol = d.strip().split(" ")
43
+ self.precision = None
44
+ for c in known_chains:
45
+ if self.precision is not None:
46
+ continue
47
+ if known_chains[c]["prefix"] != prefix:
48
+ continue
49
+ for asset in known_chains[c]["chain_assets"]:
50
+ if self.precision is not None:
51
+ continue
52
+ if asset["symbol"] == self.symbol:
53
+ self.precision = asset["precision"]
54
+ self.asset = asset["asset"]
55
+ elif asset["asset"] == self.symbol:
56
+ self.precision = asset["precision"]
57
+ self.asset = asset["asset"]
58
+ if self.precision is None:
59
+ raise Exception("Asset unknown")
60
+ self.amount = round(value_to_decimal(self.amount, self.precision) * 10**self.precision)
61
+ # Workaround to allow transfers in HIVE
62
+
63
+ self.str_repr = "{:.{}f} {}".format(
64
+ (float(self.amount) / 10**self.precision), self.precision, self.symbol
65
+ )
66
+ elif isinstance(d, list):
67
+ self.amount = d[0]
68
+ self.asset = d[2]
69
+ self.precision = d[1]
70
+ self.symbol = None
71
+ for c in known_chains:
72
+ if known_chains[c]["prefix"] != prefix:
73
+ continue
74
+ for asset in known_chains[c]["chain_assets"]:
75
+ if asset["asset"] == self.asset:
76
+ self.symbol = asset["symbol"]
77
+ if self.symbol is None:
78
+ raise ValueError("Unknown NAI, cannot resolve symbol")
79
+ a = Array([String(d[0]), d[1], d[2]])
80
+ self.str_repr = str(a.__str__())
81
+ elif isinstance(d, dict) and "nai" in d:
82
+ self.asset = d["nai"]
83
+ self.symbol = None
84
+ for c in known_chains:
85
+ if known_chains[c]["prefix"] != prefix:
86
+ continue
87
+ for asset in known_chains[c]["chain_assets"]:
88
+ if asset["asset"] == d["nai"]:
89
+ self.symbol = asset["symbol"]
90
+ if self.symbol is None:
91
+ raise ValueError("Unknown NAI, cannot resolve symbol")
92
+ self.amount = d["amount"]
93
+ self.precision = d["precision"]
94
+ self.str_repr = json.dumps(d)
95
+ else:
96
+ self.amount = d.amount
97
+ self.symbol = d.symbol
98
+ self.asset = d.asset["asset"]
99
+ self.precision = d.asset["precision"]
100
+ self.amount = round(value_to_decimal(self.amount, self.precision) * 10**self.precision)
101
+ self.str_repr = str(d)
102
+ # self.str_repr = json.dumps((d.json()))
103
+ # self.str_repr = '{:.{}f} {}'.format((float(self.amount) / 10 ** self.precision), self.precision, self.asset)
104
+
105
+ def __bytes__(self):
106
+ # padding
107
+ # Workaround to allow transfers in HIVE
108
+ if self.symbol == "HBD":
109
+ self.symbol = "SBD"
110
+ elif self.symbol == "HIVE":
111
+ self.symbol = "STEEM"
112
+ symbol = self.symbol + "\x00" * (7 - len(self.symbol))
113
+ return (
114
+ struct.pack("<q", int(self.amount))
115
+ + struct.pack("<b", self.precision)
116
+ + py23_bytes(symbol, "ascii")
117
+ )
118
+
119
+ def __str__(self):
120
+ if self.json_str:
121
+ return json.dumps(
122
+ {"amount": str(self.amount), "precision": self.precision, "nai": self.asset}
123
+ )
124
+ return self.str_repr
125
+
126
+
127
+ class Operation(GPHOperation):
128
+ def __init__(self, *args, **kwargs):
129
+ self.appbase = kwargs.pop("appbase", False)
130
+ self.prefix = kwargs.pop("prefix", default_prefix)
131
+ super(Operation, self).__init__(*args, **kwargs)
132
+
133
+ def _getklass(self, name):
134
+ module = __import__("nectarbase.operations", fromlist=["operations"])
135
+ class_ = getattr(module, name)
136
+ return class_
137
+
138
+ def operations(self):
139
+ return operations
140
+
141
+ def getOperationNameForId(self, i):
142
+ """Convert an operation id into the corresponding string"""
143
+ for key in self.operations():
144
+ if int(self.operations()[key]) is int(i):
145
+ return key
146
+ return "Unknown Operation ID %d" % i
147
+
148
+ def json(self):
149
+ return json.loads(str(self))
150
+ # return json.loads(str(json.dumps([self.name, self.op.toJson()])))
151
+
152
+ def __bytes__(self):
153
+ return py23_bytes(Id(self.opId)) + py23_bytes(self.op)
154
+
155
+ def __str__(self):
156
+ if self.appbase:
157
+ return json.dumps({"type": self.name.lower() + "_operation", "value": self.op.toJson()})
158
+ else:
159
+ return json.dumps([self.name.lower(), self.op.toJson()])
160
+
161
+
162
+ class Memo(GrapheneObject):
163
+ def __init__(self, *args, **kwargs):
164
+ if isArgsThisClass(self, args):
165
+ self.data = args[0].data
166
+ else:
167
+ prefix = kwargs.pop("prefix", default_prefix)
168
+ if "encrypted" not in kwargs or not kwargs["encrypted"]:
169
+ super(Memo, self).__init__(None)
170
+ else:
171
+ if len(args) == 1 and len(kwargs) == 0:
172
+ kwargs = args[0]
173
+ if "encrypted" in kwargs and kwargs["encrypted"]:
174
+ super(Memo, self).__init__(
175
+ OrderedDict(
176
+ [
177
+ ("from", PublicKey(kwargs["from"], prefix=prefix)),
178
+ ("to", PublicKey(kwargs["to"], prefix=prefix)),
179
+ ("nonce", Uint64(int(kwargs["nonce"]))),
180
+ ("check", Uint32(int(kwargs["check"]))),
181
+ ("encrypted", Bytes(kwargs["encrypted"])),
182
+ ]
183
+ )
184
+ )
185
+
186
+
187
+ class WitnessProps(GrapheneObject):
188
+ def __init__(self, *args, **kwargs):
189
+ if isArgsThisClass(self, args):
190
+ self.data = args[0].data
191
+ else:
192
+ if len(args) == 1 and len(kwargs) == 0:
193
+ kwargs = args[0]
194
+ prefix = kwargs.get("prefix", default_prefix)
195
+ if "sbd_interest_rate" in kwargs:
196
+ super(WitnessProps, self).__init__(
197
+ OrderedDict(
198
+ [
199
+ (
200
+ "account_creation_fee",
201
+ Amount(kwargs["account_creation_fee"], prefix=prefix),
202
+ ),
203
+ ("maximum_block_size", Uint32(kwargs["maximum_block_size"])),
204
+ ("sbd_interest_rate", Uint16(kwargs["sbd_interest_rate"])),
205
+ ]
206
+ )
207
+ )
208
+ elif "hbd_interest_rate" in kwargs:
209
+ super(WitnessProps, self).__init__(
210
+ OrderedDict(
211
+ [
212
+ (
213
+ "account_creation_fee",
214
+ Amount(kwargs["account_creation_fee"], prefix=prefix),
215
+ ),
216
+ ("maximum_block_size", Uint32(kwargs["maximum_block_size"])),
217
+ ("hbd_interest_rate", Uint16(kwargs["hbd_interest_rate"])),
218
+ ]
219
+ )
220
+ )
221
+ else:
222
+ super(WitnessProps, self).__init__(
223
+ OrderedDict(
224
+ [
225
+ (
226
+ "account_creation_fee",
227
+ Amount(kwargs["account_creation_fee"], prefix=prefix),
228
+ ),
229
+ ("maximum_block_size", Uint32(kwargs["maximum_block_size"])),
230
+ ]
231
+ )
232
+ )
233
+
234
+
235
+ class Price(GrapheneObject):
236
+ def __init__(self, *args, **kwargs):
237
+ if isArgsThisClass(self, args):
238
+ self.data = args[0].data
239
+ else:
240
+ if len(args) == 1 and len(kwargs) == 0:
241
+ kwargs = args[0]
242
+ prefix = kwargs.get("prefix", default_prefix)
243
+ super(Price, self).__init__(
244
+ OrderedDict(
245
+ [
246
+ ("base", Amount(kwargs["base"], prefix=prefix)),
247
+ ("quote", Amount(kwargs["quote"], prefix=prefix)),
248
+ ]
249
+ )
250
+ )
251
+
252
+
253
+ class Permission(GrapheneObject):
254
+ def __init__(self, *args, **kwargs):
255
+ if isArgsThisClass(self, args):
256
+ self.data = args[0].data
257
+ else:
258
+ prefix = kwargs.pop("prefix", default_prefix)
259
+
260
+ if len(args) == 1 and len(kwargs) == 0:
261
+ kwargs = args[0]
262
+
263
+ # Sort keys (FIXME: ideally, the sorting is part of Public
264
+ # Key and not located here)
265
+ kwargs["key_auths"] = sorted(
266
+ kwargs["key_auths"],
267
+ key=lambda x: repr(PublicKey(x[0], prefix=prefix)),
268
+ reverse=False,
269
+ )
270
+ kwargs["account_auths"] = sorted(
271
+ kwargs["account_auths"],
272
+ key=lambda x: x[0],
273
+ reverse=False,
274
+ )
275
+ accountAuths = Map([[String(e[0]), Uint16(e[1])] for e in kwargs["account_auths"]])
276
+ keyAuths = Map(
277
+ [[PublicKey(e[0], prefix=prefix), Uint16(e[1])] for e in kwargs["key_auths"]]
278
+ )
279
+ super(Permission, self).__init__(
280
+ OrderedDict(
281
+ [
282
+ ("weight_threshold", Uint32(int(kwargs["weight_threshold"]))),
283
+ ("account_auths", accountAuths),
284
+ ("key_auths", keyAuths),
285
+ ]
286
+ )
287
+ )
288
+
289
+
290
+ class Extension(Array):
291
+ def __str__(self):
292
+ """We overload the __str__ function because the json
293
+ representation is different for extensions
294
+ """
295
+ return json.dumps(self.json)
296
+
297
+
298
+ class ExchangeRate(GrapheneObject):
299
+ def __init__(self, *args, **kwargs):
300
+ if isArgsThisClass(self, args):
301
+ self.data = args[0].data
302
+ else:
303
+ if len(args) == 1 and len(kwargs) == 0:
304
+ kwargs = args[0]
305
+
306
+ prefix = kwargs.get("prefix", default_prefix)
307
+ super(ExchangeRate, self).__init__(
308
+ OrderedDict(
309
+ [
310
+ ("base", Amount(kwargs["base"], prefix=prefix)),
311
+ ("quote", Amount(kwargs["quote"], prefix=prefix)),
312
+ ]
313
+ )
314
+ )
315
+
316
+
317
+ class Beneficiary(GrapheneObject):
318
+ def __init__(self, *args, **kwargs):
319
+ if isArgsThisClass(self, args):
320
+ self.data = args[0].data
321
+ else:
322
+ if len(args) == 1 and len(kwargs) == 0:
323
+ kwargs = args[0]
324
+ super(Beneficiary, self).__init__(
325
+ OrderedDict(
326
+ [
327
+ ("account", String(kwargs["account"])),
328
+ ("weight", Int16(kwargs["weight"])),
329
+ ]
330
+ )
331
+ )
332
+
333
+
334
+ class Beneficiaries(GrapheneObject):
335
+ def __init__(self, *args, **kwargs):
336
+ if isArgsThisClass(self, args):
337
+ self.data = args[0].data
338
+ else:
339
+ if len(args) == 1 and len(kwargs) == 0:
340
+ kwargs = args[0]
341
+
342
+ super(Beneficiaries, self).__init__(
343
+ OrderedDict(
344
+ [
345
+ ("beneficiaries", Array([Beneficiary(o) for o in kwargs["beneficiaries"]])),
346
+ ]
347
+ )
348
+ )
349
+
350
+
351
+ class CommentOptionExtensions(Static_variant):
352
+ """Serialize Comment Payout Beneficiaries.
353
+
354
+ :param list beneficiaries: A static_variant containing beneficiaries.
355
+
356
+ Example::
357
+
358
+ [0,
359
+ {'beneficiaries': [
360
+ {'account': 'furion', 'weight': 10000}
361
+ ]}
362
+ ]
363
+
364
+ """
365
+
366
+ def __init__(self, o):
367
+ if type(o) == dict and "type" in o and "value" in o:
368
+ if o["type"] == "comment_payout_beneficiaries":
369
+ type_id = 0
370
+ else:
371
+ type_id = ~0
372
+ data = o["value"]
373
+ else:
374
+ type_id, data = o
375
+ if type_id == 0:
376
+ data = Beneficiaries(data)
377
+ else:
378
+ raise Exception("Unknown CommentOptionExtension")
379
+ super(CommentOptionExtensions, self).__init__(data, type_id)
380
+
381
+
382
+ class UpdateProposalEndDate(GrapheneObject):
383
+ def __init__(self, *args, **kwargs):
384
+ if isArgsThisClass(self, args):
385
+ self.data = args[0].data
386
+ else:
387
+ if len(args) == 1 and len(kwargs) == 0:
388
+ kwargs = args[0]
389
+
390
+ super(UpdateProposalEndDate, self).__init__(
391
+ OrderedDict(
392
+ [
393
+ ("end_date", PointInTime(kwargs["end_date"])),
394
+ ]
395
+ )
396
+ )
397
+
398
+
399
+ class UpdateProposalExtensions(Static_variant):
400
+ """Serialize Update proposal extensions.
401
+
402
+ :param end_date: A static_variant containing the new end_date.
403
+
404
+ Example::
405
+
406
+ {
407
+ 'type': '1',
408
+ 'value':
409
+ {
410
+ 'end_date': '2021-04-05T13:39:48'
411
+ }
412
+ }
413
+
414
+ """
415
+
416
+ def __init__(self, o):
417
+ if isinstance(o, dict) and "type" in o and "value" in o:
418
+ if o["type"] == "update_proposal_end_date":
419
+ type_id = 1
420
+ else:
421
+ type_id = ~0
422
+ else:
423
+ type_id, data = o
424
+
425
+ if type_id == 1:
426
+ data = UpdateProposalEndDate(o["value"])
427
+ else:
428
+ raise Exception("Unknown UpdateProposalExtension")
429
+ super(UpdateProposalExtensions, self).__init__(data, type_id, False)
@@ -0,0 +1,22 @@
1
+ # -*- coding: utf-8 -*-
2
+ #: Object types for object ids
3
+ object_type = {}
4
+ object_type["dynamic_global_property"] = 0
5
+ object_type["reserved0"] = 1
6
+ object_type["account"] = 2
7
+ object_type["witness"] = 3
8
+ object_type["transaction"] = 4
9
+ object_type["block_summary"] = 5
10
+ object_type["chain_property"] = 6
11
+ object_type["witness_schedule"] = 7
12
+ object_type["comment"] = 8
13
+ object_type["category"] = 9
14
+ object_type["comment_vote"] = 10
15
+ object_type["vote"] = 11
16
+ object_type["witness_vote"] = 12
17
+ object_type["limit_order"] = 13
18
+ object_type["feed_history"] = 14
19
+ object_type["convert_request"] = 15
20
+ object_type["liquidity_reward_balance"] = 16
21
+ object_type["operation"] = 17
22
+ object_type["account_history"] = 18