New Configuration Options (Beta)
New kora.toml configuration sections introduced in Kora v2.2.0-beta.
These configuration options are available starting in v2.2.0-beta.1. Add them to your existing kora.toml alongside stable configuration.
Transaction Plugins
The [kora.plugins] section configures transaction plugins that run during signing flows. Plugins validate the shape and contents of transactions before Kora signs them. They execute for signTransaction, signAndSendTransaction, signBundle, and signAndSendBundle — but not for estimateBundleFee.
[kora.plugins]
enabled = ["gas_swap"]| Option | Description | Required | Type |
|---|---|---|---|
enabled | List of enabled transaction plugins | No (default: []) | string[] |
gas_swap Plugin
The gas_swap plugin enforces a strict transaction shape for gasless token-for-SOL swap operations. When enabled, every transaction submitted through signing flows must contain exactly:
- One SPL Token transfer (SPL Token or Token-2022) — from a non-fee-payer owner
- One System SOL transfer (
TransferorTransferWithSeed) — from the fee payer
Compute Budget instructions (set compute unit limit/price) are allowed alongside the two required instructions. Any additional or non-swap outer instructions are rejected.
Configuration Requirements
The gas_swap plugin validates your config at startup and will error if requirements are not met:
- System Program must be in
allowed_programs - At least one token program (SPL Token or Token-2022) must be in
allowed_programs - At least one token must be in
allowed_tokens - Pricing model must not be
Free— set a margin or fixed price
[kora.plugins]
enabled = ["gas_swap"]
[validation]
allowed_programs = [
"11111111111111111111111111111111", # System Program
"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", # SPL Token Program
"TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb", # Token-2022 Program
]
allowed_tokens = [
"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", # USDC
]
[validation.price]
type = "margin"
margin = 0.0Warning: When using
gas_swapwith Fixed pricing, ensure the fixed token fee is worth at leastmax_allowed_lamportsin SOL to avoid a drain condition where the SOL sent exceeds the token received.
Bundle Configuration
The [kora.bundle] section enables Jito bundle support for atomic multi-transaction execution:
[kora.bundle]
enabled = true
[kora.bundle.jito]
block_engine_url = "https://mainnet.block-engine.jito.wtf"| Option | Description | Required | Type |
|---|---|---|---|
enabled | Enable bundle functionality | No (default: false) | boolean |
Jito Configuration
| Option | Description | Required | Type |
|---|---|---|---|
block_engine_url | Jito block engine URL | Yes (when bundles enabled) | string |
Available Jito block engine URLs:
- Mainnet (public):
https://mainnet.block-engine.jito.wtf - Mainnet (private): Contact Jito for access
Important: When using bundles with Jito tips paid by Kora, set
allow_transfer = truein[validation.fee_payer_policy.system]to allow the signer to transfer SOL for the tip.
For a complete guide on implementing Jito bundles with Kora, see the Jito Bundle Guide.
Lighthouse Fee Payer Protection
The [kora.lighthouse] section enables Lighthouse fee payer protection. When enabled, Kora adds balance assertion instructions to transactions, protecting the fee payer from drainage attacks by verifying the fee payer's balance doesn't drop below expected levels.
[kora.lighthouse]
enabled = true
fail_if_transaction_size_overflow = true| Option | Description | Required | Type |
|---|---|---|---|
enabled | Enable Lighthouse assertions for fee payer protection | No (default: false) | boolean |
fail_if_transaction_size_overflow | Reject transaction if adding assertion exceeds size limit. If false, skips adding assertion silently. | No (default: true) | boolean |
How It Works
When Lighthouse is enabled, Kora fetches the fee payer's current balance and adds a Lighthouse assertion instruction that verifies the balance doesn't drop below (current_balance - estimated_fee) at transaction completion. This prevents malicious transactions from draining the fee payer beyond expected costs.
Method Compatibility
Lighthouse protection only works with signTransaction and signBundle. It does NOT work with signAndSendTransaction or signAndSendBundle.
When Lighthouse adds an assertion instruction, it modifies the transaction message. This invalidates any pre-existing client signatures. The signAndSend* flows would fail because:
- Client signs transaction
- Kora adds Lighthouse assertion (modifies message)
- Client's original signature becomes invalid
- Network rejects with "signature verification failure"
Recommended pattern with Lighthouse:
signTransaction → client receives modified tx → client re-signs → client sends to networkConfiguration Requirements
When enabling Lighthouse, add the Lighthouse program to your allowed_programs:
[validation]
allowed_programs = [
# ... other programs ...
"L2TExMFKdjpN9kozasaurPirfHy9P8sbXoAN1qA3S95", # Lighthouse Program
]Kora validates this on startup and will error if Lighthouse is enabled but the program is not in allowed_programs.
Note: If
signAndSendTransactionorsignAndSendBundleare enabled alongside Lighthouse, Kora will log a warning that these methods won't have fee payer protection.
reCAPTCHA Bot Protection
reCAPTCHA v3 provides invisible bot protection for sensitive endpoints. Unlike API Key and HMAC which authenticate all requests, reCAPTCHA only protects specific high-risk methods (signing methods by default).
Server Configuration
Add KORA_RECAPTCHA_SECRET to your environment variables (has priority), or add a recaptcha_secret to your kora.toml:
[kora.auth]
recaptcha_secret = "your-recaptcha-v3-secret-key"
recaptcha_score_threshold = 0.5 # Optional: 0.0-1.0, default 0.5
protected_methods = ["signTransaction", "signAndSendTransaction", "signBundle", "signAndSendBundle"] # Optional| Option | Description | Default |
|---|---|---|
recaptcha_secret | Your reCAPTCHA v3 secret key from Google | - |
recaptcha_score_threshold | Minimum score to pass (0.0 = all pass, 1.0 = none pass) | 0.5 |
protected_methods | RPC methods requiring verification | Signing methods |
How It Works
- Client obtains a reCAPTCHA token from Google's reCAPTCHA v3 API
- Client includes the token in the
x-recaptcha-tokenheader - Server verifies the token with Google and checks the score
- If score >= threshold, request proceeds; otherwise returns 401 Unauthorized
reCAPTCHA runs after API Key/HMAC authentication succeeds (if configured). Unprotected methods bypass reCAPTCHA verification entirely.
Client Implementation
Using Kora SDK:
const { KoraClient } = require('@solana/kora');
const kora = new KoraClient({
rpcUrl: 'http://localhost:8080',
apiKey: process.env.KORA_API_KEY,
// Callback called for each request - return fresh token
getRecaptchaToken: async () => {
return await grecaptcha.execute('your-site-key', { action: 'sign' });
}
});
// Token is automatically included for all requests
const result = await kora.signTransaction({ transaction: 'base64...' });Using fetch:
async function callKoraProtectedMethod(method, params = {}) {
const recaptchaToken = await grecaptcha.execute('your-site-key', { action: 'sign' });
const response = await fetch('http://localhost:8080', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-recaptcha-token': recaptchaToken
},
body: JSON.stringify({
jsonrpc: '2.0',
method,
params,
id: 1
})
});
return response.json();
}Getting reCAPTCHA Keys
- Go to Google reCAPTCHA Admin Console
- Create a new site with reCAPTCHA v3
- Use the Site Key in your frontend (client-side)
- Use the Secret Key in your Kora configuration (server-side)
Usage Limits
The [kora.usage_limit] section configures per-wallet usage limiting to prevent abuse and ensure fair usage. This can also be used to create rewards programs to subsidize users' transaction fees up to a certain limit.
Note: This feature requires Redis when enabled across multiple Kora instances.
[kora.usage_limit]
enabled = true
cache_url = "redis://localhost:6379"
fallback_if_unavailable = true| Option | Description | Required | Type |
|---|---|---|---|
enabled | Enable per-wallet usage limiting | No (default: false) | boolean |
cache_url | Redis connection URL for shared usage tracking | No | string |
fallback_if_unavailable | Allow transactions if Redis is unavailable | No (default: true) | boolean |
When
fallback_if_unavailableis true, the system allows transactions to proceed if Redis is temporarily unavailable, preventing service disruption.
Usage Limit Rules
The beta introduces granular, rule-based usage limits. Instead of a single max_transactions count, you can define multiple rules that target specific transaction types or individual instructions, with optional time windows.
[[kora.usage_limit.rules]]
type = "transaction"
max = 100
window_seconds = 86400 # 100 transactions per day
[[kora.usage_limit.rules]]
type = "instruction"
program = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
instruction = "Transfer"
max = 50
window_seconds = 3600 # 50 SPL transfers per hour| Rule Field | Description | Required |
|---|---|---|
type | "transaction" (counts all transactions) or "instruction" (counts specific instruction types) | Yes |
max | Maximum count before the wallet is blocked | Yes |
window_seconds | Time window in seconds. If omitted, the limit is permanent. | No |
program | Program address to match (required for instruction type) | Conditional |
instruction | Instruction name to match, e.g. "Transfer", "Burn" (required for instruction type) | Conditional |
When window_seconds is set, the counter resets after the time window expires. Without it, the limit is permanent — once reached, the wallet is blocked until manually cleared from Redis.
New Enabled Methods
The following methods have been added to [kora.enabled_methods]:
[kora.enabled_methods]
get_version = true
estimate_bundle_fee = true
sign_bundle = false
sign_and_send_bundle = false| Method | Description |
|---|---|
get_version | Return the Kora server version |
estimate_bundle_fee | Estimate fees for a bundle of transactions |
sign_bundle | Sign a bundle of transactions without sending |
sign_and_send_bundle | Sign and submit a bundle to Jito |
See Bundle Methods for full API documentation.