v0.1.0-pre.024
This commit is contained in:
670
kb-onchain-transport/src/standard_methods.rs
Normal file
670
kb-onchain-transport/src/standard_methods.rs
Normal file
@@ -0,0 +1,670 @@
|
||||
// file: kb-onchain-transport/src/standard_methods.rs
|
||||
// version: 4
|
||||
|
||||
//! Canonical inventory of standard Solana HTTP and WebSocket JSON-RPC methods.
|
||||
|
||||
/// Strongest implementation contract exposed for one standard RPC method.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Serialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum StandardRpcContract {
|
||||
/// The crate exposes a dedicated request/result adapter in addition to raw JSON transport.
|
||||
TypedAdapter,
|
||||
/// The method is explicitly registered and callable through validated raw JSON transport.
|
||||
RawJson,
|
||||
}
|
||||
|
||||
impl crate::StandardRpcContract {
|
||||
/// Returns the stable matrix code for this contract.
|
||||
pub const fn code(self) -> &'static str {
|
||||
return match self {
|
||||
Self::TypedAdapter => "typed_adapter",
|
||||
Self::RawJson => "raw_json",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// Local category used to group standard Solana HTTP methods.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Serialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum StandardHttpCategory {
|
||||
/// Account state and account ownership reads.
|
||||
Accounts,
|
||||
/// SPL Token account and mint reads.
|
||||
Tokens,
|
||||
/// Transaction, signature, fee, simulation and submission methods.
|
||||
Transactions,
|
||||
/// Block, ledger and performance methods.
|
||||
Blocks,
|
||||
/// Cluster, node, epoch, slot and validator methods.
|
||||
Cluster,
|
||||
/// Inflation, supply and stake-economics methods.
|
||||
Economics,
|
||||
}
|
||||
|
||||
impl crate::StandardHttpCategory {
|
||||
/// Returns the stable matrix code for this category.
|
||||
pub const fn code(self) -> &'static str {
|
||||
return match self {
|
||||
Self::Accounts => "accounts",
|
||||
Self::Tokens => "tokens",
|
||||
Self::Transactions => "transactions",
|
||||
Self::Blocks => "blocks",
|
||||
Self::Cluster => "cluster",
|
||||
Self::Economics => "economics",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// One standard Solana HTTP JSON-RPC method specification.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct StandardHttpMethodSpec {
|
||||
/// Exact JSON-RPC method name.
|
||||
pub method: &'static str,
|
||||
/// Local inventory category.
|
||||
pub category: crate::StandardHttpCategory,
|
||||
/// Strongest contract currently exposed by `kb-onchain-transport`.
|
||||
pub contract: crate::StandardRpcContract,
|
||||
}
|
||||
|
||||
impl crate::StandardHttpMethodSpec {
|
||||
/// Returns the local HTTP routing class for this method.
|
||||
pub fn method_class(&self) -> crate::HttpMethodClass {
|
||||
return match self.method {
|
||||
"requestAirdrop" | "sendTransaction" => crate::HttpMethodClass::SendTransaction,
|
||||
"getBlock"
|
||||
| "getBlocks"
|
||||
| "getBlocksWithLimit"
|
||||
| "getProgramAccounts"
|
||||
| "getSignaturesForAddress"
|
||||
| "getTransaction"
|
||||
| "simulateTransaction" => crate::HttpMethodClass::HeavyRead,
|
||||
_ => crate::HttpMethodClass::GeneralRpc,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// Every standard Solana HTTP JSON-RPC method documented by the canonical RPC reference.
|
||||
pub const STANDARD_HTTP_METHODS: [crate::StandardHttpMethodSpec; 52] = [
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getAccountInfo",
|
||||
category: crate::StandardHttpCategory::Accounts,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getBalance",
|
||||
category: crate::StandardHttpCategory::Accounts,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getLargestAccounts",
|
||||
category: crate::StandardHttpCategory::Accounts,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getMinimumBalanceForRentExemption",
|
||||
category: crate::StandardHttpCategory::Accounts,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getMultipleAccounts",
|
||||
category: crate::StandardHttpCategory::Accounts,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getProgramAccounts",
|
||||
category: crate::StandardHttpCategory::Accounts,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getTokenAccountBalance",
|
||||
category: crate::StandardHttpCategory::Tokens,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getTokenAccountsByDelegate",
|
||||
category: crate::StandardHttpCategory::Tokens,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getTokenAccountsByOwner",
|
||||
category: crate::StandardHttpCategory::Tokens,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getTokenLargestAccounts",
|
||||
category: crate::StandardHttpCategory::Tokens,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getTokenSupply",
|
||||
category: crate::StandardHttpCategory::Tokens,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getFeeForMessage",
|
||||
category: crate::StandardHttpCategory::Transactions,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getLatestBlockhash",
|
||||
category: crate::StandardHttpCategory::Transactions,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getRecentPrioritizationFees",
|
||||
category: crate::StandardHttpCategory::Transactions,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getSignaturesForAddress",
|
||||
category: crate::StandardHttpCategory::Transactions,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getSignatureStatuses",
|
||||
category: crate::StandardHttpCategory::Transactions,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getTransaction",
|
||||
category: crate::StandardHttpCategory::Transactions,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getTransactionCount",
|
||||
category: crate::StandardHttpCategory::Transactions,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "isBlockhashValid",
|
||||
category: crate::StandardHttpCategory::Transactions,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "requestAirdrop",
|
||||
category: crate::StandardHttpCategory::Transactions,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "sendTransaction",
|
||||
category: crate::StandardHttpCategory::Transactions,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "simulateTransaction",
|
||||
category: crate::StandardHttpCategory::Transactions,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getBlock",
|
||||
category: crate::StandardHttpCategory::Blocks,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getBlockCommitment",
|
||||
category: crate::StandardHttpCategory::Blocks,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getBlockHeight",
|
||||
category: crate::StandardHttpCategory::Blocks,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getBlockProduction",
|
||||
category: crate::StandardHttpCategory::Blocks,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getBlocks",
|
||||
category: crate::StandardHttpCategory::Blocks,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getBlocksWithLimit",
|
||||
category: crate::StandardHttpCategory::Blocks,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getBlockTime",
|
||||
category: crate::StandardHttpCategory::Blocks,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getFirstAvailableBlock",
|
||||
category: crate::StandardHttpCategory::Blocks,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getRecentPerformanceSamples",
|
||||
category: crate::StandardHttpCategory::Blocks,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "minimumLedgerSlot",
|
||||
category: crate::StandardHttpCategory::Blocks,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getClusterNodes",
|
||||
category: crate::StandardHttpCategory::Cluster,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getEpochInfo",
|
||||
category: crate::StandardHttpCategory::Cluster,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getEpochSchedule",
|
||||
category: crate::StandardHttpCategory::Cluster,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getGenesisHash",
|
||||
category: crate::StandardHttpCategory::Cluster,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getHealth",
|
||||
category: crate::StandardHttpCategory::Cluster,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getHighestSnapshotSlot",
|
||||
category: crate::StandardHttpCategory::Cluster,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getIdentity",
|
||||
category: crate::StandardHttpCategory::Cluster,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getLeaderSchedule",
|
||||
category: crate::StandardHttpCategory::Cluster,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getMaxRetransmitSlot",
|
||||
category: crate::StandardHttpCategory::Cluster,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getMaxShredInsertSlot",
|
||||
category: crate::StandardHttpCategory::Cluster,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getSlot",
|
||||
category: crate::StandardHttpCategory::Cluster,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getSlotLeader",
|
||||
category: crate::StandardHttpCategory::Cluster,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getSlotLeaders",
|
||||
category: crate::StandardHttpCategory::Cluster,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getVersion",
|
||||
category: crate::StandardHttpCategory::Cluster,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getVoteAccounts",
|
||||
category: crate::StandardHttpCategory::Cluster,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getInflationGovernor",
|
||||
category: crate::StandardHttpCategory::Economics,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getInflationRate",
|
||||
category: crate::StandardHttpCategory::Economics,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getInflationReward",
|
||||
category: crate::StandardHttpCategory::Economics,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getStakeMinimumDelegation",
|
||||
category: crate::StandardHttpCategory::Economics,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
crate::StandardHttpMethodSpec {
|
||||
method: "getSupply",
|
||||
category: crate::StandardHttpCategory::Economics,
|
||||
contract: crate::StandardRpcContract::TypedAdapter,
|
||||
},
|
||||
];
|
||||
|
||||
/// Returns the canonical specification for one exact standard HTTP method name.
|
||||
pub fn standard_http_method(
|
||||
method: &str,
|
||||
) -> std::option::Option<&'static crate::StandardHttpMethodSpec> {
|
||||
return crate::STANDARD_HTTP_METHODS.iter().find(|entry| return entry.method == method);
|
||||
}
|
||||
|
||||
/// Stability of one standard Solana WebSocket subscription surface.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Serialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum StandardWsStability {
|
||||
/// Stable standard PubSub method.
|
||||
Stable,
|
||||
/// Method documented as unstable and potentially gated by validator flags.
|
||||
Unstable,
|
||||
}
|
||||
|
||||
impl crate::StandardWsStability {
|
||||
/// Returns the stable matrix code for this stability class.
|
||||
pub const fn code(self) -> &'static str {
|
||||
return match self {
|
||||
Self::Stable => "stable",
|
||||
Self::Unstable => "unstable",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// One standard Solana WebSocket subscribe/unsubscribe pair.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct StandardWsSubscriptionSpec {
|
||||
/// Exact subscribe method name.
|
||||
pub subscribe_method: &'static str,
|
||||
/// Exact unsubscribe method name.
|
||||
pub unsubscribe_method: &'static str,
|
||||
/// Exact notification method name emitted by the server.
|
||||
pub notification_method: &'static str,
|
||||
/// Stability declared by the canonical Solana RPC documentation.
|
||||
pub stability: crate::StandardWsStability,
|
||||
/// Strongest typed request contract exposed by `kb-onchain-transport`.
|
||||
pub request_contract: crate::StandardRpcContract,
|
||||
/// Strongest typed notification contract exposed by `kb-onchain-transport`.
|
||||
pub notification_contract: crate::StandardRpcContract,
|
||||
/// Whether the pair is supported by the reusable persistent session runtime.
|
||||
pub persistent_runtime: bool,
|
||||
}
|
||||
|
||||
/// Every standard Solana WebSocket subscription pair documented by the canonical RPC reference.
|
||||
pub const STANDARD_WS_SUBSCRIPTIONS: [crate::StandardWsSubscriptionSpec; 9] = [
|
||||
crate::StandardWsSubscriptionSpec {
|
||||
subscribe_method: "accountSubscribe",
|
||||
unsubscribe_method: "accountUnsubscribe",
|
||||
notification_method: "accountNotification",
|
||||
stability: crate::StandardWsStability::Stable,
|
||||
request_contract: crate::StandardRpcContract::TypedAdapter,
|
||||
notification_contract: crate::StandardRpcContract::TypedAdapter,
|
||||
persistent_runtime: true,
|
||||
},
|
||||
crate::StandardWsSubscriptionSpec {
|
||||
subscribe_method: "blockSubscribe",
|
||||
unsubscribe_method: "blockUnsubscribe",
|
||||
notification_method: "blockNotification",
|
||||
stability: crate::StandardWsStability::Unstable,
|
||||
request_contract: crate::StandardRpcContract::TypedAdapter,
|
||||
notification_contract: crate::StandardRpcContract::TypedAdapter,
|
||||
persistent_runtime: true,
|
||||
},
|
||||
crate::StandardWsSubscriptionSpec {
|
||||
subscribe_method: "logsSubscribe",
|
||||
unsubscribe_method: "logsUnsubscribe",
|
||||
notification_method: "logsNotification",
|
||||
stability: crate::StandardWsStability::Stable,
|
||||
request_contract: crate::StandardRpcContract::TypedAdapter,
|
||||
notification_contract: crate::StandardRpcContract::TypedAdapter,
|
||||
persistent_runtime: true,
|
||||
},
|
||||
crate::StandardWsSubscriptionSpec {
|
||||
subscribe_method: "programSubscribe",
|
||||
unsubscribe_method: "programUnsubscribe",
|
||||
notification_method: "programNotification",
|
||||
stability: crate::StandardWsStability::Stable,
|
||||
request_contract: crate::StandardRpcContract::TypedAdapter,
|
||||
notification_contract: crate::StandardRpcContract::TypedAdapter,
|
||||
persistent_runtime: true,
|
||||
},
|
||||
crate::StandardWsSubscriptionSpec {
|
||||
subscribe_method: "rootSubscribe",
|
||||
unsubscribe_method: "rootUnsubscribe",
|
||||
notification_method: "rootNotification",
|
||||
stability: crate::StandardWsStability::Stable,
|
||||
request_contract: crate::StandardRpcContract::TypedAdapter,
|
||||
notification_contract: crate::StandardRpcContract::TypedAdapter,
|
||||
persistent_runtime: true,
|
||||
},
|
||||
crate::StandardWsSubscriptionSpec {
|
||||
subscribe_method: "signatureSubscribe",
|
||||
unsubscribe_method: "signatureUnsubscribe",
|
||||
notification_method: "signatureNotification",
|
||||
stability: crate::StandardWsStability::Stable,
|
||||
request_contract: crate::StandardRpcContract::TypedAdapter,
|
||||
notification_contract: crate::StandardRpcContract::TypedAdapter,
|
||||
persistent_runtime: true,
|
||||
},
|
||||
crate::StandardWsSubscriptionSpec {
|
||||
subscribe_method: "slotSubscribe",
|
||||
unsubscribe_method: "slotUnsubscribe",
|
||||
notification_method: "slotNotification",
|
||||
stability: crate::StandardWsStability::Stable,
|
||||
request_contract: crate::StandardRpcContract::TypedAdapter,
|
||||
notification_contract: crate::StandardRpcContract::TypedAdapter,
|
||||
persistent_runtime: true,
|
||||
},
|
||||
crate::StandardWsSubscriptionSpec {
|
||||
subscribe_method: "slotsUpdatesSubscribe",
|
||||
unsubscribe_method: "slotsUpdatesUnsubscribe",
|
||||
notification_method: "slotsUpdatesNotification",
|
||||
stability: crate::StandardWsStability::Unstable,
|
||||
request_contract: crate::StandardRpcContract::TypedAdapter,
|
||||
notification_contract: crate::StandardRpcContract::TypedAdapter,
|
||||
persistent_runtime: true,
|
||||
},
|
||||
crate::StandardWsSubscriptionSpec {
|
||||
subscribe_method: "voteSubscribe",
|
||||
unsubscribe_method: "voteUnsubscribe",
|
||||
notification_method: "voteNotification",
|
||||
stability: crate::StandardWsStability::Unstable,
|
||||
request_contract: crate::StandardRpcContract::TypedAdapter,
|
||||
notification_contract: crate::StandardRpcContract::TypedAdapter,
|
||||
persistent_runtime: true,
|
||||
},
|
||||
];
|
||||
|
||||
/// Returns the canonical subscription specification matching a subscribe or unsubscribe method.
|
||||
pub fn standard_ws_subscription(
|
||||
method: &str,
|
||||
) -> std::option::Option<&'static crate::StandardWsSubscriptionSpec> {
|
||||
return crate::STANDARD_WS_SUBSCRIPTIONS.iter().find(|entry| {
|
||||
return entry.subscribe_method == method || entry.unsubscribe_method == method;
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn standard_http_inventory_is_exact_unique_and_classified() {
|
||||
assert_eq!(crate::STANDARD_HTTP_METHODS.len(), 52);
|
||||
let mut names = std::collections::BTreeSet::new();
|
||||
let mut typed_count = 0_usize;
|
||||
for method in &crate::STANDARD_HTTP_METHODS {
|
||||
assert!(names.insert(method.method));
|
||||
if method.contract == crate::StandardRpcContract::TypedAdapter {
|
||||
typed_count = typed_count.saturating_add(1);
|
||||
}
|
||||
assert_eq!(
|
||||
crate::standard_http_method(method.method),
|
||||
std::option::Option::Some(method)
|
||||
);
|
||||
}
|
||||
assert_eq!(typed_count, 52);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn configurable_request_registry_covers_the_former_thirty_eight_raw_methods() {
|
||||
fn method<Request: crate::StandardHttpRequest>() -> &'static str {
|
||||
return <Request as crate::StandardHttpRequest>::METHOD;
|
||||
}
|
||||
let methods = [
|
||||
method::<crate::GetLargestAccountsRequest>(),
|
||||
method::<crate::GetMultipleAccountsRequest>(),
|
||||
method::<crate::GetProgramAccountsRequest>(),
|
||||
method::<crate::GetTokenAccountBalanceRequest>(),
|
||||
method::<crate::GetTokenAccountsByDelegateRequest>(),
|
||||
method::<crate::GetTokenAccountsByOwnerRequest>(),
|
||||
method::<crate::GetTokenLargestAccountsRequest>(),
|
||||
method::<crate::GetTokenSupplyRequest>(),
|
||||
method::<crate::GetRecentPrioritizationFeesRequest>(),
|
||||
method::<crate::GetTransactionCountRequest>(),
|
||||
method::<crate::IsBlockhashValidRequest>(),
|
||||
method::<crate::GetBlockRequest>(),
|
||||
method::<crate::GetBlockCommitmentRequest>(),
|
||||
method::<crate::GetBlockProductionRequest>(),
|
||||
method::<crate::GetBlocksRequest>(),
|
||||
method::<crate::GetBlocksWithLimitRequest>(),
|
||||
method::<crate::GetBlockTimeRequest>(),
|
||||
method::<crate::GetFirstAvailableBlockRequest>(),
|
||||
method::<crate::GetRecentPerformanceSamplesRequest>(),
|
||||
method::<crate::MinimumLedgerSlotRequest>(),
|
||||
method::<crate::GetClusterNodesRequest>(),
|
||||
method::<crate::GetEpochScheduleRequest>(),
|
||||
method::<crate::GetHealthRequest>(),
|
||||
method::<crate::GetHighestSnapshotSlotRequest>(),
|
||||
method::<crate::GetIdentityRequest>(),
|
||||
method::<crate::GetLeaderScheduleRequest>(),
|
||||
method::<crate::GetMaxRetransmitSlotRequest>(),
|
||||
method::<crate::GetMaxShredInsertSlotRequest>(),
|
||||
method::<crate::GetSlotRequest>(),
|
||||
method::<crate::GetSlotLeaderRequest>(),
|
||||
method::<crate::GetSlotLeadersRequest>(),
|
||||
method::<crate::GetVersionRequest>(),
|
||||
method::<crate::GetVoteAccountsRequest>(),
|
||||
method::<crate::GetInflationGovernorRequest>(),
|
||||
method::<crate::GetInflationRateRequest>(),
|
||||
method::<crate::GetInflationRewardRequest>(),
|
||||
method::<crate::GetStakeMinimumDelegationRequest>(),
|
||||
method::<crate::GetSupplyRequest>(),
|
||||
];
|
||||
assert_eq!(methods.len(), 38);
|
||||
let mut unique = std::collections::BTreeSet::new();
|
||||
for method_name in methods {
|
||||
assert!(unique.insert(method_name));
|
||||
let specification = match crate::standard_http_method(method_name) {
|
||||
std::option::Option::Some(specification) => specification,
|
||||
std::option::Option::None => panic!("typed method absent from registry"),
|
||||
};
|
||||
assert_eq!(specification.contract, crate::StandardRpcContract::TypedAdapter);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn standard_ws_inventory_contains_nine_pairs_and_eighteen_unique_methods() {
|
||||
assert_eq!(crate::STANDARD_WS_SUBSCRIPTIONS.len(), 9);
|
||||
let mut names = std::collections::BTreeSet::new();
|
||||
let mut unstable_count = 0_usize;
|
||||
for subscription in &crate::STANDARD_WS_SUBSCRIPTIONS {
|
||||
assert!(names.insert(subscription.subscribe_method));
|
||||
assert!(names.insert(subscription.unsubscribe_method));
|
||||
if subscription.stability == crate::StandardWsStability::Unstable {
|
||||
unstable_count = unstable_count.saturating_add(1);
|
||||
}
|
||||
assert_eq!(subscription.request_contract, crate::StandardRpcContract::TypedAdapter);
|
||||
assert_eq!(
|
||||
subscription.notification_contract,
|
||||
crate::StandardRpcContract::TypedAdapter
|
||||
);
|
||||
assert!(subscription.persistent_runtime);
|
||||
assert_eq!(
|
||||
crate::standard_ws_subscription(subscription.subscribe_method),
|
||||
std::option::Option::Some(subscription)
|
||||
);
|
||||
assert_eq!(
|
||||
crate::standard_ws_subscription(subscription.unsubscribe_method),
|
||||
std::option::Option::Some(subscription)
|
||||
);
|
||||
}
|
||||
assert_eq!(names.len(), 18);
|
||||
assert_eq!(unstable_count, 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn standard_rpc_matrix_matches_compiled_inventory() {
|
||||
let raw = include_str!("../../docs/SOLANA_STANDARD_RPC_MATRIX.json");
|
||||
let parsed = match serde_json::from_str::<serde_json::Value>(raw) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => panic!("rpc matrix parsing failed: {error}"),
|
||||
};
|
||||
let http_methods = match parsed.get("http_methods").and_then(serde_json::Value::as_array) {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => panic!("rpc matrix http_methods missing"),
|
||||
};
|
||||
let ws_subscriptions =
|
||||
match parsed.get("ws_subscriptions").and_then(serde_json::Value::as_array) {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => panic!("rpc matrix ws_subscriptions missing"),
|
||||
};
|
||||
assert_eq!(http_methods.len(), crate::STANDARD_HTTP_METHODS.len());
|
||||
assert_eq!(ws_subscriptions.len(), crate::STANDARD_WS_SUBSCRIPTIONS.len());
|
||||
for method in &crate::STANDARD_HTTP_METHODS {
|
||||
let matrix_entry = http_methods.iter().find(|entry| {
|
||||
return entry.get("method").and_then(serde_json::Value::as_str)
|
||||
== std::option::Option::Some(method.method);
|
||||
});
|
||||
let matrix_entry = match matrix_entry {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => panic!("rpc matrix HTTP method missing"),
|
||||
};
|
||||
assert_eq!(
|
||||
matrix_entry.get("category").and_then(serde_json::Value::as_str),
|
||||
std::option::Option::Some(method.category.code())
|
||||
);
|
||||
assert_eq!(
|
||||
matrix_entry.get("contract").and_then(serde_json::Value::as_str),
|
||||
std::option::Option::Some(method.contract.code())
|
||||
);
|
||||
}
|
||||
for subscription in &crate::STANDARD_WS_SUBSCRIPTIONS {
|
||||
let matrix_entry = ws_subscriptions.iter().find(|entry| {
|
||||
return entry.get("subscribe_method").and_then(serde_json::Value::as_str)
|
||||
== std::option::Option::Some(subscription.subscribe_method);
|
||||
});
|
||||
let matrix_entry = match matrix_entry {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => panic!("rpc matrix WS subscription missing"),
|
||||
};
|
||||
assert_eq!(
|
||||
matrix_entry.get("unsubscribe_method").and_then(serde_json::Value::as_str),
|
||||
std::option::Option::Some(subscription.unsubscribe_method)
|
||||
);
|
||||
assert_eq!(
|
||||
matrix_entry.get("notification_method").and_then(serde_json::Value::as_str),
|
||||
std::option::Option::Some(subscription.notification_method)
|
||||
);
|
||||
assert_eq!(
|
||||
matrix_entry.get("stability").and_then(serde_json::Value::as_str),
|
||||
std::option::Option::Some(subscription.stability.code())
|
||||
);
|
||||
assert_eq!(
|
||||
matrix_entry.get("request_contract").and_then(serde_json::Value::as_str),
|
||||
std::option::Option::Some(subscription.request_contract.code())
|
||||
);
|
||||
assert_eq!(
|
||||
matrix_entry.get("notification_contract").and_then(serde_json::Value::as_str),
|
||||
std::option::Option::Some(subscription.notification_contract.code())
|
||||
);
|
||||
assert_eq!(
|
||||
matrix_entry.get("persistent_runtime").and_then(serde_json::Value::as_bool),
|
||||
std::option::Option::Some(subscription.persistent_runtime)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user