예제 #1
0
def test_deserialize_deployment_ethereum_transaction():
    data = {
        'timeStamp': 0,
        'blockNumber': 1,
        'hash': '0xc5be14f87be25174846ed53ed239517e4c45c1fe024b184559c17d4f1fefa736',
        'from': '0x568Ab4b8834646f97827bB966b13d60246157B8E',
        'to': None,
        'value': 0,
        'gas': 1,
        'gasPrice': 1,
        'gasUsed': 1,
        'input': '',
        'nonce': 1,
    }
    tx = deserialize_ethereum_transaction(
        data=data,
        internal=False,
        ethereum=None,
    )
    expected = EthereumTransaction(
        timestamp=Timestamp(0),
        block_number=1,
        tx_hash=deserialize_evm_tx_hash(data['hash']),
        from_address=deserialize_ethereum_address(data['from']),
        to_address=None,
        value=data['value'],
        gas=data['gas'],
        gas_price=data['gasPrice'],
        gas_used=data['gasUsed'],
        input_data=read_hash(data, 'input'),
        nonce=data['nonce'],
    )
    assert tx == expected
예제 #2
0
파일: etherscan.py 프로젝트: rotki/rotki
    def get_transactions(
        self,
        account: ChecksumEthAddress,
        from_ts: Optional[Timestamp] = None,
        to_ts: Optional[Timestamp] = None,
    ) -> List[EthereumTransaction]:
        """Gets a list of transactions (either normal or internal) for account.

        May raise:
        - RemoteError due to self._query(). Also if the returned result
        is not in the expected format
        """
        options = {'address': str(account), 'sort': 'asc'}
        if from_ts is not None:
            from_block = self.get_blocknumber_by_time(from_ts)
            options['startBlock'] = str(from_block)
        if to_ts is not None:
            to_block = self.get_blocknumber_by_time(to_ts)
            options['endBlock'] = str(to_block)

        transactions = []
        while True:
            result = self._query(module='account',
                                 action='txlist',
                                 options=options)
            for entry in result:
                try:
                    tx = deserialize_ethereum_transaction(data=entry,
                                                          ethereum=None)
                except DeserializationError as e:
                    self.msg_aggregator.add_warning(
                        f'{str(e)}. Skipping transaction')
                    continue

                transactions.append(tx)

            if len(result) != ETHERSCAN_TX_QUERY_LIMIT:
                break
            # else we hit the limit. Query once more with startBlock being the last
            # block we got. There may be duplicate entries if there are more than one
            # transactions for that last block but they should be filtered
            # out when we input all of these in the DB
            last_block = result[-1]['blockNumber']  # pylint: disable=unsubscriptable-object
            options['startBlock'] = last_block

        return transactions
예제 #3
0
    def _get_transaction_by_hash(
            self,
            web3: Optional[Web3],
            tx_hash: EVMTxHash,
    ) -> EthereumTransaction:
        if web3 is None:
            tx_data = self.etherscan.get_transaction_by_hash(tx_hash=tx_hash)
        else:
            tx_data = web3.eth.get_transaction(tx_hash)  # type: ignore

        try:
            transaction = deserialize_ethereum_transaction(data=tx_data, internal=False, ethereum=self)  # noqa: E501
        except (DeserializationError, ValueError) as e:
            raise RemoteError(
                f'Couldnt deserialize ethereum transaction data from {tx_data}. Error: {str(e)}',
            ) from e

        return transaction
예제 #4
0
def test_deserialize_transaction_from_etherscan():
    # Make sure that a missing to address due to contract creation is handled
    data = {
        'blockNumber': 54092,
        'timeStamp': 1439048640,
        'hash':
        '0x9c81f44c29ff0226f835cd0a8a2f2a7eca6db52a711f8211b566fd15d3e0e8d4',
        'nonce': 0,
        'blockHash':
        '0xd3cabad6adab0b52ea632c386ea19403680571e682c62cb589b5abcd76de2159',
        'transactionIndex': 0,
        'from': '0x5153493bB1E1642A63A098A65dD3913daBB6AE24',
        'to': '',
        'value': 11901464239480000000000000,
        'gas': 2000000,
        'gasPrice': 10000000000000,
        'isError': 0,
        'txreceipt_status': '',
        'input': '0x313233',
        'contractAddress': '0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae',
        'cumulativeGasUsed': 1436963,
        'gasUsed': 1436963,
        'confirmations': 8569454
    }  # noqa: E501
    transaction = deserialize_ethereum_transaction(data,
                                                   internal=False,
                                                   ethereum=None)
    assert transaction == EthereumTransaction(
        tx_hash=deserialize_evm_tx_hash(data['hash']),
        timestamp=1439048640,
        block_number=54092,
        from_address='0x5153493bB1E1642A63A098A65dD3913daBB6AE24',
        to_address=None,
        value=11901464239480000000000000,
        gas=2000000,
        gas_price=10000000000000,
        gas_used=1436963,
        input_data=bytes.fromhex(data['input'][2:]),
        nonce=0,
    )
예제 #5
0
    def get_transactions(
        self,
        account: ChecksumEthAddress,
        action: Literal['txlist', 'txlistinternal'],
        from_ts: Optional[Timestamp] = None,
        to_ts: Optional[Timestamp] = None,
    ) -> Union[Iterator[List[EthereumTransaction]],
               Iterator[List[EthereumInternalTransaction]]]:
        """Gets a list of transactions (either normal or internal) for account.

        May raise:
        - RemoteError due to self._query(). Also if the returned result
        is not in the expected format
        """
        options = {'address': str(account), 'sort': 'asc'}
        if from_ts is not None:
            from_block = self.get_blocknumber_by_time(from_ts)
            options['startBlock'] = str(from_block)
        if to_ts is not None:
            to_block = self.get_blocknumber_by_time(to_ts)
            options['endBlock'] = str(to_block)

        transactions: Union[Sequence[EthereumTransaction],
                            Sequence[EthereumInternalTransaction]] = [
                            ]  # noqa: E501
        is_internal = action == 'txlistinternal'
        while True:
            result = self._query(module='account',
                                 action=action,
                                 options=options)
            last_ts = deserialize_timestamp(
                result[0]['timeStamp']) if len(result) != 0 else None  # noqa: E501 pylint: disable=unsubscriptable-object
            for entry in result:
                gevent.sleep(0)
                try:
                    tx = deserialize_ethereum_transaction(  # type: ignore
                        data=entry,
                        internal=is_internal,
                        ethereum=None,
                    )
                except DeserializationError as e:
                    self.msg_aggregator.add_warning(
                        f'{str(e)}. Skipping transaction')
                    continue

                if tx.timestamp > last_ts and len(
                        transactions) >= TRANSACTIONS_BATCH_NUM:
                    yield transactions
                    last_ts = tx.timestamp
                    transactions = []
                transactions.append(tx)  # type: ignore

            if len(result) != ETHERSCAN_TX_QUERY_LIMIT:
                break
            # else we hit the limit. Query once more with startBlock being the last
            # block we got. There may be duplicate entries if there are more than one
            # transactions for that last block but they should be filtered
            # out when we input all of these in the DB
            last_block = result[-1]['blockNumber']  # pylint: disable=unsubscriptable-object
            options['startBlock'] = last_block

        yield transactions