Visão Geral da Arquitetura
O Kora utiliza o crate externo
solana-keychain para
todas as operações de assinatura. Esta arquitetura fornece uma interface de
assinatura unificada para assinar transações Solana. Para adicionar um novo
signatário ao Kora, você precisará:
- Primeiro: Adicionar a implementação do seu signatário ao crate
solana-keychain - Segundo: Adicionar suporte de configuração para seu signatário no Kora
Guia de Integração Passo a Passo
Lista de Verificação Rápida de Integração
Parte 1: Adicionar Signatário ao Crate solana-keychain
- Implemente seu signatário seguindo o guia de integração do solana-keychain
- Aguarde a aprovação do PR e a publicação do crate
Parte 2: Adicionar Suporte de Configuração no Kora
- Atualize a dependência no Cargo.toml para que o crate
solana-keychainuse a versão mais recente (que inclui seu signatário) - Adicione uma struct de configuração para as variáveis de ambiente do seu signatário
- Atualize o enum
SignerTypeConfigemcrates/lib/src/signer/config.rs - Adicione lógica de validação para a configuração do seu signatário
- Adicione lógica de construção para criar seu signatário a partir da configuração
- Exporte a struct de configuração em
crates/lib/src/signer/mod.rs - (Opcional) Adicione um construtor mock de teste em
crates/lib/src/tests/config_mock.rs - Atualize os arquivos de configuração de exemplo
- Atualize os scripts de teste para incluir seu signatário (veja abaixo)
- Atualize a documentação para incluir seu signatário (veja abaixo)
- Envie o PR para o repositório do Kora
Adicionar Suporte de Assinante no Kora
Primeiro, certifique-se de que seu assinante é suportado no crate
solana-keychain. Caso não seja, siga o guia em:
https://github.com/solana-foundation/solana-keychain/blob/main/docs/ADDING_SIGNERS.md
Passo 1: Atualizar o Cargo.toml
Atualize a dependência do Cargo.toml para que o crate solana-keychain use a
versão mais recente (que inclui seu assinante):
[dependencies]solana-keychain = { version = "X.Y.Z", default-features = false, features = ["all","sdk-v3",] }
Passo 2: Definir Sua Estrutura de Configuração
Em crates/lib/src/signer/config.rs, adicione uma nova estrutura de
configuração para seu assinante que define quais variáveis de ambiente são
necessárias. Por exemplo:
/// 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,}
Passo 2: Adicionar Seu Assinante ao Enum SignerTypeConfig
Adicione a variante do seu assinante ao enum SignerTypeConfig em
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,},}
Passo 3: Adicionar Lógica de Construção
No mesmo arquivo (config.rs), adicione um método para construir seu assinante
a partir da configuração na implementação de 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: O nome do método Signer::from_your_service() deve corresponder ao
que você implementou no crate solana-keychain.
Passo 4: Adicionar Lógica de Validação
Adicione validação para a configuração do seu assinante no método
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(())}}
Passo 5: Exportar Sua Configuração
Adicione sua nova estrutura de configuração às exportações do módulo em
crates/lib/src/signer/mod.rs (ou no topo do arquivo se for pública):
pub use config::{MemorySignerConfig,PrivySignerConfig,SignerTypeConfig,TurnkeySignerConfig,VaultSignerConfig,YourServiceSignerConfig, // Add this// ... other exports};
Testando Sua Integração
Adicionar Construtor de Mock de Teste
Para facilitar os testes, adicione um método construtor a
SignerPoolConfigBuilder em 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}}
Isso permite que outros testes criem facilmente configurações simuladas que incluam o seu assinante:
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();
Variáveis de Ambiente
Adicione as variáveis de ambiente de exemplo aos seguintes ficheiros:
.env.example(raiz do projeto).env(raiz do projeto, para testes locais)./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
Testes de Integração
Cada fase de integração é o seu próprio alvo [[test]] em tests/Cargo.toml. Cada
alvo inicia uma surfnet incorporada e um nó Kora através de harness_context,
inicializados do zero. O Kora mantém a configuração num estado global do processo, pelo que um novo
assinante precisa de um novo alvo em vez de um novo módulo num já existente.
1. Adicionar um Fixture de Assinante
Crie uma configuração de assinante em 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. Adicionar um Alvo de Teste
Registe a fase em tests/Cargo.toml:
[[test]]name = "your_service"path = "your_service/main.rs"
Depois, crie tests/your_service/main.rs. Este ficheiro aponta o harness para o seu fixture
e tem de conter pelo menos um #[tokio::test] que teste o assinante:
#[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());}
Adicione também um teste signTransaction para que o fluxo de assinatura do assinante seja executado, e não apenas
a procura de chaves. tests/multi_signer/ é um exemplo completo a partir do qual pode copiar.
3. Executar Testes
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
Requisitos de Documentação
Ao submeter o seu PR, inclua:
1. Atualizar o Guia de Assinantes
Adicione documentação do assinante seguindo o guia
ADDING_SIGNERS.md,
explicando os pré-requisitos, configuração e utilização.
## 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. Atualizar o README
Adicione o seu serviço à lista de signatários do README principal.
Lista de Verificação para Submissão
- O seu signatário é suportado no crate
solana-keychain - Dependência
solana-keychainatualizada no Cargo.toml para a versão mais recente - Adicionada a struct de configuração para o seu signatário
- Adicionada a variante
SignerTypeConfig - Adicionada lógica de build em
build_signer_from_config - Adicionada lógica de validação em
validate_individual_signer_config - Struct de configuração exportada em
mod.rs - (Opcional) Adicionado método mock builder de teste em
config_mock.rs - Código compila sem avisos
- Todos os testes passam (
just test) - Documentação adicionada seguindo
ADDING_SIGNERS.md - Ficheiros de configuração de exemplo criados (
.tomle.env.example) - Sem valores ou segredos codificados
- Mensagens de erro são úteis
- Segue as convenções de nomenclatura Rust (snake_case)
- Linting passa (
make lint) - Contacte a equipa Kora com as Chaves de API para testes de integração
Obter Ajuda
- Para implementação de signatários: Abra uma issue no repositório
solana-keychain - Para integração com o Kora: Abra uma issue no repositório Kora para discussões de design
- Junte-se aos nossos canais de comunidade
- Reveja as configurações de signatários existentes em
crates/lib/src/signer/config.rs
Exemplo de Estrutura de PR
Para o repositório 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
Bem-vindo ao ecossistema Kora! Estamos entusiasmados por ter a sua solução de gestão de chaves como parte da plataforma.
Is this page helpful?