diff --git a/defichain/transactions/address/address.py b/defichain/transactions/address/address.py index 2a027256..7b490bde 100644 --- a/defichain/transactions/address/address.py +++ b/defichain/transactions/address/address.py @@ -11,6 +11,7 @@ from .p2pkh import P2PKH from .p2sh import P2SH from .p2wpkh import P2WPKH +from .erc55 import ERC55 class Address: @@ -53,10 +54,17 @@ def get_addressType(address: str) -> (Network, str): for network in [DefichainMainnet, DefichainTestnet]: if prefix == network.SEGWIT_ADDRESS.HRP: return network, AddressTypes.P2WPKH + + # ERC55 + try: + if ERC55.verify(address): + return None, AddressTypes.ERC55 + except: + pass raise AddressError("This address ist not supported") @staticmethod - def from_address(address: str) -> "BaseAddress": + def from_address(address: str) -> "P2PKH | P2SH | P2WPKH | ERC55": """ Creates the matching address object for the given address @@ -71,6 +79,8 @@ def from_address(address: str) -> "BaseAddress": return P2SH(network, address) elif addressType == AddressTypes.P2WPKH: # Native Segwit return P2WPKH(network, address) + elif addressType == AddressTypes.ERC55: # ERC55 + return ERC55(address) else: raise AddressError("This address ist not supported") @@ -98,6 +108,12 @@ def from_scriptPublicKey(network: Any, scriptPublicKey: str) -> "BaseAddress": except: pass + # ERC55 + try: + return Address.from_address(ERC55.from_scriptPublicKey(scriptPublicKey).get_address()) + except: + pass + raise AddressError("This script public key is not supported. Could be a multi signature transaction, witch is " "currently not supported") diff --git a/defichain/transactions/address/erc55.py b/defichain/transactions/address/erc55.py new file mode 100644 index 00000000..4f66cd5a --- /dev/null +++ b/defichain/transactions/address/erc55.py @@ -0,0 +1,54 @@ +from typing import Any + +from web3 import Web3 +from eth_keys import keys + +from .baseaddress import BaseAddress +from .script import Script +from defichain.transactions.utils import Converter +from defichain.transactions.constants import AddressTypes, OPCodes + + +class ERC55: + @staticmethod + def from_publicKey(publicKey: str) -> "ERC55": + address = keys.PublicKey(Converter.hex_to_bytes(publicKey)).to_address() + return ERC55(address) + + @staticmethod + def from_privateKey(privateKey: str) -> "ERC55": + address = keys.PrivateKey(Converter.hex_to_bytes(privateKey)).to_address() + return ERC55(address) + + @staticmethod + def from_scriptPublicKey(scriptPublicKey: str) -> "ERC55": + address = "0x" + bytes(reversed(bytes().fromhex(scriptPublicKey[4:]))).hex() + return ERC55(address) + + @staticmethod + def verify(address: str) -> bool: + return Web3.is_address(address) + + def __init__(self, address: str): + self._address = None + self.set_address(address) + + def get_addressType(self) -> str: + return AddressTypes.ERC55 + + def get_address(self) -> str: + return self._address + + def get_scriptPublicKey(self) -> str: + return Script.build_script([OPCodes.OP_16, bytes(reversed(bytes().fromhex(self.get_address()[2:]))).hex()]) + + def get_bytes_scriptPublicKey(self) -> bytes: + return bytes.fromhex(self.get_scriptPublicKey()) + + + def set_address(self, address: str) -> None: + self._address = address + + def set_scriptPublicKey(self, scriptPublicKey: str) -> None: + self._address = "0x" + bytes(reversed(bytes().fromhex(scriptPublicKey[4:]))).hex() + diff --git a/defichain/transactions/constants/address.py b/defichain/transactions/constants/address.py index 27bccb3b..193c22c4 100644 --- a/defichain/transactions/constants/address.py +++ b/defichain/transactions/constants/address.py @@ -10,6 +10,7 @@ class AddressTypes: P2PKH: str = "P2PKH" P2SH: str = "P2SH" P2WPKH: str = "P2WPKH" + ERC55: str = "ERC55" # Max Script Length