@piprail/sdk 2.12.0 → 2.13.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/CHANGELOG.md +40 -0
- package/dist/index.cjs +11 -4
- package/dist/index.d.cts +31 -11
- package/dist/index.d.ts +31 -11
- package/dist/index.js +11 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,46 @@ All notable changes to `@piprail/sdk` are documented here. The format
|
|
|
4
4
|
follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the
|
|
5
5
|
versions follow [Semantic Versioning](https://semver.org/).
|
|
6
6
|
|
|
7
|
+
## [2.13.0] — 2026-06-21 — A2A hardening: spec-correct `payment-failed`, schema-contract precision + exhaustive edge-case coverage
|
|
8
|
+
|
|
9
|
+
An extreme-hardening pass on the **x402-over-A2A seller transport**, audited against the **real
|
|
10
|
+
`@a2a-js/sdk` 0.3.13 types**, the **a2a-x402 spec (v0.1+v0.2)**, Google's **reference `x402_a2a`
|
|
11
|
+
executor**, and the canonical **x402 V2** lib. Net: **zero runtime defects found** — the wire is
|
|
12
|
+
schema-perfect. This ships the two correctness fixes plus a comprehensive test + doc-precision pass.
|
|
13
|
+
HTTP and every other rail are byte-identical to 2.12.0; additive, defaults unchanged.
|
|
14
|
+
|
|
15
|
+
- **fix(a2a): a rejected (failed-verification) proof now emits `x402.payment.status: payment-failed`,
|
|
16
|
+
not `payment-required`.** a2a.md §9 is a MUST — *"If a payment fails, the server MUST set
|
|
17
|
+
x402.payment.status to payment-failed"* — and its worked **expired-signature** example (a
|
|
18
|
+
verification failure) emits `payment-failed`. Google's reference executor matches it verbatim
|
|
19
|
+
(`verify_response.is_valid == false → record_payment_failure → PAYMENT_FAILED`). **Retryability is
|
|
20
|
+
unchanged** — it rides on the A2A Task `state` (`input-required`), with a fresh challenge re-issued in
|
|
21
|
+
`x402.payment.required` + the failure receipt + the `x402.payment.error` code. (2.11.0 correctly
|
|
22
|
+
removed the client-only `payment-rejected` but landed on `payment-required`; this is the final notch.)
|
|
23
|
+
A genuine first/no-proof challenge is still `payment-required`.
|
|
24
|
+
- **fix(a2a): a tx-suppressed success receipt (`receipts.includeTxHash:false`) is no longer dropped**
|
|
25
|
+
when an earlier failed attempt on the same task shares the empty `transaction`. The `receipts[]`
|
|
26
|
+
dedupe now skips the empty-string transaction (an empty tx is not an idempotency key), so a
|
|
27
|
+
`payment-completed` task always carries its success receipt. Default (`includeTxHash:true`) unaffected.
|
|
28
|
+
- **fix(a2a): `wrong_recipient` / `transfer_not_found` map to the spec's `SETTLEMENT_FAILED`, not
|
|
29
|
+
`INVALID_AMOUNT`.** Neither is an amount mismatch; the a2a.md §9.1 enum has no recipient/not-found
|
|
30
|
+
member, so its catch-all `SETTLEMENT_FAILED` is the correct nearest fit — a buyer is no longer told to
|
|
31
|
+
retry with a "corrected amount" when the real issue is a recipient/asset. The raw PipRail code still
|
|
32
|
+
rides in `extensions.piprail`. `INVALID_AMOUNT` is now reserved for genuine amount errors.
|
|
33
|
+
- **test: +24 A2A coverage cases** (the suite is now exhaustive) — the `payment-failed` rejection
|
|
34
|
+
contract; standard **`exact` (EIP-3009) happy-path settle over A2A** (the scheme a real Google client
|
|
35
|
+
sends); the **`upto` metered rail over A2A** incl. a `$0` settle; **multi-chain CAIP-2 rail selection**;
|
|
36
|
+
the **forged-`accepted` guard** (an unoffered network/asset can't redirect funds); the
|
|
37
|
+
tx-suppressed-dedupe regression; `fulfill` throwing a non-Error / returning `undefined`; `newTaskId`
|
|
38
|
+
minting; TTL-eviction + receipts-cap **boundary** (tail-preserving) cases; the host-adapter
|
|
39
|
+
required-field-set contract; and the **error-enum codomain guard** (every emitted code is one of the 7
|
|
40
|
+
canonical `x402ErrorCode` members).
|
|
41
|
+
- **docs: the A2A guide is corrected + sharpened** — the lifecycle table/prose pair a rejection with
|
|
42
|
+
`payment-failed` (retry via `input-required`); a new **"Which A2A package?"** note (A2A is a Linux
|
|
43
|
+
Foundation project, official runtime `@a2a-js/sdk`); a **transport-metadata** note (PipRail emits x402
|
|
44
|
+
payment state; the host adapter stamps the SDK-required `contextId`/`messageId`/`artifactId`);
|
|
45
|
+
`receipt.amount` clarified as base units; the buyer-payload snippet made internally consistent.
|
|
46
|
+
|
|
7
47
|
## [2.12.0] — 2026-06-21 — BNB: the `U` (United Stables) token + Binance `permit2-exact` interop
|
|
8
48
|
|
|
9
49
|
BNB Chain max-out — full token parity with Binance's own x402 set, plus tolerance for Binance's
|
package/dist/index.cjs
CHANGED
|
@@ -7478,11 +7478,18 @@ var MAX_TASK_RECEIPTS = 64;
|
|
|
7478
7478
|
var VERIFY_CODE_TO_A2A_ERROR = {
|
|
7479
7479
|
payment_expired: "EXPIRED_PAYMENT",
|
|
7480
7480
|
tx_already_used: "DUPLICATE_NONCE",
|
|
7481
|
+
// Genuine amount mismatches only — the spec defines INVALID_AMOUNT as "the payment amount does
|
|
7482
|
+
// not match the required amount" (a2a.md §9.1), so keep it strictly for amount errors.
|
|
7481
7483
|
amount_too_low: "INVALID_AMOUNT",
|
|
7482
7484
|
upto_settle_exceeds_max: "INVALID_AMOUNT",
|
|
7483
7485
|
signature_invalid: "INVALID_SIGNATURE",
|
|
7484
|
-
|
|
7485
|
-
|
|
7486
|
+
// NOT amount mismatches — a proof for an unoffered asset/network, or paid to the wrong recipient.
|
|
7487
|
+
// The spec's 7-member enum (errors.py x402ErrorCode) has no WRONG_RECIPIENT/TRANSFER_NOT_FOUND, so
|
|
7488
|
+
// these map to SETTLEMENT_FAILED — its explicit catch-all "the transaction failed on-chain for a
|
|
7489
|
+
// reason other than the above" (a2a.md §9.1) — never INVALID_AMOUNT, which would mislead a buyer
|
|
7490
|
+
// into retrying with a corrected amount. The raw PipRail code still rides in extensions.piprail.
|
|
7491
|
+
transfer_not_found: "SETTLEMENT_FAILED",
|
|
7492
|
+
wrong_recipient: "SETTLEMENT_FAILED",
|
|
7486
7493
|
tx_reverted: "SETTLEMENT_FAILED",
|
|
7487
7494
|
tx_not_found: "EXPIRED_PAYMENT",
|
|
7488
7495
|
insufficient_confirmations: "EXPIRED_PAYMENT",
|
|
@@ -7565,7 +7572,7 @@ function createA2APaymentHandler(options) {
|
|
|
7565
7572
|
const store = _nullishCoalesce(options.taskStore, () => ( defaultTaskStore()));
|
|
7566
7573
|
function appendReceipt(taskId, entry) {
|
|
7567
7574
|
const prior = _nullishCoalesce(_optionalChain([store, 'access', _138 => _138.get, 'call', _139 => _139(taskId), 'optionalAccess', _140 => _140.receipts]), () => ( []));
|
|
7568
|
-
const isDup = "success" in entry && entry.success === true && prior.some((r) => "transaction" in r && r.transaction === entry.transaction);
|
|
7575
|
+
const isDup = "success" in entry && entry.success === true && entry.transaction !== "" && prior.some((r) => "transaction" in r && r.transaction === entry.transaction);
|
|
7569
7576
|
const next = isDup ? prior : [...prior, entry];
|
|
7570
7577
|
const receipts = next.length > MAX_TASK_RECEIPTS ? next.slice(-MAX_TASK_RECEIPTS) : next;
|
|
7571
7578
|
store.set(taskId, { receipts }, ttlMs);
|
|
@@ -7595,7 +7602,7 @@ function createA2APaymentHandler(options) {
|
|
|
7595
7602
|
const network = _nullishCoalesce(attempted, () => ( singleNetworkOf(result.challenge)));
|
|
7596
7603
|
const receipts = appendReceiptFailed(taskId, result.error, result.detail, network);
|
|
7597
7604
|
const metadata = {
|
|
7598
|
-
[A2A_STATUS_KEY]: "payment-
|
|
7605
|
+
[A2A_STATUS_KEY]: "payment-failed",
|
|
7599
7606
|
[A2A_ERROR_KEY]: toA2AErrorCode(result.error),
|
|
7600
7607
|
[A2A_REQUIRED_KEY]: result.challenge,
|
|
7601
7608
|
...toA2APaymentReceipts(receipts)
|
package/dist/index.d.cts
CHANGED
|
@@ -7834,11 +7834,11 @@ declare const PERMIT2_UPTO_WITNESS_TYPES: {
|
|
|
7834
7834
|
declare function renderLandingPage(sd: SelfDescription): string;
|
|
7835
7835
|
|
|
7836
7836
|
/**
|
|
7837
|
-
* Minimal, DUCK-TYPED
|
|
7838
|
-
*
|
|
7839
|
-
*
|
|
7840
|
-
*
|
|
7841
|
-
* them structurally — **with ZERO `@a2a` dependency**.
|
|
7837
|
+
* Minimal, DUCK-TYPED Agent2Agent (A2A) shapes — the structural surface the PipRail A2A
|
|
7838
|
+
* transport reads/writes, and NOTHING more. Like `ExpressLikeRequest` in `server.ts`, these
|
|
7839
|
+
* declare only the fields the adapter touches, so any A2A runtime's objects (the official
|
|
7840
|
+
* `@a2a-js/sdk` — `a2aproject` org, the Linux Foundation A2A project — ADK, or a hand-rolled
|
|
7841
|
+
* JSON-RPC handler) satisfy them structurally — **with ZERO `@a2a` dependency**.
|
|
7842
7842
|
*
|
|
7843
7843
|
* x402-over-A2A carries PipRail's existing `PaymentRequired`/`PaymentPayload`/
|
|
7844
7844
|
* `SettlementResponse` envelopes inside A2A `Task`/`Message` `metadata`, keyed off five
|
|
@@ -7948,9 +7948,11 @@ interface A2ATaskRecord {
|
|
|
7948
7948
|
}
|
|
7949
7949
|
|
|
7950
7950
|
/**
|
|
7951
|
-
* x402-over-A2A — the SELLER-side transport adapter
|
|
7951
|
+
* x402-over-A2A — the SELLER-side transport adapter for the Agent2Agent (A2A) protocol.
|
|
7952
7952
|
*
|
|
7953
|
-
* A2A is
|
|
7953
|
+
* A2A is an open protocol (created by Google, now a Linux Foundation project — a2a-protocol.org;
|
|
7954
|
+
* official JS runtime `@a2a-js/sdk` from the `a2aproject` org). It is x402's third official transport
|
|
7955
|
+
* (alongside HTTP and MCP). It carries PipRail's
|
|
7954
7956
|
* BYTE-IDENTICAL `PaymentRequired`/`PaymentPayload`/`SettlementResponse` envelopes inside
|
|
7955
7957
|
* A2A `Task`/`Message` JSON-RPC `metadata` (five namespaced `x402.payment.*` keys) keyed
|
|
7956
7958
|
* off a coarse A2A Task state — instead of base64 HTTP headers. It is a thin codec + adapter
|
|
@@ -7979,9 +7981,15 @@ interface A2ATaskRecord {
|
|
|
7979
7981
|
* PaymentPayload byte-identically, while the legacy v0.1 `x402_a2a` package (x402Version 1,
|
|
7980
7982
|
* `maxAmountRequired`, chain slugs) is bitrotted. Inbound v1 object-cores are absorbed for the
|
|
7981
7983
|
* standard `exact` scheme; PipRail-native `onchain-proof` is always v2 (never sent v1-flat).
|
|
7982
|
-
* • Merchant statuses are spec-bounded: `payment-required` (
|
|
7983
|
-
*
|
|
7984
|
-
*
|
|
7984
|
+
* • Merchant statuses are spec-bounded: `payment-required` (a genuine first/no-proof challenge) /
|
|
7985
|
+
* `payment-completed` / `payment-failed`. A SUBMITTED proof that fails verification (expired /
|
|
7986
|
+
* wrong-amount / replayed) emits `payment-failed` — the a2a.md §9 rule ("If a payment fails, the
|
|
7987
|
+
* server MUST set x402.payment.status to payment-failed") and its EXPIRED-signature example, which
|
|
7988
|
+
* Google's reference executor matches verbatim (`is_valid == false → record_payment_failure →
|
|
7989
|
+
* PAYMENT_FAILED`). Retryability rides on the A2A Task `state` (`input-required`), NOT the status —
|
|
7990
|
+
* so a rejection is `payment-failed` + `input-required` (retry) while a terminal settlement error is
|
|
7991
|
+
* `payment-failed` + `failed`. `payment-rejected` + `payment-submitted` are CLIENT→merchant statuses
|
|
7992
|
+
* we never emit.
|
|
7985
7993
|
*
|
|
7986
7994
|
* ── DEFERRED (NOT built here — see the x402-parity/03-a2a-transport plan) ──────
|
|
7987
7995
|
* • Phase 4 — the A2A BUYER (`A2APayer`): the HTTP buyer mints the payload that rides A2A today.
|
|
@@ -8017,6 +8025,12 @@ declare function toA2AErrorCode(code: string): string;
|
|
|
8017
8025
|
* Build the `input-required` payment-request Task carrying the challenge as RAW JSON
|
|
8018
8026
|
* (NOT base64) in `x402.payment.required` + `x402.payment.status = 'payment-required'`.
|
|
8019
8027
|
* `parts` are any human-readable message parts the merchant wants alongside it.
|
|
8028
|
+
*
|
|
8029
|
+
* Returns a **transport-metadata** Task: it carries the x402 `payment` state, NOT the host-owned
|
|
8030
|
+
* ids the `@a2a-js/sdk` runtime requires (`Task.contextId`, `status.message.messageId`/`parts`,
|
|
8031
|
+
* `artifacts[].artifactId` are all REQUIRED in the SDK's types). The host adapter stamps those
|
|
8032
|
+
* before publishing — see the `@a2a-js/sdk` mount in the docs / `examples/a2a-server/lib.mjs`.
|
|
8033
|
+
* This keeps the protocol layer chain- and runtime-agnostic (zero `@a2a` dependency).
|
|
8020
8034
|
*/
|
|
8021
8035
|
declare function toA2APaymentRequired(taskId: string, challenge: X402Challenge, parts?: A2APart[]): A2ATask;
|
|
8022
8036
|
/** Build the `x402.payment.receipts` metadata block (an ARRAY, append-only, B7 union). */
|
|
@@ -8078,9 +8092,15 @@ interface A2APaymentHandler {
|
|
|
8078
8092
|
* `gate.verify()`'s `VerifyPaymentResult` exactly:
|
|
8079
8093
|
* - no payload yet → Task `input-required` + `x402.payment.required`
|
|
8080
8094
|
* - payload, verified+settled → Task `completed` + `x402.payment.receipts` + artifacts
|
|
8081
|
-
* - payload, rejected → Task `input-required` re-challenge (RETRYABLE)
|
|
8095
|
+
* - payload, rejected → Task `input-required` re-challenge, status `payment-failed` (RETRYABLE)
|
|
8082
8096
|
* - settle threw (relayer) → Task `failed` + `x402.payment.error` (NOT retryable)
|
|
8083
8097
|
* - settle OK but fulfill threw → Task `completed` + receipt + error annotation (B7)
|
|
8098
|
+
*
|
|
8099
|
+
* The returned Task is **transport metadata only** — it carries the x402 `payment.*` state but NOT
|
|
8100
|
+
* the host-owned ids the `@a2a-js/sdk` runtime requires (`Task.contextId`, `status.message.messageId`
|
|
8101
|
+
* /`parts`, `artifacts[].artifactId`). The host adapter (the `AgentExecutor`) stamps those before
|
|
8102
|
+
* `bus.publish` — see the mount in the docs / `examples/a2a-server/lib.mjs`. This keeps the protocol
|
|
8103
|
+
* layer free of any `@a2a` dependency.
|
|
8084
8104
|
*/
|
|
8085
8105
|
handleMessage(message: A2AMessage, taskId?: string): Promise<A2ATask>;
|
|
8086
8106
|
/** Stamp the x402 extension into an AgentCard's `capabilities.extensions` (§2.4). */
|
package/dist/index.d.ts
CHANGED
|
@@ -7834,11 +7834,11 @@ declare const PERMIT2_UPTO_WITNESS_TYPES: {
|
|
|
7834
7834
|
declare function renderLandingPage(sd: SelfDescription): string;
|
|
7835
7835
|
|
|
7836
7836
|
/**
|
|
7837
|
-
* Minimal, DUCK-TYPED
|
|
7838
|
-
*
|
|
7839
|
-
*
|
|
7840
|
-
*
|
|
7841
|
-
* them structurally — **with ZERO `@a2a` dependency**.
|
|
7837
|
+
* Minimal, DUCK-TYPED Agent2Agent (A2A) shapes — the structural surface the PipRail A2A
|
|
7838
|
+
* transport reads/writes, and NOTHING more. Like `ExpressLikeRequest` in `server.ts`, these
|
|
7839
|
+
* declare only the fields the adapter touches, so any A2A runtime's objects (the official
|
|
7840
|
+
* `@a2a-js/sdk` — `a2aproject` org, the Linux Foundation A2A project — ADK, or a hand-rolled
|
|
7841
|
+
* JSON-RPC handler) satisfy them structurally — **with ZERO `@a2a` dependency**.
|
|
7842
7842
|
*
|
|
7843
7843
|
* x402-over-A2A carries PipRail's existing `PaymentRequired`/`PaymentPayload`/
|
|
7844
7844
|
* `SettlementResponse` envelopes inside A2A `Task`/`Message` `metadata`, keyed off five
|
|
@@ -7948,9 +7948,11 @@ interface A2ATaskRecord {
|
|
|
7948
7948
|
}
|
|
7949
7949
|
|
|
7950
7950
|
/**
|
|
7951
|
-
* x402-over-A2A — the SELLER-side transport adapter
|
|
7951
|
+
* x402-over-A2A — the SELLER-side transport adapter for the Agent2Agent (A2A) protocol.
|
|
7952
7952
|
*
|
|
7953
|
-
* A2A is
|
|
7953
|
+
* A2A is an open protocol (created by Google, now a Linux Foundation project — a2a-protocol.org;
|
|
7954
|
+
* official JS runtime `@a2a-js/sdk` from the `a2aproject` org). It is x402's third official transport
|
|
7955
|
+
* (alongside HTTP and MCP). It carries PipRail's
|
|
7954
7956
|
* BYTE-IDENTICAL `PaymentRequired`/`PaymentPayload`/`SettlementResponse` envelopes inside
|
|
7955
7957
|
* A2A `Task`/`Message` JSON-RPC `metadata` (five namespaced `x402.payment.*` keys) keyed
|
|
7956
7958
|
* off a coarse A2A Task state — instead of base64 HTTP headers. It is a thin codec + adapter
|
|
@@ -7979,9 +7981,15 @@ interface A2ATaskRecord {
|
|
|
7979
7981
|
* PaymentPayload byte-identically, while the legacy v0.1 `x402_a2a` package (x402Version 1,
|
|
7980
7982
|
* `maxAmountRequired`, chain slugs) is bitrotted. Inbound v1 object-cores are absorbed for the
|
|
7981
7983
|
* standard `exact` scheme; PipRail-native `onchain-proof` is always v2 (never sent v1-flat).
|
|
7982
|
-
* • Merchant statuses are spec-bounded: `payment-required` (
|
|
7983
|
-
*
|
|
7984
|
-
*
|
|
7984
|
+
* • Merchant statuses are spec-bounded: `payment-required` (a genuine first/no-proof challenge) /
|
|
7985
|
+
* `payment-completed` / `payment-failed`. A SUBMITTED proof that fails verification (expired /
|
|
7986
|
+
* wrong-amount / replayed) emits `payment-failed` — the a2a.md §9 rule ("If a payment fails, the
|
|
7987
|
+
* server MUST set x402.payment.status to payment-failed") and its EXPIRED-signature example, which
|
|
7988
|
+
* Google's reference executor matches verbatim (`is_valid == false → record_payment_failure →
|
|
7989
|
+
* PAYMENT_FAILED`). Retryability rides on the A2A Task `state` (`input-required`), NOT the status —
|
|
7990
|
+
* so a rejection is `payment-failed` + `input-required` (retry) while a terminal settlement error is
|
|
7991
|
+
* `payment-failed` + `failed`. `payment-rejected` + `payment-submitted` are CLIENT→merchant statuses
|
|
7992
|
+
* we never emit.
|
|
7985
7993
|
*
|
|
7986
7994
|
* ── DEFERRED (NOT built here — see the x402-parity/03-a2a-transport plan) ──────
|
|
7987
7995
|
* • Phase 4 — the A2A BUYER (`A2APayer`): the HTTP buyer mints the payload that rides A2A today.
|
|
@@ -8017,6 +8025,12 @@ declare function toA2AErrorCode(code: string): string;
|
|
|
8017
8025
|
* Build the `input-required` payment-request Task carrying the challenge as RAW JSON
|
|
8018
8026
|
* (NOT base64) in `x402.payment.required` + `x402.payment.status = 'payment-required'`.
|
|
8019
8027
|
* `parts` are any human-readable message parts the merchant wants alongside it.
|
|
8028
|
+
*
|
|
8029
|
+
* Returns a **transport-metadata** Task: it carries the x402 `payment` state, NOT the host-owned
|
|
8030
|
+
* ids the `@a2a-js/sdk` runtime requires (`Task.contextId`, `status.message.messageId`/`parts`,
|
|
8031
|
+
* `artifacts[].artifactId` are all REQUIRED in the SDK's types). The host adapter stamps those
|
|
8032
|
+
* before publishing — see the `@a2a-js/sdk` mount in the docs / `examples/a2a-server/lib.mjs`.
|
|
8033
|
+
* This keeps the protocol layer chain- and runtime-agnostic (zero `@a2a` dependency).
|
|
8020
8034
|
*/
|
|
8021
8035
|
declare function toA2APaymentRequired(taskId: string, challenge: X402Challenge, parts?: A2APart[]): A2ATask;
|
|
8022
8036
|
/** Build the `x402.payment.receipts` metadata block (an ARRAY, append-only, B7 union). */
|
|
@@ -8078,9 +8092,15 @@ interface A2APaymentHandler {
|
|
|
8078
8092
|
* `gate.verify()`'s `VerifyPaymentResult` exactly:
|
|
8079
8093
|
* - no payload yet → Task `input-required` + `x402.payment.required`
|
|
8080
8094
|
* - payload, verified+settled → Task `completed` + `x402.payment.receipts` + artifacts
|
|
8081
|
-
* - payload, rejected → Task `input-required` re-challenge (RETRYABLE)
|
|
8095
|
+
* - payload, rejected → Task `input-required` re-challenge, status `payment-failed` (RETRYABLE)
|
|
8082
8096
|
* - settle threw (relayer) → Task `failed` + `x402.payment.error` (NOT retryable)
|
|
8083
8097
|
* - settle OK but fulfill threw → Task `completed` + receipt + error annotation (B7)
|
|
8098
|
+
*
|
|
8099
|
+
* The returned Task is **transport metadata only** — it carries the x402 `payment.*` state but NOT
|
|
8100
|
+
* the host-owned ids the `@a2a-js/sdk` runtime requires (`Task.contextId`, `status.message.messageId`
|
|
8101
|
+
* /`parts`, `artifacts[].artifactId`). The host adapter (the `AgentExecutor`) stamps those before
|
|
8102
|
+
* `bus.publish` — see the mount in the docs / `examples/a2a-server/lib.mjs`. This keeps the protocol
|
|
8103
|
+
* layer free of any `@a2a` dependency.
|
|
8084
8104
|
*/
|
|
8085
8105
|
handleMessage(message: A2AMessage, taskId?: string): Promise<A2ATask>;
|
|
8086
8106
|
/** Stamp the x402 extension into an AgentCard's `capabilities.extensions` (§2.4). */
|
package/dist/index.js
CHANGED
|
@@ -7478,11 +7478,18 @@ var MAX_TASK_RECEIPTS = 64;
|
|
|
7478
7478
|
var VERIFY_CODE_TO_A2A_ERROR = {
|
|
7479
7479
|
payment_expired: "EXPIRED_PAYMENT",
|
|
7480
7480
|
tx_already_used: "DUPLICATE_NONCE",
|
|
7481
|
+
// Genuine amount mismatches only — the spec defines INVALID_AMOUNT as "the payment amount does
|
|
7482
|
+
// not match the required amount" (a2a.md §9.1), so keep it strictly for amount errors.
|
|
7481
7483
|
amount_too_low: "INVALID_AMOUNT",
|
|
7482
7484
|
upto_settle_exceeds_max: "INVALID_AMOUNT",
|
|
7483
7485
|
signature_invalid: "INVALID_SIGNATURE",
|
|
7484
|
-
|
|
7485
|
-
|
|
7486
|
+
// NOT amount mismatches — a proof for an unoffered asset/network, or paid to the wrong recipient.
|
|
7487
|
+
// The spec's 7-member enum (errors.py x402ErrorCode) has no WRONG_RECIPIENT/TRANSFER_NOT_FOUND, so
|
|
7488
|
+
// these map to SETTLEMENT_FAILED — its explicit catch-all "the transaction failed on-chain for a
|
|
7489
|
+
// reason other than the above" (a2a.md §9.1) — never INVALID_AMOUNT, which would mislead a buyer
|
|
7490
|
+
// into retrying with a corrected amount. The raw PipRail code still rides in extensions.piprail.
|
|
7491
|
+
transfer_not_found: "SETTLEMENT_FAILED",
|
|
7492
|
+
wrong_recipient: "SETTLEMENT_FAILED",
|
|
7486
7493
|
tx_reverted: "SETTLEMENT_FAILED",
|
|
7487
7494
|
tx_not_found: "EXPIRED_PAYMENT",
|
|
7488
7495
|
insufficient_confirmations: "EXPIRED_PAYMENT",
|
|
@@ -7565,7 +7572,7 @@ function createA2APaymentHandler(options) {
|
|
|
7565
7572
|
const store = options.taskStore ?? defaultTaskStore();
|
|
7566
7573
|
function appendReceipt(taskId, entry) {
|
|
7567
7574
|
const prior = store.get(taskId)?.receipts ?? [];
|
|
7568
|
-
const isDup = "success" in entry && entry.success === true && prior.some((r) => "transaction" in r && r.transaction === entry.transaction);
|
|
7575
|
+
const isDup = "success" in entry && entry.success === true && entry.transaction !== "" && prior.some((r) => "transaction" in r && r.transaction === entry.transaction);
|
|
7569
7576
|
const next = isDup ? prior : [...prior, entry];
|
|
7570
7577
|
const receipts = next.length > MAX_TASK_RECEIPTS ? next.slice(-MAX_TASK_RECEIPTS) : next;
|
|
7571
7578
|
store.set(taskId, { receipts }, ttlMs);
|
|
@@ -7595,7 +7602,7 @@ function createA2APaymentHandler(options) {
|
|
|
7595
7602
|
const network = attempted ?? singleNetworkOf(result.challenge);
|
|
7596
7603
|
const receipts = appendReceiptFailed(taskId, result.error, result.detail, network);
|
|
7597
7604
|
const metadata = {
|
|
7598
|
-
[A2A_STATUS_KEY]: "payment-
|
|
7605
|
+
[A2A_STATUS_KEY]: "payment-failed",
|
|
7599
7606
|
[A2A_ERROR_KEY]: toA2AErrorCode(result.error),
|
|
7600
7607
|
[A2A_REQUIRED_KEY]: result.challenge,
|
|
7601
7608
|
...toA2APaymentReceipts(receipts)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@piprail/sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.13.0",
|
|
4
4
|
"description": "Accept x402 crypto payments across 29 chains — every major EVM chain plus Solana, TON, Tron, NEAR, Sui, Aptos, Algorand, Stellar & XRPL — in a couple of lines. No backend, no database, no fee; payments settle straight to your wallet.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|