v0.3.15-pre.003
This commit is contained in:
@@ -53,6 +53,7 @@
|
||||
],
|
||||
"resources": {
|
||||
"../../config/composite.ksp-app-backfill-desk.json": "config/composite.ksp-app-backfill-desk.json",
|
||||
"../../config/composite.ksp-app-raw-transaction-ingest-desk.json": "config/composite.ksp-app-raw-transaction-ingest-desk.json",
|
||||
"../../config/composite.ksp-app-solprices-desk.json": "config/composite.ksp-app-solprices-desk.json",
|
||||
"../../config/composite.ksp-app-store-desk.json": "config/composite.ksp-app-store-desk.json",
|
||||
"../../config/composite.ksp-app-wallet-desk.json": "config/composite.ksp-app-wallet-desk.json",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-app-backfill-desk/tests/desktop_contract.rs
|
||||
// version: 17
|
||||
// version: 18
|
||||
|
||||
//! Structural desktop contract checks for the Backfill Desk scaffold.
|
||||
|
||||
@@ -145,9 +145,10 @@ fn pre_003_composite_packaging_follows_atomic_config_registry_contract() {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return,
|
||||
};
|
||||
assert_eq!(resources.len(), 15);
|
||||
assert_eq!(resources.len(), 16);
|
||||
for required in [
|
||||
"../../config/composite.ksp-app-backfill-desk.json",
|
||||
"../../config/composite.ksp-app-raw-transaction-ingest-desk.json",
|
||||
"../../config/composite.ksp-app-solprices-desk.json",
|
||||
"../../config/composite.ksp-app-store-desk.json",
|
||||
"../../config/composite.ksp-app-wallet-desk.json",
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
],
|
||||
"resources": {
|
||||
"../../config/composite.ksp-app-backfill-desk.json": "config/composite.ksp-app-backfill-desk.json",
|
||||
"../../config/composite.ksp-app-raw-transaction-ingest-desk.json": "config/composite.ksp-app-raw-transaction-ingest-desk.json",
|
||||
"../../config/composite.ksp-app-solprices-desk.json": "config/composite.ksp-app-solprices-desk.json",
|
||||
"../../config/composite.ksp-app-store-desk.json": "config/composite.ksp-app-store-desk.json",
|
||||
"../../config/composite.ksp-app-wallet-desk.json": "config/composite.ksp-app-wallet-desk.json",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-app-config-desk/tests/desktop_contract.rs
|
||||
// version: 13
|
||||
// version: 14
|
||||
|
||||
//! Desktop build/shell contract audits for Config Desk.
|
||||
|
||||
@@ -110,11 +110,15 @@ fn pre_018_packaged_runtime_bundles_config_resources_and_activates_shared_writab
|
||||
let resources = tauri.pointer("/bundle/resources").and_then(serde_json::Value::as_object);
|
||||
assert!(resources.is_some(), "packaged Config resources map must exist");
|
||||
if let std::option::Option::Some(resources) = resources {
|
||||
assert_eq!(resources.len(), 15);
|
||||
assert_eq!(resources.len(), 16);
|
||||
assert_eq!(
|
||||
resources.get("../../config/composite.ksp-app-backfill-desk.json").and_then(serde_json::Value::as_str),
|
||||
std::option::Option::Some("config/composite.ksp-app-backfill-desk.json"),
|
||||
);
|
||||
assert_eq!(
|
||||
resources.get("../../config/composite.ksp-app-raw-transaction-ingest-desk.json").and_then(serde_json::Value::as_str),
|
||||
std::option::Option::Some("config/composite.ksp-app-raw-transaction-ingest-desk.json"),
|
||||
);
|
||||
assert_eq!(
|
||||
resources.get("../../config/composite.ksp-app-solprices-desk.json").and_then(serde_json::Value::as_str),
|
||||
std::option::Option::Some("config/composite.ksp-app-solprices-desk.json"),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-app-config-desk/unit_tests/profiles.rs
|
||||
// version: 8
|
||||
// version: 9
|
||||
|
||||
#[test]
|
||||
fn profile_inventory_exposes_registered_profile_documents() {
|
||||
@@ -21,6 +21,9 @@ fn profile_inventory_exposes_registered_profile_documents() {
|
||||
assert!(inventory.iter().any(|document| -> bool {
|
||||
return document.file_id == ksp_config_lib::FILE_ID_STD_WALLET;
|
||||
}));
|
||||
assert!(inventory.iter().any(|document| -> bool {
|
||||
return document.file_id == ksp_config_lib::FILE_ID_COMPOSITE_KSP_APP_RAW_TRANSACTION_INGEST_DESK;
|
||||
}));
|
||||
assert!(inventory.iter().any(|document| -> bool {
|
||||
return document.file_id == ksp_config_lib::FILE_ID_COMPOSITE_KSP_APP_WALLET_DESK;
|
||||
}));
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
],
|
||||
"resources": {
|
||||
"../../config/composite.ksp-app-backfill-desk.json": "config/composite.ksp-app-backfill-desk.json",
|
||||
"../../config/composite.ksp-app-raw-transaction-ingest-desk.json": "config/composite.ksp-app-raw-transaction-ingest-desk.json",
|
||||
"../../config/composite.ksp-app-solprices-desk.json": "config/composite.ksp-app-solprices-desk.json",
|
||||
"../../config/composite.ksp-app-store-desk.json": "config/composite.ksp-app-store-desk.json",
|
||||
"../../config/composite.ksp-app-wallet-desk.json": "config/composite.ksp-app-wallet-desk.json",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-app-solprices-desk/tests/desktop_contract.rs
|
||||
// version: 12
|
||||
// version: 13
|
||||
|
||||
//! Desktop scaffold, shared-template and Config packaging contract audits for SOL Prices Desk `0.2.12`.
|
||||
|
||||
@@ -85,17 +85,21 @@ fn pre_002_package_is_mixed_lib_bin_and_frontend_is_scaffold_only() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn v0_3_8_pre_006_packaging_contains_current_fifteen_config_resources() {
|
||||
fn v0_3_8_pre_006_packaging_contains_current_sixteen_config_resources() {
|
||||
let root = app_root();
|
||||
let tauri = read_json(root.join("tauri.conf.json").as_path());
|
||||
let resources = tauri.pointer("/bundle/resources").and_then(serde_json::Value::as_object);
|
||||
assert!(resources.is_some());
|
||||
if let std::option::Option::Some(resources) = resources {
|
||||
assert_eq!(resources.len(), 15);
|
||||
assert_eq!(resources.len(), 16);
|
||||
assert_eq!(
|
||||
resources.get("../../config/composite.ksp-app-backfill-desk.json").and_then(serde_json::Value::as_str),
|
||||
std::option::Option::Some("config/composite.ksp-app-backfill-desk.json"),
|
||||
);
|
||||
assert_eq!(
|
||||
resources.get("../../config/composite.ksp-app-raw-transaction-ingest-desk.json").and_then(serde_json::Value::as_str),
|
||||
std::option::Option::Some("config/composite.ksp-app-raw-transaction-ingest-desk.json"),
|
||||
);
|
||||
assert_eq!(
|
||||
resources.get("../../config/composite.ksp-app-solprices-desk.json").and_then(serde_json::Value::as_str),
|
||||
std::option::Option::Some("config/composite.ksp-app-solprices-desk.json"),
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
],
|
||||
"resources": {
|
||||
"../../config/composite.ksp-app-backfill-desk.json": "config/composite.ksp-app-backfill-desk.json",
|
||||
"../../config/composite.ksp-app-raw-transaction-ingest-desk.json": "config/composite.ksp-app-raw-transaction-ingest-desk.json",
|
||||
"../../config/composite.ksp-app-solprices-desk.json": "config/composite.ksp-app-solprices-desk.json",
|
||||
"../../config/composite.ksp-app-store-desk.json": "config/composite.ksp-app-store-desk.json",
|
||||
"../../config/composite.ksp-app-wallet-desk.json": "config/composite.ksp-app-wallet-desk.json",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-app-store-desk/tests/desktop_contract.rs
|
||||
// version: 10
|
||||
// version: 11
|
||||
|
||||
//! Desktop template and frontend contract tests for the Store Desk scaffold.
|
||||
|
||||
@@ -153,7 +153,8 @@ fn pre_006_composite_and_packaged_resources_cover_store_desk_and_the_complete_co
|
||||
let resources = tauri["bundle"]["resources"].as_object();
|
||||
assert!(resources.is_some());
|
||||
if let std::option::Option::Some(resources) = resources {
|
||||
assert_eq!(resources.len(), 15);
|
||||
assert_eq!(resources.len(), 16);
|
||||
assert!(resources.contains_key("../../config/composite.ksp-app-raw-transaction-ingest-desk.json"));
|
||||
assert!(resources.contains_key("../../config/composite.ksp-app-store-desk.json"));
|
||||
assert!(resources.contains_key("../../config/std.store.json"));
|
||||
assert!(resources.contains_key("../../config/schemas/std.store.schema.json"));
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
],
|
||||
"resources": {
|
||||
"../../config/composite.ksp-app-backfill-desk.json": "config/composite.ksp-app-backfill-desk.json",
|
||||
"../../config/composite.ksp-app-raw-transaction-ingest-desk.json": "config/composite.ksp-app-raw-transaction-ingest-desk.json",
|
||||
"../../config/composite.ksp-app-solprices-desk.json": "config/composite.ksp-app-solprices-desk.json",
|
||||
"../../config/composite.ksp-app-store-desk.json": "config/composite.ksp-app-store-desk.json",
|
||||
"../../config/composite.ksp-app-wallet-desk.json": "config/composite.ksp-app-wallet-desk.json",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-app-wallet-desk/tests/desktop_contract.rs
|
||||
// version: 33
|
||||
// version: 34
|
||||
|
||||
//! Desktop build, shell and Config-status contract audits for Wallet Desk.
|
||||
|
||||
@@ -432,11 +432,15 @@ fn pre_018_packaged_runtime_bundles_config_resources_and_keeps_wallet_desk_versi
|
||||
let resources = tauri.pointer("/bundle/resources").and_then(serde_json::Value::as_object);
|
||||
assert!(resources.is_some(), "packaged Wallet Desk Config resources map must exist");
|
||||
if let std::option::Option::Some(resources) = resources {
|
||||
assert_eq!(resources.len(), 15);
|
||||
assert_eq!(resources.len(), 16);
|
||||
assert_eq!(
|
||||
resources.get("../../config/composite.ksp-app-backfill-desk.json").and_then(serde_json::Value::as_str),
|
||||
std::option::Option::Some("config/composite.ksp-app-backfill-desk.json"),
|
||||
);
|
||||
assert_eq!(
|
||||
resources.get("../../config/composite.ksp-app-raw-transaction-ingest-desk.json").and_then(serde_json::Value::as_str),
|
||||
std::option::Option::Some("config/composite.ksp-app-raw-transaction-ingest-desk.json"),
|
||||
);
|
||||
assert_eq!(
|
||||
resources.get("../../config/composite.ksp-app-solprices-desk.json").and_then(serde_json::Value::as_str),
|
||||
std::option::Option::Some("config/composite.ksp-app-solprices-desk.json"),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-app-wallet-desk/tests/release_compliance.rs
|
||||
// version: 12
|
||||
// version: 13
|
||||
|
||||
//! Release-wide deterministic compliance canaries for Wallet Desk.
|
||||
|
||||
@@ -199,7 +199,7 @@ fn packaged_resources_include_only_registered_config_sources_and_schemas() {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return,
|
||||
};
|
||||
assert_eq!(resources.len(), 15);
|
||||
assert_eq!(resources.len(), 16);
|
||||
for (source, destination) in resources {
|
||||
let destination = destination.as_str();
|
||||
assert!(destination.is_some(), "resource destination must be textual");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: crates/ksp-config-lib/README.md -->
|
||||
<!-- version: 12 -->
|
||||
<!-- version: 13 -->
|
||||
|
||||
# ksp-config-lib
|
||||
|
||||
@@ -35,8 +35,9 @@ La crate centralise les documents JSON, leurs schemas, les profils et compositio
|
||||
Le registre par défaut connaît :
|
||||
|
||||
```text
|
||||
cfg.composite.ksp-app-backfill-desk -> config/composite.ksp-app-backfill-desk.json
|
||||
cfg.composite.ksp-app-solprices-desk -> config/composite.ksp-app-solprices-desk.json
|
||||
cfg.composite.ksp-app-backfill-desk -> config/composite.ksp-app-backfill-desk.json
|
||||
cfg.composite.ksp-app-raw-transaction-ingest-desk -> config/composite.ksp-app-raw-transaction-ingest-desk.json
|
||||
cfg.composite.ksp-app-solprices-desk -> config/composite.ksp-app-solprices-desk.json
|
||||
cfg.composite.ksp-app-store-desk -> config/composite.ksp-app-store-desk.json
|
||||
cfg.composite.ksp-app-wallet-desk -> config/composite.ksp-app-wallet-desk.json
|
||||
cfg.std.logging -> config/std.logging.json
|
||||
@@ -103,6 +104,7 @@ Le document Logging refuse les valeurs de sensibilité `Secret` dans sa configur
|
||||
- [`../../config/std.store.json`](../../config/std.store.json) — targets Store PostgreSQL Devnet/Mainnet/Testnet et settings runtime bornés ;
|
||||
- [`../../config/std.wallet.json`](../../config/std.wallet.json) — racine Wallet globale et sous-répertoire optionnel par profil ;
|
||||
- [`../../config/composite.ksp-app-backfill-desk.json`](../../config/composite.ksp-app-backfill-desk.json) — composition Logging/Transport/Store de Backfill Desk ;
|
||||
- [`../../config/composite.ksp-app-raw-transaction-ingest-desk.json`](../../config/composite.ksp-app-raw-transaction-ingest-desk.json) — profils cohérents Logging/Transport/Store du Raw Transaction Ingest Desk ;
|
||||
- [`../../config/composite.ksp-app-solprices-desk.json`](../../config/composite.ksp-app-solprices-desk.json) — composition Logging/Off-chain Transport de SOL Prices Desk ;
|
||||
- [`../../config/composite.ksp-app-store-desk.json`](../../config/composite.ksp-app-store-desk.json) — composition Logging/Store de Store Desk ;
|
||||
- [`../../config/composite.ksp-app-wallet-desk.json`](../../config/composite.ksp-app-wallet-desk.json) — composition Logging/Off-chain Transport/On-chain Transport/Wallet de Wallet Desk ;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- file: crates/ksp-config-lib/USAGE.md -->
|
||||
<!-- version: 15 -->
|
||||
<!-- version: 16 -->
|
||||
|
||||
# Utilisation de ksp-config-lib
|
||||
|
||||
@@ -28,6 +28,7 @@ Les arguments compris par Config sont :
|
||||
```text
|
||||
--cfgpath=/path/to/config
|
||||
--schemapath=/path/to/schemas
|
||||
--filemap=cfg.composite.ksp-app-raw-transaction-ingest-desk=my-raw-ingest-desk.json
|
||||
--filemap=cfg.composite.ksp-app-solprices-desk=my-solprices-desk.json
|
||||
--filemap=cfg.composite.ksp-app-wallet-desk=my-wallet-desk.json
|
||||
--filemap=cfg.std.logging=my-logging.json
|
||||
@@ -161,7 +162,9 @@ Le provider affiche `solana-yellowstone-grpc.publicnode.com:443` ; le profil ver
|
||||
|
||||
L'accesseur historique `into_transport_settings()` conserve volontairement son tuple `(HTTP, Option<WS>)`. Un consumer ayant besoin des trois backends utilise `into_all_transport_settings()` ou les accesseurs séparés afin de ne pas casser silencieusement les consumers V2.
|
||||
|
||||
Les protocoles WebSocket restent `kind = "solana_standard"` et `kind = "helius_laserstream"`. Helius LaserStream WebSocket conserve ses URLs Config-owned et sa clé `KSP_SECRET_HELIUS_API_KEY`; cette surface est indépendante de Yellowstone gRPC.
|
||||
Les protocoles WebSocket restent `kind = "solana_standard"` et `kind = "helius_laserstream"`. Chaque endpoint peut en plus déclarer `capabilities`, liste de descriptors `WsSubscriptionKind` (`account`, `block`, `logs`, `program`, `root`, `signature`, `slot`, `slots_updates`, `vote`, `helius_transaction`). L'absence de cette liste reste backward-compatible mais ne constitue aucune preuve de support ; une liste présente est mappée explicitement vers Transport puis validée contre le protocole. Config ne déduit jamais une capability depuis `provider`.
|
||||
|
||||
Les profils Solana standard versionnés déclarent conservativement les six familles stables `account/logs/program/root/signature/slot` et ne déclarent donc pas `block`. Les profils `helius_devnet` et `helius_mainnet` déclarent les sept familles Helius déjà supportées par la façade (`account/logs/program/root/signature/slot/slots_updates`) plus `helius_transaction`, sans `block` ni `vote`. Helius LaserStream WebSocket conserve ses URLs Config-owned et sa clé `KSP_SECRET_HELIUS_API_KEY`; cette surface est indépendante de Yellowstone gRPC.
|
||||
|
||||
Les scalaires `*_ms` restent des valeurs Config et sont convertis en `std::time::Duration` par l'adapter. La dépendance reste unidirectionnelle : Config connaît les contrats Transport pour les construire ; Transport ne connaît ni Config, ni `.env`, ni les variables KSP.
|
||||
|
||||
@@ -289,7 +292,7 @@ let component = match composite.component("wallet") {
|
||||
let wallet = engine.resolve_wallet_config_profile(component.resolved(), &environment);
|
||||
```
|
||||
|
||||
La même forme existe pour Logging via `resolve_logging_config_profile`. Le composite `cfg.composite.ksp-app-solprices-desk` référence `logging` et `offchain_transport`. Le composite `cfg.composite.ksp-app-wallet-desk` référence `logging`, `offchain_transport`, `transport` et `wallet`; chaque application valide ses frontières de composition au bootstrap.
|
||||
La même forme existe pour Logging via `resolve_logging_config_profile`. Le composite `cfg.composite.ksp-app-raw-transaction-ingest-desk` référence exactement `logging`, `transport` et `store`; ses profils couplent explicitement un profil Transport et un profil Store du même réseau logique (`devnet`, `mainnet` ou `testnet`) afin que l'application n'assemble jamais arbitrairement deux réseaux. Le composite `cfg.composite.ksp-app-solprices-desk` référence `logging` et `offchain_transport`. Le composite `cfg.composite.ksp-app-wallet-desk` référence `logging`, `offchain_transport`, `transport` et `wallet`; chaque application valide ses frontières de composition au bootstrap.
|
||||
|
||||
## 6. Management de `std.logging.json`
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-config-lib/src/lib.rs
|
||||
// version: 23
|
||||
// version: 24
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![deny(unreachable_pub)]
|
||||
@@ -153,6 +153,8 @@ pub use self::registry::ConfigFileKind;
|
||||
pub use self::registry::ConfigFileRegistry;
|
||||
/// Default physical filename for the Backfill Desk composite configuration document.
|
||||
pub use self::registry::DEFAULT_COMPOSITE_KSP_APP_BACKFILL_DESK_FILENAME;
|
||||
/// Default physical filename for the Raw Transaction Ingest Desk composite configuration document.
|
||||
pub use self::registry::DEFAULT_COMPOSITE_KSP_APP_RAW_TRANSACTION_INGEST_DESK_FILENAME;
|
||||
/// Default physical filename for the SOL Prices Desk composite configuration document.
|
||||
pub use self::registry::DEFAULT_COMPOSITE_KSP_APP_SOLPRICES_DESK_FILENAME;
|
||||
/// Default physical filename for the Store Desk composite configuration document.
|
||||
@@ -183,6 +185,8 @@ pub use self::registry::DEFAULT_STD_WALLET_FILENAME;
|
||||
pub use self::registry::DEFAULT_STD_WALLET_SCHEMA_FILENAME;
|
||||
/// Logical file identifier for the Backfill Desk composite configuration document.
|
||||
pub use self::registry::FILE_ID_COMPOSITE_KSP_APP_BACKFILL_DESK;
|
||||
/// Logical file identifier for the Raw Transaction Ingest Desk composite configuration document.
|
||||
pub use self::registry::FILE_ID_COMPOSITE_KSP_APP_RAW_TRANSACTION_INGEST_DESK;
|
||||
/// Logical file identifier for the SOL Prices Desk composite configuration document.
|
||||
pub use self::registry::FILE_ID_COMPOSITE_KSP_APP_SOLPRICES_DESK;
|
||||
/// Logical file identifier for the Store Desk composite configuration document.
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
// file: crates/ksp-config-lib/src/registry.rs
|
||||
// version: 15
|
||||
// version: 16
|
||||
|
||||
/// Bootstrap argument used to replace a known Config filename mapping.
|
||||
pub const ARG_FILE_MAP: &str = "--filemap";
|
||||
/// Default physical filename for the Backfill Desk composite configuration document.
|
||||
pub const DEFAULT_COMPOSITE_KSP_APP_BACKFILL_DESK_FILENAME: &str = "composite.ksp-app-backfill-desk.json";
|
||||
/// Default physical filename for the Raw Transaction Ingest Desk composite configuration document.
|
||||
pub const DEFAULT_COMPOSITE_KSP_APP_RAW_TRANSACTION_INGEST_DESK_FILENAME: &str = "composite.ksp-app-raw-transaction-ingest-desk.json";
|
||||
/// Default physical filename for the SOL Prices Desk composite configuration document.
|
||||
pub const DEFAULT_COMPOSITE_KSP_APP_SOLPRICES_DESK_FILENAME: &str = "composite.ksp-app-solprices-desk.json";
|
||||
/// Default physical filename for the Store Desk composite configuration document.
|
||||
@@ -35,6 +37,8 @@ pub const DEFAULT_STD_WALLET_FILENAME: &str = "std.wallet.json";
|
||||
pub const DEFAULT_STD_WALLET_SCHEMA_FILENAME: &str = "std.wallet.schema.json";
|
||||
/// Logical file identifier for the Backfill Desk composite configuration document.
|
||||
pub const FILE_ID_COMPOSITE_KSP_APP_BACKFILL_DESK: &str = "cfg.composite.ksp-app-backfill-desk";
|
||||
/// Logical file identifier for the Raw Transaction Ingest Desk composite configuration document.
|
||||
pub const FILE_ID_COMPOSITE_KSP_APP_RAW_TRANSACTION_INGEST_DESK: &str = "cfg.composite.ksp-app-raw-transaction-ingest-desk";
|
||||
/// Logical file identifier for the SOL Prices Desk composite configuration document.
|
||||
pub const FILE_ID_COMPOSITE_KSP_APP_SOLPRICES_DESK: &str = "cfg.composite.ksp-app-solprices-desk";
|
||||
/// Logical file identifier for the Store Desk composite configuration document.
|
||||
@@ -178,6 +182,16 @@ impl ConfigFileRegistry {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let raw_transaction_ingest_composite = ConfigFileDescriptor::new(
|
||||
FILE_ID_COMPOSITE_KSP_APP_RAW_TRANSACTION_INGEST_DESK,
|
||||
ConfigFileKind::Config,
|
||||
DEFAULT_COMPOSITE_KSP_APP_RAW_TRANSACTION_INGEST_DESK_FILENAME,
|
||||
std::option::Option::Some(FILE_ID_SCHEMA_COMPOSITE),
|
||||
);
|
||||
let raw_transaction_ingest_composite = match raw_transaction_ingest_composite {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let solprices_composite = ConfigFileDescriptor::new(
|
||||
FILE_ID_COMPOSITE_KSP_APP_SOLPRICES_DESK,
|
||||
ConfigFileKind::Config,
|
||||
@@ -300,6 +314,7 @@ impl ConfigFileRegistry {
|
||||
};
|
||||
return crate::build_registry([
|
||||
backfill_composite,
|
||||
raw_transaction_ingest_composite,
|
||||
solprices_composite,
|
||||
store_desk_composite,
|
||||
wallet_composite,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-config-lib/src/transport.rs
|
||||
// version: 5
|
||||
// version: 6
|
||||
|
||||
/// Effective standard on-chain Transport configuration resolved from Config and mapped to HTTP plus optional WebSocket and Yellowstone gRPC runtime contracts.
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
@@ -259,6 +259,8 @@ struct EffectiveWsEndpointSource {
|
||||
kind: String,
|
||||
url: String,
|
||||
#[serde(default)]
|
||||
capabilities: std::option::Option<std::vec::Vec<String>>,
|
||||
#[serde(default)]
|
||||
session: std::option::Option<EffectiveWsSessionOverrideSource>,
|
||||
}
|
||||
|
||||
@@ -812,7 +814,7 @@ fn map_ws_endpoints(
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
endpoints.push(ksp_onchain_transport_lib::WsEndpointSettings::new(
|
||||
let mut endpoint = ksp_onchain_transport_lib::WsEndpointSettings::new(
|
||||
source.name,
|
||||
source.enabled,
|
||||
ksp_onchain_transport_lib::WsProviderName::new(source.provider),
|
||||
@@ -820,7 +822,20 @@ fn map_ws_endpoints(
|
||||
protocol,
|
||||
url,
|
||||
session,
|
||||
));
|
||||
);
|
||||
if let std::option::Option::Some(capability_sources) = source.capabilities {
|
||||
let mut capabilities = std::vec::Vec::<ksp_onchain_transport_lib::WsSubscriptionKind>::with_capacity(capability_sources.len());
|
||||
for capability_source in capability_sources {
|
||||
let capability = map_ws_subscription_capability(capability_source.as_str(), profile, endpoint_name.as_str());
|
||||
let capability = match capability {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
capabilities.push(capability);
|
||||
}
|
||||
endpoint = endpoint.with_subscription_capabilities(capabilities);
|
||||
}
|
||||
endpoints.push(endpoint);
|
||||
}
|
||||
return std::result::Result::Ok(endpoints);
|
||||
}
|
||||
@@ -841,6 +856,30 @@ fn map_ws_protocol_kind(
|
||||
};
|
||||
}
|
||||
|
||||
fn map_ws_subscription_capability(
|
||||
value: &str,
|
||||
profile: &crate::ResolvedConfigProfile,
|
||||
endpoint_name: &str,
|
||||
) -> ksp_core_lib::Result<ksp_onchain_transport_lib::WsSubscriptionKind> {
|
||||
return match value {
|
||||
"account" => std::result::Result::Ok(ksp_onchain_transport_lib::WsSubscriptionKind::Account),
|
||||
"block" => std::result::Result::Ok(ksp_onchain_transport_lib::WsSubscriptionKind::Block),
|
||||
"logs" => std::result::Result::Ok(ksp_onchain_transport_lib::WsSubscriptionKind::Logs),
|
||||
"program" => std::result::Result::Ok(ksp_onchain_transport_lib::WsSubscriptionKind::Program),
|
||||
"root" => std::result::Result::Ok(ksp_onchain_transport_lib::WsSubscriptionKind::Root),
|
||||
"signature" => std::result::Result::Ok(ksp_onchain_transport_lib::WsSubscriptionKind::Signature),
|
||||
"slot" => std::result::Result::Ok(ksp_onchain_transport_lib::WsSubscriptionKind::Slot),
|
||||
"slots_updates" => std::result::Result::Ok(ksp_onchain_transport_lib::WsSubscriptionKind::SlotsUpdates),
|
||||
"vote" => std::result::Result::Ok(ksp_onchain_transport_lib::WsSubscriptionKind::Vote),
|
||||
"helius_transaction" => std::result::Result::Ok(ksp_onchain_transport_lib::WsSubscriptionKind::HeliusTransaction),
|
||||
_ => std::result::Result::Err(
|
||||
effective_error(profile, "effective WebSocket subscription capability is unsupported")
|
||||
.with_context("endpoint_name", endpoint_name)
|
||||
.with_context("ws_capability", value),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
fn map_ws_session_settings(
|
||||
defaults: &EffectiveWsSessionSource,
|
||||
overrides: std::option::Option<&EffectiveWsSessionOverrideSource>,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-config-lib/tests/ownership.rs
|
||||
// version: 9
|
||||
// version: 10
|
||||
|
||||
//! Workspace ownership audits for KSP application configuration boundaries.
|
||||
|
||||
@@ -262,6 +262,7 @@ fn workspace_crates_do_not_hardcode_config_managed_physical_files() {
|
||||
};
|
||||
for token in [
|
||||
"\".env\"",
|
||||
"\"composite.ksp-app-raw-transaction-ingest-desk.json\"",
|
||||
"\"composite.ksp-app-solprices-desk.json\"",
|
||||
"\"composite.ksp-app-wallet-desk.json\"",
|
||||
"\"composite.schema.json\"",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-config-lib/tests/public_api.rs
|
||||
// version: 28
|
||||
// version: 29
|
||||
|
||||
//! Integration tests for the public `ksp-config-lib` bootstrap, registry, JSON/profile/composite, environment-resolution, sensitivity,
|
||||
//! Logging/Transport/Store adapters and management contracts.
|
||||
@@ -80,23 +80,24 @@ fn registry_descriptor_inventory_is_available_from_crate_root() {
|
||||
assert!(registry.is_ok(), "public registry should remain constructible: {registry:?}");
|
||||
if let std::result::Result::Ok(registry) = registry {
|
||||
let descriptors: std::vec::Vec<&ksp_config_lib::ConfigFileDescriptor> = registry.descriptors().collect();
|
||||
assert_eq!(descriptors.len(), 15);
|
||||
assert_eq!(descriptors.len(), 16);
|
||||
assert_eq!(descriptors[0].file_id().as_str(), ksp_config_lib::FILE_ID_COMPOSITE_KSP_APP_BACKFILL_DESK);
|
||||
assert_eq!(descriptors[1].file_id().as_str(), ksp_config_lib::FILE_ID_COMPOSITE_KSP_APP_SOLPRICES_DESK);
|
||||
assert_eq!(descriptors[2].file_id().as_str(), ksp_config_lib::FILE_ID_COMPOSITE_KSP_APP_STORE_DESK);
|
||||
assert_eq!(descriptors[3].file_id().as_str(), ksp_config_lib::FILE_ID_COMPOSITE_KSP_APP_WALLET_DESK);
|
||||
assert_eq!(descriptors[4].file_id().as_str(), ksp_config_lib::FILE_ID_STD_LOGGING);
|
||||
assert_eq!(descriptors[5].file_id().as_str(), ksp_config_lib::FILE_ID_STD_OFFCHAIN_TRANSPORT);
|
||||
assert_eq!(descriptors[6].file_id().as_str(), ksp_config_lib::FILE_ID_STD_STORE);
|
||||
assert_eq!(descriptors[7].file_id().as_str(), ksp_config_lib::FILE_ID_STD_TRANSPORT);
|
||||
assert_eq!(descriptors[8].file_id().as_str(), ksp_config_lib::FILE_ID_STD_WALLET);
|
||||
assert_eq!(descriptors[9].file_id().as_str(), ksp_config_lib::FILE_ID_SCHEMA_COMPOSITE);
|
||||
assert_eq!(descriptors[10].file_id().as_str(), ksp_config_lib::FILE_ID_SCHEMA_STD_LOGGING);
|
||||
assert_eq!(descriptors[11].file_id().as_str(), ksp_config_lib::FILE_ID_SCHEMA_STD_OFFCHAIN_TRANSPORT);
|
||||
assert_eq!(descriptors[12].file_id().as_str(), ksp_config_lib::FILE_ID_SCHEMA_STD_STORE);
|
||||
assert_eq!(descriptors[13].file_id().as_str(), ksp_config_lib::FILE_ID_SCHEMA_STD_TRANSPORT);
|
||||
assert_eq!(descriptors[14].file_id().as_str(), ksp_config_lib::FILE_ID_SCHEMA_STD_WALLET);
|
||||
let schema_file_id = descriptors[8].schema_file_id();
|
||||
assert_eq!(descriptors[1].file_id().as_str(), ksp_config_lib::FILE_ID_COMPOSITE_KSP_APP_RAW_TRANSACTION_INGEST_DESK);
|
||||
assert_eq!(descriptors[2].file_id().as_str(), ksp_config_lib::FILE_ID_COMPOSITE_KSP_APP_SOLPRICES_DESK);
|
||||
assert_eq!(descriptors[3].file_id().as_str(), ksp_config_lib::FILE_ID_COMPOSITE_KSP_APP_STORE_DESK);
|
||||
assert_eq!(descriptors[4].file_id().as_str(), ksp_config_lib::FILE_ID_COMPOSITE_KSP_APP_WALLET_DESK);
|
||||
assert_eq!(descriptors[5].file_id().as_str(), ksp_config_lib::FILE_ID_STD_LOGGING);
|
||||
assert_eq!(descriptors[6].file_id().as_str(), ksp_config_lib::FILE_ID_STD_OFFCHAIN_TRANSPORT);
|
||||
assert_eq!(descriptors[7].file_id().as_str(), ksp_config_lib::FILE_ID_STD_STORE);
|
||||
assert_eq!(descriptors[8].file_id().as_str(), ksp_config_lib::FILE_ID_STD_TRANSPORT);
|
||||
assert_eq!(descriptors[9].file_id().as_str(), ksp_config_lib::FILE_ID_STD_WALLET);
|
||||
assert_eq!(descriptors[10].file_id().as_str(), ksp_config_lib::FILE_ID_SCHEMA_COMPOSITE);
|
||||
assert_eq!(descriptors[11].file_id().as_str(), ksp_config_lib::FILE_ID_SCHEMA_STD_LOGGING);
|
||||
assert_eq!(descriptors[12].file_id().as_str(), ksp_config_lib::FILE_ID_SCHEMA_STD_OFFCHAIN_TRANSPORT);
|
||||
assert_eq!(descriptors[13].file_id().as_str(), ksp_config_lib::FILE_ID_SCHEMA_STD_STORE);
|
||||
assert_eq!(descriptors[14].file_id().as_str(), ksp_config_lib::FILE_ID_SCHEMA_STD_TRANSPORT);
|
||||
assert_eq!(descriptors[15].file_id().as_str(), ksp_config_lib::FILE_ID_SCHEMA_STD_WALLET);
|
||||
let schema_file_id = descriptors[9].schema_file_id();
|
||||
assert!(schema_file_id.is_some(), "public Wallet descriptor should preserve schema association");
|
||||
if let std::option::Option::Some(schema_file_id) = schema_file_id {
|
||||
assert_eq!(schema_file_id.as_str(), ksp_config_lib::FILE_ID_SCHEMA_STD_WALLET);
|
||||
@@ -167,6 +168,8 @@ fn composite_schema_and_provenance_contracts_are_available_from_crate_root() {
|
||||
}
|
||||
assert_eq!(ksp_config_lib::FILE_ID_COMPOSITE_KSP_APP_BACKFILL_DESK, "cfg.composite.ksp-app-backfill-desk");
|
||||
assert_eq!(ksp_config_lib::DEFAULT_COMPOSITE_KSP_APP_BACKFILL_DESK_FILENAME, "composite.ksp-app-backfill-desk.json");
|
||||
assert_eq!(ksp_config_lib::FILE_ID_COMPOSITE_KSP_APP_RAW_TRANSACTION_INGEST_DESK, "cfg.composite.ksp-app-raw-transaction-ingest-desk");
|
||||
assert_eq!(ksp_config_lib::DEFAULT_COMPOSITE_KSP_APP_RAW_TRANSACTION_INGEST_DESK_FILENAME, "composite.ksp-app-raw-transaction-ingest-desk.json");
|
||||
assert_eq!(ksp_config_lib::FILE_ID_COMPOSITE_KSP_APP_SOLPRICES_DESK, "cfg.composite.ksp-app-solprices-desk");
|
||||
assert_eq!(ksp_config_lib::DEFAULT_COMPOSITE_KSP_APP_SOLPRICES_DESK_FILENAME, "composite.ksp-app-solprices-desk.json");
|
||||
assert_eq!(ksp_config_lib::FILE_ID_COMPOSITE_KSP_APP_STORE_DESK, "cfg.composite.ksp-app-store-desk");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-config-lib/unit_tests/composite.rs
|
||||
// version: 4
|
||||
// version: 5
|
||||
|
||||
const TEST_COMPOSITE_FILENAME: &str = "examples/composite.example.json";
|
||||
const TEST_COMPOSITE_FILE_ID: &str = "cfg.composite.test";
|
||||
@@ -128,6 +128,71 @@ fn duplicate_component_ids_are_rejected_inside_one_composite_profile() {
|
||||
cleanup_fixture(&fixture);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn v0_3_15_pre_003_raw_ingest_composite_keeps_transport_and_store_networks_coherent() {
|
||||
let workspace = workspace_root();
|
||||
let bootstrap = crate::ConfigBootstrapOptions::from_paths(workspace.join("config"), workspace.join("config/schemas"));
|
||||
assert!(bootstrap.is_ok(), "committed Config roots should be valid: {bootstrap:?}");
|
||||
let registry = crate::ConfigFileRegistry::defaults();
|
||||
assert!(registry.is_ok(), "default Config registry should be valid: {registry:?}");
|
||||
let file_id = crate::ConfigFileId::new(crate::FILE_ID_COMPOSITE_KSP_APP_RAW_TRANSACTION_INGEST_DESK);
|
||||
assert!(file_id.is_ok(), "Raw Transaction Ingest Desk composite file_id should be valid: {file_id:?}");
|
||||
let (bootstrap, registry, file_id) = match (bootstrap, registry, file_id) {
|
||||
(std::result::Result::Ok(bootstrap), std::result::Result::Ok(registry), std::result::Result::Ok(file_id)) => (bootstrap, registry, file_id),
|
||||
_ => return,
|
||||
};
|
||||
let engine = crate::ConfigDocumentEngine::new(bootstrap, registry);
|
||||
let mut process = std::collections::BTreeMap::<String, String>::new();
|
||||
process.insert("KSP_SECRET_HELIUS_API_KEY".to_owned(), "helius-composite-canary".to_owned());
|
||||
process.insert("KSP_SECRET_ORBITFLARE_DEVNET_GRPC_X_TOKEN".to_owned(), "orbitflare-composite-canary".to_owned());
|
||||
process.insert("KSP_SECRET_PUBLICNODE_MAINNET_GRPC_X_TOKEN".to_owned(), "publicnode-mainnet-composite-canary".to_owned());
|
||||
process.insert("KSP_SECRET_PUBLICNODE_TESTNET_GRPC_X_TOKEN".to_owned(), "publicnode-testnet-composite-canary".to_owned());
|
||||
let environment = crate::ConfigEnvironment::from_maps(process, std::collections::BTreeMap::new());
|
||||
for (profile_id, expected_network) in [
|
||||
("devnet_public", "devnet"),
|
||||
("helius_devnet", "devnet"),
|
||||
("orbitflare_devnet", "devnet"),
|
||||
("mainnet_public", "mainnet"),
|
||||
("helius_mainnet", "mainnet"),
|
||||
("publicnode_mainnet", "mainnet"),
|
||||
("publicnode_testnet", "testnet"),
|
||||
] {
|
||||
let composite = engine.load_resolved_composite(&file_id, std::option::Option::Some(profile_id));
|
||||
assert!(composite.is_ok(), "Raw Ingest composite profile {profile_id} should resolve: {composite:?}");
|
||||
let composite = match composite {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => continue,
|
||||
};
|
||||
assert_eq!(composite.profile_id(), profile_id);
|
||||
let transport_component = composite.component("transport");
|
||||
let store_component = composite.component("store");
|
||||
assert!(transport_component.is_some(), "profile {profile_id} should contain Transport");
|
||||
assert!(store_component.is_some(), "profile {profile_id} should contain Store");
|
||||
let (transport_component, store_component) = match (transport_component, store_component) {
|
||||
(std::option::Option::Some(transport), std::option::Option::Some(store)) => (transport, store),
|
||||
_ => continue,
|
||||
};
|
||||
assert_eq!(transport_component.resolved().profile_id(), profile_id);
|
||||
assert_eq!(store_component.resolved().profile_id(), expected_network);
|
||||
let transport = engine.resolve_transport_config_profile(transport_component.resolved(), &environment);
|
||||
let store = engine.resolve_store_config_profile(store_component.resolved(), &environment);
|
||||
assert!(transport.is_ok(), "Transport profile {profile_id} should map: {transport:?}");
|
||||
assert!(store.is_ok(), "Store profile {expected_network} should map: {store:?}");
|
||||
let (transport, store) = match (transport, store) {
|
||||
(std::result::Result::Ok(transport), std::result::Result::Ok(store)) => (transport, store),
|
||||
_ => continue,
|
||||
};
|
||||
assert_eq!(store.settings().network().as_str(), expected_network);
|
||||
assert!(transport.http_settings().endpoints().iter().all(|endpoint| return endpoint.cluster().as_str() == expected_network));
|
||||
if let std::option::Option::Some(ws) = transport.ws_settings() {
|
||||
assert!(ws.endpoints().iter().all(|endpoint| return endpoint.cluster().as_str() == expected_network));
|
||||
}
|
||||
if let std::option::Option::Some(grpc) = transport.grpc_settings() {
|
||||
assert!(grpc.endpoints().iter().all(|endpoint| return endpoint.cluster().as_str() == expected_network));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn fixture_example_engine() -> ksp_core_lib::Result<crate::ConfigDocumentEngine> {
|
||||
let workspace = workspace_root();
|
||||
let fixture_root = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("unit_tests/fixtures");
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
{
|
||||
"format_version": 1,
|
||||
"default_profile": "devnet_public",
|
||||
"profiles": [
|
||||
{
|
||||
"profile_id": "devnet_public",
|
||||
"documents": [
|
||||
{
|
||||
"component_id": "logging",
|
||||
"file_id": "cfg.std.logging",
|
||||
"profile_id": "local_dev"
|
||||
},
|
||||
{
|
||||
"component_id": "transport",
|
||||
"file_id": "cfg.std.transport",
|
||||
"profile_id": "secret_test"
|
||||
},
|
||||
{
|
||||
"component_id": "store",
|
||||
"file_id": "cfg.std.store",
|
||||
"profile_id": "devnet"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"profile_id": "helius_devnet",
|
||||
"documents": [
|
||||
{
|
||||
"component_id": "logging",
|
||||
"file_id": "cfg.std.logging",
|
||||
"profile_id": "local_dev"
|
||||
},
|
||||
{
|
||||
"component_id": "transport",
|
||||
"file_id": "cfg.std.transport",
|
||||
"profile_id": "helius_devnet"
|
||||
},
|
||||
{
|
||||
"component_id": "store",
|
||||
"file_id": "cfg.std.store",
|
||||
"profile_id": "devnet"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"profile_id": "orbitflare_devnet",
|
||||
"documents": [
|
||||
{
|
||||
"component_id": "logging",
|
||||
"file_id": "cfg.std.logging",
|
||||
"profile_id": "local_dev"
|
||||
},
|
||||
{
|
||||
"component_id": "transport",
|
||||
"file_id": "cfg.std.transport",
|
||||
"profile_id": "secret_test"
|
||||
},
|
||||
{
|
||||
"component_id": "store",
|
||||
"file_id": "cfg.std.store",
|
||||
"profile_id": "devnet"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"profile_id": "mainnet_public",
|
||||
"documents": [
|
||||
{
|
||||
"component_id": "logging",
|
||||
"file_id": "cfg.std.logging",
|
||||
"profile_id": "local_dev"
|
||||
},
|
||||
{
|
||||
"component_id": "transport",
|
||||
"file_id": "cfg.std.transport",
|
||||
"profile_id": "secret_test"
|
||||
},
|
||||
{
|
||||
"component_id": "store",
|
||||
"file_id": "cfg.std.store",
|
||||
"profile_id": "mainnet"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"profile_id": "helius_mainnet",
|
||||
"documents": [
|
||||
{
|
||||
"component_id": "logging",
|
||||
"file_id": "cfg.std.logging",
|
||||
"profile_id": "local_dev"
|
||||
},
|
||||
{
|
||||
"component_id": "transport",
|
||||
"file_id": "cfg.std.transport",
|
||||
"profile_id": "secret_test"
|
||||
},
|
||||
{
|
||||
"component_id": "store",
|
||||
"file_id": "cfg.std.store",
|
||||
"profile_id": "mainnet"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"profile_id": "publicnode_mainnet",
|
||||
"documents": [
|
||||
{
|
||||
"component_id": "logging",
|
||||
"file_id": "cfg.std.logging",
|
||||
"profile_id": "local_dev"
|
||||
},
|
||||
{
|
||||
"component_id": "transport",
|
||||
"file_id": "cfg.std.transport",
|
||||
"profile_id": "secret_test"
|
||||
},
|
||||
{
|
||||
"component_id": "store",
|
||||
"file_id": "cfg.std.store",
|
||||
"profile_id": "mainnet"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"profile_id": "publicnode_testnet",
|
||||
"documents": [
|
||||
{
|
||||
"component_id": "logging",
|
||||
"file_id": "cfg.std.logging",
|
||||
"profile_id": "local_dev"
|
||||
},
|
||||
{
|
||||
"component_id": "transport",
|
||||
"file_id": "cfg.std.transport",
|
||||
"profile_id": "secret_test"
|
||||
},
|
||||
{
|
||||
"component_id": "store",
|
||||
"file_id": "cfg.std.store",
|
||||
"profile_id": "testnet"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -70,7 +70,15 @@
|
||||
"resubscribe": "never",
|
||||
"notification_queue_capacity": 48,
|
||||
"max_pending_requests": 24
|
||||
}
|
||||
},
|
||||
"capabilities": [
|
||||
"account",
|
||||
"logs",
|
||||
"program",
|
||||
"root",
|
||||
"signature",
|
||||
"slot"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "fixture_helius_ws",
|
||||
@@ -78,7 +86,17 @@
|
||||
"provider": "helius",
|
||||
"cluster": "mainnet",
|
||||
"kind": "helius_laserstream",
|
||||
"url": "wss://mainnet.helius-rpc.com/?api-key=${KSP_SECRET_HELIUS_API_KEY:-fixture-helius-key}"
|
||||
"url": "wss://mainnet.helius-rpc.com/?api-key=${KSP_SECRET_HELIUS_API_KEY:-fixture-helius-key}",
|
||||
"capabilities": [
|
||||
"account",
|
||||
"logs",
|
||||
"program",
|
||||
"root",
|
||||
"signature",
|
||||
"slot",
|
||||
"slots_updates",
|
||||
"helius_transaction"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -119,7 +137,17 @@
|
||||
"provider": "helius",
|
||||
"cluster": "devnet",
|
||||
"kind": "helius_laserstream",
|
||||
"url": "wss://devnet.helius-rpc.com/?api-key=${KSP_SECRET_HELIUS_API_KEY:-fixture-helius-key}"
|
||||
"url": "wss://devnet.helius-rpc.com/?api-key=${KSP_SECRET_HELIUS_API_KEY:-fixture-helius-key}",
|
||||
"capabilities": [
|
||||
"account",
|
||||
"logs",
|
||||
"program",
|
||||
"root",
|
||||
"signature",
|
||||
"slot",
|
||||
"slots_updates",
|
||||
"helius_transaction"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-config-lib/unit_tests/registry.rs
|
||||
// version: 13
|
||||
// version: 14
|
||||
|
||||
#[test]
|
||||
fn descriptors_expose_complete_registry_in_deterministic_file_id_order() {
|
||||
@@ -7,30 +7,33 @@ fn descriptors_expose_complete_registry_in_deterministic_file_id_order() {
|
||||
assert!(registry.is_ok(), "default registry should be valid: {registry:?}");
|
||||
if let std::result::Result::Ok(registry) = registry {
|
||||
let descriptors: std::vec::Vec<&crate::ConfigFileDescriptor> = registry.descriptors().collect();
|
||||
assert_eq!(descriptors.len(), 15);
|
||||
assert_eq!(descriptors.len(), 16);
|
||||
assert_eq!(descriptors[0].file_id().as_str(), crate::FILE_ID_COMPOSITE_KSP_APP_BACKFILL_DESK);
|
||||
assert_eq!(descriptors[0].filename(), std::path::Path::new(crate::DEFAULT_COMPOSITE_KSP_APP_BACKFILL_DESK_FILENAME));
|
||||
assert_eq!(descriptors[0].schema_file_id().map(crate::ConfigFileId::as_str), std::option::Option::Some(crate::FILE_ID_SCHEMA_COMPOSITE));
|
||||
assert_eq!(descriptors[1].file_id().as_str(), crate::FILE_ID_COMPOSITE_KSP_APP_SOLPRICES_DESK);
|
||||
assert_eq!(descriptors[2].file_id().as_str(), crate::FILE_ID_COMPOSITE_KSP_APP_STORE_DESK);
|
||||
assert_eq!(descriptors[2].filename(), std::path::Path::new(crate::DEFAULT_COMPOSITE_KSP_APP_STORE_DESK_FILENAME));
|
||||
assert_eq!(descriptors[2].schema_file_id().map(crate::ConfigFileId::as_str), std::option::Option::Some(crate::FILE_ID_SCHEMA_COMPOSITE));
|
||||
assert_eq!(descriptors[3].file_id().as_str(), crate::FILE_ID_COMPOSITE_KSP_APP_WALLET_DESK);
|
||||
assert_eq!(descriptors[4].file_id().as_str(), crate::FILE_ID_STD_LOGGING);
|
||||
assert_eq!(descriptors[5].file_id().as_str(), crate::FILE_ID_STD_OFFCHAIN_TRANSPORT);
|
||||
assert_eq!(descriptors[6].file_id().as_str(), crate::FILE_ID_STD_STORE);
|
||||
assert_eq!(descriptors[7].file_id().as_str(), crate::FILE_ID_STD_TRANSPORT);
|
||||
assert_eq!(descriptors[8].file_id().as_str(), crate::FILE_ID_STD_WALLET);
|
||||
assert_eq!(descriptors[8].filename(), std::path::Path::new(crate::DEFAULT_STD_WALLET_FILENAME));
|
||||
assert_eq!(descriptors[8].schema_file_id().map(crate::ConfigFileId::as_str), std::option::Option::Some(crate::FILE_ID_SCHEMA_STD_WALLET));
|
||||
assert_eq!(descriptors[9].file_id().as_str(), crate::FILE_ID_SCHEMA_COMPOSITE);
|
||||
assert_eq!(descriptors[10].file_id().as_str(), crate::FILE_ID_SCHEMA_STD_LOGGING);
|
||||
assert_eq!(descriptors[11].file_id().as_str(), crate::FILE_ID_SCHEMA_STD_OFFCHAIN_TRANSPORT);
|
||||
assert_eq!(descriptors[12].file_id().as_str(), crate::FILE_ID_SCHEMA_STD_STORE);
|
||||
assert_eq!(descriptors[13].file_id().as_str(), crate::FILE_ID_SCHEMA_STD_TRANSPORT);
|
||||
assert_eq!(descriptors[14].file_id().as_str(), crate::FILE_ID_SCHEMA_STD_WALLET);
|
||||
assert!(descriptors[0..9].iter().all(|descriptor| return descriptor.kind() == crate::ConfigFileKind::Config));
|
||||
assert!(descriptors[9..15].iter().all(|descriptor| return descriptor.kind() == crate::ConfigFileKind::Schema));
|
||||
assert_eq!(descriptors[1].file_id().as_str(), crate::FILE_ID_COMPOSITE_KSP_APP_RAW_TRANSACTION_INGEST_DESK);
|
||||
assert_eq!(descriptors[1].filename(), std::path::Path::new(crate::DEFAULT_COMPOSITE_KSP_APP_RAW_TRANSACTION_INGEST_DESK_FILENAME));
|
||||
assert_eq!(descriptors[1].schema_file_id().map(crate::ConfigFileId::as_str), std::option::Option::Some(crate::FILE_ID_SCHEMA_COMPOSITE));
|
||||
assert_eq!(descriptors[2].file_id().as_str(), crate::FILE_ID_COMPOSITE_KSP_APP_SOLPRICES_DESK);
|
||||
assert_eq!(descriptors[3].file_id().as_str(), crate::FILE_ID_COMPOSITE_KSP_APP_STORE_DESK);
|
||||
assert_eq!(descriptors[3].filename(), std::path::Path::new(crate::DEFAULT_COMPOSITE_KSP_APP_STORE_DESK_FILENAME));
|
||||
assert_eq!(descriptors[3].schema_file_id().map(crate::ConfigFileId::as_str), std::option::Option::Some(crate::FILE_ID_SCHEMA_COMPOSITE));
|
||||
assert_eq!(descriptors[4].file_id().as_str(), crate::FILE_ID_COMPOSITE_KSP_APP_WALLET_DESK);
|
||||
assert_eq!(descriptors[5].file_id().as_str(), crate::FILE_ID_STD_LOGGING);
|
||||
assert_eq!(descriptors[6].file_id().as_str(), crate::FILE_ID_STD_OFFCHAIN_TRANSPORT);
|
||||
assert_eq!(descriptors[7].file_id().as_str(), crate::FILE_ID_STD_STORE);
|
||||
assert_eq!(descriptors[8].file_id().as_str(), crate::FILE_ID_STD_TRANSPORT);
|
||||
assert_eq!(descriptors[9].file_id().as_str(), crate::FILE_ID_STD_WALLET);
|
||||
assert_eq!(descriptors[9].filename(), std::path::Path::new(crate::DEFAULT_STD_WALLET_FILENAME));
|
||||
assert_eq!(descriptors[9].schema_file_id().map(crate::ConfigFileId::as_str), std::option::Option::Some(crate::FILE_ID_SCHEMA_STD_WALLET));
|
||||
assert_eq!(descriptors[10].file_id().as_str(), crate::FILE_ID_SCHEMA_COMPOSITE);
|
||||
assert_eq!(descriptors[11].file_id().as_str(), crate::FILE_ID_SCHEMA_STD_LOGGING);
|
||||
assert_eq!(descriptors[12].file_id().as_str(), crate::FILE_ID_SCHEMA_STD_OFFCHAIN_TRANSPORT);
|
||||
assert_eq!(descriptors[13].file_id().as_str(), crate::FILE_ID_SCHEMA_STD_STORE);
|
||||
assert_eq!(descriptors[14].file_id().as_str(), crate::FILE_ID_SCHEMA_STD_TRANSPORT);
|
||||
assert_eq!(descriptors[15].file_id().as_str(), crate::FILE_ID_SCHEMA_STD_WALLET);
|
||||
assert!(descriptors[0..10].iter().all(|descriptor| return descriptor.kind() == crate::ConfigFileKind::Config));
|
||||
assert!(descriptors[10..16].iter().all(|descriptor| return descriptor.kind() == crate::ConfigFileKind::Schema));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,16 +368,18 @@ fn absolute_fixture_path() -> std::path::PathBuf {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn defaults_register_generic_composite_schema_and_four_runtime_composites() {
|
||||
fn defaults_register_generic_composite_schema_and_five_runtime_composites() {
|
||||
let registry = crate::ConfigFileRegistry::defaults();
|
||||
let schema_id = crate::ConfigFileId::new(crate::FILE_ID_SCHEMA_COMPOSITE);
|
||||
let backfill_id = crate::ConfigFileId::new(crate::FILE_ID_COMPOSITE_KSP_APP_BACKFILL_DESK);
|
||||
let raw_ingest_id = crate::ConfigFileId::new(crate::FILE_ID_COMPOSITE_KSP_APP_RAW_TRANSACTION_INGEST_DESK);
|
||||
let solprices_id = crate::ConfigFileId::new(crate::FILE_ID_COMPOSITE_KSP_APP_SOLPRICES_DESK);
|
||||
let store_desk_id = crate::ConfigFileId::new(crate::FILE_ID_COMPOSITE_KSP_APP_STORE_DESK);
|
||||
let wallet_id = crate::ConfigFileId::new(crate::FILE_ID_COMPOSITE_KSP_APP_WALLET_DESK);
|
||||
assert!(registry.is_ok(), "default registry should be valid: {registry:?}");
|
||||
assert!(schema_id.is_ok(), "composite schema file_id should be valid: {schema_id:?}");
|
||||
assert!(backfill_id.is_ok(), "Backfill Desk composite runtime file_id should be valid: {backfill_id:?}");
|
||||
assert!(raw_ingest_id.is_ok(), "Raw Transaction Ingest Desk composite runtime file_id should be valid: {raw_ingest_id:?}");
|
||||
assert!(solprices_id.is_ok(), "SOL Prices Desk composite runtime file_id should be valid: {solprices_id:?}");
|
||||
assert!(store_desk_id.is_ok(), "Store Desk composite runtime file_id should be valid: {store_desk_id:?}");
|
||||
assert!(wallet_id.is_ok(), "Wallet Desk composite runtime file_id should be valid: {wallet_id:?}");
|
||||
@@ -382,34 +387,41 @@ fn defaults_register_generic_composite_schema_and_four_runtime_composites() {
|
||||
std::result::Result::Ok(registry),
|
||||
std::result::Result::Ok(schema_id),
|
||||
std::result::Result::Ok(backfill_id),
|
||||
std::result::Result::Ok(raw_ingest_id),
|
||||
std::result::Result::Ok(solprices_id),
|
||||
std::result::Result::Ok(store_desk_id),
|
||||
std::result::Result::Ok(wallet_id),
|
||||
) = (registry, schema_id, backfill_id, solprices_id, store_desk_id, wallet_id)
|
||||
) = (registry, schema_id, backfill_id, raw_ingest_id, solprices_id, store_desk_id, wallet_id)
|
||||
{
|
||||
let schema = registry.descriptor(&schema_id);
|
||||
let backfill = registry.descriptor(&backfill_id);
|
||||
let raw_ingest = registry.descriptor(&raw_ingest_id);
|
||||
let solprices = registry.descriptor(&solprices_id);
|
||||
let store_desk = registry.descriptor(&store_desk_id);
|
||||
let wallet = registry.descriptor(&wallet_id);
|
||||
assert!(schema.is_ok(), "generic composite schema should be registered: {schema:?}");
|
||||
assert!(backfill.is_ok(), "Backfill Desk runtime composite should be registered: {backfill:?}");
|
||||
assert!(raw_ingest.is_ok(), "Raw Transaction Ingest Desk runtime composite should be registered: {raw_ingest:?}");
|
||||
assert!(solprices.is_ok(), "SOL Prices Desk runtime composite should be registered: {solprices:?}");
|
||||
assert!(store_desk.is_ok(), "Store Desk runtime composite should be registered: {store_desk:?}");
|
||||
assert!(wallet.is_ok(), "Wallet Desk runtime composite should be registered: {wallet:?}");
|
||||
if let (
|
||||
std::result::Result::Ok(schema),
|
||||
std::result::Result::Ok(backfill),
|
||||
std::result::Result::Ok(raw_ingest),
|
||||
std::result::Result::Ok(solprices),
|
||||
std::result::Result::Ok(store_desk),
|
||||
std::result::Result::Ok(wallet),
|
||||
) = (schema, backfill, solprices, store_desk, wallet)
|
||||
) = (schema, backfill, raw_ingest, solprices, store_desk, wallet)
|
||||
{
|
||||
assert_eq!(schema.kind(), crate::ConfigFileKind::Schema);
|
||||
assert_eq!(schema.filename(), std::path::Path::new(crate::DEFAULT_COMPOSITE_SCHEMA_FILENAME));
|
||||
assert_eq!(backfill.kind(), crate::ConfigFileKind::Config);
|
||||
assert_eq!(backfill.filename(), std::path::Path::new(crate::DEFAULT_COMPOSITE_KSP_APP_BACKFILL_DESK_FILENAME));
|
||||
assert_eq!(backfill.schema_file_id(), std::option::Option::Some(&schema_id));
|
||||
assert_eq!(raw_ingest.kind(), crate::ConfigFileKind::Config);
|
||||
assert_eq!(raw_ingest.filename(), std::path::Path::new(crate::DEFAULT_COMPOSITE_KSP_APP_RAW_TRANSACTION_INGEST_DESK_FILENAME));
|
||||
assert_eq!(raw_ingest.schema_file_id(), std::option::Option::Some(&schema_id));
|
||||
assert_eq!(solprices.kind(), crate::ConfigFileKind::Config);
|
||||
assert_eq!(solprices.filename(), std::path::Path::new(crate::DEFAULT_COMPOSITE_KSP_APP_SOLPRICES_DESK_FILENAME));
|
||||
assert_eq!(solprices.schema_file_id(), std::option::Option::Some(&schema_id));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-config-lib/unit_tests/transport.rs
|
||||
// version: 13
|
||||
// version: 14
|
||||
|
||||
#[test]
|
||||
fn fixture_transport_profile_maps_complete_runtime_contract() {
|
||||
@@ -51,6 +51,19 @@ fn fixture_transport_profile_maps_complete_runtime_contract() {
|
||||
assert_eq!(endpoint.provider().as_str(), "fixture-provider");
|
||||
assert_eq!(endpoint.cluster().as_str(), "fixture-cluster");
|
||||
assert_eq!(endpoint.protocol(), ksp_onchain_transport_lib::WsProtocolKind::SolanaStandard);
|
||||
assert_eq!(
|
||||
endpoint.subscription_capabilities(),
|
||||
std::option::Option::Some(
|
||||
&[
|
||||
ksp_onchain_transport_lib::WsSubscriptionKind::Account,
|
||||
ksp_onchain_transport_lib::WsSubscriptionKind::Logs,
|
||||
ksp_onchain_transport_lib::WsSubscriptionKind::Program,
|
||||
ksp_onchain_transport_lib::WsSubscriptionKind::Root,
|
||||
ksp_onchain_transport_lib::WsSubscriptionKind::Signature,
|
||||
ksp_onchain_transport_lib::WsSubscriptionKind::Slot,
|
||||
][..],
|
||||
)
|
||||
);
|
||||
assert_eq!(endpoint.url().as_str(), "wss://fallback.invalid");
|
||||
assert_eq!(endpoint.session().command_timeout(), std::time::Duration::from_millis(4500));
|
||||
assert_eq!(endpoint.session().close_timeout(), std::time::Duration::from_millis(4000));
|
||||
@@ -70,6 +83,21 @@ fn fixture_transport_profile_maps_complete_runtime_contract() {
|
||||
assert_eq!(helius.provider().as_str(), "helius");
|
||||
assert_eq!(helius.cluster().as_str(), "mainnet");
|
||||
assert_eq!(helius.protocol(), ksp_onchain_transport_lib::WsProtocolKind::HeliusLaserStream);
|
||||
assert_eq!(
|
||||
helius.subscription_capabilities(),
|
||||
std::option::Option::Some(
|
||||
&[
|
||||
ksp_onchain_transport_lib::WsSubscriptionKind::Account,
|
||||
ksp_onchain_transport_lib::WsSubscriptionKind::Logs,
|
||||
ksp_onchain_transport_lib::WsSubscriptionKind::Program,
|
||||
ksp_onchain_transport_lib::WsSubscriptionKind::Root,
|
||||
ksp_onchain_transport_lib::WsSubscriptionKind::Signature,
|
||||
ksp_onchain_transport_lib::WsSubscriptionKind::Slot,
|
||||
ksp_onchain_transport_lib::WsSubscriptionKind::SlotsUpdates,
|
||||
ksp_onchain_transport_lib::WsSubscriptionKind::HeliusTransaction,
|
||||
][..],
|
||||
)
|
||||
);
|
||||
assert_eq!(helius.url().as_str(), "wss://mainnet.helius-rpc.com/?api-key=fixture-helius-key");
|
||||
let _connect_future = ksp_onchain_transport_lib::HeliusLaserStreamWsSession::connect(helius.clone());
|
||||
}
|
||||
@@ -117,6 +145,8 @@ fn committed_transport_document_maps_default_and_explicit_profiles() {
|
||||
if let std::option::Option::Some(ws) = ws {
|
||||
assert_eq!(ws.endpoints()[0].url().as_str(), "wss://api.devnet.solana.com");
|
||||
assert_eq!(ws.endpoints()[0].protocol(), ksp_onchain_transport_lib::WsProtocolKind::SolanaStandard);
|
||||
assert!(ws.endpoints()[0].supports_subscription(ksp_onchain_transport_lib::WsSubscriptionKind::Logs));
|
||||
assert!(!ws.endpoints()[0].supports_subscription(ksp_onchain_transport_lib::WsSubscriptionKind::Block));
|
||||
}
|
||||
}
|
||||
if let std::result::Result::Ok(mainnet) = mainnet {
|
||||
@@ -129,6 +159,8 @@ fn committed_transport_document_maps_default_and_explicit_profiles() {
|
||||
assert!(ws.is_some(), "committed V3 Mainnet profile should expose WebSocket settings");
|
||||
if let std::option::Option::Some(ws) = ws {
|
||||
assert_eq!(ws.endpoints()[0].url().as_str(), "wss://api.mainnet.solana.com");
|
||||
assert!(ws.endpoints()[0].supports_subscription(ksp_onchain_transport_lib::WsSubscriptionKind::Logs));
|
||||
assert!(!ws.endpoints()[0].supports_subscription(ksp_onchain_transport_lib::WsSubscriptionKind::Block));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -529,6 +561,47 @@ fn helius_laserstream_mainnet_and_devnet_api_key_map_to_protocol_and_safe_redact
|
||||
assert!(devnet_debug.contains(crate::REDACTED_CONFIG_VALUE));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn v0_3_15_pre_003_committed_helius_profiles_map_transaction_capability_without_block_or_vote() {
|
||||
let engine = committed_engine();
|
||||
let engine = match engine {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => return,
|
||||
};
|
||||
let canary = "helius-pre-003-api-key-canary";
|
||||
let mut process = std::collections::BTreeMap::<String, String>::new();
|
||||
process.insert("KSP_SECRET_HELIUS_API_KEY".to_owned(), canary.to_owned());
|
||||
let environment = crate::ConfigEnvironment::from_maps(process, std::collections::BTreeMap::new());
|
||||
for (profile_id, cluster, expected_url) in [
|
||||
("helius_devnet", "devnet", "wss://devnet.helius-rpc.com/?api-key=helius-pre-003-api-key-canary"),
|
||||
("helius_mainnet", "mainnet", "wss://mainnet.helius-rpc.com/?api-key=helius-pre-003-api-key-canary"),
|
||||
] {
|
||||
let resolved = engine.load_resolved_transport_config(std::option::Option::Some(profile_id), &environment);
|
||||
assert!(resolved.is_ok(), "committed Helius profile {profile_id} should resolve: {resolved:?}");
|
||||
let resolved = match resolved {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(_) => continue,
|
||||
};
|
||||
assert_eq!(resolved.http_settings().endpoints()[0].cluster().as_str(), cluster);
|
||||
let ws = resolved.ws_settings();
|
||||
assert!(ws.is_some(), "committed Helius profile {profile_id} should expose WebSocket settings");
|
||||
if let std::option::Option::Some(ws) = ws {
|
||||
assert_eq!(ws.endpoints().len(), 1);
|
||||
let endpoint = &ws.endpoints()[0];
|
||||
assert_eq!(endpoint.provider().as_str(), "helius");
|
||||
assert_eq!(endpoint.cluster().as_str(), cluster);
|
||||
assert_eq!(endpoint.protocol(), ksp_onchain_transport_lib::WsProtocolKind::HeliusLaserStream);
|
||||
assert_eq!(endpoint.url().as_str(), expected_url);
|
||||
assert!(endpoint.supports_subscription(ksp_onchain_transport_lib::WsSubscriptionKind::Logs));
|
||||
assert!(endpoint.supports_subscription(ksp_onchain_transport_lib::WsSubscriptionKind::HeliusTransaction));
|
||||
assert!(!endpoint.supports_subscription(ksp_onchain_transport_lib::WsSubscriptionKind::Block));
|
||||
assert!(!endpoint.supports_subscription(ksp_onchain_transport_lib::WsSubscriptionKind::Vote));
|
||||
}
|
||||
let debug = format!("{resolved:?}");
|
||||
assert!(!debug.contains(canary));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transport_secret_url_provenance_uses_process_and_process_beats_dotenv() {
|
||||
let engine = fixture_engine();
|
||||
|
||||
Reference in New Issue
Block a user