Forums

Solana/solders

To whomever this may concern,

I hope you’re doing well. My name is Joseph Bliss.I’m using Python 3.9 in a PythonAnywhere environment for a Solana aggregator project that frequently requires address lookup tables. I’ve attempted numerous combinations of solana-py (e.g. 0.26.0, 0.36.5, 0.36.6) and solders (e.g. 0.24.x, 0.25.0, 0.26.x, etc.)—almost every version ChatGPT recommended—yet I’m still facing: 1. proxy Argument Issue • Even after removing all proxy= references in my own scripts, I get TypeError: init() got an unexpected keyword argument 'proxy' in Client(...). I suspect a custom or forked build of solana-py referencing proxy in HTTPProvider. 2. Versioned Transaction Mismatches • Some solders versions are missing .sign([...]); others are missing .create_signatures(...). So I can’t reliably decode & sign the aggregator’s versioned transaction. • I’ve also run into “No matching distribution found” for certain solders releases on PythonAnywhere, or partial upgrades that break the environment.

Below is my entire diagnostic.py script, which does a minimal aggregator call (GET /quote, POST /swap) for wSOL→USDC, then tries to decode & sign the versioned transaction. If you see any leftover references to proxy or other mismatches, please let me know. I’d love any guidance on: • Recommended solana-py + solders versions (for Python 3.9) that handle versioned transactions without the proxy fiasco. • Whether there’s a known fork that includes proxy=. • Best practices for building solders from source on PythonAnywhere (if wheels aren’t available).

Thank you so much for your time and for the libraries you’ve created. I’m happy to provide more logs or environment details if needed.

!/usr/bin/env python3

import os import sys import json import requests import base58 import base64 from dotenv import load_dotenv

solana-py for RPC (no proxy argument)

from solana.rpc.api import Client from solana.rpc.types import TxOpts

solders for decode/sign versioned transactions

from solders.keypair import Keypair as SoldersKeypair from solders.transaction import VersionedTransaction

load_dotenv()

SOLANA_RPC_URL = os.getenv("SOLANA_RPC_URL", "https://api.mainnet-beta.solana.com") PHANTOM_PRIVATE_KEY = os.getenv("PHANTOM_PRIVATE_KEY", "")

if not PHANTOM_PRIVATE_KEY: print("No PHANTOM_PRIVATE_KEY found in .env. Exiting.") sys.exit(1)

1) Decode base58 private key -> solders Keypair

try: decoded = base58.b58decode(PHANTOM_PRIVATE_KEY) user_keypair = SoldersKeypair.from_bytes(decoded) except Exception as e: print("Error decoding PHANTOM_PRIVATE_KEY:", e) sys.exit(1)

2) Create solana-py client (no 'proxy' param)

client = Client(SOLANA_RPC_URL) print("RPC =>", SOLANA_RPC_URL) print("Solders Keypair pubkey =>", user_keypair.pubkey())

Minimal aggregator usage

QUOTE_URL = "https://api.jup.ag/swap/v1/quote" SWAP_URL = "https://api.jup.ag/swap/v1/swap"

WSOL_MINT = "So11111111111111111111111111111111111111112" USDC_MINT = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"

def main(): # 3) GET /quote => wSOL->USDC (0.1 SOL) amount_lamports = 100_000_000 # 0.1 SOL if wSOL has 9 decimals quote_params = { "inputMint": WSOL_MINT, "outputMint": USDC_MINT, "amount": str(amount_lamports), "swapMode": "ExactIn", "slippageBps": "50" } print("Requesting aggregator quote => wSOL->USDC, 0.1 SOL, slippage=0.5%")

try:
    r = requests.get(QUOTE_URL, params=quote_params, timeout=10)
    if r.status_code != 200:
        print(f"HTTP {r.status_code} => {r.text}")
        return
    quote_json = r.json()
    print("\nFull Quote JSON =>", json.dumps(quote_json, indent=2))

    if "routePlan" not in quote_json or len(quote_json["routePlan"]) == 0:
        print("No route found => aggregator returned empty routePlan.")
        return
    print("Aggregator found a route for wSOL->USDC!")
except Exception as e:
    print("Error calling aggregator GET /quote =>", e)
    return

# 4) POST /swap => minimal body
swap_body = {
    "quoteResponse": quote_json,
    "userPublicKey": str(user_keypair.pubkey()),
    "wrapAndUnwrapSol": True
}
print("\nSwap Body =>", json.dumps(swap_body, indent=2))

try:
    s = requests.post(SWAP_URL, json=swap_body, timeout=10)
    if s.status_code != 200:
        print(f"HTTP {s.status_code} => {s.text}")
        return
    swap_json = s.json()
    print("\nFull Swap JSON =>", json.dumps(swap_json, indent=2))

    if "swapTransaction" not in swap_json:
        print("No 'swapTransaction' => aggregator returned no transaction.")
        return
    swap_tx_b64 = swap_json["swapTransaction"]
    print("Got aggregator transaction =>", swap_tx_b64[:60], "...")
except Exception as e:
    print("Error calling aggregator POST /swap =>", e)
    return

# 5) Decode, sign, send with solders + solana-py
try:
    tx_bytes = base64.b64decode(swap_tx_b64)
    versioned_tx = VersionedTransaction.from_bytes(tx_bytes)

    # If solders version has create_signatures(...):
    signatures = versioned_tx.create_signatures([user_keypair])
    versioned_tx.set_signatures(signatures)
    serialized = versioned_tx.serialize()

    # If older approach .sign([...]) is available, you'd do that instead:
    # versioned_tx.sign([user_keypair])
    # serialized = versioned_tx.to_bytes()

    send_resp = client.send_raw_transaction(serialized, opts=TxOpts(skip_preflight=True, max_retries=3))
    if isinstance(send_resp, dict):
        if "result" in send_resp:
            sig = send_resp["result"]
            print("Transaction submitted =>", sig)
            client.confirm_transaction(sig, commitment="finalized")
            print(f"Confirmed => https://solscan.io/tx/{sig}")
        elif "error" in send_resp:
            print("Transaction error =>", send_resp["error"])
    else:
        print("Unexpected =>", send_resp)

except Exception as e:
    print("Error signing or sending transaction =>", e)

if name == "main": main()

Thank you again for your time, and please let me know if there’s any additional detail or logs I can provide. I truly appreciate your work on these libraries and any advice you might have to resolve these issues.

Sincerely,

Joseph Bliss

Unexpected keyword argument in all the versions sounds like ChatGPT was hallucinating api. That's common problem. The known solution is to read the docs of the package you try to use.