6.8 KiB
Utilisation de ksp-raw-transaction-lib
Cette page décrit la façade publique durable de ksp-raw-transaction-lib. Les consumers utilisent uniquement les exports du crate-root.
Parser une signature transactionnelle
Lorsqu'une source fournit une signature Base58 textuelle, la convertir avec le parser commun plutôt que de dupliquer le décodage :
fn parse_signature(value: &str) -> ksp_core_lib::Result<ksp_store_api::RawTransactionSignature> {
return ksp_raw_transaction_lib::parse_raw_transaction_signature(value);
}
Le résultat contient exactement 64 bytes canoniques. Les entrées vides, hors bornes, Base58 invalides ou de longueur décodée incorrecte sont rejetées sans recopier la valeur hostile dans l'erreur.
Lorsqu'un wire Base64 complet contient déjà son tableau de signatures, utiliser :
fn embedded_signature(value: &str) -> ksp_core_lib::Result<ksp_store_api::RawTransactionSignature> {
return ksp_raw_transaction_lib::extract_raw_transaction_signature_from_binary_base64(value);
}
Construire et sérialiser un wire Solana source-neutral
Le producer peut projeter son DTO Transport/protobuf vers les types RawSolana*, puis utiliser le sérialiseur commun. Exemple V1 minimal :
fn serialize_v1() -> ksp_core_lib::Result<std::string::String> {
let message = ksp_raw_transaction_lib::RawSolanaTransactionMessage::new(
ksp_raw_transaction_lib::RawSolanaMessageVersion::V1,
ksp_raw_transaction_lib::RawSolanaMessageHeader::new(1, 0, 0),
vec![[1_u8; 32]],
[2_u8; 32],
vec![ksp_raw_transaction_lib::RawSolanaCompiledInstruction::new(0, vec![0], vec![3])],
vec![],
std::option::Option::Some(ksp_raw_transaction_lib::RawSolanaTransactionConfig::default()),
);
let wire = ksp_raw_transaction_lib::RawSolanaTransactionWire::new(vec![[4_u8; 64]], message);
return ksp_raw_transaction_lib::serialize_solana_transaction_wire_base64(&wire);
}
Pour Legacy ou V0, choisir RawSolanaMessageVersion::Legacy ou V0 et fournir uniquement les éléments admis par cette version. Le sérialiseur valide les invariants structurels avant de produire les bytes.
RawSolanaAddressTableLookup représente les lookups V0. RawSolanaTransactionConfig représente la configuration inline V1 ; le cas explicite où toutes ses options valent None reste sémantiquement présent.
Construire le matériau RAW canonique
Une fois le wire transactionnel Base64 et les métadonnées source-neutral disponibles, construire RawTransactionMaterial. Les états wire doivent conserver la différence entre champ absent, null explicite et valeur :
fn material(
network: ksp_store_api::RawNetworkId,
signature: ksp_store_api::RawTransactionSignature,
transaction_base64: std::string::String,
) -> ksp_raw_transaction_lib::RawTransactionMaterial {
return ksp_raw_transaction_lib::RawTransactionMaterial::binary_base64(
network,
signature,
42,
std::option::Option::None,
transaction_base64,
ksp_raw_transaction_lib::RawTransactionWireField::Omitted,
ksp_raw_transaction_lib::RawTransactionWireField::Value(ksp_raw_transaction_lib::RawTransactionVersion::Legacy),
ksp_raw_transaction_lib::RawTransactionWireField::Omitted,
);
}
Pour une source où la signature doit être extraite du wire lui-même, RawTransactionMaterial::binary_base64_with_embedded_signature évite un second parser producer-owned.
Canonicaliser vers RawTransaction
La canonicalisation est déterministe pour un même matériau complet :
fn canonicalize(
material: ksp_raw_transaction_lib::RawTransactionMaterial,
) -> ksp_core_lib::Result<ksp_store_api::RawTransaction> {
return ksp_raw_transaction_lib::canonicalize_raw_transaction(material);
}
La crate :
- canonicalise les sous-arbres JSON significatifs ;
- conserve les états omission /
null/ valeur ; - construit le payload au format KSP RAW Transaction ;
- calcule son SHA-256 ;
- applique les bornes communes avant construction du modèle Store.
Elle ne persiste pas la transaction et ne choisit aucune politique de retry, endpoint ou source.
Associer l'observation du producer
Le producer construit sa provenance avec les types Store API, puis assemble l'entité et l'observation :
fn acquisition(
transaction: ksp_store_api::RawTransaction,
) -> ksp_core_lib::Result<ksp_raw_transaction_lib::RawTransactionAcquisition> {
let provider = match ksp_store_api::RawProvenanceCode::new("example") {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let protocol = match ksp_store_api::RawProvenanceCode::new("solana.http") {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let method = match ksp_store_api::RawProvenanceCode::new("get_transaction") {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let received_at = match ksp_store_api::RawTimestamp::from_unix_millis(1_700_000_000_000) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let provenance = ksp_store_api::RawAcquisitionProvenance::new(
provider,
protocol,
method,
ksp_store_api::RawAcquisitionOrigin::Live,
received_at,
);
return std::result::Result::Ok(ksp_raw_transaction_lib::assemble_raw_transaction_acquisition(
transaction,
ksp_store_api::RawObservationKey::new([7_u8; 32]),
provenance,
));
}
La clé d'observation doit être déterministe selon la politique du producer. Plusieurs sources peuvent produire des observations différentes pour la même identité canonique (network, signature).
Persister depuis un Job ou un Worker
La common crate ne dépend pas du Store runtime. Le lifecycle host concret récupère les deux parties puis appelle la façade Store appropriée :
let (transaction, observation) = acquisition.into_parts();
// Le Job/Worker concret transmet ensuite transaction + observation à ksp-store-lib.
Ne pas introduire ksp-store-lib, Transport, Config, Job ou Worker dans ksp-raw-transaction-lib pour simplifier cet appel. La direction de dépendance reste du producer vers la common RAW, puis du producer vers le Store runtime.
Frontière avec STRUCTURAL
Ne pas utiliser cette crate pour décoder des Programs ou pour produire directement des unités STRUCTURAL. Son résultat reste D1 RAW. La décomposition RAW -> STRUCTURAL appartient à une couche ultérieure et réutilise le RAW durable comme input.