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
nectarbase/objects.py ADDED
@@ -0,0 +1,521 @@
1
+ import decimal
2
+ import json
3
+ import struct
4
+ from collections import OrderedDict
5
+ from typing import Any, Dict, Union
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.types import (
12
+ Array,
13
+ Bytes,
14
+ Id,
15
+ Int16,
16
+ Map,
17
+ PointInTime,
18
+ Static_variant,
19
+ String,
20
+ Uint16,
21
+ Uint32,
22
+ Uint64,
23
+ )
24
+
25
+ from .operationids import operations
26
+
27
+ default_prefix = "STM"
28
+
29
+
30
+ def value_to_decimal(value: Union[str, float, int], decimal_places: int) -> decimal.Decimal:
31
+ decimal.getcontext().rounding = decimal.ROUND_DOWN # define rounding method
32
+ return decimal.Decimal(str(float(value))).quantize(
33
+ decimal.Decimal("1e-{}".format(decimal_places))
34
+ )
35
+
36
+
37
+ class Amount:
38
+ def __init__(
39
+ self,
40
+ d: Union[str, Any],
41
+ prefix: str = default_prefix,
42
+ json_str: bool = False,
43
+ **kwargs,
44
+ ) -> None:
45
+ self.json_str = json_str
46
+ if isinstance(d, str):
47
+ self.amount, self.symbol = d.strip().split(" ")
48
+ self.precision = None
49
+ for c in known_chains:
50
+ if self.precision is not None:
51
+ continue
52
+ if known_chains[c]["prefix"] != prefix:
53
+ continue
54
+ for asset in known_chains[c]["chain_assets"]:
55
+ if self.precision is not None:
56
+ continue
57
+ if asset["symbol"] == self.symbol:
58
+ self.precision = asset["precision"]
59
+ self.asset = asset["asset"]
60
+ elif asset["asset"] == self.symbol:
61
+ self.precision = asset["precision"]
62
+ self.asset = asset["asset"]
63
+ if self.precision is None:
64
+ raise Exception("Asset unknown")
65
+ self.amount = round(
66
+ value_to_decimal(float(self.amount), self.precision) * 10**self.precision
67
+ )
68
+ # Workaround to allow transfers in HIVE
69
+
70
+ self.str_repr = "{:.{}f} {}".format(
71
+ (float(self.amount) / 10**self.precision), self.precision, self.symbol
72
+ )
73
+ elif isinstance(d, list):
74
+ self.amount = d[0]
75
+ self.asset = d[2]
76
+ self.precision = d[1]
77
+ self.symbol = None
78
+ for c in known_chains:
79
+ if known_chains[c]["prefix"] != prefix:
80
+ continue
81
+ for asset in known_chains[c]["chain_assets"]:
82
+ if asset["asset"] == self.asset:
83
+ self.symbol = asset["symbol"]
84
+ if self.symbol is None:
85
+ raise ValueError("Unknown NAI, cannot resolve symbol")
86
+ a = Array([String(d[0]), d[1], d[2]])
87
+ self.str_repr = str(a.__str__())
88
+ elif isinstance(d, dict) and "nai" in d:
89
+ self.asset = d["nai"]
90
+ self.symbol = None
91
+ for c in known_chains:
92
+ if known_chains[c]["prefix"] != prefix:
93
+ continue
94
+ for asset in known_chains[c]["chain_assets"]:
95
+ if asset["asset"] == d["nai"]:
96
+ self.symbol = asset["symbol"]
97
+ if self.symbol is None:
98
+ raise ValueError("Unknown NAI, cannot resolve symbol")
99
+ self.amount = d["amount"]
100
+ self.precision = d["precision"]
101
+ self.str_repr = json.dumps(d)
102
+ elif isinstance(d, dict) and "amount" in d and "asset" in d:
103
+ self.amount = d["amount"]
104
+ asset_obj = d["asset"]
105
+ self.precision = asset_obj["precision"]
106
+ self.asset = asset_obj.get("asset", asset_obj.get("nai"))
107
+ self.symbol = asset_obj.get("symbol")
108
+ self.amount = round(value_to_decimal(self.amount, self.precision) * 10**self.precision)
109
+ if hasattr(d, "json"):
110
+ self.str_repr = json.dumps(d.json())
111
+ else:
112
+ # Fallback or manual construction if needed, but for now just str(d) or skip
113
+ # If d is a dict with Decimal, we can't json dump it directly.
114
+ # But we only expect nectar.amount.Amount here which has .json()
115
+ self.str_repr = json.dumps(
116
+ d
117
+ ) # This might still fail if not Amount object but just dict with Decimal
118
+
119
+ else:
120
+ self.amount = d.amount
121
+ self.symbol = d.symbol
122
+ self.asset = d.asset
123
+ self.precision = d.precision
124
+ self.amount = round(value_to_decimal(self.amount, self.precision) * 10**self.precision)
125
+ self.str_repr = str(d)
126
+ # self.str_repr = json.dumps((d.json()))
127
+ # self.str_repr = '{:.{}f} {}'.format((float(self.amount) / 10 ** self.precision), self.precision, self.asset)
128
+
129
+ def __bytes__(self) -> bytes:
130
+ # padding
131
+ # The nodes still serialize the legacy symbol name for HBD as 'SBD' and HIVE as 'STEEM' in wire format.
132
+ # To match get_transaction_hex and avoid digest mismatches, map 'HBD' -> 'SBD' and 'HIVE' -> 'STEEM' on serialization.
133
+ """
134
+ Serialize the Amount into its wire-format byte representation.
135
+
136
+ Returns:
137
+ bytes: 8-byte little-endian signed integer amount, followed by a 1-byte precision,
138
+ followed by a 7-byte ASCII symbol padded with null bytes. On serialization,
139
+ the symbol is remapped for legacy wire-format compatibility: "HBD" -> "SBD"
140
+ and "HIVE" -> "STEEM".
141
+ """
142
+ _sym = self.symbol
143
+ if _sym == "HBD":
144
+ _sym = "SBD"
145
+ elif _sym == "HIVE":
146
+ _sym = "STEEM"
147
+ symbol = str(_sym) + "\x00" * (7 - len(str(_sym)))
148
+ return (
149
+ struct.pack("<q", int(self.amount))
150
+ + struct.pack("<b", self.precision)
151
+ + bytes(symbol, "ascii")
152
+ )
153
+
154
+ def __str__(self) -> str:
155
+ if self.json_str:
156
+ return json.dumps(
157
+ {
158
+ "amount": str(self.amount),
159
+ "precision": self.precision,
160
+ "nai": self.asset,
161
+ }
162
+ )
163
+ return self.str_repr
164
+
165
+ def toJson(self):
166
+ try:
167
+ return json.loads(str(self))
168
+ except Exception:
169
+ return str(self)
170
+
171
+
172
+ class Operation(GPHOperation):
173
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
174
+ self.appbase = kwargs.pop("appbase", False)
175
+ self.prefix = kwargs.pop("prefix", default_prefix)
176
+ super().__init__(*args, **kwargs)
177
+
178
+ def _getklass(self, name: str) -> type:
179
+ module = __import__("nectarbase.operations", fromlist=["operations"])
180
+ class_ = getattr(module, name)
181
+ return class_
182
+
183
+ def operations(self) -> Dict[str, int]:
184
+ return operations
185
+
186
+ def getOperationNameForId(self, i: int) -> str:
187
+ """Convert an operation id into the corresponding string"""
188
+ for key in self.operations():
189
+ if int(self.operations()[key]) == int(i):
190
+ return key
191
+ return "Unknown Operation ID %d" % i
192
+
193
+ def json(self) -> Dict[str, Any]:
194
+ return json.loads(str(self))
195
+ # return json.loads(str(json.dumps([self.name, self.op.toJson()])))
196
+
197
+ def __bytes__(self) -> bytes:
198
+ if self.opId is not None:
199
+ return bytes(Id(self.opId)) + bytes(self.op)
200
+ return bytes(self.op)
201
+
202
+ def __str__(self) -> str:
203
+ if self.appbase:
204
+ op_data = self.op.toJson() if isinstance(self.op, GrapheneObject) else str(self.op)
205
+ return json.dumps({"type": self.name.lower() + "_operation", "value": op_data})
206
+ else:
207
+ op_data = self.op.toJson() if isinstance(self.op, GrapheneObject) else str(self.op)
208
+ return json.dumps([self.name.lower(), op_data])
209
+
210
+
211
+ class Memo(GrapheneObject):
212
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
213
+ if isArgsThisClass(self, args):
214
+ self.data = args[0].data
215
+ else:
216
+ prefix = kwargs.pop("prefix", default_prefix)
217
+ if "encrypted" not in kwargs or not kwargs["encrypted"]:
218
+ super().__init__(None)
219
+ else:
220
+ if len(args) == 1 and len(kwargs) == 0:
221
+ kwargs = args[0]
222
+ if "encrypted" in kwargs and kwargs["encrypted"]:
223
+ super().__init__(
224
+ OrderedDict(
225
+ [
226
+ ("from", PublicKey(kwargs["from"], prefix=prefix)),
227
+ ("to", PublicKey(kwargs["to"], prefix=prefix)),
228
+ ("nonce", Uint64(int(kwargs["nonce"]))),
229
+ ("check", Uint32(int(kwargs["check"]))),
230
+ ("encrypted", Bytes(kwargs["encrypted"])),
231
+ ]
232
+ )
233
+ )
234
+
235
+
236
+ class WitnessProps(GrapheneObject):
237
+ def __init__(self, *args, **kwargs):
238
+ if isArgsThisClass(self, args):
239
+ self.data = args[0].data
240
+ else:
241
+ if len(args) == 1 and len(kwargs) == 0:
242
+ kwargs = args[0]
243
+ prefix = kwargs.get("prefix", default_prefix)
244
+ json_str = kwargs.get("json_str", False)
245
+ if "sbd_interest_rate" in kwargs:
246
+ super().__init__(
247
+ OrderedDict(
248
+ [
249
+ (
250
+ "account_creation_fee",
251
+ Amount(
252
+ kwargs["account_creation_fee"],
253
+ prefix=prefix,
254
+ json_str=json_str,
255
+ ),
256
+ ),
257
+ (
258
+ "maximum_block_size",
259
+ Uint32(kwargs["maximum_block_size"]),
260
+ ),
261
+ ("sbd_interest_rate", Uint16(kwargs["sbd_interest_rate"])),
262
+ ]
263
+ )
264
+ )
265
+ elif "hbd_interest_rate" in kwargs:
266
+ super().__init__(
267
+ OrderedDict(
268
+ [
269
+ (
270
+ "account_creation_fee",
271
+ Amount(
272
+ kwargs["account_creation_fee"],
273
+ prefix=prefix,
274
+ json_str=json_str,
275
+ ),
276
+ ),
277
+ (
278
+ "maximum_block_size",
279
+ Uint32(kwargs["maximum_block_size"]),
280
+ ),
281
+ ("hbd_interest_rate", Uint16(kwargs["hbd_interest_rate"])),
282
+ ]
283
+ )
284
+ )
285
+ else:
286
+ super().__init__(
287
+ OrderedDict(
288
+ [
289
+ (
290
+ "account_creation_fee",
291
+ Amount(
292
+ kwargs["account_creation_fee"],
293
+ prefix=prefix,
294
+ json_str=json_str,
295
+ ),
296
+ ),
297
+ (
298
+ "maximum_block_size",
299
+ Uint32(kwargs["maximum_block_size"]),
300
+ ),
301
+ ]
302
+ )
303
+ )
304
+
305
+
306
+ class Price(GrapheneObject):
307
+ def __init__(self, *args, **kwargs):
308
+ if isArgsThisClass(self, args):
309
+ self.data = args[0].data
310
+ else:
311
+ if len(args) == 1 and len(kwargs) == 0:
312
+ kwargs = args[0]
313
+ prefix = kwargs.get("prefix", default_prefix)
314
+ super().__init__(
315
+ OrderedDict(
316
+ [
317
+ ("base", Amount(kwargs["base"], prefix=prefix)),
318
+ ("quote", Amount(kwargs["quote"], prefix=prefix)),
319
+ ]
320
+ )
321
+ )
322
+
323
+
324
+ class Permission(GrapheneObject):
325
+ def __init__(self, *args, **kwargs):
326
+ if isArgsThisClass(self, args):
327
+ self.data = args[0].data
328
+ else:
329
+ prefix = kwargs.pop("prefix", default_prefix)
330
+
331
+ if len(args) == 1 and len(kwargs) == 0:
332
+ kwargs = args[0]
333
+
334
+ # Sort keys (FIXME: ideally, the sorting is part of Public
335
+ # Key and not located here)
336
+ kwargs["key_auths"] = sorted(
337
+ kwargs["key_auths"],
338
+ key=lambda x: repr(PublicKey(x[0], prefix=prefix)),
339
+ reverse=False,
340
+ )
341
+ kwargs["account_auths"] = sorted(
342
+ kwargs["account_auths"],
343
+ key=lambda x: x[0],
344
+ reverse=False,
345
+ )
346
+ accountAuths = Map([(String(e[0]), Uint16(e[1])) for e in kwargs["account_auths"]])
347
+ keyAuths = Map(
348
+ [(PublicKey(e[0], prefix=prefix), Uint16(e[1])) for e in kwargs["key_auths"]]
349
+ )
350
+ super().__init__(
351
+ OrderedDict(
352
+ [
353
+ ("weight_threshold", Uint32(int(kwargs["weight_threshold"]))),
354
+ ("account_auths", accountAuths),
355
+ ("key_auths", keyAuths),
356
+ ]
357
+ )
358
+ )
359
+
360
+
361
+ class Extension(Array):
362
+ def __str__(self):
363
+ """We overload the __str__ function because the json
364
+ representation is different for extensions
365
+ """
366
+ return json.dumps(self.data if hasattr(self, "data") else [])
367
+
368
+
369
+ class ExchangeRate(GrapheneObject):
370
+ def __init__(self, *args, **kwargs):
371
+ if isArgsThisClass(self, args):
372
+ self.data = args[0].data
373
+ else:
374
+ if len(args) == 1 and len(kwargs) == 0:
375
+ kwargs = args[0]
376
+
377
+ prefix = kwargs.get("prefix", default_prefix)
378
+ json_str = kwargs.get("json_str", False)
379
+ super().__init__(
380
+ OrderedDict(
381
+ [
382
+ (
383
+ "base",
384
+ Amount(kwargs["base"], prefix=prefix, json_str=json_str),
385
+ ),
386
+ (
387
+ "quote",
388
+ Amount(kwargs["quote"], prefix=prefix, json_str=json_str),
389
+ ),
390
+ ]
391
+ )
392
+ )
393
+
394
+
395
+ class Beneficiary(GrapheneObject):
396
+ def __init__(self, *args, **kwargs):
397
+ if isArgsThisClass(self, args):
398
+ self.data = args[0].data
399
+ else:
400
+ if len(args) == 1 and len(kwargs) == 0:
401
+ kwargs = args[0]
402
+ super().__init__(
403
+ OrderedDict(
404
+ [
405
+ ("account", String(kwargs["account"])),
406
+ ("weight", Int16(kwargs["weight"])),
407
+ ]
408
+ )
409
+ )
410
+
411
+
412
+ class Beneficiaries(GrapheneObject):
413
+ def __init__(self, *args, **kwargs):
414
+ if isArgsThisClass(self, args):
415
+ self.data = args[0].data
416
+ else:
417
+ if len(args) == 1 and len(kwargs) == 0:
418
+ kwargs = args[0]
419
+
420
+ super().__init__(
421
+ OrderedDict(
422
+ [
423
+ (
424
+ "beneficiaries",
425
+ Array([Beneficiary(o) for o in kwargs["beneficiaries"]]),
426
+ ),
427
+ ]
428
+ )
429
+ )
430
+
431
+
432
+ class CommentOptionExtensions(Static_variant):
433
+ """Serialize Comment Payout Beneficiaries.
434
+
435
+ :param list beneficiaries: A static_variant containing beneficiaries.
436
+
437
+ Example::
438
+
439
+ [0,
440
+ {'beneficiaries': [
441
+ {'account': 'furion', 'weight': 10000}
442
+ ]}
443
+ ]
444
+
445
+ """
446
+
447
+ def __init__(self, o):
448
+ if isinstance(o, dict) and "type" in o and "value" in o:
449
+ if o["type"] == "comment_payout_beneficiaries":
450
+ type_id = 0
451
+ else:
452
+ type_id = ~0
453
+ data = o["value"]
454
+ else:
455
+ type_id, data = o
456
+ if type_id == 0:
457
+ data = Beneficiaries(data)
458
+ else:
459
+ raise Exception("Unknown CommentOptionExtension")
460
+ super().__init__(data, type_id)
461
+
462
+ def __str__(self):
463
+ if self.type_id == 0:
464
+ return json.dumps({"type": "comment_payout_beneficiaries", "value": self.data.json()})
465
+ return super().__str__()
466
+
467
+
468
+ class UpdateProposalEndDate(GrapheneObject):
469
+ def __init__(self, *args, **kwargs):
470
+ if isArgsThisClass(self, args):
471
+ self.data = args[0].data
472
+ else:
473
+ if len(args) == 1 and len(kwargs) == 0:
474
+ kwargs = args[0]
475
+
476
+ super().__init__(
477
+ OrderedDict(
478
+ [
479
+ ("end_date", PointInTime(kwargs["end_date"])),
480
+ ]
481
+ )
482
+ )
483
+
484
+
485
+ class UpdateProposalExtensions(Static_variant):
486
+ """Serialize Update proposal extensions.
487
+
488
+ :param end_date: A static_variant containing the new end_date.
489
+
490
+ Example::
491
+
492
+ {
493
+ 'type': '1',
494
+ 'value':
495
+ {
496
+ 'end_date': '2021-04-05T13:39:48'
497
+ }
498
+ }
499
+
500
+ """
501
+
502
+ def __init__(self, o):
503
+ if isinstance(o, dict) and "type" in o and "value" in o:
504
+ if o["type"] == "update_proposal_end_date":
505
+ type_id = 1
506
+ else:
507
+ type_id = ~0
508
+ data = o["value"]
509
+ else:
510
+ type_id, data = o
511
+
512
+ if type_id == 1:
513
+ data = UpdateProposalEndDate(data)
514
+ else:
515
+ raise Exception("Unknown UpdateProposalExtension")
516
+ super().__init__(data, type_id, False)
517
+
518
+ def __str__(self):
519
+ if self.type_id == 1:
520
+ return json.dumps({"type": "update_proposal_end_date", "value": self.data.json()})
521
+ return super().__str__()
@@ -0,0 +1,21 @@
1
+ #: Object types for object ids
2
+ object_type = {}
3
+ object_type["dynamic_global_property"] = 0
4
+ object_type["reserved0"] = 1
5
+ object_type["account"] = 2
6
+ object_type["witness"] = 3
7
+ object_type["transaction"] = 4
8
+ object_type["block_summary"] = 5
9
+ object_type["chain_property"] = 6
10
+ object_type["witness_schedule"] = 7
11
+ object_type["comment"] = 8
12
+ object_type["category"] = 9
13
+ object_type["comment_vote"] = 10
14
+ object_type["vote"] = 11
15
+ object_type["witness_vote"] = 12
16
+ object_type["limit_order"] = 13
17
+ object_type["feed_history"] = 14
18
+ object_type["convert_request"] = 15
19
+ object_type["liquidity_reward_balance"] = 16
20
+ object_type["operation"] = 17
21
+ object_type["account_history"] = 18
@@ -0,0 +1,102 @@
1
+ #: Operation ids
2
+ from typing import Dict, List
3
+
4
+ # https://gitlab.syncad.com/hive/hive/-/blob/master/libraries/protocol/include/hive/protocol/operations.hpp
5
+ ops: List[str] = [
6
+ "vote", # 0
7
+ "comment", # 1
8
+ "transfer", # 2
9
+ "transfer_to_vesting", # 3
10
+ "withdraw_vesting", # 4
11
+ "limit_order_create", # 5
12
+ "limit_order_cancel", # 6
13
+ "feed_publish", # 7
14
+ "convert", # 8
15
+ "account_create", # 9
16
+ "account_update", # 10
17
+ "witness_update", # 11
18
+ "account_witness_vote", # 12
19
+ "account_witness_proxy", # 13
20
+ "pow", # 14
21
+ "custom", # 15
22
+ "report_over_production", # 16
23
+ "delete_comment", # 17
24
+ "custom_json", # 18
25
+ "comment_options", # 19
26
+ "set_withdraw_vesting_route", # 20
27
+ "limit_order_create2", # 21
28
+ "claim_account", # 22
29
+ "create_claimed_account", # 23
30
+ "request_account_recovery", # 24
31
+ "recover_account", # 25
32
+ "change_recovery_account", # 26
33
+ "escrow_transfer", # 27
34
+ "escrow_dispute", # 28
35
+ "escrow_release", # 29
36
+ "pow2", # 30
37
+ "escrow_approve", # 31
38
+ "transfer_to_savings", # 32
39
+ "transfer_from_savings", # 33
40
+ "cancel_transfer_from_savings", # 34
41
+ "custom_binary", # 35
42
+ "decline_voting_rights", # 36
43
+ "reset_account", # 37
44
+ "set_reset_account", # 38
45
+ "claim_reward_balance", # 39
46
+ "delegate_vesting_shares", # 40
47
+ "account_create_with_delegation", # 41
48
+ "witness_set_properties", # 42
49
+ "account_update2", # 43
50
+ "create_proposal", # 44
51
+ "update_proposal_votes", # 45
52
+ "remove_proposal", # 46
53
+ "update_proposal", # 47
54
+ "collateralized_convert", # 48
55
+ "recurrent_transfer", # 49
56
+ # virtual operations below this point
57
+ "fill_convert_request", # last_regular + 1
58
+ "author_reward", # last_regular + 2
59
+ "curation_reward", # last_regular + 3
60
+ "comment_reward", # last_regular + 4
61
+ "liquidity_reward", # last_regular + 5
62
+ "interest", # last_regular + 6
63
+ "fill_vesting_withdraw", # last_regular + 7
64
+ "fill_order", # last_regular + 8
65
+ "shutdown_witness", # last_regular + 9
66
+ "fill_transfer_from_savings", # last_regular + 10
67
+ "hardfork", # last_regular + 11
68
+ "comment_payout_update", # last_regular + 12
69
+ "return_vesting_delegation", # last_regular + 13
70
+ "comment_benefactor_reward", # last_regular + 14
71
+ "producer_reward", # last_regular + 15
72
+ "clear_null_account_balance", # last_regular + 16
73
+ "proposal_pay", # last_regular + 17
74
+ "sps_fund", # last_regular + 18
75
+ "hardfork_hive", # last_regular + 19
76
+ "hardfork_hive_restore", # last_regular + 20
77
+ "delayed_voting", # last_regular + 21
78
+ "consolidate_treasury_balance", # last_regular + 22
79
+ "effective_comment_vote", # last_regular + 23
80
+ "ineffective_delete_comment", # last_regular + 24
81
+ "sps_convert", # last_regular + 25
82
+ "expired_account_notification", # last_regular + 26
83
+ "changed_recovery_account", # last_regular + 27
84
+ "transfer_to_vesting_completed", # last_regular + 28
85
+ "pow_reward", # last_regular + 29
86
+ "vesting_shares_split", # last_regular + 30
87
+ "account_created", # last_regular + 31
88
+ "fill_collateralized_convert_request", # last_regular + 32
89
+ "system_warning", # last_regular + 33,
90
+ "fill_recurrent_transfer", # last_regular + 34
91
+ "failed_recurrent_transfer", # last_regular + 35
92
+ ]
93
+
94
+ operations: Dict[str, int] = {o: ops.index(o) for o in ops}
95
+
96
+
97
+ def getOperationNameForId(i: int) -> str:
98
+ """Convert an operation id into the corresponding string"""
99
+ for key in operations:
100
+ if operations[key] == i:
101
+ return key
102
+ return "Unknown Operation ID %d" % i