kb_rpc
Ce crate contient les clients et adaptateurs Solana JSON-RPC HTTP/WebSocket du workspace. Il reste indépendant des stores concrets, des décodeurs, des matérialiseurs, du wallet et de Tauri.
API publique principale
| Famille d’exports | Usage |
|---|---|
RpcEndpoint, SolanaRpcClient |
Configuration d’un endpoint et abstraction minimale d’un client RPC. |
HttpClient, HttpEndpointPool |
Appels JSON-RPC HTTP et routage déterministe par rôle/request kind. |
WsClient, WsEndpointPool |
Configuration WebSocket et sélection d’un endpoint compatible par rôle. |
StandardWsRequest, StandardWsNotification, WsSession |
Neuf contrats PubSub typés et runtime persistant multiplexé avec unsubscribe, reconnexion et réabonnement bornés. |
JsonRpcRequest, JsonRpcResponse, parse_json_rpc_text(...) |
Contrats et parsing JSON-RPC 2.0 communs aux transports. |
GetTransactionConfig, GetTransactionAdapter, CanonicalTransactionAdapter |
Acquisition et adaptation d’une transaction vers le modèle canonique. |
GetSignaturesForAddressConfig, AddressSignatureInfo |
Pagination bornée des signatures pour les backfills. |
configurations/résultats execution_rpc |
Paramètres et réponses typés pour cluster, blockhash, frais, simulation, comptes, airdrop, envoi et confirmation. |
fonctions adapt_* |
Conversion explicite d’une valeur JSON-RPC en contrat typé validé. |
validate_solana_hash_text, validate_solana_pubkey_text, validate_transaction_signature_text |
Validation base58 et longueur des identifiants Solana. |
request_kind_from_method(...) |
Normalisation stable du nom d’une méthode pour le routage d’endpoint. |
StandardHttpRequest, requêtes Get*Request, configurations Rpc*Config |
Contrats configurables propres à kb_rpc pour toutes les méthodes HTTP standard. |
Les méthodes réseau retournent kb_core::Result. Les fonctions adapt_* sont utiles aux tests, aux transports alternatifs et à l’analyse de réponses déjà acquises ; elles n’effectuent aucun I/O.
Exemple minimal
let config = kb_rpc::GetLatestBlockhashConfig::confirmed();
let result = client.get_latest_blockhash(&config).await?;
let blockhash = result.blockhash;
L’application choisit un HttpClient direct ou un HttpEndpointPool. Le pool vérifie les rôles et request kinds avant d’appeler le client ; il ne modifie pas la sémantique du résultat.
Transports et routage
- client HTTP JSON-RPC standard basé sur
reqwest; - pool HTTP sélectionné par
roleetrequest_kind; - client WebSocket standard basé sur
tokio-tungstenite; - pool WebSocket par rôle ;
- contrats JSON-RPC 2.0 communs ;
- tracing canonique
kb_rpcsans journalisation des secrets intégrés aux URL.
Acquisition canonique
getTransaction
GetTransactionConfig, GetTransactionAdapter et CanonicalTransactionAdapter transforment une réponse JSON-RPC standard en kb_model::CanonicalTransaction indépendante du fournisseur.
getSignaturesForAddress
GetSignaturesForAddressConfig construit les pages bornées before/until et AddressSignatureInfo conserve les métadonnées nécessaires au backfill.
RPC d’exécution — 0.4.2-pre.004 à pre.013
Les méthodes suivantes possèdent maintenant des configurations, résultats et adaptateurs typés :
| Méthode | Entrée principale | Résultat |
|---|---|---|
HttpClient::get_genesis_hash |
aucune | GenesisHashResult avec hash et classification Devnet/Testnet/Mainnet éventuelle. |
HttpClient::get_latest_blockhash |
GetLatestBlockhashConfig |
LatestBlockhashResult avec contexte, blockhash et dernière block height valide. |
HttpClient::get_fee_for_message |
message legacy/v0 sérialisé en base64, GetFeeForMessageConfig |
FeeForMessageResult, dont la valeur peut être absente si le blockhash n’est plus valide. |
HttpClient::simulate_transaction |
transaction sérialisée en base64, SimulateTransactionConfig |
SimulateTransactionResult avec erreur runtime, logs, unités, frais, blockhash de remplacement et diagnostics optionnels. |
HttpClient::get_account_info |
public key, GetAccountInfoConfig |
AccountInfoResult avec contexte, métadonnées, space et données complètes optionnelles bornées. |
HttpClient::get_minimum_balance_for_rent_exemption |
longueur de données, GetMinimumBalanceForRentExemptionConfig |
minimum rent-exempt en lamports pour cette taille. |
HttpClient::get_balance |
public key, GetBalanceConfig |
BalanceResult avec contexte et lamports. |
HttpClient::request_airdrop |
public key, lamports, RequestAirdropConfig |
AirdropResult avec signature du faucet. |
HttpClient::send_transaction |
transaction signée base64, signature primaire attendue, SendTransactionConfig |
SendTransactionResult uniquement si la signature RPC correspond à la transaction locale. |
HttpClient::get_signature_statuses |
une à 256 signatures, GetSignatureStatusesConfig |
SignatureStatusesResult positionnel. |
HttpClient::get_block_height |
GetBlockHeightConfig |
BlockHeightResult. |
Chaque méthode existe également sur HttpEndpointPool avec le suffixe _for_role afin de conserver le routage configuré.
SimulateTransactionConfig::unsigned_with_replacement() prépare une simulation sans vérification de signature avec remplacement du recent blockhash. Elle permet de simuler avant la phase de signature, conformément au pipeline d’exécution du projet.
SimulateTransactionResult::to_execution_result(...) convertit le résultat RPC vers kb_execution_api::ExecutionSimulationResult. Le contexte de cluster, de blockhash récent ou de nonce durable reste fourni explicitement par l’orchestrateur ; kb_rpc ne l’invente pas.
Les adaptateurs appliquent :
- validation base58 des genesis hashes et blockhashes ;
- validation base64 non vide et bornée des messages/transactions ;
- limite locale du nombre de snapshots de comptes demandés ;
- conservation provider-neutral des erreurs, return data, inner instructions et comptes simulés ;
- lecture metadata-only de l’existence, du solde, de l’owner, de
spaceet du statut executable avecdataSlice.length = 0; - lecture optionnelle des données complètes en base64 avec limite locale, contrôle de l’encodage et égalité stricte entre
spaceet longueur décodée ; - conservation explicite du minimum rent-exempt et de la longueur de données demandée ;
- distinction entre erreur de transport/JSON-RPC et erreur runtime de la transaction simulée.
Modes getAccountInfo
GetAccountInfoConfig::confirmed() conserve le mode léger historique. La requête utilise dataSlice = { offset: 0, length: 0 } et l’adaptateur exige un payload décodé vide tout en conservant le champ space complet.
GetAccountInfoConfig::confirmed_with_data(max_data_bytes) demande les données complètes en omettant dataSlice. La limite doit être comprise entre 1 et 65 536 octets. L’adaptateur refuse avant utilisation :
- un
spacesupérieur à la limite demandée ; - un tuple
datamal formé ; - un encodage différent de
base64; - un payload encodé ou décodé trop grand ;
- une longueur décodée différente de
space.
Ce mode est utilisé pour charger exactement les 80 octets d’un compte durable nonce avant validation dans kb_execution_solana. Le RPC ne décode pas lui-même la sémantique du compte.
Classification du cluster
Les genesis hashes officiels Devnet, Testnet et Mainnet sont reconnus. Le hash Mainnet n’a pas changé ; mainnet-beta reste un alias historique encore utilisé par les endpoints RPC et la CLI. Le contrat public utilise ExecutionCluster::Mainnet, sérialisé mainnet, tout en acceptant mainnet_beta à la désérialisation pour compatibilité. Un hash différent reste non classifié : il peut correspondre à un validateur local ou à un cluster privé et doit être rapproché du contexte attendu par l’orchestrateur.
Pour le chemin de signature, SimulateTransactionConfig::unsigned_exact() conserve le blockhash du message. unsigned_with_replacement() reste disponible pour le diagnostic, mais son résultat est marqué par le contrat commun et ne peut pas autoriser la signature ou l’envoi du message original.
Envoi et confirmation bornée
SendTransactionConfig interdit skipPreflight = true dans le chemin d’exécution. Il peut être construit depuis ExecutionConfig, transmet maxRetries et minContextSlot, puis vérifie que la signature retournée par le nœud est exactement la signature primaire calculée localement.
ConfirmTransactionConfig borne l’intervalle et le nombre de polls. HttpEndpointPool::confirm_transaction_for_roles interroge getSignatureStatuses, contrôle l’erreur runtime, compare le commitment demandé et utilise getBlockHeight lorsqu’une dernière block height valide est connue. Le résultat commun contient le statut, le slot éventuel, le nombre de tentatives, la dernière block height observée et le diagnostic éventuel.
Frontières
kb_rpc ne construit pas le message, ne résout aucun signer et ne signe rien. Il accepte uniquement un payload déjà signé et conserve l’envoi séparé de la confirmation :
PreparedExecutionPlan
-> kb_execution_solana build/simulation/signature
-> kb_rpc sendTransaction
-> kb_rpc confirmation bornée
-> orchestration post-exécution
Validation
Les tests offline vérifient les paramètres JSON-RPC, les réponses valides/nulles, les erreurs runtime, les hashes invalides, les payloads base64 invalides, les limites des données de compte, les divergences space/longueur, la classification de cluster et la conversion vers le contrat d’exécution commun.
Informations d’époque pour l’exécution stateful
GetEpochInfoConfig, EpochInfoResult, HttpClient::get_epoch_info et HttpEndpointPool::get_epoch_info_for_role encapsulent getEpochInfo avec commitment et minContextSlot optionnel. Cette primitive est utilisée pour les fenêtres de slot ALT/Slashing et les délais de fermeture. Elle reste indépendante de toute logique métier d’exécution.
Inventaire HTTP standard configurable — 0.4.2-pre.024
STANDARD_HTTP_METHODS enregistre exactement les 52 méthodes HTTP de la référence Solana. Elles possèdent maintenant toutes un contrat typé : les 14 adaptateurs spécialisés existants restent inchangés et les 38 méthodes auparavant limitées au JSON brut utilisent des requêtes Get*Request propres à kb_rpc.
La couche configurable ne réexporte aucun DTO d’Agave. Les options sont des champs Option indépendants : une valeur absente n’est pas sérialisée, tandis que Some(false), Some(0) ou Some([]) reste distinguable lorsqu’il s’agit d’une valeur valide du contrat RPC. Les types officiels peuvent servir d’oracle dans les tests, mais ne constituent pas l’API publique du crate.
let request = kb_rpc::GetProgramAccountsRequest {
program_id,
config: Some(kb_rpc::RpcProgramAccountsConfig {
filters: Some(vec![kb_rpc::RpcProgramAccountFilter::DataSize(165)]),
encoding: Some(kb_rpc::RpcAccountEncoding::Base64Zstd),
data_slice: None,
commitment: Some(kb_rpc::RpcCommitmentLevel::Confirmed),
min_context_slot: Some(anchor_slot),
with_context: Some(true),
sort_results: Some(true),
}),
};
let response = client.execute_standard_request(&request).await?;
Le même contrat est disponible via HttpEndpointPool::execute_standard_request_for_role. La requête fournit son nom de méthode, construit le tableau positionnel exact et définit son type de réponse associé. Le transport refuse un type absent du registre ou déclaré avec un contrat autre que typed_adapter.
Les validations locales couvrent notamment :
- 100 comptes maximum pour
getMultipleAccounts; - 128 comptes verrouillés maximum pour
getRecentPrioritizationFees; - 500 000 slots maximum pour les plages et limites de blocs ;
- 720 entrées maximum pour
getRecentPerformanceSamples; - 128 octets décodés maximum pour un filtre memcmp ;
- refus de
processedpour les méthodes historiques qui ne l’acceptent pas ; - incompatibilité
jsonParsed/dataSlice; - validation base58 de toutes les clés et blockhashes structurants.
| Surface | Inventaire | Contrat actuel |
|---|---|---|
| HTTP | 52 méthodes | 52 adaptateurs typés, 0 contrat standard limité au JSON brut |
| WebSocket | 9 paires / 18 méthodes | 9 requêtes typées, 9 notifications typées et runtime persistant réutilisable |
| WebSocket instable | 3 paires | block, slotsUpdates et vote, refusées sans capacité explicite de l’endpoint |
execute_standard_method_raw reste disponible pour les outils bas niveau qui manipulent explicitement un StandardHttpMethodSpec, mais n’est plus nécessaire pour couvrir une méthode HTTP standard.
PubSub WebSocket standard — 0.4.2-pre.025
StandardWsRequest représente exactement les neuf familles officielles. Chaque variante construit son tableau de paramètres sans valeur implicite imposée par la bibliothèque : encodage, dataSlice, filtres, commitment, détails de bloc, rewards, version maximale et notification anticipée de signature restent sélectionnables indépendamment.
adapt_standard_ws_notification transforme les neuf méthodes de notification en StandardWsNotification. Les réponses contextuelles, les comptes directs ou contextualisés de programNotification, le marqueur receivedSignature, les mises à jour de slots taguées et les votes gossip sont conservés dans des types propres à kb_rpc.
let client = pool.select_client_for_role_and_method("slot_notifications", "slotSubscribe")?;
let session = kb_rpc::WsSession::connect(
client,
kb_rpc::StandardWsCapabilities::default(),
kb_rpc::WsReconnectPolicy::bounded(3, 250, 2_000)?,
)
.await?;
let mut events = session.subscribe_events();
let acknowledgement = session
.subscribe(kb_rpc::StandardWsRequest::Slot(kb_rpc::SlotSubscribeRequest))
.await?;
let remote_id = acknowledgement.subscription.remote_subscription_id;
La session possède un identifiant local stable par souscription et suit séparément l’identifiant distant attribué par le nœud. Après reconnexion, elle réémet les requêtes actives, remappe les IDs distants et publie SubscriptionRemapped. L’unsubscribe explicite attend une réponse booléenne vraie ; les requêtes et désabonnements ont leurs timeouts propres. Une notification terminale signatureNotification retire automatiquement la souscription one-shot, tandis que receivedSignature la conserve jusqu’au statut terminal. La fermeture envoie des désabonnements best-effort avant la frame Close.
Les méthodes instables blockSubscribe, slotsUpdatesSubscribe et voteSubscribe ne sont jamais déduites d’un simple nom de méthode demandé : StandardWsCapabilities::from_endpoint exige qu’un rôle activé de l’endpoint annonce explicitement le request kind correspondant, ou un wildcard volontaire.
La première souscription réelle sert de probe du nœud. Lorsqu’une réponse JSON-RPC indique que la méthode est absente, non activée, indisponible ou non supportée, WsSession désactive uniquement la capacité concernée, met à jour son snapshot et refuse localement les appels suivants. Une erreur de paramètres, d’authentification ou de rate limit ne désactive pas la capacité.
La validation finale 0.4.2 compte 113 tests kb_rpc. Les logs Tauri réels confirment des souscriptions et désabonnements slot, root et program, ainsi que le garde-fou interdisant de changer d’endpoint sans fermer la session active. L’état détaillé est documenté dans docs/SOLANA_NATIVE_RPC_CLOSURE_AUDIT.md.