feat(solana): add video/music/speech/portrait/realface/price/rpc media support#16
Merged
Merged
Conversation
f409703 to
9e20faf
Compare
…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.
9e20faf to
fd496e4
Compare
This was referenced Jul 4, 2026
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
SolanaLLMClientonly 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
SolanaLLMClientandAsyncSolanaLLMClient, reusing the existing SVM x402 helpers.Key changes
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 onstatus(not HTTP 200) +txHashpulled from the settlement header.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./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).