Files
khadhroony-solana-project/crates/ksp-program-api/USAGE.md
2026-08-28 14:21:21 +02:00

148 lines
4.4 KiB
Markdown

<!-- file: crates/ksp-program-api/USAGE.md -->
<!-- version: 3 -->
# 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
```rust
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 :
```rust
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 :
```rust
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
```rust
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 :
```rust
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 :
```text
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.