4.4 KiB
Usage de ksp-program-api
Cette page décrit la surface publique disponible à partir de 0.2.14-pre.004. Utiliser uniquement les exports du crate-root ; aucun module interne ne fait partie du contrat consommable.
Construire un input Program avec la façade
let program_id = ksp_program_api::Pubkey::new_from_array([1_u8; 32]);
let account_id = ksp_program_api::Pubkey::new_from_array([2_u8; 32]);
let account = ksp_program_api::ProgramAccountMeta::readonly(account_id, true);
let instruction = ksp_program_api::ProgramInstruction::try_new(
program_id,
std::vec![account],
std::vec![0x01_u8, 0x02, 0x03],
);
assert!(instruction.is_ok());
Pubkey, ProgramAccountMeta et ProgramInstruction conservent leur ownership Core/Interface.
Implémenter un decoder externe
Le type décodé reste entièrement possédé par la crate d'implémentation :
struct ExternalDecodedInstruction {
opcode: u8,
}
struct ExternalDecoder {
program_ids: [ksp_program_api::Pubkey; 1],
}
impl ksp_program_api::ProgramInstructionDecoder for ExternalDecoder {
type Decoded = ExternalDecodedInstruction;
fn program_ids(&self) -> &[ksp_program_api::Pubkey] {
return &self.program_ids;
}
fn recognize(
&self,
instruction: &ksp_program_api::ProgramInstruction,
) -> ksp_program_api::ProgramInstructionRecognition {
if instruction.program_id() != &self.program_ids[0] {
return ksp_program_api::ProgramInstructionRecognition::NoMatch;
}
return ksp_program_api::ProgramInstructionRecognition::ProgramMatch;
}
fn decode(
&self,
instruction: &ksp_program_api::ProgramInstruction,
) -> ksp_program_api::Result<ksp_program_api::ProgramInstructionDecodeOutcome<Self::Decoded>> {
let opcode = match instruction.data().first() {
std::option::Option::Some(value) => *value,
std::option::Option::None => {
return std::result::Result::Ok(
ksp_program_api::ProgramInstructionDecodeOutcome::Unsupported,
);
}
};
return std::result::Result::Ok(
ksp_program_api::ProgramInstructionDecodeOutcome::Decoded(
ExternalDecodedInstruction { opcode },
),
);
}
}
Aucun ksp-program-lib, enum centrale, Any, JSON ou codec n'est nécessaire. Le Program ID peut être un Pubkey opaque non enregistré par Core.
Sélection explicite
La sélection reste distincte du décodage :
let recognition = ksp_program_api::ProgramInstructionDecoder::recognize(
&decoder,
&instruction,
);
match recognition {
ksp_program_api::ProgramInstructionRecognition::NoMatch => {}
ksp_program_api::ProgramInstructionRecognition::ProgramMatch => {}
ksp_program_api::ProgramInstructionRecognition::ExactMatch => {}
_ => {}
}
L'enum est #[non_exhaustive]. decode n'est pas un substitut à recognize : il traite une instruction déjà sélectionnée pour le decoder.
Outcome et erreur
let outcome = ksp_program_api::ProgramInstructionDecoder::decode(
&decoder,
&instruction,
)?;
match outcome {
ksp_program_api::ProgramInstructionDecodeOutcome::Decoded(value) => {
let _opcode = value.opcode;
}
ksp_program_api::ProgramInstructionDecodeOutcome::Unsupported => {}
_ => {}
}
Une erreur réelle est un Err(ksp_program_api::Error). Unsupported n'est pas une deuxième forme d'erreur : il indique qu'une instruction reconnue n'est volontairement pas décodée par cette capability.
Debug sûr
ProgramInstructionDecodeOutcome<Decoded> possède un Debug volontairement opaque :
struct SecretDecoded;
let outcome = ksp_program_api::ProgramInstructionDecodeOutcome::Decoded(SecretDecoded);
assert_eq!(std::format!("{outcome:?}"), "Decoded");
SecretDecoded n'a pas besoin d'implémenter Debug et sa valeur n'est jamais rendue par l'outcome.
Hors surface pre.004
Il n'existe toujours aucun :
registry de decoders
composition dyn hétérogène
identity/version/coverage descriptor
payload canonique D3
ProgramAccountDecoder / Event / ReturnData
ProgramExecutionPreparer
execution policy
serde / JSON / codec
logging / runtime réseau
Ces surfaces ne doivent pas être simulées côté consumer. Elles attendent les vertical slices qui justifieront leurs contrats réels.