Skip to content

fix(wrtc-price-bot): DexScreener parse always returns None (float / str divide)#7973

Open
Vyacheslav-Tomashevskiy wants to merge 1 commit into
Scottcjn:mainfrom
Vyacheslav-Tomashevskiy:fix/wrtc-price-bot-dexscreener-string-fields
Open

fix(wrtc-price-bot): DexScreener parse always returns None (float / str divide)#7973
Vyacheslav-Tomashevskiy wants to merge 1 commit into
Scottcjn:mainfrom
Vyacheslav-Tomashevskiy:fix/wrtc-price-bot-dexscreener-string-fields

Conversation

@Vyacheslav-Tomashevskiy

Copy link
Copy Markdown
Contributor

Problem

DexScreener returns every numeric field as a JSON string ("priceUsd": "0.25", "priceNative": "0.002") — which is exactly why every other field on the surrounding lines is wrapped in float(). One line divides the raw value:

"sol_price_usd": price_usd / pair.get("priceNative", 1) if pair.get("priceNative") else 0,

float / str raises TypeError, the broad except Exception swallows it, and fetch_dexscreener_price() returns None on a valid API response. So the primary price source never returns anything, and get_price() silently degrades to the Jupiter fallback — which hardcodes change_24h: 0, liquidity: 0, price_sol: 0.

Downstream that means the bot reports "24h Change: +0.00%" and "Liquidity: N/A" permanently, and check_price_alert() can never fire, since every history entry carries an identical unchanged basis. It fails closed and logs nothing a user would read as an error.

That the sibling implementation in bridge/dashboard_api.py:513-524 parses the same endpoint with float() on every field is what convinced me this is an oversight rather than intent.

Fix

Cast priceNative once and reuse it. The or 0 and the post-cast truthiness check also close a latent ZeroDivisionError: the string "0" is truthy, so the original guard would have let a zero-priced pair through to a divide-by-zero once the type issue was fixed.

Test — tests/test_wrtc_price_bot_dexscreener.py

On current main (payload mirrors the real API shape, all-strings):

FAILED tests/test_wrtc_price_bot_dexscreener.py::test_dexscreener_parses_string_fields
FAILED tests/test_wrtc_price_bot_dexscreener.py::test_get_price_uses_dexscreener_not_jupiter_fallback
E   AssertionError: DexScreener parse returned None on a valid API payload
----------------------------- Captured stdout -----------------------------
[DexScreener API] Error: unsupported operand type(s) for /: 'float' and 'str'
2 failed

The captured stdout names the exact division. With the fix, these plus the existing tests/test_wrtc_price_bot.py and wrtc_price_bot/test_price_fetch.py6 passed.

Branched off clean current main; touches only the bot and the new test.

RTC payout address: RTCd1554f0f35576faf01d386a6be1c947f560dd0b7

DexScreener returns every numeric field as a JSON string, which is why the
surrounding lines all wrap float(). The sol_price_usd line divided the raw
value instead: price_usd / pair.get('priceNative', 1) is float / str, raising
TypeError. The broad 'except Exception' swallowed it, so fetch_dexscreener_price
returned None on a perfectly valid API response and get_price silently fell back
to Jupiter, which hardcodes change_24h/liquidity/price_sol to 0.

Cast priceNative once and reuse it. The 'or 0' plus the post-cast truthiness
check also close a latent ZeroDivisionError: the string '0' is truthy, so a
zero-priced pair would have divided by zero once the type issue was resolved.
@github-actions

Copy link
Copy Markdown
Contributor

Welcome to RustChain! Thanks for your first pull request.

Before we review, please make sure:

  • Non-doc PRs have a BCOS-L1 or BCOS-L2 label
  • Doc-only PRs are exempt from BCOS tier labels when they only touch docs/**, *.md, or common image/PDF files
  • New code files include an SPDX license header
  • You've tested your changes against the live node

Bounty tiers: Micro (1-10 RTC) | Standard (20-50) | Major (75-100) | Critical (100-150)

A maintainer will review your PR soon. Thanks for contributing!

@github-actions github-actions Bot added BCOS-L1 Beacon Certified Open Source tier BCOS-L1 (required for non-doc PRs) tests Test suite changes size/M PR: 51-200 lines labels Jul 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

BCOS-L1 Beacon Certified Open Source tier BCOS-L1 (required for non-doc PRs) size/M PR: 51-200 lines tests Test suite changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant