def setUp(self):
        super(GetAccountDataCommandTestCase, self).setUp()

        self.adapter = MockAdapter()
        self.command = GetAccountDataCommand(self.adapter)

        # Define some tryte sequences we can re-use between tests.
        self.addy1 =\
          Address(
            b'TESTVALUEONE9DONTUSEINPRODUCTION99999YDZ'
            b'E9TAFAJGJA9CECKDAEPHBICDR9LHFCOFRBQDHC9IG',

            key_index = 0,
          )

        self.addy2 =\
          Address(
            b'TESTVALUETWO9DONTUSEINPRODUCTION99999TES'
            b'GINEIDLEEHRAOGEBMDLENFDAFCHEIHZ9EBZDD9YHL',

            key_index = 1,
          )

        self.hash1 =\
          TransactionHash(
            b'TESTVALUE9DONTUSEINPRODUCTION99999O99IDB'
            b'MBPAPDXBSDWAMHV9DASEGCOGHBV9VAF9UGRHFDPFJ'
          )

        self.hash2 =\
          TransactionHash(
            b'TESTVALUE9DONTUSEINPRODUCTION99999OCNCHC'
            b'TEPBHEPBJEWFXERHSCQCH9TAAANDBBCCHCIDEAVBV'
          )
    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_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,
            },
        )
    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_fail_trytes_contents_invalid(self):
        """
    ``trytes`` is an array, but it contains invalid values.
    """
        self.assertFilterErrors(
            {
                'trytes': [
                    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' * (TransactionTrytes.LEN + 1),
                ],
                'branchTransaction':
                TransactionHash(self.txn_id),
                'minWeightMagnitude':
                13,
                'trunkTransaction':
                TransactionHash(self.txn_id),
            },
            {
                'trytes.0': [f.NotEmpty.CODE_EMPTY],
                'trytes.1': [f.Type.CODE_WRONG_TYPE],
                'trytes.2': [f.Required.CODE_EMPTY],
                'trytes.3': [Trytes.CODE_NOT_TRYTES],
                'trytes.5': [f.Type.CODE_WRONG_TYPE],
                'trytes.6': [Trytes.CODE_WRONG_FORMAT],
            },
        )
예제 #6
0
 def test_fail_tips_wrong_type(self):
     """
 ``tips`` is not an array.
 """
     self.assertFilterErrors(
         {
             'tips': TransactionHash(self.trytes2),
             'transactions': [TransactionHash(self.trytes1)],
         },
         {
             'tips': [f.Type.CODE_WRONG_TYPE],
         },
     )
    def test_pass_compatible_types(self):
        """
    Incoming values can be converted into the expected types.
    """
        filter_ = self._filter({
            # Any value that can be converted into an ASCII representation of
            # a TransactionHash is valid here.
            'trunkTransaction':
            TransactionHash(self.txn_id),
            'branchTransaction':
            bytearray(self.txn_id.encode('ascii')),
            'trytes': [
                # ``trytes`` can contain any value that can be converted into a
                # TryteString.
                binary_type(TransactionTrytes(self.trytes1)),

                # This is probably wrong (s/b :py:class:`TransactionTrytes`),
                # but technically it's valid.
                TransactionHash(
                    b'CCPCBDVC9DTCEAKDXC9D9DEARCWCPCBDVCTCEAHDWCTCEAKDCDFD9DSCSA',
                ),
            ],

            # This still has to be an int, however.
            'minWeightMagnitude':
            30,
        })

        self.assertFilterPasses(filter_)
        self.assertDictEqual(
            filter_.cleaned_data,

            # After running through the filter, all of the values have been
            # converted to the correct types.
            {
                'trunkTransaction':
                self.txn_id,
                'branchTransaction':
                self.txn_id,
                'minWeightMagnitude':
                30,
                'trytes': [
                    text_type(TransactionTrytes(self.trytes1)),
                    text_type(
                        TransactionTrytes(
                            b'CCPCBDVC9DTCEAKDXC9D9DEARCWCPCBDVCTCEAHD'
                            b'WCTCEAKDCDFD9DSCSA99999999999999999999999', )),
                ],
            })
 def test_fail_min_weight_magnitude_null(self):
     """
 ``minWeightMagnitude`` is null.
 """
     self.assertFilterErrors(
         {
             'minWeightMagnitude': None,
             'branchTransaction': TransactionHash(self.txn_id),
             'trunkTransaction': TransactionHash(self.txn_id),
             'trytes': [TryteString(self.trytes1)],
         },
         {
             'minWeightMagnitude': [f.Required.CODE_EMPTY],
         },
     )
 def test_fail_min_weight_magnitude_too_small(self):
     """
 ``minWeightMagnitude`` is less than 1.
 """
     self.assertFilterErrors(
         {
             'minWeightMagnitude': 0,
             'branchTransaction': TransactionHash(self.txn_id),
             'trunkTransaction': TransactionHash(self.txn_id),
             'trytes': [TryteString(self.trytes1)],
         },
         {
             'minWeightMagnitude': [f.Min.CODE_TOO_SMALL],
         },
     )
 def test_fail_trytes_null(self):
     """
 ``trytes`` is null.
 """
     self.assertFilterErrors(
         {
             'trytes': None,
             'branchTransaction': TransactionHash(self.txn_id),
             'minWeightMagnitude': 13,
             'trunkTransaction': TransactionHash(self.txn_id),
         },
         {
             'trytes': [f.Required.CODE_EMPTY],
         },
     )
예제 #11
0
  def test_non_tail_transaction(self):
    """
    Trying to get a bundle for a non-tail transaction.

    This is not valid; you have to start with a tail transaction.
    """
    self.adapter.seed_response('getTrytes', {
      'trytes': [
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999999999999999999999999999999999999999999999999999999999999'
        b'999999999WUQXEGBVIECGIWO9IGSYKWWPYCIVUJJGSJPWGIAFJPYSF9NSQOHWAHS9P'
        b'9PWQHOBXNNQIF9IRHVQXKPZW999999999999999999999999999999999999999999'
        b'999999999999HNLFMVD99A99999999A99999999PDQWLVVDPUU9VIBODGMRIAZPGQX'
        b'DOGSEXIHKIBWSLDAWUKZCZMK9Z9YZSPCKBDJSVDPRQLJSTKUMTNVSXBGUEHHGAIWWQ'
        b'BCJZHZAQOWZMAIDAFUZBVMUVPWQJLUGGQKNKLMGTWXXNZKUCBJLEDAMYVRGABAWBY9'
        b'999MYIYBTGIOQYYZFJBLIAWMPSZEFFTXUZPCDIXSLLQDQSFYGQSQOGSPKCZNLVSZ9L'
        b'MCUWVNGEN9EJEW9999XZUIENOTTBKJMDPRXWGQYG9PWGTXUO9AXMP9FLMDRMADLRPW'
        b'CZCJBROYCDRJMYU9HDYJM9NDBFUPIZVTR'
      ],
    })

    with self.assertRaises(BadApiResponse):
      self.command(
        transaction =
          TransactionHash(
            b'FSEWUNJOEGNUI9QOCRFMYSIFAZLJHKZBPQZZYFG9'
            b'ORYCRDX9TOMJPFCRB9R9KPUUGFPVOWYXFIWEW9999'
          ),
      )
 def test_fail_min_weight_magnitude_string(self):
     """
 ``minWeightMagnitude`` is a string.
 """
     self.assertFilterErrors(
         {
             # For want of an int cast, the transaction was lost.
             'minWeightMagnitude': '20',
             'branchTransaction': TransactionHash(self.txn_id),
             'trunkTransaction': TransactionHash(self.txn_id),
             'trytes': [TryteString(self.trytes1)],
         },
         {
             'minWeightMagnitude': [f.Type.CODE_WRONG_TYPE],
         },
     )
예제 #13
0
    def test_fail_tips_contents_invalid(self):
        """
    ``tips`` contains invalid values.
    """
        self.assertFilterErrors(
            {
                'tips': [
                    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' * 82,
                ],
                'transactions': [TransactionHash(self.trytes1)],
            },
            {
                'tips.0': [f.Required.CODE_EMPTY],
                'tips.1': [f.Type.CODE_WRONG_TYPE],
                'tips.2': [f.Required.CODE_EMPTY],
                'tips.3': [Trytes.CODE_NOT_TRYTES],
                'tips.5': [f.Type.CODE_WRONG_TYPE],
                'tips.6': [Trytes.CODE_WRONG_FORMAT],
            },
        )
 def test_fail_min_weight_magnitude_float(self):
     """
 ``minWeightMagnitude`` is a float.
 """
     self.assertFilterErrors(
         {
             # I don't care if the fpart is empty; it's still not an int!
             'minWeightMagnitude': 20.0,
             'branchTransaction': TransactionHash(self.txn_id),
             'trunkTransaction': TransactionHash(self.txn_id),
             'trytes': [TryteString(self.trytes1)],
         },
         {
             'minWeightMagnitude': [f.Type.CODE_WRONG_TYPE],
         },
     )
    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_fail_trytes_wrong_type(self):
     """
 ``trytes`` is not an array.
 """
     self.assertFilterErrors(
         {
             # You have to specify an array, even if you only want to attach
             # a single tryte sequence.
             'trytes': TryteString(self.trytes1),
             'branchTransaction': TransactionHash(self.txn_id),
             'minWeightMagnitude': 13,
             'trunkTransaction': TransactionHash(self.txn_id),
         },
         {
             'trytes': [f.Type.CODE_WRONG_TYPE],
         },
     )
예제 #17
0
 def test_init_error_too_long(self):
     """
 Attempting to create a transaction hash longer than 81 trytes.
 """
     with self.assertRaises(ValueError):
         # noinspection SpellCheckingInspection
         TransactionHash(b'JVMTDGDPDFYHMZPMWEKKANBQSLSDTIIHAYQUMZOK'
                         b'HXXXGJHJDQPOMDOMNRDKYCZRUFZROZDADTHZC99999')
 def test_fail_trytes_empty(self):
     """
 ``trytes`` is an array, but it's empty.
 """
     self.assertFilterErrors(
         {
             # Ok, you got the list part down, but you have to put something
             # inside it.
             'trytes': [],
             'branchTransaction': TransactionHash(self.txn_id),
             'minWeightMagnitude': 13,
             'trunkTransaction': TransactionHash(self.txn_id),
         },
         {
             'trytes': [f.Required.CODE_EMPTY],
         },
     )
    def test_fail_unexpected_parameters(self):
        """
    The incoming request contains unexpected parameters.
    """
        self.assertFilterErrors(
            {
                'branchTransaction': TransactionHash(self.txn_id),
                'minWeightMagnitude': 20,
                'trunkTransaction': TransactionHash(self.txn_id),
                'trytes': [TryteString(self.trytes1)],

                # Hey, how'd that get in there?
                'foo': 'bar',
            },
            {
                'foo': [f.FilterMapper.CODE_EXTRA_KEY],
            },
        )
 def test_fail_approvees_wrong_type(self):
     """
 ``approvees`` is not an array.
 """
     self.assertFilterErrors(
         {
             'approvees': TransactionHash(self.trytes1),
         },
         {
             'approvees': [f.Type.CODE_WRONG_TYPE],
         },
     )
예제 #21
0
    def test_start(self):
        """
    Using ``start`` to offset the key range.
    """
        self.adapter.seed_response('getBalances', {
            'balances': [86],
        })

        # ``getInputs`` uses ``findTransactions`` to identify unused
        # addresses.
        # noinspection SpellCheckingInspection
        self.adapter.seed_response(
            'findTransactions', {
                'hashes': [
                    TransactionHash(
                        b'TESTVALUE9DONTUSEINPRODUCTION99999YFXGOD'
                        b'GISBJAX9PDJIRDMDV9DCRDCAEG9FN9KECCBDDFZ9H'),
                ],
            })

        self.adapter.seed_response('findTransactions', {
            'hashes': [],
        })

        # To keep the unit test nice and speedy, we will mock the address
        # generator.  We already have plenty of unit tests for that
        # functionality, so we can get away with mocking it here.
        # noinspection PyUnusedLocal
        def mock_address_generator(ag, start, step=1):
            # If ``start`` has the wrong value, return garbage to make the
            # test asplode.
            for addy in [None, self.addy1, self.addy2][start::step]:
                yield addy

        # When ``stop`` is None, the command uses a generator internally.
        with mock.patch(
                'iota_async.crypto.addresses.AddressGenerator.create_iterator',
                mock_address_generator,
        ):
            response = self.command(
                seed=Seed.random(),
                start=1,
            )

        self.assertEqual(response['totalBalance'], 86)
        self.assertEqual(len(response['inputs']), 1)

        input0 = response['inputs'][0]
        self.assertIsInstance(input0, Address)

        self.assertEqual(input0, self.addy1)
        self.assertEqual(input0.balance, 86)
        self.assertEqual(input0.key_index, 1)
예제 #22
0
    def setUp(self):
        super(PromoteTransactionCommandTestCase, self).setUp()

        self.adapter = MockAdapter()
        self.command = PromoteTransactionCommand(self.adapter)

        self.trytes1 = b'RBTC9D9DCDQAEASBYBCCKBFA'
        self.trytes2 =\
          b'CCPCBDVC9DTCEAKDXC9D9DEARCWCPCBDVCTCEAHDWCTCEAKDCDFD9DSCSA'

        self.hash1 = TransactionHash(
            b'TESTVALUE9DONTUSEINPRODUCTION99999TBPDM9'
            b'ADFAWCKCSFUALFGETFIFG9UHIEFE9AYESEHDUBDDF')
  def test_pass_happy_path_with_reference(self):
    """
    Request is valid with reference.
    """
    request = {
      'depth': 100,
      'reference': TransactionHash(self.trytes1),
    }

    filter_ = self._filter(request)

    self.assertFilterPasses(filter_)
    self.assertDictEqual(filter_.cleaned_data, request)
    def test_pass_happy_path(self):
        """
    The incoming request is valid.
    """
        request = {
            'trunkTransaction':
            text_type(TransactionHash(self.txn_id)),
            'branchTransaction':
            text_type(TransactionHash(self.txn_id)),
            'minWeightMagnitude':
            20,
            'trytes': [
                # Raw trytes are extracted to match the IRI's JSON protocol.
                text_type(TransactionTrytes(self.trytes1)),
                text_type(TransactionTrytes(self.trytes2)),
            ],
        }

        filter_ = self._filter(request)

        self.assertFilterPasses(filter_)
        self.assertDictEqual(filter_.cleaned_data, request)
  def test_pass_happy_path(self):
    """
    Typical ``getTransactionsToApprove`` response.
    """
    response = {
      'trunkTransaction':
        'TKGDZ9GEI9CPNQGHEATIISAKYPPPSXVCXBSR9EIW'
        'CTHHSSEQCD9YLDPEXYERCNJVASRGWMAVKFQTC9999',

      'branchTransaction':
        'TKGDZ9GEI9CPNQGHEATIISAKYPPPSXVCXBSR9EIW'
        'CTHHSSEQCD9YLDPEXYERCNJVASRGWMAVKFQTC9999',

      'duration': 936,
    }

    filter_ = self._filter(response)

    self.assertFilterPasses(filter_)
    self.assertDictEqual(
      filter_.cleaned_data,

      {
        'trunkTransaction':
          TransactionHash(
            b'TKGDZ9GEI9CPNQGHEATIISAKYPPPSXVCXBSR9EIW'
            b'CTHHSSEQCD9YLDPEXYERCNJVASRGWMAVKFQTC9999'
          ),

        'branchTransaction':
          TransactionHash(
            b'TKGDZ9GEI9CPNQGHEATIISAKYPPPSXVCXBSR9EIW'
            b'CTHHSSEQCD9YLDPEXYERCNJVASRGWMAVKFQTC9999'
          ),

        'duration': 936,
      },
    )
예제 #26
0
 def test_fail_min_weight_magnitude_too_small(self):
     """
 ``minWeightMagnitude`` is < 1.
 """
     self.assertFilterErrors(
         {
             'minWeightMagnitude': 0,
             'depth': 100,
             'transaction': TransactionHash(self.trytes1),
         },
         {
             'minWeightMagnitude': [f.Min.CODE_TOO_SMALL],
         },
     )
예제 #27
0
 def test_fail_hashes_wrong_type(self):
     """
 ``hashes`` is not an array.
 """
     self.assertFilterErrors(
         {
             # ``hashes`` must be an array, even if we're only querying
             # against a single transaction.
             'hashes': TransactionHash(self.trytes1),
         },
         {
             'hashes': [f.Type.CODE_WRONG_TYPE],
         },
     )
예제 #28
0
    def test_pass_happy_path(self):
        """
    Request is valid.
    """
        request = {
            'depth': 100,
            'minWeightMagnitude': 18,
            'transaction': TransactionHash(self.trytes1),
        }

        filter_ = self._filter(request)

        self.assertFilterPasses(filter_)
        self.assertDictEqual(filter_.cleaned_data, request)
  def test_fail_hashes_wrong_type(self):
    """
    ``hashes`` is not an array.
    """
    self.assertFilterErrors(
      {
        # It's gotta be an array, even if there's only one hash.
        'hashes': TransactionHash(self.hash1),
      },

      {
        'hashes': [f.Type.CODE_WRONG_TYPE],
      },
    )
예제 #30
0
 def test_fail_transactions_wrong_type(self):
     """
 ``transactions`` is not an array.
 """
     self.assertFilterErrors(
         {
             # Has to be an array, even if we're only querying for one
             # transaction.
             'transactions': TransactionHash(self.trytes1),
         },
         {
             'transactions': [f.Type.CODE_WRONG_TYPE],
         },
     )