def validate_address(value):
    """
    Helper function for validating an address
    """
    if not isinstance(value, str):
        raise TypeError(
            'Address {} must be provided as a string'.format(value))
    if not is_hex_address(value):
        raise InvalidAddress(
            "Address must be 20 bytes, as a hex string with a 0x prefix",
            value)
    if not is_checksum_address(value):
        if value == value.lower():
            raise InvalidAddress(
                "Web3.py only accepts checksum addresses. "
                "The software that gave you this non-checksum address should be considered unsafe, "
                "please file it as a bug on their platform. "
                "Try using an ENS name instead. Or, if you must accept lower safety, "
                "use Web3.toChecksumAddress(lower_case_address).",
                value,
            )
        else:
            raise InvalidAddress(
                "Address has an invalid EIP-55 checksum. "
                "After looking up the address from the original source, try again.",
                value,
            )
 def _validate_set_ens(self) -> None:
     if not self.web3:
         raise InvalidAddress(
             "Could not look up ENS address because no web3 "
             "connection available")
     elif not self.web3.ens:
         raise InvalidAddress(
             "Could not look up ENS address because web3.ens is "
             "set to None")
Example #3
0
def abi_ens_resolver(w3, abi_type, val):
    if abi_type == 'address' and is_ens_name(val):
        if w3 is None:
            raise InvalidAddress("Could not look up name, because no web3 connection available")
        elif w3.ens is None:
            raise InvalidAddress("Could not look up name, because ENS is set to None")
        else:
            return (abi_type, validate_name_has_address(w3.ens, val))
    else:
        return (abi_type, val)
Example #4
0
def validate_address(value):
    """
    Helper function for validating an address
    """
    if not isinstance(value, str):
        raise TypeError(
            'Address {} must be provided as a string'.format(value))
    if not is_hex_address(value):
        raise InvalidAddress(
            "Address must be 20 bytes, as a hex string with a 0x prefix",
            value)
    if not is_checksum_address(value):
        raise InvalidAddress("Address has an invalid EIP checksum", value)
Example #5
0
def abi_ens_resolver(w3, type_str, val):
    if type_str == 'address' and is_ens_name(val):
        if w3 is None:
            raise InvalidAddress("Could not look up name %r because no web3"
                                 " connection available" % (val))
        elif w3.ens is None:
            raise InvalidAddress("Could not look up name %r because ENS is"
                                 " set to None" % (val))
        elif int(w3.net.version) != 1 and not isinstance(w3.ens, StaticENS):
            raise InvalidAddress("Could not look up name %r because web3 is"
                                 " not connected to mainnet" % (val))
        else:
            return type_str, validate_name_has_address(w3.ens, val)
    else:
        return type_str, val
def __to_checksum_address(address, web3):
    if eth_utils.address.is_address(address):
        if eth_utils.address.is_checksum_address(address):
            return address
        else:
            return eth_utils.address.to_checksum_address(address)
    elif is_ens_name(address):
        return __resolve_ens_name_to_address(address, web3=web3)
    else:
        raise InvalidAddress("%a is not valid address or ENS name" % address)
Example #7
0
def abi_ens_resolver(w3: "Web3", type_str: TypeStr,
                     val: Any) -> Tuple[TypeStr, Any]:
    if type_str == 'address' and is_ens_name(val):
        if w3 is None:
            raise InvalidAddress(
                f"Could not look up name {val!r} because no web3"
                " connection available")
        elif w3.ens is None:
            raise InvalidAddress(
                f"Could not look up name {val!r} because ENS is"
                " set to None")
        elif int(w3.net.version) != 1 and not isinstance(w3.ens, StaticENS):
            raise InvalidAddress(
                f"Could not look up name {val!r} because web3 is"
                " not connected to mainnet")
        else:
            return type_str, validate_name_has_address(w3.ens, val)
    else:
        return type_str, val
Example #8
0
def validate_address(value):
    """
    Helper function for validating an address
    """
    if not isinstance(value, str):
        raise TypeError('Address {} must be provided as a string'.format(value))
    if not is_hex_address(value):
        raise InvalidAddress("Address must be 20 bytes, as a hex string with a 0x prefix", value)
    if not is_checksum_address(value):
        # Shamelessly ignore EIP checksum validation
        # https://github.com/ethereum/web3.py/issues/674
        # raise InvalidAddress("Address has an invalid EIP checksum", value)
        pass
Example #9
0
def __to_checksum_address(address, web3):
    if eth_utils.address.is_address(address):
        if eth_utils.address.is_checksum_address(address):
            return address
        else:
            return eth_utils.address.to_checksum_address(address)
    elif (re.match("^4[a-zA-Z0-9]+$", address) is not None) and (len(address)
                                                                 == 48):
        return address
    elif is_ens_name(address):
        return __resolve_ens_name_to_address(address, web3=web3)
    else:
        raise InvalidAddress("%a is not valid address or ENS name" % address)
Example #10
0
    def send_transaction(
        configuration,
        keystore_password,
        to_address,
        value,
        token_symbol=None,
        gas_price_speed=20  # MetaMask default transaction speedup is gasPrice*10
    ):
        """
        Sign and send transaction
        :param configuration: loaded configuration file instance
        :param keystore_password: password from encrypted keystore with private key for transaction sign
        :param to_address: address in hex string where originator's funds will be sent
        :param value: amount of funds to send in ETH or token defined in token_symbol
        :param token_symbol: None for ETH, ERC20 symbol for other tokens transaction
        :param gas_price_speed: gas price will be multiplied with this number to speed up transaction
        :return: tuple of transaction hash and transaction cost
        """
        # my MetaMask address: 0xAAD533eb7Fe7F2657960AC7703F87E10c73ae73b
        wallet = Wallet(configuration).load_keystore(keystore_password)
        w3 = Infura().get_web3()
        transaction = Transaction(account=wallet.get_account(), w3=w3)

        # check if value to send is possible to convert to the number
        try:
            float(value)
        except ValueError:
            raise InvalidValueException()

        if token_symbol is None:  # create ETH transaction dictionary
            tx_dict = transaction.build_transaction(
                to_address=to_address,
                value=Web3.toWei(value, "ether"),
                gas=
                21000,  # fixed gasLimit to transfer ether from one EOA to another EOA (doesn't include contracts)
                gas_price=w3.eth.gasPrice * gas_price_speed,
                # be careful about sending more transactions in row, nonce will be duplicated
                nonce=w3.eth.getTransactionCount(wallet.get_address()),
                chain_id=configuration.network)
        else:  # create ERC20 contract transaction dictionary
            try:  # check if token is added to the wallet
                contract_address = configuration.contracts[token_symbol]
            except KeyError:
                raise ERC20NotExistsException()
            contract = Contract(configuration, contract_address)
            erc20_decimals = contract.get_decimals()
            token_amount = int(float(value) * (10**erc20_decimals))
            data_for_contract = Transaction.get_tx_erc20_data_field(
                to_address, token_amount)

            # check whether there is sufficient ERC20 token balance
            erc20_balance, _ = WalletAPI.get_balance(configuration,
                                                     token_symbol)
            if float(value) > erc20_balance:
                raise InsufficientERC20FundsException()

            # calculate how much gas I need, unused gas is returned to the wallet
            estimated_gas = w3.eth.estimateGas({
                'to': contract_address,
                'from': wallet.get_address(),
                'data': data_for_contract
            })

            tx_dict = transaction.build_transaction(
                to_address=
                contract_address,  # receiver address is defined in data field for this contract
                value=
                0,  # amount of tokens to send is defined in data field for contract
                gas=estimated_gas,
                gas_price=w3.eth.gasPrice * gas_price_speed,
                # be careful about sending more transactions in row, nonce will be duplicated
                nonce=w3.eth.getTransactionCount(wallet.get_address()),
                chain_id=configuration.network,
                data=data_for_contract)

        # check whether to address is valid checksum address
        if not Web3.isChecksumAddress(to_address):
            raise InvalidAddress()

        # check whether there is sufficient eth balance for this transaction
        balance, _ = WalletAPI.get_balance(configuration)
        transaction_const_wei = tx_dict['gas'] * tx_dict['gasPrice']
        transaction_const_eth = w3.fromWei(transaction_const_wei, 'ether')
        if token_symbol is None:
            if (transaction_const_eth + Decimal(value)) > balance:
                raise InsufficientFundsException()
        else:
            if transaction_const_eth > balance:
                raise InsufficientFundsException()

        # send transaction
        tx_hash = transaction.send_transaction(tx_dict)

        print('Pending', end='', flush=True)
        while True:
            tx_receipt = w3.eth.getTransactionReceipt(tx_hash)
            if tx_receipt is None:
                print('.', end='', flush=True)
                time.sleep(1)
            else:
                print('\nTransaction mined!')
                break

        return tx_hash, transaction_const_eth