Panoramica dell'Architettura
Kora utilizza il crate esterno
solana-keychain per
tutte le operazioni di firma. Questa architettura fornisce un'interfaccia di
firma unificata per firmare le transazioni Solana. Per aggiungere un nuovo
firmatario a Kora, dovrai:
- Prima fase: Aggiungere l'implementazione del tuo firmatario al crate
solana-keychain - Seconda fase: Aggiungere il supporto di configurazione per il tuo firmatario in Kora
Guida all'Integrazione Passo dopo Passo
Lista di Controllo Rapida per l'Integrazione
Parte 1: Aggiungere il Firmatario al Crate solana-keychain
- Implementa il tuo firmatario seguendo la guida all'integrazione di solana-keychain
- Attendi l'approvazione della PR e la pubblicazione del crate
Parte 2: Aggiungere il Supporto di Configurazione in Kora
- Aggiorna la dipendenza nel Cargo.toml in modo che il crate
solana-keychainutilizzi l'ultima versione (che include il tuo firmatario) - Aggiungi la struct di configurazione per le variabili d'ambiente del tuo firmatario
- Aggiorna l'enum
SignerTypeConfigincrates/lib/src/signer/config.rs - Aggiungi la logica di validazione per la configurazione del tuo firmatario
- Aggiungi la logica di build per costruire il tuo firmatario dalla configurazione
- Esporta la struct di configurazione in
crates/lib/src/signer/mod.rs - (Facoltativo) Aggiungi il builder mock di test in
crates/lib/src/tests/config_mock.rs - Aggiorna i file di configurazione di esempio
- Aggiorna gli script di test per includere il tuo firmatario (vedi sotto)
- Aggiorna la documentazione per includere il tuo firmatario (vedi sotto)
- Invia la PR al repository di Kora
Aggiungere il Supporto per Signer in Kora
Innanzitutto, assicurati che il tuo signer sia supportato nel crate
solana-keychain. Se non lo è, segui la guida disponibile a:
https://github.com/solana-foundation/solana-keychain/blob/main/docs/ADDING_SIGNERS.md
Passaggio 1: Aggiornare Cargo.toml
Aggiorna la dipendenza in Cargo.toml in modo che il crate solana-keychain
utilizzi l'ultima versione (che include il tuo signer):
[dependencies]solana-keychain = { version = "X.Y.Z", default-features = false, features = ["all","sdk-v3",] }
Passaggio 2: Definire la Struct di Configurazione
In crates/lib/src/signer/config.rs, aggiungi una nuova struct di
configurazione per il tuo signer che definisca quali variabili d'ambiente sono
necessarie. Ad esempio:
/// 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,}
Passaggio 2: Aggiungere il Tuo Signer all'Enum SignerTypeConfig
Aggiungi la variante del tuo signer all'enum SignerTypeConfig in
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,},}
Passaggio 3: Aggiungere la Logica di Compilazione
Nello stesso file (config.rs), aggiungi un metodo per compilare il tuo signer
dalla configurazione nell'implementazione di 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)))})}}
Nota: Il nome del metodo Signer::from_your_service() dovrebbe
corrispondere a quello che hai implementato nel crate solana-keychain.
Passaggio 4: Aggiungere la Logica di Validazione
Aggiungi la validazione per la configurazione del tuo signer nel metodo
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(())}}
Passaggio 5: Esportare la Tua Configurazione
Aggiungi la tua nuova struct di configurazione alle esportazioni del modulo in
crates/lib/src/signer/mod.rs (o all'inizio del file se è pubblica):
pub use config::{MemorySignerConfig,PrivySignerConfig,SignerTypeConfig,TurnkeySignerConfig,VaultSignerConfig,YourServiceSignerConfig, // Add this// ... other exports};
Testare la Tua Integrazione
Aggiungere il Builder per i Mock di Test
Per facilitare i test, aggiungi un metodo builder a SignerPoolConfigBuilder in
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}}
Questo consente ad altri test di creare facilmente configurazioni mock che includono il tuo signer:
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();
Variabili d'Ambiente
Aggiungi le variabili d'ambiente di esempio ai seguenti file:
.env.example(radice del progetto).env(radice del progetto, per test locali)./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
Test d'Integrazione
Ogni fase di integrazione è un proprio target [[test]] in tests/Cargo.toml. Ogni
target avvia un surfnet embedded e un nodo Kora tramite harness_context,
inizializzati da zero. Kora mantiene la configurazione in uno stato globale di processo, quindi un nuovo signer
richiede un nuovo target anziché un nuovo modulo in uno esistente.
1. Aggiungi una Fixture del Signer
Crea una configurazione del signer 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. Aggiungi un Target di Test
Registra la fase in tests/Cargo.toml:
[[test]]name = "your_service"path = "your_service/main.rs"
Poi crea tests/your_service/main.rs. Questo file indirizza l'harness alla tua fixture
e deve contenere almeno un #[tokio::test] che metta alla prova il signer:
#[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());}
Aggiungi anche un test signTransaction, in modo che venga eseguito il percorso di firma del signer, non solo
la ricerca della chiave. tests/multi_signer/ è un esempio completo da cui partire.
3. Esecuzione dei Test
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
Requisiti di Documentazione
Quando invii la tua PR, includi:
1. Aggiorna la Guida ai Signer
Aggiungi la documentazione del signer seguendo la guida
ADDING_SIGNERS.md,
spiegando i prerequisiti, la configurazione e l'utilizzo.
## 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. Aggiorna il README
Aggiungi il tuo servizio all'elenco dei firmatari nel README principale.
Checklist per la Submission
- Il tuo firmatario è supportato nel crate
solana-keychain - Dipendenza
solana-keychainaggiornata in Cargo.toml all'ultima versione - Aggiunta la struct di configurazione per il tuo firmatario
- Aggiunta la variante
SignerTypeConfig - Aggiunta la logica di build in
build_signer_from_config - Aggiunta la logica di validazione in
validate_individual_signer_config - Struct di configurazione esportata in
mod.rs - (Opzionale) Aggiunto il metodo mock builder per i test in
config_mock.rs - Il codice compila senza avvisi
- Tutti i test passano (
just test) - Documentazione aggiunta seguendo
ADDING_SIGNERS.md - File di configurazione di esempio creati (
.tomle.env.example) - Nessun valore hardcoded o segreto
- I messaggi di errore sono utili
- Segue le convenzioni di denominazione Rust (snake_case)
- Il linting passa (
make lint) - Contatta il team Kora con le API Key per i test di integrazione
Ottenere Assistenza
- Per l'implementazione del firmatario: Apri una issue nel repository
solana-keychain - Per l'integrazione con Kora: Apri una issue nel repository Kora per discussioni di design
- Unisciti ai nostri canali community
- Consulta le configurazioni dei firmatari esistenti in
crates/lib/src/signer/config.rs
Struttura della PR di Esempio
Per il repository 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
Benvenuto nell'ecosistema Kora! Siamo entusiasti di avere la tua soluzione di gestione delle chiavi come parte della piattaforma.
Is this page helpful?