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

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.