@relaycore/sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/PUBLISHING.md ADDED
@@ -0,0 +1,37 @@
1
+ # Publishing the Relay Core SDK
2
+
3
+ The SDK has been refactored to be self-contained and ready for the npm registry.
4
+
5
+ ## Prerequisites
6
+ 1. You need an npm account.
7
+ 2. You must belong to the `relaycore` organization on npm (or change the package name).
8
+
9
+ ## Steps
10
+
11
+ 1. **Login to npm**
12
+ ```bash
13
+ npm login
14
+ ```
15
+
16
+ 2. **Build the SDK**
17
+ Ensure dependencies are installed and build:
18
+ ```bash
19
+ cd src/sdk
20
+ npm install
21
+ npm run build
22
+ ```
23
+ *Success means you see `dist/` folder with .js and .d.ts files.*
24
+
25
+ 3. **Publish**
26
+ ```bash
27
+ npm publish --access public
28
+ ```
29
+
30
+ ## Troubleshooting
31
+ - **"You do not have permission to publish"**:
32
+ - Check if you are logged in: `npm whoami`
33
+ - Check if you own `@relaycore`. If not, change `"name"` in `package.json` to `@<your-username>/relaycore-sdk`.
34
+
35
+ - **Build fails**:
36
+ - Ensure all dependencies are installed (`npm install`).
37
+ - Check `tsup.config.ts` if new native dependencies are added.
package/README.md ADDED
@@ -0,0 +1,434 @@
1
+ # Relay Core SDK
2
+
3
+ TypeScript SDK for building AI agents and service providers on Relay Core. Provides agent discovery, x402 payment handling, session management, and service registration with production-grade error handling and observability.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @relaycore/sdk
9
+ ```
10
+
11
+ ## Agent SDK
12
+
13
+ The Agent SDK enables autonomous agents to discover services, manage payment sessions, and execute paid operations.
14
+
15
+ ### Basic Setup
16
+
17
+ ```typescript
18
+ import { RelayAgent, createAgent } from '@relaycore/sdk';
19
+
20
+ const agent = createAgent({
21
+ wallet: signer, // ethers.Signer from connected wallet
22
+ apiKey: "rc_test_...", // From Dashboard → API Keys
23
+ network: 'cronos-testnet',
24
+ });
25
+ ```
26
+
27
+ ### Service Discovery
28
+
29
+ ```typescript
30
+ const service = await agent.selectService({
31
+ category: 'data.prices',
32
+ constraints: {
33
+ minReputation: 90,
34
+ maxLatency: 200,
35
+ },
36
+ });
37
+ ```
38
+
39
+ ### Service Execution
40
+
41
+ ```typescript
42
+ const result = await agent.execute(service, { pair: 'BTC/USD' });
43
+
44
+ if (result.success) {
45
+ console.log('Price:', result.data);
46
+ console.log('Latency:', result.metrics.totalMs, 'ms');
47
+ } else {
48
+ console.log('Error:', result.error?.message);
49
+ }
50
+ ```
51
+
52
+ ### Session Management
53
+
54
+ **Create Session**
55
+ ```typescript
56
+ const { sessionId, paymentRequest } = await agent.createSession({
57
+ maxSpend: 10, // USDC
58
+ durationHours: 24,
59
+ authorizedAgents: [] // Optional: restrict to specific agents
60
+ });
61
+
62
+ console.log(`Session ID: ${sessionId}`);
63
+ console.log(`Pay ${paymentRequest.amount} USDC to ${paymentRequest.payTo}`);
64
+ ```
65
+
66
+ **Activate Session**
67
+ ```typescript
68
+ // After transferring USDC to paymentRequest.payTo
69
+ const activation = await agent.activateSession(
70
+ sessionId,
71
+ "0x...txHash...", // USDC transfer transaction hash
72
+ paymentRequest.amount
73
+ );
74
+
75
+ if (activation.success) {
76
+ console.log("Session activated");
77
+ }
78
+ ```
79
+
80
+ **Query Session**
81
+ ```typescript
82
+ const session = await agent.getSession(sessionId);
83
+ console.log(`Budget: ${session.maxSpend} USDC`);
84
+ console.log(`Spent: ${session.spent} USDC`);
85
+ console.log(`Remaining: ${Number(session.maxSpend) - Number(session.spent)} USDC`);
86
+ ```
87
+
88
+ ### Trust Policy
89
+
90
+ ```typescript
91
+ agent.setTrustPolicy({
92
+ minReputation: 85,
93
+ maxLatency: 500,
94
+ verifiedOnly: true,
95
+ blacklistedProviders: ['0x...'],
96
+ });
97
+ ```
98
+
99
+ ### Workflow Execution
100
+
101
+ ```typescript
102
+ const result = await agent.executeWorkflow([
103
+ { name: 'getPrice', criteria: { category: 'data.prices' } },
104
+ { name: 'validate', transform: (price) => price.value > 0 ? price : null },
105
+ { name: 'trade', criteria: { category: 'trading.execution' } },
106
+ ], { pair: 'BTC/USD' });
107
+
108
+ console.log('Steps completed:', result.completedSteps);
109
+ console.log('Total time:', result.totalMs, 'ms');
110
+ ```
111
+
112
+ ### Outcome Tracking
113
+
114
+ ```typescript
115
+ agent.onOutcome((outcome) => {
116
+ console.log(`Service ${outcome.serviceId}: ${outcome.success ? 'success' : 'failure'}`);
117
+ });
118
+
119
+ const stats = agent.memory.getStats();
120
+ console.log('Success rate:', stats.successRate);
121
+ ```
122
+
123
+ ### Agent Discovery
124
+
125
+ **Discover Single Agent**
126
+ ```typescript
127
+ const card = await agent.discoverAgentCard('https://perpai.relaycore.xyz');
128
+
129
+ if (card) {
130
+ console.log('Agent:', card.name);
131
+ console.log('Capabilities:', card.capabilities);
132
+
133
+ card.resources.forEach(resource => {
134
+ console.log(`${resource.title}: ${resource.url}`);
135
+ console.log(` Price: ${resource.price}`);
136
+ console.log(` Settlement: ${resource.paywall.settlement}`);
137
+ });
138
+ }
139
+ ```
140
+
141
+ **Discover Multiple Agents**
142
+ ```typescript
143
+ const agents = await agent.discoverRemoteAgents([
144
+ 'https://perpai.relaycore.xyz',
145
+ 'https://rwa.relaycore.xyz',
146
+ 'https://treasury.relaycore.xyz',
147
+ ]);
148
+
149
+ const onlineAgents = agents.filter(a => a.online);
150
+ console.log(`${onlineAgents.length}/${agents.length} agents online`);
151
+ ```
152
+
153
+ **Get Local Agent Card**
154
+ ```typescript
155
+ const localCard = await agent.getAgentCard();
156
+ console.log('Local resources:', localCard.resources.length);
157
+ ```
158
+
159
+ ### Task Artifacts
160
+
161
+ **Create Task**
162
+ ```typescript
163
+ const task = await agent.createTask({
164
+ service_id: 'perpai-quote',
165
+ inputs: { pair: 'BTC/USD', size: 1000 },
166
+ });
167
+ console.log('Task ID:', task.task_id);
168
+ ```
169
+
170
+ **Settle Task**
171
+ ```typescript
172
+ const result = await agent.execute(service, { pair: 'BTC/USD' });
173
+
174
+ if (result.success) {
175
+ await agent.settleTask(task.task_id, result.data, {
176
+ total_ms: result.metrics.totalMs,
177
+ payment_ms: result.metrics.paymentMs,
178
+ service_ms: result.metrics.serviceMs,
179
+ });
180
+ } else {
181
+ await agent.failTask(task.task_id, {
182
+ code: result.error?.code || 'UNKNOWN',
183
+ message: result.error?.message || 'Unknown error',
184
+ retryable: result.error?.retryable || false,
185
+ });
186
+ }
187
+ ```
188
+
189
+ **Query Tasks**
190
+ ```typescript
191
+ const tasks = await agent.getTasks({
192
+ state: 'settled',
193
+ from: new Date(Date.now() - 24 * 60 * 60 * 1000), // Last 24 hours
194
+ limit: 50,
195
+ });
196
+ console.log('Completed tasks:', tasks.length);
197
+
198
+ const stats = await agent.getTaskStats();
199
+ console.log('Success rate:', (stats.success_rate * 100).toFixed(1) + '%');
200
+ console.log('Avg duration:', stats.avg_duration_ms + 'ms');
201
+ ```
202
+
203
+ ## Service SDK
204
+
205
+ The Service SDK enables service providers to register services, handle x402 payments, and record delivery proofs.
206
+
207
+ ### Service Definition
208
+
209
+ ```typescript
210
+ import { RelayService, createService, defineService, hashProof } from '@relaycore/sdk';
211
+
212
+ const myService = defineService({
213
+ name: 'price-feed',
214
+ category: 'data.prices',
215
+ price: '0.01', // USDC per call
216
+ inputType: 'PriceQuery',
217
+ outputType: 'PriceData',
218
+ tags: ['prices', 'real-time', 'crypto'],
219
+ });
220
+ ```
221
+
222
+ ### Service Registration
223
+
224
+ ```typescript
225
+ const provider = createService({
226
+ wallet: signer, // ethers.Signer
227
+ network: 'cronos-testnet',
228
+ });
229
+
230
+ const registered = await provider.register(myService);
231
+ console.log('Service ID:', registered.id);
232
+ ```
233
+
234
+ ### Payment Handling
235
+
236
+ **Manual Payment Check**
237
+ ```typescript
238
+ app.use('/api/price', async (req, res, next) => {
239
+ const paymentId = req.headers['x-payment-id'];
240
+
241
+ if (!paymentId) {
242
+ const requirements = await provider.createPaymentRequired({
243
+ amount: '0.01',
244
+ description: 'Price feed access',
245
+ });
246
+ return res.status(402).json(requirements);
247
+ }
248
+
249
+ const { verified } = await provider.verifyPayment(paymentId);
250
+ if (!verified) {
251
+ return res.status(402).json({ error: 'Payment not verified' });
252
+ }
253
+
254
+ next();
255
+ });
256
+ ```
257
+
258
+ **Delivery with Proof**
259
+ ```typescript
260
+ app.get('/api/price', async (req, res) => {
261
+ const startTime = Date.now();
262
+
263
+ const result = { price: 42000.50, pair: 'BTC/USD', timestamp: Date.now() };
264
+
265
+ await provider.recordDelivery(req.headers['x-payment-id'], {
266
+ result,
267
+ proof: hashProof(result),
268
+ latencyMs: Date.now() - startTime,
269
+ });
270
+
271
+ res.json(result);
272
+ });
273
+ ```
274
+
275
+ ### Middleware Helper
276
+
277
+ ```typescript
278
+ import { createPaymentMiddleware } from '@relaycore/sdk';
279
+
280
+ const paymentRequired = createPaymentMiddleware(provider, {
281
+ amount: '0.01',
282
+ description: 'API access',
283
+ });
284
+
285
+ app.use('/api/protected', paymentRequired, (req, res) => {
286
+ res.json({ data: 'protected data' });
287
+ });
288
+ ```
289
+
290
+ ### Payment Event Handlers
291
+
292
+ ```typescript
293
+ provider.onPaymentReceived(async (ctx) => {
294
+ console.log('Payment received:', ctx.paymentId, ctx.amount, 'USDC');
295
+
296
+ const result = await processRequest(ctx.input);
297
+
298
+ ctx.deliver({
299
+ result,
300
+ proof: hashProof(result),
301
+ });
302
+ });
303
+
304
+ provider.onPaymentFailed(async (event) => {
305
+ console.log('Payment failed:', event.paymentId, event.error);
306
+ });
307
+ ```
308
+
309
+ ### Reputation and Metrics
310
+
311
+ **Check Reputation**
312
+ ```typescript
313
+ const reputation = await provider.getReputation();
314
+ console.log('Score:', reputation.reputationScore);
315
+ console.log('Success rate:', reputation.successRate);
316
+ console.log('Trend:', reputation.trend);
317
+ ```
318
+
319
+ **View Metrics**
320
+ ```typescript
321
+ const metrics = await provider.getMetrics(serviceId, {
322
+ from: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000), // Last 7 days
323
+ interval: '1d',
324
+ });
325
+
326
+ metrics.forEach((m) => {
327
+ console.log(`${m.timestamp}: ${m.totalCalls} calls, ${m.successRate}% success`);
328
+ });
329
+ ```
330
+
331
+ ## x402 Protocol Implementation
332
+
333
+ ### Protecting Routes
334
+
335
+ ```typescript
336
+ import { requireX402 } from '@relaycore/sdk';
337
+
338
+ router.get('/premium-data',
339
+ requireX402({
340
+ network: 'cronos-testnet',
341
+ payTo: '0xYourMerchantAddress',
342
+ asset: '0xUSDCAddress',
343
+ maxAmountRequired: '1000000', // 1 USDC
344
+ description: 'Access to premium data feed',
345
+ resource: '/api/premium-data',
346
+ }),
347
+ (req, res) => {
348
+ res.json({ data: 'Premium content' });
349
+ }
350
+ );
351
+ ```
352
+
353
+ ### Settlement Endpoint
354
+
355
+ ```typescript
356
+ import { handleX402Settlement, Facilitator } from '@relaycore/sdk';
357
+
358
+ router.post('/pay', async (req, res) => {
359
+ const { paymentId, paymentHeader, paymentRequirements } = req.body;
360
+
361
+ const facilitator = new Facilitator({ network: 'cronos-testnet' });
362
+
363
+ const result = await handleX402Settlement({
364
+ facilitator,
365
+ paymentId,
366
+ paymentHeader,
367
+ paymentRequirements,
368
+ });
369
+
370
+ if (!result.ok) {
371
+ return res.status(400).json(result);
372
+ }
373
+
374
+ res.json({ success: true, txHash: result.txHash });
375
+ });
376
+ ```
377
+
378
+ ### x402 Flow
379
+
380
+ 1. Client requests protected resource
381
+ 2. Server returns 402 Payment Required with payment requirements
382
+ 3. Client creates EIP-3009 authorization
383
+ 4. Client submits payment to settlement endpoint
384
+ 5. Server verifies and settles via Facilitator
385
+ 6. Client retries with x-payment-id header
386
+ 7. Server returns protected content
387
+
388
+ ## Error Handling
389
+
390
+ Both SDKs use structured errors for programmatic handling:
391
+
392
+ ```typescript
393
+ const result = await agent.execute(service, input);
394
+
395
+ if (!result.success) {
396
+ switch (result.error?.code) {
397
+ case 'SERVICE_NOT_FOUND':
398
+ console.log('Service not found');
399
+ break;
400
+ case 'PAYMENT_FAILED':
401
+ console.log('Payment failed, check balance');
402
+ break;
403
+ case 'RATE_LIMITED':
404
+ await sleep(result.error.retryAfterMs);
405
+ // Retry
406
+ break;
407
+ case 'EXECUTION_TIMEOUT':
408
+ // Retry with longer timeout
409
+ break;
410
+ default:
411
+ console.log(result.error?.message);
412
+ }
413
+ }
414
+ ```
415
+
416
+ ## Network Configuration
417
+
418
+ | Network | Chain ID | Description |
419
+ |---------|----------|-------------|
420
+ | `cronos-mainnet` | 25 | Cronos EVM Mainnet |
421
+ | `cronos-testnet` | 338 | Cronos EVM Testnet |
422
+ | `cronos-zkevm` | 388 | Cronos zkEVM Mainnet |
423
+
424
+ ## Design Principles
425
+
426
+ 1. **Progressive Configuration**: Start simple, add options as needed
427
+ 2. **Explicit Payments**: No magic, full visibility into payment flow
428
+ 3. **Proof of Delivery**: Every outcome has a hash for verification
429
+ 4. **Structured Errors**: Retryable vs terminal, with explanations
430
+ 5. **Built-in Observability**: Logs, metrics, and stats out of the box
431
+
432
+ ## License
433
+
434
+ MIT