Architekturübersicht
Kora verwendet die externe
solana-keychain Crate
für alle Signierungsvorgänge. Diese Architektur bietet eine einheitliche
Signierungsschnittstelle zum Signieren von Solana-Transaktionen. Um einen neuen
Signer zu Kora hinzuzufügen, müssen Sie:
- Zuerst: Ihre Signer-Implementierung zur
solana-keychainCrate hinzufügen - Zweitens: Konfigurationsunterstützung für Ihren Signer in Kora hinzufügen
Schritt-für-Schritt-Integrationsleitfaden
Schnelle Integrations-Checkliste
Teil 1: Signer zur solana-keychain Crate hinzufügen
- Implementieren Sie Ihren Signer gemäß dem solana-keychain Integrationsleitfaden
- Warten Sie auf die PR-Genehmigung und Veröffentlichung der Crate
Teil 2: Kora-Konfigurationsunterstützung hinzufügen
- Aktualisieren Sie die Abhängigkeit in Cargo.toml, sodass die
solana-keychainCrate die neueste Version verwendet (die Ihren Signer enthält) - Fügen Sie eine Konfigurationsstruktur für die Umgebungsvariablen Ihres Signers hinzu
- Aktualisieren Sie das
SignerTypeConfigEnum incrates/lib/src/signer/config.rs - Fügen Sie Validierungslogik für die Konfiguration Ihres Signers hinzu
- Fügen Sie Build-Logik hinzu, um Ihren Signer aus der Konfiguration zu erstellen
- Exportieren Sie die Konfigurationsstruktur in
crates/lib/src/signer/mod.rs - (Optional) Fügen Sie einen Test-Mock-Builder in
crates/lib/src/tests/config_mock.rshinzu - Aktualisieren Sie die Beispielkonfigurationsdateien
- Aktualisieren Sie die Testskripte, um Ihren Signer einzuschließen (siehe unten)
- Aktualisieren Sie die Dokumentation, um Ihren Signer einzuschließen (siehe unten)
- Reichen Sie einen PR im Kora-Repository ein
Signer-Unterstützung in Kora hinzufügen
Stellen Sie zunächst sicher, dass Ihr Signer im solana-keychain-Crate
unterstützt wird. Falls nicht, folgen Sie der Anleitung unter:
https://github.com/solana-foundation/solana-keychain/blob/main/docs/ADDING_SIGNERS.md
Schritt 1: Cargo.toml aktualisieren
Aktualisieren Sie die Abhängigkeit in Cargo.toml, damit das
solana-keychain-Crate die neueste Version (die Ihren Signer enthält)
verwendet:
[dependencies]solana-keychain = { version = "X.Y.Z", default-features = false, features = ["all","sdk-v3",] }
Schritt 2: Definieren Sie Ihre Konfigurationsstruktur
Fügen Sie in crates/lib/src/signer/config.rs eine neue Konfigurationsstruktur
für Ihren Signer hinzu, die festlegt, welche Umgebungsvariablen benötigt werden.
Zum Beispiel:
/// YourService signer configuration#[derive(Clone, Serialize, Deserialize)]pub struct YourServiceSignerConfig {pub api_key_env: String,pub api_secret_env: String,pub wallet_id_env: String,}
Schritt 2: Fügen Sie Ihren Signer zum SignerTypeConfig-Enum hinzu
Fügen Sie Ihre Signer-Variante zum SignerTypeConfig-Enum in
crates/lib/src/signer/config.rs hinzu:
/// Signer type-specific configuration#[derive(Clone, Serialize, Deserialize)]#[serde(tag = "type", rename_all = "snake_case")]pub enum SignerTypeConfig {// Existing signer variantsMemory { #[serde(flatten)] config: MemorySignerConfig },// ... existing variants ...// Add your signer hereYourService {#[serde(flatten)]config: YourServiceSignerConfig,},}
Schritt 3: Build-Logik hinzufügen
Fügen Sie in derselben Datei (config.rs) eine Methode hinzu, um Ihren Signer
aus der Konfiguration in der SignerConfig-Implementierung zu erstellen:
impl SignerConfig {pub async fn build_signer_from_config(config: &SignerConfig) -> Result<Signer, KoraError> {match &config.config {// ... existing casesSignerTypeConfig::YourService { config: your_service_config } => {Self::build_your_service_signer(your_service_config, &config.name).await}}}// Add this new methodasync fn build_your_service_signer(config: &YourServiceSignerConfig,signer_name: &str,) -> Result<Signer, KoraError> {// Update the environment variable names to match your signer's configurationlet api_key = get_env_var_for_signer(&config.api_key_env, signer_name)?;let api_secret = get_env_var_for_signer(&config.api_secret_env, signer_name)?;let wallet_id = get_env_var_for_signer(&config.wallet_id_env, signer_name)?;// Call the constructor from solana-keychain crateSigner::from_your_service(api_key, api_secret, wallet_id).await.map_err(|e| {KoraError::SigningError(format!("Failed to create YourService signer '{signer_name}': {}",sanitize_error!(e)))})}}
Hinweis: Der Methodenname Signer::from_your_service() sollte mit dem
übereinstimmen, was Sie im solana-keychain-Crate implementiert haben.
Schritt 4: Validierungslogik hinzufügen
Fügen Sie eine Validierung für die Konfiguration Ihres Signers in der
validate_individual_signer_config-Methode hinzu:
impl SignerConfig {pub fn validate_individual_signer_config(&self, index: usize) -> Result<(), KoraError> {// ... existing validationmatch &self.config {// ... existing casesSignerTypeConfig::YourService { config } => {Self::validate_your_service_config(config, &self.name)}}}// Add this new validation methodfn validate_your_service_config(config: &YourServiceSignerConfig,signer_name: &str,) -> Result<(), KoraError> {// Update the environment variable names to match your signer's configurationlet env_vars = [("api_key_env", &config.api_key_env),("api_secret_env", &config.api_secret_env),("wallet_id_env", &config.wallet_id_env),];for (field_name, env_var) in env_vars {if env_var.is_empty() {return Err(KoraError::ValidationError(format!("YourService signer '{signer_name}' must specify non-empty {field_name}")));}}Ok(())}}
Schritt 5: Exportieren Sie Ihre Konfiguration
Fügen Sie Ihre neue Konfigurationsstruktur zu den Modulexporten in
crates/lib/src/signer/mod.rs hinzu (oder am Anfang der Datei, falls sie
öffentlich ist):
pub use config::{MemorySignerConfig,PrivySignerConfig,SignerTypeConfig,TurnkeySignerConfig,VaultSignerConfig,YourServiceSignerConfig, // Add this// ... other exports};
Testen Ihrer Integration
Test-Mock-Builder hinzufügen
Um das Testen zu erleichtern, fügen Sie eine Builder-Methode zu
SignerPoolConfigBuilder in crates/lib/src/tests/config_mock.rs hinzu:
impl SignerPoolConfigBuilder {// ... existing methodspub fn with_your_service_signer(mut self,name: String,api_key_env: String,api_secret_env: String,wallet_id_env: String,weight: Option<u32>,) -> Self {let signer = SignerConfig {name,weight,config: SignerTypeConfig::YourService {config: YourServiceSignerConfig {api_key_env,api_secret_env,wallet_id_env,},},};self.config.signers.push(signer);self}}
Dies ermöglicht es anderen Tests, einfach Mock-Konfigurationen zu erstellen, die Ihren Signer enthalten:
use crate::tests::config_mock::SignerPoolConfigBuilder;let config = SignerPoolConfigBuilder::new().with_your_service_signer("yourservice_test".to_string(),"YOUR_SERVICE_API_KEY".to_string(),"YOUR_SERVICE_API_SECRET".to_string(),"YOUR_SERVICE_WALLET_ID".to_string(),Some(1)).build();
Umgebungsvariablen
Fügen Sie die Beispiel-Umgebungsvariablen zu den folgenden Dateien hinzu:
.env.example(Stammverzeichnis des Projekts).env(Stammverzeichnis des Projekts, für lokale Tests)./sdks/ts/.env.example./sdks/ts/.env
# YourService Signer ConfigurationYOUR_SERVICE_API_KEY=your_api_key_hereYOUR_SERVICE_API_SECRET=your_api_secret_hereYOUR_SERVICE_WALLET_ID=your_wallet_id_here
Integrationstests
Jede Integrationsphase ist ein eigenes [[test]]-Target in tests/Cargo.toml. Jedes
Target startet über harness_context ein eingebettetes Surfnet sowie einen Kora-Node,
jeweils von Grund auf neu initialisiert. Kora hält die Konfiguration in einem
prozessglobalen Zustand, daher benötigt ein neuer Signer ein neues Target statt eines
neuen Moduls in einem bestehenden.
1. Signer-Fixture hinzufügen
Erstellen Sie eine Signer-Konfiguration in tests/src/common/fixtures/:
# tests/src/common/fixtures/signers-your-service.toml[signer_pool]strategy = "round_robin"[[signers]]name = "yourservice_main"type = "your_service"api_key_env = "YOUR_SERVICE_API_KEY"api_secret_env = "YOUR_SERVICE_API_SECRET"wallet_id_env = "YOUR_SERVICE_WALLET_ID"
2. Test-Target hinzufügen
Registrieren Sie die Phase in tests/Cargo.toml:
[[test]]name = "your_service"path = "your_service/main.rs"
Erstellen Sie anschließend tests/your_service/main.rs. Diese Datei verweist das Harness
auf Ihre Fixture und muss mindestens einen #[tokio::test] enthalten, der den Signer
testet:
#[path = "../src/common/mod.rs"]mod common;use common::*;use jsonrpsee::rpc_params;pub async fn ctx() -> TestContext {harness_context(KoraSpec {config: "tests/src/common/fixtures/kora-test.toml",signers: "tests/src/common/fixtures/signers-your-service.toml",initialize_payments_atas: false,}).await}#[tokio::test]async fn test_your_service_signs_as_fee_payer() {let ctx = ctx().await;let response: serde_json::Value = ctx.rpc_call("getPayerSigner", rpc_params![]).await.expect("Failed to get payer signer");response.assert_success();assert!(response["signer_address"].as_str().is_some());}
Fügen Sie außerdem einen signTransaction-Test hinzu, damit der Signiervorgang des
Signers ausgeführt wird und nicht nur die Schlüsselsuche. tests/multi_signer/ ist ein
vollständiges Beispiel zum Kopieren.
3. Tests ausführen
just installexport YOUR_SERVICE_API_KEY="your_key"export YOUR_SERVICE_API_SECRET="your_secret"export YOUR_SERVICE_WALLET_ID="your_wallet"# Run only your phasecargo test -p tests --test your_service# Run every integration phasejust integration-test
Dokumentationsanforderungen
Fügen Sie bei der Einreichung Ihres PRs Folgendes hinzu:
1. Aktualisieren Sie den Signer-Leitfaden
Fügen Sie Signer-Dokumentation gemäß dem
ADDING_SIGNERS.md-Leitfaden
hinzu, in dem die Voraussetzungen, die Einrichtung und die Verwendung erklärt
werden.
## YourService Signer[YourService](https://yourservice.com) provides [brief description of yourservice].### Prerequisites- YourService account- API credentials- Funded wallet### Setup1. Get your API credentials from [dashboard link]2. Create a wallet...3. Configure environment variables:\```bash YOUR_SERVICE_API_KEY="your_api_key"YOUR_SERVICE_API_SECRET="your_api_secret"YOUR_SERVICE_WALLET_ID="your_wallet_id" \```### Configure signers.toml\```toml [signer_pool] strategy = "round_robin"[[signers]] name = "yourservice_main" type = "your_service" api_key_env ="YOUR_SERVICE_API_KEY" api_secret_env = "YOUR_SERVICE_API_SECRET" wallet_id_env= "YOUR_SERVICE_WALLET_ID" weight = 1 \```### Run Kora with YourService Signer\```bash kora rpc start --signers-config signers.toml \```
2. README aktualisieren
Fügen Sie Ihren Dienst zur Signer-Liste in der Haupt-README hinzu.
Einreichungs-Checkliste
- Ihr Signer wird im
solana-keychain-Crate unterstützt -
solana-keychain-Abhängigkeit in Cargo.toml auf die neueste Version aktualisiert - Konfigurationsstruktur für Ihren Signer hinzugefügt
-
SignerTypeConfig-Variante hinzugefügt - Build-Logik in
build_signer_from_confighinzugefügt - Validierungslogik in
validate_individual_signer_confighinzugefügt - Konfigurationsstruktur in
mod.rsexportiert - (Optional) Test-Mock-Builder-Methode in
config_mock.rshinzugefügt - Code kompiliert ohne Warnungen
- Alle Tests bestehen (
just test) - Dokumentation gemäß
ADDING_SIGNERS.mdhinzugefügt - Beispiel-Konfigurationsdateien erstellt (
.tomlund.env.example) - Keine hartcodierten Werte oder Geheimnisse
- Fehlermeldungen sind hilfreich
- Folgt den Rust-Namenskonventionen (snake_case)
- Linting besteht (
make lint) - Kontaktieren Sie das Kora-Team mit API-Schlüsseln für Integrationstests
Hilfe erhalten
- Zur Signer-Implementierung: Öffnen Sie ein Issue im
solana-keychain-Repository - Zur Kora-Integration: Öffnen Sie ein Issue im Kora-Repository für Design-Diskussionen
- Treten Sie unseren Community-Kanälen bei
- Überprüfen Sie bestehende Signer-Konfigurationen in
crates/lib/src/signer/config.rs
Beispiel-PR-Struktur
Für das Kora-Repository:
feat(signer): add YourService signer configuration support- Add YourServiceSignerConfig struct- Add YourService variant to SignerTypeConfig enum- Add build and validation logic for YourService- Add example configuration files- Add documentation to SIGNERS.md- Add integration tests
Willkommen im Kora-Ökosystem! Wir freuen uns, Ihre Schlüsselverwaltungslösung als Teil der Plattform begrüßen zu dürfen.
Is this page helpful?