Skip to content

feat(solana): add video/music/speech/portrait/realface/price/rpc media support#16

Merged
VickyXAI merged 1 commit into
BlockRunAI:mainfrom
KillerQueen-Z:feat/solana-media
Jul 4, 2026
Merged

feat(solana): add video/music/speech/portrait/realface/price/rpc media support#16
VickyXAI merged 1 commit into
BlockRunAI:mainfrom
KillerQueen-Z:feat/solana-media

Conversation

@KillerQueen-Z

Copy link
Copy Markdown
Contributor

What

SolanaLLMClient only exposed chat + image — every other medium the gateway already supports had no SVM-payment method. So Solana users (and the litellm sidecar) could not call video (xai/grok-imagine-video), music, speech/TTS, sound-effects, portrait/realface enrollment, Pyth market data, or multi-chain RPC.

This adds all of them to both SolanaLLMClient and AsyncSolanaLLMClient, reusing the existing SVM x402 helpers.

Key changes

  • Video (video, video_from_content): generalizes the image async-poll helper — configurable poll budget/interval + mid-poll re-signing to survive the 600s x402 authorization window on long video jobs; completion keyed on status (not HTTP 200) + txHash pulled from the settlement header.
  • Audio (music, speech, sound_effect, list_voices), enrollment (portrait_enroll, realface_*), market data (price, price_history, list_symbols), RPC (rpc, rpc_batch) — thin methods over the existing raw payment helpers.
  • cache: disable client-side caching for /v1/videos, /v1/audio, /v1/rpc, and Pyth price endpoints (generation is unique; RPC/price are realtime).

Validation

Tested live on Solana mainnet (real USDC): grok-imagine-video clip delivered with an on-chain settlement tx; speech (flash + turbo), sound-effects, and music also confirmed end-to-end. Failed settlements (transient transaction_simulation_failed, a blockhash-window issue) correctly take no payment.

Independent of the timeout PR (branched off main).

…a support

SolanaLLMClient only exposed chat + image; every other medium the gateway
supports (video, music, speech, sound-effects, portrait/realface enrollment,
Pyth market data, multi-chain RPC) had no SVM-payment method, so Solana users
(and the litellm sidecar) could not call e.g. xai/grok-imagine-video.

- Add the missing methods to both SolanaLLMClient and AsyncSolanaLLMClient,
  reusing the existing SVM x402 helpers.
- Generalize the image async-poll helper for video (configurable poll budget/
  interval; completion keyed on status not HTTP 200; txHash from header).
- Stale-blockhash settlement recovery: video is signed at submit time but only
  settles when the job completes (60-180s later), by which point the signed
  transaction's recent-blockhash can be expired -> the facilitator returns a
  402 'transaction_simulation_failed'. That failing poll carries no fresh
  challenge, so on a mid-poll 402 we re-GET poll_url WITHOUT the stale signature
  to solicit a fresh 402 (new blockhash), re-sign, and keep polling. Bounded by
  MEDIA_POLL_MAX_RESIGNS. Verified live: bytedance/seedance-2.0-fast went from
  failing 2/2 to succeeding with an on-chain settlement tx.
- cache: disable client-side caching for video/audio/rpc/price endpoints.

Validated live on Solana mainnet (real USDC): grok-imagine-video, seedance,
speech, music, sound-effects all delivered. Failed settlements take no payment.
@VickyXAI VickyXAI merged commit 32399a1 into BlockRunAI:main Jul 4, 2026
0 of 3 checks passed
VickyXAI added a commit that referenced this pull request Jul 4, 2026
…ard (#19)

Follow-up hardening on the Solana media methods added in #16, addressing
a two-model review (correctness/money-path + parity) and completing the
in-progress security work.

Security / money-path:
- Wire _assert_same_payment_terms into the sync mid-poll re-sign: a fresh
  402 challenge that reprices or redirects the payment vs. what the job
  originally authorized now raises PaymentError instead of signing an
  unbounded, unrelated payment. The guard was defined but never called
  (dead orig_amount/orig_pay_to capture); now enforced and unit-tested.
- Sync + async re-sign: guard the challenge GET and signing so a network
  or signing error surfaces the gateway's real 402 reason instead of
  masking it (async challenge GET was unwrapped before).
- _safe_path_segment on every network/symbol/market/wallet URL segment
  (LLM-controlled values can no longer escape the path).

Correctness / parity vs the Base clients:
- list_voices returns the gateway's {"data":[...]} list, not the whole
  envelope dict.
- price(): data.get("price") so a paid body missing "price" surfaces a
  clean validation error, not a raw KeyError after the charge settled.
- RealFace group_id validated with the shared _GROUP_ID_RE (was truthy-only).
- RPC/music/speech settlement receipt + gateway metadata plumbed via
  _attach_receipt / _last_raw_headers / _rpc_response.
- MEDIA_POLL_MAX_RESIGNS 3 -> 2 to match Base VideoClient.

Tests:
- New tests/unit/test_solana_media.py: the payment-terms guard, media
  dispatch (music/speech/sound-effects body + endpoint), list_voices
  envelope, local validation (lyrics+instrumental, video exclusivity,
  face-id prefix, portrait url), price KeyError-safety, and path-segment
  injection rejection.
- Fixed the timeout-test payment fake to carry pay_to (the guard reads it).

Known follow-up: the async re-sign does not yet run the re-price guard
(needs submit-time payload threading through _sign_payment_from_response);
async is otherwise unchanged from Base. validate_resource_url import was
dropped as unused — wiring poll_url redirect validation is a separate change.

286 passed, 15 skipped; ruff + black clean.

Co-authored-by: 1bcMax <viewitter@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants