This commit is contained in:
2026-07-23 16:37:12 +02:00
parent 99c345f2f2
commit 0da75c1311
2159 changed files with 230833 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
# file: kb_executor_spl_associated_token_account/Cargo.toml
# version: 4
[package]
name = "kb_executor_spl_associated_token_account"
version.workspace = true
edition.workspace = true
license.workspace = true
publish.workspace = true
[dependencies]
kb_core = { path = "../kb_core" }
kb_execution_api = { path = "../kb_execution_api" }
kb_model = { path = "../kb_model" }
kb_program_ids = { path = "../kb_program_ids" }
serde_json.workspace = true
serde.workspace = true
solana-instruction.workspace = true
solana-pubkey.workspace = true
spl-associated-token-account-interface.workspace = true
tracing.workspace = true
ts-rs.workspace = true
[lints]
workspace = true

View File

@@ -0,0 +1,35 @@
<!-- file: kb_executor_spl_associated_token_account/README.md -->
<!-- version: 3 -->
# kb_executor_spl_associated_token_account
Ce crate construit les plans typés de la surface SPL Associated Token Account courante.
## Surface
- `Create` ;
- `CreateIdempotent` ;
- `RecoverNested` ;
- Token Program classique ou Token-2022 comme cible explicite de la dérivation.
Chaque plan conserve lordre et les flags des metas produits par le builder officiel de
`spl-associated-token-account-interface 2.0.0`. Les signataires requis sont dédupliqués séparément,
sans réordonner les comptes de linstruction.
## Garde-fous
La simulation est obligatoire, le mode par défaut reste `dry_run`, les plafonds de rent et de frais
sont explicites et le replay post-exécution complet est requis. Le préflight stateful Localnet/Devnet
est orchestré par `kb_pipeline` : il contrôle cluster, mints, PDA, comptes Token existants,
`RecoverNested`, signataires et solde couvrant le plafond rent-plus-frais.
Pour Token-2022, le préflight valide uniquement le préfixe commun Mint/Token Account et accepte des
octets dextension suffixés. Il ne décode ni instruction ni extension Token-2022 ; la simulation
officielle reste lautorité pour la taille de compte et le rent exacts liés aux extensions.
## Preuves Devnet
Les parcours contrôlés du 16 juillet 2026 ont validé `CreateIdempotent` pour un mint classique et
un mint Token-2022, puis la réutilisation des deux ATA avec second replay sans doublon. Un scénario
`RecoverNested` classique a transféré 1 000 000 000 unités brutes vers l'ATA wallet, fermé le nested
ATA et confirmé les postconditions ainsi que deux matérialisations distinctes lifecycle/risk.

View File

@@ -0,0 +1,490 @@
// file: kb_executor_spl_associated_token_account/src/builder.rs
// version: 4
//! Official ATA builders and conservative simulation-first plan validation.
macro_rules! parse_key {
($value:expr, $field:expr) => {
match $value.0.parse() {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => {
return std::result::Result::Err(kb_core::Error::new(
"execution_spl_ata_pubkey_invalid",
format!("invalid ATA {} public key: {error}", $field),
));
},
}
};
}
pub(crate) fn build_prepared_plan(
intent: &crate::SplAssociatedTokenAccountExecutionIntent,
) -> kb_core::Result<kb_execution_api::PreparedExecutionPlan> {
if intent.intent_id.trim().is_empty() {
return std::result::Result::Err(kb_core::Error::new(
"execution_spl_ata_intent_id_empty",
"ATA execution intent id must not be empty",
));
}
match crate::builder::validate_policy(intent) {
std::result::Result::Ok(()) => {},
std::result::Result::Err(error) => return std::result::Result::Err(error),
}
let fee_payer = parse_key!(&intent.fee_payer, "fee_payer");
let token_program_text = intent.operation.token_program().program_id();
let instruction = match &intent.operation {
crate::SplAssociatedTokenAccountOperation::Create {
wallet_owner,
mint,
token_program: _,
} => {
let wallet_owner = parse_key!(wallet_owner, "wallet_owner");
let mint = parse_key!(mint, "mint");
let token_program: solana_pubkey::Pubkey = match token_program_text.parse() {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => {
return std::result::Result::Err(kb_core::Error::new(
"execution_spl_ata_token_program_invalid",
error.to_string(),
));
},
};
spl_associated_token_account_interface::instruction::create_associated_token_account(
&fee_payer,
&wallet_owner,
&mint,
&token_program,
)
},
crate::SplAssociatedTokenAccountOperation::CreateIdempotent {
wallet_owner,
mint,
token_program: _,
} => {
let wallet_owner = parse_key!(wallet_owner, "wallet_owner");
let mint = parse_key!(mint, "mint");
let token_program: solana_pubkey::Pubkey = match token_program_text.parse() {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => {
return std::result::Result::Err(kb_core::Error::new(
"execution_spl_ata_token_program_invalid",
error.to_string(),
));
},
};
spl_associated_token_account_interface::instruction::create_associated_token_account_idempotent(
&fee_payer,
&wallet_owner,
&mint,
&token_program,
)
},
crate::SplAssociatedTokenAccountOperation::RecoverNested {
wallet_owner,
owner_mint,
nested_mint,
token_program: _,
} => {
let wallet_owner = parse_key!(wallet_owner, "wallet_owner");
let owner_mint = parse_key!(owner_mint, "owner_mint");
let nested_mint = parse_key!(nested_mint, "nested_mint");
let token_program: solana_pubkey::Pubkey = match token_program_text.parse() {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => {
return std::result::Result::Err(kb_core::Error::new(
"execution_spl_ata_token_program_invalid",
error.to_string(),
));
},
};
spl_associated_token_account_interface::instruction::recover_nested(
&wallet_owner,
&owner_mint,
&nested_mint,
&token_program,
)
},
};
let planned_instruction =
crate::builder::planned_instruction(intent.operation.operation_code(), &instruction);
let required_signers =
crate::builder::required_signers(&intent.fee_payer, &planned_instruction.accounts);
tracing::debug!(
target: crate::TRACING_TARGET,
action = "build_prepared_plan",
intent_id = %intent.intent_id,
operation_code = intent.operation.operation_code(),
token_program_id = token_program_text,
account_occurrence_count = planned_instruction.accounts.len(),
required_signer_count = required_signers.len(),
max_rent_lamports = intent.max_rent_lamports,
dry_run = intent.policy.dry_run,
"built SPL Associated Token Account execution plan"
);
return std::result::Result::Ok(kb_execution_api::PreparedExecutionPlan {
executor_name: "kb_executor_spl_associated_token_account".to_string(),
executor_version: env!("CARGO_PKG_VERSION").to_string(),
intent_id: intent.intent_id.clone(),
operation_code: intent.operation.operation_code().to_string(),
fee_payer: kb_model::Pubkey(fee_payer.to_string()),
instructions: std::vec![planned_instruction],
required_signers,
policy: intent.policy.clone(),
requested_spend_lamports: intent.max_rent_lamports,
requested_compute_unit_price_micro_lamports: std::option::Option::None,
});
}
fn validate_policy(
intent: &crate::SplAssociatedTokenAccountExecutionIntent,
) -> kb_core::Result<()> {
if intent.policy.simulation != kb_execution_api::ExecutionSimulationPolicy::Required {
return std::result::Result::Err(kb_core::Error::new(
"execution_spl_ata_simulation_required",
"ATA execution requires simulation before signing or sending",
));
}
if intent.operation.is_creation() && intent.max_rent_lamports == 0 {
return std::result::Result::Err(kb_core::Error::new(
"execution_spl_ata_rent_limit_missing",
"ATA creation requires a positive rent spending ceiling",
));
}
if !intent.operation.is_creation() && intent.max_rent_lamports != 0 {
return std::result::Result::Err(kb_core::Error::new(
"execution_spl_ata_recovery_rent_must_be_zero",
"RecoverNested must declare zero rent spending",
));
}
if intent.policy.cost_limit.max_spend_lamports
!= std::option::Option::Some(intent.max_rent_lamports)
{
return std::result::Result::Err(kb_core::Error::new(
"execution_spl_ata_spend_limit_mismatch",
"ATA policy max spend must equal the declared maximum rent lamports",
));
}
match intent.policy.cost_limit.max_fee_lamports {
std::option::Option::Some(value) if value > 0 => {},
std::option::Option::Some(_) | std::option::Option::None => {
return std::result::Result::Err(kb_core::Error::new(
"execution_spl_ata_fee_limit_missing",
"ATA execution requires a positive transaction fee ceiling",
));
},
}
let validation = &intent.policy.post_execution_validation;
if !validation.canonical_insert_required
|| !validation.core_extraction_required
|| !validation.decode_replay_required
|| !validation.materialization_required
{
return std::result::Result::Err(kb_core::Error::new(
"execution_spl_ata_post_validation_required",
"ATA execution requires canonical insertion, core extraction, decode replay and materialization validation",
));
}
return std::result::Result::Ok(());
}
fn planned_instruction(
operation_code: &str,
instruction: &solana_instruction::Instruction,
) -> kb_execution_api::PlannedInstruction {
return kb_execution_api::PlannedInstruction {
program_id: kb_model::ProgramId(instruction.program_id.to_string()),
operation_code: operation_code.to_string(),
accounts: instruction
.accounts
.iter()
.map(|account| {
return kb_execution_api::PlannedAccount {
pubkey: kb_model::Pubkey(account.pubkey.to_string()),
is_signer: account.is_signer,
is_writable: account.is_writable,
};
})
.collect(),
data: instruction.data.clone(),
};
}
fn required_signers(
fee_payer: &kb_model::Pubkey,
accounts: &[kb_execution_api::PlannedAccount],
) -> std::vec::Vec<kb_execution_api::RequiredSigner> {
let mut required = std::vec![kb_execution_api::RequiredSigner {
pubkey: fee_payer.clone(),
role: "fee_payer".to_string(),
}];
for account in accounts.iter().filter(|account| return account.is_signer) {
if required.iter().any(|candidate| return candidate.pubkey == account.pubkey) {
continue;
}
required.push(kb_execution_api::RequiredSigner {
pubkey: account.pubkey.clone(),
role: "wallet_owner".to_string(),
});
}
return required;
}
#[cfg(test)]
pub(crate) mod tests {
fn pubkey(value: &str) -> kb_model::Pubkey {
return kb_model::Pubkey(value.to_string());
}
fn intent(
operation: crate::SplAssociatedTokenAccountOperation,
max_rent_lamports: u64,
) -> crate::SplAssociatedTokenAccountExecutionIntent {
let fee_payer = pubkey(kb_program_ids::SYSTEM_PROGRAM_ID);
let wallet_owner = match &operation {
crate::SplAssociatedTokenAccountOperation::Create { wallet_owner, .. }
| crate::SplAssociatedTokenAccountOperation::CreateIdempotent {
wallet_owner, ..
}
| crate::SplAssociatedTokenAccountOperation::RecoverNested { wallet_owner, .. } => {
wallet_owner.clone()
},
};
let mut authorized_signers = std::vec![fee_payer.clone()];
if !authorized_signers.contains(&wallet_owner) {
authorized_signers.push(wallet_owner);
}
return crate::SplAssociatedTokenAccountExecutionIntent {
intent_id: "ata-intent-1".to_string(),
fee_payer,
max_rent_lamports,
policy: kb_execution_api::ExecutionPolicy {
simulation: kb_execution_api::ExecutionSimulationPolicy::Required,
cost_limit: kb_execution_api::ExecutionCostLimit {
max_spend_lamports: std::option::Option::Some(max_rent_lamports),
max_fee_lamports: std::option::Option::Some(10_000),
max_compute_unit_price_micro_lamports: std::option::Option::None,
},
authorized_signers,
dry_run: true,
post_execution_validation: kb_execution_api::PostExecutionValidationPolicy {
canonical_insert_required: true,
core_extraction_required: true,
decode_replay_required: true,
materialization_required: true,
},
..kb_execution_api::ExecutionPolicy::default()
},
operation,
};
}
fn official_instruction(
intent: &crate::SplAssociatedTokenAccountExecutionIntent,
) -> solana_instruction::Instruction {
let fee_payer = intent
.fee_payer
.0
.parse()
.unwrap_or_else(|error| panic!("invalid fee payer fixture: {error}"));
let token_program = intent
.operation
.token_program()
.program_id()
.parse()
.unwrap_or_else(|error| panic!("invalid Token Program fixture: {error}"));
return match &intent.operation {
crate::SplAssociatedTokenAccountOperation::Create {
wallet_owner,
mint,
token_program: _,
} => {
let wallet_owner = wallet_owner
.0
.parse()
.unwrap_or_else(|error| panic!("invalid wallet fixture: {error}"));
let mint =
mint.0.parse().unwrap_or_else(|error| panic!("invalid mint fixture: {error}"));
spl_associated_token_account_interface::instruction::create_associated_token_account(
&fee_payer,
&wallet_owner,
&mint,
&token_program,
)
},
crate::SplAssociatedTokenAccountOperation::CreateIdempotent {
wallet_owner,
mint,
token_program: _,
} => {
let wallet_owner = wallet_owner
.0
.parse()
.unwrap_or_else(|error| panic!("invalid wallet fixture: {error}"));
let mint =
mint.0.parse().unwrap_or_else(|error| panic!("invalid mint fixture: {error}"));
spl_associated_token_account_interface::instruction::create_associated_token_account_idempotent(
&fee_payer,
&wallet_owner,
&mint,
&token_program,
)
},
crate::SplAssociatedTokenAccountOperation::RecoverNested {
wallet_owner,
owner_mint,
nested_mint,
token_program: _,
} => {
let wallet_owner = wallet_owner
.0
.parse()
.unwrap_or_else(|error| panic!("invalid wallet fixture: {error}"));
let owner_mint = owner_mint
.0
.parse()
.unwrap_or_else(|error| panic!("invalid owner mint fixture: {error}"));
let nested_mint = nested_mint
.0
.parse()
.unwrap_or_else(|error| panic!("invalid nested mint fixture: {error}"));
spl_associated_token_account_interface::instruction::recover_nested(
&wallet_owner,
&owner_mint,
&nested_mint,
&token_program,
)
},
};
}
fn assert_matches_official(intent: &crate::SplAssociatedTokenAccountExecutionIntent) {
let plan = kb_execution_api::TypedInstructionExecutor::build_prepared_plan(
&crate::SplAssociatedTokenAccountExecutor,
intent,
)
.unwrap_or_else(|error| panic!("ATA plan failed: {error}"));
let official = official_instruction(intent);
assert_eq!(plan.instructions.len(), 1);
let actual = &plan.instructions[0];
assert_eq!(actual.program_id.0, official.program_id.to_string());
assert_eq!(actual.data, official.data);
assert_eq!(actual.accounts.len(), official.accounts.len());
for (actual_account, official_account) in
actual.accounts.iter().zip(official.accounts.iter())
{
assert_eq!(actual_account.pubkey.0, official_account.pubkey.to_string());
assert_eq!(actual_account.is_signer, official_account.is_signer);
assert_eq!(actual_account.is_writable, official_account.is_writable);
}
assert_eq!(plan.requested_spend_lamports, intent.max_rent_lamports);
assert_eq!(plan.policy.simulation, kb_execution_api::ExecutionSimulationPolicy::Required);
assert!(plan.policy.dry_run);
}
#[test]
fn every_variant_and_token_program_matches_the_official_builder() {
for token_program in [
crate::SplAssociatedTokenProgram::Classic,
crate::SplAssociatedTokenProgram::Token2022,
] {
for operation in [
crate::SplAssociatedTokenAccountOperation::Create {
wallet_owner: pubkey(kb_program_ids::STAKE_PROGRAM_ID),
mint: pubkey(kb_program_ids::VOTE_PROGRAM_ID),
token_program,
},
crate::SplAssociatedTokenAccountOperation::CreateIdempotent {
wallet_owner: pubkey(kb_program_ids::STAKE_PROGRAM_ID),
mint: pubkey(kb_program_ids::VOTE_PROGRAM_ID),
token_program,
},
] {
let intent = intent(operation, 2_100_000);
assert_matches_official(&intent);
}
let recovery = intent(
crate::SplAssociatedTokenAccountOperation::RecoverNested {
wallet_owner: pubkey(kb_program_ids::STAKE_PROGRAM_ID),
owner_mint: pubkey(kb_program_ids::VOTE_PROGRAM_ID),
nested_mint: pubkey(kb_program_ids::CONFIG_PROGRAM_ID),
token_program,
},
0,
);
assert_matches_official(&recovery);
}
}
#[test]
fn signer_set_is_unique_without_reordering_instruction_metas() {
let intent = intent(
crate::SplAssociatedTokenAccountOperation::RecoverNested {
wallet_owner: pubkey(kb_program_ids::STAKE_PROGRAM_ID),
owner_mint: pubkey(kb_program_ids::VOTE_PROGRAM_ID),
nested_mint: pubkey(kb_program_ids::CONFIG_PROGRAM_ID),
token_program: crate::SplAssociatedTokenProgram::Classic,
},
0,
);
let plan = crate::build_prepared_plan(&intent)
.unwrap_or_else(|error| panic!("ATA recovery plan failed: {error}"));
assert_eq!(plan.required_signers.len(), 2);
assert_eq!(plan.required_signers[0].role, "fee_payer");
assert_eq!(plan.required_signers[1].role, "wallet_owner");
assert_eq!(plan.instructions[0].accounts[5].pubkey, plan.required_signers[1].pubkey);
assert!(plan.instructions[0].accounts[5].is_signer);
}
#[test]
fn conservative_policy_rejects_unsafe_cost_and_replay_shapes() {
let operation = crate::SplAssociatedTokenAccountOperation::Create {
wallet_owner: pubkey(kb_program_ids::STAKE_PROGRAM_ID),
mint: pubkey(kb_program_ids::VOTE_PROGRAM_ID),
token_program: crate::SplAssociatedTokenProgram::Classic,
};
let mut intent = intent(operation, 2_100_000);
intent.policy.simulation = kb_execution_api::ExecutionSimulationPolicy::Optional;
let error = crate::build_prepared_plan(&intent).expect_err("optional simulation must fail");
assert_eq!(error.code(), "execution_spl_ata_simulation_required");
intent.policy.simulation = kb_execution_api::ExecutionSimulationPolicy::Required;
intent.policy.cost_limit.max_spend_lamports = std::option::Option::Some(1);
let error =
crate::build_prepared_plan(&intent).expect_err("mismatched spend ceiling must fail");
assert_eq!(error.code(), "execution_spl_ata_spend_limit_mismatch");
intent.policy.cost_limit.max_spend_lamports = std::option::Option::Some(2_100_000);
intent.policy.post_execution_validation.materialization_required = false;
let error = crate::build_prepared_plan(&intent)
.expect_err("incomplete replay validation must fail");
assert_eq!(error.code(), "execution_spl_ata_post_validation_required");
}
#[test]
fn recovery_requires_zero_rent_and_creation_requires_a_positive_ceiling() {
let create = intent(
crate::SplAssociatedTokenAccountOperation::Create {
wallet_owner: pubkey(kb_program_ids::STAKE_PROGRAM_ID),
mint: pubkey(kb_program_ids::VOTE_PROGRAM_ID),
token_program: crate::SplAssociatedTokenProgram::Classic,
},
0,
);
let error =
crate::build_prepared_plan(&create).expect_err("zero creation ceiling must fail");
assert_eq!(error.code(), "execution_spl_ata_rent_limit_missing");
let recovery = intent(
crate::SplAssociatedTokenAccountOperation::RecoverNested {
wallet_owner: pubkey(kb_program_ids::STAKE_PROGRAM_ID),
owner_mint: pubkey(kb_program_ids::VOTE_PROGRAM_ID),
nested_mint: pubkey(kb_program_ids::CONFIG_PROGRAM_ID),
token_program: crate::SplAssociatedTokenProgram::Token2022,
},
1,
);
let error =
crate::build_prepared_plan(&recovery).expect_err("recovery rent spending must fail");
assert_eq!(error.code(), "execution_spl_ata_recovery_rent_must_be_zero");
}
}

View File

@@ -0,0 +1,7 @@
// file: kb_executor_spl_associated_token_account/src/constants.rs
// version: 3
//! Local constants for the `kb_executor_spl_associated_token_account` crate. Program identifiers live in `kb_program_ids`.
/// Canonical tracing target for this crate.
pub(crate) const TRACING_TARGET: &str = "kb_executor_spl_associated_token_account";

View File

@@ -0,0 +1,284 @@
// file: kb_executor_spl_associated_token_account/src/executor.rs
// version: 4
//! Exact ATA capability dispatch and typed plan construction.
/// SPL Associated Token Account executor implementation.
#[derive(Clone, Debug, Default)]
pub struct SplAssociatedTokenAccountExecutor;
impl crate::SplAssociatedTokenAccountExecutor {
fn exact_capability(
&self,
program_id: &kb_model::ProgramId,
operation_code: &str,
) -> kb_execution_api::ExecutionCapability {
if program_id.0 != kb_program_ids::ASSOCIATED_TOKEN_PROGRAM_ID {
return kb_execution_api::ExecutionCapability::unsupported(
"execution_spl_ata_program_not_owned",
format!(
"program {} is not owned by kb_executor_spl_associated_token_account",
program_id.0
),
);
}
if crate::SUPPORTED_OPERATION_CODES.contains(&operation_code) {
return kb_execution_api::ExecutionCapability::supported(operation_code);
}
return kb_execution_api::ExecutionCapability::unsupported(
"execution_spl_ata_operation_unsupported",
format!("SPL Associated Token Account operation {operation_code} is not implemented"),
);
}
}
impl kb_execution_api::TypedInstructionExecutor for crate::SplAssociatedTokenAccountExecutor {
type Intent = crate::SplAssociatedTokenAccountExecutionIntent;
fn capability(
&self,
program_id: &kb_model::ProgramId,
operation_code: &str,
) -> kb_execution_api::ExecutionCapability {
return self.exact_capability(program_id, operation_code);
}
fn build_prepared_plan(
&self,
intent: &Self::Intent,
) -> kb_core::Result<kb_execution_api::PreparedExecutionPlan> {
let program_id = kb_model::ProgramId(std::string::String::from(
kb_program_ids::ASSOCIATED_TOKEN_PROGRAM_ID,
));
return match self.exact_capability(&program_id, intent.operation.operation_code()) {
kb_execution_api::ExecutionCapability::Supported { operation_code: _ } => {
crate::build_prepared_plan(intent)
},
kb_execution_api::ExecutionCapability::Unsupported { reason_code, reason } => {
std::result::Result::Err(kb_core::Error::new(reason_code, reason))
},
};
}
}
impl kb_execution_api::InstructionExecutor for crate::SplAssociatedTokenAccountExecutor {
fn executor_name(&self) -> &'static str {
return "kb_executor_spl_associated_token_account";
}
fn executor_version(&self) -> &'static str {
return env!("CARGO_PKG_VERSION");
}
fn program_ids(&self) -> &'static [&'static str] {
return &[kb_program_ids::ASSOCIATED_TOKEN_PROGRAM_ID];
}
fn supports_request(
&self,
request: &kb_execution_api::ExecutionRequest,
) -> kb_execution_api::ExecutionSupport {
return match self.exact_capability(&request.program_id, &request.operation_code) {
kb_execution_api::ExecutionCapability::Supported { operation_code: _ } => {
kb_execution_api::ExecutionSupport::Yes
},
kb_execution_api::ExecutionCapability::Unsupported { reason_code: _, reason: _ } => {
kb_execution_api::ExecutionSupport::No
},
};
}
fn build_plan(
&self,
request: &kb_execution_api::ExecutionRequest,
) -> kb_core::Result<kb_execution_api::ExecutionPlan> {
match self.exact_capability(&request.program_id, &request.operation_code) {
kb_execution_api::ExecutionCapability::Supported { operation_code: _ } => {},
kb_execution_api::ExecutionCapability::Unsupported { reason_code, reason } => {
return std::result::Result::Err(kb_core::Error::new(reason_code, reason));
},
}
let intent = match serde_json::from_str::<crate::SplAssociatedTokenAccountExecutionIntent>(
&request.payload_json,
) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => {
return std::result::Result::Err(kb_core::Error::new(
"execution_spl_ata_intent_deserialize_failed",
error.to_string(),
));
},
};
if intent.operation.operation_code() != request.operation_code.as_str() {
return std::result::Result::Err(kb_core::Error::new(
"execution_operation_code_mismatch",
format!(
"request operation {} does not match typed intent operation {}",
request.operation_code,
intent.operation.operation_code()
),
));
}
let prepared =
match kb_execution_api::TypedInstructionExecutor::build_prepared_plan(self, &intent) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
let payload_value = match serde_json::to_value(&prepared) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => {
return std::result::Result::Err(kb_core::Error::new(
"execution_spl_ata_plan_serialize_failed",
error.to_string(),
));
},
};
let payload_json = match kb_execution_api::serialize_payload_json(&payload_value) {
std::result::Result::Ok(value) => value,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
return std::result::Result::Ok(kb_execution_api::ExecutionPlan {
executor_name: std::string::String::from("kb_executor_spl_associated_token_account"),
instruction_count: prepared.instructions.len(),
payload_json,
});
}
}
#[cfg(test)]
mod tests {
fn pubkey(value: &str) -> kb_model::Pubkey {
return kb_model::Pubkey(value.to_string());
}
fn intent(
operation: crate::SplAssociatedTokenAccountOperation,
max_rent_lamports: u64,
) -> crate::SplAssociatedTokenAccountExecutionIntent {
let fee_payer = pubkey(kb_program_ids::SYSTEM_PROGRAM_ID);
let wallet_owner = match &operation {
crate::SplAssociatedTokenAccountOperation::Create { wallet_owner, .. }
| crate::SplAssociatedTokenAccountOperation::CreateIdempotent {
wallet_owner, ..
}
| crate::SplAssociatedTokenAccountOperation::RecoverNested { wallet_owner, .. } => {
wallet_owner.clone()
},
};
let mut authorized_signers = std::vec![fee_payer.clone()];
if !authorized_signers.contains(&wallet_owner) {
authorized_signers.push(wallet_owner);
}
return crate::SplAssociatedTokenAccountExecutionIntent {
intent_id: "ata-intent-1".to_string(),
fee_payer,
max_rent_lamports,
policy: kb_execution_api::ExecutionPolicy {
simulation: kb_execution_api::ExecutionSimulationPolicy::Required,
cost_limit: kb_execution_api::ExecutionCostLimit {
max_spend_lamports: std::option::Option::Some(max_rent_lamports),
max_fee_lamports: std::option::Option::Some(10_000),
max_compute_unit_price_micro_lamports: std::option::Option::None,
},
authorized_signers,
dry_run: true,
post_execution_validation: kb_execution_api::PostExecutionValidationPolicy {
canonical_insert_required: true,
core_extraction_required: true,
decode_replay_required: true,
materialization_required: true,
},
..kb_execution_api::ExecutionPolicy::default()
},
operation,
};
}
fn request(program_id: &str, operation_code: &str) -> kb_execution_api::ExecutionRequest {
return kb_execution_api::ExecutionRequest {
program_id: kb_model::ProgramId(program_id.to_string()),
operation_code: operation_code.to_string(),
payload_json: std::string::String::from("{}"),
};
}
#[test]
fn exact_capabilities_cover_every_published_current_variant() {
let executor = crate::SplAssociatedTokenAccountExecutor;
for operation_code in crate::SUPPORTED_OPERATION_CODES {
let request = request(kb_program_ids::ASSOCIATED_TOKEN_PROGRAM_ID, operation_code);
assert_eq!(
kb_execution_api::InstructionExecutor::supports_request(&executor, &request),
kb_execution_api::ExecutionSupport::Yes
);
}
for (program_id, operation_code) in [
(kb_program_ids::SYSTEM_PROGRAM_ID, crate::CREATE_OPERATION),
(
kb_program_ids::ASSOCIATED_TOKEN_PROGRAM_ID,
"spl_associated_token_account.close",
),
] {
let request = request(program_id, operation_code);
assert_eq!(
kb_execution_api::InstructionExecutor::supports_request(&executor, &request),
kb_execution_api::ExecutionSupport::No
);
}
}
#[test]
fn generic_request_roundtrips_one_typed_instruction() {
let pintent = intent(
crate::SplAssociatedTokenAccountOperation::CreateIdempotent {
wallet_owner: pubkey(kb_program_ids::STAKE_PROGRAM_ID),
mint: pubkey(kb_program_ids::VOTE_PROGRAM_ID),
token_program: crate::SplAssociatedTokenProgram::Token2022,
},
2_100_000,
);
let payload_json = serde_json::to_string(&pintent)
.unwrap_or_else(|error| panic!("ATA intent serialization failed: {error}"));
let request = kb_execution_api::ExecutionRequest {
program_id: kb_model::ProgramId(
kb_program_ids::ASSOCIATED_TOKEN_PROGRAM_ID.to_string(),
),
operation_code: crate::CREATE_IDEMPOTENT_OPERATION.to_string(),
payload_json,
};
let plan = kb_execution_api::InstructionExecutor::build_plan(
&crate::SplAssociatedTokenAccountExecutor,
&request,
)
.unwrap_or_else(|error| panic!("generic ATA plan failed: {error}"));
assert_eq!(plan.instruction_count, 1);
let prepared =
serde_json::from_str::<kb_execution_api::PreparedExecutionPlan>(&plan.payload_json)
.unwrap_or_else(|error| panic!("prepared ATA plan parsing failed: {error}"));
assert_eq!(prepared.operation_code, crate::CREATE_IDEMPOTENT_OPERATION);
assert_eq!(prepared.instructions[0].data, std::vec![1]);
}
#[test]
fn machine_readable_matrix_matches_compiled_executor_capabilities() {
let matrix: serde_json::Value = serde_json::from_str(include_str!(
"../../docs/SPL_ASSOCIATED_TOKEN_ACCOUNT_MATRIX.json"
))
.unwrap_or_else(|error| panic!("ATA matrix parsing failed: {error}"));
let instructions = matrix["instructions"]
.as_array()
.unwrap_or_else(|| panic!("ATA matrix instructions must be an array"));
let matrix_operations = instructions
.iter()
.map(|instruction| {
assert_eq!(instruction["executorSupport"]["status"], "supported");
return instruction["executorSupport"]["operationCode"]
.as_str()
.unwrap_or_else(|| panic!("ATA operation code must be a string"));
})
.collect::<std::vec::Vec<_>>();
assert_eq!(matrix_operations, crate::SUPPORTED_OPERATION_CODES);
assert_eq!(matrix["surfaceEquality"]["matrixVariantCount"], 3);
assert_eq!(matrix["surfaceEquality"]["officialInterfaceVariantCount"], 3);
}
}

View File

@@ -0,0 +1,122 @@
// file: kb_executor_spl_associated_token_account/src/intent.rs
// version: 2
//! Typed SPL Associated Token Account execution intents.
use ts_rs::TS; // rust-rules: derive-import
/// Stable operation code for strict ATA creation.
pub const CREATE_OPERATION: &str = "spl_associated_token_account.create";
/// Stable operation code for idempotent ATA creation or reuse.
pub const CREATE_IDEMPOTENT_OPERATION: &str = "spl_associated_token_account.create_idempotent";
/// Stable operation code for nested ATA recovery.
pub const RECOVER_NESTED_OPERATION: &str = "spl_associated_token_account.recover_nested";
/// Every current officially constructible ATA operation.
pub const SUPPORTED_OPERATION_CODES: &[&str] =
&[CREATE_OPERATION, CREATE_IDEMPOTENT_OPERATION, RECOVER_NESTED_OPERATION];
/// Exact Token Program targeted by ATA derivation and runtime CPIs.
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
#[serde(rename_all = "snake_case")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_executor_spl_associated_token_account/intent/SplAssociatedTokenProgram.ts"
)]
pub enum SplAssociatedTokenProgram {
/// Classic SPL Token program.
Classic,
/// Token-2022 program without extension-specific executor semantics.
Token2022,
}
impl crate::SplAssociatedTokenProgram {
/// Returns the exact target Token Program ID.
pub fn program_id(&self) -> &'static str {
return match self {
Self::Classic => kb_program_ids::SPL_TOKEN_PROGRAM_ID,
Self::Token2022 => kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID,
};
}
}
/// One officially constructible ATA operation.
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
#[serde(tag = "operation", rename_all = "snake_case")]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_executor_spl_associated_token_account/intent/SplAssociatedTokenAccountOperation.ts"
)]
pub enum SplAssociatedTokenAccountOperation {
/// Strictly create an absent canonical ATA.
Create {
/// Wallet owner used as the first PDA seed.
wallet_owner: kb_model::Pubkey,
/// Mint used as the third PDA seed.
mint: kb_model::Pubkey,
/// Token Program used as the second PDA seed and runtime CPI target.
token_program: crate::SplAssociatedTokenProgram,
},
/// Create an absent ATA or accept an existing compatible ATA.
CreateIdempotent {
/// Wallet owner used as the first PDA seed.
wallet_owner: kb_model::Pubkey,
/// Mint used as the third PDA seed.
mint: kb_model::Pubkey,
/// Token Program used as the second PDA seed and runtime CPI target.
token_program: crate::SplAssociatedTokenProgram,
},
/// Recover tokens and lamports from one canonical nested ATA.
RecoverNested {
/// Wallet owner that must sign the recovery.
wallet_owner: kb_model::Pubkey,
/// Mint whose ATA currently owns the nested ATA.
owner_mint: kb_model::Pubkey,
/// Mint held by the nested ATA and the wallet destination ATA.
nested_mint: kb_model::Pubkey,
/// Token Program shared by all three derived ATA addresses.
token_program: crate::SplAssociatedTokenProgram,
},
}
impl crate::SplAssociatedTokenAccountOperation {
/// Returns the stable generic dispatch operation code.
pub fn operation_code(&self) -> &'static str {
return match self {
Self::Create { .. } => crate::CREATE_OPERATION,
Self::CreateIdempotent { .. } => crate::CREATE_IDEMPOTENT_OPERATION,
Self::RecoverNested { .. } => crate::RECOVER_NESTED_OPERATION,
};
}
/// Returns the exact target Token Program.
pub fn token_program(&self) -> crate::SplAssociatedTokenProgram {
return match self {
Self::Create { token_program, .. }
| Self::CreateIdempotent { token_program, .. }
| Self::RecoverNested { token_program, .. } => *token_program,
};
}
pub(crate) fn is_creation(&self) -> bool {
return matches!(self, Self::Create { .. } | Self::CreateIdempotent { .. });
}
}
/// Complete typed intent accepted by the ATA executor.
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/kb_executor_spl_associated_token_account/intent/SplAssociatedTokenAccountExecutionIntent.ts"
)]
pub struct SplAssociatedTokenAccountExecutionIntent {
/// Stable caller-provided identifier used for logs and replay correlation.
pub intent_id: std::string::String,
/// Transaction fee payer and Create/CreateIdempotent funding account.
pub fee_payer: kb_model::Pubkey,
/// Maximum rent lamports the creation operation may spend; zero for RecoverNested.
pub max_rent_lamports: u64,
/// Conservative common execution policy.
pub policy: kb_execution_api::ExecutionPolicy,
/// Typed ATA operation and exact address inputs.
pub operation: crate::SplAssociatedTokenAccountOperation,
}

View File

@@ -0,0 +1,34 @@
// file: kb_executor_spl_associated_token_account/src/lib.rs
// version: 5
//! Executor crate for `spl_associated_token_account`.
#![warn(missing_docs)]
#![deny(unreachable_pub)]
#![forbid(unsafe_code)]
mod builder;
mod constants;
mod executor;
mod intent;
/// Crate-root access to `build_prepared_plan` from `builder`.
pub(crate) use crate::builder::build_prepared_plan;
/// Canonical tracing target for this crate.
pub(crate) use crate::constants::TRACING_TARGET;
/// Exposes the exact ATA executor.
pub use crate::executor::SplAssociatedTokenAccountExecutor;
/// Stable CreateIdempotent operation code.
pub use crate::intent::CREATE_IDEMPOTENT_OPERATION;
/// Stable Create operation code.
pub use crate::intent::CREATE_OPERATION;
/// Stable RecoverNested operation code.
pub use crate::intent::RECOVER_NESTED_OPERATION;
/// All officially constructible ATA operation codes.
pub use crate::intent::SUPPORTED_OPERATION_CODES;
/// Exposes the typed ATA execution intent.
pub use crate::intent::SplAssociatedTokenAccountExecutionIntent;
/// Exposes the typed ATA operation.
pub use crate::intent::SplAssociatedTokenAccountOperation;
/// Exposes the exact target Token Program selection.
pub use crate::intent::SplAssociatedTokenProgram;