# Buggy code
def block_until_ready(self, poll_rate: int = None, timeout: int = None):
    """
    Polls the staking_agent and blocks until the staking address is not
    a null address for the given worker_address. Once the worker is bonded, it returns the staker address.
    """
    if not self.__worker_address:
        raise RuntimeError("No worker address available")

    timeout = timeout or self.BONDING_TIMEOUT
    poll_rate = poll_rate or self.BONDING_POLL_RATE
    staking_agent = ContractAgency.get_agent(StakingEscrowAgent, registry=self.registry)
    client = staking_agent.blockchain.client
    start = maya.now()

    emitter = StdoutEmitter()  # TODO: Make injectable, or embed this logic into Ursula
    emitter.message("Waiting for bonding and funding...")

    funded, bonded = False, False
    while True:
        # Read
        staking_address = staking_agent.get_staker_from_worker(self.__worker_address)
        ether_balance = client.get_balance(self.__worker_address)

        # Bonding
        if (not bonded) and (staking_address != BlockchainInterface.NULL_ADDRESS):
            bonded = True
            emitter.message(
                f"Worker is bonded to ({staking_address})!", color="green", bold=True
            )

        # Balance
        if ether_balance and (not funded):
            funded, balance = True, Web3.fromWei(ether_balance, "ether")
            emitter.message(
                f"Worker is funded with {balance} ETH!", color="green", bold=True
            )

        # Success and Escape
        if staking_address != BlockchainInterface.NULL_ADDRESS and ether_balance:
            self._checksum_address = staking_address

            # TODO: #1823 - Workaround for new nickname every restart
            self.nickname, self.nickname_metadata = nickname_from_seed(
                self.checksum_address
            )

            emitter.message(f"Starting services...", color="yellow", bold=True)
            break

        # Crash on Timeout
        if timeout:
            now = maya.now()
            delta = now - start
            if delta.total_seconds() >= timeout:
                if staking_address == BlockchainInterface.NULL_ADDRESS:
                    raise self.DetachedWorker(
                        f"Worker {self.__worker_address} not bonded after waiting {timeout} seconds."
                    )
                elif not ether_balance:
                    raise RuntimeError(
                        f"Worker {self.__worker_address} has no ether after waiting {timeout} seconds."
                    )

        # Increment
        time.sleep(poll_rate)


# Traceback (ValueError)
Apr 02 17:02:28 ip-172-31-19-8 nucypher[29582]: Unhandled error in Deferred:
Apr 02 17:02:28 ip-172-31-19-8 nucypher[29582]: Traceback (most recent call last):
Apr 02 17:02:28 ip-172-31-19-8 nucypher[29582]:   File "/home/ubuntu/nucypher-venv/lib/python3.6/site-packages/twisted/internet/base.py", line 1283, in run
Apr 02 17:02:28 ip-172-31-19-8 nucypher[29582]:     self.mainLoop()
Apr 02 17:02:28 ip-172-31-19-8 nucypher[29582]:   File "/home/ubuntu/nucypher-venv/lib/python3.6/site-packages/twisted/internet/base.py", line 1292, in mainLoop
Apr 02 17:02:28 ip-172-31-19-8 nucypher[29582]:     self.runUntilCurrent()
Apr 02 17:02:28 ip-172-31-19-8 nucypher[29582]:   File "/home/ubuntu/nucypher-venv/lib/python3.6/site-packages/twisted/internet/base.py", line 913, in runUntilCurrent
Apr 02 17:02:28 ip-172-31-19-8 nucypher[29582]:     call.func(*call.args, **call.kw)
Apr 02 17:02:28 ip-172-31-19-8 nucypher[29582]:   File "/home/ubuntu/nucypher-venv/lib/python3.6/site-packages/twisted/internet/task.py", line 239, in __call__
Apr 02 17:02:28 ip-172-31-19-8 nucypher[29582]:     d = defer.maybeDeferred(self.f, *self.a, **self.kw)
Apr 02 17:02:28 ip-172-31-19-8 nucypher[29582]: --- <exception caught here> ---
Apr 02 17:02:28 ip-172-31-19-8 nucypher[29582]:   File "/home/ubuntu/nucypher-venv/lib/python3.6/site-packages/twisted/internet/defer.py", line 654, in _runCallbacks
Apr 02 17:02:28 ip-172-31-19-8 nucypher[29582]:     current.result = callback(current.result, *args, **kw)
Apr 02 17:02:28 ip-172-31-19-8 nucypher[29582]:   File "/home/ubuntu/nucypher/nucypher/network/sensors.py", line 89, in handle_measurement_errors
Apr 02 17:02:28 ip-172-31-19-8 nucypher[29582]:     failure.raiseException()
Apr 02 17:02:28 ip-172-31-19-8 nucypher[29582]:   File "/home/ubuntu/nucypher-venv/lib/python3.6/site-packages/twisted/python/failure.py", line 488, in raiseException
Apr 02 17:02:28 ip-172-31-19-8 nucypher[29582]:     raise self.value.with_traceback(self.tb)
Apr 02 17:02:28 ip-172-31-19-8 nucypher[29582]:   File "/home/ubuntu/nucypher-venv/lib/python3.6/site-packages/twisted/internet/defer.py", line 151, in maybeDeferred
Apr 02 17:02:28 ip-172-31-19-8 nucypher[29582]:     result = f(*args, **kw)
Apr 02 17:02:28 ip-172-31-19-8 nucypher[29582]:   File "/home/ubuntu/nucypher/nucypher/network/sensors.py", line 138, in maintain
Apr 02 17:02:28 ip-172-31-19-8 nucypher[29582]:     self.measure()
Apr 02 17:02:28 ip-172-31-19-8 nucypher[29582]:   File "/home/ubuntu/nucypher/nucypher/network/sensors.py", line 191, in measure
Apr 02 17:02:28 ip-172-31-19-8 nucypher[29582]:     certificate_filepath=certificate_filepath)
Apr 02 17:02:28 ip-172-31-19-8 nucypher[29582]:   File "/home/ubuntu/nucypher/nucypher/network/middleware.py", line 248, in check_rest_availability
Apr 02 17:02:28 ip-172-31-19-8 nucypher[29582]:     certificate_filepath=certificate_filepath)
Apr 02 17:02:28 ip-172-31-19-8 nucypher[29582]:   File "/home/ubuntu/nucypher/nucypher/network/middleware.py", line 114, in method_wrapper
Apr 02 17:02:28 ip-172-31-19-8 nucypher[29582]:     raise ValueError("Don't try to pass a node with a certificate_filepath while also passing a"
Apr 02 17:02:28 ip-172-31-19-8 nucypher[29582]: builtins.ValueError: Don't try to pass a node with a certificate_filepath while also passing a different certificate_filepath.  What do you even expect?
Apr 03 00:02:29 ip-172-31-19-8 nucypher[29582]: Broadcasting CONFIRMACTIVITY Transaction (264369 gwei @ 3000000000)...

# Fixed code
def block_until_ready(self, poll_rate: int = None, timeout: int = None):
    """
    Polls the staking_agent and blocks until the staking address is not
    a null address for the given worker_address. Once the worker is bonded, it returns the staker address.
    """
    if not self.__worker_address:
        raise RuntimeError("No worker address available")

    timeout = timeout or self.BONDING_TIMEOUT
    poll_rate = poll_rate or self.BONDING_POLL_RATE
    staking_agent = ContractAgency.get_agent(StakingEscrowAgent, registry=self.registry)
    client = staking_agent.blockchain.client
    start = maya.now()

    emitter = StdoutEmitter()  # TODO: Make injectable, or embed this logic into Ursula
    emitter.message("Waiting for bonding and funding...", color="yellow")

    funded, bonded = False, False
    while True:
        # Read
        staking_address = staking_agent.get_staker_from_worker(self.__worker_address)
        ether_balance = client.get_balance(self.__worker_address)

        # Bonding
        if (not bonded) and (staking_address != BlockchainInterface.NULL_ADDRESS):
            bonded = True
            emitter.message(
                f"Worker is bonded to ({staking_address})!", color="green", bold=True
            )

        # Balance
        if ether_balance and (not funded):
            funded, balance = True, Web3.fromWei(ether_balance, "ether")
            emitter.message(
                f"Worker is funded with {balance} ETH!", color="green", bold=True
            )

        # Success and Escape
        if staking_address != BlockchainInterface.NULL_ADDRESS and ether_balance:
            self._checksum_address = staking_address

            # TODO: #1823 - Workaround for new nickname every restart
            self.nickname, self.nickname_metadata = nickname_from_seed(
                self.checksum_address
            )
            break

        # Crash on Timeout
        if timeout:
            now = maya.now()
            delta = now - start
            if delta.total_seconds() >= timeout:
                if staking_address == BlockchainInterface.NULL_ADDRESS:
                    raise self.DetachedWorker(
                        f"Worker {self.__worker_address} not bonded after waiting {timeout} seconds."
                    )
                elif not ether_balance:
                    raise RuntimeError(
                        f"Worker {self.__worker_address} has no ether after waiting {timeout} seconds."
                    )

        # Increment
        time.sleep(poll_rate)