|
| 1 | +import binascii |
| 2 | +import math |
| 3 | +from abc import ABC |
| 4 | + |
| 5 | +import base58 |
| 6 | +from Crypto.Hash import keccak |
| 7 | + |
| 8 | +from tronapi.constants import DEFAULT_TRON_NODE, DEFAULT_SOLIDITY_NODE |
| 9 | +from tronapi.provider import HttpProvider |
| 10 | + |
| 11 | + |
| 12 | +class TronBase(ABC): |
| 13 | + def __init__(self, full_node, solidity_node=None, event_server=None, private_key=None): |
| 14 | + """A Python API for interacting with the Tron (TRX) |
| 15 | +
|
| 16 | + Args: |
| 17 | + full_node (:obj:`str`): A provider connected to a valid full node |
| 18 | + solidity_node (:obj:`str`): A provider connected to a valid solidity node |
| 19 | + event_server (:obj:`str`, optional): Optional for smart contract events. Expects a valid event server URL |
| 20 | + private_key (str): Optional default private key used when signing transactions |
| 21 | +
|
| 22 | + """ |
| 23 | + |
| 24 | + if not solidity_node: |
| 25 | + solidity_node = DEFAULT_SOLIDITY_NODE |
| 26 | + |
| 27 | + if isinstance(full_node, str): |
| 28 | + full_node = HttpProvider(full_node) |
| 29 | + |
| 30 | + if isinstance(solidity_node, str): |
| 31 | + solidity_node = HttpProvider(solidity_node) |
| 32 | + |
| 33 | + if isinstance(event_server, str): |
| 34 | + event_server = HttpProvider(event_server) |
| 35 | + |
| 36 | + self.__set_full_node(full_node) |
| 37 | + self.__set_solidity_node(solidity_node) |
| 38 | + self.__set_event_server(event_server) |
| 39 | + |
| 40 | + self.tron_node = HttpProvider(DEFAULT_TRON_NODE) |
| 41 | + |
| 42 | + if private_key: |
| 43 | + self.private_key = private_key |
| 44 | + |
| 45 | + def __set_full_node(self, provider): |
| 46 | + """Check specified "full node" |
| 47 | +
|
| 48 | + Args: |
| 49 | + provider (HttpProvider): full node |
| 50 | +
|
| 51 | + """ |
| 52 | + if not self.is_valid_provider(provider): |
| 53 | + raise Exception('Invalid full node provided') |
| 54 | + |
| 55 | + self.full_node = provider |
| 56 | + self.full_node.status_page = '/wallet/getnowblock' |
| 57 | + |
| 58 | + def __set_solidity_node(self, provider): |
| 59 | + """Check specified "solidity node" |
| 60 | +
|
| 61 | + Args: |
| 62 | + provider (HttpProvider): solidity node |
| 63 | +
|
| 64 | + """ |
| 65 | + if not self.is_valid_provider(provider): |
| 66 | + raise Exception('Invalid solidity node provided') |
| 67 | + |
| 68 | + self.solidity_node = provider |
| 69 | + self.solidity_node.status_page = '/walletsolidity/getnowblock' |
| 70 | + |
| 71 | + def __set_event_server(self, server): |
| 72 | + """Check specified "event server" |
| 73 | +
|
| 74 | + Args: |
| 75 | + server (HttpProvider): event server |
| 76 | +
|
| 77 | + """ |
| 78 | + if server and not self.is_valid_provider(server): |
| 79 | + raise Exception('Invalid event provided') |
| 80 | + |
| 81 | + self.event_server = server |
| 82 | + |
| 83 | + def is_event_connected(self): |
| 84 | + """ |
| 85 | + Checks if is connected to the event server. |
| 86 | +
|
| 87 | + Returns: |
| 88 | + bool: True if successful, False otherwise. |
| 89 | +
|
| 90 | + """ |
| 91 | + if not self.event_server: |
| 92 | + return False |
| 93 | + |
| 94 | + return self.event_server.request('/healthcheck') == 'OK' |
| 95 | + |
| 96 | + @staticmethod |
| 97 | + def is_valid_provider(provider): |
| 98 | + """Check connected provider |
| 99 | +
|
| 100 | + Args: |
| 101 | + provider(HttpProvider): Provider |
| 102 | +
|
| 103 | + Returns: |
| 104 | + True if successful, False otherwise. |
| 105 | +
|
| 106 | + """ |
| 107 | + return isinstance(provider, HttpProvider) |
| 108 | + |
| 109 | + @staticmethod |
| 110 | + def to_ascii(s): |
| 111 | + return binascii.a2b_hex(s) |
| 112 | + |
| 113 | + @staticmethod |
| 114 | + def from_ascii(string): |
| 115 | + return binascii.b2a_hex(bytes(string, encoding="utf8")) |
| 116 | + |
| 117 | + @staticmethod |
| 118 | + def to_utf8(hex_string): |
| 119 | + return binascii.unhexlify(hex_string).decode('utf8') |
| 120 | + |
| 121 | + @staticmethod |
| 122 | + def from_utf8(string): |
| 123 | + return binascii.hexlify(bytes(string, encoding="utf8")) |
| 124 | + |
| 125 | + @staticmethod |
| 126 | + def from_decimal(value): |
| 127 | + return hex(value) |
| 128 | + |
| 129 | + @staticmethod |
| 130 | + def to_decimal(value): |
| 131 | + return int((str(value)), 10) |
| 132 | + |
| 133 | + @staticmethod |
| 134 | + def string_utf8_to_hex(name): |
| 135 | + """Convert a string to Hex format |
| 136 | +
|
| 137 | + Args: |
| 138 | + name (str): string |
| 139 | +
|
| 140 | + """ |
| 141 | + return bytes(name, encoding='utf-8').hex() |
| 142 | + |
| 143 | + @staticmethod |
| 144 | + def to_tron(amount): |
| 145 | + """Convert float to trx format |
| 146 | +
|
| 147 | + Args: |
| 148 | + amount (float): Value |
| 149 | +
|
| 150 | + """ |
| 151 | + return math.floor(amount * 1e6) |
| 152 | + |
| 153 | + @staticmethod |
| 154 | + def from_tron(amount): |
| 155 | + """Convert trx to float |
| 156 | +
|
| 157 | + Args: |
| 158 | + amount (int): Value |
| 159 | +
|
| 160 | + """ |
| 161 | + return abs(amount) / 1e6 |
| 162 | + |
| 163 | + @staticmethod |
| 164 | + def to_hex(address): |
| 165 | + """Helper function that will convert a generic value to hex |
| 166 | +
|
| 167 | + Args: |
| 168 | + address (str): address |
| 169 | +
|
| 170 | + """ |
| 171 | + return base58.b58decode_check(address).hex().upper() |
| 172 | + |
| 173 | + @staticmethod |
| 174 | + def from_hex(address): |
| 175 | + """Helper function that will convert a generic value from hex |
| 176 | +
|
| 177 | + Args: |
| 178 | + address (str): address |
| 179 | +
|
| 180 | + """ |
| 181 | + return base58.b58encode_check(bytes.fromhex(address)) |
| 182 | + |
| 183 | + @staticmethod |
| 184 | + def sha3(string, prefix=False): |
| 185 | + """Helper function that will sha3 any value using keccak256 |
| 186 | +
|
| 187 | + Args: |
| 188 | + string (str): String to hash. |
| 189 | + prefix (bool): If true, adds '0x' |
| 190 | +
|
| 191 | + """ |
| 192 | + keccak_hash = keccak.new(digest_bits=256) |
| 193 | + keccak_hash.update(bytes(string, encoding='utf8')) |
| 194 | + |
| 195 | + if prefix: |
| 196 | + return '0x' + keccak_hash.hexdigest() |
| 197 | + |
| 198 | + return keccak_hash.hexdigest() |
| 199 | + |
| 200 | + def is_connected(self): |
| 201 | + """Check all connected nodes""" |
| 202 | + |
| 203 | + return { |
| 204 | + 'full_node': self.full_node.is_connected(), |
| 205 | + 'solidity_node': self.solidity_node.is_connected(), |
| 206 | + 'event_server': self.is_event_connected() |
| 207 | + } |
0 commit comments