Protocols
Protocol adapters abstract blockchain interactions into a unified interface. They handle quote generation, transaction building, and protocol-specific logic.
Protocol Adapter Interface
interface ProtocolAdapter {
readonly name : string ; // Protocol identifier
readonly version : string ; // Adapter version (semver)
readonly programIds : string []; // On-chain program addresses
readonly capabilities : string []; // Supported operations
// Swap operations
getSwapQuote ? ( params : SwapQuoteParams ) : Promise < SwapQuote >;
buildSwap ? ( params : SwapExecuteParams ) : Promise < BuildResult >;
// Staking operations
buildStake ? ( params : StakeParams ) : Promise < BuildResult >;
buildUnstake ? ( params : StakeParams ) : Promise < BuildResult >;
// Lending operations
buildSupply ? ( params : LendingParams ) : Promise < BuildResult >;
buildBorrow ? ( params : LendingParams ) : Promise < BuildResult >;
// Generic intent builder
buildIntent ? (
intentType : string ,
walletAddress : string ,
intent : Record < string , unknown >
) : Promise < BuildResult >;
// Intent migration
migrateIntent ? (
input : MigrationInput
) : Promise < Record < string , unknown >>;
// Health check
healthCheck ? () : Promise < AdapterHealth >;
}
Supported Protocols
Agentic Wallet includes adapters for 9 protocols:
System Program Native SOL transfers
transfer_sol
Program ID: 11111111111111111111111111111111
SPL Token Token operations
transfer_spl
create_mint
mint_token
Program ID: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
Jupiter DEX aggregator
swap (quote + build)
Version: 1.0.0
API: https://lite-api.jup.ag/swap/v1
Marinade Liquid staking
stake
unstake
Capabilities: stake, unstake
Solend Lending protocol
lend_supply
lend_borrow
Fail-closed quotes
Metaplex NFT operations
NFT minting
Metadata creation
Escrow Custom escrow program
create_escrow
accept_escrow
release_escrow
refund_escrow
dispute_escrow
resolve_dispute
Solend, Orca, and Raydium adapters now fail closed instead of returning synthetic quotes. This prevents execution if external APIs are unavailable.
Protocol Registry
The AdapterRegistry manages protocol lifecycle:
// services/protocol-adapters/src/registry.ts
class AdapterRegistry {
private readonly adapters = new Map < string , ProtocolAdapter >();
register ( adapter : ProtocolAdapter ) : void ;
get ( name : string ) : ProtocolAdapter | null ;
list () : ProtocolAdapter [];
registerMigration ( protocol : string , migration : AdapterMigration ) : void ;
checkCompatibility ( protocol : string , targetVersion : string ) : CompatibilityResult ;
migrateIntent ( protocol : string , input : MigrationInput ) : Promise < MigratedIntent >;
}
Listing Protocols
npm run cli -- protocol list
Response:
{
"data" : [
{
"protocol" : "jupiter" ,
"version" : "1.0.0" ,
"capabilities" : [ "swap" , "getQuote" ],
"programIds" : [
"JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"
]
},
{
"protocol" : "marinade" ,
"version" : "1.0.0" ,
"capabilities" : [ "stake" , "unstake" ],
"programIds" : [
"MarBmsSgKXdrN1egZf5sqe1TMai9K1rChYNDJgjq7aD"
]
}
]
}
Protocol Capabilities
Query specific protocol capabilities:
npm run cli -- protocol caps jupiter
Response:
{
"data" : {
"protocol" : "jupiter" ,
"version" : "1.0.0" ,
"capabilities" : [ "swap" , "getQuote" ],
"programIds" : [
"JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"
]
}
}
Quote/Build Flow
Protocol adapters follow a two-phase pattern:
1. Quote Phase (Read-Only)
Generate a quote without executing:
interface SwapQuoteParams {
inputMint : string ;
outputMint : string ;
amount : string ;
slippageBps ?: number ;
walletAddress : string ;
}
interface SwapQuote {
inputMint : string ;
outputMint : string ;
inputAmount : string ;
outputAmount : string ;
priceImpactPct : number ;
fee : string ;
route : unknown ;
}
Example:
npm run cli -- protocol quote \
--protocol jupiter \
--input-mint So11111111111111111111111111111111111111112 \
--output-mint EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v \
--amount 1000000000 \
--wallet 9B5XszUGdMaxCZ7uSQhPzdks5ZQSmWxrmzCSvtJ6Ns6g
2. Build Phase (Transaction Construction)
Convert quote into executable transaction:
interface BuildResult {
mode : 'transaction' | 'instructions' ;
transaction ?: string ; // Base64 serialized transaction
instructions ?: SerializedInstruction []; // Individual instructions
programIds : string []; // Programs invoked
metadata ?: Record < string , unknown >; // Protocol-specific data
}
Example flow:
// services/protocol-adapters/src/index.ts:88
if ( type === 'swap' && adapter . getSwapQuote && adapter . buildSwap ) {
// Phase 1: Get quote
const quote = await adapter . getSwapQuote ({
inputMint: intent [ 'inputMint' ],
outputMint: intent [ 'outputMint' ],
amount: intent [ 'amount' ],
slippageBps: intent [ 'slippageBps' ] ?? 50 ,
walletAddress ,
});
// Phase 2: Build transaction
return adapter . buildSwap ({ walletAddress , quote });
}
Protocol-Specific Operations
Jupiter Swaps
npm run cli -- protocol swap \
--protocol jupiter \
--input-mint So11111111111111111111111111111111111111112 \
--output-mint EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v \
--amount 1000000000 \
--wallet 9B5XszUGdMaxCZ7uSQhPzdks5ZQSmWxrmzCSvtJ6Ns6g \
--slippage-bps 50
Marinade Staking
npm run cli -- protocol stake \
--protocol marinade \
--wallet 9B5XszUGdMaxCZ7uSQhPzdks5ZQSmWxrmzCSvtJ6Ns6g \
--amount 1000000000
Solend Lending
npm run cli -- protocol lend-supply \
--protocol solend \
--wallet 9B5XszUGdMaxCZ7uSQhPzdks5ZQSmWxrmzCSvtJ6Ns6g \
--mint EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v \
--amount 1000000
Escrow Operations
Create Escrow
Accept Escrow
Release Escrow
npm run cli -- protocol escrow-create \
--wallet 9B5XszUGdMaxCZ7uSQhPzdks5ZQSmWxrmzCSvtJ6Ns6g \
--intent '{"amount":1000000000,"recipient":"..."}'
The escrow adapter requires a deployed escrow program. Set ESCROW_PROGRAM_ID in your environment. This repository does not ship a pre-deployed program artifact.
Protocol Health Checks
Adapters can implement health checks:
interface AdapterHealth {
ok : boolean ;
details ?: Record < string , unknown >;
}
Checking Health
All Protocols
Specific Protocol
curl http://localhost:3000/api/v1/protocols/health
Response:
{
"data" : {
"ok" : true ,
"checks" : [
{
"protocol" : "jupiter" ,
"version" : "1.0.0" ,
"ok" : true ,
"details" : { "mode" : "api" , "endpoint" : "https://lite-api.jup.ag" }
},
{
"protocol" : "marinade" ,
"version" : "1.0.0" ,
"ok" : true ,
"details" : { "mode" : "static" }
}
]
}
}
Protocol Versioning
Adapters use semantic versioning. Check compatibility:
curl -X POST http://localhost:3000/api/v1/protocols/jupiter/compatibility-check \
-H "Content-Type: application/json" \
-d '{"targetVersion":"2.0.0"}'
Response:
{
"data" : {
"compatible" : false ,
"currentVersion" : "1.0.0" ,
"reason" : "Major version mismatch 1.0.0 -> 2.0.0"
}
}
Compatibility rules:
Same major version: Compatible
Different major version: Incompatible (breaking changes)
Intent Migration
Migrate intents between adapter versions:
interface AdapterMigration {
fromVersion : string ;
toVersion : string ;
migrate : ( type : string , intent : Record < string , unknown >) => Record < string , unknown >;
}
Example migration:
// services/protocol-adapters/src/index.ts:65
registry . registerMigration ( 'jupiter' , {
fromVersion: '0.9.0' ,
toVersion: '1.0.0' ,
migrate : ( _type , intent ) => ({
... intent ,
... ( intent [ 'maxSlippageBps' ] === undefined && intent [ 'slippageBps' ] !== undefined
? { maxSlippageBps: intent [ 'slippageBps' ] }
: {}),
}),
});
Migrating Intents
curl -X POST http://localhost:3000/api/v1/protocols/jupiter/migrate-intent \
-H "Content-Type: application/json" \
-d '{
"fromVersion": "0.9.0",
"toVersion": "1.0.0",
"type": "swap",
"intent": {
"inputMint": "...",
"outputMint": "...",
"amount": "1000000",
"slippageBps": 50
}
}'
Response:
{
"data" : {
"intent" : {
"inputMint" : "..." ,
"outputMint" : "..." ,
"amount" : "1000000" ,
"slippageBps" : 50 ,
"maxSlippageBps" : 50
},
"migrationApplied" : true
}
}
Generic Build Endpoint
Build transactions for any protocol/intent combination:
curl -X POST http://localhost:3000/api/v1/build \
-H "Content-Type: application/json" \
-d '{
"protocol": "jupiter",
"type": "swap",
"walletAddress": "9B5XszUGdMaxCZ7uSQhPzdks5ZQSmWxrmzCSvtJ6Ns6g",
"intent": {
"inputMint": "So11111111111111111111111111111111111111112",
"outputMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"amount": "1000000000",
"slippageBps": 50
}
}'
Configuration
# Jupiter API endpoint
JUPITER_API_URL = https://lite-api.jup.ag/swap/v1
# Escrow program
ESCROW_PROGRAM_ID = YourEscrowProgramIdHere
# Protocol service
PORT = 3005
Best Practices
Use jupiter for best swap prices (aggregates multiple DEXes)
Use marinade for liquid staking (mSOL receipt tokens)
Check protocol health before execution
Implement fallback protocols for critical paths
Monitor adapter version updates
Always fetch fresh quotes (quotes expire quickly)
Validate slippage before execution
Check priceImpactPct for large trades
Handle quote failures gracefully (fail-closed)
Don’t cache quotes across requests
DEX adapters may fail if external APIs are down
Implement retries for transient failures
Check AdapterHealth before submission
Validate programIds match expected values
Monitor adapter error rates
Validate program IDs returned in BuildResult
Use protocol allowlists in policies
Set per-protocol risk rules
Audit adapter code before production use
Monitor for unexpected protocol behavior
Source Code Reference
Protocol adapter functionality is implemented in:
services/protocol-adapters/src/index.ts - Main service (services/protocol-adapters/src/index.ts:1)
services/protocol-adapters/src/registry.ts - Adapter registry (services/protocol-adapters/src/registry.ts:1)
services/protocol-adapters/src/adapters/adapter.interface.ts - Interface definitions (services/protocol-adapters/src/adapters/adapter.interface.ts:1)
services/protocol-adapters/src/adapters/jupiter.adapter.ts - Jupiter implementation (services/protocol-adapters/src/adapters/jupiter.adapter.ts:1)
services/protocol-adapters/src/adapters/escrow.adapter.ts - Escrow implementation (services/protocol-adapters/src/adapters/escrow.adapter.ts:1)