Get Priority Fee Estimate
Learn how to estimate Solana priority fees using Helius's getPriorityFeeEstimate RPC extension through solana-py.
Helius extends the standard Solana JSON-RPC API with getPriorityFeeEstimate. solana-py does not define a dedicated model for that vendor-specific method, but its public JsonRpcRequest and AsyncClient.send_rpc_request APIs let you add strong request and response types without implementing an HTTP client.
Ref: https://www.helius.dev/docs/api-reference/priority-fee/getpriorityfeeestimate
Code Example
import asyncio
from enum import StrEnum
from typing import Literal, TypedDict
from pydantic import BaseModel, Field
from solana.rpc.async_api import AsyncClient
from solana.rpc.jsonrpc import JsonRpcRequest
HELIUS_RPC_URL = "https://mainnet.helius-rpc.com/?api-key=YOUR_HELIUS_API_KEY"
TARGET_ACCOUNT = "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P"
class TransactionEncoding(StrEnum):
"""Transaction encodings accepted by Helius."""
BASE58 = "Base58"
BASE64 = "Base64"
class PriorityLevel(StrEnum):
"""Helius priority levels, ordered from cheapest to most aggressive."""
MIN = "Min"
LOW = "Low"
MEDIUM = "Medium"
HIGH = "High"
VERY_HIGH = "VeryHigh"
UNSAFE_MAX = "UnsafeMax"
# Request types are ordered from nested fields to the JSON-RPC envelope.
class PriorityFeeOptions(TypedDict, total=False):
"""Optional Helius controls, using the exact JSON field names."""
transactionEncoding: TransactionEncoding
priorityLevel: PriorityLevel
includeAllPriorityFeeLevels: bool
lookbackSlots: int
includeVote: bool
recommended: bool
evaluateEmptySlotAsZero: bool
class PriorityFeeEstimateParams(TypedDict, total=False):
"""One parameter object accepted by getPriorityFeeEstimate."""
transaction: str
accountKeys: list[str]
options: PriorityFeeOptions
class GetPriorityFeeEstimateRequest(JsonRpcRequest):
"""Bind solana-py's generic request model to the Helius method."""
method: Literal["getPriorityFeeEstimate"] = "getPriorityFeeEstimate"
params: list[PriorityFeeEstimateParams]
# Response types are ordered from nested data to the top-level result.
class PriorityFeeLevels(BaseModel):
"""Estimates for all levels when includeAllPriorityFeeLevels is true."""
minimum: float = Field(alias="min")
low: float
medium: float
high: float
very_high: float = Field(alias="veryHigh")
unsafe_max: float = Field(alias="unsafeMax")
class PriorityFeeEstimateResult(BaseModel):
"""The result object returned by Helius."""
priority_fee_estimate: float | None = Field(default=None, alias="priorityFeeEstimate")
priority_fee_levels: PriorityFeeLevels | None = Field(default=None, alias="priorityFeeLevels")
async def main() -> None:
"""Build, display, and send one strongly typed Helius RPC request."""
# TypedDict checks this nested shape statically while keeping the payload
# identical to the JSON documented by Helius.
request = GetPriorityFeeEstimateRequest(
params=[
{
# accountKeys makes the estimate reflect transactions that
# lock this program/account instead of only global fee data.
"accountKeys": [TARGET_ACCOUNT],
"options": {"includeAllPriorityFeeLevels": True},
},
],
)
print("Serialized request:")
print(request.to_json(indent=2))
print()
# Keep credentials out of teaching material. Replace only this placeholder
# before running the live request; no environment variable is consulted.
if "YOUR_HELIUS_API_KEY" in HELIUS_RPC_URL:
print("Replace YOUR_HELIUS_API_KEY in HELIUS_RPC_URL to send the request.")
return
async with AsyncClient(HELIUS_RPC_URL) as client:
# send_rpc_request handles the JSON-RPC envelope and uses Pydantic's
# TypeAdapter internally to validate the result as our custom model.
result = await client.send_rpc_request(request, PriorityFeeEstimateResult)
print("Response result:")
print(result.model_dump_json(by_alias=True, exclude_none=True, indent=2))
if __name__ == "__main__":
asyncio.run(main())
Explanation
- Bind the method with a
JsonRpcRequestsubclass —GetPriorityFeeEstimateRequestlocksmethodto the"getPriorityFeeEstimate"literal and typesparamsas a list ofPriorityFeeEstimateParams, so solana-py's generic request model is bound to the Helius method. - TypedDict for request payloads —
PriorityFeeOptionsandPriorityFeeEstimateParamsmirror the exact JSON field names documented by Helius. This keeps the serialized wire payload identical while giving you static type checks on the nested shape. - Pydantic models for the response —
PriorityFeeLevelsandPriorityFeeEstimateResultuseField(alias=...)to map Helius's camelCase JSON keys (priorityFeeEstimate,veryHigh,unsafeMax) to snake_case Python attributes, withmodel_dump_json(by_alias=True)to round-trip them. - Send with
AsyncClient.send_rpc_request— This API handles the JSON-RPC envelope (including thejsonrpcandidfields) and uses Pydantic'sTypeAdapterinternally to validate the result as your customPriorityFeeEstimateResult, so no custom HTTP client is required. accountKeysfor accurate estimates — Passing the target account inaccountKeysmakes the estimate reflect transactions that lock that program/account instead of only global fee data.includeAllPriorityFeeLevels: Truerequests estimates for every priority level.- Credential placeholder — The example prints the serialized request and a hint instead of sending when the
YOUR_HELIUS_API_KEYplaceholder is still inHELIUS_RPC_URL, keeping credentials out of teaching material.