Agentic Wallet supports gasless transaction execution via Kora RPC, enabling agents to perform operations without holding SOL for transaction fees. This is ideal for onboarding new users and enabling frictionless agent interactions.
Overview
Gasless execution allows:
Zero SOL requirement : Agents can operate with only token balances
Protocol-gated eligibility : Only approved protocols support gasless
Automatic fee sponsorship : Kora RPC covers transaction fees
Transparent fallback : Same intent API, just add gasless: true
Gasless transactions are routed through Kora RPC (KORA_RPC_URL) instead of standard Solana RPC endpoints.
Configuration
Environment Setup
Add Kora RPC endpoint to .env:
KORA_RPC_URL = https://kora-rpc.example.com
For local testing:
KORA_RPC_URL = http://localhost:8080
Restart Services
set -a ; source .env ; set +a
npm run dev
The transaction engine will use Kora RPC for all gasless-flagged intents.
Protocol Eligibility
Check Protocol Support
curl -H 'x-api-key: dev-api-key' \
http://localhost:3000/api/v1/risk/protocols/ < protocol-nam e >
Response includes:
{
"data" : {
"protocol" : "system-program" ,
"decision" : "allow" ,
"config" : {
"gaslessEligible" : true ,
"maxNotionalLamports" : 100000000 ,
"slippageBps" : 100
}
}
}
Default Eligible Protocols
By default, most protocols are gasless-eligible:
system-program (SOL transfers)
spl-token (token transfers)
jupiter (swaps)
marinade (staking)
escrow (escrow operations)
Restricting Gasless Access
Disable gasless for a specific protocol:
curl -X PUT http://localhost:3000/api/v1/risk/protocols/ < protoco l > \
-H 'x-api-key: dev-api-key' \
-H 'content-type: application/json' \
-d '{
"gaslessEligible": false
}'
If a protocol is marked gaslessEligible: false, gasless intents will be rejected at the policy stage.
Enabling Gasless for Intents
Via Intent Runner
Add "gasless": true to any intent:
npm run intent-runner -- --intent '{
"type": "transfer_sol",
"walletId": "<wallet-id>",
"protocol": "system-program",
"gasless": true,
"intent": {
"destination": "<recipient-pubkey>",
"lamports": 1000000
}
}'
Via CLI
npm run cli -- agent execute < agent-i d > \
--type transfer_sol \
--protocol system-program \
--intent '{"destination":"<pubkey>","lamports":1000000}' \
--gasless
Via SDK
import { AgenticWalletSDK } from '@agentic-wallet/sdk' ;
const client = new AgenticWalletSDK (
'http://localhost:3000' ,
{ 'x-api-key' : 'dev-api-key' }
);
const result = await client . transactions . create ({
walletId: '<wallet-id>' ,
type: 'transfer_sol' ,
protocol: 'system-program' ,
gasless: true ,
intent: {
destination: '<recipient-pubkey>' ,
lamports: 1_000_000 ,
},
});
console . log ( 'Gasless transaction:' , result . signature );
Via API Gateway
curl -X POST http://localhost:3000/api/v1/transactions \
-H 'x-api-key: dev-api-key' \
-H 'content-type: application/json' \
-d '{
"walletId": "<wallet-id>",
"type": "transfer_sol",
"protocol": "system-program",
"gasless": true,
"intent": {
"destination": "<recipient-pubkey>",
"lamports": 1000000
}
}'
How It Works
Gasless execution follows the same pipeline with RPC routing changes:
Intent submission
User/agent submits intent with gasless: true flag.
Eligibility check
Transaction engine queries protocol risk config: if ( request . gasless && ! protocolRisk . config . gaslessEligible ) {
throw new Error ( 'Protocol not eligible for gasless execution' );
}
Transaction build
Protocol adapter builds the transaction (unchanged from normal flow).
Policy evaluation
Policy engine evaluates the intent (unchanged).
Signing
Wallet engine signs the transaction (unchanged).
Gasless submission
Transaction engine routes to Kora RPC: const response = await fetch ( koraRpcUrl , {
method: 'POST' ,
headers: { 'content-type' : 'application/json' },
body: JSON . stringify ({
jsonrpc: '2.0' ,
id: 1 ,
method: 'signAndSendTransaction' ,
params: { transaction: signedTxBase64 },
}),
});
Confirmation
Transaction engine confirms via standard Solana RPC.
Gasless Agent Configuration
Create agents that always use gasless execution:
const gaslessAgent = await client . agents . create ({
name: 'gasless-trader' ,
allowedIntents: [ 'swap' , 'transfer_sol' ],
allowedProtocols: [ 'jupiter' , 'system-program' ],
executionMode: 'autonomous' ,
autonomy: {
enabled: true ,
mode: 'execute' ,
steps: [
{
id: 'gasless-swap' ,
type: 'swap' ,
protocol: 'jupiter' ,
gasless: true , // Force gasless for this step
intent: {
inputMint: 'So11111111111111111111111111111111111111112' ,
outputMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' ,
amount: 1000000 ,
slippageBps: 100 ,
},
maxRuns: 10 ,
cooldownSeconds: 60 ,
},
],
},
});
Limitations
Kora RPC may impose limits:
Maximum transactions per wallet per hour
Maximum fee amount per transaction
Protocol-specific restrictions
If Kora RPC rejects a transaction, the engine will return: {
"status" : "failure" ,
"errorCode" : "CONFIRMATION_FAILED" ,
"failedAt" : "send" ,
"message" : "Kora signAndSendTransaction failed: rate limit exceeded"
}
Fallback Strategy
If gasless fails, retry without gasless flag:
try {
return await client . transactions . create ({ ... intent , gasless: true });
} catch ( error ) {
console . warn ( 'Gasless failed, retrying with normal execution:' , error );
return await client . transactions . create ({ ... intent , gasless: false });
}
Not Available for All Operations
Gasless mode is not supported for:
Program deployments
Account creations requiring rent deposits
Operations requiring token account initialization
These require the wallet to hold SOL.
Monitoring Gasless Transactions
Gasless transactions are marked in history:
curl -H 'x-api-key: dev-api-key' \
http://localhost:3000/api/v1/transactions/ < tx-i d >
Response includes:
{
"data" : {
"id" : "<tx-id>" ,
"gasless" : true ,
"status" : "confirmed" ,
"signature" : "<signature>" ,
"stage" : "completed"
}
}
Audit Events
curl -H 'x-api-key: dev-api-key' \
'http://localhost:3000/api/v1/audit/events?category=gasless'
Metrics
Query gasless execution statistics:
curl -H 'x-api-key: dev-api-key' \
http://localhost:3000/api/v1/metrics
Look for:
gasless_transaction_success_total
gasless_transaction_failure_total
gasless_protocol_usage_total
Testing Gasless Locally
Mock Kora RPC
For testing without a real Kora instance, use a mock server:
import express from 'express' ;
const app = express ();
app . use ( express . json ());
app . post ( '/' , ( req , res ) => {
const { method , params } = req . body ;
if ( method === 'signAndSendTransaction' ) {
// Simulate success
res . json ({
jsonrpc: '2.0' ,
id: req . body . id ,
result: {
signature: '5j7s3...' + Date . now (), // Mock signature
},
});
} else {
res . status ( 400 ). json ({
jsonrpc: '2.0' ,
id: req . body . id ,
error: { message: 'Method not supported' },
});
}
});
app . listen ( 8080 , () => {
console . log ( 'Mock Kora RPC listening on http://localhost:8080' );
});
Run:
KORA_RPC_URL = http://localhost:8080 npm run dev
Security Considerations
Gasless Security Checklist:
Validate Kora RPC endpoint is HTTPS in production
Set protocol eligibility conservatively
Monitor for abuse patterns (rapid gasless submissions)
Implement wallet-level gasless rate limits
Log all gasless transactions for auditing
Rate Limiting
Add per-wallet gasless caps:
const gaslessLimits = new Map < string , number []>();
function checkGaslessRateLimit ( walletId : string ) : boolean {
const now = Date . now ();
const recentTxs = gaslessLimits . get ( walletId ) ?? [];
const filtered = recentTxs . filter ( ts => now - ts < 60_000 ); // Last minute
if ( filtered . length >= 10 ) {
throw new Error ( 'Gasless rate limit exceeded (max 10/min)' );
}
filtered . push ( now );
gaslessLimits . set ( walletId , filtered );
return true ;
}
Production Deployment
Environment Variables
# Production Kora RPC endpoint
KORA_RPC_URL = https://kora-rpc.mainnet.example.com
# Fallback to standard RPC if Kora unavailable
SOLANA_RPC_URL = https://api.mainnet-beta.solana.com
# Restrict gasless to specific protocols
GASLESS_ALLOWED_PROTOCOLS = system-program,jupiter,escrow
Health Checks
Monitor Kora RPC availability:
curl -X POST ${ KORA_RPC_URL } \
-H 'content-type: application/json' \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "getHealth"
}'
Next Steps
Multi-Agent Orchestration Use gasless for agent-to-agent transfers
Strategy Backtesting Test gasless strategies before deployment