Skip to content

fix(solana): allow paid GET endpoints for Solana clients - #9

Merged
VickyXAI merged 2 commits into
mainfrom
fix/solana-paid-get
Aug 4, 2026
Merged

fix(solana): allow paid GET endpoints for Solana clients#9
VickyXAI merged 2 commits into
mainfrom
fix/solana-paid-get

Conversation

@VickyXAI

@VickyXAI VickyXAI commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Closes #8.

What

doGetWithPayment guarded the 402 branch on bc.privateKey == nil:

if resp.StatusCode == http.StatusPaymentRequired {
    if bc.privateKey == nil {
        return nil, &PaymentError{Message: "endpoint returned 402 but no wallet is configured"}
    }

But Solana clients leave privateKey nil by design and sign with solanaKey — the baseClient doc comment says exactly that. So every paid GET failed for Solana users with a misleading "no wallet is configured", before signing was ever attempted.

Replaced with hasWallet(), which resolves the expected key per chain. This was the only privateKey == nil guard in the repo.

Impact

Restores paid GET access for Solana on dex.go, market.go (3 call sites), prediction_market.go, and defi.go — all of which hang off *LLMClient, which has NewLLMClientSolana. POST paths use a different code path and were never affected, which is why this went unnoticed.

Correction: the original description also listed surf.go:244. That was wrong. NewSurfClient only calls newBaseClient, so a SurfClient can never have chain == "solana" — the guard was never what blocked surf, and surf stays unreachable for Solana after this fix. Tracked in #12.

Testing

  • TestPaidGetSolanaSignsInsteadOfRejecting — a Solana client with a configured wallet completes a paid GET and the server receives a real SVM exact-scheme PAYMENT-SIGNATURE. Watched it fail first against the old guard, reproducing the exact user-facing error: endpoint returned 402 but no wallet is configured.
  • TestPaidGetWithoutWalletStillRejected — the guard still fires for a Solana client with no solanaKey and a Base client with no privateKey, so this does not weaken the check.
  • Full suite green with -race; go vet clean.

VERSION/CHANGELOG intentionally untouched — left for /ship.

Provenance

Surfaced by Codex during the /review pass on #7 while tracing callers of CreateSolanaPaymentPayload. Not introduced by #7, and deliberately kept out of it to avoid widening the blast radius of a payment-path change.

1bcMax added 2 commits August 3, 2026 22:44
doGetWithPayment guarded the 402 branch on `bc.privateKey == nil`, but Solana
clients leave privateKey nil by design and sign with solanaKey (as the
baseClient doc comment states). Every paid GET surface therefore failed for
Solana users with a misleading "no wallet is configured" before signing was
ever attempted: dex, market (3 call sites), prediction market, defi and surf.
POST paths use a different code path, which is why this went unnoticed.

Replace the check with hasWallet(), which resolves the expected key per chain.

Closes #8
The new test signed against production Solana RPC on every run. The
baseClient literal left solanaRPCURL empty, so CreateSolanaPaymentPayload
fell back to DefaultSolanaRPCURL and cachedSolanaBlockhash issued a live
request to sol.blockrun.ai. Proven by running with egress blocked:

  failed to fetch blockhash: Post "https://sol.blockrun.ai/api/v1/solana/rpc"

The recentBlockhash in Extra was dead data: server-provided blockhash is
d73f4a7, which is not an ancestor of this branch, so nothing here reads
option.Extra["recentBlockhash"]. The helper comment claiming "zero RPC to
sign" was false, and that claim is what let the network call through.

Pin solanaRPCURL to newRPCCounterServer instead, and assert the signed
transaction carries the blockhash that fake served rather than merely
being non-zero, so the check fails on a stub as well as on a zero hash.

Add TestPaidGetBaseSignsInsteadOfRejecting. hasWallet is the gate on the
money path and only three of its four quadrants were covered; mutating
the Base branch to `return false` — which breaks every paid GET on the
SDK's default chain — left the whole suite green. Both branches are now
mutation-covered: each mutation fails its own test and nothing else.

Also reset the package-level blockhash cache, matching every other Solana
test, and reuse testPaymentOption instead of duplicating it.

Full suite passes with network fully blocked, -race -count=2 -shuffle=on.
@VickyXAI
VickyXAI merged commit 942a267 into main Aug 4, 2026
1 check passed
@VickyXAI
VickyXAI deleted the fix/solana-paid-get branch August 4, 2026 04:17
VickyXAI pushed a commit that referenced this pull request Aug 4, 2026
Ships the Solana paid-GET fix from #9 (fixes #8). Solana clients were
rejected at the 402 branch of doGetWithPayment before signing was ever
attempted, so every paid GET — market data, dex, defi, prediction
markets — failed with "no wallet is configured" despite a valid wallet.

Nothing else since 0.19.1.
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.

Solana clients cannot pay for any GET endpoint (402 rejected before signing)

1 participant