Aperçu de l'architecture
Kora utilise la crate externe
solana-keychain pour
toutes les opérations de signature. Cette architecture fournit une interface de
signature unifiée pour signer les transactions Solana. Pour ajouter un nouveau
signataire à Kora, vous devrez :
- Premièrement : Ajouter votre implémentation de signataire à la crate
solana-keychain - Deuxièmement : Ajouter la prise en charge de la configuration pour votre signataire dans Kora
Guide d'intégration étape par étape
Liste de contrôle d'intégration rapide
Partie 1 : Ajouter le signataire à la crate solana-keychain
- Implémentez votre signataire en suivant le guide d'intégration solana-keychain
- Attendez l'approbation de la PR et la publication de la crate
Partie 2 : Ajouter la prise en charge de la configuration Kora
- Mettez à jour la dépendance dans Cargo.toml afin que la crate
solana-keychainutilise la dernière version (qui inclut votre signataire) - Ajoutez une structure de configuration pour les variables d'environnement de votre signataire
- Mettez à jour l'énumération
SignerTypeConfigdanscrates/lib/src/signer/config.rs - Ajoutez la logique de validation pour la configuration de votre signataire
- Ajoutez la logique de construction pour créer votre signataire à partir de la configuration
- Exportez la structure de configuration dans
crates/lib/src/signer/mod.rs - (Optionnel) Ajoutez un constructeur de mock de test dans
crates/lib/src/tests/config_mock.rs - Mettez à jour les fichiers de configuration d'exemple
- Mettez à jour les scripts de test pour inclure votre signataire (voir ci-dessous)
- Mettez à jour la documentation pour inclure votre signataire (voir ci-dessous)
- Soumettez une PR au dépôt Kora
Ajouter la prise en charge du signataire dans Kora
Tout d'abord, assurez-vous que votre signataire est pris en charge dans la crate
solana-keychain. S'il ne l'est pas, suivez le guide à l'adresse :
https://github.com/solana-foundation/solana-keychain/blob/main/docs/ADDING_SIGNERS.md
Étape 1 : Mettre à jour Cargo.toml
Mettez à jour la dépendance de Cargo.toml afin que la crate solana-keychain
utilise la dernière version (qui inclut votre signataire) :
[dependencies]solana-keychain = { version = "X.Y.Z", default-features = false, features = ["all","sdk-v3",] }
Étape 2 : Définir votre structure de configuration
Dans crates/lib/src/signer/config.rs, ajoutez une nouvelle structure de
configuration pour votre signataire qui définit les variables d'environnement
nécessaires. Par exemple :
/// 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,}
Étape 2 : Ajouter votre signataire à l'énumération SignerTypeConfig
Ajoutez votre variante de signataire à l'énumération SignerTypeConfig dans
crates/lib/src/signer/config.rs :
/// 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,},}
Étape 3 : Ajouter la logique de construction
Dans le même fichier (config.rs), ajoutez une méthode pour construire votre
signataire à partir de la configuration dans l'implémentation SignerConfig :
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)))})}}
Remarque : Le nom de la méthode Signer::from_your_service() doit
correspondre à ce que vous avez implémenté dans la crate solana-keychain.
Étape 4 : Ajouter la logique de validation
Ajoutez la validation de la configuration de votre signataire dans la méthode
validate_individual_signer_config :
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(())}}
Étape 5 : Exporter votre configuration
Ajoutez votre nouvelle structure de configuration aux exports du module dans
crates/lib/src/signer/mod.rs (ou en haut du fichier si elle est publique) :
pub use config::{MemorySignerConfig,PrivySignerConfig,SignerTypeConfig,TurnkeySignerConfig,VaultSignerConfig,YourServiceSignerConfig, // Add this// ... other exports};
Tester votre intégration
Ajouter un constructeur de mock de test
Pour faciliter les tests, ajoutez une méthode de construction à
SignerPoolConfigBuilder dans crates/lib/src/tests/config_mock.rs :
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}}
Cela permet à d'autres tests de créer facilement des configurations simulées incluant votre signataire :
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();
Variables d'environnement
Ajoutez les exemples de variables d'environnement aux fichiers suivants :
.env.example(racine du projet).env(racine du projet, pour les tests locaux)./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
Tests d'intégration
Chaque phase d'intégration correspond à sa propre cible [[test]] dans tests/Cargo.toml. Chaque
cible démarre un surfnet embarqué ainsi qu'un nœud Kora via harness_context,
initialisés à partir de zéro. Kora conserve sa configuration dans un état global au niveau du processus, donc un nouveau signataire
nécessite une nouvelle cible plutôt qu'un nouveau module dans une cible existante.
1. Ajouter une fixture de signataire
Créez une configuration de signataire dans 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. Ajouter une cible de test
Déclarez la phase dans tests/Cargo.toml :
[[test]]name = "your_service"path = "your_service/main.rs"
Créez ensuite tests/your_service/main.rs. Ce fichier indique au harness d'utiliser votre fixture
et doit contenir au moins un #[tokio::test] qui exerce le signataire :
#[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());}
Ajoutez également un test signTransaction afin que le chemin de signature du signataire soit exécuté, et pas seulement
la recherche de clé. tests/multi_signer/ est un exemple complet dont vous pouvez vous inspirer.
3. Exécution des tests
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
Exigences de documentation
Lors de la soumission de votre PR, incluez :
1. Mettre à jour le guide des signataires
Ajoutez la documentation du signataire en suivant le guide
ADDING_SIGNERS.md,
en expliquant les prérequis, la configuration et l'utilisation.
## 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. Mettre à jour le README
Ajoutez votre service à la liste des signataires dans le README principal.
Liste de vérification pour la soumission
- Votre signataire est pris en charge dans la crate
solana-keychain - Dépendance
solana-keychainmise à jour dans Cargo.toml à la dernière version - Struct de configuration ajoutée pour votre signataire
- Variante
SignerTypeConfigajoutée - Logique de build ajoutée dans
build_signer_from_config - Logique de validation ajoutée dans
validate_individual_signer_config - Struct de configuration exportée dans
mod.rs - (Optionnel) Méthode de construction de mock de test ajoutée dans
config_mock.rs - Le code compile sans avertissements
- Tous les tests passent (
just test) - Documentation ajoutée conformément à
ADDING_SIGNERS.md - Fichiers de configuration d'exemple créés (
.tomlet.env.example) - Aucune valeur codée en dur ni secret
- Les messages d'erreur sont explicites
- Respecte les conventions de nommage Rust (snake_case)
- Le linting passe (
make lint) - Contacter l'équipe Kora avec les clés API pour les tests d'intégration
Obtenir de l'aide
- Pour l'implémentation du signataire : Ouvrez un ticket dans le dépôt
solana-keychain - Pour l'intégration Kora : Ouvrez un ticket dans le dépôt Kora pour les discussions de conception
- Rejoignez nos canaux communautaires
- Consultez les configurations de signataires existantes dans
crates/lib/src/signer/config.rs
Exemple de structure de PR
Pour le dépôt Kora :
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
Bienvenue dans l'écosystème Kora ! Nous sommes ravis d'accueillir votre solution de gestion de clés au sein de la plateforme.
Is this page helpful?