Esempio n. 1
0
    def test_get_metrics(self, mocker, blockchain_sync, processor, db_session,
                         persistence_module: SQLPersistenceInterface):
        # Generate dummy activity for metrics
        tf1 = blockchain_sync.add_transaction_filter(
            '0x000090c5a236130E5D51260A2A5Bfde834C694b6', self.contract_type,
            self.filter_parameters, self.filter_type, self.decimals,
            self.block_epoch).id

        tf2 = blockchain_sync.add_transaction_filter(
            '0x000090c5a236130E5D51260A2A5Bfde844C694b6', self.contract_type,
            self.filter_parameters, self.filter_type, self.decimals,
            self.block_epoch).id

        success_tx = BlockchainTransaction(
            _status='PENDING',
            block=10,
            hash='0x4444444444444444444444444',
            contract_address=self.contract_address,
            is_synchronized_with_app=False,
            recipient_address='0x3333333333333333333333333',
            sender_address='0x2222222222222222222222222',
            amount=10,
            is_third_party_transaction=True)
        db_session.add(success_tx)

        fail_tx = BlockchainTransaction(
            _status='PENDING',
            block=10,
            hash='0x4444444444444444444444445',
            contract_address=self.contract_address,
            is_synchronized_with_app=True,
            recipient_address='0x3333333333333333333333334',
            sender_address='0x2222222222222222222222223',
            amount=10,
            is_third_party_transaction=True)
        db_session.add(fail_tx)

        expected_resp = {
            'unsynchronized_transaction_count': {
                '0x468F90c5a236130E5D51260A2A5Bfde834C694b6': 1
            },
            'synchronized_transaction_count': {
                '0x468F90c5a236130E5D51260A2A5Bfde834C694b6': 1
            },
            'last_time_synchronized': None
        }
        # Check base metrics
        resp = blockchain_sync.get_metrics()
        resp['last_time_synchronized'] = None
        assert resp == expected_resp

        # Check failed callbacks
        failed_callbacks = blockchain_sync.get_failed_callbacks()
        expected_resp = {
            '0x468F90c5a236130E5D51260A2A5Bfde834C694b6':
            ['0x4444444444444444444444444']
        }
        assert failed_callbacks == expected_resp
Esempio n. 2
0
def second_dummy_transaction(db_session, dummy_task, dummy_wallet):
    from sql_persistence.models import BlockchainTransaction

    txn = BlockchainTransaction(signing_wallet=dummy_wallet)

    txn.task = dummy_task

    db_session.add(txn)
    db_session.commit()

    return txn
Esempio n. 3
0
    def test_transaction_status_propagation(self, db_session):

        task = BlockchainTask(uuid=str_uuid())

        assert task.status == 'UNSTARTED'

        transaction_1 = BlockchainTransaction()
        transaction_1.task = task
        transaction_1.status = 'PENDING'

        assert task.status == 'PENDING'

        transaction_2 = BlockchainTransaction()
        transaction_2.task = task
        transaction_2.status = 'SUCCESS'

        assert task.status == 'SUCCESS'
        assert task.status_code == 1

        db_session.add_all([task, transaction_1, transaction_2])
        db_session.commit()

        # Uses a custom expression so worth testing the filter
        queried_task = db_session.query(BlockchainTask).filter(
            BlockchainTask.status == 'SUCCESS').first()
        assert queried_task == task
Esempio n. 4
0
        def created_nonced_transaction():
            t = BlockchainTransaction(
                first_block_hash=persistence_module.first_block_hash)
            t.signing_wallet = wallet
            db_session.add(t)
            db_session.commit()

            nonce = persistence_module.locked_claim_transaction_nonce(
                network_nonce=starting_nonce,
                signing_wallet_id=wallet.id,
                transaction_id=t.id)

            t.nonce_consumed = True

            return t, nonce
Esempio n. 5
0
    def create_blockchain_transaction(self, task_uuid):

        task = session.query(BlockchainTask).filter_by(uuid=task_uuid).first()

        blockchain_transaction = BlockchainTransaction(
            signing_wallet=task.signing_wallet,
            first_block_hash=self.first_block_hash)

        session.add(blockchain_transaction)

        if task:
            blockchain_transaction.task = task

        session.commit()

        return blockchain_transaction
Esempio n. 6
0
    def test_force_recall_webhook(self, mocker, blockchain_sync, processor,
                                  db_session,
                                  persistence_module: SQLPersistenceInterface):
        fail_tx = BlockchainTransaction(
            _status='PENDING',
            block=10,
            hash='0x4444444444444444444444445',
            contract_address=self.contract_address,
            is_synchronized_with_app=False,
            recipient_address='0x3333333333333333333333334',
            sender_address='0x2222222222222222222222223',
            amount=10,
            is_third_party_transaction=True)
        db_session.add(fail_tx)

        class RequestsResp():
            ok = True

        assert fail_tx.is_synchronized_with_app == False

        def check_correct_webhook_call(transaction):
            assert transaction == fail_tx
            return RequestsResp()

        mocker.patch.object(blockchain_sync, 'call_webhook',
                            check_correct_webhook_call)

        blockchain_sync.force_recall_webhook('0x4444444444444444444444445')

        assert fail_tx.is_synchronized_with_app == True
Esempio n. 7
0
    def _claim_transaction_nonce(
        self,
        network_nonce: int,
        signing_wallet: BlockchainWallet,
        transaction: BlockchainTransaction,
    ) -> int:

        if transaction.nonce is not None:
            return transaction.nonce
        calculated_nonce = self._calculate_nonce(signing_wallet, network_nonce)
        transaction.signing_wallet = signing_wallet
        transaction.nonce = calculated_nonce
        transaction.status = 'PENDING'

        # TODO: can we shift this commit out?
        self.session.commit()

        return calculated_nonce
Esempio n. 8
0
    def create_blockchain_transaction(self, task_uuid):

        task = self.session.query(BlockchainTask).filter_by(
            uuid=task_uuid).first()

        blockchain_transaction = BlockchainTransaction(
            signing_wallet=task.signing_wallet,
            first_block_hash=self.first_block_hash)

        self.session.add(blockchain_transaction)

        if task:
            # TODO: when is this ever not the case?
            # We should just force signing walelt based off the task
            blockchain_transaction.task = task

        self.session.commit()

        return blockchain_transaction
Esempio n. 9
0
    def test_set_transaction_status(self, db_session):

        transaction = BlockchainTransaction()

        assert transaction.status == 'UNKNOWN'
        assert transaction.status_code == 99

        transaction.status = 'PENDING'

        assert transaction.status == 'PENDING'
        assert transaction.status_code == 2

        with pytest.raises(ValueError):
            transaction.status = 'NOT_A_STATUS'

        db_session.add(transaction)
        db_session.commit()

        # Uses a custom expression so worth testing the filter
        queried_transaction = db_session.query(BlockchainTransaction).filter(
            BlockchainTransaction.status_code == 2).first()
        assert queried_transaction == transaction
Esempio n. 10
0
    def test_update_transaction_data(
            self, db_session, persistence_module: SQLPersistenceInterface):
        transaction = BlockchainTransaction()
        db_session.add(transaction)

        db_session.commit()

        persistence_module.update_transaction_data(transaction.id, {
            'status': 'SUCCESS',
            'ignore': True
        })

        assert transaction.status == 'SUCCESS'
        assert transaction.ignore is True
Esempio n. 11
0
 def create_external_transaction(self, status, block, hash, contract_address, is_synchronized_with_app, recipient_address, sender_address, amount):
     transaction_object = BlockchainTransaction(
         _status = status,
         block = block,
         hash = hash,
         contract_address = contract_address,
         is_synchronized_with_app = is_synchronized_with_app,
         recipient_address = recipient_address,
         sender_address = sender_address,
         amount = amount,
         is_third_party_transaction = True # External transaction will always be third party
     )   
     self.session.add(transaction_object)
     self.session.commit()
     return transaction_object
Esempio n. 12
0
    def test_handle_event(self, mocker, blockchain_sync, processor,
                          persistence_module: SQLPersistenceInterface):
        # Create dummy objects for this functions to consume (handle_event only uses decimals)
        class DummyFilter():
            decimals = 18

        filt = DummyFilter()

        class RequestsResp():
            ok = True

        # Check if handle_event halts (returns true) if there's already a synchronized transaction
        # with the same ID in the DB
        t = self.Transaction(10, '0x1111111111111111111111111111',
                             self.contract_address, True,
                             '0x2222222222222222222222222',
                             '0x3333333333333333333333333', 10)
        tx = BlockchainTransaction(
            _status='PENDING',
            block=10,
            hash='0x5555555555555555555555555',
            contract_address=self.contract_address,
            is_synchronized_with_app=False,
            recipient_address='0x3333333333333333333333333',
            sender_address='0x2222222222222222222222222',
            amount=10,
            is_third_party_transaction=True)

        # If the webhook call doesn't work, it does not call mark_as_completed
        def check_correct_webhook_call_fail(transaction):
            assert transaction == tx
            resp = RequestsResp()
            resp.ok = False
            return resp

        # from celery_app import persistence_module as pm
        pm = persistence_module
        mocker.patch.object(blockchain_sync, 'call_webhook',
                            check_correct_webhook_call_fail)
        mocker.patch.object(pm, 'get_transaction', lambda hash: tx)
        mocker.patch.object(pm, 'create_external_transaction',
                            lambda *args, **kwargs: tx)
        mark_as_completed_mock = mocker.patch.object(
            pm, 'mark_transaction_as_completed')

        result = blockchain_sync.handle_event(t, filt)
        assert result == True

        blockchain_sync.handle_event(t, filt)
        # Make sure mark_as_completed is NOT called
        assert len(mark_as_completed_mock.call_args_list) == 0

        # If the filter isn't already synchronized, create the object and call the webhook
        mocker.patch.object(pm, 'get_transaction', lambda hash: None)
        tx = BlockchainTransaction(
            _status='PENDING',
            block=10,
            hash='0x4444444444444444444444444',
            contract_address=self.contract_address,
            is_synchronized_with_app=False,
            recipient_address='0x3333333333333333333333333',
            sender_address='0x2222222222222222222222222',
            amount=10,
            is_third_party_transaction=True)

        # Make sure call_webhook is called with the right data
        def check_correct_webhook_call(transaction):
            assert transaction == tx
            return RequestsResp()

        mocker.patch.object(blockchain_sync, 'call_webhook',
                            check_correct_webhook_call)

        blockchain_sync.handle_event(t, filt)
        # Make sure mark_as_completed is called
        assert len(mark_as_completed_mock.call_args_list) == 1