Beispiel #1
0
def iter_used_addresses(
        adapter,  # type: BaseAdapter
        seed,  # type: Seed
        start,  # type: int
        security_level=None,  # type: Optional[int]
):
    # type: (...) -> Generator[Tuple[Address, List[TransactionHash]], None, None]
    """
    Scans the Tangle for used addresses.

    This is basically the opposite of invoking ``getNewAddresses`` with
    ``stop=None``.
    """
    if security_level is None:
        security_level = AddressGenerator.DEFAULT_SECURITY_LEVEL

    ft_command = FindTransactionsCommand(adapter)

    for addy in AddressGenerator(seed, security_level).create_iterator(start):
        ft_response = ft_command(addresses=[addy])

        if ft_response['hashes']:
            yield addy, ft_response['hashes']
        else:
            break

        # Reset the command so that we can call it again.
        ft_command.reset()
Beispiel #2
0
def iter_used_addresses(adapter, seed, start):
  # type: (BaseAdapter, Seed, int) -> Generator[Tuple[Address, List[TransactionHash]]]
  """
  Scans the Tangle for used addresses.

  This is basically the opposite of invoking ``getNewAddresses`` with
  ``stop=None``.
  """
  ft_command = FindTransactionsCommand(adapter)

  for addy in AddressGenerator(seed).create_iterator(start):
    ft_response = ft_command(addresses=[addy])

    if ft_response['hashes']:
      yield addy, ft_response['hashes']
    else:
      break

    # Reset the command so that we can call it again.
    ft_command.reset()
Beispiel #3
0
def iter_used_addresses(adapter, seed, start):
    # type: (BaseAdapter, Seed, int) -> Generator[Tuple[Address, List[TransactionHash]]]
    """
  Scans the Tangle for used addresses.

  This is basically the opposite of invoking ``getNewAddresses`` with
  ``stop=None``.
  """
    ft_command = FindTransactionsCommand(adapter)

    for addy in AddressGenerator(seed).create_iterator(start):
        ft_response = ft_command(addresses=[addy])

        if ft_response['hashes']:
            yield addy, ft_response['hashes']
        else:
            break

        # Reset the command so that we can call it again.
        ft_command.reset()
Beispiel #4
0
async def iter_used_addresses(
        adapter: BaseAdapter,
        seed: Seed,
        start: int,
        security_level: Optional[int] = None,
        # 'typing' only supports AsyncGenerator from python 3.6.1, so put it
        # as string literal here.
) -> 'AsyncGenerator[Tuple[Address, List[TransactionHash]], None]':
    """
    Scans the Tangle for used addresses. A used address is an address that
    was spent from or has a transaction.

    This is basically the opposite of invoking ``getNewAddresses`` with
    ``count=None``.

    .. important::
        This is an async generator!

    """
    if security_level is None:
        security_level = AddressGenerator.DEFAULT_SECURITY_LEVEL

    ft_command = FindTransactionsCommand(adapter)
    wasf_command = WereAddressesSpentFromCommand(adapter)

    for addy in AddressGenerator(seed, security_level).create_iterator(start):
        ft_response = await ft_command(addresses=[addy])

        if ft_response['hashes']:
            yield addy, ft_response['hashes']
        else:
            wasf_response = await wasf_command(addresses=[addy])
            if wasf_response['states'][0]:
                yield addy, []
            else:
                break

        # Reset the commands so that we can call them again.
        ft_command.reset()
        wasf_command.reset()
Beispiel #5
0
    def _execute(self, request):
        stop = request['stop']  # type: Optional[int]
        inclusion_states = request['inclusionStates']  # type: bool
        seed = request['seed']  # type: Seed
        start = request['start']  # type: int

        generator = AddressGenerator(seed)
        ft_command = FindTransactionsCommand(self.adapter)

        # Determine the addresses we will be scanning, and pull their
        # transaction hashes.
        if stop is None:
            # This is similar to the ``getNewAddresses`` command, except it
            # is interested in all the addresses that `getNewAddresses`
            # skips.
            hashes = []
            for addy in generator.create_generator(start):
                ft_response = ft_command(addresses=[addy])

                if ft_response.get('hashes'):
                    hashes += ft_response['hashes']
                else:
                    break

                # Reset the command so that we can call it again.
                ft_command.reset()
        else:
            ft_response =\
              ft_command(addresses=generator.get_addresses(start, stop - start))

            hashes = ft_response.get('hashes') or []

        all_bundles = []  # type: List[Bundle]

        if hashes:
            # Sort transactions into tail and non-tail.
            tail_transaction_hashes = set()
            non_tail_bundle_hashes = set()

            gt_response = GetTrytesCommand(self.adapter)(hashes=hashes)
            all_transactions = list(
                map(
                    Transaction.from_tryte_string,
                    gt_response['trytes'],
                ))  # type: List[Transaction]

            for txn in all_transactions:
                if txn.is_tail:
                    tail_transaction_hashes.add(txn.hash)
                else:
                    # Capture the bundle ID instead of the transaction hash so that
                    # we can query the node to find the tail transaction for that
                    # bundle.
                    non_tail_bundle_hashes.add(txn.bundle_hash)

            if non_tail_bundle_hashes:
                for txn in self._find_transactions(
                        bundles=list(non_tail_bundle_hashes)):
                    if txn.is_tail:
                        if txn.hash not in tail_transaction_hashes:
                            all_transactions.append(txn)
                            tail_transaction_hashes.add(txn.hash)

            # Filter out all non-tail transactions.
            tail_transactions = [
                txn for txn in all_transactions
                if txn.hash in tail_transaction_hashes
            ]

            # Attach inclusion states, if requested.
            if inclusion_states:
                gli_response = GetLatestInclusionCommand(self.adapter)(
                    hashes=list(tail_transaction_hashes), )

                for txn in tail_transactions:
                    txn.is_confirmed = gli_response['states'].get(txn.hash)

            # Find the bundles for each transaction.
            for txn in tail_transactions:
                gb_response = GetBundlesCommand(
                    self.adapter)(transaction=txn.hash)
                txn_bundles = gb_response['bundles']  # type: List[Bundle]

                if inclusion_states:
                    for bundle in txn_bundles:
                        bundle.is_confirmed = txn.is_confirmed

                all_bundles.extend(txn_bundles)

        return {
            # Sort bundles by tail transaction timestamp.
            'bundles':
            list(
                sorted(
                    all_bundles,
                    key=lambda bundle_: bundle_.tail_transaction.timestamp,
                )),
        }