This repository was archived by the owner on Jan 13, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 124
/
Copy pathutils.py
146 lines (117 loc) · 4.57 KB
/
utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# coding=utf-8
from __future__ import absolute_import, division, print_function, \
unicode_literals
from typing import Generator, Iterable, List, Optional, Tuple
from iota import Address
from iota.adapter import BaseAdapter
from iota.commands.core.find_transactions import FindTransactionsCommand
from iota.commands.core.get_trytes import GetTrytesCommand
from iota.commands.extended.get_bundles import GetBundlesCommand
from iota.commands.extended.get_latest_inclusion import \
GetLatestInclusionCommand
from iota.crypto.addresses import AddressGenerator
from iota.crypto.types import Seed
from iota.transaction.base import Bundle, Transaction
from iota.transaction.types import TransactionHash
def find_transaction_objects(adapter, **kwargs):
# type: (BaseAdapter, **Iterable) -> List[Transaction]
"""
Finds transactions matching the specified criteria, fetches the
corresponding trytes and converts them into Transaction objects.
"""
ft_response = FindTransactionsCommand(adapter)(**kwargs)
hashes = ft_response['hashes']
if hashes:
gt_response = GetTrytesCommand(adapter)(hashes=hashes)
return list(map(
Transaction.from_tryte_string,
gt_response.get('trytes') or [],
)) # type: List[Transaction]
return []
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()
def get_bundles_from_transaction_hashes(
adapter,
transaction_hashes,
inclusion_states,
):
# type: (BaseAdapter, Iterable[TransactionHash], bool) -> List[Bundle]
"""
Given a set of transaction hashes, returns the corresponding bundles,
sorted by tail transaction timestamp.
"""
transaction_hashes = list(transaction_hashes)
if not transaction_hashes:
return []
my_bundles = [] # type: List[Bundle]
# Sort transactions into tail and non-tail.
tail_transaction_hashes = set()
non_tail_bundle_hashes = set()
gt_response = GetTrytesCommand(adapter)(hashes=transaction_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 find_transaction_objects(
adapter=adapter,
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(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(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
my_bundles.extend(txn_bundles)
return list(sorted(
my_bundles,
key=lambda bundle_: bundle_.tail_transaction.timestamp,
))