672 lines
28 KiB
Rust
672 lines
28 KiB
Rust
// 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!("../../test-fixtures/contract-matrices/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)
|
|
);
|
|
}
|
|
}
|
|
}
|