Beispiel #1
0
    def __init__(self, w3: Web3, master_copy_address: str,
                 proxy_factory_address: str):
        """
        Init builder for safe creation using create2
        :param w3: Web3 instance
        :param master_copy_address: `Gnosis Safe` master copy address
        :param proxy_factory_address: `Gnosis Proxy Factory` address
        """
        assert Web3.isChecksumAddress(master_copy_address)
        assert Web3.isChecksumAddress(proxy_factory_address)

        self.w3 = w3
        self.master_copy_address = master_copy_address
        self.proxy_factory_address = proxy_factory_address
        self.safe_version = get_safe_contract(
            w3, master_copy_address).functions.VERSION().call()
        if self.safe_version == '1.1.1':
            self.master_copy_contract = get_safe_contract(
                w3, master_copy_address)
        elif self.safe_version == '1.0.0':
            self.master_copy_contract = get_safe_V1_0_0_contract(
                w3, master_copy_address)
        else:
            raise ValueError('Safe version must be 1.1.1 or 1.0.0')
        self.proxy_factory_contract = get_proxy_factory_contract(
            w3, proxy_factory_address)
    def build(self, owners: List[str], threshold: int, salt_nonce: int,
              gas_price: int, fallback_handler: Optional[str] = None, payment_receiver: Optional[str] = None,
              payment_token: Optional[str] = None,
              payment_token_eth_value: float = 1.0, fixed_creation_cost: Optional[int] = None):
        """
        Prepare Safe creation
        :param owners: Owners of the Safe
        :param threshold: Minimum number of users required to operate the Safe
        :param fallback_handler: Handler for fallback calls to the Safe
        :param salt_nonce: Web3 instance
        :param gas_price: Gas Price
        :param payment_receiver: Address to refund when the Safe is created. Address(0) if no need to refund
        :param payment_token: Payment token instead of paying the funder with ether. If None Ether will be used
        :param payment_token_eth_value: Value of payment token per 1 Ether
        :param fixed_creation_cost: Fixed creation cost of Safe (Wei)
        """

        assert 0 < threshold <= len(owners)
        fallback_handler = fallback_handler or NULL_ADDRESS
        payment_receiver = payment_receiver or NULL_ADDRESS
        payment_token = payment_token or NULL_ADDRESS
        assert Web3.isChecksumAddress(payment_receiver)
        assert Web3.isChecksumAddress(payment_token)

        # Get bytes for `setup(address[] calldata _owners, uint256 _threshold, address to, bytes calldata data,
        # address paymentToken, uint256 payment, address payable paymentReceiver)`
        # This initializer will be passed to the ProxyFactory to be called right after proxy is deployed
        # We use `payment=0` as safe has no ether yet and estimation will fail
        safe_setup_data: bytes = self._get_initial_setup_safe_data(owners, threshold, fallback_handler=fallback_handler,
                                                                   payment_token=payment_token,
                                                                   payment_receiver=payment_receiver)

        magic_gas: int = self._calculate_gas(owners, safe_setup_data, payment_token)
        estimated_gas: int = self._estimate_gas(safe_setup_data,
                                                salt_nonce, payment_token, payment_receiver)
        logger.debug('Magic gas %d - Estimated gas %d' % (magic_gas, estimated_gas))
        gas = max(magic_gas, estimated_gas)

        # Payment will be safe deploy cost
        payment = self._calculate_refund_payment(gas,
                                                 gas_price,
                                                 fixed_creation_cost,
                                                 payment_token_eth_value)

        # Now we have a estimate for `payment` so we get initialization data again
        final_safe_setup_data: bytes = self._get_initial_setup_safe_data(owners, threshold,
                                                                         fallback_handler=fallback_handler,
                                                                         payment_token=payment_token, payment=payment,
                                                                         payment_receiver=payment_receiver)

        safe_address = self.calculate_create2_address(final_safe_setup_data, salt_nonce)
        assert int(safe_address, 16), 'Calculated Safe address cannot be the NULL ADDRESS'

        return SafeCreate2Tx(salt_nonce, owners, threshold, fallback_handler,
                             self.master_copy_address, self.proxy_factory_address,
                             payment_receiver, payment_token, payment, gas, gas_price, payment_token_eth_value,
                             fixed_creation_cost, safe_address, final_safe_setup_data)
    def delete(self, request, address, delegate_address, *args, **kwargs):
        """
        Delete a delegate for a Safe. Signature is built the same way that for adding a delegate.
        Check `POST /delegates/`
        """
        if not Web3.isChecksumAddress(address) or not Web3.isChecksumAddress(delegate_address):
            return Response(status=status.HTTP_422_UNPROCESSABLE_ENTITY, data='Invalid ethereum address')

        request.data['safe'] = address
        request.data['delegate'] = delegate_address
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        return super().delete(request, address, delegate_address, *args, **kwargs)
Beispiel #4
0
 def command_addorder(self, update: Update, context: CallbackContext):
     assert update.callback_query and context.user_data is not None
     query = update.callback_query
     assert query.data
     token_address = query.data.split(':')[1]
     if not Web3.isChecksumAddress(token_address):
         self.command_error(update, context, text='Invalid token address.')
         return ConversationHandler.END
     token = self.parent.watchers[token_address]
     context.user_data['addorder'] = {'token_address': token_address}
     reply_markup = InlineKeyboardMarkup(inline_keyboard=[
         [
             InlineKeyboardButton('🚫 Stop loss sell',
                                  callback_data='stop_loss'),
             InlineKeyboardButton('💰 Take profit sell',
                                  callback_data='limit_sell'),
         ],
         [
             InlineKeyboardButton('💵 Limit buy', callback_data='limit_buy'),
             InlineKeyboardButton('❌ Cancel', callback_data='cancel'),
         ],
     ])
     chat_message(
         update,
         context,
         text=
         f'Creating order for token {token.name}.\nWhich <u>type of order</u> would you like to create?',
         reply_markup=reply_markup,
         edit=self.config.update_messages,
     )
     return self.next.TYPE
Beispiel #5
0
 def command_edittoken(self, update: Update, context: CallbackContext):
     assert update.callback_query and context.user_data is not None
     query = update.callback_query
     assert query.data
     token_address = query.data.split(':')[1]
     if not Web3.isChecksumAddress(token_address):
         self.command_error(update, context, text='Invalid token address.')
         return ConversationHandler.END
     token: TokenWatcher = self.parent.watchers[token_address]
     context.user_data['edittoken'] = {'token_address': token_address}
     buttons = [
         [
             InlineKeyboardButton(f'{token.emoji}Edit emoji',
                                  callback_data='emoji'),
             InlineKeyboardButton('Edit default slippage',
                                  callback_data='slippage'),
         ],
         [
             InlineKeyboardButton('Edit buy price',
                                  callback_data='buyprice'),
             InlineKeyboardButton('❌ Cancel', callback_data='cancel'),
         ],
     ]
     reply_markup = InlineKeyboardMarkup(buttons)
     chat_message(
         update,
         context,
         text=f'What do you want to edit for token {token.name}?',
         reply_markup=reply_markup,
         edit=self.config.update_messages,
     )
     return self.next.ACTION_CHOICE
    def post(self, request, address, *args, **kwargs):
        """
        Estimates `safeTxGas` for a Safe Multisig Transaction.
        """
        if not Web3.isChecksumAddress(address):
            return Response(status=status.HTTP_422_UNPROCESSABLE_ENTITY,
                            data={
                                'code': 1,
                                'message':
                                'Checksum address validation failed',
                                'arguments': [address]
                            })

        if not SafeContract.objects.filter(address=address).exists():
            return Response(status=status.HTTP_404_NOT_FOUND)

        serializer = self.get_serializer(data=request.data)
        if serializer.is_valid():
            try:
                response_serializer = self.response_serializer(
                    data=serializer.save())
                response_serializer.is_valid(raise_exception=True)
                return Response(status=status.HTTP_200_OK,
                                data=response_serializer.data)
            except CannotEstimateGas:
                return Response(status=status.HTTP_422_UNPROCESSABLE_ENTITY,
                                data=serializer.errors)
        else:
            return Response(status=status.HTTP_400_BAD_REQUEST,
                            data=serializer.errors)
    def get(self, request, address):
        """
        Get balance for Ether and ERC20 tokens
        """
        if not Web3.isChecksumAddress(address):
            return Response(
                status=status.HTTP_422_UNPROCESSABLE_ENTITY,
                data={
                    "code": 1,
                    "message": "Checksum address validation failed",
                    "arguments": [address],
                },
            )
        else:
            try:
                SafeContract.objects.get(address=address)
            except SafeContract.DoesNotExist:
                return Response(status=status.HTTP_404_NOT_FOUND)

            only_trusted, exclude_spam = self.get_parameters()
            safe_balances = self.get_result(address,
                                            only_trusted=only_trusted,
                                            exclude_spam=exclude_spam)
            serializer = self.get_serializer(safe_balances, many=True)
            return Response(status=status.HTTP_200_OK, data=serializer.data)
    def delete(self, request, delegate_address, *args, **kwargs):
        """
        Delete every pair delegate/delegator found. Signature is built the same way as for adding a delegate,
        but in this case the signer can be either the `delegator` (owner) or the `delegate` itself.
        Check `POST /delegates/`
        """
        if not Web3.isChecksumAddress(delegate_address):
            return Response(
                status=status.HTTP_422_UNPROCESSABLE_ENTITY,
                data={
                    "code": 1,
                    "message": "Checksum address validation failed",
                    "arguments": [delegate_address],
                },
            )

        request.data["delegate"] = delegate_address
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        deleted, _ = SafeContractDelegate.objects.filter(
            delegate=serializer.validated_data["delegate"],
            delegator=serializer.validated_data["delegator"],
        ).delete()
        if deleted:
            return Response(status=status.HTTP_204_NO_CONTENT)
        else:
            return Response(status=status.HTTP_404_NOT_FOUND)
def process_airdrop():
    print('\n\n\nProcessing AirDrop List')
    airdrop_list = [
        i.strip() for i in open(constants.AIRDROP_FILE).read().split()
        if i.strip()
    ]
    airdrop_final = []
    error = []
    not_checksum = 0
    duplicate = 0
    for i in airdrop_list:
        if not Web3.isAddress(i):
            error.append(i)
            continue
        if not Web3.isChecksumAddress(i):
            not_checksum += 1
            addr_with_checksum = Web3.toChecksumAddress(i)
        else:
            addr_with_checksum = i
        if i in airdrop_final:
            duplicate += 1
            continue
        else:
            airdrop_final.append(i)

    print(
        'Processing {} input address.\n{} addresses are invalid.\n{} addresses got corrected for checksum.\n{} addresses were duplicates.\nFinally got {} valid addresses'
        .format(len(airdrop_list), len(error), not_checksum, duplicate,
                len(airdrop_final)))

    # for i in error:
    #   print (i)

    return airdrop_final
Beispiel #10
0
    def get(self):
        ret = {'ret': 0, 'code': 0, 'msg': '', 'data': dict()}
        address = self.get_argument('address', '', True)
        est = self.get_argument('est', '', True)
        if not address or not est:
            ret['ret'] = ret['code'] = 400
            ret['msg'] = 'address or est cannot be empty'
            self.write(json_encode(ret))
            return

        address = Web3.toChecksumAddress(address)
        if not Web3.isChecksumAddress(address):
            ret['ret'] = ret['code'] = 400
            ret['msg'] = 'address invalid'
            self.write(json_encode(ret))
            return

        base_conf = estconf['base']

        trans = TransactionMaker(provider_url=base_conf['provider_url'], my_wallet_address=base_conf['from_address'])
        trans.set_abi_type(erc20_abi_json=base_conf['erc20_abi'])

        value = int(float(est) * 10 ** 9)
        cost = trans.get_transfer_cost(to=address, value=value, contract_address=base_conf['contract_address'])
        if not cost:
            ret['ret'] = ret['code'] = 400
            ret['msg'] = 'System maintenance'
            self.write(json_encode(ret))
            return
        ret['data'] = {'cost': cost}

        self.write(json_encode(ret))
        return
Beispiel #11
0
    def get(self, request, address, *args, **kwargs):
        """
        Get status of the safe
        """
        if not Web3.isChecksumAddress(address):
            return Response(status=status.HTTP_422_UNPROCESSABLE_ENTITY,
                            data={
                                'code': 1,
                                'message':
                                'Checksum address validation failed',
                                'arguments': [address]
                            })

        if not SafeContract.objects.filter(address=address).exists():
            return Response(status=status.HTTP_404_NOT_FOUND)

        try:
            safe_info = SafeServiceProvider().get_safe_info(address)
            serializer = self.serializer_class(safe_info)
            return Response(status=status.HTTP_200_OK, data=serializer.data)
        except CannotGetSafeInfo:
            return Response(status=status.HTTP_422_UNPROCESSABLE_ENTITY,
                            data={
                                'code': 50,
                                'message': 'Cannot get Safe info',
                                'arguments': [address]
                            })
Beispiel #12
0
    def test_get_multisig_transaction(self):
        safe_tx_hash = Web3.keccak(text='gnosis').hex()
        response = self.client.get(reverse('v1:multisig-transaction', args=(safe_tx_hash,)), format='json')
        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)

        add_owner_with_threshold_data = HexBytes('0x0d582f130000000000000000000000001b9a0da11a5cace4e7035993cbb2e4'
                                                 'b1b3b164cf000000000000000000000000000000000000000000000000000000'
                                                 '0000000001')
        multisig_tx = MultisigTransactionFactory(data=add_owner_with_threshold_data)
        safe_tx_hash = multisig_tx.safe_tx_hash
        response = self.client.get(reverse('v1:multisig-transaction', args=(safe_tx_hash,)), format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(len(response.data['confirmations']), 0)
        self.assertTrue(Web3.isChecksumAddress(response.data['executor']))
        self.assertEqual(response.data['transaction_hash'], multisig_tx.ethereum_tx.tx_hash)
        self.assertEqual(response.data['origin'], multisig_tx.origin)
        self.assertEqual(response.data['data_decoded'], {'addOwnerWithThreshold': [{'name': 'owner',
                                                                                    'type': 'address',
                                                                                    'value': '0x1b9a0DA11a5caCE4e703599'
                                                                                             '3Cbb2E4B1B3b164Cf'},
                                                                                   {'name': '_threshold',
                                                                                    'type': 'uint256',
                                                                                    'value': 1}]
                                                         })
        # Test camelCase
        self.assertEqual(response.json()['transactionHash'], multisig_tx.ethereum_tx.tx_hash)
Beispiel #13
0
    def test_get_multisig_transactions(self):
        safe_address = Account.create().address
        response = self.client.get(reverse('v1:multisig-transactions', args=(safe_address,)), format='json')
        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)

        multisig_tx = MultisigTransactionFactory(safe=safe_address)
        response = self.client.get(reverse('v1:multisig-transactions', args=(safe_address,)), format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['count'], 1)
        self.assertEqual(response.data['count_unique_nonce'], 1)
        self.assertEqual(len(response.data['results']), 1)
        self.assertEqual(len(response.data['results'][0]['confirmations']), 0)
        self.assertTrue(Web3.isChecksumAddress(response.data['results'][0]['executor']))
        self.assertEqual(response.data['results'][0]['transaction_hash'], multisig_tx.ethereum_tx.tx_hash)
        # Test camelCase
        self.assertEqual(response.json()['results'][0]['transactionHash'], multisig_tx.ethereum_tx.tx_hash)
        # Check Etag header
        self.assertTrue(response['Etag'])

        MultisigConfirmationFactory(multisig_transaction=multisig_tx)
        response = self.client.get(reverse('v1:multisig-transactions', args=(safe_address,)), format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(len(response.data['results']), 1)
        self.assertEqual(len(response.data['results'][0]['confirmations']), 1)

        MultisigTransactionFactory(safe=safe_address, nonce=multisig_tx.nonce)
        response = self.client.get(reverse('v1:multisig-transactions', args=(safe_address,)), format='json')
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['count'], 2)
        self.assertEqual(response.data['count_unique_nonce'], 1)
Beispiel #14
0
    def __init__(self, address: str, ethereum_client: EthereumClient):
        assert Web3.isChecksumAddress(
            address), '%s is not a valid address' % address

        self.ethereum_client = ethereum_client
        self.w3 = self.ethereum_client.w3
        self.address = address
Beispiel #15
0
 def handle(self):
     PoW(self.request)
     self.request.sendall(menu().encode('utf-8'))
     option = self.request.recv(1024).strip()
     try:
         option = int(option)
         if option == 1:
             session_id = random_token()
             self.request.sendall('Your token is: {}\r\n'.format(b64encode(session_id).decode('utf-8')).encode('utf-8'))
             self.request.sendall('Deploy challenge for you...\r\n'.encode('utf-8'))
             address = new_challenge()
             session[session_id] = Web3.toChecksumAddress(address)
             self.request.sendall('OK~ Your address is: {}'.format(address).encode('utf-8'))
         elif option == 2:
             self.request.sendall('Give me your token: \r\n> '.encode('utf-8'))
             token = b64decode(self.request.recv(1024).strip())
             if Web3.isChecksumAddress(session[token]):
                 self.request.sendall(get_flag(session[token]).encode('utf-8'))
             else:
                 self.request.sendall(session[token].encode('utf-8'))
         else:
             raise('')
     except Exception as e:
         print(e)
         self.request.sendall('wrong, bye~~'.encode('utf-8')) 
Beispiel #16
0
def validate_address(value):
    is_address = Web3.isAddress(value)
    if not is_address:
        raise ValidationError("Not valid Eth address. Please check it again")

    if not Web3.isChecksumAddress(value):
        raise ValidationError('Address has an invalid EIP checksum')
Beispiel #17
0
    def post(self, request, address):
        """
        Estimates a Safe Multisig Transaction for all tokens supported. `operational_gas` and `data_gas`
        are deprecated, use `base_gas` instead
        """
        if not Web3.isChecksumAddress(address):
            return Response(status=status.HTTP_422_UNPROCESSABLE_ENTITY)

        request.data["safe"] = address
        serializer = self.get_serializer_class()(data=request.data)

        if serializer.is_valid():
            data = serializer.validated_data

            transaction_estimations = (
                TransactionServiceProvider().estimate_tx_for_all_tokens(
                    address, data["to"], data["value"], data["data"], data["operation"]
                )
            )
            response_serializer = (
                TransactionEstimationWithNonceAndGasTokensResponseSerializer(
                    transaction_estimations
                )
            )
            return Response(status=status.HTTP_200_OK, data=response_serializer.data)
        else:
            return Response(status=status.HTTP_400_BAD_REQUEST, data=serializer.errors)
Beispiel #18
0
    def process_addresses(
            self,
            safe_addresses: List[str]) -> Optional[Tuple[List[Any], bool]]:
        """
        Find and process relevant data for `safe_addresses`, then store and return it
        :param safe_addresses: Addresses to process
        :return: List of processed data and a boolean (`True` if no more blocks to scan, `False` otherwise)
        """
        assert safe_addresses, 'Safe addresses cannot be empty!'
        assert all([Web3.isChecksumAddress(safe_address) for safe_address in safe_addresses]), \
            'A safe address has invalid checksum: %s' % safe_addresses

        parameters = self.get_block_numbers_for_search(safe_addresses)
        if parameters is None:
            return
        from_block_number, to_block_number = parameters
        updated = to_block_number == (
            self.ethereum_client.current_block_number - self.confirmations)
        tx_hashes = self.find_relevant_tx_hashes(safe_addresses,
                                                 from_block_number,
                                                 to_block_number)
        processed_objects = [
            self.process_tx_hash(tx_hash) for tx_hash in tx_hashes
        ]
        flatten_processed_objects = [
            item for sublist in processed_objects for item in sublist
        ]

        self.update_safe_tx_status(safe_addresses, to_block_number)
        return flatten_processed_objects, updated
Beispiel #19
0
    def get(self, request, *args, **kwargs):
        """
        Returns a paginated list of transactions for a Safe. The list has different structures depending on the
        transaction type:
        - Multisig Transactions for a Safe. `tx_type=MULTISIG_TRANSACTION`. If the query parameter `queued=False` is
        set only the transactions with `safe nonce < current Safe nonce` will be displayed. By default, only the
        `trusted` transactions will be displayed (transactions indexed, with at least one confirmation or proposed
        by a delegate). If you need that behaviour to be disabled set the query parameter `trusted=False`
        - Module Transactions for a Safe. `tx_type=MODULE_TRANSACTION`
        - Incoming Transfers of Ether/ERC20 Tokens/ERC721 Tokens. `tx_type=ETHEREUM_TRANSACTION`
        """
        address = kwargs['address']
        if not Web3.isChecksumAddress(address):
            return Response(status=status.HTTP_422_UNPROCESSABLE_ENTITY,
                            data={
                                'code': 1,
                                'message':
                                'Checksum address validation failed',
                                'arguments': [address]
                            })

        response = super().get(request, *args, **kwargs)
        response.setdefault(
            'ETag', 'W/' +
            hashlib.md5(str(response.data['results']).encode()).hexdigest())
        return response
Beispiel #20
0
 def command_removeorder(self, update: Update, context: CallbackContext):
     assert update.callback_query and context.user_data is not None
     query = update.callback_query
     assert query.data
     token_address = query.data.split(':')[1]
     if not Web3.isChecksumAddress(token_address):
         self.command_error(update, context, text='Invalid token address.')
         return ConversationHandler.END
     token: TokenWatcher = self.parent.watchers[token_address]
     context.user_data['removeorder'] = {'token_address': token_address}
     orders = token.orders
     buttons: List[InlineKeyboardButton] = [
         InlineKeyboardButton(
             f'{self.get_type_icon(o)} #{o.order_record.id} - {self.get_type_name(o)}',
             callback_data=o.order_record.id,
         ) for o in orders
     ]
     buttons_layout = [buttons[i:i + 2]
                       for i in range(0, len(buttons), 2)]  # noqa: E203
     buttons_layout.append(
         [InlineKeyboardButton('❌ Cancel', callback_data='cancel')])
     reply_markup = InlineKeyboardMarkup(inline_keyboard=buttons_layout)
     chat_message(
         update,
         context,
         text=f'Select the order you want to remove for {token.name}.',
         reply_markup=reply_markup,
         edit=self.config.update_messages,
     )
     return self.next.CONFIRM
Beispiel #21
0
    def get_balances(self, safe_address: str) -> List[Balance]:
        """
        :param safe_address:
        :return: `{'token_address': str, 'balance': int}`. For ether, `token_address` is `None`
        """
        assert Web3.isChecksumAddress(
            safe_address
        ), f'Not valid address {safe_address} for getting balances'

        erc20_addresses = list(
            EthereumEvent.objects.erc20_tokens_used_by_address(safe_address))
        raw_balances = self.ethereum_client.erc20.get_balances(
            safe_address, erc20_addresses)

        balances = []
        for balance in raw_balances:
            if not balance['token_address']:  # Ether
                balance['token'] = None
            elif balance['balance'] > 0:
                balance['token'] = self.get_token_info(
                    balance['token_address'])
                if not balance[
                        'token']:  # Ignore ERC20 tokens that cannot be queried
                    continue
            else:
                continue
            balances.append(Balance(**balance))
        return balances
Beispiel #22
0
    def get_balances(self, safe_address: str, only_trusted: bool = False, exclude_spam: bool = False) -> List[Balance]:
        """
        :param safe_address:
        :param only_trusted: If True, return balance only for trusted tokens
        :param exclude_spam: If True, exclude spam tokens
        :return: `{'token_address': str, 'balance': int}`. For ether, `token_address` is `None`
        """
        assert Web3.isChecksumAddress(safe_address), f'Not valid address {safe_address} for getting balances'

        all_erc20_addresses = list(EthereumEvent.objects.erc20_tokens_used_by_address(safe_address))
        for address in all_erc20_addresses:
            # Store tokens in database if not present
            self.get_token_info(address)  # This is cached
        erc20_addresses = self._filter_addresses(all_erc20_addresses, only_trusted, exclude_spam)

        try:
            raw_balances = self.ethereum_client.erc20.get_balances(safe_address, erc20_addresses)
        except IOError as exc:
            raise NodeConnectionError from exc

        balances = []
        for balance in raw_balances:
            if not balance['token_address']:  # Ether
                balance['token'] = None
            elif balance['balance'] > 0:
                balance['token'] = self.get_token_info(balance['token_address'])
                if not balance['token']:  # Ignore ERC20 tokens that cannot be queried
                    continue
            else:
                continue
            balances.append(Balance(**balance))
        return balances
Beispiel #23
0
    def process_addresses(self, addresses: Sequence[str],
                          current_block_number: Optional[int] = None) -> Tuple[Sequence[Any], bool]:
        """
        Find and process relevant data for `addresses`, then store and return it
        :param addresses: Addresses to process
        :param current_block_number: To prevent fetching it again
        :return: List of processed data and a boolean (`True` if no more blocks to scan, `False` otherwise)
        """
        assert addresses, 'Addresses cannot be empty!'
        assert all([Web3.isChecksumAddress(address) for address in addresses]), \
            f'An address has invalid checksum: {addresses}'

        current_block_number = current_block_number or self.ethereum_client.current_block_number
        parameters = self.get_block_numbers_for_search(addresses, current_block_number)
        if parameters is None:
            return [], True
        from_block_number, to_block_number = parameters

        updated = to_block_number == (current_block_number - self.confirmations)

        # Optimize number of elements processed every time (block process limit)
        # Check that we are processing the `block_process_limit`, if not, measures are not valid
        if self.block_auto_process_limit and (to_block_number - from_block_number) == self.block_process_limit:
            start = time.time()
        else:
            start = None

        try:
            elements = self.find_relevant_elements(addresses, from_block_number, to_block_number,
                                                   current_block_number=current_block_number)
        except (self.FindRelevantElementsException, SoftTimeLimitExceeded) as e:
            self.block_process_limit = min(self.initial_block_process_limit, 10)  # Set back to less than default
            logger.info('%s: block_process_limit set back to %d', self.__class__.__name__, self.block_process_limit)
            raise e

        if start:
            end = time.time()
            time_diff = end - start
            if time_diff > 30:
                self.block_process_limit //= 2
                logger.info('%s: block_process_limit halved to %d', self.__class__.__name__,
                            self.block_process_limit)
            if time_diff > 10:
                new_block_process_limit = max(self.block_process_limit - 5000, 500)
                self.block_process_limit = new_block_process_limit
                logger.info('%s: block_process_limit decreased to %d', self.__class__.__name__,
                            self.block_process_limit)
            elif time_diff < 1:
                self.block_process_limit *= 2
                logger.info('%s: block_process_limit duplicated to %d', self.__class__.__name__,
                            self.block_process_limit)
            elif time_diff < 3:
                self.block_process_limit += 5000
                logger.info('%s: block_process_limit increased to %d', self.__class__.__name__,
                            self.block_process_limit)

        processed_elements = self.process_elements(elements)

        self.update_monitored_address(addresses, from_block_number, to_block_number)
        return processed_elements, updated
Beispiel #24
0
    def __init__(self, address: str, ethereum_client: EthereumClient):
        assert Web3.isChecksumAddress(address), \
            '%s proxy factory address not valid' % address

        self.address = address
        self.ethereum_client = ethereum_client
        self.w3 = ethereum_client.w3
def process_presale_bonus():
    print('\n\n\nProcessing Presale List')
    rows = [
        i for i in csv.reader(open('presale.bonus.feb23-1800.tsv', 'r'),
                              delimiter='\t')
    ]
    # neglect first row
    rows = rows[1:]
    presale_bonus_final = []

    for row in rows:
        addr, tokens, cliff, notes, _, _, _ = row
        addr = addr.strip()
        if not Web3.isAddress(addr):
            print('Invalid Address <{}> for {}'.format(addr, notes))
            continue

        if not Web3.isChecksumAddress(addr):
            addr = Web3.toChecksumAddress(addr)

        tokens = int(tokens.replace(',', '').strip())
        presale_bonus_final.append([addr, tokens, int(cliff)])

    print(
        'Processed {} input and got {} valid presale allocation with {} total tokens'
        .format(len(rows), len(presale_bonus_final),
                sum(i[1] for i in presale_bonus_final)))

    return presale_bonus_final
    def get(self, request, address, *args, **kwargs):
        """
        Get status of the safe
        """
        if not Web3.isChecksumAddress(address):
            return Response(
                status=status.HTTP_422_UNPROCESSABLE_ENTITY,
                data={
                    "code": 1,
                    "message": "Checksum address validation failed",
                    "arguments": [address],
                },
            )

        if not SafeContract.objects.filter(address=address).exists():
            return Response(status=status.HTTP_404_NOT_FOUND)

        try:
            # safe_info = SafeServiceProvider().get_safe_info(address)
            safe_info = SafeServiceProvider().get_safe_info_from_blockchain(
                address)
            serializer = self.get_serializer(safe_info)
            return Response(status=status.HTTP_200_OK, data=serializer.data)
        except CannotGetSafeInfoFromBlockchain:
            return Response(
                status=status.HTTP_422_UNPROCESSABLE_ENTITY,
                data={
                    "code": 50,
                    "message": "Cannot get Safe info from blockchain",
                    "arguments": [address],
                },
            )
Beispiel #27
0
    def post(self, request, address):
        """
        Estimates a Safe Multisig Transaction. `operational_gas` and `data_gas` are deprecated, use `base_gas` instead
        """
        if not Web3.isChecksumAddress(address):
            return Response(status=status.HTTP_422_UNPROCESSABLE_ENTITY)
        else:
            try:
                SafeContract.objects.get(address=address)
            except SafeContract.DoesNotExist:
                return Response(status=status.HTTP_404_NOT_FOUND)

        request.data['safe'] = address
        serializer = self.get_serializer_class()(data=request.data)

        if serializer.is_valid():
            data = serializer.validated_data

            transaction_estimations = TransactionServiceProvider(
            ).estimate_tx_for_all_tokens(address, data['to'], data['value'],
                                         data['data'], data['operation'])
            response_serializer = TransactionEstimationWithNonceAndGasTokensResponseSerializer(
                transaction_estimations)
            return Response(status=status.HTTP_200_OK,
                            data=response_serializer.data)
        else:
            return Response(status=status.HTTP_400_BAD_REQUEST,
                            data=serializer.errors)
    def post(self, request, address, format=None):
        """
        Creates a Multisig Transaction with its confirmations and retrieves all the information related.
        """
        if not Web3.isChecksumAddress(address):
            return Response(status=status.HTTP_422_UNPROCESSABLE_ENTITY,
                            data='Invalid ethereum address')

        request.data['safe'] = address
        serializer = self.get_serializer_class()(data=request.data)

        if not serializer.is_valid():
            return Response(status=status.HTTP_422_UNPROCESSABLE_ENTITY,
                            data=serializer.errors)
        else:
            serializer.save()

            # Create task if transaction hash
            # data = serializer.validated_data
            # transaction_hash = data.get('transaction_hash')
            # if transaction_hash:
            #     check_approve_transaction_task.delay(safe_address=address,
            #                                          safe_tx_hash=data['contract_transaction_hash'].hex(),
            #                                          transaction_hash=transaction_hash.hex(),
            #                                          owner=data['sender'])

            return Response(status=status.HTTP_202_ACCEPTED)
Beispiel #29
0
    def post(self, request, address, format=None):
        """
        Send a Safe Multisig Transaction
        """
        if not Web3.isChecksumAddress(address):
            return Response(status=status.HTTP_422_UNPROCESSABLE_ENTITY)

        request.data['safe'] = address
        serializer = self.get_serializer_class()(data=request.data)

        if not serializer.is_valid():
            return Response(status=status.HTTP_400_BAD_REQUEST,
                            data=serializer.errors)
        else:
            data = serializer.validated_data
            safe_multisig_tx = TransactionServiceProvider().create_multisig_tx(
                safe_address=data['safe'],
                to=data['to'],
                value=data['value'],
                data=data['data'],
                operation=data['operation'],
                safe_tx_gas=data['safe_tx_gas'],
                base_gas=data['data_gas'],
                gas_price=data['gas_price'],
                gas_token=data['gas_token'],
                refund_receiver=data['refund_receiver'],
                safe_nonce=data['nonce'],
                signatures=data['signatures'])
            response_serializer = SafeMultisigTxResponseSerializer(
                safe_multisig_tx)
            return Response(status=status.HTTP_201_CREATED,
                            data=response_serializer.data)
    def get(self, request, *args, **kwargs):
        address = self.kwargs["address"]
        if not Web3.isChecksumAddress(address):
            return response.Response(
                status=status.HTTP_422_UNPROCESSABLE_ENTITY,
                data={
                    "code": 1,
                    "message": "Invalid ethereum address",
                    "arguments": [address],
                },
            )

        price_service = PriceServiceProvider()
        if address == NULL_ADDRESS:
            data = {
                "fiat_code": "USD",
                "fiat_price": str(price_service.get_native_coin_usd_price()),
                "timestamp": timezone.now(),
            }
        else:
            token = self.get_object()  # Raises 404 if not found
            fiat_price_with_timestamp = next(
                price_service.get_cached_usd_values(
                    [token.get_price_address()]))
            data = {
                "fiat_code": fiat_price_with_timestamp.fiat_code.name,
                "fiat_price": str(fiat_price_with_timestamp.fiat_price),
                "timestamp": fiat_price_with_timestamp.timestamp,
            }

        serializer = self.get_serializer(data=data)
        assert serializer.is_valid()
        return Response(status=status.HTTP_200_OK, data=serializer.data)