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 _find_addresses(self, seed, index, count, security_level, checksum): # type: (Seed, int, Optional[int], int, bool) -> List[Address] """ Find addresses matching the command parameters. """ generator = AddressGenerator(seed, security_level, checksum) if count is None: # Connect to Tangle and find the first unused address. for addy in generator.create_iterator(start=index): # We use addy.address here because the commands do # not work on an address with a checksum response = WereAddressesSpentFromCommand(self.adapter)( addresses=[addy.address], ) if response['states'][0]: continue response = FindTransactionsCommand(self.adapter)( addresses=[addy.address], ) if response.get('hashes'): continue return [addy] return generator.get_addresses(start=index, count=count)
def _execute(self, request): inclusion_states = request['inclusionStates'] # type: bool seed = request['seed'] # type: Seed start = request['start'] # type: int stop = request['stop'] # type: Optional[int] # Determine the addresses we will be scanning, and pull their # transaction hashes. if stop is None: my_hashes = list( chain(*(hashes for _, hashes in iter_used_addresses( self.adapter, seed, start)))) else: ft_response = \ FindTransactionsCommand(self.adapter)( addresses= AddressGenerator(seed).get_addresses(start, stop - start), ) my_hashes = ft_response['hashes'] return { 'bundles': get_bundles_from_transaction_hashes( adapter=self.adapter, transaction_hashes=my_hashes, inclusion_states=inclusion_states, ), }
class FindTransactionsResponseFilterTestCase(BaseFilterTestCase): filter_type = FindTransactionsCommand(MockAdapter()).get_response_filter skip_value_check = True # noinspection SpellCheckingInspection def setUp(self): super(FindTransactionsResponseFilterTestCase, self).setUp() # Define a few valid values here that we can reuse across multiple # tests. self.trytes1 = b'RBTC9D9DCDQAEASBYBCCKBFA' self.trytes2 =\ b'CCPCBDVC9DTCEAKDXC9D9DEARCWCPCBDVCTCEAHDWCTCEAKDCDFD9DSCSA' def test_no_results(self): """ The incoming response contains no hashes. """ response = { 'hashes': [], 'duration': 42, } filter_ = self._filter(response) self.assertFilterPasses(filter_) self.assertDictEqual(filter_.cleaned_data, response) # noinspection SpellCheckingInspection def test_search_results(self): """ The incoming response contains lots of hashes. """ filter_ = self._filter({ 'hashes': [ 'RVORZ9SIIP9RCYMREUIXXVPQIPHVCNPQ9HZWYKFW' 'YWZRE9JQKG9REPKIASHUUECPSQO9JT9XNMVKWYGVA', 'ZJVYUGTDRPDYFGFXMKOTV9ZWSGFK9CFPXTITQLQN' 'LPPG9YNAARMKNKYQO9GSCSBIOTGMLJUFLZWSY9999', ], 'duration': 42, }) self.assertFilterPasses(filter_) self.assertDictEqual( filter_.cleaned_data, { 'hashes': [ TransactionHash( b'RVORZ9SIIP9RCYMREUIXXVPQIPHVCNPQ9HZWYKFW' b'YWZRE9JQKG9REPKIASHUUECPSQO9JT9XNMVKWYGVA', ), TransactionHash( b'ZJVYUGTDRPDYFGFXMKOTV9ZWSGFK9CFPXTITQLQN' b'LPPG9YNAARMKNKYQO9GSCSBIOTGMLJUFLZWSY9999', ), ], 'duration': 42, }, )
async def _find_addresses(self, seed: Seed, index: int, count: Optional[int], security_level: int, checksum: bool) -> List[Address]: """ Find addresses matching the command parameters. """ generator = AddressGenerator(seed, security_level, checksum) if count is None: # Connect to Tangle and find the first unused address. for addy in generator.create_iterator(start=index): # We use addy.address here because the commands do # not work on an address with a checksum # Execute two checks concurrently responses = await asyncio.gather( WereAddressesSpentFromCommand(self.adapter)( addresses=[addy.address], ), FindTransactionsCommand(self.adapter)( addresses=[addy.address], ), ) # responses[0] -> was it spent from? # responses[1] -> any transaction found? if responses[0]['states'][0] or responses[1].get('hashes'): continue return [addy] return generator.get_addresses(start=index, count=count)
def _find_addresses(self, seed, index, count): """ Find addresses matching the command parameters. """ # type: (Seed, int, Optional[int]) -> List[Address] generator = AddressGenerator(seed) if count is None: # Connect to Tangle and find the first address without any # transactions. for addy in generator.create_iterator(start=index): response = FindTransactionsCommand( self.adapter)(addresses=[addy]) if not response.get('hashes'): return [addy] return generator.get_addresses(start=index, count=count)
def _find_transactions(self, **kwargs): # type: (dict) -> List[Transaction] """ Finds transactions matching the specified criteria, fetches the corresponding trytes and converts them into Transaction objects. """ ft_response = FindTransactionsCommand(self.adapter)(**kwargs) hashes = ft_response.get('hashes') or [] if hashes: gt_response = GetTrytesCommand(self.adapter)(hashes=hashes) return list( map( Transaction.from_tryte_string, gt_response.get('trytes') or [], )) # type: List[Transaction] return []
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()
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()
def _find_addresses(self, seed, index, count, security_level, checksum): # type: (Seed, int, Optional[int], int, bool) -> List[Address] """ Find addresses matching the command parameters. """ generator = AddressGenerator(seed, security_level, checksum) if count is None: # Connect to Tangle and find the first address without any # transactions. for addy in generator.create_iterator(start=index): # We use addy.address here because FindTransactions does # not work on an address with a checksum response = FindTransactionsCommand(self.adapter)( addresses=[addy.address] ) if not response.get('hashes'): return [addy] return generator.get_addresses(start=index, count=count)
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()
async def _execute(self, request: dict) -> dict: inclusion_states: bool = request['inclusionStates'] seed: Seed = request['seed'] start: int = request['start'] stop: Optional[int] = request['stop'] security_level: Optional[int] = request['security_level'] if stop is None: my_addresses: List[Address] = [] my_hashes: List[TransactionHash] = [] async for addy, hashes in iter_used_addresses( self.adapter, seed, start, security_level): my_addresses.append(addy) my_hashes.extend(hashes) else: ft_command = FindTransactionsCommand(self.adapter) my_addresses = (AddressGenerator(seed, security_level).get_addresses( start, stop - start)) my_hashes = (await ft_command(addresses=my_addresses )).get('hashes') or [] account_balance = 0 if my_addresses: # Load balances for the addresses that we generated. gb_response = (await GetBalancesCommand(self.adapter) (addresses=my_addresses)) for i, balance in enumerate(gb_response['balances']): my_addresses[i].balance = balance account_balance += balance return { 'addresses': list(sorted(my_addresses, key=attrgetter('key_index'))), 'balance': account_balance, 'bundles': await get_bundles_from_transaction_hashes( adapter=self.adapter, transaction_hashes=my_hashes, inclusion_states=inclusion_states, ), }
def _execute(self, request): inclusion_states = request['inclusionStates'] # type: bool seed = request['seed'] # type: Seed start = request['start'] # type: int stop = request['stop'] # type: Optional[int] if stop is None: my_addresses = [] # type: List[Address] my_hashes = [] # type: List[TransactionHash] for addy, hashes in iter_used_addresses(self.adapter, seed, start): my_addresses.append(addy) my_hashes.extend(hashes) else: ft_command = FindTransactionsCommand(self.adapter) my_addresses = AddressGenerator(seed).get_addresses( start, stop - start) my_hashes = ft_command(addresses=my_addresses).get('hashes') or [] account_balance = 0 if my_hashes: # Load balances for the addresses that we generated. gb_response = GetBalancesCommand( self.adapter)(addresses=my_addresses) for i, balance in enumerate(gb_response['balances']): my_addresses[i].balance = balance account_balance += balance return { 'addresses': list(sorted(my_addresses, key=attrgetter('key_index'))), 'balance': account_balance, 'bundles': get_bundles_from_transaction_hashes( adapter=self.adapter, transaction_hashes=my_hashes, inclusion_states=inclusion_states, ), }
def _execute(self, request): inclusion_states = request['inclusionStates'] # type: bool address = request['address'] # type: Address # Determine the addresses we will be scanning, and pull their # transaction hashes. ft_response =\ FindTransactionsCommand(self.adapter)( addresses = address ) my_hashes = ft_response['hashes'] return { 'bundles': get_bundles_from_transaction_hashes( adapter=self.adapter, transaction_hashes=my_hashes, inclusion_states=inclusion_states, ), }
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, )), }
class FindTransactionsRequestFilterTestCase(BaseFilterTestCase): filter_type = FindTransactionsCommand(MockAdapter()).get_request_filter skip_value_check = True # noinspection SpellCheckingInspection def setUp(self): super(FindTransactionsRequestFilterTestCase, self).setUp() # Define a few valid values that we can reuse across tests. self.trytes1 = 'RBTC9D9DCDQAEASBYBCCKBFA' self.trytes2 =\ 'CCPCBDVC9DTCEAKDXC9D9DEARCWCPCBDVCTCEAHDWCTCEAKDCDFD9DSCSA' self.trytes3 = '999999999999999999999999999' def test_pass_all_parameters(self): """ The request contains valid values for all parameters. """ # Raw trytes are extracted to match the IRI's JSON protocol. request = { 'bundles': [ text_type(BundleHash(self.trytes1)), text_type(BundleHash(self.trytes2)), ], 'addresses': [ text_type(Address(self.trytes1)), text_type(Address(self.trytes2)), ], 'tags': [ text_type(Tag(self.trytes1)), text_type(Tag(self.trytes3)), ], 'approvees': [ text_type(TransactionHash(self.trytes1)), text_type(TransactionHash(self.trytes3)), ], } filter_ = self._filter(request) self.assertFilterPasses(filter_) self.assertDictEqual(filter_.cleaned_data, request) def test_pass_compatible_types(self): """ The request contains values that can be converted to the expected types. """ filter_ = self._filter({ 'bundles': [ self.trytes1.encode('ascii'), BundleHash(self.trytes2), ], 'addresses': [ self.trytes1.encode('ascii'), Address(self.trytes2), ], 'tags': [ self.trytes1.encode('ascii'), Tag(self.trytes3), ], 'approvees': [ self.trytes1.encode('ascii'), TransactionHash(self.trytes3), ], }) self.assertFilterPasses(filter_) self.assertDictEqual( filter_.cleaned_data, { # Raw trytes are extracted to match the IRI's JSON protocol. 'bundles': [ text_type(BundleHash(self.trytes1)), text_type(BundleHash(self.trytes2)), ], 'addresses': [ text_type(Address(self.trytes1)), text_type(Address(self.trytes2)), ], 'tags': [ text_type(Tag(self.trytes1)), text_type(Tag(self.trytes3)), ], 'approvees': [ text_type(TransactionHash(self.trytes1)), text_type(TransactionHash(self.trytes3)), ], }, ) def test_pass_bundles_only(self): """ The request only includes bundles. """ request = { 'bundles': [ BundleHash(self.trytes1), BundleHash(self.trytes2), ], } filter_ = self._filter(request) self.assertFilterPasses(filter_) self.assertDictEqual( filter_.cleaned_data, { 'bundles': [ text_type(BundleHash(self.trytes1)), text_type(BundleHash(self.trytes2)), ], # Null criteria are not included in the request. # https://github.com/iotaledger/iota.lib.py/issues/96 # 'addresses': [], # 'approvees': [], # 'tags': [], }, ) def test_pass_addresses_only(self): """ The request only includes addresses. """ request = { 'addresses': [ Address(self.trytes1), Address(self.trytes2), ], } filter_ = self._filter(request) self.assertFilterPasses(filter_) self.assertDictEqual( filter_.cleaned_data, { 'addresses': [ text_type(Address(self.trytes1)), text_type(Address(self.trytes2)), ], # Null criteria are not included in the request. # https://github.com/iotaledger/iota.lib.py/issues/96 # 'approvees': [], # 'bundles': [], # 'tags': [], }, ) def test_pass_tags_only(self): """ The request only includes tags. """ request = { 'tags': [ Tag(self.trytes1), Tag(self.trytes3), ], } filter_ = self._filter(request) self.assertFilterPasses(filter_) self.assertDictEqual( filter_.cleaned_data, { 'tags': [ text_type(Tag(self.trytes1)), text_type(Tag(self.trytes3)), ], # Null criteria are not included in the request. # https://github.com/iotaledger/iota.lib.py/issues/96 # 'addresses': [], # 'approvees': [], # 'bundles': [], }, ) def test_pass_approvees_only(self): """ The request only includes approvees. """ request = { 'approvees': [ TransactionHash(self.trytes1), TransactionHash(self.trytes3), ], } filter_ = self._filter(request) self.assertFilterPasses(filter_) self.assertDictEqual( filter_.cleaned_data, { 'approvees': [ text_type(TransactionHash(self.trytes1)), text_type(TransactionHash(self.trytes3)), ], # Null criteria are not included in the request. # https://github.com/iotaledger/iota.lib.py/issues/96 # 'addresses': [], # 'bundles': [], # 'tags': [], }, ) def test_fail_empty(self): """ The request does not contain any parameters. """ self.assertFilterErrors( {}, { '': [FindTransactionsRequestFilter.CODE_NO_SEARCH_VALUES], }, ) def test_fail_all_parameters_null(self): """ The request contains all parameters, but every one is null. """ self.assertFilterErrors( { 'addresses': None, 'approvees': None, 'bundles': None, 'tags': None, }, { '': [FindTransactionsRequestFilter.CODE_NO_SEARCH_VALUES], }, ) def test_success_all_parameters_empty(self): """ All of the parameters are empty lists. This is technically valid, though probably not very useful. """ self.assertFilterPasses( { 'addresses': [], 'approvees': [], 'bundles': [], 'tags': [], }, ) def test_fail_unexpected_parameters(self): """ The request contains unexpected parameters. """ self.assertFilterErrors( { 'addresses': [Address(self.trytes1)], 'approvees': [TransactionHash(self.trytes1)], 'bundles': [BundleHash(self.trytes1)], 'tags': [Tag(self.trytes1)], # Hey, you're not allowed in he-argh! 'foo': 'bar', }, { 'foo': [f.FilterMapper.CODE_EXTRA_KEY], }, ) def test_fail_bundles_wrong_type(self): """ ``bundles`` is not an array. """ self.assertFilterErrors( { 'bundles': BundleHash(self.trytes1), }, { 'bundles': [f.Type.CODE_WRONG_TYPE], }, ) def test_fail_bundles_contents_invalid(self): """ ``bundles`` is an array, but it contains invalid values. """ self.assertFilterErrors( { 'bundles': [ b'', True, None, b'not valid trytes', # This is actually valid; I just added it to make sure the # filter isn't cheating! TryteString(self.trytes2), 2130706433, b'9' * 82, ], }, { 'bundles.0': [f.Required.CODE_EMPTY], 'bundles.1': [f.Type.CODE_WRONG_TYPE], 'bundles.2': [f.Required.CODE_EMPTY], 'bundles.3': [Trytes.CODE_NOT_TRYTES], 'bundles.5': [f.Type.CODE_WRONG_TYPE], 'bundles.6': [Trytes.CODE_WRONG_FORMAT], }, ) def test_fail_addresses_wrong_type(self): """ ``addresses`` is not an array. """ self.assertFilterErrors( { 'addresses': Address(self.trytes1), }, { 'addresses': [f.Type.CODE_WRONG_TYPE], }, ) def test_fail_addresses_contents_invalid(self): """ ``addresses`` is an array, but it contains invalid values. """ self.assertFilterErrors( { 'addresses': [ b'', True, None, b'not valid trytes', # This is actually valid; I just added it to make sure the # filter isn't cheating! TryteString(self.trytes2), 2130706433, b'9' * 82, ], }, { 'addresses.0': [f.Required.CODE_EMPTY], 'addresses.1': [f.Type.CODE_WRONG_TYPE], 'addresses.2': [f.Required.CODE_EMPTY], 'addresses.3': [Trytes.CODE_NOT_TRYTES], 'addresses.5': [f.Type.CODE_WRONG_TYPE], 'addresses.6': [Trytes.CODE_WRONG_FORMAT], }, ) def test_fail_tags_wrong_type(self): """ ``tags`` is not an array. """ self.assertFilterErrors( { 'tags': Tag(self.trytes1), }, { 'tags': [f.Type.CODE_WRONG_TYPE], }, ) def test_fail_tags_contents_invalid(self): """ ``tags`` is an array, but it contains invalid values. """ self.assertFilterErrors( { 'tags': [ b'', True, None, b'not valid trytes', # This is actually valid; I just added it to make sure the # filter isn't cheating! TryteString(self.trytes1), 2130706433, b'9' * 28, ], }, { 'tags.0': [f.Required.CODE_EMPTY], 'tags.1': [f.Type.CODE_WRONG_TYPE], 'tags.2': [f.Required.CODE_EMPTY], 'tags.3': [Trytes.CODE_NOT_TRYTES], 'tags.5': [f.Type.CODE_WRONG_TYPE], 'tags.6': [Trytes.CODE_WRONG_FORMAT], }, ) def test_fail_approvees_wrong_type(self): """ ``approvees`` is not an array. """ self.assertFilterErrors( { 'approvees': TransactionHash(self.trytes1), }, { 'approvees': [f.Type.CODE_WRONG_TYPE], }, ) def test_fail_approvees_contents_invalid(self): """ ``approvees`` is an array, but it contains invalid values. """ self.assertFilterErrors( { 'approvees': [ b'', True, None, b'not valid trytes', # This is actually valid; I just added it to make sure the # filter isn't cheating! TryteString(self.trytes2), 2130706433, b'9' * 82, ], }, { 'approvees.0': [f.Required.CODE_EMPTY], 'approvees.1': [f.Type.CODE_WRONG_TYPE], 'approvees.2': [f.Required.CODE_EMPTY], 'approvees.3': [Trytes.CODE_NOT_TRYTES], 'approvees.5': [f.Type.CODE_WRONG_TYPE], 'approvees.6': [Trytes.CODE_WRONG_FORMAT], }, )
def _execute(self, request): stop = request['stop'] # type: Optional[int] seed = request['seed'] # type: Seed start = request['start'] # type: int threshold = request['threshold'] # type: Optional[int] generator = AddressGenerator(seed) # Determine the addresses we will be scanning. if stop is None: # This is similar to the ``getNewAddresses`` command, except it # is interested in all the addresses that `getNewAddresses` # skips. addresses = [] # type: List[Address] for addy in generator.create_generator(start): ft_response = FindTransactionsCommand( self.adapter)(addresses=[addy]) if ft_response.get('hashes'): addresses.append(addy) else: break else: addresses = generator.get_addresses(start, stop) # Load balances for the addresses that we generated. gb_response = GetBalancesCommand(self.adapter)(addresses=addresses) result = { 'inputs': [], 'totalBalance': 0, } threshold_met = threshold is None for i, balance in enumerate(gb_response['balances']): addresses[i].balance = balance if balance: result['inputs'].append(addresses[i]) result['totalBalance'] += balance if (threshold is not None) and (result['totalBalance'] >= threshold): threshold_met = True break if threshold_met: return result else: # This is an exception case, but note that we attach the result # to the exception context so that it can be used for # troubleshooting. raise with_context( exc=BadApiResponse( 'Accumulated balance {balance} is less than threshold {threshold} ' '(``exc.context`` contains more information).'.format( threshold=threshold, balance=result['totalBalance'], ), ), context={ 'inputs': result['inputs'], 'request': request, 'total_balance': result['totalBalance'], }, )
class FindTransactionsRequestFilterTestCase(BaseFilterTestCase): filter_type = FindTransactionsCommand(MockAdapter()).get_request_filter print_var_type_n_val(var001=filter_type, pointer="#ZERTsdfgrd1234jh") #ZERTsdfgrd1234jh # Value: # # <bound method FindTransactionsCommand.get_request_filter of <iota.commands.core.find_transactions.FindTransactionsCommand object at 0x0000021C318C8A58>> # Type: <class 'method'> skip_value_check = True # noinspection SpellCheckingInspection def setUp(self): super(FindTransactionsRequestFilterTestCase, self).setUp() # Define a few valid values that we can reuse across tests. self.trytes1 = 'RBTC9D9DCDQAEASBYBCCKBFA' self.trytes2 =\ 'CCPCBDVC9DTCEAKDXC9D9DEARCWCPCBDVCTCEAHDWCTCEAKDCDFD9DSCSA' self.trytes3 = '999999999999999999999999999' def test_pass_all_parameters(self): """ The request contains valid values for all parameters. """ # Raw trytes are extracted to match the IRI's JSON protocol. request = { 'bundles': [ text_type( TransactionHash(self.trytes1) # # self.trytes1 = 'RBTC9D9DCDQAEASBYBCCKBFA' ), text_type(TransactionHash(self.trytes2)), ], 'addresses': [ text_type(Address(self.trytes1)), text_type(Address(self.trytes2)), ], 'tags': [ text_type(Tag(self.trytes1)), text_type( Tag(self.trytes3) # # self.trytes3 = '999999999999999999999999999' ), ], 'approvees': [ text_type(TransactionHash(self.trytes1)), text_type(TransactionHash(self.trytes3)), ], } print_var_type_n_val( var001=request, pointer="#XXXXCVBVCZZZzzzer12345") #XXXXCVBVCZZZzzzer12345 # Value: # # {'bundles': ['RBTC9D9DCDQAEASBYBCCKBFA999999999999999999999999999999999999999999999999999999999', 'CCPCBDVC9DTCEAKDXC9D9DEARCWCPCBDVCTCEAHDWCTCEAKDCDFD9DSCSA99999999999999999999999'], 'addresses': ['RBTC9D9DCDQAEASBYBCCKBFA999999999999999999999999999999999999999999999999999999999', 'CCPCBDVC9DTCEAKDXC9D9DEARCWCPCBDVCTCEAHDWCTCEAKDCDFD9DSCSA99999999999999999999999'], 'tags': ['RBTC9D9DCDQAEASBYBCCKBFA999', '999999999999999999999999999'], 'approvees': ['RBTC9D9DCDQAEASBYBCCKBFA999999999999999999999999999999999999999999999999999999999', '999999999999999999999999999999999999999999999999999999999999999999999999999999999']} # Type: <class 'dict'> filter_ = self._filter(request) #here001 print_var_type_n_val(var001=filter_, pointer="#WXCVRDFGTFGHV") #WXCVRDFGTFGHV # Value: # # FindTransactionsRequestFilter(FilterChain(Type(Mapping, allow_subclass=True) | FilterMapper(addresses=FilterChain(Array(Sequence, allow_subclass=True) | FilterRepeater(FilterChain(Required(allow_none=False) | AddressNoChecksum() | Unicode(encoding='ascii')))), approvees=FilterChain(Array(Sequence, allow_subclass=True) | FilterRepeater(FilterChain(Required(allow_none=False) | Trytes() | Unicode(encoding='ascii')))), bundles=FilterChain(Array(Sequence, allow_subclass=True) | FilterRepeater(FilterChain(Required(allow_none=False) | Trytes() | Unicode(encoding='ascii')))), tags=FilterChain(Array(Sequence, allow_subclass=True) | FilterRepeater(FilterChain(Required(allow_none=False) | Trytes() | Unicode(encoding='ascii'))))))) # Type: <class 'filters.handlers.FilterRunner'> self.assertFilterPasses(filter_) self.assertDictEqual(filter_.cleaned_data, request) # print('filter_.cleaned_data: ', filter_.cleaned_data) # # {'tags': ['RBTC9D9DCDQAEASBYBCCKBFA999', '999999999999999999999999999']} def test_pass_compatible_types(self): """ The request contains values that can be converted to the expected types. """ filter_ = self._filter({ 'bundles': [ self.trytes1.encode('ascii'), TransactionHash(self.trytes2), ], 'addresses': [ self.trytes1.encode('ascii'), Address(self.trytes2), ], 'tags': [ self.trytes1.encode('ascii'), Tag(self.trytes3), ], 'approvees': [ self.trytes1.encode('ascii'), TransactionHash(self.trytes3), ], }) print_var_type_n_val( var001=filter_, pointer="#WXCVBFGrtrer12349999") #WXCVBFGrtrer12349999 # Value: # # FindTransactionsRequestFilter(FilterChain(Type(Mapping, allow_subclass=True) | FilterMapper(addresses=FilterChain(Array(Sequence, allow_subclass=True) | FilterRepeater(FilterChain(Required(allow_none=False) | AddressNoChecksum() | Unicode(encoding='ascii')))), approvees=FilterChain(Array(Sequence, allow_subclass=True) | FilterRepeater(FilterChain(Required(allow_none=False) | Trytes() | Unicode(encoding='ascii')))), bundles=FilterChain(Array(Sequence, allow_subclass=True) | FilterRepeater(FilterChain(Required(allow_none=False) | Trytes() | Unicode(encoding='ascii')))), tags=FilterChain(Array(Sequence, allow_subclass=True) | FilterRepeater(FilterChain(Required(allow_none=False) | Trytes() | Unicode(encoding='ascii'))))))) # Type: <class 'filters.handlers.FilterRunner'> self.assertFilterPasses(filter_) # to_find: where is the command above is being created self.assertDictEqual( filter_.cleaned_data, { # Raw trytes are extracted to match the IRI's JSON protocol. 'bundles': [ text_type(TransactionHash(self.trytes1)), text_type(TransactionHash(self.trytes2)), ], 'addresses': [ text_type(Address(self.trytes1)), text_type(Address(self.trytes2)), ], 'tags': [ text_type(Tag(self.trytes1)), text_type(Tag(self.trytes3)), ], 'approvees': [ text_type(TransactionHash(self.trytes1)), text_type(TransactionHash(self.trytes3)), ], }, ) def test_pass_bundles_only(self): """ The request only includes bundles. """ request = { 'bundles': [ TransactionHash(self.trytes1), TransactionHash(self.trytes2), ], } filter_ = self._filter(request) print_var_type_n_val(var001=filter_, pointer="#5555ttyhgffbbvcvbaazezZZZSSS" ) #5555ttyhgffbbvcvbaazezZZZSSS # Value: # # FindTransactionsRequestFilter(FilterChain(Type(Mapping, allow_subclass=True) | FilterMapper(addresses=FilterChain(Array(Sequence, allow_subclass=True) | FilterRepeater(FilterChain(Required(allow_none=False) | AddressNoChecksum() | Unicode(encoding='ascii')))), approvees=FilterChain(Array(Sequence, allow_subclass=True) | FilterRepeater(FilterChain(Required(allow_none=False) | Trytes() | Unicode(encoding='ascii')))), bundles=FilterChain(Array(Sequence, allow_subclass=True) | FilterRepeater(FilterChain(Required(allow_none=False) | Trytes() | Unicode(encoding='ascii')))), tags=FilterChain(Array(Sequence, allow_subclass=True) | FilterRepeater(FilterChain(Required(allow_none=False) | Trytes() | Unicode(encoding='ascii'))))))) # Type: <class 'filters.handlers.FilterRunner'> self.assertFilterPasses(filter_) print_var_type_n_val( var001=text_type(TransactionHash(self.trytes1)), pointer="#4543ERTGF555666aaaqsCE") #4543ERTGF555666aaaqsCE # Value: RBTC9D9DCDQAEASBYBCCKBFA999999999999999999999999999999999999999999999999999999999 # Type: <class 'str'> print_var_type_n_val(var001=TransactionHash(self.trytes1), pointer="#XCEDFGtrefg654") #XCEDFGtrefg654 # Value: RBTC9D9DCDQAEASBYBCCKBFA999999999999999999999999999999999999999999999999999999999 # Type: <class 'iota.transaction.types.TransactionHash'> print_var_type_n_val(var001=self.trytes1, pointer="#XCVDFFERRRTdd4544") #XCVDFFERRRTdd4544 # Value: RBTC9D9DCDQAEASBYBCCKBFA # Type: <class 'str'> self.assertDictEqual( filter_.cleaned_data, { 'bundles': [ text_type(TransactionHash(self.trytes1)), text_type(TransactionHash(self.trytes2)), ], # Null criteria are not included in the request. # https://github.com/iotaledger/iota.lib.py/issues/96 # 'addresses': [], # 'approvees': [], # 'tags': [], }, ) def test_pass_addresses_only(self): """ The request only includes addresses. """ request = { 'addresses': [ Address(self.trytes1), # print("type(Address(self.trytes1)): ", type(Address(self.trytes1))) # # <class 'iota.types.Address'> # print('Address(self.trytes1): ', Address(self.trytes1)) # # RBTC9D9DCDQAEASBYBCCKBFA999999999999999999999999999999999999999999999999999999999 Address(self.trytes2), ], } filter_ = self._filter(request) self.assertFilterPasses(filter_) self.assertDictEqual( filter_.cleaned_data, { 'addresses': [ text_type(Address(self.trytes1)), # print("type(Address(self.trytes1)): ", type(Address(self.trytes1))) # # <class 'iota.types.Address'> # print('Address(self.trytes1): ', Address(self.trytes1)) # # RBTC9D9DCDQAEASBYBCCKBFA999999999999999999999999999999999999999999999999999999999 text_type(Address(self.trytes2)), ], # Null criteria are not included in the request. # https://github.com/iotaledger/iota.lib.py/issues/96 # 'approvees': [], # 'bundles': [], # 'tags': [], }, ) def test_pass_tags_only(self): """ The request only includes tags. """ # print("type(Tag(self.trytes1)): ", type(Tag(self.trytes1))) # # <class 'iota.types.Tag'> # print('Tag(self.trytes1): ', Tag(self.trytes1)) # # RBTC9D9DCDQAEASBYBCCKBFA999 request = { 'tags': [ Tag(self.trytes1), Tag(self.trytes3), ], } filter_ = self._filter(request) # print('filter_.cleaned_data: ', filter_.cleaned_data) # # {'tags': ['RBTC9D9DCDQAEASBYBCCKBFA999', '999999999999999999999999999']} self.assertFilterPasses(filter_) self.assertDictEqual( filter_.cleaned_data, { 'tags': [ text_type(Tag(self.trytes1)), text_type(Tag(self.trytes3)), ], # Null criteria are not included in the request. # https://github.com/iotaledger/iota.lib.py/issues/96 # 'addresses': [], # 'approvees': [], # 'bundles': [], }, ) def test_pass_approvees_only(self): """ The request only includes approvees. """ request = { 'approvees': [ TransactionHash(self.trytes1), TransactionHash(self.trytes3), ], } filter_ = self._filter(request) self.assertFilterPasses(filter_) self.assertDictEqual( filter_.cleaned_data, { 'approvees': [ text_type(TransactionHash(self.trytes1)), text_type(TransactionHash(self.trytes3)), ], # Null criteria are not included in the request. # https://github.com/iotaledger/iota.lib.py/issues/96 # 'addresses': [], # 'bundles': [], # 'tags': [], }, ) def test_fail_empty(self): """ The request does not contain any parameters. """ self.assertFilterErrors( {}, { '': [FindTransactionsRequestFilter.CODE_NO_SEARCH_VALUES], }, ) def test_fail_all_parameters_null(self): """ The request contains all parameters, but every one is null. """ self.assertFilterErrors( { 'addresses': None, 'approvees': None, 'bundles': None, 'tags': None, }, { '': [FindTransactionsRequestFilter.CODE_NO_SEARCH_VALUES], }, ) def test_success_all_parameters_empty(self): """ All of the parameters are empty lists. This is technically valid, though probably not very useful. """ self.assertFilterPasses( { 'addresses': [], 'approvees': [], 'bundles': [], 'tags': [], }, ) def test_fail_unexpected_parameters(self): """ The request contains unexpected parameters. """ self.assertFilterErrors( { 'addresses': [Address(self.trytes1)], 'approvees': [TransactionHash(self.trytes1)], 'bundles': [TransactionHash(self.trytes1)], 'tags': [Tag(self.trytes1)], # Hey, you're not allowed in he-argh! 'foo': 'bar', }, { 'foo': [f.FilterMapper.CODE_EXTRA_KEY], }, ) def test_fail_bundles_wrong_type(self): """ ``bundles`` is not an array. """ self.assertFilterErrors( { 'bundles': TransactionHash(self.trytes1), }, { 'bundles': [f.Type.CODE_WRONG_TYPE], }, ) def test_fail_bundles_contents_invalid(self): """ ``bundles`` is an array, but it contains invalid values. """ self.assertFilterErrors( { 'bundles': [ b'', True, None, b'not valid trytes', # This is actually valid; I just added it to make sure the # filter isn't cheating! TryteString(self.trytes2), 2130706433, b'9' * 82, ], }, { 'bundles.0': [f.Required.CODE_EMPTY], 'bundles.1': [f.Type.CODE_WRONG_TYPE], 'bundles.2': [f.Required.CODE_EMPTY], 'bundles.3': [Trytes.CODE_NOT_TRYTES], 'bundles.5': [f.Type.CODE_WRONG_TYPE], 'bundles.6': [Trytes.CODE_WRONG_FORMAT], }, ) def test_fail_addresses_wrong_type(self): """ ``addresses`` is not an array. """ self.assertFilterErrors( { 'addresses': Address(self.trytes1), }, { 'addresses': [f.Type.CODE_WRONG_TYPE], }, ) def test_fail_addresses_contents_invalid(self): """ ``addresses`` is an array, but it contains invalid values. """ self.assertFilterErrors( { 'addresses': [ b'', True, None, b'not valid trytes', # This is actually valid; I just added it to make sure the # filter isn't cheating! TryteString(self.trytes2), 2130706433, b'9' * 82, ], }, { 'addresses.0': [f.Required.CODE_EMPTY], 'addresses.1': [f.Type.CODE_WRONG_TYPE], 'addresses.2': [f.Required.CODE_EMPTY], 'addresses.3': [Trytes.CODE_NOT_TRYTES], 'addresses.5': [f.Type.CODE_WRONG_TYPE], 'addresses.6': [Trytes.CODE_WRONG_FORMAT], }, ) def test_fail_tags_wrong_type(self): """ ``tags`` is not an array. """ self.assertFilterErrors( { 'tags': Tag(self.trytes1), }, { 'tags': [f.Type.CODE_WRONG_TYPE], }, ) def test_fail_tags_contents_invalid(self): """ ``tags`` is an array, but it contains invalid values. """ self.assertFilterErrors( { 'tags': [ b'', True, None, b'not valid trytes', # This is actually valid; I just added it to make sure the # filter isn't cheating! TryteString(self.trytes1), 2130706433, b'9' * 28, ], }, { 'tags.0': [f.Required.CODE_EMPTY], 'tags.1': [f.Type.CODE_WRONG_TYPE], 'tags.2': [f.Required.CODE_EMPTY], 'tags.3': [Trytes.CODE_NOT_TRYTES], 'tags.5': [f.Type.CODE_WRONG_TYPE], 'tags.6': [Trytes.CODE_WRONG_FORMAT], }, ) def test_fail_approvees_wrong_type(self): """ ``approvees`` is not an array. """ self.assertFilterErrors( { 'approvees': TransactionHash(self.trytes1), }, { 'approvees': [f.Type.CODE_WRONG_TYPE], }, ) def test_fail_approvees_contents_invalid(self): """ ``approvees`` is an array, but it contains invalid values. """ self.assertFilterErrors( { 'approvees': [ b'', True, None, b'not valid trytes', # This is actually valid; I just added it to make sure the # filter isn't cheating! TryteString(self.trytes2), 2130706433, b'9' * 82, ], }, { 'approvees.0': [f.Required.CODE_EMPTY], 'approvees.1': [f.Type.CODE_WRONG_TYPE], 'approvees.2': [f.Required.CODE_EMPTY], 'approvees.3': [Trytes.CODE_NOT_TRYTES], 'approvees.5': [f.Type.CODE_WRONG_TYPE], 'approvees.6': [Trytes.CODE_WRONG_FORMAT], }, )
class FindTransactionsRequestFilterTestCase(BaseFilterTestCase): filter_type = FindTransactionsCommand(MockAdapter()).get_request_filter skip_value_check = True # noinspection SpellCheckingInspection def setUp(self): super(FindTransactionsRequestFilterTestCase, self).setUp() # Define a few valid values that we can reuse across tests. self.trytes1 = b'RBTC9D9DCDQAEASBYBCCKBFA' self.trytes2 =\ b'CCPCBDVC9DTCEAKDXC9D9DEARCWCPCBDVCTCEAHDWCTCEAKDCDFD9DSCSA' self.trytes3 = b'999999999999999999999999999' def test_pass_all_parameters(self): """ The request contains valid values for all parameters. """ request = { 'bundles': [ TransactionHash(self.trytes1), TransactionHash(self.trytes2), ], 'addresses': [ Address(self.trytes1), Address(self.trytes2), ], 'tags': [ Tag(self.trytes1), Tag(self.trytes3), ], 'approvees': [ TransactionHash(self.trytes1), TransactionHash(self.trytes3), ], } filter_ = self._filter(request) self.assertFilterPasses(filter_) self.assertDictEqual(filter_.cleaned_data, request) def test_pass_compatible_types(self): """ The request contains values that can be converted to the expected types. """ filter_ = self._filter({ 'bundles': [ binary_type(self.trytes1), bytearray(self.trytes2), ], 'addresses': [ binary_type(self.trytes1), bytearray(self.trytes2), ], 'tags': [ binary_type(self.trytes1), bytearray(self.trytes3), ], 'approvees': [ binary_type(self.trytes1), bytearray(self.trytes3), ], }) self.assertFilterPasses(filter_) self.assertDictEqual( filter_.cleaned_data, { 'bundles': [ TransactionHash(self.trytes1), TransactionHash(self.trytes2), ], 'addresses': [ Address(self.trytes1), Address(self.trytes2), ], 'tags': [ Tag(self.trytes1), Tag(self.trytes3), ], 'approvees': [ TransactionHash(self.trytes1), TransactionHash(self.trytes3), ], }, ) def test_pass_bundles_only(self): """ The request only includes bundles. """ request = { 'bundles': [ TransactionHash(self.trytes1), TransactionHash(self.trytes2), ], } filter_ = self._filter(request) self.assertFilterPasses(filter_) self.assertDictEqual( filter_.cleaned_data, { 'bundles': [ TransactionHash(self.trytes1), TransactionHash(self.trytes2), ], 'addresses': [], 'approvees': [], 'tags': [], }, ) def test_pass_addresses_only(self): """ The request only includes addresses. """ request = { 'addresses': [ Address(self.trytes1), Address(self.trytes2), ], } filter_ = self._filter(request) self.assertFilterPasses(filter_) self.assertDictEqual( filter_.cleaned_data, { 'addresses': [ Address(self.trytes1), Address(self.trytes2), ], 'approvees': [], 'bundles': [], 'tags': [], }, ) def test_pass_tags_only(self): """ The request only includes tags. """ request = { 'tags': [ Tag(self.trytes1), Tag(self.trytes3), ], } filter_ = self._filter(request) self.assertFilterPasses(filter_) self.assertDictEqual( filter_.cleaned_data, { 'tags': [ Tag(self.trytes1), Tag(self.trytes3), ], 'addresses': [], 'approvees': [], 'bundles': [], }, ) def test_pass_approvees_only(self): """ The request only includes approvees. """ request = { 'approvees': [ TransactionHash(self.trytes1), TransactionHash(self.trytes3), ], } filter_ = self._filter(request) self.assertFilterPasses(filter_) self.assertDictEqual( filter_.cleaned_data, { 'approvees': [ TransactionHash(self.trytes1), TransactionHash(self.trytes3), ], 'addresses': [], 'bundles': [], 'tags': [], }, ) def test_fail_empty(self): """ The request does not contain any parameters. """ self.assertFilterErrors( {}, { '': [FindTransactionsRequestFilter.CODE_NO_SEARCH_VALUES], }, ) def test_fail_all_parameters_empty(self): """ The request contains all parameters, but every one is empty. """ self.assertFilterErrors( { 'addresses': [], 'approvees': [], 'bundles': [], 'tags': [], }, { '': [FindTransactionsRequestFilter.CODE_NO_SEARCH_VALUES], }, ) def test_fail_unexpected_parameters(self): """ The request contains unexpected parameters. """ self.assertFilterErrors( { 'addresses': [Address(self.trytes1)], 'approvees': [TransactionHash(self.trytes1)], 'bundles': [TransactionHash(self.trytes1)], 'tags': [Tag(self.trytes1)], # Hey, you're not allowed in he-argh! 'foo': 'bar', }, { 'foo': [f.FilterMapper.CODE_EXTRA_KEY], }, ) def test_fail_bundles_wrong_type(self): """ ``bundles`` is not an array. """ self.assertFilterErrors( { 'bundles': TransactionHash(self.trytes1), }, { 'bundles': [f.Type.CODE_WRONG_TYPE], }, ) def test_fail_bundles_contents_invalid(self): """ ``bundles`` is an array, but it contains invalid values. """ self.assertFilterErrors( { 'bundles': [ b'', text_type(self.trytes1, 'ascii'), True, None, b'not valid trytes', # This is actually valid; I just added it to make sure the # filter isn't cheating! TryteString(self.trytes2), 2130706433, b'9' * 82, ], }, { 'bundles.0': [f.Required.CODE_EMPTY], 'bundles.1': [f.Type.CODE_WRONG_TYPE], 'bundles.2': [f.Type.CODE_WRONG_TYPE], 'bundles.3': [f.Required.CODE_EMPTY], 'bundles.4': [Trytes.CODE_NOT_TRYTES], 'bundles.6': [f.Type.CODE_WRONG_TYPE], 'bundles.7': [Trytes.CODE_WRONG_FORMAT], }, ) def test_fail_addresses_wrong_type(self): """ ``addresses`` is not an array. """ self.assertFilterErrors( { 'addresses': Address(self.trytes1), }, { 'addresses': [f.Type.CODE_WRONG_TYPE], }, ) def test_fail_addresses_contents_invalid(self): """ ``addresses`` is an array, but it contains invalid values. """ self.assertFilterErrors( { 'addresses': [ b'', text_type(self.trytes1, 'ascii'), True, None, b'not valid trytes', # This is actually valid; I just added it to make sure the # filter isn't cheating! TryteString(self.trytes2), 2130706433, b'9' * 82, ], }, { 'addresses.0': [f.Required.CODE_EMPTY], 'addresses.1': [f.Type.CODE_WRONG_TYPE], 'addresses.2': [f.Type.CODE_WRONG_TYPE], 'addresses.3': [f.Required.CODE_EMPTY], 'addresses.4': [Trytes.CODE_NOT_TRYTES], 'addresses.6': [f.Type.CODE_WRONG_TYPE], 'addresses.7': [Trytes.CODE_WRONG_FORMAT], }, ) def test_fail_tags_wrong_type(self): """ ``tags`` is not an array. """ self.assertFilterErrors( { 'tags': Tag(self.trytes1), }, { 'tags': [f.Type.CODE_WRONG_TYPE], }, ) def test_fail_tags_contents_invalid(self): """ ``tags`` is an array, but it contains invalid values. """ self.assertFilterErrors( { 'tags': [ b'', text_type(self.trytes1, 'ascii'), True, None, b'not valid trytes', # This is actually valid; I just added it to make sure the # filter isn't cheating! TryteString(self.trytes1), 2130706433, b'9' * 28, ], }, { 'tags.0': [f.Required.CODE_EMPTY], 'tags.1': [f.Type.CODE_WRONG_TYPE], 'tags.2': [f.Type.CODE_WRONG_TYPE], 'tags.3': [f.Required.CODE_EMPTY], 'tags.4': [Trytes.CODE_NOT_TRYTES], 'tags.6': [f.Type.CODE_WRONG_TYPE], 'tags.7': [Trytes.CODE_WRONG_FORMAT], }, ) def test_fail_approvees_wrong_type(self): """ ``approvees`` is not an array. """ self.assertFilterErrors( { 'approvees': TransactionHash(self.trytes1), }, { 'approvees': [f.Type.CODE_WRONG_TYPE], }, ) def test_fail_approvees_contents_invalid(self): """ ``approvees`` is an array, but it contains invalid values. """ self.assertFilterErrors( { 'approvees': [ b'', text_type(self.trytes1, 'ascii'), True, None, b'not valid trytes', # This is actually valid; I just added it to make sure the # filter isn't cheating! TryteString(self.trytes2), 2130706433, b'9' * 82, ], }, { 'approvees.0': [f.Required.CODE_EMPTY], 'approvees.1': [f.Type.CODE_WRONG_TYPE], 'approvees.2': [f.Type.CODE_WRONG_TYPE], 'approvees.3': [f.Required.CODE_EMPTY], 'approvees.4': [Trytes.CODE_NOT_TRYTES], 'approvees.6': [f.Type.CODE_WRONG_TYPE], 'approvees.7': [Trytes.CODE_WRONG_FORMAT], }, )