Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

[Bug] Response models declare numeric fields as strict `str`, causing silent fallback of `.data()` to raw dict (simple-earn & staking)

Aperta
#553 2 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
68/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
python

Direzione di ricerca

Inizia riproducendo gli esempi di model_validate nell'issue. Esamina i modelli indicati in binance-sdk-simple-earn/rest_api/models e binance-sdk-staking/rest_api/models, quindi leggi binance_common.utils.send_request per comprendere il fallback ai dizionari grezzi. Il lavoro è completato quando i payload numerici con forma di produzione restituiscono costantemente oggetti modello e il comportamento di fallback viene gestito come previsto.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

[Bug] Response models declare numeric fields as strict str, causing silent fallback of .data() to raw dict (simple-earn & staking)

Environment

  • binance-sdk-simple-earn 8.0.0
  • binance-sdk-staking 5.11.0
  • binance-common 4.0.0
  • Python 3.14.6, Windows 11

Summary

Several REST response models declare fields as StrictStr while the live API returns JSON numbers for them. Pydantic strict validation therefore fails on every real response, and binance_common.utils.send_request silently falls back to returning the raw parsed JSON. As a result, ApiResponse.data() returns a plain dict instead of the documented model object for these endpoints — data.to_dict() / attribute access then raises AttributeError in user code, with no warning that validation failed.

All cases below were reproduced against the production API with real responses on 2026-07-07/08.

Case 1 (verified): SubscribeLockedProductResponse.position_id

POST /sapi/v1/simple-earn/locked/subscribe returns positionId as a number, but the model declares it as strict str.

from binance_sdk_simple_earn.rest_api.models.subscribe_locked_product_response import SubscribeLockedProductResponse

# actual live response of a successful subscription
payload = {'purchaseId': 351129167, 'positionId': 347608223, 'success': True, 'amount': '0.05'}
SubscribeLockedProductResponse.model_validate(payload)
1 validation error for SubscribeLockedProductResponse
positionId
  Input should be a valid string [type=string_type, input_value=347608223, input_type=int]

Note: purchase_id is declared StrictInt in the same model, so the numeric purchaseId passes while the numeric positionId fails — the declarations are inconsistent within one model.

Case 2 (verified): GetLockedProductPositionResponse rows

GET /sapi/v1/simple-earn/locked/position rows contain numeric duration, accrualDays, payPeriod, redeemPeriod, but the rows-inner model declares them as strict str.

from binance_sdk_simple_earn.rest_api.models.get_locked_product_position_response import GetLockedProductPositionResponse

# actual live response row of a held position
row = {'positionId': 347608038, 'projectId': 'Bnb*120', 'asset': 'BNB', 'amount': '0.05',
       'purchaseTime': 1783439066000, 'duration': 120, 'accrualDays': 0, 'rewardAsset': 'BNB',
       'rewardAmt': '0', 'nextPay': '0.00000054', 'nextPayDate': 1783555200000, 'payPeriod': 1,
       'redeemAmountEarly': '0.05', 'rewardsEndDate': 1793836800000, 'deliverDate': 1793959200000,
       'redeemPeriod': 1, 'canRedeemEarly': True, 'canFastRedemption': True, 'autoSubscribe': False,
       'type': 'NORMAL', 'status': 'HOLDING', 'canReStake': False, 'redeemTo': 'SPOT',
       'totalBoostRewardAmt': '0', 'apy': '0.004'}
GetLockedProductPositionResponse.model_validate({'rows': [row], 'total': 1})
4 validation errors for GetLockedProductPositionResponse
rows.0.duration      Input should be a valid string [input_value=120, input_type=int]
rows.0.accrualDays   Input should be a valid string [input_value=0, input_type=int]
rows.0.payPeriod     Input should be a valid string [input_value=1, input_type=int]
rows.0.redeemPeriod  Input should be a valid string [input_value=1, input_type=int]

Important detail: with an empty rows the wrapper model validates fine, so the endpoint appears healthy until the account actually holds a position — then every call degrades to a raw dict.

Case 3 (same pattern, static): SubscribeOnChainYieldsLockedProductResponse.position_id

binance-sdk-staking, POST /sapi/v1/onchain-yields/locked/subscribe — the model declares:

purchase_id: StrictInt | None
position_id: StrictStr | None   <-- same inconsistency as Case 1

The twin Simple Earn endpoint empirically returns positionId as a number (Case 1), and the official docs example for this endpoint also shows a numeric positionId.

Case 4 (same pattern, static): GetOnChainYieldsLockedProductPositionResponseRowsInner

Every field of the rows-inner model is declared strict str, including ones that are numbers on the wire for the twin locked endpoint (Case 2): purchase_time, duration, accrual_days, pay_period, next_pay_date, rewards_end_date, deliver_date, ...

Impact

  • ApiResponse.data() type is inconsistent per endpoint (model vs raw dict), and the switch is silent — user code calling .to_dict() or accessing attributes crashes with AttributeError.
  • Particularly nasty on the subscribe endpoint: the subscription has already executed server-side, then response parsing fails client-side, which looks like a failed request.

Suggested fix

  • Align model field types with the actual wire types (int for positionId, duration, timestamps, etc.), or relax Strict to allow coercion.
  • Independently of the type fixes: consider logging a warning in binance_common.utils.send_request when model validation fails and the raw payload is returned, so the fallback is observable.
Lingua principale
Python
Stelle
2.9k
Fork
699
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

Guida per i contributori

Nessuna guida per i contributori indicizzata per questo repository

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di binance/binance-connector-python

Tutte le issue di binance/binance-connector-python

Issue simili

Altre issue su Python

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.