uvd-x402-sdk 2.72.0 → 2.74.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uvd-x402-sdk",
3
- "version": "2.72.0",
3
+ "version": "2.74.0",
4
4
  "description": "x402 Payment SDK - Gasless crypto payments across 25 blockchains via Ultravioleta facilitator. Supports EVM (including Scroll, SKALE Base, Robinhood Chain), Solana, Fogo, Stellar, NEAR, Algorand, Sui, and XRP Ledger. Features: ERC-8004 Trustless Agents, Escrow/Refunds, multi-stablecoin (USDC, EURC, AUSD, PYUSD, USDT, USDG).",
5
5
  "author": "Ultravioleta DAO <ultravioletadao@gmail.com>",
6
6
  "license": "MIT",
@@ -3186,6 +3186,22 @@ export interface PrepareRelayFeedbackResponse {
3186
3186
  * nobody.
3187
3187
  */
3188
3188
  signingPayload?: string;
3189
+ /**
3190
+ * The full `eth_signTypedData_v4` payload. **v4 delegates only.**
3191
+ *
3192
+ * Present exactly when the delegate deployed on that chain is v4, which the
3193
+ * facilitator reads from the chain per request rather than assuming from a
3194
+ * release. **When it is present, sign IT** — the wallet renders the agent, the
3195
+ * score, the tags and the deadline as named fields, so the rater sees what
3196
+ * they authorise instead of a hex blob.
3197
+ *
3198
+ * v4 carries no {@link signingPayload} and needs none: `signTypedData` has no
3199
+ * envelope to apply twice, which is the entire class of bug that kept the v3
3200
+ * rail at zero signatures for days.
3201
+ *
3202
+ * Requires facilitator v1.96.0+.
3203
+ */
3204
+ typedData?: Record<string, unknown>;
3189
3205
  /**
3190
3206
  * Unix seconds after which the authorisation is void. Short on purpose:
3191
3207
  * relaying is permissionless, so a signed authorisation is live in the wild
@@ -3231,6 +3247,41 @@ export interface SubmitRelayFeedbackRequest {
3231
3247
  authorization?: RelayAuthorizationParams;
3232
3248
  }
3233
3249
 
3250
+ /**
3251
+ * Request body for `POST /feedback/response/evm/prepare`.
3252
+ *
3253
+ * `responder` is the address the chain will record as the author.
3254
+ */
3255
+ export interface PrepareRelayResponseRequest {
3256
+ x402Version: 1 | 2;
3257
+ network: Erc8004Network;
3258
+ responder: string;
3259
+ agentId: number | string;
3260
+ /** WHOSE feedback is being answered — inside the signed struct. */
3261
+ clientAddress: string;
3262
+ /** Which feedback (1-indexed) — also inside the struct. */
3263
+ feedbackIndex: number;
3264
+ responseUri: string;
3265
+ responseHash?: string;
3266
+ }
3267
+
3268
+ /** Request body for `POST /feedback/response/evm/submit`. */
3269
+ export interface SubmitRelayResponseRequest {
3270
+ x402Version: 1 | 2;
3271
+ network: Erc8004Network;
3272
+ responder: string;
3273
+ agentId: number | string;
3274
+ clientAddress: string;
3275
+ feedbackIndex: number;
3276
+ responseUri: string;
3277
+ responseHash?: string;
3278
+ deadline: number;
3279
+ nonce: string;
3280
+ /** The responder's signature over the typed data. */
3281
+ signature: string;
3282
+ authorization?: RelayAuthorizationParams;
3283
+ }
3284
+
3234
3285
  /**
3235
3286
  * Proof of payment returned when settling with ERC-8004 extension
3236
3287
  */
@@ -4017,6 +4068,9 @@ export class Erc8004Client {
4017
4068
  * - wallet: `personal_sign` over `signingPayload`. `personal_sign` adds the
4018
4069
  * envelope itself, so signing `digest` with it wraps the value TWICE and
4019
4070
  * recovers a stranger — the only symptom is `relay_bad_signature`.
4071
+ * - **unless `typedData` came back** — that chain runs a v4 delegate. Then
4072
+ * sign THAT with `eth_signTypedData_v4` and ignore the other two: it is
4073
+ * the only form the rater can read, and it has no envelope ambiguity.
4020
4074
  * 2. If `delegated` is `false`, also produce an EIP-7702 authorization over
4021
4075
  * `(chainId, delegate, accountNonce)`.
4022
4076
  * 3. Hand both to {@link submitRelayedFeedback} with the SAME feedback
@@ -4265,11 +4319,89 @@ export class Erc8004Client {
4265
4319
  }
4266
4320
  }
4267
4321
 
4322
+ /**
4323
+ * Ask what the RESPONDER must sign to author a response on-chain.
4324
+ *
4325
+ * The mirror of {@link prepareRelayedFeedback}, for the other write the
4326
+ * registry accepts from anybody. `appendResponse` is not agent-only — the
4327
+ * registry takes it from any address — so on the plain {@link appendResponse}
4328
+ * route the `responder` recorded on-chain is the FACILITATOR. That does not
4329
+ * destroy anyone's reputation the way a revoke would; it ties the
4330
+ * facilitator's on-chain identity to a third party's content, which is its own
4331
+ * kind of wrong.
4332
+ *
4333
+ * **v4 delegates only.** The v3 delegate accepts exactly two selectors and
4334
+ * `appendResponse` is not one of them, so a v3 network answers 400
4335
+ * `relay_response_needs_v4` rather than silently falling back to the route
4336
+ * this replaces.
4337
+ *
4338
+ * `clientAddress` and `feedbackIndex` are inside the signed struct: without
4339
+ * them one signature would answer any client's rating, or any rating at that
4340
+ * index.
4341
+ */
4342
+ async prepareRelayedResponse(
4343
+ request: PrepareRelayResponseRequest
4344
+ ): Promise<PrepareRelayFeedbackResponse> {
4345
+ return this.postRelay('/feedback/response/evm/prepare', request, {
4346
+ success: false,
4347
+ delegated: false,
4348
+ chainId: 0,
4349
+ network: request.network,
4350
+ });
4351
+ }
4352
+
4353
+ /**
4354
+ * Relay a responder-authored response; the facilitator pays the gas.
4355
+ *
4356
+ * Pass back the same parameters, `deadline` and `nonce` that
4357
+ * {@link prepareRelayedResponse} returned: the facilitator rebuilds the struct
4358
+ * from them and refuses to relay anything the signature does not cover.
4359
+ */
4360
+ async submitRelayedResponse(
4361
+ request: SubmitRelayResponseRequest
4362
+ ): Promise<FeedbackResponse> {
4363
+ return this.postRelay('/feedback/response/evm/submit', request, {
4364
+ success: false,
4365
+ network: request.network,
4366
+ });
4367
+ }
4368
+
4369
+ /** Shared POST for the relay routes: a refusal is data, never a throw. */
4370
+ private async postRelay<T>(path: string, request: { network: Erc8004Network }, onError: T): Promise<T> {
4371
+ const controller = new AbortController();
4372
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
4373
+ try {
4374
+ const response = await fetch(`${this.baseUrl}${path}`, {
4375
+ method: 'POST',
4376
+ headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
4377
+ body: JSON.stringify({ ...request, network: wireNetwork(request.network) }),
4378
+ signal: controller.signal,
4379
+ });
4380
+ clearTimeout(timeoutId);
4381
+ if (!response.ok) {
4382
+ const errorText = await response.text();
4383
+ return { ...onError, error: `Facilitator error: ${response.status} - ${errorText}` };
4384
+ }
4385
+ return await response.json();
4386
+ } catch (error) {
4387
+ clearTimeout(timeoutId);
4388
+ return { ...onError, error: error instanceof Error ? error.message : 'Unknown error' };
4389
+ }
4390
+ }
4391
+
4268
4392
  /**
4269
4393
  * Append a response to existing feedback
4270
4394
  *
4271
- * Allows agents to respond to feedback they received.
4272
- * Only the agent (identity owner) can append responses.
4395
+ * @deprecated On this route the facilitator is the AUTHOR: the registry
4396
+ * records `msg.sender` as the `responder`, and that is the facilitator's
4397
+ * wallet. Where the delegate is **v4**, use {@link prepareRelayedResponse} +
4398
+ * {@link submitRelayedResponse} instead. This route still works and is the
4399
+ * only one available where the delegate is still v3.
4400
+ *
4401
+ * **This is NOT agent-only**, despite what this comment claimed until
4402
+ * 2026-08-25. Verified on-chain on 2026-08-18: the registry accepts
4403
+ * `appendResponse` from ANY address. There is no identity-owner check, here or
4404
+ * in the contract.
4273
4405
  *
4274
4406
  * @param network - Network where feedback was submitted
4275
4407
  * @param agentId - Agent ID