# Path: bts_tools/base58.py
# def ripemd160(s):
#     ripemd160 = hashlib.new('ripemd160')
#     ripemd160.update(unhexlify(s))
#     return ripemd160.digest()
# 
# class Base58(object) :
#     """Base58 base class
#     This class serves as an abstraction layer to deal with base58 encoded
#     strings and their corresponding hex and binary representation throughout the
#     library.
#     :param data: Data to initialize object, e.g. pubkey data, address data, ...
#     :type data: hex, wif, bip38 encrypted wif, base58 string
#     :param str prefix: Prefix to use for Address/PubKey strings (defaults to ``BTS``)
#     :return: Base58 object initialized with ``data``
#     :rtype: Base58
#     :raises ValueError: if data cannot be decoded
#     * ``bytes(Base58)``: Returns the raw data
#     * ``str(Base58)``:   Returns the readable ``Base58CheckEncoded`` data.
#     * ``repr(Base58)``:  Gives the hex representation of the data.
#     *  ``format(Base58,_format)`` Formats the instance according to ``_format``:
#         * ``"btc"``: prefixed with ``0x80``. Yields a valid btc address
#         * ``"wif"``: prefixed with ``0x00``. Yields a valid wif key
#         * ``"bts"``: prefixed with ``BTS``
#         * ``"muse"``: prefixed with ``MUSE``
#     """
#     def __init__(self, data, prefix=PREFIX) :
#         self._prefix = prefix
#         if all(c in string.hexdigits for c in data) :
#             self._hex     = data
#         elif data[0] == "5" or data[0] == "6" :
#             self._hex     = base58CheckDecode(data)
#         elif data[:len(self._prefix)] == self._prefix :
#             self._hex     = btsBase58CheckDecode(data[len(self._prefix):])
#         else :
#             raise ValueError("Error loading Base58 object")
# 
#     def __format__(self, _format) :
#         """ Format output according to argument _format (wif,btc,bts)
#             :param str _format: Format to use
#             :return: formatted data according to _format
#             :rtype: str
#         """
#         if _format.lower() == "wif" :
#             return base58CheckEncode(0x80, self._hex)
#         elif _format.lower() == "encwif" :
#             return base58encode(self._hex)
#         elif _format.lower() == "btc":
#             return base58CheckEncode(0x00, self._hex)
#         elif _format.lower() == "bts" :
#             return _format.upper() + str(self)
#         elif _format.lower() == "bts-testnet" :
#             return 'TEST' + str(self)
#         elif _format.lower() == "muse" :
#             return _format.upper() + str(self)
#         elif _format.lower() == "steem":
#             return 'STM' + str(self)
#         elif _format.lower() == "test" :
#             return _format.upper() + str(self)
#         elif _format.lower() == "gph" :
#             return _format.upper() + str(self)
#         elif _format.lower() == "ppy":
#             return _format.upper() + str(self)
#         elif _format.lower() == "ppy-testnet":
#             return 'PPYTEST' + str(self)
#         else :
#             sys.stderr.write("Format %s unkown. You've been warned!\n" % _format)
#             return _format.upper() + str(self)
# 
#     def __repr__(self) :
#         """ Returns hex value of object
#             :return: Hex string of instance's data
#             :rtype: hex string
#         """
#         return self._hex
# 
#     def __str__(self) :
#         """ Return BTS-base58CheckEncoded string of data
#             :return: Base58 encoded data
#             :rtype: str
#         """
#         return btsBase58CheckEncode(self._hex)
# 
#     def __bytes__(self) :
#         """ Return raw bytes
#             :return: Raw bytes of instance
#             :rtype: bytes
#         """
#         return unhexlify(self._hex)


import ecdsa
import hashlib
import sys
import re
import os
            import os
from binascii import hexlify, unhexlify
from .base58 import ripemd160, Base58

""" This class and the methods require python3 """
assert sys.version_info[0] == 3, "graphenelib requires python3"


class Address(object):
    """ Address class
        This class serves as an address representation for Public Keys.
        :param str address: Base58 encoded address (defaults to ``None``)
        :param str pubkey: Base58 encoded pubkey (defaults to ``None``)
        :param str prefix: Network prefix (defaults to ``BTS``)
        Example::
           Address("BTSFN9r6VYzBK8EKtMewfNbfiGCr56pHDBFi")
    """
    def __init__(self, address=None, pubkey=None, prefix="BTS"):
        self.prefix = prefix
        if pubkey is not None :
            self._pubkey  = Base58(pubkey, prefix=prefix)
            self._address = None
        elif address is not None :
            self._pubkey  = None
            self._address = Base58(address, prefix=prefix)
        else :
            raise Exception("Address has to be initialized by either the " +
                            "pubkey or the address.")

    def derivesha256address(self):
        """ Derive address using ``RIPEMD160(SHA256(x))`` """
        pkbin         = unhexlify(repr(self._pubkey))
        addressbin    = ripemd160(hexlify(hashlib.sha256(pkbin).digest()))

# Path: bts_tools/base58.py
# def ripemd160(s):
#     ripemd160 = hashlib.new('ripemd160')
#     ripemd160.update(unhexlify(s))
#     return ripemd160.digest()
# 
# class Base58(object) :
#     """Base58 base class
#     This class serves as an abstraction layer to deal with base58 encoded
#     strings and their corresponding hex and binary representation throughout the
#     library.
#     :param data: Data to initialize object, e.g. pubkey data, address data, ...
#     :type data: hex, wif, bip38 encrypted wif, base58 string
#     :param str prefix: Prefix to use for Address/PubKey strings (defaults to ``BTS``)
#     :return: Base58 object initialized with ``data``
#     :rtype: Base58
#     :raises ValueError: if data cannot be decoded
#     * ``bytes(Base58)``: Returns the raw data
#     * ``str(Base58)``:   Returns the readable ``Base58CheckEncoded`` data.
#     * ``repr(Base58)``:  Gives the hex representation of the data.
#     *  ``format(Base58,_format)`` Formats the instance according to ``_format``:
#         * ``"btc"``: prefixed with ``0x80``. Yields a valid btc address
#         * ``"wif"``: prefixed with ``0x00``. Yields a valid wif key
#         * ``"bts"``: prefixed with ``BTS``
#         * ``"muse"``: prefixed with ``MUSE``
#     """
#     def __init__(self, data, prefix=PREFIX) :
#         self._prefix = prefix
#         if all(c in string.hexdigits for c in data) :
#             self._hex     = data
#         elif data[0] == "5" or data[0] == "6" :
#             self._hex     = base58CheckDecode(data)
#         elif data[:len(self._prefix)] == self._prefix :
#             self._hex     = btsBase58CheckDecode(data[len(self._prefix):])
#         else :
#             raise ValueError("Error loading Base58 object")
# 
#     def __format__(self, _format) :
#         """ Format output according to argument _format (wif,btc,bts)
#             :param str _format: Format to use
#             :return: formatted data according to _format
#             :rtype: str
#         """
#         if _format.lower() == "wif" :
#             return base58CheckEncode(0x80, self._hex)
#         elif _format.lower() == "encwif" :
#             return base58encode(self._hex)
#         elif _format.lower() == "btc":
#             return base58CheckEncode(0x00, self._hex)
#         elif _format.lower() == "bts" :
#             return _format.upper() + str(self)
#         elif _format.lower() == "bts-testnet" :
#             return 'TEST' + str(self)
#         elif _format.lower() == "muse" :
#             return _format.upper() + str(self)
#         elif _format.lower() == "steem":
#             return 'STM' + str(self)
#         elif _format.lower() == "test" :
#             return _format.upper() + str(self)
#         elif _format.lower() == "gph" :
#             return _format.upper() + str(self)
#         elif _format.lower() == "ppy":
#             return _format.upper() + str(self)
#         elif _format.lower() == "ppy-testnet":
#             return 'PPYTEST' + str(self)
#         else :
#             sys.stderr.write("Format %s unkown. You've been warned!\n" % _format)
#             return _format.upper() + str(self)
# 
#     def __repr__(self) :
#         """ Returns hex value of object
#             :return: Hex string of instance's data
#             :rtype: hex string
#         """
#         return self._hex
# 
#     def __str__(self) :
#         """ Return BTS-base58CheckEncoded string of data
#             :return: Base58 encoded data
#             :rtype: str
#         """
#         return btsBase58CheckEncode(self._hex)
# 
#     def __bytes__(self) :
#         """ Return raw bytes
#             :return: Raw bytes of instance
#             :rtype: bytes
#         """
#         return unhexlify(self._hex)


# Path: bts_tools/privatekey.py
import ecdsa
import hashlib
import sys
import re
import os
            import os
from binascii import hexlify, unhexlify
from .base58 import ripemd160, Base58


""" This class and the methods require python3 """
assert sys.version_info[0] == 3, "graphenelib requires python3"


class Address(object):
    """ Address class
        This class serves as an address representation for Public Keys.
        :param str address: Base58 encoded address (defaults to ``None``)
        :param str pubkey: Base58 encoded pubkey (defaults to ``None``)
        :param str prefix: Network prefix (defaults to ``BTS``)
        Example::
           Address("BTSFN9r6VYzBK8EKtMewfNbfiGCr56pHDBFi")
    """
    def __init__(self, address=None, pubkey=None, prefix="BTS"):
        self.prefix = prefix
        if pubkey is not None :
            self._pubkey  = Base58(pubkey, prefix=prefix)
            self._address = None
        elif address is not None :
            self._pubkey  = None
            self._address = Base58(address, prefix=prefix)
        else :
            raise Exception("Address has to be initialized by either the " +
                            "pubkey or the address.")

    def derivesha256address(self):
        """ Derive address using ``RIPEMD160(SHA256(x))`` """
        pkbin         = unhexlify(repr(self._pubkey))
        addressbin    = ripemd160(hexlify(hashlib.sha256(pkbin).digest()))

        return Base58(hexlify(addressbin).decode('ascii'))