uvd-x402-sdk 2.16.2 → 2.17.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.
Files changed (57) hide show
  1. package/README.md +70 -5
  2. package/dist/adapters/index.js +103 -0
  3. package/dist/adapters/index.js.map +1 -1
  4. package/dist/adapters/index.mjs +103 -0
  5. package/dist/adapters/index.mjs.map +1 -1
  6. package/dist/backend/index.d.mts +392 -2
  7. package/dist/backend/index.d.ts +392 -2
  8. package/dist/backend/index.js +448 -0
  9. package/dist/backend/index.js.map +1 -1
  10. package/dist/backend/index.mjs +445 -1
  11. package/dist/backend/index.mjs.map +1 -1
  12. package/dist/{index-oE4dj05k.d.mts → index-BDLgm-Sg.d.mts} +3 -2
  13. package/dist/{index-B2cQzyKa.d.ts → index-DDrvK4em.d.ts} +3 -2
  14. package/dist/index.d.mts +1 -1
  15. package/dist/index.d.ts +1 -1
  16. package/dist/index.js +103 -0
  17. package/dist/index.js.map +1 -1
  18. package/dist/index.mjs +103 -0
  19. package/dist/index.mjs.map +1 -1
  20. package/dist/providers/algorand/index.js +103 -0
  21. package/dist/providers/algorand/index.js.map +1 -1
  22. package/dist/providers/algorand/index.mjs +103 -0
  23. package/dist/providers/algorand/index.mjs.map +1 -1
  24. package/dist/providers/evm/index.js +103 -0
  25. package/dist/providers/evm/index.js.map +1 -1
  26. package/dist/providers/evm/index.mjs +103 -0
  27. package/dist/providers/evm/index.mjs.map +1 -1
  28. package/dist/providers/near/index.js +103 -0
  29. package/dist/providers/near/index.js.map +1 -1
  30. package/dist/providers/near/index.mjs +103 -0
  31. package/dist/providers/near/index.mjs.map +1 -1
  32. package/dist/providers/solana/index.js +103 -0
  33. package/dist/providers/solana/index.js.map +1 -1
  34. package/dist/providers/solana/index.mjs +103 -0
  35. package/dist/providers/solana/index.mjs.map +1 -1
  36. package/dist/providers/stellar/index.js +103 -0
  37. package/dist/providers/stellar/index.js.map +1 -1
  38. package/dist/providers/stellar/index.mjs +103 -0
  39. package/dist/providers/stellar/index.mjs.map +1 -1
  40. package/dist/providers/sui/index.js +103 -0
  41. package/dist/providers/sui/index.js.map +1 -1
  42. package/dist/providers/sui/index.mjs +103 -0
  43. package/dist/providers/sui/index.mjs.map +1 -1
  44. package/dist/react/index.d.mts +1 -1
  45. package/dist/react/index.d.ts +1 -1
  46. package/dist/react/index.js +103 -0
  47. package/dist/react/index.js.map +1 -1
  48. package/dist/react/index.mjs +103 -0
  49. package/dist/react/index.mjs.map +1 -1
  50. package/dist/utils/index.js +103 -0
  51. package/dist/utils/index.js.map +1 -1
  52. package/dist/utils/index.mjs +103 -0
  53. package/dist/utils/index.mjs.map +1 -1
  54. package/package.json +9 -3
  55. package/src/backend/index.ts +695 -1
  56. package/src/chains/index.ts +102 -2
  57. package/src/types/index.ts +3 -0
@@ -746,10 +746,14 @@ export type BazaarNetwork =
746
746
  | 'hyperevm'
747
747
  | 'unichain'
748
748
  | 'monad'
749
+ | 'scroll'
750
+ | 'skale'
749
751
  | 'solana'
750
752
  | 'fogo'
751
753
  | 'stellar'
752
- | 'near';
754
+ | 'near'
755
+ | 'algorand'
756
+ | 'sui';
753
757
 
754
758
  /**
755
759
  * Token/asset filter for discovery
@@ -2129,3 +2133,693 @@ export function isEscrowExpired(escrow: EscrowPayment): boolean {
2129
2133
  export function escrowTimeRemaining(escrow: EscrowPayment): number {
2130
2134
  return new Date(escrow.expiresAt).getTime() - Date.now();
2131
2135
  }
2136
+
2137
+ // ============================================================================
2138
+ // ERC-8004 TRUSTLESS AGENTS
2139
+ // ============================================================================
2140
+
2141
+ /**
2142
+ * ERC-8004 extension identifier
2143
+ */
2144
+ export const ERC8004_EXTENSION_ID = '8004-reputation';
2145
+
2146
+ /**
2147
+ * ERC-8004 contract addresses per network
2148
+ */
2149
+ export const ERC8004_CONTRACTS: Record<string, {
2150
+ identityRegistry?: string;
2151
+ reputationRegistry?: string;
2152
+ validationRegistry?: string;
2153
+ }> = {
2154
+ ethereum: {
2155
+ identityRegistry: '0x8004A169FB4a3325136EB29fA0ceB6D2e539a432',
2156
+ reputationRegistry: '0x8004BAa17C55a88189AE136b182e5fdA19dE9b63',
2157
+ },
2158
+ 'ethereum-sepolia': {
2159
+ identityRegistry: '0x8004A818BFB912233c491871b3d84c89A494BD9e',
2160
+ reputationRegistry: '0x8004B663056A597Dffe9eCcC1965A193B7388713',
2161
+ validationRegistry: '0x8004Cb1BF31DAf7788923b405b754f57acEB4272',
2162
+ },
2163
+ };
2164
+
2165
+ /**
2166
+ * Network type for ERC-8004 operations
2167
+ */
2168
+ export type Erc8004Network = 'ethereum' | 'ethereum-sepolia';
2169
+
2170
+ /**
2171
+ * Proof of payment returned when settling with ERC-8004 extension
2172
+ */
2173
+ export interface ProofOfPayment {
2174
+ /** Transaction hash of the settled payment */
2175
+ transactionHash: string;
2176
+ /** Block number where the transaction was included */
2177
+ blockNumber: number;
2178
+ /** Network where the payment was settled */
2179
+ network: string;
2180
+ /** The payer (consumer/client) address */
2181
+ payer: string;
2182
+ /** The payee (agent/resource owner) address */
2183
+ payee: string;
2184
+ /** Amount paid in token base units */
2185
+ amount: string;
2186
+ /** Token contract address */
2187
+ token: string;
2188
+ /** Unix timestamp of the block */
2189
+ timestamp: number;
2190
+ /** Keccak256 hash of the payment data for verification */
2191
+ paymentHash: string;
2192
+ }
2193
+
2194
+ /**
2195
+ * Extended settle response with ERC-8004 proof of payment
2196
+ */
2197
+ export interface SettleResponseWithProof extends SettleResponse {
2198
+ /** Proof of payment for ERC-8004 reputation submission */
2199
+ proofOfPayment?: ProofOfPayment;
2200
+ }
2201
+
2202
+ /**
2203
+ * Agent identity from the Identity Registry
2204
+ */
2205
+ export interface AgentIdentity {
2206
+ /** The agent's ID (ERC-721 tokenId) */
2207
+ agentId: number;
2208
+ /** Owner address of the agent NFT */
2209
+ owner: string;
2210
+ /** URI pointing to agent registration file */
2211
+ agentUri: string;
2212
+ /** Payment wallet address (if set) */
2213
+ agentWallet?: string;
2214
+ /** Network where the agent is registered */
2215
+ network: Erc8004Network;
2216
+ }
2217
+
2218
+ /**
2219
+ * Agent registration file structure (resolved from agentURI)
2220
+ */
2221
+ export interface AgentRegistrationFile {
2222
+ /** Type identifier */
2223
+ type: string;
2224
+ /** Agent name */
2225
+ name: string;
2226
+ /** Agent description */
2227
+ description: string;
2228
+ /** Image URL */
2229
+ image?: string;
2230
+ /** List of services the agent provides */
2231
+ services: AgentService[];
2232
+ /** Whether x402 payments are supported */
2233
+ x402Support: boolean;
2234
+ /** Whether the agent is active */
2235
+ active: boolean;
2236
+ /** List of registrations across chains */
2237
+ registrations: AgentRegistration[];
2238
+ /** Supported trust models */
2239
+ supportedTrust: string[];
2240
+ }
2241
+
2242
+ /**
2243
+ * Agent service entry
2244
+ */
2245
+ export interface AgentService {
2246
+ name: string;
2247
+ endpoint: string;
2248
+ version?: string;
2249
+ }
2250
+
2251
+ /**
2252
+ * Agent registration reference
2253
+ */
2254
+ export interface AgentRegistration {
2255
+ agentId: number;
2256
+ agentRegistry: string; // Format: {namespace}:{chainId}:{address}
2257
+ }
2258
+
2259
+ /**
2260
+ * Reputation summary for an agent
2261
+ */
2262
+ export interface ReputationSummary {
2263
+ /** Agent ID */
2264
+ agentId: number;
2265
+ /** Number of feedback entries */
2266
+ count: number;
2267
+ /** Aggregated value */
2268
+ summaryValue: number;
2269
+ /** Decimal places for summaryValue */
2270
+ summaryValueDecimals: number;
2271
+ /** Network */
2272
+ network: Erc8004Network;
2273
+ }
2274
+
2275
+ /**
2276
+ * Individual feedback entry
2277
+ */
2278
+ export interface FeedbackEntry {
2279
+ /** Client who submitted the feedback */
2280
+ client: string;
2281
+ /** Feedback index (1-indexed) */
2282
+ feedbackIndex: number;
2283
+ /** Feedback value */
2284
+ value: number;
2285
+ /** Value decimals */
2286
+ valueDecimals: number;
2287
+ /** Primary tag */
2288
+ tag1: string;
2289
+ /** Secondary tag */
2290
+ tag2: string;
2291
+ /** Whether this feedback was revoked */
2292
+ isRevoked: boolean;
2293
+ }
2294
+
2295
+ /**
2296
+ * Parameters for submitting reputation feedback
2297
+ */
2298
+ export interface FeedbackParams {
2299
+ /** The agent's ID (tokenId in Identity Registry) */
2300
+ agentId: number;
2301
+ /** Feedback value (e.g., 87 for 87/100) */
2302
+ value: number;
2303
+ /** Decimal places for value interpretation (0-18) */
2304
+ valueDecimals?: number;
2305
+ /** Primary categorization tag (e.g., "starred", "uptime") */
2306
+ tag1?: string;
2307
+ /** Secondary categorization tag */
2308
+ tag2?: string;
2309
+ /** Service endpoint that was used */
2310
+ endpoint?: string;
2311
+ /** URI to off-chain feedback file (IPFS, HTTPS) */
2312
+ feedbackUri?: string;
2313
+ /** Keccak256 hash of feedback content (for integrity) */
2314
+ feedbackHash?: string;
2315
+ /** Proof of payment (required for authorized feedback) */
2316
+ proof?: ProofOfPayment;
2317
+ }
2318
+
2319
+ /**
2320
+ * Feedback request body for POST /feedback
2321
+ */
2322
+ export interface FeedbackRequest {
2323
+ /** x402 protocol version */
2324
+ x402Version: 1 | 2;
2325
+ /** Network where feedback will be submitted */
2326
+ network: Erc8004Network;
2327
+ /** Feedback parameters */
2328
+ feedback: FeedbackParams;
2329
+ }
2330
+
2331
+ /**
2332
+ * Feedback response from POST /feedback
2333
+ */
2334
+ export interface FeedbackResponse {
2335
+ /** Whether the feedback was successfully submitted */
2336
+ success: boolean;
2337
+ /** Transaction hash of the feedback submission */
2338
+ transaction?: string;
2339
+ /** Feedback index assigned (1-indexed) */
2340
+ feedbackIndex?: number;
2341
+ /** Error message (if failed) */
2342
+ error?: string;
2343
+ /** Network where feedback was submitted */
2344
+ network: Erc8004Network;
2345
+ }
2346
+
2347
+ /**
2348
+ * Reputation query response
2349
+ */
2350
+ export interface ReputationResponse {
2351
+ agentId: number;
2352
+ summary: ReputationSummary;
2353
+ feedback?: FeedbackEntry[];
2354
+ network: Erc8004Network;
2355
+ }
2356
+
2357
+ /**
2358
+ * Options for the ERC8004Client
2359
+ */
2360
+ export interface Erc8004ClientOptions {
2361
+ /** Base URL of the facilitator (default: https://facilitator.ultravioletadao.xyz) */
2362
+ baseUrl?: string;
2363
+ /** Request timeout in milliseconds (default: 30000) */
2364
+ timeout?: number;
2365
+ }
2366
+
2367
+ /**
2368
+ * Client for ERC-8004 Trustless Agents API
2369
+ *
2370
+ * Provides methods for:
2371
+ * - Querying agent identity
2372
+ * - Querying agent reputation
2373
+ * - Submitting reputation feedback
2374
+ * - Revoking feedback
2375
+ *
2376
+ * @example
2377
+ * ```ts
2378
+ * const client = new Erc8004Client();
2379
+ *
2380
+ * // Get agent identity
2381
+ * const identity = await client.getIdentity('ethereum', 42);
2382
+ * console.log(identity.agentUri);
2383
+ *
2384
+ * // Get agent reputation
2385
+ * const reputation = await client.getReputation('ethereum', 42);
2386
+ * console.log(`Score: ${reputation.summary.summaryValue}`);
2387
+ *
2388
+ * // Submit feedback after payment
2389
+ * const result = await client.submitFeedback({
2390
+ * x402Version: 1,
2391
+ * network: 'ethereum',
2392
+ * feedback: {
2393
+ * agentId: 42,
2394
+ * value: 95,
2395
+ * valueDecimals: 0,
2396
+ * tag1: 'quality',
2397
+ * proof: settleResponse.proofOfPayment,
2398
+ * },
2399
+ * });
2400
+ * ```
2401
+ */
2402
+ export class Erc8004Client {
2403
+ private readonly baseUrl: string;
2404
+ private readonly timeout: number;
2405
+
2406
+ constructor(options: Erc8004ClientOptions = {}) {
2407
+ this.baseUrl = options.baseUrl || 'https://facilitator.ultravioletadao.xyz';
2408
+ this.timeout = options.timeout || 30000;
2409
+ }
2410
+
2411
+ /**
2412
+ * Get agent identity from the Identity Registry
2413
+ *
2414
+ * @param network - Network where agent is registered
2415
+ * @param agentId - Agent's tokenId
2416
+ * @returns Agent identity information
2417
+ */
2418
+ async getIdentity(network: Erc8004Network, agentId: number): Promise<AgentIdentity> {
2419
+ const url = `${this.baseUrl}/identity/${network}/${agentId}`;
2420
+
2421
+ const controller = new AbortController();
2422
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
2423
+
2424
+ try {
2425
+ const response = await fetch(url, {
2426
+ method: 'GET',
2427
+ headers: { 'Accept': 'application/json' },
2428
+ signal: controller.signal,
2429
+ });
2430
+
2431
+ clearTimeout(timeoutId);
2432
+
2433
+ if (!response.ok) {
2434
+ const errorText = await response.text();
2435
+ throw new Error(`ERC-8004 API error: ${response.status} - ${errorText}`);
2436
+ }
2437
+
2438
+ return await response.json();
2439
+ } catch (error) {
2440
+ clearTimeout(timeoutId);
2441
+ throw error;
2442
+ }
2443
+ }
2444
+
2445
+ /**
2446
+ * Resolve agent registration file from agentURI
2447
+ *
2448
+ * @param agentUri - URI pointing to agent registration file
2449
+ * @returns Resolved agent registration file
2450
+ */
2451
+ async resolveAgentUri(agentUri: string): Promise<AgentRegistrationFile> {
2452
+ const controller = new AbortController();
2453
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
2454
+
2455
+ try {
2456
+ // Handle IPFS URIs
2457
+ let url = agentUri;
2458
+ if (agentUri.startsWith('ipfs://')) {
2459
+ const cid = agentUri.replace('ipfs://', '');
2460
+ url = `https://ipfs.io/ipfs/${cid}`;
2461
+ }
2462
+
2463
+ const response = await fetch(url, {
2464
+ method: 'GET',
2465
+ headers: { 'Accept': 'application/json' },
2466
+ signal: controller.signal,
2467
+ });
2468
+
2469
+ clearTimeout(timeoutId);
2470
+
2471
+ if (!response.ok) {
2472
+ throw new Error(`Failed to resolve agentURI: ${response.status}`);
2473
+ }
2474
+
2475
+ return await response.json();
2476
+ } catch (error) {
2477
+ clearTimeout(timeoutId);
2478
+ throw error;
2479
+ }
2480
+ }
2481
+
2482
+ /**
2483
+ * Get agent reputation from the Reputation Registry
2484
+ *
2485
+ * @param network - Network where agent is registered
2486
+ * @param agentId - Agent's tokenId
2487
+ * @param options - Query options (tag filters, include individual feedback)
2488
+ * @returns Reputation summary and optionally individual feedback entries
2489
+ */
2490
+ async getReputation(
2491
+ network: Erc8004Network,
2492
+ agentId: number,
2493
+ options: {
2494
+ tag1?: string;
2495
+ tag2?: string;
2496
+ includeFeedback?: boolean;
2497
+ } = {}
2498
+ ): Promise<ReputationResponse> {
2499
+ const params = new URLSearchParams();
2500
+ if (options.tag1) params.set('tag1', options.tag1);
2501
+ if (options.tag2) params.set('tag2', options.tag2);
2502
+ if (options.includeFeedback) params.set('includeFeedback', 'true');
2503
+
2504
+ const url = `${this.baseUrl}/reputation/${network}/${agentId}${params.toString() ? `?${params}` : ''}`;
2505
+
2506
+ const controller = new AbortController();
2507
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
2508
+
2509
+ try {
2510
+ const response = await fetch(url, {
2511
+ method: 'GET',
2512
+ headers: { 'Accept': 'application/json' },
2513
+ signal: controller.signal,
2514
+ });
2515
+
2516
+ clearTimeout(timeoutId);
2517
+
2518
+ if (!response.ok) {
2519
+ const errorText = await response.text();
2520
+ throw new Error(`ERC-8004 API error: ${response.status} - ${errorText}`);
2521
+ }
2522
+
2523
+ return await response.json();
2524
+ } catch (error) {
2525
+ clearTimeout(timeoutId);
2526
+ throw error;
2527
+ }
2528
+ }
2529
+
2530
+ /**
2531
+ * Submit reputation feedback for an agent
2532
+ *
2533
+ * Requires proof of payment for authorized feedback submission.
2534
+ *
2535
+ * @param request - Feedback request with agent ID, value, and proof
2536
+ * @returns Feedback response with transaction hash
2537
+ *
2538
+ * @example
2539
+ * ```ts
2540
+ * // After settling a payment with ERC-8004 extension
2541
+ * const settleResult = await facilitator.settle(payment, {
2542
+ * ...requirements,
2543
+ * extra: { '8004-reputation': { includeProof: true } },
2544
+ * });
2545
+ *
2546
+ * // Submit feedback with proof of payment
2547
+ * const feedback = await erc8004.submitFeedback({
2548
+ * x402Version: 1,
2549
+ * network: 'ethereum',
2550
+ * feedback: {
2551
+ * agentId: 42,
2552
+ * value: 95, // 95/100
2553
+ * valueDecimals: 0,
2554
+ * tag1: 'quality',
2555
+ * tag2: 'response-time',
2556
+ * proof: settleResult.proofOfPayment,
2557
+ * },
2558
+ * });
2559
+ * ```
2560
+ */
2561
+ async submitFeedback(request: FeedbackRequest): Promise<FeedbackResponse> {
2562
+ const url = `${this.baseUrl}/feedback`;
2563
+
2564
+ const controller = new AbortController();
2565
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
2566
+
2567
+ try {
2568
+ const response = await fetch(url, {
2569
+ method: 'POST',
2570
+ headers: {
2571
+ 'Content-Type': 'application/json',
2572
+ 'Accept': 'application/json',
2573
+ },
2574
+ body: JSON.stringify(request),
2575
+ signal: controller.signal,
2576
+ });
2577
+
2578
+ clearTimeout(timeoutId);
2579
+
2580
+ if (!response.ok) {
2581
+ const errorText = await response.text();
2582
+ return {
2583
+ success: false,
2584
+ error: `Facilitator error: ${response.status} - ${errorText}`,
2585
+ network: request.network,
2586
+ };
2587
+ }
2588
+
2589
+ return await response.json();
2590
+ } catch (error) {
2591
+ clearTimeout(timeoutId);
2592
+ return {
2593
+ success: false,
2594
+ error: error instanceof Error ? error.message : 'Unknown error',
2595
+ network: request.network,
2596
+ };
2597
+ }
2598
+ }
2599
+
2600
+ /**
2601
+ * Revoke previously submitted feedback
2602
+ *
2603
+ * Only the original submitter can revoke their feedback.
2604
+ *
2605
+ * @param network - Network where feedback was submitted
2606
+ * @param agentId - Agent ID
2607
+ * @param feedbackIndex - Index of feedback to revoke
2608
+ * @returns Revocation result
2609
+ */
2610
+ async revokeFeedback(
2611
+ network: Erc8004Network,
2612
+ agentId: number,
2613
+ feedbackIndex: number
2614
+ ): Promise<FeedbackResponse> {
2615
+ const url = `${this.baseUrl}/feedback/revoke`;
2616
+
2617
+ const controller = new AbortController();
2618
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
2619
+
2620
+ try {
2621
+ const response = await fetch(url, {
2622
+ method: 'POST',
2623
+ headers: {
2624
+ 'Content-Type': 'application/json',
2625
+ 'Accept': 'application/json',
2626
+ },
2627
+ body: JSON.stringify({
2628
+ x402Version: 1,
2629
+ network,
2630
+ agentId,
2631
+ feedbackIndex,
2632
+ }),
2633
+ signal: controller.signal,
2634
+ });
2635
+
2636
+ clearTimeout(timeoutId);
2637
+
2638
+ if (!response.ok) {
2639
+ const errorText = await response.text();
2640
+ return {
2641
+ success: false,
2642
+ error: `Facilitator error: ${response.status} - ${errorText}`,
2643
+ network,
2644
+ };
2645
+ }
2646
+
2647
+ return await response.json();
2648
+ } catch (error) {
2649
+ clearTimeout(timeoutId);
2650
+ return {
2651
+ success: false,
2652
+ error: error instanceof Error ? error.message : 'Unknown error',
2653
+ network,
2654
+ };
2655
+ }
2656
+ }
2657
+
2658
+ /**
2659
+ * Get ERC-8004 contract addresses for a network
2660
+ *
2661
+ * @param network - Network to get contracts for
2662
+ * @returns Contract addresses or undefined if not deployed
2663
+ */
2664
+ getContracts(network: Erc8004Network): typeof ERC8004_CONTRACTS[Erc8004Network] | undefined {
2665
+ return ERC8004_CONTRACTS[network];
2666
+ }
2667
+
2668
+ /**
2669
+ * Check if ERC-8004 is available on a network
2670
+ *
2671
+ * @param network - Network to check
2672
+ * @returns True if ERC-8004 contracts are deployed
2673
+ */
2674
+ isAvailable(network: string): network is Erc8004Network {
2675
+ return network in ERC8004_CONTRACTS;
2676
+ }
2677
+
2678
+ /**
2679
+ * Get feedback endpoint metadata
2680
+ *
2681
+ * @returns Endpoint information for /feedback
2682
+ */
2683
+ async getFeedbackMetadata(): Promise<{
2684
+ endpoint: string;
2685
+ supportedNetworks: Erc8004Network[];
2686
+ version: string;
2687
+ }> {
2688
+ const url = `${this.baseUrl}/feedback`;
2689
+
2690
+ const controller = new AbortController();
2691
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
2692
+
2693
+ try {
2694
+ const response = await fetch(url, {
2695
+ method: 'GET',
2696
+ headers: { 'Accept': 'application/json' },
2697
+ signal: controller.signal,
2698
+ });
2699
+
2700
+ clearTimeout(timeoutId);
2701
+
2702
+ if (!response.ok) {
2703
+ throw new Error(`Failed to get feedback metadata: ${response.status}`);
2704
+ }
2705
+
2706
+ return await response.json();
2707
+ } catch (error) {
2708
+ clearTimeout(timeoutId);
2709
+ throw error;
2710
+ }
2711
+ }
2712
+
2713
+ /**
2714
+ * Append a response to existing feedback
2715
+ *
2716
+ * Allows agents to respond to feedback they received.
2717
+ * Only the agent (identity owner) can append responses.
2718
+ *
2719
+ * @param network - Network where feedback was submitted
2720
+ * @param agentId - Agent ID
2721
+ * @param feedbackIndex - Index of feedback to respond to
2722
+ * @param response - Response content
2723
+ * @param responseUri - Optional URI to off-chain response file
2724
+ * @returns Response result
2725
+ *
2726
+ * @example
2727
+ * ```ts
2728
+ * // Agent responds to feedback
2729
+ * const result = await erc8004.appendResponse(
2730
+ * 'ethereum',
2731
+ * 42,
2732
+ * 1,
2733
+ * 'Thank you for your feedback! We have addressed the issue.',
2734
+ * );
2735
+ * ```
2736
+ */
2737
+ async appendResponse(
2738
+ network: Erc8004Network,
2739
+ agentId: number,
2740
+ feedbackIndex: number,
2741
+ response: string,
2742
+ responseUri?: string
2743
+ ): Promise<FeedbackResponse> {
2744
+ const url = `${this.baseUrl}/feedback/response`;
2745
+
2746
+ const controller = new AbortController();
2747
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
2748
+
2749
+ try {
2750
+ const fetchResponse = await fetch(url, {
2751
+ method: 'POST',
2752
+ headers: {
2753
+ 'Content-Type': 'application/json',
2754
+ 'Accept': 'application/json',
2755
+ },
2756
+ body: JSON.stringify({
2757
+ x402Version: 1,
2758
+ network,
2759
+ agentId,
2760
+ feedbackIndex,
2761
+ response,
2762
+ responseUri,
2763
+ }),
2764
+ signal: controller.signal,
2765
+ });
2766
+
2767
+ clearTimeout(timeoutId);
2768
+
2769
+ if (!fetchResponse.ok) {
2770
+ const errorText = await fetchResponse.text();
2771
+ return {
2772
+ success: false,
2773
+ error: `Facilitator error: ${fetchResponse.status} - ${errorText}`,
2774
+ network,
2775
+ };
2776
+ }
2777
+
2778
+ return await fetchResponse.json();
2779
+ } catch (error) {
2780
+ clearTimeout(timeoutId);
2781
+ return {
2782
+ success: false,
2783
+ error: error instanceof Error ? error.message : 'Unknown error',
2784
+ network,
2785
+ };
2786
+ }
2787
+ }
2788
+ }
2789
+
2790
+ /**
2791
+ * Build payment requirements with ERC-8004 extension
2792
+ *
2793
+ * Adds the 8004-reputation extension to include proof of payment
2794
+ * in settlement responses for reputation submission.
2795
+ *
2796
+ * @param options - Base payment requirements options
2797
+ * @returns Payment requirements with ERC-8004 extension
2798
+ *
2799
+ * @example
2800
+ * ```ts
2801
+ * const requirements = buildErc8004PaymentRequirements({
2802
+ * amount: '1.00',
2803
+ * recipient: '0x...',
2804
+ * resource: 'https://api.example.com/service',
2805
+ * chainName: 'ethereum',
2806
+ * });
2807
+ *
2808
+ * // Settlement will include proofOfPayment
2809
+ * const result = await facilitator.settle(payment, requirements);
2810
+ * console.log(result.proofOfPayment);
2811
+ * ```
2812
+ */
2813
+ export function buildErc8004PaymentRequirements(
2814
+ options: PaymentRequirementsOptions
2815
+ ): PaymentRequirements & { extra: { '8004-reputation': { includeProof: boolean } } } {
2816
+ const base = buildPaymentRequirements(options);
2817
+ return {
2818
+ ...base,
2819
+ extra: {
2820
+ [ERC8004_EXTENSION_ID]: {
2821
+ includeProof: true,
2822
+ },
2823
+ },
2824
+ };
2825
+ }