def fix_uniswap_pool_tokens_task() -> Optional[int]:
    ethereum_client = EthereumClientProvider()
    ethereum_network = ethereum_client.get_network()
    if ethereum_network == EthereumNetwork.MAINNET:
        try:
            number = Token.objects.fix_uniswap_pool_tokens()
            if number:
                logger.info('%d uniswap pool token names were fixed', number)
            return number
        finally:
            close_gevent_db_connection()
Example #2
0
def send_notification_task(address: Optional[str],
                           payload: Dict[str, Any]) -> Tuple[int, int]:
    """
    :param address:
    :param payload:
    :return: Tuple with the number of successful and failed notifications sent
    """
    if not (address and payload):  # Both must be present
        return 0, 0

    try:
        firebase_devices = FirebaseDevice.objects.filter(
            safes__address=address).exclude(
                cloud_messaging_token=None)  # TODO Use cache
        tokens = [
            firebase_device.cloud_messaging_token
            for firebase_device in firebase_devices
        ]

        if is_pending_multisig_transaction(payload):
            send_notification_owner_task.delay(address, payload['safeTxHash'])

        if not (tokens and filter_notification(payload)):
            return 0, 0

        # Make sure notification has not been sent before
        duplicate_notification = DuplicateNotification(address, payload)
        if duplicate_notification.is_duplicated():
            logger.info(
                'Duplicated notification about Safe=%s with payload=%s to tokens=%s',
                address, payload, tokens)
            return 0, 0

        duplicate_notification.set_duplicated()

        with FirebaseClientPool() as firebase_client:
            logger.info(
                'Sending notification about Safe=%s with payload=%s to tokens=%s',
                address, payload, tokens)
            success_count, failure_count, invalid_tokens = firebase_client.send_message(
                tokens, payload)
            if invalid_tokens:
                logger.info('Removing invalid tokens for safe=%s. Tokens=%s',
                            address, invalid_tokens)
                FirebaseDevice.objects.filter(
                    cloud_messaging_token__in=invalid_tokens).update(
                        cloud_messaging_token=None)

        return success_count, failure_count
    finally:
        close_gevent_db_connection()
def fix_pool_tokens_task() -> Optional[int]:
    """
    Fix names for generic pool tokens, like Balancer or Uniswap
    :return: Number of pool token names updated
    """
    ethereum_client = EthereumClientProvider()
    ethereum_network = ethereum_client.get_network()
    if ethereum_network == EthereumNetwork.MAINNET:
        try:
            number = Token.pool_tokens.fix_all_pool_tokens()
            if number:
                logger.info('%d pool token names were fixed', number)
            return number
        finally:
            close_gevent_db_connection()
def send_notification_owner_task(address: str, safe_tx_hash: str):
    """
    Send a confirmation request to an owner
    :param address: Safe address
    :param safe_tx_hash: Hash of the safe tx
    :return: Tuple with the number of successful and failed notifications sent
    """
    assert safe_tx_hash, 'Safe tx hash was not provided'

    try:
        confirmed_owners = MultisigConfirmation.objects.filter(
            multisig_transaction_id=safe_tx_hash).values_list('owner',
                                                              flat=True)
        safe_status = SafeStatus.objects.last_for_address(address)
        if not safe_status:
            logger.info('Cannot find threshold information for safe=%s',
                        address)
            return 0, 0

        if safe_status.threshold <= len(confirmed_owners):
            # No need for more confirmations
            logger.info(
                'Multisig transaction with safe-tx-hash=%s for safe=%s does not require more confirmations',
                safe_tx_hash, address)
            return 0, 0

        # Get cloud messaging token for missing owners
        owners_to_notify = set(safe_status.owners) - set(confirmed_owners)
        tokens = list(
            FirebaseDeviceOwner.objects.filter(
                owner__in=owners_to_notify).values_list(
                    'firebase_device__cloud_messaging_token', flat=True))

        if not tokens:
            logger.info(
                'No cloud messaging tokens found for needed owners %s to sign safe-tx-hash=%s for safe=%s',
                owners_to_notify, safe_tx_hash, address)
            return 0, 0

        payload = {
            'type': WebHookType.CONFIRMATION_REQUEST.name,
            'address': address,
            'safeTxHash': safe_tx_hash,
        }
        # Make sure notification has not been sent before
        duplicate_notification = DuplicateNotification(address, payload)
        if duplicate_notification.is_duplicated():
            logger.info(
                'Duplicated notification about Safe=%s with payload=%s to tokens=%s',
                address, payload, tokens)
            return 0, 0

        duplicate_notification.set_duplicated()

        with FirebaseClientPool() as firebase_client:
            logger.info(
                'Sending notification about Safe=%s with payload=%s to tokens=%s',
                address, payload, tokens)
            success_count, failure_count, invalid_tokens = firebase_client.send_message(
                tokens, payload)
            if invalid_tokens:
                logger.info('Removing invalid tokens for safe=%s', address)
                FirebaseDevice.objects.filter(
                    cloud_messaging_token__in=invalid_tokens).update(
                        cloud_messaging_token=None)

        return success_count, failure_count
    finally:
        close_gevent_db_connection()
Example #5
0
from gnosis.eth import EthereumClientProvider

from safe_transaction_service.history.utils import close_gevent_db_connection

from .models import Contract

logger = get_task_logger(__name__)


@app.shared_task()
def index_contracts_metadata_task(addresses: Sequence[str]):
    ethereum_client = EthereumClientProvider()
    ethereum_network = ethereum_client.get_network()
    try:
        for address in addresses:
            try:
                with transaction.atomic():
                    if contract := Contract.objects.create_from_address(
                            address, network_id=ethereum_network.value):
                        logger.info(
                            'Indexed contract with address=%s name=%s abi-present=%s',
                            address, contract.name,
                            bool(contract.contract_abi.abi))
                    else:
                        Contract.objects.create(address=address)
            except IntegrityError:
                logger.warning('Contract with address=%s was already created',
                               address)
    finally:
        close_gevent_db_connection()