0.5.1-pre.002

This commit is contained in:
2026-08-09 19:34:08 +02:00
parent 816eee59a9
commit 6a680767ae
767 changed files with 12257 additions and 12195 deletions

View File

@@ -0,0 +1,499 @@
// file: ks-lib/src/executor/api/execution.rs
// version: 10
//! Typed execution plans, policies and result contracts.
use ts_rs::TS; // rust-rules: derive-import
/// Exact capability returned for one program operation.
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
#[serde(tag = "status", rename_all = "snake_case")]
#[ts(
export,
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/ExecutionCapability.ts"
)]
pub enum ExApiExecutionCapability {
/// The operation is implemented by the executor.
Supported {
/// Stable operation code implemented by the executor.
operation_code: std::string::String,
},
/// The operation is not implemented or is rejected by design.
Unsupported {
/// Stable reason code.
reason_code: std::string::String,
/// Human-readable reason.
reason: std::string::String,
},
}
impl crate::ExApiExecutionCapability {
/// Creates a supported capability value.
pub fn supported(operation_code: impl std::convert::Into<std::string::String>) -> Self {
return Self::Supported { operation_code: operation_code.into() };
}
/// Creates an unsupported capability value.
pub fn unsupported(
reason_code: impl std::convert::Into<std::string::String>,
reason: impl std::convert::Into<std::string::String>,
) -> Self {
return Self::Unsupported {
reason_code: reason_code.into(),
reason: reason.into(),
};
}
/// Returns whether the capability is explicitly supported.
pub fn is_supported(&self) -> bool {
return matches!(self, Self::Supported { operation_code: _ });
}
}
/// Solana cluster expected by an execution plan.
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Serialize, TS)]
#[serde(rename_all = "snake_case")]
#[ts(
export,
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/ExecutionCluster.ts"
)]
pub enum ExApiExecutionCluster {
/// Local validator cluster.
Localnet,
/// Public development cluster.
Devnet,
/// Public test cluster.
Testnet,
/// Public production cluster.
///
/// RPC URLs and CLI aliases may still use `mainnet-beta`.
Mainnet,
}
#[derive(serde::Deserialize)]
#[serde(rename_all = "snake_case")]
enum ExecutionClusterWire {
Localnet,
Devnet,
Testnet,
#[serde(alias = "mainnet_beta")]
Mainnet,
}
impl<'de> serde::Deserialize<'de> for crate::ExApiExecutionCluster {
fn deserialize<Deserializer>(
deserializer: Deserializer,
) -> std::result::Result<Self, Deserializer::Error>
where
Deserializer: serde::Deserializer<'de>,
{
let wire = match <ExecutionClusterWire as serde::Deserialize>::deserialize(deserializer) {
std::result::Result::Ok(wire) => wire,
std::result::Result::Err(error) => return std::result::Result::Err(error),
};
return std::result::Result::Ok(match wire {
ExecutionClusterWire::Localnet => Self::Localnet,
ExecutionClusterWire::Devnet => Self::Devnet,
ExecutionClusterWire::Testnet => Self::Testnet,
ExecutionClusterWire::Mainnet => Self::Mainnet,
});
}
}
/// Cluster restrictions attached to an execution plan.
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/ExecutionClusterPolicy.ts"
)]
pub struct ExApiExecutionClusterPolicy {
/// Cluster that the RPC endpoint must report.
pub expected_cluster: crate::ExApiExecutionCluster,
/// Whether production execution may proceed after all other checks.
pub allow_mainnet: bool,
/// Whether the operator explicitly confirmed this production execution.
pub mainnet_confirmation: bool,
}
impl std::default::Default for crate::ExApiExecutionClusterPolicy {
fn default() -> Self {
return Self {
expected_cluster: crate::ExApiExecutionCluster::Devnet,
allow_mainnet: false,
mainnet_confirmation: false,
};
}
}
/// Simulation requirement attached to an execution plan.
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
#[serde(rename_all = "snake_case")]
#[ts(
export,
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/ExecutionSimulationPolicy.ts"
)]
pub enum ExApiExecutionSimulationPolicy {
/// Simulation must succeed before signing or sending.
Required,
/// Simulation is not required. Safety policy rejects this mode by default.
Optional,
}
/// Blockhash source required when a transaction is assembled.
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
#[serde(rename_all = "snake_case")]
#[ts(
export,
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/ExecutionBlockhashKind.ts"
)]
pub enum ExApiExecutionBlockhashKind {
/// Fetch a recent blockhash and enforce a bounded age.
Latest,
/// Use a durable nonce account and authority.
DurableNonce,
}
/// Blockhash or durable nonce policy attached to an execution plan.
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/ExecutionBlockhashPolicy.ts"
)]
pub struct ExApiExecutionBlockhashPolicy {
/// Selected blockhash source.
pub kind: crate::ExApiExecutionBlockhashKind,
/// Maximum accepted age for a recent blockhash, in slots.
pub max_age_slots: std::option::Option<u64>,
/// Durable nonce account when `kind` is `DurableNonce`.
pub nonce_account: std::option::Option<crate::MdPubkey>,
/// Durable nonce authority when `kind` is `DurableNonce`.
pub nonce_authority: std::option::Option<crate::MdPubkey>,
}
impl std::default::Default for crate::ExApiExecutionBlockhashPolicy {
fn default() -> Self {
return Self {
kind: crate::ExApiExecutionBlockhashKind::Latest,
max_age_slots: std::option::Option::Some(150),
nonce_account: std::option::Option::None,
nonce_authority: std::option::Option::None,
};
}
}
/// Explicit cost ceilings attached to an execution plan.
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/ExecutionCostLimit.ts"
)]
pub struct ExApiExecutionCostLimit {
/// Maximum lamports that operation instructions may transfer or lock.
pub max_spend_lamports: std::option::Option<u64>,
/// Maximum total transaction fee accepted after simulation.
pub max_fee_lamports: std::option::Option<u64>,
/// Maximum compute-unit price accepted, in micro-lamports per compute unit.
pub max_compute_unit_price_micro_lamports: std::option::Option<u64>,
}
impl std::default::Default for crate::ExApiExecutionCostLimit {
fn default() -> Self {
return Self {
max_spend_lamports: std::option::Option::None,
max_fee_lamports: std::option::Option::None,
max_compute_unit_price_micro_lamports: std::option::Option::None,
};
}
}
/// Post-execution replay validation policy.
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/PostExecutionValidationPolicy.ts"
)]
pub struct ExApiPostExecutionValidationPolicy {
/// Whether the sent signature must be inserted into canonical storage.
pub canonical_insert_required: bool,
/// Whether core extraction must complete.
pub core_extraction_required: bool,
/// Whether contextual decode replay must complete.
pub decode_replay_required: bool,
/// Whether compatible materializers must run.
pub materialization_required: bool,
}
impl std::default::Default for crate::ExApiPostExecutionValidationPolicy {
fn default() -> Self {
return Self {
canonical_insert_required: true,
core_extraction_required: true,
decode_replay_required: true,
materialization_required: false,
};
}
}
/// Conservative policy carried from intent creation to transaction assembly.
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/ExecutionPolicy.ts"
)]
pub struct ExApiExecutionPolicy {
/// Cluster restrictions.
pub cluster: crate::ExApiExecutionClusterPolicy,
/// Simulation requirement.
pub simulation: crate::ExApiExecutionSimulationPolicy,
/// Blockhash source restrictions.
pub blockhash: crate::ExApiExecutionBlockhashPolicy,
/// Explicit operation and fee ceilings.
pub cost_limit: crate::ExApiExecutionCostLimit,
/// Public keys authorized to sign this plan.
pub authorized_signers: std::vec::Vec<crate::MdPubkey>,
/// Whether the operation is restricted to plan construction and simulation.
pub dry_run: bool,
/// Required post-execution validation steps.
pub post_execution_validation: crate::ExApiPostExecutionValidationPolicy,
}
impl std::default::Default for crate::ExApiExecutionPolicy {
fn default() -> Self {
return Self {
cluster: crate::ExApiExecutionClusterPolicy::default(),
simulation: crate::ExApiExecutionSimulationPolicy::Required,
blockhash: crate::ExApiExecutionBlockhashPolicy::default(),
cost_limit: crate::ExApiExecutionCostLimit::default(),
authorized_signers: std::vec::Vec::new(),
dry_run: true,
post_execution_validation: crate::ExApiPostExecutionValidationPolicy::default(),
};
}
}
/// One account required by a planned instruction.
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/PlannedAccount.ts"
)]
pub struct ExApiPlannedAccount {
/// Account public key.
pub pubkey: crate::MdPubkey,
/// Whether the account must sign the transaction.
pub is_signer: bool,
/// Whether the account must be writable.
pub is_writable: bool,
}
/// One fully encoded instruction in an execution plan.
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/PlannedInstruction.ts"
)]
pub struct ExApiPlannedInstruction {
/// Target program id.
pub program_id: crate::MdProgramId,
/// Stable operation code represented by the instruction.
pub operation_code: std::string::String,
/// Ordered account metadata.
pub accounts: std::vec::Vec<crate::ExApiPlannedAccount>,
/// Exact encoded instruction payload.
pub data: std::vec::Vec<u8>,
}
/// Signer required before transaction assembly.
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/RequiredSigner.ts"
)]
pub struct ExApiRequiredSigner {
/// Signer public key.
pub pubkey: crate::MdPubkey,
/// Stable signer role such as `fee_payer`, `funding_account` or `new_account`.
pub role: std::string::String,
}
/// Typed execution plan produced before transaction assembly.
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/PreparedExecutionPlan.ts"
)]
pub struct ExApiPreparedExecutionPlan {
/// Stable executor crate name.
pub executor_name: std::string::String,
/// Executor package version.
pub executor_version: std::string::String,
/// Caller-provided intent identifier.
pub intent_id: std::string::String,
/// Stable operation code.
pub operation_code: std::string::String,
/// Transaction fee payer.
pub fee_payer: crate::MdPubkey,
/// Ordered instructions to place in the transaction message.
pub instructions: std::vec::Vec<crate::ExApiPlannedInstruction>,
/// Deduplicated signers required by the fee payer and instruction metas.
pub required_signers: std::vec::Vec<crate::ExApiRequiredSigner>,
/// Explicit policy to evaluate before simulation, signing and sending.
pub policy: crate::ExApiExecutionPolicy,
/// Lamports explicitly transferred or locked by planned instructions.
pub requested_spend_lamports: u64,
/// Requested compute-unit price, when present.
pub requested_compute_unit_price_micro_lamports: std::option::Option<u64>,
}
/// Result returned by a transaction simulation adapter.
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/ExecutionSimulationResult.ts"
)]
pub struct ExApiExecutionSimulationResult {
/// Whether an RPC simulation call was actually performed.
pub simulated: bool,
/// Whether the simulated transaction completed successfully.
pub success: bool,
/// Cluster reported by the simulation adapter.
pub cluster: crate::ExApiExecutionCluster,
/// Blockhash source used by the simulated transaction.
pub blockhash_kind: crate::ExApiExecutionBlockhashKind,
/// Observed recent blockhash age, in slots.
pub blockhash_age_slots: std::option::Option<u64>,
/// Replacement blockhash returned by the node, if replacement was requested.
#[serde(default)]
pub replacement_blockhash: std::option::Option<std::string::String>,
/// Last valid block height associated with the replacement blockhash.
#[serde(default)]
pub replacement_last_valid_block_height: std::option::Option<u64>,
/// Durable nonce account used by the simulated transaction.
pub nonce_account: std::option::Option<crate::MdPubkey>,
/// Durable nonce authority used by the simulated transaction.
pub nonce_authority: std::option::Option<crate::MdPubkey>,
/// Compute units consumed when reported by the RPC endpoint.
pub units_consumed: std::option::Option<u64>,
/// Estimated transaction fee in lamports when available.
pub estimated_fee_lamports: std::option::Option<u64>,
/// Simulation logs in runtime order.
pub logs: std::vec::Vec<std::string::String>,
/// Program return data retained as provider-neutral JSON when reported.
#[serde(default)]
pub return_data: std::option::Option<serde_json::Value>,
/// Stable or provider error text when simulation failed.
pub error: std::option::Option<std::string::String>,
}
/// Result returned after an adapter submits a signed transaction.
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/ExecutionSendResult.ts"
)]
pub struct ExApiExecutionSendResult {
/// Cluster used for submission.
pub cluster: crate::ExApiExecutionCluster,
/// Signature returned by the RPC endpoint.
pub signature: crate::MdSignature,
/// Whether submission was accepted by the RPC endpoint.
pub submitted: bool,
}
/// Confirmation state returned by an execution confirmation adapter.
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
#[serde(rename_all = "snake_case")]
#[ts(
export,
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/ExecutionConfirmationStatus.ts"
)]
pub enum ExApiExecutionConfirmationStatus {
/// The transaction was observed at processed commitment.
Processed,
/// The transaction reached confirmed commitment.
Confirmed,
/// The transaction reached finalized commitment.
Finalized,
/// The transaction was confirmed with a runtime error.
Failed,
/// The transaction was not confirmed before its blockhash expired.
Expired,
/// The bounded confirmation poll ended before reaching the requested commitment.
TimedOut,
}
/// Result returned after waiting for transaction confirmation.
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/ExecutionConfirmationResult.ts"
)]
pub struct ExApiExecutionConfirmationResult {
/// Cluster queried for confirmation.
pub cluster: crate::ExApiExecutionCluster,
/// Submitted transaction signature.
pub signature: crate::MdSignature,
/// Highest confirmation state reached.
pub status: crate::ExApiExecutionConfirmationStatus,
/// Slot that reported the transaction when available.
pub slot: std::option::Option<u64>,
/// Number of status polling attempts performed.
pub attempts: u32,
/// Last block height observed while checking recent-blockhash expiration.
pub last_observed_block_height: std::option::Option<u64>,
/// Stable or provider error text when confirmation failed.
pub error: std::option::Option<std::string::String>,
}
/// Diagnostic produced by post-execution canonical replay validation.
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/ks_lib/executor/api/execution/PostExecutionDiagnostic.ts"
)]
pub struct ExApiPostExecutionDiagnostic {
/// Executed transaction signature.
pub signature: crate::MdSignature,
/// Whether canonical insertion completed.
pub canonical_inserted: bool,
/// Whether core extraction completed.
pub core_extracted: bool,
/// Whether contextual decode replay completed.
pub decode_replayed: bool,
/// Whether requested materialization completed.
pub materialized: bool,
/// Diagnostic messages from orchestration layers.
pub diagnostics: std::vec::Vec<std::string::String>,
}
/// Contract implemented by executors that expose typed intents and exact plans.
pub trait ExApiTypedInstructionExecutor {
/// Protocol-specific typed intent.
type Intent;
/// Returns the exact capability for one program and operation code.
fn capability(
&self,
program_id: &crate::MdProgramId,
operation_code: &str,
) -> crate::ExApiExecutionCapability;
/// Builds a typed execution plan without signing, sending or performing I/O.
fn build_prepared_plan(
&self,
intent: &Self::Intent,
) -> ks_core::Result<crate::ExApiPreparedExecutionPlan>;
}
#[cfg(test)]
mod tests {
#[test]
fn mainnet_cluster_serializes_with_current_name() {
let serialized = serde_json::to_string(&crate::ExApiExecutionCluster::Mainnet)
.unwrap_or_else(|error| panic!("unexpected serialization error: {error}"));
assert_eq!(serialized, "\"mainnet\"");
let legacy = serde_json::from_str::<crate::ExApiExecutionCluster>("\"mainnet_beta\"")
.unwrap_or_else(|error| panic!("unexpected deserialization error: {error}"));
assert_eq!(legacy, crate::ExApiExecutionCluster::Mainnet);
}
}

View File

@@ -0,0 +1,109 @@
// file: ks-lib/src/executor/api/executor.rs
// version: 5
//! Shared execution contract and neutral request models.
use ts_rs::TS; // rust-rules: derive-import
/// Support level returned by an executor for a requested operation.
#[derive(Clone, Copy, Debug, Eq, PartialEq, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/ks_lib/executor/api/executor/ExecutionSupport.ts"
)]
pub enum ExApiExecutionSupport {
/// The executor cannot handle the request.
No,
/// The executor may handle the request after account and payload validation.
Maybe,
/// The executor explicitly supports the request.
Yes,
}
/// Generic request used before protocol-specific execution models are introduced.
#[derive(Clone, Debug, Eq, PartialEq, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/ks_lib/executor/api/executor/ExecutionRequest.ts"
)]
pub struct ExApiExecutionRequest {
/// Target program id.
pub program_id: crate::MdProgramId,
/// Stable operation code such as buy, sell, transfer or route.
pub operation_code: std::string::String,
/// Serialized JSON payload reserved for protocol-specific arguments.
pub payload_json: std::string::String,
}
/// Neutral execution plan placeholder produced by executor crates.
#[derive(Clone, Debug, Eq, PartialEq, TS)]
#[ts(
export,
export_to = "../frontend/ts/bindings/ks_lib/executor/api/executor/ExecutionPlan.ts"
)]
pub struct ExApiExecutionPlan {
/// Stable executor crate name.
pub executor_name: std::string::String,
/// Number of instructions that would be produced by the final implementation.
pub instruction_count: usize,
/// Serialized JSON payload reserved for future instruction data and account metadata.
pub payload_json: std::string::String,
}
/// Serializes a JSON payload to its compact string representation.
pub fn executor_api_serialize_payload_json(
value: &serde_json::Value,
) -> ks_core::Result<std::string::String> {
return match serde_json::to_string(value) {
std::result::Result::Ok(serialized) => std::result::Result::Ok(serialized),
std::result::Result::Err(error) => std::result::Result::Err(ks_core::Error::new(
"execution_payload_json_serialize_failed",
error.to_string(),
)),
};
}
/// Serializes a JSON payload to its pretty string representation.
pub fn executor_api_serialize_payload_json_pretty(
value: &serde_json::Value,
) -> ks_core::Result<std::string::String> {
return match serde_json::to_string_pretty(value) {
std::result::Result::Ok(serialized) => std::result::Result::Ok(serialized),
std::result::Result::Err(error) => std::result::Result::Err(ks_core::Error::new(
"execution_payload_json_pretty_serialize_failed",
error.to_string(),
)),
};
}
/// Common contract implemented by all execution crates.
pub trait ExApiInstructionExecutor {
/// Returns the stable executor name.
fn executor_name(&self) -> &'static str;
/// Returns the executor version.
fn executor_version(&self) -> &'static str;
/// Returns the program ids handled by this executor.
fn program_ids(&self) -> &'static [&'static str];
/// Tests whether this executor owns a program id.
fn handles_program_id(&self, program_id: &crate::MdProgramId) -> bool {
return self
.program_ids()
.iter()
.any(|candidate| return *candidate == program_id.0.as_str());
}
/// Tests whether this executor supports a request.
fn supports_request(
&self,
request: &crate::ExApiExecutionRequest,
) -> crate::ExApiExecutionSupport;
/// Builds a neutral execution plan placeholder.
fn build_plan(
&self,
request: &crate::ExApiExecutionRequest,
) -> ks_core::Result<crate::ExApiExecutionPlan>;
}