Example #1
0
async def get_uniswap_v3_range_liquidity_points(
    network: str,
    tick_lower: int,
    tick_upper: int,
    pool_address: ChecksumAddress,
    block_number: BlockNumber,
) -> Balances:
    """Fetches users' liquidity points of the Uniswap V3 pool in the specific range."""
    lowered_pool_address = pool_address.lower()

    last_id = ""
    result: Dict = await execute_uniswap_v3_gql_query(
        network=network,
        query=UNISWAP_V3_RANGE_POSITIONS_QUERY,
        variables=dict(
            block_number=block_number,
            tick_lower=tick_lower,
            tick_upper=tick_upper,
            pool_address=lowered_pool_address,
            last_id=last_id,
        ),
    )
    positions_chunk = result.get("positions", [])
    positions = positions_chunk

    # accumulate chunks of positions
    while len(positions_chunk) >= 1000:
        last_id = positions_chunk[-1]["id"]
        result: Dict = await execute_uniswap_v3_gql_query(
            network=network,
            query=UNISWAP_V3_RANGE_POSITIONS_QUERY,
            variables=dict(
                block_number=block_number,
                tick_lower=tick_lower,
                tick_upper=tick_upper,
                pool_address=lowered_pool_address,
                last_id=last_id,
            ),
        )
        positions_chunk = result.get("positions", [])
        positions.extend(positions_chunk)

    # process positions
    balances: Dict[ChecksumAddress, int] = {}
    total_supply = 0
    for position in positions:
        account = Web3.toChecksumAddress(position["owner"])
        if account == EMPTY_ADDR_HEX:
            continue

        liquidity = int(position.get("liquidity", "0"))
        if liquidity <= 0:
            continue

        balances[account] = balances.setdefault(account, 0) + liquidity

        total_supply += liquidity

    return Balances(total_supply=total_supply, balances=balances)
 def get_token_price(self, token_address: ChecksumAddress) -> float:
     """
     :param token_address:
     :return: usd price for token address, 0. if not found
     """
     token_address = token_address.lower()
     url = urljoin(self.base_url,
                   f'api/v3/simple/token_price/ethereum?contract_addresses={token_address}&vs_currencies=usd')
     return self._get_price(url, token_address)
Example #3
0
 def test_trace_raw_transaction(
     self,
     web3: "Web3",
     raw_transaction: HexStr,
     funded_account_for_raw_txn: ChecksumAddress,
 ) -> None:
     trace = web3.parity.traceRawTransaction(raw_transaction)
     assert trace['stateDiff'] is None
     assert trace['vmTrace'] is None
     assert trace['trace'][0]['action']['from'] == funded_account_for_raw_txn.lower()
Example #4
0
 def get_token_info(
         self, token_address: ChecksumAddress) -> Optional[Dict[str, Any]]:
     token_address = token_address.lower()
     url = urljoin(
         self.base_url,
         f"api/v3/coins/{self.asset_platform}/contract/{token_address}",
     )
     try:
         return self._do_request(url)
     except Coingecko404:
         return None
Example #5
0
 def test_trace_raw_transaction(
     self,
     web3: "Web3",
     raw_transaction: HexStr,
     funded_account_for_raw_txn: ChecksumAddress,
 ) -> None:
     # address 0x39EEed73fb1D3855E90Cbd42f348b3D7b340aAA6
     raw_transaction = HexStr(
         '0xf8648085174876e8008252089439eeed73fb1d3855e90cbd42f348b3d7b340aaa601801ba0ec1295f00936acd0c2cb90ab2cdaacb8bf5e11b3d9957833595aca9ceedb7aada05dfc8937baec0e26029057abd3a1ef8c505dca2cdc07ffacb046d090d2bea06a'
     )  # noqa: E501
     trace = web3.parity.trace_raw_transaction(raw_transaction)
     assert trace['stateDiff'] is None
     assert trace['vmTrace'] is None
     assert trace['trace'][0]['action'][
         'from'] == funded_account_for_raw_txn.lower()
Example #6
0
    def test_eth_sendTransaction_addr_checksum_required(
            self, web3: "Web3", unlocked_account: ChecksumAddress) -> None:
        non_checksum_addr = unlocked_account.lower()
        txn_params = {
            'from': unlocked_account,
            'to': unlocked_account,
            'value': 1,
            'gas': 21000,
            'gasPrice': web3.eth.gasPrice,
        }

        with pytest.raises(InvalidAddress):
            invalid_params = dict(txn_params, **{'from': non_checksum_addr})
            web3.eth.sendTransaction(invalid_params)

        with pytest.raises(InvalidAddress):
            invalid_params = dict(txn_params, **{'to': non_checksum_addr})
            web3.eth.sendTransaction(invalid_params)
Example #7
0
async def get_uniswap_v3_single_token_balances(
    network: str,
    pool_address: ChecksumAddress,
    token: ChecksumAddress,
    block_number: BlockNumber,
) -> Balances:
    """Fetches users' single token balances of the Uniswap V3 pair across all the ticks."""
    lowered_pool_address = pool_address.lower()
    result: Dict = await execute_uniswap_v3_gql_query(
        network=network,
        query=UNISWAP_V3_POOL_QUERY,
        variables=dict(block_number=block_number,
                       pool_address=lowered_pool_address),
    )
    pools = result.get("pools", [])
    if not pools:
        return Balances(total_supply=0, balances={})
    pool = pools[0]

    try:
        tick_current: int = int(pool["tick"])
    except TypeError:
        return Balances(total_supply=0, balances={})

    sqrt_price: int = pool.get("sqrtPrice", "")
    if not sqrt_price:
        return Balances(total_supply=0, balances={})
    sqrt_price = int(sqrt_price)

    token0_address: ChecksumAddress = Web3.toChecksumAddress(pool["token0"])
    token1_address: ChecksumAddress = Web3.toChecksumAddress(pool["token1"])

    last_id = ""
    result: Dict = await execute_uniswap_v3_gql_query(
        network=network,
        query=UNISWAP_V3_POSITIONS_QUERY,
        variables=dict(
            block_number=block_number,
            pool_address=lowered_pool_address,
            last_id=last_id,
        ),
    )
    positions_chunk = result.get("positions", [])
    positions = positions_chunk

    # TODO: calculated earned fees

    # accumulate chunks of positions
    while len(positions_chunk) >= 1000:
        last_id = positions_chunk[-1]["id"]
        result: Dict = await execute_uniswap_v3_gql_query(
            network=network,
            query=UNISWAP_V3_POSITIONS_QUERY,
            variables=dict(
                block_number=block_number,
                pool_address=lowered_pool_address,
                last_id=last_id,
            ),
        )
        positions_chunk = result.get("positions", [])
        positions.extend(positions_chunk)

    # process positions
    balances: Dict[ChecksumAddress, int] = {}
    total_supply = 0
    for position in positions:
        account = Web3.toChecksumAddress(position["owner"])
        if account == EMPTY_ADDR_HEX:
            continue

        liquidity: int = int(position["liquidity"])
        if liquidity <= 0:
            continue

        try:
            tick_lower: int = int(position["tickLower"])
            tick_upper: int = int(position["tickUpper"])
        except TypeError:
            continue

        if token0_address == token:
            token0_amount = get_amount0(
                tick_current=tick_current,
                sqrt_ratio_x96=sqrt_price,
                tick_lower=tick_lower,
                tick_upper=tick_upper,
                liquidity=liquidity,
            )
            balances[account] = balances.setdefault(account, 0) + token0_amount
            total_supply += token0_amount
        elif token1_address == token:
            token1_amount = get_amount1(
                tick_current=tick_current,
                sqrt_ratio_x96=sqrt_price,
                tick_lower=tick_lower,
                tick_upper=tick_upper,
                liquidity=liquidity,
            )

            balances[account] = balances.setdefault(account, 0) + token1_amount
            total_supply += token1_amount

    return Balances(total_supply=total_supply, balances=balances)
Example #8
0
async def get_token_liquidity_points(
    network: str,
    token_address: ChecksumAddress,
    from_block: BlockNumber,
    to_block: BlockNumber,
) -> Balances:
    """Fetches distributor token holders' balances."""
    lowered_token_address = token_address.lower()
    last_id = ""
    result: Dict = await execute_sw_gql_query(
        network=network,
        query=DISTRIBUTOR_TOKEN_HOLDERS_QUERY,
        variables=dict(
            token_address=lowered_token_address,
            block_number=to_block,
            last_id=last_id,
        ),
    )
    positions_chunk = result.get("distributorTokenHolders", [])
    positions = positions_chunk

    # accumulate chunks of positions
    while len(positions_chunk) >= 1000:
        last_id = positions_chunk[-1]["id"]
        result: Dict = await execute_sw_gql_query(
            network=network,
            query=DISTRIBUTOR_TOKEN_HOLDERS_QUERY,
            variables=dict(
                token_address=lowered_token_address,
                block_number=to_block,
                last_id=last_id,
            ),
        )
        positions_chunk = result.get("distributorTokenHolders", [])
        positions.extend(positions_chunk)

    # process balances
    points: Dict[ChecksumAddress, int] = {}
    total_points = 0
    for position in positions:
        account = Web3.toChecksumAddress(position["account"])
        if account == EMPTY_ADDR_HEX:
            continue

        principal = int(position["amount"])
        prev_account_points = int(position["distributorPoints"])
        updated_at_block = BlockNumber(int(position["updatedAtBlock"]))
        if from_block > updated_at_block:
            updated_at_block = from_block
            prev_account_points = 0

        account_points = prev_account_points + (
            principal * (to_block - updated_at_block)
        )
        if account_points <= 0:
            continue

        points[account] = points.get(account, 0) + account_points
        total_points += account_points

    return Balances(total_supply=total_points, balances=points)