@teneo-protocol/sdk 2.2.2 → 3.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.
Files changed (228) hide show
  1. package/.github/ISSUE_TEMPLATE/config.yml +1 -1
  2. package/CHANGELOG.md +366 -15
  3. package/CONCEPTS.md +182 -44
  4. package/README.md +524 -94
  5. package/dist/constants.d.ts +3 -1
  6. package/dist/constants.d.ts.map +1 -1
  7. package/dist/constants.js +5 -3
  8. package/dist/constants.js.map +1 -1
  9. package/dist/core/websocket-client.d.ts.map +1 -1
  10. package/dist/core/websocket-client.js +9 -5
  11. package/dist/core/websocket-client.js.map +1 -1
  12. package/dist/formatters/response-formatter.d.ts +6 -6
  13. package/dist/handlers/message-handlers/agent-details-response-handler.d.ts +756 -756
  14. package/dist/handlers/message-handlers/agent-details-response-handler.js +2 -2
  15. package/dist/handlers/message-handlers/agent-details-response-handler.js.map +1 -1
  16. package/dist/handlers/message-handlers/agent-error-handler.d.ts +91 -0
  17. package/dist/handlers/message-handlers/agent-error-handler.d.ts.map +1 -0
  18. package/dist/handlers/message-handlers/agent-error-handler.js +44 -0
  19. package/dist/handlers/message-handlers/agent-error-handler.js.map +1 -0
  20. package/dist/handlers/message-handlers/agent-selected-handler.d.ts +6 -0
  21. package/dist/handlers/message-handlers/agent-selected-handler.d.ts.map +1 -1
  22. package/dist/handlers/message-handlers/agent-status-update-handler.d.ts +756 -756
  23. package/dist/handlers/message-handlers/agent-status-update-handler.d.ts.map +1 -1
  24. package/dist/handlers/message-handlers/agent-status-update-handler.js +2 -7
  25. package/dist/handlers/message-handlers/agent-status-update-handler.js.map +1 -1
  26. package/dist/handlers/message-handlers/all-agents-response-handler.js +2 -2
  27. package/dist/handlers/message-handlers/all-agents-response-handler.js.map +1 -1
  28. package/dist/handlers/message-handlers/auth-error-handler.d.ts +6 -0
  29. package/dist/handlers/message-handlers/auth-error-handler.d.ts.map +1 -1
  30. package/dist/handlers/message-handlers/auth-message-handler.d.ts.map +1 -1
  31. package/dist/handlers/message-handlers/auth-message-handler.js +6 -1
  32. package/dist/handlers/message-handlers/auth-message-handler.js.map +1 -1
  33. package/dist/handlers/message-handlers/auth-required-handler.d.ts +6 -0
  34. package/dist/handlers/message-handlers/auth-required-handler.d.ts.map +1 -1
  35. package/dist/handlers/message-handlers/auth-success-handler.d.ts.map +1 -1
  36. package/dist/handlers/message-handlers/auth-success-handler.js +6 -1
  37. package/dist/handlers/message-handlers/auth-success-handler.js.map +1 -1
  38. package/dist/handlers/message-handlers/base-handler.d.ts +2 -1
  39. package/dist/handlers/message-handlers/base-handler.d.ts.map +1 -1
  40. package/dist/handlers/message-handlers/base-handler.js +24 -4
  41. package/dist/handlers/message-handlers/base-handler.js.map +1 -1
  42. package/dist/handlers/message-handlers/challenge-handler.d.ts +6 -0
  43. package/dist/handlers/message-handlers/challenge-handler.d.ts.map +1 -1
  44. package/dist/handlers/message-handlers/error-message-handler.d.ts +6 -0
  45. package/dist/handlers/message-handlers/error-message-handler.d.ts.map +1 -1
  46. package/dist/handlers/message-handlers/index.d.ts +4 -0
  47. package/dist/handlers/message-handlers/index.d.ts.map +1 -1
  48. package/dist/handlers/message-handlers/index.js +23 -1
  49. package/dist/handlers/message-handlers/index.js.map +1 -1
  50. package/dist/handlers/message-handlers/list-available-agents-handler.d.ts +792 -756
  51. package/dist/handlers/message-handlers/list-available-agents-handler.d.ts.map +1 -1
  52. package/dist/handlers/message-handlers/list-available-agents-handler.js +23 -10
  53. package/dist/handlers/message-handlers/list-available-agents-handler.js.map +1 -1
  54. package/dist/handlers/message-handlers/list-room-agents-handler.d.ts +756 -756
  55. package/dist/handlers/message-handlers/list-room-agents-handler.d.ts.map +1 -1
  56. package/dist/handlers/message-handlers/list-room-agents-handler.js +2 -6
  57. package/dist/handlers/message-handlers/list-room-agents-handler.js.map +1 -1
  58. package/dist/handlers/message-handlers/list-rooms-response-handler.d.ts.map +1 -1
  59. package/dist/handlers/message-handlers/list-rooms-response-handler.js +2 -5
  60. package/dist/handlers/message-handlers/list-rooms-response-handler.js.map +1 -1
  61. package/dist/handlers/message-handlers/ping-pong-handler.d.ts +52 -4
  62. package/dist/handlers/message-handlers/ping-pong-handler.d.ts.map +1 -1
  63. package/dist/handlers/message-handlers/ping-pong-handler.js +23 -4
  64. package/dist/handlers/message-handlers/ping-pong-handler.js.map +1 -1
  65. package/dist/handlers/message-handlers/rate-limit-notification-handler.d.ts.map +1 -1
  66. package/dist/handlers/message-handlers/rate-limit-notification-handler.js +3 -2
  67. package/dist/handlers/message-handlers/rate-limit-notification-handler.js.map +1 -1
  68. package/dist/handlers/message-handlers/regular-message-handler.d.ts +6 -0
  69. package/dist/handlers/message-handlers/regular-message-handler.d.ts.map +1 -1
  70. package/dist/handlers/message-handlers/subscribe-response-handler.d.ts +12 -6
  71. package/dist/handlers/message-handlers/subscribe-response-handler.d.ts.map +1 -1
  72. package/dist/handlers/message-handlers/success-handler.d.ts +82 -0
  73. package/dist/handlers/message-handlers/success-handler.d.ts.map +1 -0
  74. package/dist/handlers/message-handlers/success-handler.js +24 -0
  75. package/dist/handlers/message-handlers/success-handler.js.map +1 -0
  76. package/dist/handlers/message-handlers/task-confirmed-handler.d.ts +110 -0
  77. package/dist/handlers/message-handlers/task-confirmed-handler.d.ts.map +1 -0
  78. package/dist/handlers/message-handlers/task-confirmed-handler.js +46 -0
  79. package/dist/handlers/message-handlers/task-confirmed-handler.js.map +1 -0
  80. package/dist/handlers/message-handlers/trigger-wallet-tx-handler.d.ts +244 -0
  81. package/dist/handlers/message-handlers/trigger-wallet-tx-handler.d.ts.map +1 -0
  82. package/dist/handlers/message-handlers/trigger-wallet-tx-handler.js +58 -0
  83. package/dist/handlers/message-handlers/trigger-wallet-tx-handler.js.map +1 -0
  84. package/dist/handlers/message-handlers/unsubscribe-response-handler.d.ts +12 -6
  85. package/dist/handlers/message-handlers/unsubscribe-response-handler.d.ts.map +1 -1
  86. package/dist/handlers/message-handlers/user-authenticated-handler.js +2 -2
  87. package/dist/handlers/message-handlers/user-authenticated-handler.js.map +1 -1
  88. package/dist/handlers/message-handlers/user-count-handler.js +2 -2
  89. package/dist/handlers/message-handlers/user-count-handler.js.map +1 -1
  90. package/dist/index.d.ts +3 -3
  91. package/dist/index.d.ts.map +1 -1
  92. package/dist/index.js +11 -4
  93. package/dist/index.js.map +1 -1
  94. package/dist/managers/admin-manager.d.ts +2 -0
  95. package/dist/managers/admin-manager.d.ts.map +1 -1
  96. package/dist/managers/admin-manager.js +3 -2
  97. package/dist/managers/admin-manager.js.map +1 -1
  98. package/dist/managers/agent-room-manager.d.ts +89 -11
  99. package/dist/managers/agent-room-manager.d.ts.map +1 -1
  100. package/dist/managers/agent-room-manager.js +99 -35
  101. package/dist/managers/agent-room-manager.js.map +1 -1
  102. package/dist/managers/index.d.ts +1 -1
  103. package/dist/managers/index.d.ts.map +1 -1
  104. package/dist/managers/index.js.map +1 -1
  105. package/dist/managers/message-router.d.ts +45 -5
  106. package/dist/managers/message-router.d.ts.map +1 -1
  107. package/dist/managers/message-router.js +96 -24
  108. package/dist/managers/message-router.js.map +1 -1
  109. package/dist/managers/room-manager.d.ts +29 -7
  110. package/dist/managers/room-manager.d.ts.map +1 -1
  111. package/dist/managers/room-manager.js +37 -11
  112. package/dist/managers/room-manager.js.map +1 -1
  113. package/dist/payments/index.d.ts +3 -1
  114. package/dist/payments/index.d.ts.map +1 -1
  115. package/dist/payments/index.js +17 -3
  116. package/dist/payments/index.js.map +1 -1
  117. package/dist/payments/networks.d.ts +59 -0
  118. package/dist/payments/networks.d.ts.map +1 -0
  119. package/dist/payments/networks.js +192 -0
  120. package/dist/payments/networks.js.map +1 -0
  121. package/dist/payments/payment-client.d.ts +55 -10
  122. package/dist/payments/payment-client.d.ts.map +1 -1
  123. package/dist/payments/payment-client.js +172 -51
  124. package/dist/payments/payment-client.js.map +1 -1
  125. package/dist/teneo-sdk.d.ts +214 -40
  126. package/dist/teneo-sdk.d.ts.map +1 -1
  127. package/dist/teneo-sdk.js +360 -83
  128. package/dist/teneo-sdk.js.map +1 -1
  129. package/dist/types/config.d.ts +334 -25
  130. package/dist/types/config.d.ts.map +1 -1
  131. package/dist/types/config.js +114 -22
  132. package/dist/types/config.js.map +1 -1
  133. package/dist/types/events.d.ts +60 -14
  134. package/dist/types/events.d.ts.map +1 -1
  135. package/dist/types/events.js.map +1 -1
  136. package/dist/types/index.d.ts +1 -1
  137. package/dist/types/index.d.ts.map +1 -1
  138. package/dist/types/index.js +11 -4
  139. package/dist/types/index.js.map +1 -1
  140. package/dist/types/messages.d.ts +9801 -7222
  141. package/dist/types/messages.d.ts.map +1 -1
  142. package/dist/types/messages.js +180 -40
  143. package/dist/types/messages.js.map +1 -1
  144. package/dist/utils/pricing-resolver.d.ts +1 -1
  145. package/dist/utils/pricing-resolver.d.ts.map +1 -1
  146. package/dist/utils/pricing-resolver.js +9 -1
  147. package/dist/utils/pricing-resolver.js.map +1 -1
  148. package/examples/agent-room-management-example.ts +5 -5
  149. package/examples/basic-usage.ts +26 -6
  150. package/examples/claude-agent-x-follower/index.ts +1 -1
  151. package/examples/minimal-chat.ts +4 -3
  152. package/examples/n8n-teneo/index.ts +2 -2
  153. package/examples/nestjs-dashboard/README.md +1 -1
  154. package/examples/nestjs-dashboard/src/teneo/agents.controller.ts +3 -3
  155. package/examples/nestjs-dashboard/src/teneo/rooms.controller.ts +5 -5
  156. package/examples/nestjs-dashboard/src/teneo/teneo.service.ts +8 -8
  157. package/examples/openai-teneo/index.ts +1 -1
  158. package/examples/payment-flow.ts +143 -0
  159. package/examples/production-dashboard/README.md +6 -8
  160. package/examples/production-dashboard/server.ts +22 -10
  161. package/examples/room-management-example.ts +2 -2
  162. package/examples/usage/01-connect.ts +0 -3
  163. package/examples/usage/02-list-agents.ts +0 -2
  164. package/examples/usage/03-pick-agent.ts +3 -4
  165. package/examples/usage/04-find-by-capability.ts +10 -12
  166. package/examples/usage/05-webhook-example.ts +2 -4
  167. package/examples/usage/06-simple-api-server.ts +13 -9
  168. package/examples/usage/07-event-listener.ts +1 -13
  169. package/examples/usage/README.md +33 -7
  170. package/examples/webhook-integration.ts +9 -9
  171. package/examples/x-influencer-battle-server.ts +1 -1
  172. package/package.json +1 -1
  173. package/scripts/diagnose-connection.ts +86 -0
  174. package/scripts/investigate-payload.ts +163 -0
  175. package/scripts/list-agents.ts +58 -0
  176. package/scripts/live-multi-network-test.ts +230 -0
  177. package/src/constants.ts +5 -3
  178. package/src/core/websocket-client.ts +10 -9
  179. package/src/handlers/message-handlers/agent-details-response-handler.ts +2 -2
  180. package/src/handlers/message-handlers/agent-error-handler.ts +47 -0
  181. package/src/handlers/message-handlers/agent-status-update-handler.ts +2 -7
  182. package/src/handlers/message-handlers/all-agents-response-handler.ts +2 -2
  183. package/src/handlers/message-handlers/auth-message-handler.ts +7 -1
  184. package/src/handlers/message-handlers/auth-success-handler.ts +7 -1
  185. package/src/handlers/message-handlers/base-handler.ts +24 -4
  186. package/src/handlers/message-handlers/index.ts +24 -0
  187. package/src/handlers/message-handlers/list-available-agents-handler.ts +24 -11
  188. package/src/handlers/message-handlers/list-room-agents-handler.ts +2 -6
  189. package/src/handlers/message-handlers/list-rooms-response-handler.ts +2 -5
  190. package/src/handlers/message-handlers/ping-pong-handler.ts +29 -4
  191. package/src/handlers/message-handlers/rate-limit-notification-handler.ts +3 -2
  192. package/src/handlers/message-handlers/success-handler.ts +26 -0
  193. package/src/handlers/message-handlers/task-confirmed-handler.ts +49 -0
  194. package/src/handlers/message-handlers/trigger-wallet-tx-handler.ts +62 -0
  195. package/src/handlers/message-handlers/user-authenticated-handler.ts +2 -2
  196. package/src/handlers/message-handlers/user-count-handler.ts +2 -2
  197. package/src/index.ts +12 -4
  198. package/src/managers/admin-manager.ts +5 -2
  199. package/src/managers/agent-room-manager.ts +155 -26
  200. package/src/managers/index.ts +6 -1
  201. package/src/managers/message-router.ts +122 -27
  202. package/src/managers/room-manager.ts +39 -11
  203. package/src/payments/index.ts +20 -5
  204. package/src/payments/networks.ts +208 -0
  205. package/src/payments/payment-client.ts +211 -56
  206. package/src/teneo-sdk.ts +401 -70
  207. package/src/types/config.test.ts +24 -4
  208. package/src/types/config.ts +123 -25
  209. package/src/types/events.ts +36 -2
  210. package/src/types/index.ts +16 -3
  211. package/src/types/messages.ts +221 -57
  212. package/src/utils/pricing-resolver.ts +10 -2
  213. package/tests/direct-agent-test.ts +1 -1
  214. package/tests/integration/real-server.test.ts +1 -1
  215. package/tests/integration/websocket.test.ts +3 -3
  216. package/tests/multi-network-payment.test.ts +309 -0
  217. package/tests/multi-network.test.ts +296 -0
  218. package/tests/payment-flow-test.ts +6 -4
  219. package/tests/unit/handlers/agent-error-handler.test.ts +388 -0
  220. package/tests/unit/handlers/agent-room-operation-response-handler.test.ts +9 -6
  221. package/tests/unit/handlers/agent-status-update-handler.test.ts +11 -16
  222. package/tests/unit/handlers/list-available-agents-handler.test.ts +11 -14
  223. package/tests/unit/handlers/list-room-agents-handler.test.ts +11 -15
  224. package/tests/unit/handlers/room-operation-response-handler.test.ts +9 -6
  225. package/tests/unit/handlers/trigger-wallet-tx-handler.test.ts +431 -0
  226. package/tests/unit/managers/admin-manager.test.ts +183 -0
  227. package/tests/unit/managers/agent-room-manager.test.ts +189 -33
  228. package/tests/unit/sdk-new-methods.test.ts +221 -0
@@ -1,37 +1,21 @@
1
1
  /**
2
2
  * PaymentClient - Handles x402 payment header generation for quote-approve flow
3
3
  *
4
- * Creates x402 V2 payment headers for USDC payments on PEAQ network.
4
+ * Creates x402 V2 payment headers for USDC payments on multiple networks.
5
5
  * Implements ERC-3009 TransferWithAuthorization signing using viem's EIP-712.
6
+ *
7
+ * v2.3.0: Multi-network support with dynamic chain configuration
6
8
  */
7
9
 
8
- import { defineChain, type Hex, toHex } from "viem";
10
+ import { type Hex, toHex, keccak256, encodePacked } from "viem";
9
11
  import { privateKeyToAccount, signTypedData } from "viem/accounts";
10
12
  import type { SecurePrivateKey } from "../utils/secure-private-key";
11
-
12
- // PEAQ chain definition
13
- const peaq = defineChain({
14
- id: 3338,
15
- name: "peaq",
16
- network: "peaq",
17
- nativeCurrency: {
18
- decimals: 18,
19
- name: "PEAQ",
20
- symbol: "PEAQ"
21
- },
22
- rpcUrls: {
23
- default: {
24
- http: ["https://peaq.api.onfinality.io/public"]
25
- },
26
- public: {
27
- http: ["https://peaq.api.onfinality.io/public"]
28
- }
29
- }
30
- });
31
-
32
- // USDC contract on PEAQ
33
- const USDC_CONTRACT = "0xbbA60da06c2c5424f03f7434542280FCAd453d10";
34
- const PEAQ_NETWORK_CAIP2 = "eip155:3338";
13
+ import {
14
+ getNetwork,
15
+ getDefaultNetwork,
16
+ createChainDefinition,
17
+ type NetworkConfig
18
+ } from "./networks";
35
19
 
36
20
  // ERC-3009 TransferWithAuthorization EIP-712 types
37
21
  const ERC3009_TYPES = {
@@ -46,8 +30,9 @@ const ERC3009_TYPES = {
46
30
  } as const;
47
31
 
48
32
  export interface PaymentClientConfig {
49
- network?: string; // CAIP-2 format, default: "eip155:3338"
50
- asset?: string; // Asset contract, default: USDC on PEAQ
33
+ network?: string; // Network name (peaq, base, avalanche) or CAIP-2 format
34
+ networkChainId?: number; // Or chain ID directly
35
+ asset?: string; // Optional override for asset contract
51
36
  resourceUrl?: string; // x402 resource URL
52
37
  }
53
38
 
@@ -56,11 +41,10 @@ export const USDC_DECIMALS = 6;
56
41
  export const X402_VERSION = 2;
57
42
  export const DEFAULT_PAYMENT_TIMEOUT_SECONDS = 60;
58
43
  export const DEFAULT_PAY_TO_ADDRESS = "0x0000000000000000000000000000000000000000";
59
- export const DEFAULT_RPC_URL = "https://peaq.api.onfinality.io/public";
60
- export type SupportedChain = "peaq";
61
44
 
62
- // Re-export constants for external use
63
- export { USDC_CONTRACT, PEAQ_NETWORK_CAIP2 as PEAQ_CHAIN_ID };
45
+ // Re-export for backwards compatibility
46
+ export const USDC_CONTRACT = "0xbbA60da06c2c5424f03f7434542280FCAd453d10"; // PEAQ USDC
47
+ export const PEAQ_CHAIN_ID = "eip155:3338";
64
48
 
65
49
  /**
66
50
  * Converts a WebSocket URL to an HTTP(S) URL for x402 resource specification.
@@ -108,15 +92,71 @@ function generateNonce(): Hex {
108
92
  return toHex(randomBytes);
109
93
  }
110
94
 
95
+ /**
96
+ * Settlement data provided by backend in task_quote response.
97
+ * Used for x402x-router-settlement extension.
98
+ */
99
+ export interface SettlementData {
100
+ settlementRouter: string;
101
+ salt: string;
102
+ facilitatorFee: string;
103
+ hook: string;
104
+ hookData: string;
105
+ }
106
+
107
+ /**
108
+ * Validates that a string is a valid Ethereum address
109
+ * @param address - String to validate
110
+ * @returns True if valid Ethereum address format
111
+ */
112
+ function isValidEthereumAddress(address: string): boolean {
113
+ return /^0x[a-fA-F0-9]{40}$/.test(address);
114
+ }
115
+
116
+ /**
117
+ * Resolve network configuration from various input formats
118
+ *
119
+ * @param config - PaymentClientConfig with network options
120
+ * @returns Resolved NetworkConfig
121
+ */
122
+ function resolveNetworkConfig(config: PaymentClientConfig): NetworkConfig {
123
+ // Priority: chainId > network name > default
124
+ if (config.networkChainId) {
125
+ return getNetwork(config.networkChainId);
126
+ }
127
+ if (config.network) {
128
+ return getNetwork(config.network);
129
+ }
130
+ return getDefaultNetwork();
131
+ }
132
+
111
133
  /**
112
134
  * PaymentClient handles creation of x402 V2 payment headers
113
135
  * for the quote-approve payment flow.
136
+ *
137
+ * Supports multiple networks with dynamic configuration.
138
+ *
139
+ * @example
140
+ * ```typescript
141
+ * // Default network (PEAQ or TENEO_NETWORK env var)
142
+ * const client = new PaymentClient(secureKey, walletAddress);
143
+ *
144
+ * // Specific network by name
145
+ * const baseClient = new PaymentClient(secureKey, walletAddress, {
146
+ * network: "base"
147
+ * });
148
+ *
149
+ * // Specific network by chain ID
150
+ * const avaxClient = new PaymentClient(secureKey, walletAddress, {
151
+ * networkChainId: 43114
152
+ * });
153
+ * ```
114
154
  */
115
155
  export class PaymentClient {
116
156
  private readonly secureKey: SecurePrivateKey;
117
157
  private readonly walletAddress: string;
118
- private readonly network: string;
119
- private readonly asset: string;
158
+ private readonly networkConfig: NetworkConfig;
159
+ private readonly assetOverride?: string;
120
160
  private readonly resourceUrl: string;
121
161
 
122
162
  constructor(
@@ -124,29 +164,67 @@ export class PaymentClient {
124
164
  walletAddress: string,
125
165
  config: PaymentClientConfig = {}
126
166
  ) {
167
+ if (!isValidEthereumAddress(walletAddress)) {
168
+ throw new Error(`Invalid wallet address: ${walletAddress}`);
169
+ }
127
170
  this.secureKey = secureKey;
128
171
  this.walletAddress = walletAddress;
129
- this.network = config.network ?? PEAQ_NETWORK_CAIP2;
130
- this.asset = config.asset ?? USDC_CONTRACT;
172
+ this.networkConfig = resolveNetworkConfig(config);
173
+ this.assetOverride = config.asset;
131
174
  this.resourceUrl = config.resourceUrl ?? "";
132
175
  }
133
176
 
177
+ /**
178
+ * Get the current network configuration
179
+ */
180
+ get network(): NetworkConfig {
181
+ return this.networkConfig;
182
+ }
183
+
184
+ /**
185
+ * Get the USDC contract address for the current network
186
+ */
187
+ get asset(): string {
188
+ return this.assetOverride ?? this.networkConfig.usdcContract;
189
+ }
190
+
191
+ /**
192
+ * Get the CAIP-2 network identifier
193
+ */
194
+ get caip2(): string {
195
+ return this.networkConfig.caip2;
196
+ }
197
+
134
198
  /**
135
199
  * Creates an x402 V2 payment header for a specific amount and recipient.
136
200
  *
137
201
  * @param amountMicroUnits - Amount in micro-units (e.g., 1000 = 0.001 USDC)
138
202
  * @param recipientAddress - Wallet address of the payment recipient (agent)
139
203
  * @param resourceUrl - Optional override for x402 resource URL
204
+ * @param networkOverride - Optional network override for this specific payment
205
+ * @param settlementData - Backend-provided settlement data for x402x-router-settlement
140
206
  * @returns Base64 encoded x402 V2 payment header
141
207
  */
142
208
  async createPaymentHeader(
143
209
  amountMicroUnits: number,
144
210
  recipientAddress: string,
145
- resourceUrl?: string
211
+ resourceUrl?: string,
212
+ networkOverride?: string | number,
213
+ settlementData?: SettlementData
146
214
  ): Promise<string> {
215
+ if (!isValidEthereumAddress(recipientAddress)) {
216
+ throw new Error(`Invalid recipient address: ${recipientAddress}`);
217
+ }
147
218
  const resource = resourceUrl || this.resourceUrl || this.getDefaultResourceUrl();
148
219
  const amountStr = Math.round(amountMicroUnits).toString();
149
220
 
221
+ // Resolve network for this payment (allows per-request override)
222
+ const network = networkOverride ? getNetwork(networkOverride) : this.networkConfig;
223
+
224
+ // When using a per-request network override, always use that network's asset contract
225
+ const asset = networkOverride ? network.usdcContract : (this.assetOverride ?? network.usdcContract);
226
+ const chain = createChainDefinition(network);
227
+
150
228
  // Create payment header using the secure key
151
229
  const header = await this.secureKey.use(async (privateKey) => {
152
230
  const account = privateKeyToAccount(privateKey as `0x${string}`);
@@ -155,24 +233,70 @@ export class PaymentClient {
155
233
  const now = Math.floor(Date.now() / 1000);
156
234
  const validAfter = now - 60; // Valid from 60 seconds ago
157
235
  const validBefore = now + 60; // Valid until 60 seconds from now
158
- const nonce = generateNonce();
159
236
 
160
- // EIP-712 domain for USDC on PEAQ
237
+ // Use backend-provided settlement data or fall back to defaults
238
+ // CRITICAL: For x402x-router-settlement to work, we MUST use the values
239
+ // provided by the backend in the task_quote response
240
+ const salt = settlementData?.salt as Hex ?? generateNonce();
241
+ const facilitatorFee = settlementData?.facilitatorFee ?? "1000";
242
+ const hookData = (settlementData?.hookData ?? "0x") as Hex;
243
+ const settlementRouter = settlementData?.settlementRouter ?? network.settlementRouter;
244
+ const hook = settlementData?.hook ?? network.transferHook;
245
+
246
+ // Calculate commitment hash (becomes the EIP-3009 nonce)
247
+ // This cryptographically binds all settlement parameters to the signature
248
+ const commitment = keccak256(
249
+ encodePacked(
250
+ [
251
+ "string", // Protocol identifier
252
+ "uint256", // Chain ID
253
+ "address", // Hub (settlementRouter)
254
+ "address", // Token (USDC)
255
+ "address", // From (payer)
256
+ "uint256", // Value
257
+ "uint256", // Valid after
258
+ "uint256", // Valid before
259
+ "bytes32", // Salt
260
+ "address", // Pay to (final recipient)
261
+ "uint256", // Facilitator fee
262
+ "address", // Hook
263
+ "bytes32" // keccak256(hookData)
264
+ ],
265
+ [
266
+ "X402/settle/v1",
267
+ BigInt(chain.id),
268
+ settlementRouter as Hex,
269
+ asset as Hex,
270
+ account.address,
271
+ BigInt(amountStr),
272
+ BigInt(validAfter),
273
+ BigInt(validBefore),
274
+ salt as Hex,
275
+ recipientAddress as Hex,
276
+ BigInt(facilitatorFee),
277
+ hook as Hex,
278
+ keccak256(hookData)
279
+ ]
280
+ )
281
+ );
282
+
283
+ // EIP-712 domain using network-specific parameters
161
284
  const domain = {
162
- name: "USDC",
163
- version: "2",
164
- chainId: BigInt(peaq.id),
165
- verifyingContract: this.asset as `0x${string}`
285
+ name: network.eip712.name,
286
+ version: network.eip712.version,
287
+ chainId: BigInt(chain.id),
288
+ verifyingContract: asset as `0x${string}`
166
289
  };
167
290
 
168
291
  // ERC-3009 TransferWithAuthorization message
292
+ // x402x: "to" is settlementRouter, nonce is commitment hash
169
293
  const message = {
170
294
  from: account.address,
171
- to: recipientAddress as `0x${string}`,
295
+ to: settlementRouter as `0x${string}`, // Router receives funds first
172
296
  value: BigInt(amountStr),
173
297
  validAfter: BigInt(validAfter),
174
298
  validBefore: BigInt(validBefore),
175
- nonce: nonce
299
+ nonce: commitment // Commitment hash as nonce
176
300
  };
177
301
 
178
302
  // Sign the EIP-712 typed data
@@ -188,16 +312,19 @@ export class PaymentClient {
188
312
  const v1Payload = {
189
313
  authorization: {
190
314
  from: account.address,
191
- to: recipientAddress,
315
+ to: settlementRouter, // Router address
192
316
  value: amountStr,
193
317
  validAfter: validAfter.toString(),
194
318
  validBefore: validBefore.toString(),
195
- nonce: nonce
319
+ nonce: commitment // Commitment hash
196
320
  },
197
321
  signature: signature
198
322
  };
199
323
 
200
- // Build V2 payload (what the backend expects)
324
+ // Convert facilitator fee to hex format (required by facilitator)
325
+ const facilitatorFeeHex = `0x${BigInt(facilitatorFee).toString(16)}`;
326
+
327
+ // Build V2 payload with x402x-router-settlement extension
201
328
  const v2Payload = {
202
329
  x402Version: 2,
203
330
  resource: {
@@ -207,14 +334,37 @@ export class PaymentClient {
207
334
  },
208
335
  accepted: {
209
336
  scheme: "exact",
210
- network: this.network,
337
+ network: network.caip2,
211
338
  amount: amountStr,
212
- asset: this.asset,
213
- payTo: recipientAddress,
339
+ asset: asset,
340
+ payTo: recipientAddress, // Final recipient (for display)
214
341
  maxTimeoutSeconds: 60,
215
- extra: { name: "USDC", version: "2" }
342
+ extra: {
343
+ name: network.eip712.name,
344
+ version: network.eip712.version,
345
+ // Settlement router info - MUST include all fields for facilitator
346
+ settlementRouter: settlementRouter,
347
+ salt: salt,
348
+ payTo: recipientAddress, // finalPayTo
349
+ facilitatorFee: facilitatorFeeHex, // Must be hex format
350
+ hook: hook,
351
+ hookData: hookData
352
+ }
216
353
  },
217
- payload: v1Payload
354
+ payload: v1Payload,
355
+ // x402x router settlement extension (v2 format)
356
+ extensions: {
357
+ "x402x-router-settlement": {
358
+ info: {
359
+ settlementRouter: settlementRouter,
360
+ hook: hook,
361
+ hookData: hookData,
362
+ facilitatorFee: facilitatorFeeHex, // Must be hex format
363
+ salt: salt,
364
+ finalPayTo: recipientAddress // Final recipient of the payment
365
+ }
366
+ }
367
+ }
218
368
  };
219
369
 
220
370
  return Buffer.from(JSON.stringify(v2Payload)).toString("base64");
@@ -224,11 +374,16 @@ export class PaymentClient {
224
374
  }
225
375
 
226
376
  /**
227
- * Get default x402 resource URL from WebSocket URL
377
+ * Get resource URL for x402 payments.
378
+ * Throws if no resource URL is configured.
228
379
  */
229
380
  private getDefaultResourceUrl(): string {
230
- // Default fallback
231
- return "https://dev-rooms-websocket-ai-core-o9fmb.ondigitalocean.app/x402";
381
+ if (!this.resourceUrl) {
382
+ throw new Error(
383
+ "Resource URL not configured. Pass resourceUrl to PaymentClient or use buildX402ResourceUrl(wsUrl)."
384
+ );
385
+ }
386
+ return this.resourceUrl;
232
387
  }
233
388
 
234
389
  /**