@parallel-protocol/x402 0.8.1 → 0.8.2
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/README.md +11 -10
- package/dist/{chunk-GXPUE3ES.js → chunk-KTBFF5HI.js} +13 -6
- package/dist/{chunk-SNW5Z5HB.cjs → chunk-MXGS3HMS.cjs} +13 -6
- package/dist/express.cjs +5 -5
- package/dist/express.js +1 -1
- package/dist/fastify.cjs +11 -11
- package/dist/fastify.js +1 -1
- package/dist/hono.cjs +6 -6
- package/dist/hono.js +1 -1
- package/dist/index.cjs +15 -15
- package/dist/index.js +1 -1
- package/dist/next.cjs +13 -13
- package/dist/next.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -40,7 +40,7 @@ Agent Merchant (this SDK) Facilitator
|
|
|
40
40
|
- The handler only runs after the signature is verified.
|
|
41
41
|
- The on-chain settlement happens after the handler produces a 2xx response — the agent is not charged on errors.
|
|
42
42
|
- The settle is bound to the merchant that verified: `POST /x402/verify` hands the middleware a settle token that `POST /x402/settle` must present. The token stays in memory for the life of the request and never reaches the agent.
|
|
43
|
-
- If settlement fails, the middleware discards the handler's response and returns `402` with `{ error: "PAYMENT_SETTLEMENT_FAILED", reason, message }`: `reason` is the facilitator's code (`INSUFFICIENT_BALANCE`, `AUTHORIZATION_USED`, `PAYMENT_EXPIRED`, ...) or this SDK's (`SETTLE_TIMEOUT`, `FACILITATOR_UNAVAILABLE`, `FACILITATOR_INVALID_RESPONSE`, `AMOUNT_MISMATCH`, `UNKNOWN`), `message` the facilitator's text or this SDK's, and the facilitator's `Retry-After` is copied when it sent one. A settle that timed out or could not reach the facilitator is retried once first
|
|
43
|
+
- If settlement fails, the middleware discards the handler's response and returns `402` with `{ error: "PAYMENT_SETTLEMENT_FAILED", reason, message }`: `reason` is the facilitator's code (`INSUFFICIENT_BALANCE`, `AUTHORIZATION_USED`, `PAYMENT_EXPIRED`, ...) or this SDK's (`SETTLE_TIMEOUT`, `FACILITATOR_UNAVAILABLE`, `FACILITATOR_INVALID_RESPONSE`, `AMOUNT_MISMATCH`, `UNKNOWN`), `message` the facilitator's text or this SDK's, and the facilitator's `Retry-After` is copied when it sent one. A settle that timed out or could not reach the facilitator is retried once first, with the same settle token: once the first attempt has finished, the facilitator answers its recorded outcome, and any other answer to the retry tells the agent to check with the merchant.
|
|
44
44
|
- A metered settle must settle the amount the handler asked for: a confirmation for another amount is refused and the response discarded.
|
|
45
45
|
- Handlers are bounded by a 30-second timeout on Express, Hono and Next.js — a slow handler returns `504` and the agent is not charged. (Fastify manages handler execution itself, so no timeout is applied there.) Metered routes get their announced window minus two minutes kept for the settlement and its retry.
|
|
46
46
|
- On paid Fastify routes, writing to `reply.raw` (the SSE/streaming pattern) fails loudly instead of sending: a raw response skips the settlement hooks and would go out unpaid. Streaming is not supported on paid routes.
|
|
@@ -755,7 +755,7 @@ if (result.success) {
|
|
|
755
755
|
}
|
|
756
756
|
```
|
|
757
757
|
|
|
758
|
-
The constructor throws `X402ConfigError` when the URL is neither https nor plain http on `localhost`, `127.0.0.1` or `[::1]`, and the client keeps the address it checked. No call follows a redirect. `verify` uses a 10-second timeout. `settle` uses a 60-second timeout to accommodate on-chain confirmation latency. `verify` throws on any failure, with the facilitator's message in `.detail`, its HTTP status in `.status` and its `Retry-After` in `.retryAfter`. A facilitator that issues no settle token is an invalid response. `settle` returns a `FacilitatorResponse` union on facilitator errors, with the facilitator's status and `Retry-After` on `error`, and throws `X402RuntimeError` on connectivity issues (`SETTLE_TIMEOUT` when the 60 seconds ran out, the payment may still settle), an undecodable payment header, or a malformed facilitator response. A settle
|
|
758
|
+
The constructor throws `X402ConfigError` when the URL is neither https nor plain http on `localhost`, `127.0.0.1` or `[::1]`, and the client keeps the address it checked. No call follows a redirect. `verify` uses a 10-second timeout. `settle` uses a 60-second timeout to accommodate on-chain confirmation latency. `verify` throws on any failure, with the facilitator's message in `.detail`, its HTTP status in `.status` and its `Retry-After` in `.retryAfter`. A facilitator that issues no settle token is an invalid response. `settle` returns a `FacilitatorResponse` union on facilitator errors, with the facilitator's status and `Retry-After` on `error`, and throws `X402RuntimeError` on connectivity issues (`SETTLE_TIMEOUT` when the 60 seconds ran out, the payment may still settle), an undecodable payment header, or a malformed facilitator response. A settle answered with an error that carries no `error` field throws `FACILITATOR_UNAVAILABLE` with that status: the answer comes from something in front of the facilitator, and the payment may still settle. The settle token is a secret for the life of the request: keep it in memory, never log it, never send it to the payer.
|
|
759
759
|
|
|
760
760
|
For a metered payment, the requirements also carry `scheme: "upto"` and `maxTimeoutSeconds`, and `settle` takes the amount to charge, in the token's smallest unit, next to the settle token: `{ settleToken, amount }`.
|
|
761
761
|
|
|
@@ -807,12 +807,12 @@ The SDK raises it when the facilitator gave no usable answer:
|
|
|
807
807
|
- It could not be reached: a DNS, connection or TLS failure.
|
|
808
808
|
- It answered with a redirect, which the SDK never follows. The error's `status` is the redirect's, and the configured `url` is then usually not the facilitator's own https address.
|
|
809
809
|
- It did not answer a `verify` within 10 seconds. A `settle` that runs out of its 60 seconds raises `SETTLE_TIMEOUT` instead.
|
|
810
|
-
- It answered
|
|
810
|
+
- It answered with an error that carries no `error` field, such as an error page from a gateway or a firewall in front of it. The error's `status` is that answer's.
|
|
811
811
|
- It answered with a success status but a body that is not JSON, or that was cut off.
|
|
812
812
|
|
|
813
813
|
At `verify`, nothing was settled. The middleware answers the agent 402 with a new invoice and `error: "FACILITATOR_UNAVAILABLE"`, and the agent can pay again later.
|
|
814
814
|
|
|
815
|
-
At `settle`, the outcome is unknown, since the facilitator may have settled before its answer was lost. The middleware retries the settle once with the same settle token, which returns the recorded outcome
|
|
815
|
+
At `settle`, the outcome is unknown, since the facilitator may have settled before its answer was lost. The middleware retries the settle once with the same settle token, which returns the recorded outcome once the first attempt has finished. If the retry raises it too, the response is not served, and the agent gets a 402 `{ error: "PAYMENT_SETTLEMENT_FAILED", reason: "FACILITATOR_UNAVAILABLE" }` whose message tells it not to sign another payment before checking with the merchant. A retry that fails another way reports that reason instead.
|
|
816
816
|
|
|
817
817
|
### Propagated from the facilitator
|
|
818
818
|
|
|
@@ -822,7 +822,7 @@ When the facilitator refuses a payment at verify, its code is forwarded as the `
|
|
|
822
822
|
|------|--------------------|---------|--------------------------|
|
|
823
823
|
| `INVALID_PAYLOAD` | 400 | The payload does not have the shape of its route, carries a field another route would read, or uses a method of the other scheme | Sign a payment that matches one of the `accepts` entries |
|
|
824
824
|
| `INVALID_SIGNATURE` | 400 | EIP-712 signature recovery failed | Sign again |
|
|
825
|
-
| `INVALID_NONCE` | 409 | Nonce already used
|
|
825
|
+
| `INVALID_NONCE` | 409 | Nonce already used: the same payment reached the facilitator before, and may have settled | Do not sign another payment before checking with the merchant |
|
|
826
826
|
| `PAYMENT_EXPIRED` | 402 | `validBefore` has passed | Sign a new payment |
|
|
827
827
|
| `INSUFFICIENT_AMOUNT` | 402 | The amount the route guarantees the merchant is below the price, or the authorization is for zero | Sign for the invoiced `amount` |
|
|
828
828
|
| `INSUFFICIENT_BALANCE` | 402 | The payer does not hold the signed amount (metered payments) | Fund the wallet, sign a new payment |
|
|
@@ -842,19 +842,20 @@ When the facilitator refuses at settle, the 402 body is `{ error: "PAYMENT_SETTL
|
|
|
842
842
|
| Reason | Facilitator status | Meaning | What the agent should do |
|
|
843
843
|
|--------|--------------------|---------|--------------------------|
|
|
844
844
|
| `INSUFFICIENT_BALANCE` | 402 | The payer no longer holds the signed amount | Fund the wallet, sign a new payment |
|
|
845
|
-
| `AUTHORIZATION_USED` | 409 | The authorization
|
|
845
|
+
| `AUTHORIZATION_USED` | 409 | The authorization is already consumed or cancelled on-chain. It may have paid the merchant | Do not sign another payment before checking with the merchant |
|
|
846
846
|
| `PAYMENT_EXPIRED` | 402 | The authorization expired before settlement | Sign a new payment |
|
|
847
|
-
| `PAYMENT_NOT_VERIFIED` | 402 | No verified payment for this authorization, or it
|
|
847
|
+
| `PAYMENT_NOT_VERIFIED` | 402 | No verified payment for this authorization, or an earlier settle of it failed. The merchant may have been paid, or may still be | Do not sign another payment before checking with the merchant |
|
|
848
848
|
| `SETTLE_IN_PROGRESS` | 409 | Another settle of the same payment is still running | Do not sign another payment before checking with the merchant |
|
|
849
849
|
| `SETTLE_TOKEN_INVALID`, `SETTLE_TOKEN_REQUIRED` | 403 | The merchant did not present the settle token verify issued: a merchant client issue, not the payer's, and nothing was settled | Do not sign another payment before checking with the merchant |
|
|
850
|
-
| `RELAYER_UNAVAILABLE
|
|
850
|
+
| `RELAYER_UNAVAILABLE` | 503 | The facilitator is temporarily unable to settle. The payment was not taken, and the facilitator will not settle it | Retry later with a new payment, after `Retry-After` when given |
|
|
851
|
+
| `PARALLELIZER_PAUSED`, `SERVICE_UNAVAILABLE` | 503 | The facilitator or the chain is temporarily unable to settle. This settle sent nothing, but the payment may still settle until its authorization expires, and an earlier attempt may already have settled it | Do not sign another payment before checking with the merchant |
|
|
851
852
|
| `TX_REVERTED` | 500 | The transaction reverted for a reason the facilitator could not attribute | Sign a new payment |
|
|
852
853
|
| `SUBMISSION_FAILED` | 500 | The submission failed. When the message says the outcome is unknown, a transaction may have been sent, and the payment may have settled or may still settle | Sign a new payment, unless the message says the outcome is unknown: then check with the merchant first |
|
|
853
854
|
| `RECEIPT_UNAVAILABLE` | 500 | The transaction was sent but its confirmation could not be read | Do not sign another payment before checking with the merchant |
|
|
854
855
|
| `INVALID_PAYLOAD`, `NETWORK_MISMATCH`, `PAYMENT_METHOD_NOT_SUPPORTED` | 400 | The settle request does not match the payment that was verified, or a metered amount is missing, malformed or above the signed cap. Nothing was settled | Sign a new payment |
|
|
855
856
|
| `INSUFFICIENT_AMOUNT` | 402 | A metered amount of zero, or an authorization for zero. Nothing was settled | Sign a new payment |
|
|
856
857
|
|
|
857
|
-
Reasons from this SDK: `SETTLE_TIMEOUT`, `FACILITATOR_UNAVAILABLE` and `FACILITATOR_INVALID_RESPONSE` (the settle may still have gone through, do not pay again before checking with the merchant), `AMOUNT_MISMATCH` (the facilitator settled another amount than the one asked, money moved, the response was not served, do not pay again before checking), `UNKNOWN` (anything that is not a code, such as the `Too Many Requests` of the facilitator's per-IP limit). For `SETTLE_IN_PROGRESS`, `RECEIPT_UNAVAILABLE`, `SETTLE_TOKEN_INVALID` and `SETTLE_TOKEN_REQUIRED` the message is this SDK's as well, since the facilitator's text addresses the merchant.
|
|
858
|
+
Reasons from this SDK: `SETTLE_TIMEOUT`, `FACILITATOR_UNAVAILABLE` and `FACILITATOR_INVALID_RESPONSE` (the settle may still have gone through, do not pay again before checking with the merchant), `AMOUNT_MISMATCH` (the facilitator settled another amount than the one asked, money moved, the response was not served, do not pay again before checking), `UNKNOWN` (anything that is not a code, such as the `Too Many Requests` of the facilitator's per-IP limit: the payment may have settled, do not pay again before checking). For `SETTLE_IN_PROGRESS`, `RECEIPT_UNAVAILABLE`, `SETTLE_TOKEN_INVALID` and `SETTLE_TOKEN_REQUIRED` the message is this SDK's as well, since the facilitator's text addresses the merchant. The message is this SDK's too for `AUTHORIZATION_USED`, `PAYMENT_NOT_VERIFIED`, `PARALLELIZER_PAUSED` and `SERVICE_UNAVAILABLE`: the payment may have settled or may still settle, so the message tells the agent to check with the merchant before paying again.
|
|
858
859
|
|
|
859
860
|
`AMOUNT_MISMATCH` is also the one reason that points at the facilitator rather than at the request: it confirmed a settlement of another amount than the one the route asked for, so money moved. Alert on it, for example on 402 responses whose `reason` is `AMOUNT_MISMATCH`, rather than treating it as a routine refusal.
|
|
860
861
|
|
|
@@ -865,7 +866,7 @@ The facilitator counts the requests of each IP address that calls it, which is t
|
|
|
865
866
|
| Limit | Facilitator answer | What the agent gets | What the agent should do |
|
|
866
867
|
|-------|--------------------|---------------------|--------------------------|
|
|
867
868
|
| Verifies per IP | 429 `{ error: "Too Many Requests", message }`, the message naming the time left in the minute (`Rate limit exceeded, retry in 42 seconds`, for instance), with `Retry-After` in seconds | 402 with a new invoice, `error: "FACILITATOR_INVALID_RESPONSE"`, the facilitator's message and its `Retry-After`. Nothing was verified | Send the payment again after `Retry-After` |
|
|
868
|
-
| Settles per IP | The same 429 | 402 `{ error: "PAYMENT_SETTLEMENT_FAILED", reason: "UNKNOWN", message
|
|
869
|
+
| Settles per IP | The same 429 | 402 `{ error: "PAYMENT_SETTLEMENT_FAILED", reason: "UNKNOWN", message }` with the facilitator's `Retry-After`. The handler's response is discarded and the settle is not retried. This settle did nothing, but when the limit answers the SDK's retry of a settle that timed out, the first attempt may have settled | The message says the payment may have settled: check with the merchant, then sign a new payment after `Retry-After` |
|
|
869
870
|
| Verifies per payer | 429 `RATE_LIMIT_EXCEEDED`, with `Retry-After` until the next UTC hour | 402 with a new invoice, `error: "RATE_LIMIT_EXCEEDED"`, the facilitator's message and its `Retry-After` | Pay again after `Retry-After` |
|
|
870
871
|
|
|
871
872
|
The `error` of the per-IP answer is not a code, which is why the middleware reports `FACILITATOR_INVALID_RESPONSE` at verify and `UNKNOWN` at settle. A direct caller of `FacilitatorClient` sees it as it is: `verify` throws an `X402RuntimeError` whose `.code` is `"Too Many Requests"`, with `.status` 429 and `.retryAfter`, and `settle` returns it as a failure with the same code.
|
|
@@ -325,14 +325,16 @@ var FacilitatorClient = class {
|
|
|
325
325
|
throwIfRedirect(response);
|
|
326
326
|
if (!response.ok) {
|
|
327
327
|
const body = await readErrorBody(response);
|
|
328
|
-
if (body.error === void 0
|
|
329
|
-
throw new X402RuntimeError(X402_ERROR_CODES.FACILITATOR_UNAVAILABLE
|
|
328
|
+
if (body.error === void 0) {
|
|
329
|
+
throw new X402RuntimeError(X402_ERROR_CODES.FACILITATOR_UNAVAILABLE, {
|
|
330
|
+
status: response.status
|
|
331
|
+
});
|
|
330
332
|
}
|
|
331
333
|
const retryAfter = retryAfterOf(response);
|
|
332
334
|
return {
|
|
333
335
|
success: false,
|
|
334
336
|
error: {
|
|
335
|
-
code: body.error
|
|
337
|
+
code: body.error,
|
|
336
338
|
message: body.message ?? "Settlement failed",
|
|
337
339
|
status: response.status,
|
|
338
340
|
...retryAfter !== void 0 && { retryAfter }
|
|
@@ -772,8 +774,9 @@ function createPaymentGate(config) {
|
|
|
772
774
|
};
|
|
773
775
|
};
|
|
774
776
|
}
|
|
775
|
-
var
|
|
777
|
+
var DEFAULT_SETTLEMENT_MESSAGE = "The payment could not be settled.";
|
|
776
778
|
var MERCHANT_SETTLEMENT_MESSAGE = "The merchant could not complete the settlement of this payment. The payment was not taken: do not sign another payment for this request before checking with the merchant.";
|
|
779
|
+
var UNAVAILABLE_SETTLEMENT_MESSAGE = "The facilitator could not settle the payment for now. It may still settle until its authorization expires, or an earlier attempt may already have settled it: do not sign another payment for this request before checking with the merchant.";
|
|
777
780
|
var AGENT_MESSAGES = {
|
|
778
781
|
[X402_ERROR_CODES.SETTLE_TIMEOUT]: "The facilitator did not confirm the settlement in time. The payment may still settle: do not sign another payment for this request before checking with the merchant.",
|
|
779
782
|
[X402_ERROR_CODES.FACILITATOR_UNAVAILABLE]: "The facilitator could not be reached to settle the payment. It may still have settled: do not sign another payment for this request before checking with the merchant.",
|
|
@@ -782,15 +785,19 @@ var AGENT_MESSAGES = {
|
|
|
782
785
|
RECEIPT_UNAVAILABLE: "The facilitator sent the transaction but could not read its confirmation. The payment may have settled: do not sign another payment for this request before checking with the merchant.",
|
|
783
786
|
SETTLE_TOKEN_INVALID: MERCHANT_SETTLEMENT_MESSAGE,
|
|
784
787
|
SETTLE_TOKEN_REQUIRED: MERCHANT_SETTLEMENT_MESSAGE,
|
|
788
|
+
AUTHORIZATION_USED: "The payment's authorization was already consumed or cancelled on-chain. It may have paid the merchant: do not sign another payment for this request before checking with the merchant.",
|
|
789
|
+
PAYMENT_NOT_VERIFIED: "The facilitator holds no payment it can settle for this request. An earlier attempt may have paid the merchant, or may still settle: do not sign another payment for this request before checking with the merchant.",
|
|
790
|
+
PARALLELIZER_PAUSED: UNAVAILABLE_SETTLEMENT_MESSAGE,
|
|
791
|
+
SERVICE_UNAVAILABLE: UNAVAILABLE_SETTLEMENT_MESSAGE,
|
|
785
792
|
AMOUNT_MISMATCH: "The facilitator settled a different amount than this request asked for. The response was not served: do not sign another payment for this request before checking with the merchant.",
|
|
786
|
-
UNKNOWN:
|
|
793
|
+
UNKNOWN: "The facilitator gave no reason for this failure, and the payment may have settled: do not sign another payment for this request before checking with the merchant."
|
|
787
794
|
};
|
|
788
795
|
function settlementFailure(code, failure) {
|
|
789
796
|
const reason = shapedCode(code) ?? "UNKNOWN";
|
|
790
797
|
return {
|
|
791
798
|
settled: false,
|
|
792
799
|
reason,
|
|
793
|
-
message: AGENT_MESSAGES[reason] ?? boundedMessage(failure?.message) ??
|
|
800
|
+
message: AGENT_MESSAGES[reason] ?? boundedMessage(failure?.message) ?? DEFAULT_SETTLEMENT_MESSAGE,
|
|
794
801
|
...failure?.retryAfter !== void 0 && {
|
|
795
802
|
retryAfter: failure.retryAfter
|
|
796
803
|
}
|
|
@@ -327,14 +327,16 @@ var FacilitatorClient = class {
|
|
|
327
327
|
throwIfRedirect(response);
|
|
328
328
|
if (!response.ok) {
|
|
329
329
|
const body = await readErrorBody(response);
|
|
330
|
-
if (body.error === void 0
|
|
331
|
-
throw new chunkKZZY5LS6_cjs.X402RuntimeError(chunkKZZY5LS6_cjs.X402_ERROR_CODES.FACILITATOR_UNAVAILABLE
|
|
330
|
+
if (body.error === void 0) {
|
|
331
|
+
throw new chunkKZZY5LS6_cjs.X402RuntimeError(chunkKZZY5LS6_cjs.X402_ERROR_CODES.FACILITATOR_UNAVAILABLE, {
|
|
332
|
+
status: response.status
|
|
333
|
+
});
|
|
332
334
|
}
|
|
333
335
|
const retryAfter = retryAfterOf(response);
|
|
334
336
|
return {
|
|
335
337
|
success: false,
|
|
336
338
|
error: {
|
|
337
|
-
code: body.error
|
|
339
|
+
code: body.error,
|
|
338
340
|
message: body.message ?? "Settlement failed",
|
|
339
341
|
status: response.status,
|
|
340
342
|
...retryAfter !== void 0 && { retryAfter }
|
|
@@ -774,8 +776,9 @@ function createPaymentGate(config) {
|
|
|
774
776
|
};
|
|
775
777
|
};
|
|
776
778
|
}
|
|
777
|
-
var
|
|
779
|
+
var DEFAULT_SETTLEMENT_MESSAGE = "The payment could not be settled.";
|
|
778
780
|
var MERCHANT_SETTLEMENT_MESSAGE = "The merchant could not complete the settlement of this payment. The payment was not taken: do not sign another payment for this request before checking with the merchant.";
|
|
781
|
+
var UNAVAILABLE_SETTLEMENT_MESSAGE = "The facilitator could not settle the payment for now. It may still settle until its authorization expires, or an earlier attempt may already have settled it: do not sign another payment for this request before checking with the merchant.";
|
|
779
782
|
var AGENT_MESSAGES = {
|
|
780
783
|
[chunkKZZY5LS6_cjs.X402_ERROR_CODES.SETTLE_TIMEOUT]: "The facilitator did not confirm the settlement in time. The payment may still settle: do not sign another payment for this request before checking with the merchant.",
|
|
781
784
|
[chunkKZZY5LS6_cjs.X402_ERROR_CODES.FACILITATOR_UNAVAILABLE]: "The facilitator could not be reached to settle the payment. It may still have settled: do not sign another payment for this request before checking with the merchant.",
|
|
@@ -784,15 +787,19 @@ var AGENT_MESSAGES = {
|
|
|
784
787
|
RECEIPT_UNAVAILABLE: "The facilitator sent the transaction but could not read its confirmation. The payment may have settled: do not sign another payment for this request before checking with the merchant.",
|
|
785
788
|
SETTLE_TOKEN_INVALID: MERCHANT_SETTLEMENT_MESSAGE,
|
|
786
789
|
SETTLE_TOKEN_REQUIRED: MERCHANT_SETTLEMENT_MESSAGE,
|
|
790
|
+
AUTHORIZATION_USED: "The payment's authorization was already consumed or cancelled on-chain. It may have paid the merchant: do not sign another payment for this request before checking with the merchant.",
|
|
791
|
+
PAYMENT_NOT_VERIFIED: "The facilitator holds no payment it can settle for this request. An earlier attempt may have paid the merchant, or may still settle: do not sign another payment for this request before checking with the merchant.",
|
|
792
|
+
PARALLELIZER_PAUSED: UNAVAILABLE_SETTLEMENT_MESSAGE,
|
|
793
|
+
SERVICE_UNAVAILABLE: UNAVAILABLE_SETTLEMENT_MESSAGE,
|
|
787
794
|
AMOUNT_MISMATCH: "The facilitator settled a different amount than this request asked for. The response was not served: do not sign another payment for this request before checking with the merchant.",
|
|
788
|
-
UNKNOWN:
|
|
795
|
+
UNKNOWN: "The facilitator gave no reason for this failure, and the payment may have settled: do not sign another payment for this request before checking with the merchant."
|
|
789
796
|
};
|
|
790
797
|
function settlementFailure(code, failure) {
|
|
791
798
|
const reason = shapedCode(code) ?? "UNKNOWN";
|
|
792
799
|
return {
|
|
793
800
|
settled: false,
|
|
794
801
|
reason,
|
|
795
|
-
message: AGENT_MESSAGES[reason] ?? boundedMessage(failure?.message) ??
|
|
802
|
+
message: AGENT_MESSAGES[reason] ?? boundedMessage(failure?.message) ?? DEFAULT_SETTLEMENT_MESSAGE,
|
|
796
803
|
...failure?.retryAfter !== void 0 && {
|
|
797
804
|
retryAfter: failure.retryAfter
|
|
798
805
|
}
|
package/dist/express.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkMXGS3HMS_cjs = require('./chunk-MXGS3HMS.cjs');
|
|
4
4
|
require('./chunk-KZZY5LS6.cjs');
|
|
5
5
|
|
|
6
6
|
// src/express/adapter.ts
|
|
@@ -108,8 +108,8 @@ var ExpressAdapter = class {
|
|
|
108
108
|
return originalEnd(...args);
|
|
109
109
|
});
|
|
110
110
|
next();
|
|
111
|
-
const outcome = await
|
|
112
|
-
if (outcome ===
|
|
111
|
+
const outcome = await chunkMXGS3HMS_cjs.raceTimeout(endPromise, options?.timeoutMs);
|
|
112
|
+
if (outcome === chunkMXGS3HMS_cjs.HANDLER_TIMEOUT) {
|
|
113
113
|
discarded = true;
|
|
114
114
|
return {
|
|
115
115
|
status: 504,
|
|
@@ -146,7 +146,7 @@ var ExpressAdapter = class {
|
|
|
146
146
|
const chunk = chunkBytes(args);
|
|
147
147
|
if (chunk) bytes.push(chunk);
|
|
148
148
|
}
|
|
149
|
-
return
|
|
149
|
+
return chunkMXGS3HMS_cjs.parseJsonBody(
|
|
150
150
|
contentType,
|
|
151
151
|
Buffer.concat(bytes).toString("utf8")
|
|
152
152
|
);
|
|
@@ -170,7 +170,7 @@ var ExpressAdapter = class {
|
|
|
170
170
|
|
|
171
171
|
// src/express/index.ts
|
|
172
172
|
function paymentMiddleware(config) {
|
|
173
|
-
const middleware =
|
|
173
|
+
const middleware = chunkMXGS3HMS_cjs.createPaymentMiddleware(config);
|
|
174
174
|
return async (req, res, next) => {
|
|
175
175
|
const result = await middleware(new ExpressAdapter(req, res, next));
|
|
176
176
|
if ("pass" in result) {
|
package/dist/express.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { raceTimeout, HANDLER_TIMEOUT, parseJsonBody, createPaymentMiddleware } from './chunk-
|
|
1
|
+
import { raceTimeout, HANDLER_TIMEOUT, parseJsonBody, createPaymentMiddleware } from './chunk-KTBFF5HI.js';
|
|
2
2
|
import './chunk-QAECRSWF.js';
|
|
3
3
|
|
|
4
4
|
// src/express/adapter.ts
|
package/dist/fastify.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkMXGS3HMS_cjs = require('./chunk-MXGS3HMS.cjs');
|
|
4
4
|
require('./chunk-KZZY5LS6.cjs');
|
|
5
5
|
var fp = require('fastify-plugin');
|
|
6
6
|
|
|
@@ -37,7 +37,7 @@ var FastifyAdapter = class {
|
|
|
37
37
|
// src/fastify/index.ts
|
|
38
38
|
function payloadJson(contentType, payload) {
|
|
39
39
|
const text = typeof payload === "string" ? payload : payload instanceof Uint8Array ? Buffer.from(payload).toString("utf8") : void 0;
|
|
40
|
-
return
|
|
40
|
+
return chunkMXGS3HMS_cjs.parseJsonBody(contentType, text);
|
|
41
41
|
}
|
|
42
42
|
function refuse(reply, result) {
|
|
43
43
|
const json = JSON.stringify(result.body);
|
|
@@ -54,11 +54,11 @@ function headerValue(value) {
|
|
|
54
54
|
}
|
|
55
55
|
function paymentMiddleware(config) {
|
|
56
56
|
return fp__default.default(async (fastify) => {
|
|
57
|
-
const gate =
|
|
57
|
+
const gate = chunkMXGS3HMS_cjs.createPaymentGate(config);
|
|
58
58
|
const verifiedMap = /* @__PURE__ */ new WeakMap();
|
|
59
59
|
const rawWriters = /* @__PURE__ */ new WeakMap();
|
|
60
60
|
const needsBody = (req) => {
|
|
61
|
-
const route =
|
|
61
|
+
const route = chunkMXGS3HMS_cjs.matchRoute(
|
|
62
62
|
new FastifyAdapter(req).getPath(),
|
|
63
63
|
config.routes
|
|
64
64
|
);
|
|
@@ -111,29 +111,29 @@ function paymentMiddleware(config) {
|
|
|
111
111
|
if (!verified) return payload;
|
|
112
112
|
let raw;
|
|
113
113
|
if (verified.scheme === "upto") {
|
|
114
|
-
raw = headerValue(reply.getHeader(
|
|
115
|
-
reply.removeHeader(
|
|
114
|
+
raw = headerValue(reply.getHeader(chunkMXGS3HMS_cjs.SETTLE_AMOUNT_HEADER));
|
|
115
|
+
reply.removeHeader(chunkMXGS3HMS_cjs.SETTLE_AMOUNT_HEADER);
|
|
116
116
|
}
|
|
117
117
|
if (reply.statusCode < 200 || reply.statusCode >= 300) {
|
|
118
118
|
return payload;
|
|
119
119
|
}
|
|
120
120
|
let settleOptions;
|
|
121
121
|
if (verified.scheme === "upto") {
|
|
122
|
-
const resolved = await
|
|
122
|
+
const resolved = await chunkMXGS3HMS_cjs.resolveCharge(verified, raw, {
|
|
123
123
|
status: reply.statusCode,
|
|
124
124
|
header: (name) => headerValue(reply.getHeader(name)),
|
|
125
125
|
body: async () => payloadJson(headerValue(reply.getHeader("content-type")), payload)
|
|
126
126
|
});
|
|
127
127
|
if (resolved.kind === "invalid") {
|
|
128
|
-
return refuse(reply,
|
|
128
|
+
return refuse(reply, chunkMXGS3HMS_cjs.invalidSettleAmountResponse(resolved.reason));
|
|
129
129
|
}
|
|
130
130
|
if (resolved.kind === "skip") return payload;
|
|
131
131
|
settleOptions = { amount: resolved.amount };
|
|
132
132
|
}
|
|
133
|
-
const outcome = await
|
|
133
|
+
const outcome = await chunkMXGS3HMS_cjs.settleVerified(verified, settleOptions);
|
|
134
134
|
if (!outcome.settled)
|
|
135
|
-
return refuse(reply,
|
|
136
|
-
reply.header("payment-response",
|
|
135
|
+
return refuse(reply, chunkMXGS3HMS_cjs.settlementFailureResponse(outcome));
|
|
136
|
+
reply.header("payment-response", chunkMXGS3HMS_cjs.encodeBase64(outcome.confirmation));
|
|
137
137
|
reply.header("access-control-expose-headers", "payment-response");
|
|
138
138
|
return payload;
|
|
139
139
|
});
|
package/dist/fastify.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createPaymentGate, SETTLE_AMOUNT_HEADER, resolveCharge, invalidSettleAmountResponse, settleVerified, settlementFailureResponse, encodeBase64, matchRoute, parseJsonBody } from './chunk-
|
|
1
|
+
import { createPaymentGate, SETTLE_AMOUNT_HEADER, resolveCharge, invalidSettleAmountResponse, settleVerified, settlementFailureResponse, encodeBase64, matchRoute, parseJsonBody } from './chunk-KTBFF5HI.js';
|
|
2
2
|
import './chunk-QAECRSWF.js';
|
|
3
3
|
import fp from 'fastify-plugin';
|
|
4
4
|
|
package/dist/hono.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkMXGS3HMS_cjs = require('./chunk-MXGS3HMS.cjs');
|
|
4
4
|
require('./chunk-KZZY5LS6.cjs');
|
|
5
5
|
|
|
6
6
|
// src/hono/adapter.ts
|
|
@@ -30,7 +30,7 @@ var HonoAdapter = class {
|
|
|
30
30
|
// Hono caches the parsed body on the request, so the handler can still read
|
|
31
31
|
// it after the price function did.
|
|
32
32
|
async getBody() {
|
|
33
|
-
if (!
|
|
33
|
+
if (!chunkMXGS3HMS_cjs.isJsonContentType(this.c.req.header("content-type"))) return void 0;
|
|
34
34
|
try {
|
|
35
35
|
return await this.c.req.json();
|
|
36
36
|
} catch {
|
|
@@ -38,8 +38,8 @@ var HonoAdapter = class {
|
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
async runHandler(options) {
|
|
41
|
-
const outcome = await
|
|
42
|
-
if (outcome ===
|
|
41
|
+
const outcome = await chunkMXGS3HMS_cjs.raceTimeout(this.next(), options?.timeoutMs);
|
|
42
|
+
if (outcome === chunkMXGS3HMS_cjs.HANDLER_TIMEOUT) {
|
|
43
43
|
return {
|
|
44
44
|
status: 504,
|
|
45
45
|
setResponseHeader: () => {
|
|
@@ -64,7 +64,7 @@ var HonoAdapter = class {
|
|
|
64
64
|
getResponseHeader: (name) => res.headers.get(name) ?? void 0,
|
|
65
65
|
removeResponseHeader: (name) => res.headers.delete(name),
|
|
66
66
|
// Read from a clone: the response body streams once, to the client.
|
|
67
|
-
getResponseBody: () =>
|
|
67
|
+
getResponseBody: () => chunkMXGS3HMS_cjs.jsonFromResponse(res),
|
|
68
68
|
sendResponse: () => {
|
|
69
69
|
},
|
|
70
70
|
// The response is replaced: release its body (and whatever upstream
|
|
@@ -79,7 +79,7 @@ var HonoAdapter = class {
|
|
|
79
79
|
|
|
80
80
|
// src/hono/index.ts
|
|
81
81
|
function paymentMiddleware(config) {
|
|
82
|
-
const middleware =
|
|
82
|
+
const middleware = chunkMXGS3HMS_cjs.createPaymentMiddleware(config);
|
|
83
83
|
return async (c, next) => {
|
|
84
84
|
const result = await middleware(new HonoAdapter(c, next));
|
|
85
85
|
if ("pass" in result) {
|
package/dist/hono.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isJsonContentType, raceTimeout, HANDLER_TIMEOUT, jsonFromResponse, createPaymentMiddleware } from './chunk-
|
|
1
|
+
import { isJsonContentType, raceTimeout, HANDLER_TIMEOUT, jsonFromResponse, createPaymentMiddleware } from './chunk-KTBFF5HI.js';
|
|
2
2
|
import './chunk-QAECRSWF.js';
|
|
3
3
|
|
|
4
4
|
// src/hono/adapter.ts
|
package/dist/index.cjs
CHANGED
|
@@ -1,65 +1,65 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkMXGS3HMS_cjs = require('./chunk-MXGS3HMS.cjs');
|
|
4
4
|
var chunkKZZY5LS6_cjs = require('./chunk-KZZY5LS6.cjs');
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
Object.defineProperty(exports, "FacilitatorClient", {
|
|
9
9
|
enumerable: true,
|
|
10
|
-
get: function () { return
|
|
10
|
+
get: function () { return chunkMXGS3HMS_cjs.FacilitatorClient; }
|
|
11
11
|
});
|
|
12
12
|
Object.defineProperty(exports, "PARALLEL_TOKENS", {
|
|
13
13
|
enumerable: true,
|
|
14
|
-
get: function () { return
|
|
14
|
+
get: function () { return chunkMXGS3HMS_cjs.PARALLEL_TOKENS; }
|
|
15
15
|
});
|
|
16
16
|
Object.defineProperty(exports, "SETTLE_AMOUNT_HEADER", {
|
|
17
17
|
enumerable: true,
|
|
18
|
-
get: function () { return
|
|
18
|
+
get: function () { return chunkMXGS3HMS_cjs.SETTLE_AMOUNT_HEADER; }
|
|
19
19
|
});
|
|
20
20
|
Object.defineProperty(exports, "createPaymentGate", {
|
|
21
21
|
enumerable: true,
|
|
22
|
-
get: function () { return
|
|
22
|
+
get: function () { return chunkMXGS3HMS_cjs.createPaymentGate; }
|
|
23
23
|
});
|
|
24
24
|
Object.defineProperty(exports, "createPaymentMiddleware", {
|
|
25
25
|
enumerable: true,
|
|
26
|
-
get: function () { return
|
|
26
|
+
get: function () { return chunkMXGS3HMS_cjs.createPaymentMiddleware; }
|
|
27
27
|
});
|
|
28
28
|
Object.defineProperty(exports, "encodeBase64", {
|
|
29
29
|
enumerable: true,
|
|
30
|
-
get: function () { return
|
|
30
|
+
get: function () { return chunkMXGS3HMS_cjs.encodeBase64; }
|
|
31
31
|
});
|
|
32
32
|
Object.defineProperty(exports, "getDefaultAcceptedTokens", {
|
|
33
33
|
enumerable: true,
|
|
34
|
-
get: function () { return
|
|
34
|
+
get: function () { return chunkMXGS3HMS_cjs.getDefaultAcceptedTokens; }
|
|
35
35
|
});
|
|
36
36
|
Object.defineProperty(exports, "parsePrice", {
|
|
37
37
|
enumerable: true,
|
|
38
|
-
get: function () { return
|
|
38
|
+
get: function () { return chunkMXGS3HMS_cjs.parsePrice; }
|
|
39
39
|
});
|
|
40
40
|
Object.defineProperty(exports, "resolveCharge", {
|
|
41
41
|
enumerable: true,
|
|
42
|
-
get: function () { return
|
|
42
|
+
get: function () { return chunkMXGS3HMS_cjs.resolveCharge; }
|
|
43
43
|
});
|
|
44
44
|
Object.defineProperty(exports, "resolveSettleAmount", {
|
|
45
45
|
enumerable: true,
|
|
46
|
-
get: function () { return
|
|
46
|
+
get: function () { return chunkMXGS3HMS_cjs.resolveSettleAmount; }
|
|
47
47
|
});
|
|
48
48
|
Object.defineProperty(exports, "settleVerified", {
|
|
49
49
|
enumerable: true,
|
|
50
|
-
get: function () { return
|
|
50
|
+
get: function () { return chunkMXGS3HMS_cjs.settleVerified; }
|
|
51
51
|
});
|
|
52
52
|
Object.defineProperty(exports, "settlementFailureResponse", {
|
|
53
53
|
enumerable: true,
|
|
54
|
-
get: function () { return
|
|
54
|
+
get: function () { return chunkMXGS3HMS_cjs.settlementFailureResponse; }
|
|
55
55
|
});
|
|
56
56
|
Object.defineProperty(exports, "toEip155Network", {
|
|
57
57
|
enumerable: true,
|
|
58
|
-
get: function () { return
|
|
58
|
+
get: function () { return chunkMXGS3HMS_cjs.toEip155Network; }
|
|
59
59
|
});
|
|
60
60
|
Object.defineProperty(exports, "validateAddress", {
|
|
61
61
|
enumerable: true,
|
|
62
|
-
get: function () { return
|
|
62
|
+
get: function () { return chunkMXGS3HMS_cjs.validateAddress; }
|
|
63
63
|
});
|
|
64
64
|
Object.defineProperty(exports, "X402ConfigError", {
|
|
65
65
|
enumerable: true,
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { FacilitatorClient, PARALLEL_TOKENS, SETTLE_AMOUNT_HEADER, createPaymentGate, createPaymentMiddleware, encodeBase64, getDefaultAcceptedTokens, parsePrice, resolveCharge, resolveSettleAmount, settleVerified, settlementFailureResponse, toEip155Network, validateAddress } from './chunk-
|
|
1
|
+
export { FacilitatorClient, PARALLEL_TOKENS, SETTLE_AMOUNT_HEADER, createPaymentGate, createPaymentMiddleware, encodeBase64, getDefaultAcceptedTokens, parsePrice, resolveCharge, resolveSettleAmount, settleVerified, settlementFailureResponse, toEip155Network, validateAddress } from './chunk-KTBFF5HI.js';
|
|
2
2
|
export { X402ConfigError, X402PriceRejectedError, X402RuntimeError, X402_ERROR_CODES, isPriceRejection } from './chunk-QAECRSWF.js';
|
package/dist/next.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkMXGS3HMS_cjs = require('./chunk-MXGS3HMS.cjs');
|
|
4
4
|
require('./chunk-KZZY5LS6.cjs');
|
|
5
5
|
var server = require('next/server');
|
|
6
6
|
|
|
@@ -25,7 +25,7 @@ var NextAdapter = class {
|
|
|
25
25
|
// Read from a clone: a request body is a stream that can be consumed once,
|
|
26
26
|
// and the handler still needs the original.
|
|
27
27
|
async getBody() {
|
|
28
|
-
if (!
|
|
28
|
+
if (!chunkMXGS3HMS_cjs.isJsonContentType(this.req.headers.get("content-type") ?? void 0))
|
|
29
29
|
return void 0;
|
|
30
30
|
try {
|
|
31
31
|
return await this.req.clone().json();
|
|
@@ -43,7 +43,7 @@ function fromResult(result) {
|
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
45
|
function withPayment(config, handler) {
|
|
46
|
-
const gate =
|
|
46
|
+
const gate = chunkMXGS3HMS_cjs.createPaymentGate(config);
|
|
47
47
|
return async (req) => {
|
|
48
48
|
const gateResult = await gate(new NextAdapter(req));
|
|
49
49
|
if (gateResult.type === "pass") {
|
|
@@ -52,11 +52,11 @@ function withPayment(config, handler) {
|
|
|
52
52
|
if (gateResult.type === "error") return fromResult(gateResult.result);
|
|
53
53
|
let response;
|
|
54
54
|
try {
|
|
55
|
-
const outcome = await
|
|
55
|
+
const outcome = await chunkMXGS3HMS_cjs.raceTimeout(
|
|
56
56
|
handler(req),
|
|
57
57
|
gateResult.handlerTimeoutMs
|
|
58
58
|
);
|
|
59
|
-
if (outcome ===
|
|
59
|
+
if (outcome === chunkMXGS3HMS_cjs.HANDLER_TIMEOUT) {
|
|
60
60
|
return new server.NextResponse(null, { status: 504 });
|
|
61
61
|
}
|
|
62
62
|
response = outcome;
|
|
@@ -65,10 +65,10 @@ function withPayment(config, handler) {
|
|
|
65
65
|
}
|
|
66
66
|
let raw;
|
|
67
67
|
if (gateResult.scheme === "upto") {
|
|
68
|
-
raw = response.headers.get(
|
|
68
|
+
raw = response.headers.get(chunkMXGS3HMS_cjs.SETTLE_AMOUNT_HEADER) ?? void 0;
|
|
69
69
|
if (raw !== void 0) {
|
|
70
70
|
const headers = new Headers(response.headers);
|
|
71
|
-
headers.delete(
|
|
71
|
+
headers.delete(chunkMXGS3HMS_cjs.SETTLE_AMOUNT_HEADER);
|
|
72
72
|
response = new server.NextResponse(response.body, {
|
|
73
73
|
status: response.status,
|
|
74
74
|
headers
|
|
@@ -79,24 +79,24 @@ function withPayment(config, handler) {
|
|
|
79
79
|
let settleOptions;
|
|
80
80
|
if (gateResult.scheme === "upto") {
|
|
81
81
|
const handled = response;
|
|
82
|
-
const resolved = await
|
|
82
|
+
const resolved = await chunkMXGS3HMS_cjs.resolveCharge(gateResult, raw, {
|
|
83
83
|
status: handled.status,
|
|
84
84
|
header: (name) => handled.headers.get(name) ?? void 0,
|
|
85
85
|
// Read from a clone: the body streams once, to the client.
|
|
86
|
-
body: () =>
|
|
86
|
+
body: () => chunkMXGS3HMS_cjs.jsonFromResponse(handled)
|
|
87
87
|
});
|
|
88
88
|
if (resolved.kind === "invalid") {
|
|
89
89
|
handled.body?.cancel().catch(() => {
|
|
90
90
|
});
|
|
91
|
-
return fromResult(
|
|
91
|
+
return fromResult(chunkMXGS3HMS_cjs.invalidSettleAmountResponse(resolved.reason));
|
|
92
92
|
}
|
|
93
93
|
if (resolved.kind === "skip") return response;
|
|
94
94
|
settleOptions = { amount: resolved.amount };
|
|
95
95
|
}
|
|
96
|
-
const outcome = await
|
|
96
|
+
const outcome = await chunkMXGS3HMS_cjs.settleVerified(gateResult, settleOptions);
|
|
97
97
|
if (outcome.settled) {
|
|
98
98
|
const headers = new Headers(response.headers);
|
|
99
|
-
headers.set("payment-response",
|
|
99
|
+
headers.set("payment-response", chunkMXGS3HMS_cjs.encodeBase64(outcome.confirmation));
|
|
100
100
|
headers.set("access-control-expose-headers", "payment-response");
|
|
101
101
|
return new server.NextResponse(response.body, {
|
|
102
102
|
status: response.status,
|
|
@@ -105,7 +105,7 @@ function withPayment(config, handler) {
|
|
|
105
105
|
}
|
|
106
106
|
response.body?.cancel().catch(() => {
|
|
107
107
|
});
|
|
108
|
-
return fromResult(
|
|
108
|
+
return fromResult(chunkMXGS3HMS_cjs.settlementFailureResponse(outcome));
|
|
109
109
|
}
|
|
110
110
|
return response;
|
|
111
111
|
};
|
package/dist/next.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isJsonContentType, createPaymentGate, raceTimeout, HANDLER_TIMEOUT, SETTLE_AMOUNT_HEADER, resolveCharge, jsonFromResponse, invalidSettleAmountResponse, settleVerified, encodeBase64, settlementFailureResponse } from './chunk-
|
|
1
|
+
import { isJsonContentType, createPaymentGate, raceTimeout, HANDLER_TIMEOUT, SETTLE_AMOUNT_HEADER, resolveCharge, jsonFromResponse, invalidSettleAmountResponse, settleVerified, encodeBase64, settlementFailureResponse } from './chunk-KTBFF5HI.js';
|
|
2
2
|
import './chunk-QAECRSWF.js';
|
|
3
3
|
import { NextResponse } from 'next/server';
|
|
4
4
|
|
package/package.json
CHANGED