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.
- hive_nectar-0.0.2.dist-info/METADATA +182 -0
- hive_nectar-0.0.2.dist-info/RECORD +86 -0
- hive_nectar-0.0.2.dist-info/WHEEL +4 -0
- hive_nectar-0.0.2.dist-info/entry_points.txt +2 -0
- hive_nectar-0.0.2.dist-info/licenses/LICENSE.txt +23 -0
- nectar/__init__.py +32 -0
- nectar/account.py +4371 -0
- nectar/amount.py +475 -0
- nectar/asciichart.py +270 -0
- nectar/asset.py +82 -0
- nectar/block.py +446 -0
- nectar/blockchain.py +1178 -0
- nectar/blockchaininstance.py +2284 -0
- nectar/blockchainobject.py +221 -0
- nectar/blurt.py +563 -0
- nectar/cli.py +6285 -0
- nectar/comment.py +1217 -0
- nectar/community.py +513 -0
- nectar/constants.py +111 -0
- nectar/conveyor.py +309 -0
- nectar/discussions.py +1709 -0
- nectar/exceptions.py +149 -0
- nectar/hive.py +546 -0
- nectar/hivesigner.py +420 -0
- nectar/imageuploader.py +72 -0
- nectar/instance.py +129 -0
- nectar/market.py +1013 -0
- nectar/memo.py +449 -0
- nectar/message.py +357 -0
- nectar/nodelist.py +444 -0
- nectar/price.py +557 -0
- nectar/profile.py +65 -0
- nectar/rc.py +308 -0
- nectar/snapshot.py +726 -0
- nectar/steem.py +582 -0
- nectar/storage.py +53 -0
- nectar/transactionbuilder.py +622 -0
- nectar/utils.py +545 -0
- nectar/version.py +2 -0
- nectar/vote.py +557 -0
- nectar/wallet.py +472 -0
- nectar/witness.py +617 -0
- nectarapi/__init__.py +11 -0
- nectarapi/exceptions.py +123 -0
- nectarapi/graphenerpc.py +589 -0
- nectarapi/node.py +178 -0
- nectarapi/noderpc.py +229 -0
- nectarapi/rpcutils.py +97 -0
- nectarapi/version.py +2 -0
- nectarbase/__init__.py +14 -0
- nectarbase/ledgertransactions.py +75 -0
- nectarbase/memo.py +243 -0
- nectarbase/objects.py +429 -0
- nectarbase/objecttypes.py +22 -0
- nectarbase/operationids.py +102 -0
- nectarbase/operations.py +1297 -0
- nectarbase/signedtransactions.py +48 -0
- nectarbase/transactions.py +11 -0
- nectarbase/version.py +2 -0
- nectargrapheneapi/__init__.py +6 -0
- nectargraphenebase/__init__.py +27 -0
- nectargraphenebase/account.py +846 -0
- nectargraphenebase/aes.py +52 -0
- nectargraphenebase/base58.py +192 -0
- nectargraphenebase/bip32.py +494 -0
- nectargraphenebase/bip38.py +134 -0
- nectargraphenebase/chains.py +149 -0
- nectargraphenebase/dictionary.py +3 -0
- nectargraphenebase/ecdsasig.py +326 -0
- nectargraphenebase/objects.py +123 -0
- nectargraphenebase/objecttypes.py +6 -0
- nectargraphenebase/operationids.py +3 -0
- nectargraphenebase/operations.py +23 -0
- nectargraphenebase/prefix.py +11 -0
- nectargraphenebase/py23.py +38 -0
- nectargraphenebase/signedtransactions.py +201 -0
- nectargraphenebase/types.py +419 -0
- nectargraphenebase/unsignedtransactions.py +283 -0
- nectargraphenebase/version.py +2 -0
- nectarstorage/__init__.py +38 -0
- nectarstorage/base.py +306 -0
- nectarstorage/exceptions.py +16 -0
- nectarstorage/interfaces.py +237 -0
- nectarstorage/masterpassword.py +239 -0
- nectarstorage/ram.py +30 -0
- nectarstorage/sqlite.py +334 -0
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
import hashlib
|
|
3
|
+
import logging
|
|
4
|
+
from binascii import hexlify, unhexlify
|
|
5
|
+
from collections import OrderedDict
|
|
6
|
+
|
|
7
|
+
import ecdsa
|
|
8
|
+
|
|
9
|
+
from nectargraphenebase.py23 import py23_bytes
|
|
10
|
+
|
|
11
|
+
from .account import PublicKey
|
|
12
|
+
from .chains import known_chains
|
|
13
|
+
from .ecdsasig import sign_message, verify_message
|
|
14
|
+
from .objects import GrapheneObject, Operation, isArgsThisClass
|
|
15
|
+
from .types import (
|
|
16
|
+
Array,
|
|
17
|
+
PointInTime,
|
|
18
|
+
Set,
|
|
19
|
+
Signature,
|
|
20
|
+
Uint16,
|
|
21
|
+
Uint32,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
log = logging.getLogger(__name__)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class Signed_Transaction(GrapheneObject):
|
|
28
|
+
"""Create a signed transaction and offer method to create the
|
|
29
|
+
signature
|
|
30
|
+
|
|
31
|
+
:param num ref_block_num: reference block number
|
|
32
|
+
:param num ref_block_prefix:
|
|
33
|
+
:param str expiration: expiration date
|
|
34
|
+
:param array operations: array of operations
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
def __init__(self, *args, **kwargs):
|
|
38
|
+
if isArgsThisClass(self, args):
|
|
39
|
+
self.data = args[0].data
|
|
40
|
+
else:
|
|
41
|
+
if len(args) == 1 and len(kwargs) == 0:
|
|
42
|
+
kwargs = args[0]
|
|
43
|
+
prefix = kwargs.pop("prefix", "STM")
|
|
44
|
+
if "extensions" not in kwargs:
|
|
45
|
+
kwargs["extensions"] = Set([])
|
|
46
|
+
elif not kwargs.get("extensions"):
|
|
47
|
+
kwargs["extensions"] = Set([])
|
|
48
|
+
if "signatures" not in kwargs:
|
|
49
|
+
kwargs["signatures"] = Array([])
|
|
50
|
+
else:
|
|
51
|
+
kwargs["signatures"] = Array(
|
|
52
|
+
[Signature(unhexlify(a)) for a in kwargs["signatures"]]
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
if "operations" in kwargs:
|
|
56
|
+
opklass = self.getOperationKlass()
|
|
57
|
+
if all([not isinstance(a, opklass) for a in kwargs["operations"]]):
|
|
58
|
+
kwargs["operations"] = Array(
|
|
59
|
+
[opklass(a, prefix=prefix) for a in kwargs["operations"]]
|
|
60
|
+
)
|
|
61
|
+
else:
|
|
62
|
+
kwargs["operations"] = Array(kwargs["operations"])
|
|
63
|
+
|
|
64
|
+
super(Signed_Transaction, self).__init__(
|
|
65
|
+
OrderedDict(
|
|
66
|
+
[
|
|
67
|
+
("ref_block_num", Uint16(kwargs["ref_block_num"])),
|
|
68
|
+
("ref_block_prefix", Uint32(kwargs["ref_block_prefix"])),
|
|
69
|
+
("expiration", PointInTime(kwargs["expiration"])),
|
|
70
|
+
("operations", kwargs["operations"]),
|
|
71
|
+
("extensions", kwargs["extensions"]),
|
|
72
|
+
("signatures", kwargs["signatures"]),
|
|
73
|
+
]
|
|
74
|
+
)
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
def id(self):
|
|
79
|
+
"""The transaction id of this transaction"""
|
|
80
|
+
# Store signatures temporarily since they are not part of
|
|
81
|
+
# transaction id
|
|
82
|
+
sigs = self.data["signatures"]
|
|
83
|
+
self.data.pop("signatures", None)
|
|
84
|
+
|
|
85
|
+
# Generage Hash of the seriliazed version
|
|
86
|
+
h = hashlib.sha256(py23_bytes(self)).digest()
|
|
87
|
+
|
|
88
|
+
# recover signatures
|
|
89
|
+
self.data["signatures"] = sigs
|
|
90
|
+
|
|
91
|
+
# Return properly truncated tx hash
|
|
92
|
+
return hexlify(h[:20]).decode("ascii")
|
|
93
|
+
|
|
94
|
+
def getOperationKlass(self):
|
|
95
|
+
return Operation
|
|
96
|
+
|
|
97
|
+
def derSigToHexSig(self, s):
|
|
98
|
+
"""Format DER to HEX signature"""
|
|
99
|
+
s, junk = ecdsa.der.remove_sequence(unhexlify(s))
|
|
100
|
+
if junk:
|
|
101
|
+
log.debug("JUNK: %s", hexlify(junk).decode("ascii"))
|
|
102
|
+
if not (junk == b""):
|
|
103
|
+
raise AssertionError()
|
|
104
|
+
x, s = ecdsa.der.remove_integer(s)
|
|
105
|
+
y, s = ecdsa.der.remove_integer(s)
|
|
106
|
+
return "%064x%064x" % (x, y)
|
|
107
|
+
|
|
108
|
+
def getKnownChains(self):
|
|
109
|
+
return known_chains
|
|
110
|
+
|
|
111
|
+
def getChainParams(self, chain):
|
|
112
|
+
# Which network are we on:
|
|
113
|
+
chains = self.getKnownChains()
|
|
114
|
+
if isinstance(chain, str) and chain in chains:
|
|
115
|
+
chain_params = chains[chain]
|
|
116
|
+
elif isinstance(chain, dict):
|
|
117
|
+
chain_params = chain
|
|
118
|
+
else:
|
|
119
|
+
raise Exception("sign() only takes a string or a dict as chain!")
|
|
120
|
+
if "chain_id" not in chain_params:
|
|
121
|
+
raise Exception("sign() needs a 'chain_id' in chain params!")
|
|
122
|
+
return chain_params
|
|
123
|
+
|
|
124
|
+
def deriveDigest(self, chain):
|
|
125
|
+
chain_params = self.getChainParams(chain)
|
|
126
|
+
# Chain ID
|
|
127
|
+
self.chainid = chain_params["chain_id"]
|
|
128
|
+
|
|
129
|
+
# Do not serialize signatures
|
|
130
|
+
sigs = self.data["signatures"]
|
|
131
|
+
self.data["signatures"] = []
|
|
132
|
+
|
|
133
|
+
# Get message to sign
|
|
134
|
+
# bytes(self) will give the wire formated data according to
|
|
135
|
+
# GrapheneObject and the data given in __init__()
|
|
136
|
+
self.message = unhexlify(self.chainid) + py23_bytes(self)
|
|
137
|
+
self.digest = hashlib.sha256(self.message).digest()
|
|
138
|
+
|
|
139
|
+
# restore signatures
|
|
140
|
+
self.data["signatures"] = sigs
|
|
141
|
+
|
|
142
|
+
def verify(self, pubkeys=[], chain=None, recover_parameter=False):
|
|
143
|
+
"""Returned pubkeys have to be checked if they are existing"""
|
|
144
|
+
if not chain:
|
|
145
|
+
raise
|
|
146
|
+
chain_params = self.getChainParams(chain)
|
|
147
|
+
self.deriveDigest(chain)
|
|
148
|
+
signatures = self.data["signatures"].data
|
|
149
|
+
pubKeysFound = []
|
|
150
|
+
|
|
151
|
+
for signature in signatures:
|
|
152
|
+
if recover_parameter:
|
|
153
|
+
p = verify_message(self.message, py23_bytes(signature))
|
|
154
|
+
else:
|
|
155
|
+
p = None
|
|
156
|
+
if p is None:
|
|
157
|
+
for i in range(4):
|
|
158
|
+
try:
|
|
159
|
+
p = verify_message(self.message, py23_bytes(signature), recover_parameter=i)
|
|
160
|
+
phex = hexlify(p).decode("ascii")
|
|
161
|
+
pubKeysFound.append(phex)
|
|
162
|
+
except Exception:
|
|
163
|
+
p = None
|
|
164
|
+
else:
|
|
165
|
+
phex = hexlify(p).decode("ascii")
|
|
166
|
+
pubKeysFound.append(phex)
|
|
167
|
+
|
|
168
|
+
for pubkey in pubkeys:
|
|
169
|
+
if not isinstance(pubkey, PublicKey):
|
|
170
|
+
raise Exception("Pubkeys must be array of 'PublicKey'")
|
|
171
|
+
|
|
172
|
+
k = pubkey.unCompressed()[2:]
|
|
173
|
+
if k not in pubKeysFound and repr(pubkey) not in pubKeysFound:
|
|
174
|
+
k = PublicKey(PublicKey(k).compressed())
|
|
175
|
+
f = format(k, chain_params["prefix"])
|
|
176
|
+
raise Exception("Signature for %s missing!" % f)
|
|
177
|
+
return pubKeysFound
|
|
178
|
+
|
|
179
|
+
def sign(self, wifkeys, chain=None):
|
|
180
|
+
"""Sign the transaction with the provided private keys.
|
|
181
|
+
|
|
182
|
+
:param array wifkeys: Array of wif keys
|
|
183
|
+
:param str chain: identifier for the chain
|
|
184
|
+
|
|
185
|
+
"""
|
|
186
|
+
if not chain:
|
|
187
|
+
raise Exception("Chain needs to be provided!")
|
|
188
|
+
self.deriveDigest(chain)
|
|
189
|
+
|
|
190
|
+
# Get Unique private keys
|
|
191
|
+
self.privkeys = []
|
|
192
|
+
[self.privkeys.append(item) for item in wifkeys if item not in self.privkeys]
|
|
193
|
+
|
|
194
|
+
# Sign the message with every private key given!
|
|
195
|
+
sigs = []
|
|
196
|
+
for wif in self.privkeys:
|
|
197
|
+
signature = sign_message(self.message, wif)
|
|
198
|
+
sigs.append(Signature(signature))
|
|
199
|
+
|
|
200
|
+
self.data["signatures"] = Array(sigs)
|
|
201
|
+
return self
|
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
import json
|
|
3
|
+
import struct
|
|
4
|
+
import sys
|
|
5
|
+
import time
|
|
6
|
+
from binascii import hexlify, unhexlify
|
|
7
|
+
from calendar import timegm
|
|
8
|
+
from datetime import datetime
|
|
9
|
+
|
|
10
|
+
from .py23 import py23_bytes
|
|
11
|
+
|
|
12
|
+
timeformat = "%Y-%m-%dT%H:%M:%S%Z"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def varint(n):
|
|
16
|
+
"""Varint encoding."""
|
|
17
|
+
data = b""
|
|
18
|
+
while n >= 0x80:
|
|
19
|
+
data += bytes([(n & 0x7F) | 0x80])
|
|
20
|
+
n >>= 7
|
|
21
|
+
data += bytes([n])
|
|
22
|
+
return data
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def varintdecode(data):
|
|
26
|
+
"""Varint decoding."""
|
|
27
|
+
shift = 0
|
|
28
|
+
result = 0
|
|
29
|
+
for b in bytes(data):
|
|
30
|
+
result |= (b & 0x7F) << shift
|
|
31
|
+
if not (b & 0x80):
|
|
32
|
+
break
|
|
33
|
+
shift += 7
|
|
34
|
+
return result
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def variable_buffer(s):
|
|
38
|
+
"""Encodes variable length buffer."""
|
|
39
|
+
return varint(len(s)) + s
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def JsonObj(data):
|
|
43
|
+
"""Returns json object from data."""
|
|
44
|
+
return json.loads(str(data))
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class Uint8(object):
|
|
48
|
+
"""Uint8."""
|
|
49
|
+
|
|
50
|
+
def __init__(self, d):
|
|
51
|
+
"""init."""
|
|
52
|
+
self.data = int(d)
|
|
53
|
+
|
|
54
|
+
def __bytes__(self):
|
|
55
|
+
"""Returns bytes."""
|
|
56
|
+
return struct.pack("<B", self.data)
|
|
57
|
+
|
|
58
|
+
def __str__(self):
|
|
59
|
+
"""Returns str"""
|
|
60
|
+
return "%d" % self.data
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class Int16(object):
|
|
64
|
+
"""Int16."""
|
|
65
|
+
|
|
66
|
+
def __init__(self, d):
|
|
67
|
+
"""init."""
|
|
68
|
+
self.data = int(d)
|
|
69
|
+
|
|
70
|
+
def __bytes__(self):
|
|
71
|
+
"""Returns bytes."""
|
|
72
|
+
return struct.pack("<h", int(self.data))
|
|
73
|
+
|
|
74
|
+
def __str__(self):
|
|
75
|
+
return "%d" % self.data
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class Uint16(object):
|
|
79
|
+
def __init__(self, d):
|
|
80
|
+
self.data = int(d)
|
|
81
|
+
|
|
82
|
+
def __bytes__(self):
|
|
83
|
+
"""Returns bytes."""
|
|
84
|
+
return struct.pack("<H", self.data)
|
|
85
|
+
|
|
86
|
+
def __str__(self):
|
|
87
|
+
return "%d" % self.data
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class Uint32(object):
|
|
91
|
+
def __init__(self, d):
|
|
92
|
+
self.data = int(d)
|
|
93
|
+
|
|
94
|
+
def __bytes__(self):
|
|
95
|
+
"""Returns bytes."""
|
|
96
|
+
return struct.pack("<I", self.data)
|
|
97
|
+
|
|
98
|
+
def __str__(self):
|
|
99
|
+
"""Returns data as string."""
|
|
100
|
+
return "%d" % self.data
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class Uint64(object):
|
|
104
|
+
def __init__(self, d):
|
|
105
|
+
self.data = int(d)
|
|
106
|
+
|
|
107
|
+
def __bytes__(self):
|
|
108
|
+
"""Returns bytes."""
|
|
109
|
+
return struct.pack("<Q", self.data)
|
|
110
|
+
|
|
111
|
+
def __str__(self):
|
|
112
|
+
"""Returns data as string."""
|
|
113
|
+
return "%d" % self.data
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class Varint32(object):
|
|
117
|
+
def __init__(self, d):
|
|
118
|
+
self.data = int(d)
|
|
119
|
+
|
|
120
|
+
def __bytes__(self):
|
|
121
|
+
"""Returns bytes."""
|
|
122
|
+
return varint(self.data)
|
|
123
|
+
|
|
124
|
+
def __str__(self):
|
|
125
|
+
"""Returns data as string."""
|
|
126
|
+
return "%d" % self.data
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class Int64(object):
|
|
130
|
+
def __init__(self, d):
|
|
131
|
+
self.data = int(d)
|
|
132
|
+
|
|
133
|
+
def __bytes__(self):
|
|
134
|
+
"""Returns bytes."""
|
|
135
|
+
return struct.pack("<q", self.data)
|
|
136
|
+
|
|
137
|
+
def __str__(self):
|
|
138
|
+
"""Returns data as string."""
|
|
139
|
+
return "%d" % self.data
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
class HexString(object):
|
|
143
|
+
def __init__(self, d):
|
|
144
|
+
self.data = d
|
|
145
|
+
|
|
146
|
+
def __bytes__(self):
|
|
147
|
+
"""Returns bytes representation."""
|
|
148
|
+
d = bytes(unhexlify(bytes(self.data, "ascii")))
|
|
149
|
+
return varint(len(d)) + d
|
|
150
|
+
|
|
151
|
+
def __str__(self):
|
|
152
|
+
"""Returns data as string."""
|
|
153
|
+
return "%s" % str(self.data)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
class String(object):
|
|
157
|
+
def __init__(self, d):
|
|
158
|
+
self.data = d
|
|
159
|
+
|
|
160
|
+
def __bytes__(self):
|
|
161
|
+
"""Returns bytes representation."""
|
|
162
|
+
d = self.unicodify()
|
|
163
|
+
return varint(len(d)) + d
|
|
164
|
+
|
|
165
|
+
def __str__(self):
|
|
166
|
+
"""Returns data as string."""
|
|
167
|
+
return "%s" % str(self.data)
|
|
168
|
+
|
|
169
|
+
def unicodify(self):
|
|
170
|
+
r = []
|
|
171
|
+
for s in self.data:
|
|
172
|
+
o = ord(s)
|
|
173
|
+
if (o <= 7) or (o == 11) or (o > 13 and o < 32):
|
|
174
|
+
r.append("u%04x" % o)
|
|
175
|
+
elif o == 8:
|
|
176
|
+
r.append("b")
|
|
177
|
+
elif o == 9:
|
|
178
|
+
r.append("\t")
|
|
179
|
+
elif o == 10:
|
|
180
|
+
r.append("\n")
|
|
181
|
+
elif o == 12:
|
|
182
|
+
r.append("f")
|
|
183
|
+
elif o == 13:
|
|
184
|
+
r.append("\r")
|
|
185
|
+
else:
|
|
186
|
+
r.append(s)
|
|
187
|
+
return bytes("".join(r), "utf-8")
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
class Bytes(object):
|
|
191
|
+
def __init__(self, d):
|
|
192
|
+
self.data = d
|
|
193
|
+
|
|
194
|
+
def __bytes__(self):
|
|
195
|
+
"""Returns data as bytes."""
|
|
196
|
+
d = unhexlify(bytes(self.data, "utf-8"))
|
|
197
|
+
return varint(len(d)) + d
|
|
198
|
+
|
|
199
|
+
def __str__(self):
|
|
200
|
+
"""Returns data as string."""
|
|
201
|
+
return str(self.data)
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
class Hash(Bytes):
|
|
205
|
+
def json(self):
|
|
206
|
+
return str(self.data)
|
|
207
|
+
|
|
208
|
+
def __bytes__(self):
|
|
209
|
+
return unhexlify(bytes(self.data, "utf-8"))
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
class Ripemd160(Hash):
|
|
213
|
+
def __init__(self, a):
|
|
214
|
+
assert len(a) == 40, "Require 40 char long hex"
|
|
215
|
+
super().__init__(a)
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
class Sha1(Hash):
|
|
219
|
+
def __init__(self, a):
|
|
220
|
+
assert len(a) == 40, "Require 40 char long hex"
|
|
221
|
+
super().__init__(a)
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
class Sha256(Hash):
|
|
225
|
+
def __init__(self, a):
|
|
226
|
+
assert len(a) == 64, "Require 64 char long hex"
|
|
227
|
+
super().__init__(a)
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
class Void(object):
|
|
231
|
+
def __init__(self):
|
|
232
|
+
pass
|
|
233
|
+
|
|
234
|
+
def __bytes__(self):
|
|
235
|
+
"""Returns bytes representation."""
|
|
236
|
+
return b""
|
|
237
|
+
|
|
238
|
+
def __str__(self):
|
|
239
|
+
"""Returns data as string."""
|
|
240
|
+
return ""
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
class Array(object):
|
|
244
|
+
def __init__(self, d):
|
|
245
|
+
self.data = d
|
|
246
|
+
self.length = Varint32(len(self.data))
|
|
247
|
+
|
|
248
|
+
def __bytes__(self):
|
|
249
|
+
"""Returns bytes representation."""
|
|
250
|
+
return py23_bytes(self.length) + b"".join([py23_bytes(a) for a in self.data])
|
|
251
|
+
|
|
252
|
+
def __str__(self):
|
|
253
|
+
"""Returns data as string."""
|
|
254
|
+
r = []
|
|
255
|
+
for a in self.data:
|
|
256
|
+
try:
|
|
257
|
+
if isinstance(a, String):
|
|
258
|
+
r.append(str(a))
|
|
259
|
+
else:
|
|
260
|
+
r.append(JsonObj(a))
|
|
261
|
+
except Exception:
|
|
262
|
+
r.append(str(a))
|
|
263
|
+
return json.dumps(r)
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
class PointInTime(object):
|
|
267
|
+
def __init__(self, d):
|
|
268
|
+
self.data = d
|
|
269
|
+
|
|
270
|
+
def __bytes__(self):
|
|
271
|
+
"""Returns bytes representation."""
|
|
272
|
+
if isinstance(self.data, datetime):
|
|
273
|
+
unixtime = timegm(self.data.timetuple())
|
|
274
|
+
elif sys.version > "3":
|
|
275
|
+
unixtime = timegm(time.strptime((self.data + "UTC"), timeformat))
|
|
276
|
+
else:
|
|
277
|
+
unixtime = timegm(time.strptime((self.data + "UTC"), timeformat.encode("utf-8")))
|
|
278
|
+
if unixtime < 0:
|
|
279
|
+
return struct.pack("<i", unixtime)
|
|
280
|
+
return struct.pack("<I", unixtime)
|
|
281
|
+
|
|
282
|
+
def __str__(self):
|
|
283
|
+
"""Returns data as string."""
|
|
284
|
+
return self.data
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
class Signature(object):
|
|
288
|
+
def __init__(self, d):
|
|
289
|
+
self.data = d
|
|
290
|
+
|
|
291
|
+
def __bytes__(self):
|
|
292
|
+
"""Returns bytes representation."""
|
|
293
|
+
return self.data
|
|
294
|
+
|
|
295
|
+
def __str__(self):
|
|
296
|
+
"""Returns data as string."""
|
|
297
|
+
return json.dumps(hexlify(self.data).decode("ascii"))
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
class Bool(Uint8): # Bool = Uint8
|
|
301
|
+
def __init__(self, d):
|
|
302
|
+
super(Bool, self).__init__(d)
|
|
303
|
+
|
|
304
|
+
def __str__(self):
|
|
305
|
+
"""Returns data as string."""
|
|
306
|
+
return json.dumps(True) if self.data else json.dumps(False)
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
class Set(Array): # Set = Array
|
|
310
|
+
def __init__(self, d):
|
|
311
|
+
super(Set, self).__init__(d)
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
class Fixed_array(object):
|
|
315
|
+
def __init__(self, d):
|
|
316
|
+
raise NotImplementedError
|
|
317
|
+
|
|
318
|
+
def __bytes__(self):
|
|
319
|
+
"""Returns bytes representation."""
|
|
320
|
+
raise NotImplementedError
|
|
321
|
+
|
|
322
|
+
def __str__(self):
|
|
323
|
+
"""Returns data as string."""
|
|
324
|
+
raise NotImplementedError
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
class Optional(object):
|
|
328
|
+
def __init__(self, d):
|
|
329
|
+
self.data = d
|
|
330
|
+
|
|
331
|
+
def __bytes__(self):
|
|
332
|
+
"""Returns data as bytes."""
|
|
333
|
+
if not self.data:
|
|
334
|
+
return py23_bytes(Bool(0))
|
|
335
|
+
else:
|
|
336
|
+
return (
|
|
337
|
+
py23_bytes(Bool(1)) + py23_bytes(self.data)
|
|
338
|
+
if py23_bytes(self.data)
|
|
339
|
+
else py23_bytes(Bool(0))
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
def __str__(self):
|
|
343
|
+
"""Returns data as string."""
|
|
344
|
+
return str(self.data)
|
|
345
|
+
|
|
346
|
+
def isempty(self):
|
|
347
|
+
if not self.data:
|
|
348
|
+
return True
|
|
349
|
+
return not bool(py23_bytes(self.data))
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
class Static_variant(object):
|
|
353
|
+
def __init__(self, d, type_id, legacy_style=True):
|
|
354
|
+
self.data = d
|
|
355
|
+
self.type_id = type_id
|
|
356
|
+
|
|
357
|
+
# `legacy_style = True` it means, that static variant is treated like an array, otherwise like an object
|
|
358
|
+
self.legacy_style = legacy_style
|
|
359
|
+
|
|
360
|
+
def __bytes__(self):
|
|
361
|
+
"""Returns bytes representation."""
|
|
362
|
+
return varint(self.type_id) + py23_bytes(self.data)
|
|
363
|
+
|
|
364
|
+
def __str__(self):
|
|
365
|
+
"""Returns data as string."""
|
|
366
|
+
if self.legacy_style:
|
|
367
|
+
return json.dumps([self.type_id, self.data.json()])
|
|
368
|
+
else:
|
|
369
|
+
return json.dumps({"type": self.type_id, "value": self.data.json()})
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
class Map(object):
|
|
373
|
+
def __init__(self, data):
|
|
374
|
+
self.data = data
|
|
375
|
+
|
|
376
|
+
def __bytes__(self):
|
|
377
|
+
"""Returns bytes representation."""
|
|
378
|
+
b = b""
|
|
379
|
+
b += varint(len(self.data))
|
|
380
|
+
for e in self.data:
|
|
381
|
+
b += py23_bytes(e[0]) + py23_bytes(e[1])
|
|
382
|
+
return b
|
|
383
|
+
|
|
384
|
+
def __str__(self):
|
|
385
|
+
"""Returns data as string."""
|
|
386
|
+
r = []
|
|
387
|
+
for e in self.data:
|
|
388
|
+
r.append([str(e[0]), str(e[1])])
|
|
389
|
+
return json.dumps(r)
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
class Id(object):
|
|
393
|
+
def __init__(self, d):
|
|
394
|
+
self.data = Varint32(d)
|
|
395
|
+
|
|
396
|
+
def __bytes__(self):
|
|
397
|
+
"""Returns bytes representation."""
|
|
398
|
+
return py23_bytes(self.data)
|
|
399
|
+
|
|
400
|
+
def __str__(self):
|
|
401
|
+
"""Returns data as string."""
|
|
402
|
+
return str(self.data)
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
class Enum8(Uint8):
|
|
406
|
+
# List needs to be provided by super class
|
|
407
|
+
options = []
|
|
408
|
+
|
|
409
|
+
def __init__(self, selection):
|
|
410
|
+
if selection not in self.options or (
|
|
411
|
+
isinstance(selection, int) and len(self.options) < selection
|
|
412
|
+
):
|
|
413
|
+
raise ValueError("Options are {}. Given '{}'".format(str(self.options), selection))
|
|
414
|
+
|
|
415
|
+
super(Enum8, self).__init__(self.options.index(selection))
|
|
416
|
+
|
|
417
|
+
def __str__(self):
|
|
418
|
+
"""Returns data as string."""
|
|
419
|
+
return str(self.options[self.data])
|