Documentation Index Fetch the complete documentation index at: https://docs.relaycore.xyz/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The RelayService class enables service providers to:
Register services with pricing and metadata
Handle payments via x402 protocol
Prove delivery with cryptographic evidence
Track reputation based on outcomes
Design Philosophy : Explicit service definition, proof-first delivery, reputation as first-class.
Installation
npm install @relaycore/sdk ethers
Quick Start
import { RelayService } from '@relaycore/sdk' ;
import { ethers } from 'ethers' ;
// Initialize service
const service = new RelayService ({
wallet: new ethers . Wallet ( privateKey , provider ),
network: 'cronos-testnet' ,
apiUrl: 'https://api.relaycore.xyz'
});
// Register service
const registered = await service . register ({
name: 'Pyth Price Oracle' ,
description: 'Real-time price feeds from Pyth Network' ,
category: 'oracle' ,
price: '100000' , // 0.1 USDC per call
inputSchema: {
type: 'object' ,
properties: {
symbol: { type: 'string' }
},
required: [ 'symbol' ]
},
outputSchema: {
type: 'object' ,
properties: {
price: { type: 'number' },
timestamp: { type: 'number' }
}
}
});
// Handle payments
service . handlePayment <{ symbol : string }, { price : number ; timestamp : number }>(
async ( ctx ) => {
// Execute service logic
const price = await getPythPrice ( ctx . input . symbol );
// Deliver result with proof
await ctx . deliver ({
result: {
price: price . value ,
timestamp: price . timestamp
},
proof: price . signature ,
latencyMs: Date . now () - ctx . timestamp . getTime ()
});
}
);
Core Methods
constructor(config: ServiceConfig)
Initialize the service provider.
Parameters :
interface ServiceConfig {
wallet : ethers . Signer ; // Wallet for receiving payments
network ?: Network ; // 'cronos-testnet' | 'cronos-mainnet'
apiUrl ?: string ; // API endpoint
}
register(definition: ServiceDefinition): Promise<RegisteredService>
Register service on the RelayCore platform.
Parameters :
interface ServiceDefinition {
name : string ;
description ?: string ;
category : string ; // e.g., 'oracle', 'trading', 'data'
price : string ; // Price per call (base units)
endpoint ?: string ; // Service endpoint URL
inputSchema ?: JsonSchema ; // JSON Schema for input validation
outputSchema ?: JsonSchema ; // JSON Schema for output validation
inputType ?: string ; // Human-readable input type
outputType ?: string ; // Human-readable output type
tags ?: string []; // Searchable tags
capabilities ?: string []; // Service capabilities
version ?: string ; // Service version
}
Returns :
interface RegisteredService {
id : string ; // Service ID
ownerAddress : string ; // Provider wallet address
registeredAt : Date ;
isActive : boolean ;
}
Example :
const service = await provider . register ({
name: 'DEX Quote Aggregator' ,
description: 'Aggregate quotes from 6 perpetual DEX venues' ,
category: 'trading' ,
price: '10000' , // 0.01 USDC
inputSchema: {
type: 'object' ,
properties: {
pair: { type: 'string' },
side: { type: 'string' , enum: [ 'long' , 'short' ] },
leverage: { type: 'number' , minimum: 1 , maximum: 50 },
sizeUsd: { type: 'number' , minimum: 100 }
},
required: [ 'pair' , 'side' , 'leverage' , 'sizeUsd' ]
},
outputSchema: {
type: 'object' ,
properties: {
entryPrice: { type: 'number' },
liquidationPrice: { type: 'number' },
fundingRate: { type: 'number' },
bestVenue: { type: 'string' }
}
},
tags: [ 'dex' , 'perpetuals' , 'aggregator' ],
capabilities: [ 'multi-venue' , 'best-execution' ],
version: '1.0.0'
});
console . log ( 'Service registered:' , service . id );
handlePayment<TInput, TOutput>(handler: (ctx: PaymentContext<TInput>) => Promise<void>): void
Set payment handler for incoming requests.
Parameters :
interface PaymentContext < TInput > {
paymentId : string ; // Unique payment ID
txHash : string ; // On-chain transaction hash
amount : string ; // Amount paid (base units)
payerAddress : string ; // Payer wallet address
input : TInput ; // Service input data
timestamp : Date ; // Payment timestamp
// Delivery methods
deliver : < TOutput >( proof : DeliveryProof < TOutput >) => Promise < void >;
fail : ( reason : string , retryable ?: boolean ) => Promise < void >;
}
Delivery Proof :
interface DeliveryProof < T > {
result : T ; // Service output
proof ?: string ; // Cryptographic proof (optional)
evidence ?: Record < string , unknown >; // Additional evidence
latencyMs ?: number ; // Execution latency
}
Example :
service . handlePayment < QuoteInput , QuoteOutput >( async ( ctx ) => {
const startTime = Date . now ();
try {
// Validate input
if ( ! ctx . input . pair || ! ctx . input . side ) {
return await ctx . fail ( 'Invalid input: missing required fields' , false );
}
// Execute service logic
const quote = await aggregateQuotes ({
pair: ctx . input . pair ,
side: ctx . input . side ,
leverage: ctx . input . leverage ,
sizeUsd: ctx . input . sizeUsd
});
// Deliver with proof
await ctx . deliver ({
result: {
entryPrice: quote . entryPrice ,
liquidationPrice: quote . liquidationPrice ,
fundingRate: quote . fundingRate ,
bestVenue: quote . bestVenue
},
proof: quote . signature , // Optional cryptographic proof
evidence: {
sources: quote . sources ,
timestamp: Date . now ()
},
latencyMs: Date . now () - startTime
});
console . log ( 'Quote delivered:' , ctx . paymentId );
} catch ( error ) {
// Report failure
await ctx . fail (
`Service error: ${ error . message } ` ,
true // retryable
);
}
});
getReputation(): Promise<ProviderReputation>
Get current reputation score and metrics.
Returns :
interface ProviderReputation {
reputationScore : number ; // Score 0-100
successRate : number ; // Success rate percentage
totalDeliveries : number ; // Total successful deliveries
avgLatencyMs : number ; // Average latency
trend : 'improving' | 'stable' | 'declining' ;
rank ?: number ; // Rank among all providers
percentile ?: number ; // Percentile ranking
}
Example :
const reputation = await service . getReputation ();
console . log ( 'Reputation Score:' , reputation . reputationScore );
console . log ( 'Success Rate:' , reputation . successRate , '%' );
console . log ( 'Avg Latency:' , reputation . avgLatencyMs , 'ms' );
console . log ( 'Trend:' , reputation . trend );
console . log ( 'Rank:' , reputation . rank , '(top' , reputation . percentile , '%)' );
getMetrics(): Promise<ServiceMetrics>
Get detailed service performance metrics.
Returns :
interface ServiceMetrics {
timestamp : Date ;
reputationScore : number ;
successRate : number ;
avgLatencyMs : number ;
totalCalls : number ;
totalPayments : number ;
totalRevenue : string ; // Total revenue in base units
}
Example :
const metrics = await service . getMetrics ();
console . log ( 'Total Calls:' , metrics . totalCalls );
console . log ( 'Total Revenue:' , ( parseInt ( metrics . totalRevenue ) / 1e6 ). toFixed ( 2 ), 'USDC' );
console . log ( 'Success Rate:' , metrics . successRate , '%' );
deactivate(): Promise<void>
Deactivate the service (stop accepting new requests).
Example :
await service . deactivate ();
console . log ( 'Service deactivated' );
Reputation System
How Reputation is Calculated
reputationScore = (successRate * 0.7) + (latencyScore * 0.2) + (volumeScore * 0.1)
where:
successRate = (successfulDeliveries / totalDeliveries) * 100
latencyScore = max(0, 100 - (avgLatencyMs / 10))
volumeScore = min(100, (totalDeliveries / 100) * 100)
Reputation Updates
Reputation updates after each delivery:
// On successful delivery
await ctx . deliver ( proof );
// → Increments successfulDeliveries
// → Updates avgLatencyMs
// → Recalculates reputationScore
// On failure
await ctx . fail ( reason , retryable );
// → Increments failedDeliveries
// → Decreases reputationScore
Reputation Trends
interface ReputationTrend {
'improving' : reputationScore increased > 5 points in last 7 days
'stable' : reputationScore changed < 5 points in last 7 days
'declining' : reputationScore decreased > 5 points in last 7 days
}
Payment Events
Listen to payment events for logging and analytics:
service . on ( 'payment:received' , ( event : PaymentEvent ) => {
console . log ( 'Payment received:' , event . paymentId );
console . log ( 'Amount:' , event . amount );
console . log ( 'Payer:' , event . payerAddress );
});
service . on ( 'payment:settled' , ( event : PaymentEvent ) => {
console . log ( 'Payment settled:' , event . txHash );
});
service . on ( 'payment:failed' , ( event : PaymentEvent ) => {
console . error ( 'Payment failed:' , event . error );
});
Advanced Usage
SLA Enforcement
service . handlePayment < Input , Output >( async ( ctx ) => {
const startTime = Date . now ();
const SLA_MAX_LATENCY = 5000 ; // 5 seconds
try {
const result = await executeService ( ctx . input );
const latency = Date . now () - startTime ;
if ( latency > SLA_MAX_LATENCY ) {
// SLA violated - refund
await ctx . fail (
`SLA violation: latency ${ latency } ms exceeds ${ SLA_MAX_LATENCY } ms` ,
false
);
return ;
}
await ctx . deliver ({
result ,
latencyMs: latency ,
evidence: { slaCompliant: true }
});
} catch ( error ) {
await ctx . fail ( error . message , true );
}
});
Cryptographic Proof
import { ethers } from 'ethers' ;
service . handlePayment ( async ( ctx ) => {
const result = await executeService ( ctx . input );
// Generate cryptographic proof
const message = JSON . stringify ({
paymentId: ctx . paymentId ,
result ,
timestamp: Date . now ()
});
const signature = await wallet . signMessage ( message );
await ctx . deliver ({
result ,
proof: signature ,
evidence: {
message ,
signer: await wallet . getAddress ()
}
});
});
Rate Limiting
const rateLimiter = new Map < string , number >();
const RATE_LIMIT = 10 ; // requests per minute
service . handlePayment ( async ( ctx ) => {
const count = rateLimiter . get ( ctx . payerAddress ) || 0 ;
if ( count >= RATE_LIMIT ) {
return await ctx . fail (
'Rate limit exceeded: max 10 requests per minute' ,
true
);
}
rateLimiter . set ( ctx . payerAddress , count + 1 );
setTimeout (() => {
rateLimiter . delete ( ctx . payerAddress );
}, 60000 );
// Execute service...
});
Best Practices
1. Always Provide Proof
// ❌ Bad: No proof
await ctx . deliver ({ result });
// ✅ Good: With proof and evidence
await ctx . deliver ({
result ,
proof: signature ,
evidence: { sources , timestamp },
latencyMs: executionTime
});
2. Handle Errors Gracefully
try {
const result = await executeService ( ctx . input );
await ctx . deliver ({ result });
} catch ( error ) {
await ctx . fail (
error . message ,
error . code !== 'INVALID_INPUT' // retryable if not input error
);
}
3. Track Latency
const startTime = Date . now ();
const result = await executeService ( ctx . input );
const latencyMs = Date . now () - startTime ;
await ctx . deliver ({ result , latencyMs });
service . handlePayment ( async ( ctx ) => {
// Validate against schema
if ( ! validateInput ( ctx . input , inputSchema )) {
return await ctx . fail ( 'Invalid input schema' , false );
}
// Execute service...
});
Monetization
Pricing Strategies
// Fixed price per call
await service . register ({
price: '10000' // 0.01 USDC
});
// Dynamic pricing based on input
service . handlePayment ( async ( ctx ) => {
const basePrice = 10000 ;
const complexityMultiplier = ctx . input . leverage / 10 ;
const actualPrice = basePrice * complexityMultiplier ;
// Verify payment amount
if ( parseInt ( ctx . amount ) < actualPrice ) {
return await ctx . fail ( 'Insufficient payment' , false );
}
// Execute service...
});
Revenue Tracking
const metrics = await service . getMetrics ();
const revenueUSDC = parseInt ( metrics . totalRevenue ) / 1e6 ;
console . log ( 'Total Revenue:' , revenueUSDC . toFixed ( 2 ), 'USDC' );
console . log ( 'Avg Revenue per Call:' , ( revenueUSDC / metrics . totalCalls ). toFixed ( 4 ), 'USDC' );
Next Steps
Agent SDK Build agents that use your service
Session Management Accept session-based payments
x402 Protocol Understanding payment flow
Build Service Guide Complete tutorial