@absol-labs/agent 0.11.0 → 0.12.0-rc.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 +43 -51
- package/dist/capability/invocation-capability.d.ts +2 -2
- package/dist/capability/probe-capability.d.ts +225 -0
- package/dist/capability/probe-capability.d.ts.map +1 -0
- package/dist/capability/probe-capability.js +248 -0
- package/dist/capability/probe-capability.js.map +1 -0
- package/dist/cli/args.d.ts +11 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +23 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/commands/claim.d.ts +32 -0
- package/dist/cli/commands/claim.d.ts.map +1 -1
- package/dist/cli/commands/claim.js +116 -28
- package/dist/cli/commands/claim.js.map +1 -1
- package/dist/cli/commands/close.d.ts.map +1 -1
- package/dist/cli/commands/close.js +35 -3
- package/dist/cli/commands/close.js.map +1 -1
- package/dist/cli/commands/invoke.d.ts +2 -0
- package/dist/cli/commands/invoke.d.ts.map +1 -1
- package/dist/cli/commands/invoke.js +2 -2
- package/dist/cli/commands/invoke.js.map +1 -1
- package/dist/cli/commands/mcp.d.ts.map +1 -1
- package/dist/cli/commands/mcp.js +15 -2
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/commands/open.d.ts.map +1 -1
- package/dist/cli/commands/open.js +58 -4
- package/dist/cli/commands/open.js.map +1 -1
- package/dist/cli/commands/pay.d.ts +34 -0
- package/dist/cli/commands/pay.d.ts.map +1 -0
- package/dist/cli/commands/pay.js +479 -0
- package/dist/cli/commands/pay.js.map +1 -0
- package/dist/cli/commands/reclaim-unverified.d.ts.map +1 -1
- package/dist/cli/commands/reclaim-unverified.js +3 -2
- package/dist/cli/commands/reclaim-unverified.js.map +1 -1
- package/dist/cli/commands/reclaim.d.ts +23 -2
- package/dist/cli/commands/reclaim.d.ts.map +1 -1
- package/dist/cli/commands/reclaim.js +204 -20
- package/dist/cli/commands/reclaim.js.map +1 -1
- package/dist/cli/commands/refund.d.ts +31 -0
- package/dist/cli/commands/refund.d.ts.map +1 -0
- package/dist/cli/commands/refund.js +397 -0
- package/dist/cli/commands/refund.js.map +1 -0
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +21 -2
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/commands/streams.js +8 -12
- package/dist/cli/commands/streams.js.map +1 -1
- package/dist/cli/commands/watch.d.ts.map +1 -1
- package/dist/cli/commands/watch.js +4 -1
- package/dist/cli/commands/watch.js.map +1 -1
- package/dist/cli/config.d.ts +44 -26
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/config.js +88 -38
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/context.d.ts +19 -0
- package/dist/cli/context.d.ts.map +1 -1
- package/dist/cli/deps.d.ts +53 -0
- package/dist/cli/deps.d.ts.map +1 -1
- package/dist/cli/deps.js +51 -1
- package/dist/cli/deps.js.map +1 -1
- package/dist/cli/errors.d.ts.map +1 -1
- package/dist/cli/errors.js +21 -1
- package/dist/cli/errors.js.map +1 -1
- package/dist/cli/escape-hatch.d.ts +6 -4
- package/dist/cli/escape-hatch.d.ts.map +1 -1
- package/dist/cli/escape-hatch.js +6 -2
- package/dist/cli/escape-hatch.js.map +1 -1
- package/dist/cli/listings.d.ts +18 -0
- package/dist/cli/listings.d.ts.map +1 -1
- package/dist/cli/listings.js +22 -12
- package/dist/cli/listings.js.map +1 -1
- package/dist/cli/preflight.d.ts +20 -14
- package/dist/cli/preflight.d.ts.map +1 -1
- package/dist/cli/preflight.js +34 -20
- package/dist/cli/preflight.js.map +1 -1
- package/dist/cli/privy.d.ts.map +1 -1
- package/dist/cli/privy.js +4 -2
- package/dist/cli/privy.js.map +1 -1
- package/dist/cli/progress.d.ts +13 -1
- package/dist/cli/progress.d.ts.map +1 -1
- package/dist/cli/progress.js +7 -1
- package/dist/cli/progress.js.map +1 -1
- package/dist/cli/reclaimability.d.ts +82 -0
- package/dist/cli/reclaimability.d.ts.map +1 -0
- package/dist/cli/reclaimability.js +80 -0
- package/dist/cli/reclaimability.js.map +1 -0
- package/dist/cli/run.d.ts +2 -1
- package/dist/cli/run.d.ts.map +1 -1
- package/dist/cli/run.js +62 -21
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/scan-range.d.ts +2 -2
- package/dist/cli/scan-range.js +2 -2
- package/dist/cli/status.d.ts +106 -1
- package/dist/cli/status.d.ts.map +1 -1
- package/dist/cli/status.js +325 -44
- package/dist/cli/status.js.map +1 -1
- package/dist/cli/wallet.d.ts +2 -2
- package/dist/cli/wallet.d.ts.map +1 -1
- package/dist/cli/wallet.js +29 -5
- package/dist/cli/wallet.js.map +1 -1
- package/dist/discovery/rate-band.d.ts +74 -0
- package/dist/discovery/rate-band.d.ts.map +1 -0
- package/dist/discovery/rate-band.js +114 -0
- package/dist/discovery/rate-band.js.map +1 -0
- package/dist/escrow-generation.d.ts +81 -0
- package/dist/escrow-generation.d.ts.map +1 -0
- package/dist/escrow-generation.js +76 -0
- package/dist/escrow-generation.js.map +1 -0
- package/dist/frameworks/agentkit.d.ts +8 -4
- package/dist/frameworks/agentkit.d.ts.map +1 -1
- package/dist/frameworks/agentkit.js +27 -10
- package/dist/frameworks/agentkit.js.map +1 -1
- package/dist/frameworks/eliza.d.ts +3 -3
- package/dist/frameworks/eliza.d.ts.map +1 -1
- package/dist/frameworks/eliza.js +15 -6
- package/dist/frameworks/eliza.js.map +1 -1
- package/dist/frameworks/langchain.d.ts.map +1 -1
- package/dist/frameworks/langchain.js +8 -0
- package/dist/frameworks/langchain.js.map +1 -1
- package/dist/gateway/caller-auth-gateway.d.ts +83 -31
- package/dist/gateway/caller-auth-gateway.d.ts.map +1 -1
- package/dist/gateway/caller-auth-gateway.js +180 -27
- package/dist/gateway/caller-auth-gateway.js.map +1 -1
- package/dist/gateway/http-server.d.ts +128 -44
- package/dist/gateway/http-server.d.ts.map +1 -1
- package/dist/gateway/http-server.js +506 -155
- package/dist/gateway/http-server.js.map +1 -1
- package/dist/gateway/probe-auth.d.ts +112 -0
- package/dist/gateway/probe-auth.d.ts.map +1 -0
- package/dist/gateway/probe-auth.js +127 -0
- package/dist/gateway/probe-auth.js.map +1 -0
- package/dist/gateway/signed-rate-bounds.d.ts +51 -0
- package/dist/gateway/signed-rate-bounds.d.ts.map +1 -0
- package/dist/gateway/signed-rate-bounds.js +94 -0
- package/dist/gateway/signed-rate-bounds.js.map +1 -0
- package/dist/gateway/x402-opener-mode.d.ts +252 -0
- package/dist/gateway/x402-opener-mode.d.ts.map +1 -0
- package/dist/gateway/x402-opener-mode.js +772 -0
- package/dist/gateway/x402-opener-mode.js.map +1 -0
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -5
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.d.ts +64 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +247 -37
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/x402-tools.d.ts +109 -0
- package/dist/mcp/x402-tools.d.ts.map +1 -0
- package/dist/mcp/x402-tools.js +554 -0
- package/dist/mcp/x402-tools.js.map +1 -0
- package/dist/network.d.ts +119 -0
- package/dist/network.d.ts.map +1 -0
- package/dist/network.js +199 -0
- package/dist/network.js.map +1 -0
- package/dist/sdk/client.d.ts +13 -0
- package/dist/sdk/client.d.ts.map +1 -1
- package/dist/sdk/client.js +15 -0
- package/dist/sdk/client.js.map +1 -1
- package/dist/sdk/invoke.d.ts +4 -0
- package/dist/sdk/invoke.d.ts.map +1 -1
- package/dist/sdk/invoke.js +2 -5
- package/dist/sdk/invoke.js.map +1 -1
- package/dist/wallet/autonomous-wallet-broker.d.ts +3 -0
- package/dist/wallet/autonomous-wallet-broker.d.ts.map +1 -1
- package/dist/wallet/autonomous-wallet-broker.js +27 -23
- package/dist/wallet/autonomous-wallet-broker.js.map +1 -1
- package/dist/wallet/autonomous-wallet-protocol.d.ts +8 -2
- package/dist/wallet/autonomous-wallet-protocol.d.ts.map +1 -1
- package/dist/wallet/autonomous-wallet-protocol.js +9 -2
- package/dist/wallet/autonomous-wallet-protocol.js.map +1 -1
- package/dist/wallet/autonomous-wallet.d.ts.map +1 -1
- package/dist/wallet/autonomous-wallet.js +3 -2
- package/dist/wallet/autonomous-wallet.js.map +1 -1
- package/dist/wallet/broker-escrows.d.ts +222 -0
- package/dist/wallet/broker-escrows.d.ts.map +1 -0
- package/dist/wallet/broker-escrows.js +36 -0
- package/dist/wallet/broker-escrows.js.map +1 -0
- package/dist/wallet/lifecycle.d.ts +21 -5
- package/dist/wallet/lifecycle.d.ts.map +1 -1
- package/dist/wallet/lifecycle.js +32 -12
- package/dist/wallet/lifecycle.js.map +1 -1
- package/dist/wallet/privy-broker-server.d.ts.map +1 -1
- package/dist/wallet/privy-broker-server.js +31 -26
- package/dist/wallet/privy-broker-server.js.map +1 -1
- package/dist/wallet/privy-session-broker.d.ts +14 -5
- package/dist/wallet/privy-session-broker.d.ts.map +1 -1
- package/dist/wallet/privy-session-broker.js +29 -17
- package/dist/wallet/privy-session-broker.js.map +1 -1
- package/dist/wallet/privy-session-provider.d.ts +3 -1
- package/dist/wallet/privy-session-provider.d.ts.map +1 -1
- package/dist/wallet/privy-session-provider.js +5 -3
- package/dist/wallet/privy-session-provider.js.map +1 -1
- package/dist/wallet/provider.d.ts.map +1 -1
- package/dist/wallet/provider.js +15 -8
- package/dist/wallet/provider.js.map +1 -1
- package/dist/x402/facilitator.d.ts +3 -30
- package/dist/x402/facilitator.d.ts.map +1 -1
- package/dist/x402/facilitator.js +0 -27
- package/dist/x402/facilitator.js.map +1 -1
- package/dist/x402-buyer/guarded-fetch.d.ts +51 -0
- package/dist/x402-buyer/guarded-fetch.d.ts.map +1 -0
- package/dist/x402-buyer/guarded-fetch.js +147 -0
- package/dist/x402-buyer/guarded-fetch.js.map +1 -0
- package/dist/x402-buyer/index.d.ts +10 -0
- package/dist/x402-buyer/index.d.ts.map +1 -0
- package/dist/x402-buyer/index.js +10 -0
- package/dist/x402-buyer/index.js.map +1 -0
- package/dist/x402-buyer/pay.d.ts +157 -0
- package/dist/x402-buyer/pay.d.ts.map +1 -0
- package/dist/x402-buyer/pay.js +366 -0
- package/dist/x402-buyer/pay.js.map +1 -0
- package/dist/x402-opener/abi.d.ts +684 -0
- package/dist/x402-opener/abi.d.ts.map +1 -0
- package/dist/x402-opener/abi.js +880 -0
- package/dist/x402-opener/abi.js.map +1 -0
- package/dist/x402-opener/facilitator-entry.d.ts +3 -0
- package/dist/x402-opener/facilitator-entry.d.ts.map +1 -0
- package/dist/x402-opener/facilitator-entry.js +40 -0
- package/dist/x402-opener/facilitator-entry.js.map +1 -0
- package/dist/x402-opener/facilitator-server.d.ts +209 -0
- package/dist/x402-opener/facilitator-server.d.ts.map +1 -0
- package/dist/x402-opener/facilitator-server.js +762 -0
- package/dist/x402-opener/facilitator-server.js.map +1 -0
- package/dist/x402-opener/index.d.ts +14 -0
- package/dist/x402-opener/index.d.ts.map +1 -0
- package/dist/x402-opener/index.js +14 -0
- package/dist/x402-opener/index.js.map +1 -0
- package/dist/x402-opener/listing-resolver.d.ts +55 -0
- package/dist/x402-opener/listing-resolver.d.ts.map +1 -0
- package/dist/x402-opener/listing-resolver.js +125 -0
- package/dist/x402-opener/listing-resolver.js.map +1 -0
- package/dist/x402-opener/refund-relay.d.ts +266 -0
- package/dist/x402-opener/refund-relay.d.ts.map +1 -0
- package/dist/x402-opener/refund-relay.js +1341 -0
- package/dist/x402-opener/refund-relay.js.map +1 -0
- package/dist/x402-opener/relayer-queue.d.ts +14 -0
- package/dist/x402-opener/relayer-queue.d.ts.map +1 -0
- package/dist/x402-opener/relayer-queue.js +18 -0
- package/dist/x402-opener/relayer-queue.js.map +1 -0
- package/dist/x402-opener/scheme.d.ts +296 -0
- package/dist/x402-opener/scheme.d.ts.map +1 -0
- package/dist/x402-opener/scheme.js +1035 -0
- package/dist/x402-opener/scheme.js.map +1 -0
- package/dist/x402-opener/terms.d.ts +165 -0
- package/dist/x402-opener/terms.d.ts.map +1 -0
- package/dist/x402-opener/terms.js +304 -0
- package/dist/x402-opener/terms.js.map +1 -0
- package/dist/zktls/reclaim.d.ts +2 -2
- package/dist/zktls/t2-delivery-proof.d.ts +6 -6
- package/docs/agent-layer.md +3 -2
- package/docs/autonomous-privy-wallet.md +188 -0
- package/docs/cli.md +265 -34
- package/docs/langchain.md +5 -0
- package/docs/mcp-reference.md +91 -5
- package/docs/probe-capability.md +191 -0
- package/docs/quickstart.md +39 -4
- package/docs/threat-model.md +20 -0
- package/docs/x402.md +766 -593
- package/package.json +19 -17
- package/src/capability/probe-capability.ts +355 -0
- package/src/cli/args.ts +29 -0
- package/src/cli/commands/claim.ts +168 -33
- package/src/cli/commands/close.ts +36 -3
- package/src/cli/commands/invoke.ts +5 -2
- package/src/cli/commands/mcp.ts +18 -2
- package/src/cli/commands/open.ts +75 -4
- package/src/cli/commands/pay.ts +584 -0
- package/src/cli/commands/reclaim-unverified.ts +8 -2
- package/src/cli/commands/reclaim.ts +277 -19
- package/src/cli/commands/refund.ts +475 -0
- package/src/cli/commands/status.ts +28 -2
- package/src/cli/commands/streams.ts +10 -14
- package/src/cli/commands/watch.ts +11 -1
- package/src/cli/config.ts +139 -52
- package/src/cli/context.ts +16 -0
- package/src/cli/deps.ts +111 -1
- package/src/cli/errors.ts +24 -1
- package/src/cli/escape-hatch.ts +19 -5
- package/src/cli/listings.ts +43 -10
- package/src/cli/preflight.ts +36 -21
- package/src/cli/privy.ts +4 -2
- package/src/cli/progress.ts +21 -2
- package/src/cli/reclaimability.ts +154 -0
- package/src/cli/run.ts +77 -21
- package/src/cli/scan-range.ts +2 -2
- package/src/cli/status.ts +454 -44
- package/src/cli/wallet.ts +45 -8
- package/src/discovery/rate-band.ts +172 -0
- package/src/escrow-generation.ts +135 -0
- package/src/frameworks/agentkit.ts +45 -11
- package/src/frameworks/eliza.ts +27 -5
- package/src/frameworks/langchain.ts +14 -0
- package/src/gateway/caller-auth-gateway.ts +320 -68
- package/src/gateway/http-server.ts +717 -220
- package/src/gateway/probe-auth.ts +191 -0
- package/src/gateway/signed-rate-bounds.ts +164 -0
- package/src/gateway/x402-opener-mode.ts +1171 -0
- package/src/index.ts +82 -19
- package/src/mcp/server.ts +351 -42
- package/src/mcp/x402-tools.ts +785 -0
- package/src/network.ts +302 -0
- package/src/sdk/client.ts +25 -0
- package/src/sdk/invoke.ts +6 -5
- package/src/wallet/autonomous-wallet-broker.ts +46 -20
- package/src/wallet/autonomous-wallet-protocol.ts +11 -2
- package/src/wallet/autonomous-wallet.ts +4 -2
- package/src/wallet/broker-escrows.ts +66 -0
- package/src/wallet/lifecycle.ts +53 -18
- package/src/wallet/privy-broker-server.ts +35 -25
- package/src/wallet/privy-session-broker.ts +58 -25
- package/src/wallet/privy-session-provider.ts +7 -3
- package/src/wallet/provider.ts +20 -15
- package/src/x402/facilitator.ts +3 -43
- package/src/x402-buyer/guarded-fetch.ts +213 -0
- package/src/x402-buyer/index.ts +9 -0
- package/src/x402-buyer/pay.ts +555 -0
- package/src/x402-opener/abi.ts +881 -0
- package/src/x402-opener/facilitator-entry.ts +48 -0
- package/src/x402-opener/facilitator-server.ts +1114 -0
- package/src/x402-opener/index.ts +13 -0
- package/src/x402-opener/listing-resolver.ts +202 -0
- package/src/x402-opener/refund-relay.ts +1873 -0
- package/src/x402-opener/relayer-queue.ts +18 -0
- package/src/x402-opener/scheme.ts +1551 -0
- package/src/x402-opener/terms.ts +453 -0
- package/dist/gateway/x402-mode.d.ts +0 -123
- package/dist/gateway/x402-mode.d.ts.map +0 -1
- package/dist/gateway/x402-mode.js +0 -212
- package/dist/gateway/x402-mode.js.map +0 -1
- package/dist/x402/delivery-oracle.d.ts +0 -108
- package/dist/x402/delivery-oracle.d.ts.map +0 -1
- package/dist/x402/delivery-oracle.js +0 -174
- package/dist/x402/delivery-oracle.js.map +0 -1
- package/dist/x402/facilitator-server-entry.d.ts +0 -3
- package/dist/x402/facilitator-server-entry.d.ts.map +0 -1
- package/dist/x402/facilitator-server-entry.js +0 -27
- package/dist/x402/facilitator-server-entry.js.map +0 -1
- package/dist/x402/facilitator-server.d.ts +0 -73
- package/dist/x402/facilitator-server.d.ts.map +0 -1
- package/dist/x402/facilitator-server.js +0 -305
- package/dist/x402/facilitator-server.js.map +0 -1
- package/dist/x402/payment-requirements.d.ts +0 -106
- package/dist/x402/payment-requirements.d.ts.map +0 -1
- package/dist/x402/payment-requirements.js +0 -138
- package/dist/x402/payment-requirements.js.map +0 -1
- package/dist/x402/relayer.d.ts +0 -41
- package/dist/x402/relayer.d.ts.map +0 -1
- package/dist/x402/relayer.js +0 -64
- package/dist/x402/relayer.js.map +0 -1
- package/dist/x402/resource-index.d.ts +0 -75
- package/dist/x402/resource-index.d.ts.map +0 -1
- package/dist/x402/resource-index.js +0 -126
- package/dist/x402/resource-index.js.map +0 -1
- package/dist/x402/verified-delivery-facilitator.d.ts +0 -285
- package/dist/x402/verified-delivery-facilitator.d.ts.map +0 -1
- package/dist/x402/verified-delivery-facilitator.js +0 -423
- package/dist/x402/verified-delivery-facilitator.js.map +0 -1
- package/src/gateway/x402-mode.ts +0 -350
- package/src/x402/delivery-oracle.ts +0 -285
- package/src/x402/facilitator-server-entry.ts +0 -35
- package/src/x402/facilitator-server.ts +0 -445
- package/src/x402/payment-requirements.ts +0 -231
- package/src/x402/relayer.ts +0 -122
- package/src/x402/resource-index.ts +0 -228
- package/src/x402/verified-delivery-facilitator.ts +0 -744
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
import { buildMetrikPaymentRequirements, buildX402PaymentRequiredBody, } from "../x402/payment-requirements.js";
|
|
2
|
-
/**
|
|
3
|
-
* Standard x402 mode for the seller-side gateway (Tier 1).
|
|
4
|
-
*
|
|
5
|
-
* The gateway already authorizes requests that carry a Metrik
|
|
6
|
-
* `InvocationCapability` — a buyer with an open, funded, verified stream. That
|
|
7
|
-
* path is untouched. This module adds a SECOND, independent way in: a request
|
|
8
|
-
* with no capability gets an ordinary HTTP `402` carrying real x402
|
|
9
|
-
* `PaymentRequirements`, so an agent holding nothing but `x402-fetch` can pay
|
|
10
|
-
* per call without knowing Metrik exists.
|
|
11
|
-
*
|
|
12
|
-
* ## The two paths never overlap
|
|
13
|
-
*
|
|
14
|
-
* - capability header present -> stream path, exactly as before;
|
|
15
|
-
* - capability header absent, x402 mode on -> `402` + `PaymentRequirements`;
|
|
16
|
-
* - BOTH present -> rejected. A request that looks like both is ambiguous about
|
|
17
|
-
* which one is paying for it, and the failure mode of guessing is charging the
|
|
18
|
-
* caller twice for one call. Better a loud `400` than a silent double charge.
|
|
19
|
-
*
|
|
20
|
-
* ## The per-call price is the seller's, and is not signed
|
|
21
|
-
*
|
|
22
|
-
* `payTo` comes from the operator-signed descriptor (see
|
|
23
|
-
* `../x402/payment-requirements.ts`). The price does not — the descriptor has no
|
|
24
|
-
* per-call price field. It is the seller's own number on the seller's own
|
|
25
|
-
* gateway, which is legitimate, but a buyer cannot cross-check it against the
|
|
26
|
-
* registry the way they can cross-check the payee.
|
|
27
|
-
*/
|
|
28
|
-
/** Request header carrying the x402 payment payload (x402 v1). */
|
|
29
|
-
export const X402_PAYMENT_HEADER = "x-payment";
|
|
30
|
-
/** Response header carrying the settlement result (x402 v1). */
|
|
31
|
-
export const X402_PAYMENT_RESPONSE_HEADER = "x-payment-response";
|
|
32
|
-
/**
|
|
33
|
-
* Talks to any x402 facilitator over HTTP — including Metrik's own
|
|
34
|
-
* (`../x402/facilitator-server.ts`), which is the point: a seller who wires this
|
|
35
|
-
* gateway to the Metrik facilitator gets a paywall whose payments stop when
|
|
36
|
-
* their own delivery stops being verifiable.
|
|
37
|
-
*/
|
|
38
|
-
export function createHttpFacilitatorClient(options) {
|
|
39
|
-
const base = options.url.replace(/\/+$/, "");
|
|
40
|
-
const timeoutMs = options.timeoutMs ?? 10_000;
|
|
41
|
-
const doFetch = options.fetch ?? globalThis.fetch;
|
|
42
|
-
async function post(path, body) {
|
|
43
|
-
const controller = new AbortController();
|
|
44
|
-
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
45
|
-
try {
|
|
46
|
-
const response = await doFetch(`${base}${path}`, {
|
|
47
|
-
method: "POST",
|
|
48
|
-
headers: {
|
|
49
|
-
"content-type": "application/json",
|
|
50
|
-
...(options.token === undefined
|
|
51
|
-
? {}
|
|
52
|
-
: { authorization: `Bearer ${options.token}` }),
|
|
53
|
-
...(options.headers ?? {}),
|
|
54
|
-
},
|
|
55
|
-
body: JSON.stringify(body),
|
|
56
|
-
signal: controller.signal,
|
|
57
|
-
});
|
|
58
|
-
return await response.json();
|
|
59
|
-
}
|
|
60
|
-
finally {
|
|
61
|
-
clearTimeout(timer);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
return {
|
|
65
|
-
async verify(payload, requirements) {
|
|
66
|
-
const result = (await post("/verify", {
|
|
67
|
-
x402Version: 1,
|
|
68
|
-
paymentPayload: payload,
|
|
69
|
-
paymentRequirements: requirements,
|
|
70
|
-
}));
|
|
71
|
-
// Fail closed: an unreadable facilitator answer is not a pass.
|
|
72
|
-
if (typeof result !== "object" || result === null) {
|
|
73
|
-
return { isValid: false, invalidReason: "unexpected_verify_error" };
|
|
74
|
-
}
|
|
75
|
-
return result;
|
|
76
|
-
},
|
|
77
|
-
async settle(payload, requirements) {
|
|
78
|
-
return (await post("/settle", {
|
|
79
|
-
x402Version: 1,
|
|
80
|
-
paymentPayload: payload,
|
|
81
|
-
paymentRequirements: requirements,
|
|
82
|
-
}));
|
|
83
|
-
},
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
/** One flat price per call, quoted against the request's own path. */
|
|
87
|
-
export function createListingPriceQuoter(options) {
|
|
88
|
-
const base = new URL(options.resourceBaseUrl);
|
|
89
|
-
return (request) => [
|
|
90
|
-
buildMetrikPaymentRequirements({
|
|
91
|
-
listing: options.listing,
|
|
92
|
-
resource: new URL(request.path, base).toString(),
|
|
93
|
-
priceBaseUnits: options.pricePerCallBaseUnits,
|
|
94
|
-
chainId: options.chainId,
|
|
95
|
-
...(options.description === undefined
|
|
96
|
-
? {}
|
|
97
|
-
: { description: options.description }),
|
|
98
|
-
...(options.mimeType === undefined ? {} : { mimeType: options.mimeType }),
|
|
99
|
-
...(options.maxTimeoutSeconds === undefined
|
|
100
|
-
? {}
|
|
101
|
-
: { maxTimeoutSeconds: options.maxTimeoutSeconds }),
|
|
102
|
-
...(options.asset === undefined ? {} : { asset: options.asset }),
|
|
103
|
-
}),
|
|
104
|
-
];
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Evaluates the x402 half of a request. Returns either the `402` body to send or
|
|
108
|
-
* an accepted payment to settle after the upstream has been called.
|
|
109
|
-
*/
|
|
110
|
-
export async function evaluateX402Request(request, paymentHeader, mode) {
|
|
111
|
-
const accepts = await mode.quote(request);
|
|
112
|
-
if (paymentHeader === undefined || paymentHeader.trim().length === 0) {
|
|
113
|
-
return {
|
|
114
|
-
outcome: "payment-required",
|
|
115
|
-
body: buildX402PaymentRequiredBody(accepts),
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
const payload = decodePaymentHeader(paymentHeader);
|
|
119
|
-
if (payload === undefined) {
|
|
120
|
-
return {
|
|
121
|
-
outcome: "payment-required",
|
|
122
|
-
body: buildX402PaymentRequiredBody(accepts, "X-PAYMENT header is not base64-encoded JSON"),
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
const requirements = selectRequirements(accepts, payload);
|
|
126
|
-
if (requirements === undefined) {
|
|
127
|
-
return {
|
|
128
|
-
outcome: "payment-required",
|
|
129
|
-
body: buildX402PaymentRequiredBody(accepts, "X-PAYMENT does not match any offered payment requirements"),
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
let verified;
|
|
133
|
-
try {
|
|
134
|
-
verified = await mode.facilitator.verify(payload, requirements);
|
|
135
|
-
}
|
|
136
|
-
catch (error) {
|
|
137
|
-
// An unreachable facilitator is a refusal, never a free call.
|
|
138
|
-
return {
|
|
139
|
-
outcome: "payment-required",
|
|
140
|
-
body: buildX402PaymentRequiredBody(accepts, `payment could not be verified: ${error instanceof Error ? error.message : "facilitator unreachable"}`),
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
if (!verified.isValid) {
|
|
144
|
-
return {
|
|
145
|
-
outcome: "payment-required",
|
|
146
|
-
body: buildX402PaymentRequiredBody(accepts, verified.invalidReason ?? "payment rejected by facilitator"),
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
// A Metrik facilitator reports up front whether it would actually broadcast
|
|
150
|
-
// this payment (asset allowlist, settlement scope, ...). Refusing HERE — before
|
|
151
|
-
// the upstream runs — is the difference between "the caller gets nothing" and
|
|
152
|
-
// "the caller gets the upstream's side effects for free and we cannot charge
|
|
153
|
-
// for them". A non-Metrik facilitator omits the field and nothing changes.
|
|
154
|
-
const annotation = verified.metrik;
|
|
155
|
-
if (annotation?.settleable === false) {
|
|
156
|
-
return {
|
|
157
|
-
outcome: "payment-required",
|
|
158
|
-
body: buildX402PaymentRequiredBody(accepts, `facilitator will not settle this payment: ${annotation.detail ?? "refused"}`),
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
const validBefore = readValidBefore(payload);
|
|
162
|
-
return {
|
|
163
|
-
outcome: "accepted",
|
|
164
|
-
payment: {
|
|
165
|
-
payload,
|
|
166
|
-
requirements,
|
|
167
|
-
...(verified.payer === undefined ? {} : { payer: verified.payer }),
|
|
168
|
-
...(validBefore === undefined ? {} : { validBefore }),
|
|
169
|
-
},
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
/** Reads the exact-EVM authorization deadline, if the payload has one. */
|
|
173
|
-
function readValidBefore(payload) {
|
|
174
|
-
const authorization = payload?.payload?.authorization;
|
|
175
|
-
const raw = authorization?.validBefore;
|
|
176
|
-
if (typeof raw !== "string" && typeof raw !== "number") {
|
|
177
|
-
return undefined;
|
|
178
|
-
}
|
|
179
|
-
const parsed = Number(raw);
|
|
180
|
-
return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;
|
|
181
|
-
}
|
|
182
|
-
/**
|
|
183
|
-
* Seconds of headroom the settlement leg needs after the upstream returns.
|
|
184
|
-
*
|
|
185
|
-
* The x402 `exact` verifier rejects an authorization whose `validBefore` is less
|
|
186
|
-
* than 6 s away, so an upstream allowed to run right up to the deadline would
|
|
187
|
-
* hand back a response that can never be settled. This leaves room for that
|
|
188
|
-
* check plus the settle round trip.
|
|
189
|
-
*/
|
|
190
|
-
export const X402_SETTLEMENT_HEADROOM_SECONDS = 10;
|
|
191
|
-
/** Matches the payload's scheme+network against the quotes actually offered. */
|
|
192
|
-
function selectRequirements(accepts, payload) {
|
|
193
|
-
if (typeof payload !== "object" || payload === null) {
|
|
194
|
-
return undefined;
|
|
195
|
-
}
|
|
196
|
-
const { scheme, network } = payload;
|
|
197
|
-
return accepts.find((candidate) => candidate.scheme === scheme && candidate.network === network);
|
|
198
|
-
}
|
|
199
|
-
export function decodePaymentHeader(header) {
|
|
200
|
-
try {
|
|
201
|
-
const decoded = Buffer.from(header.trim(), "base64").toString("utf8");
|
|
202
|
-
const parsed = JSON.parse(decoded);
|
|
203
|
-
return typeof parsed === "object" && parsed !== null ? parsed : undefined;
|
|
204
|
-
}
|
|
205
|
-
catch {
|
|
206
|
-
return undefined;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
export function encodeSettleResponseHeader(response) {
|
|
210
|
-
return Buffer.from(JSON.stringify(response), "utf8").toString("base64");
|
|
211
|
-
}
|
|
212
|
-
//# sourceMappingURL=x402-mode.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"x402-mode.js","sourceRoot":"","sources":["../../src/gateway/x402-mode.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The Metrik delivery signal, as consumed by the x402 facilitator.
|
|
3
|
-
*
|
|
4
|
-
* ## Where the signal comes from
|
|
5
|
-
*
|
|
6
|
-
* The oracle publishes `GET /services` — one row per `serviceRef`, reduced from
|
|
7
|
-
* the oracle's own settlement-path verdicts for the active streams of that
|
|
8
|
-
* service (`streamproof-oracle/src/service-status.ts`). Its three states are
|
|
9
|
-
* already buyer-favouring at the source: a FRESH failing stream beats a fresh
|
|
10
|
-
* delivering sibling, and absent/stale evidence is reported as `unverified`
|
|
11
|
-
* rather than folded into "fine".
|
|
12
|
-
*
|
|
13
|
-
* ## Why this module re-checks freshness the oracle already checked
|
|
14
|
-
*
|
|
15
|
-
* The oracle's own bound is 5 minutes (`DEFAULT_SERVICE_STATUS_TTL_MS`), which
|
|
16
|
-
* is a sensible bound for a dashboard and far too loose for a payment gate. On
|
|
17
|
-
* top of that the HTTP response itself can be cached or served by a stale
|
|
18
|
-
* replica, and `lastCheckedAt` is the only field that dates the EVIDENCE rather
|
|
19
|
-
* than the response. So the age of `lastCheckedAt` is re-derived here against
|
|
20
|
-
* this module's own, much tighter window.
|
|
21
|
-
*
|
|
22
|
-
* ## The freshness window: 90 seconds, and why
|
|
23
|
-
*
|
|
24
|
-
* The oracle checkpoints every ~15–22 s, and a service's recorded status is
|
|
25
|
-
* refreshed on that cadence. A window has to be wide enough that ordinary
|
|
26
|
-
* jitter does not flap the gate, and narrow enough that "verified" still means
|
|
27
|
-
* "now":
|
|
28
|
-
*
|
|
29
|
-
* - 3 worst-case probe intervals (3 x 22 s = 66 s) absorbs two consecutive
|
|
30
|
-
* missed or slow ticks, which is normal operational noise, not evidence of
|
|
31
|
-
* a dead service.
|
|
32
|
-
* - plus the oracle's own record-and-serve latency and this process's fetch
|
|
33
|
-
* round trip, rounded up: **90 s**.
|
|
34
|
-
*
|
|
35
|
-
* Tighter (e.g. 30 s) and a single slow tick turns a healthy service's gate
|
|
36
|
-
* indeterminate. Looser (e.g. the oracle's own 300 s) and a service that died
|
|
37
|
-
* four minutes ago still reads `delivering`, which is exactly the claim this
|
|
38
|
-
* gate exists to avoid making.
|
|
39
|
-
*
|
|
40
|
-
* Note this window is strictly stricter than the oracle's: a verdict aged
|
|
41
|
-
* between 90 s and 300 s is `delivering` at the source and `indeterminate`
|
|
42
|
-
* here.
|
|
43
|
-
*/
|
|
44
|
-
export declare const DEFAULT_DELIVERY_FRESHNESS_SECONDS = 90;
|
|
45
|
-
/** How long a fetched `/services` snapshot may be reused. See `verdictFor`. */
|
|
46
|
-
export declare const DEFAULT_DELIVERY_SNAPSHOT_TTL_MS = 10000;
|
|
47
|
-
/** Request timeout for the oracle read. Short: this sits in a payment hot path. */
|
|
48
|
-
export declare const DEFAULT_DELIVERY_ORACLE_TIMEOUT_MS = 4000;
|
|
49
|
-
export declare const DEFAULT_METRIK_ORACLE_URL = "https://oracle.metrik.live";
|
|
50
|
-
/**
|
|
51
|
-
* Three states, never two.
|
|
52
|
-
*
|
|
53
|
-
* `indeterminate` is deliberately NOT collapsed into either of the others: the
|
|
54
|
-
* facilitator's policy for "no fresh evidence" is a separate, configurable
|
|
55
|
-
* decision (see `./verified-delivery-facilitator.ts`), and folding it into
|
|
56
|
-
* `failing` would make Metrik refuse every payment whenever its own oracle is
|
|
57
|
-
* quiet or unreachable.
|
|
58
|
-
*/
|
|
59
|
-
export type DeliveryVerdict = "delivering" | "failing" | "indeterminate";
|
|
60
|
-
/** Why the verdict is what it is — machine-readable, for logs and for tests. */
|
|
61
|
-
export type DeliveryVerdictReason = "fresh-delivering" | "fresh-failing" | "no-fresh-evidence" | "verdict-stale" | "service-not-listed" | "oracle-unreachable" | "oracle-malformed";
|
|
62
|
-
export interface DeliveryAssessment {
|
|
63
|
-
readonly serviceRef: string;
|
|
64
|
-
readonly verdict: DeliveryVerdict;
|
|
65
|
-
readonly reason: DeliveryVerdictReason;
|
|
66
|
-
/** Unix ms of the newest recorded check for this service, when known. */
|
|
67
|
-
readonly lastCheckedAt: number | null;
|
|
68
|
-
/** Age of `lastCheckedAt` in seconds, when known. */
|
|
69
|
-
readonly ageSeconds: number | null;
|
|
70
|
-
/** The freshness window applied, in seconds. */
|
|
71
|
-
readonly freshnessWindowSeconds: number;
|
|
72
|
-
}
|
|
73
|
-
export interface MetrikDeliveryOracle {
|
|
74
|
-
/** Never throws: an unreachable oracle is an `indeterminate` verdict, not an exception. */
|
|
75
|
-
verdictFor(serviceRef: string): Promise<DeliveryAssessment>;
|
|
76
|
-
}
|
|
77
|
-
export type FetchLike = (input: string, init?: {
|
|
78
|
-
signal?: AbortSignal;
|
|
79
|
-
headers?: Record<string, string>;
|
|
80
|
-
}) => Promise<{
|
|
81
|
-
ok: boolean;
|
|
82
|
-
status: number;
|
|
83
|
-
json(): Promise<unknown>;
|
|
84
|
-
}>;
|
|
85
|
-
export interface OracleDeliveryOracleOptions {
|
|
86
|
-
/** Oracle base URL. Default {@link DEFAULT_METRIK_ORACLE_URL}. */
|
|
87
|
-
readonly oracleUrl?: string;
|
|
88
|
-
/** Default {@link DEFAULT_DELIVERY_FRESHNESS_SECONDS}. */
|
|
89
|
-
readonly freshnessWindowSeconds?: number;
|
|
90
|
-
/** Default {@link DEFAULT_DELIVERY_SNAPSHOT_TTL_MS}. */
|
|
91
|
-
readonly snapshotTtlMs?: number;
|
|
92
|
-
readonly timeoutMs?: number;
|
|
93
|
-
readonly fetch?: FetchLike;
|
|
94
|
-
/** Injectable clock (unix ms), for tests. */
|
|
95
|
-
readonly now?: () => number;
|
|
96
|
-
}
|
|
97
|
-
/**
|
|
98
|
-
* Reads `GET {oracleUrl}/services` and projects one row onto a
|
|
99
|
-
* {@link DeliveryAssessment}.
|
|
100
|
-
*
|
|
101
|
-
* The snapshot is cached for {@link DEFAULT_DELIVERY_SNAPSHOT_TTL_MS} so a burst
|
|
102
|
-
* of payments does not become a burst of oracle reads. The cache is SHORTER than
|
|
103
|
-
* the freshness window by design, and caching cannot make a verdict look fresher
|
|
104
|
-
* than it is: freshness is computed from the row's own `lastCheckedAt`, never
|
|
105
|
-
* from when we fetched it.
|
|
106
|
-
*/
|
|
107
|
-
export declare function createOracleDeliveryOracle(options?: OracleDeliveryOracleOptions): MetrikDeliveryOracle;
|
|
108
|
-
//# sourceMappingURL=delivery-oracle.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"delivery-oracle.d.ts","sourceRoot":"","sources":["../../src/x402/delivery-oracle.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,eAAO,MAAM,kCAAkC,KAAK,CAAC;AAErD,+EAA+E;AAC/E,eAAO,MAAM,gCAAgC,QAAS,CAAC;AAEvD,mFAAmF;AACnF,eAAO,MAAM,kCAAkC,OAAQ,CAAC;AAExD,eAAO,MAAM,yBAAyB,+BAA+B,CAAC;AAEtE;;;;;;;;GAQG;AACH,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,SAAS,GAAG,eAAe,CAAC;AAEzE,gFAAgF;AAChF,MAAM,MAAM,qBAAqB,GAC7B,kBAAkB,GAClB,eAAe,GACf,mBAAmB,GACnB,eAAe,GACf,oBAAoB,GACpB,oBAAoB,GACpB,kBAAkB,CAAC;AAEvB,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;IACvC,yEAAyE;IACzE,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC,qDAAqD;IACrD,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,gDAAgD;IAChD,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;CACzC;AAED,MAAM,WAAW,oBAAoB;IACnC,2FAA2F;IAC3F,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;CAC7D;AAeD,MAAM,MAAM,SAAS,GAAG,CACtB,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,WAAW,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,KAC9D,OAAO,CAAC;IACX,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1B,CAAC,CAAC;AAEH,MAAM,WAAW,2BAA2B;IAC1C,kEAAkE;IAClE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,0DAA0D;IAC1D,QAAQ,CAAC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IACzC,wDAAwD;IACxD,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC;IAC3B,6CAA6C;IAC7C,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CAC7B;AAED;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,GAAE,2BAAgC,GACxC,oBAAoB,CA+HtB"}
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
/**
|
|
3
|
-
* The Metrik delivery signal, as consumed by the x402 facilitator.
|
|
4
|
-
*
|
|
5
|
-
* ## Where the signal comes from
|
|
6
|
-
*
|
|
7
|
-
* The oracle publishes `GET /services` — one row per `serviceRef`, reduced from
|
|
8
|
-
* the oracle's own settlement-path verdicts for the active streams of that
|
|
9
|
-
* service (`streamproof-oracle/src/service-status.ts`). Its three states are
|
|
10
|
-
* already buyer-favouring at the source: a FRESH failing stream beats a fresh
|
|
11
|
-
* delivering sibling, and absent/stale evidence is reported as `unverified`
|
|
12
|
-
* rather than folded into "fine".
|
|
13
|
-
*
|
|
14
|
-
* ## Why this module re-checks freshness the oracle already checked
|
|
15
|
-
*
|
|
16
|
-
* The oracle's own bound is 5 minutes (`DEFAULT_SERVICE_STATUS_TTL_MS`), which
|
|
17
|
-
* is a sensible bound for a dashboard and far too loose for a payment gate. On
|
|
18
|
-
* top of that the HTTP response itself can be cached or served by a stale
|
|
19
|
-
* replica, and `lastCheckedAt` is the only field that dates the EVIDENCE rather
|
|
20
|
-
* than the response. So the age of `lastCheckedAt` is re-derived here against
|
|
21
|
-
* this module's own, much tighter window.
|
|
22
|
-
*
|
|
23
|
-
* ## The freshness window: 90 seconds, and why
|
|
24
|
-
*
|
|
25
|
-
* The oracle checkpoints every ~15–22 s, and a service's recorded status is
|
|
26
|
-
* refreshed on that cadence. A window has to be wide enough that ordinary
|
|
27
|
-
* jitter does not flap the gate, and narrow enough that "verified" still means
|
|
28
|
-
* "now":
|
|
29
|
-
*
|
|
30
|
-
* - 3 worst-case probe intervals (3 x 22 s = 66 s) absorbs two consecutive
|
|
31
|
-
* missed or slow ticks, which is normal operational noise, not evidence of
|
|
32
|
-
* a dead service.
|
|
33
|
-
* - plus the oracle's own record-and-serve latency and this process's fetch
|
|
34
|
-
* round trip, rounded up: **90 s**.
|
|
35
|
-
*
|
|
36
|
-
* Tighter (e.g. 30 s) and a single slow tick turns a healthy service's gate
|
|
37
|
-
* indeterminate. Looser (e.g. the oracle's own 300 s) and a service that died
|
|
38
|
-
* four minutes ago still reads `delivering`, which is exactly the claim this
|
|
39
|
-
* gate exists to avoid making.
|
|
40
|
-
*
|
|
41
|
-
* Note this window is strictly stricter than the oracle's: a verdict aged
|
|
42
|
-
* between 90 s and 300 s is `delivering` at the source and `indeterminate`
|
|
43
|
-
* here.
|
|
44
|
-
*/
|
|
45
|
-
export const DEFAULT_DELIVERY_FRESHNESS_SECONDS = 90;
|
|
46
|
-
/** How long a fetched `/services` snapshot may be reused. See `verdictFor`. */
|
|
47
|
-
export const DEFAULT_DELIVERY_SNAPSHOT_TTL_MS = 10_000;
|
|
48
|
-
/** Request timeout for the oracle read. Short: this sits in a payment hot path. */
|
|
49
|
-
export const DEFAULT_DELIVERY_ORACLE_TIMEOUT_MS = 4_000;
|
|
50
|
-
export const DEFAULT_METRIK_ORACLE_URL = "https://oracle.metrik.live";
|
|
51
|
-
/** The subset of the oracle's `/services` row this module relies on. */
|
|
52
|
-
const serviceStatusRowSchema = z
|
|
53
|
-
.object({
|
|
54
|
-
serviceRef: z.string(),
|
|
55
|
-
status: z.enum(["delivering", "failing", "unverified"]),
|
|
56
|
-
lastCheckedAt: z.number().nullable().optional(),
|
|
57
|
-
})
|
|
58
|
-
.passthrough();
|
|
59
|
-
const servicesResponseSchema = z.object({
|
|
60
|
-
services: z.array(serviceStatusRowSchema),
|
|
61
|
-
});
|
|
62
|
-
/**
|
|
63
|
-
* Reads `GET {oracleUrl}/services` and projects one row onto a
|
|
64
|
-
* {@link DeliveryAssessment}.
|
|
65
|
-
*
|
|
66
|
-
* The snapshot is cached for {@link DEFAULT_DELIVERY_SNAPSHOT_TTL_MS} so a burst
|
|
67
|
-
* of payments does not become a burst of oracle reads. The cache is SHORTER than
|
|
68
|
-
* the freshness window by design, and caching cannot make a verdict look fresher
|
|
69
|
-
* than it is: freshness is computed from the row's own `lastCheckedAt`, never
|
|
70
|
-
* from when we fetched it.
|
|
71
|
-
*/
|
|
72
|
-
export function createOracleDeliveryOracle(options = {}) {
|
|
73
|
-
const oracleUrl = (options.oracleUrl ?? DEFAULT_METRIK_ORACLE_URL).replace(/\/+$/, "");
|
|
74
|
-
const freshnessWindowSeconds = options.freshnessWindowSeconds ?? DEFAULT_DELIVERY_FRESHNESS_SECONDS;
|
|
75
|
-
if (!Number.isFinite(freshnessWindowSeconds) || freshnessWindowSeconds <= 0) {
|
|
76
|
-
throw new Error("freshnessWindowSeconds must be a positive number");
|
|
77
|
-
}
|
|
78
|
-
const snapshotTtlMs = options.snapshotTtlMs ?? DEFAULT_DELIVERY_SNAPSHOT_TTL_MS;
|
|
79
|
-
const timeoutMs = options.timeoutMs ?? DEFAULT_DELIVERY_ORACLE_TIMEOUT_MS;
|
|
80
|
-
const doFetch = (options.fetch ??
|
|
81
|
-
((input, init) => globalThis.fetch(input, init)));
|
|
82
|
-
const now = options.now ?? (() => Date.now());
|
|
83
|
-
let snapshot;
|
|
84
|
-
let inFlight;
|
|
85
|
-
async function loadSnapshot() {
|
|
86
|
-
const controller = new AbortController();
|
|
87
|
-
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
88
|
-
try {
|
|
89
|
-
const response = await doFetch(`${oracleUrl}/services`, {
|
|
90
|
-
signal: controller.signal,
|
|
91
|
-
headers: { accept: "application/json", "cache-control": "no-cache" },
|
|
92
|
-
});
|
|
93
|
-
if (!response.ok) {
|
|
94
|
-
return {
|
|
95
|
-
fetchedAtMs: now(),
|
|
96
|
-
rows: null,
|
|
97
|
-
failure: "oracle-unreachable",
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
const parsed = servicesResponseSchema.safeParse(await response.json());
|
|
101
|
-
if (!parsed.success) {
|
|
102
|
-
return { fetchedAtMs: now(), rows: null, failure: "oracle-malformed" };
|
|
103
|
-
}
|
|
104
|
-
const rows = new Map();
|
|
105
|
-
for (const row of parsed.data.services) {
|
|
106
|
-
rows.set(row.serviceRef.toLowerCase(), row);
|
|
107
|
-
}
|
|
108
|
-
return { fetchedAtMs: now(), rows, failure: null };
|
|
109
|
-
}
|
|
110
|
-
catch {
|
|
111
|
-
return { fetchedAtMs: now(), rows: null, failure: "oracle-unreachable" };
|
|
112
|
-
}
|
|
113
|
-
finally {
|
|
114
|
-
clearTimeout(timer);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
async function currentSnapshot() {
|
|
118
|
-
const cached = snapshot;
|
|
119
|
-
if (cached !== undefined && now() - cached.fetchedAtMs < snapshotTtlMs) {
|
|
120
|
-
return cached;
|
|
121
|
-
}
|
|
122
|
-
// Collapse concurrent misses onto one request.
|
|
123
|
-
inFlight ??= loadSnapshot().finally(() => {
|
|
124
|
-
inFlight = undefined;
|
|
125
|
-
});
|
|
126
|
-
const loaded = await inFlight;
|
|
127
|
-
snapshot = loaded;
|
|
128
|
-
return loaded;
|
|
129
|
-
}
|
|
130
|
-
return {
|
|
131
|
-
async verdictFor(serviceRef) {
|
|
132
|
-
const key = serviceRef.toLowerCase();
|
|
133
|
-
const loaded = await currentSnapshot();
|
|
134
|
-
if (loaded.rows === null) {
|
|
135
|
-
return indeterminate(serviceRef, loaded.failure ?? "oracle-unreachable", null, freshnessWindowSeconds);
|
|
136
|
-
}
|
|
137
|
-
const row = loaded.rows.get(key);
|
|
138
|
-
if (row === undefined) {
|
|
139
|
-
return indeterminate(serviceRef, "service-not-listed", null, freshnessWindowSeconds);
|
|
140
|
-
}
|
|
141
|
-
const lastCheckedAt = row.lastCheckedAt ?? null;
|
|
142
|
-
const ageSeconds = lastCheckedAt === null
|
|
143
|
-
? null
|
|
144
|
-
: Math.max(0, Math.round((now() - lastCheckedAt) / 1000));
|
|
145
|
-
if (row.status === "unverified") {
|
|
146
|
-
return indeterminate(serviceRef, "no-fresh-evidence", lastCheckedAt, freshnessWindowSeconds, ageSeconds);
|
|
147
|
-
}
|
|
148
|
-
// The oracle dated its own verdict; if it cannot be shown to be recent it
|
|
149
|
-
// is not evidence of anything, in EITHER direction.
|
|
150
|
-
if (ageSeconds === null || ageSeconds > freshnessWindowSeconds) {
|
|
151
|
-
return indeterminate(serviceRef, "verdict-stale", lastCheckedAt, freshnessWindowSeconds, ageSeconds);
|
|
152
|
-
}
|
|
153
|
-
return {
|
|
154
|
-
serviceRef,
|
|
155
|
-
verdict: row.status === "failing" ? "failing" : "delivering",
|
|
156
|
-
reason: row.status === "failing" ? "fresh-failing" : "fresh-delivering",
|
|
157
|
-
lastCheckedAt,
|
|
158
|
-
ageSeconds,
|
|
159
|
-
freshnessWindowSeconds,
|
|
160
|
-
};
|
|
161
|
-
},
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
function indeterminate(serviceRef, reason, lastCheckedAt, freshnessWindowSeconds, ageSeconds = null) {
|
|
165
|
-
return {
|
|
166
|
-
serviceRef,
|
|
167
|
-
verdict: "indeterminate",
|
|
168
|
-
reason,
|
|
169
|
-
lastCheckedAt,
|
|
170
|
-
ageSeconds,
|
|
171
|
-
freshnessWindowSeconds,
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
//# sourceMappingURL=delivery-oracle.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"delivery-oracle.js","sourceRoot":"","sources":["../../src/x402/delivery-oracle.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"facilitator-server-entry.d.ts","sourceRoot":"","sources":["../../src/x402/facilitator-server-entry.ts"],"names":[],"mappings":""}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { startMetrikFacilitatorServerFromEnv } from "./facilitator-server.js";
|
|
3
|
-
/**
|
|
4
|
-
* Runnable entrypoint for Metrik's x402 facilitator (`metrik-x402-facilitator`).
|
|
5
|
-
* All configuration comes from the environment; see
|
|
6
|
-
* {@link parseMetrikFacilitatorEnvConfig}. Refuses to start without a
|
|
7
|
-
* settlement relayer unless `METRIK_X402_ALLOW_VERIFY_ONLY=true`.
|
|
8
|
-
*/
|
|
9
|
-
async function main() {
|
|
10
|
-
const server = await startMetrikFacilitatorServerFromEnv();
|
|
11
|
-
const host = process.env.METRIK_X402_HOST ?? "0.0.0.0";
|
|
12
|
-
console.error(`[metrik-x402-facilitator] listening on http://${host}:${server.boundPort}`);
|
|
13
|
-
const shutdown = (signal) => {
|
|
14
|
-
console.error(`[metrik-x402-facilitator] ${signal} received — shutting down`);
|
|
15
|
-
server
|
|
16
|
-
.close()
|
|
17
|
-
.then(() => process.exit(0))
|
|
18
|
-
.catch(() => process.exit(1));
|
|
19
|
-
};
|
|
20
|
-
process.on("SIGINT", () => shutdown("SIGINT"));
|
|
21
|
-
process.on("SIGTERM", () => shutdown("SIGTERM"));
|
|
22
|
-
}
|
|
23
|
-
main().catch((error) => {
|
|
24
|
-
console.error(error instanceof Error ? error.message : "failed to start x402 facilitator");
|
|
25
|
-
process.exit(1);
|
|
26
|
-
});
|
|
27
|
-
//# sourceMappingURL=facilitator-server-entry.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"facilitator-server-entry.js","sourceRoot":"","sources":["../../src/x402/facilitator-server-entry.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,mCAAmC,EAAE,MAAM,yBAAyB,CAAC;AAE9E;;;;;GAKG;AACH,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,MAAM,mCAAmC,EAAE,CAAC;IAC3D,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,SAAS,CAAC;IACvD,OAAO,CAAC,KAAK,CACX,iDAAiD,IAAI,IAAI,MAAM,CAAC,SAAS,EAAE,CAC5E,CAAC;IAEF,MAAM,QAAQ,GAAG,CAAC,MAAc,EAAE,EAAE;QAClC,OAAO,CAAC,KAAK,CACX,6BAA6B,MAAM,2BAA2B,CAC/D,CAAC;QACF,MAAM;aACH,KAAK,EAAE;aACP,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;aAC3B,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAClC,CAAC,CAAC;IACF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;AACnD,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CACX,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,kCAAkC,CAC5E,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { type Server } from "node:http";
|
|
2
|
-
import { type Hex } from "viem";
|
|
3
|
-
import { MetrikVerifiedDeliveryFacilitator, type IndeterminatePolicy, type SettlementScope } from "./verified-delivery-facilitator.js";
|
|
4
|
-
export interface MetrikFacilitatorServerConfig {
|
|
5
|
-
readonly facilitator: MetrikVerifiedDeliveryFacilitator;
|
|
6
|
-
/** Present only to report settlement availability on `/supported`. */
|
|
7
|
-
readonly settlementEnabled: boolean;
|
|
8
|
-
/**
|
|
9
|
-
* Shared secret required on `POST /settle`.
|
|
10
|
-
*
|
|
11
|
-
* `/settle` spends the operator's gas: it makes the relayer sign and
|
|
12
|
-
* broadcast. It is not a public read, and leaving it open on `0.0.0.0` makes
|
|
13
|
-
* it a permissionless "make the relayer broadcast for me" endpoint. `/verify`
|
|
14
|
-
* and `/supported` stay public — they cost nothing and are genuinely useful
|
|
15
|
-
* to anyone.
|
|
16
|
-
*
|
|
17
|
-
* Omit ONLY for a verify-only server. `startMetrikFacilitatorServerFromEnv`
|
|
18
|
-
* refuses to start a settling facilitator without one.
|
|
19
|
-
*/
|
|
20
|
-
readonly settlementToken?: string;
|
|
21
|
-
}
|
|
22
|
-
export interface MetrikFacilitatorServer {
|
|
23
|
-
readonly httpServer: Server;
|
|
24
|
-
listen(port: number, host?: string): Promise<{
|
|
25
|
-
port: number;
|
|
26
|
-
host: string;
|
|
27
|
-
}>;
|
|
28
|
-
close(): Promise<void>;
|
|
29
|
-
}
|
|
30
|
-
export declare function createMetrikFacilitatorServer(config: MetrikFacilitatorServerConfig): MetrikFacilitatorServer;
|
|
31
|
-
export interface MetrikFacilitatorEnvConfig {
|
|
32
|
-
readonly host: string;
|
|
33
|
-
readonly port: number;
|
|
34
|
-
readonly chainId: number;
|
|
35
|
-
readonly rpcUrl: string;
|
|
36
|
-
readonly oracleUrl: string;
|
|
37
|
-
readonly registryUrl?: string;
|
|
38
|
-
readonly freshnessWindowSeconds: number;
|
|
39
|
-
readonly indeterminatePolicy: IndeterminatePolicy;
|
|
40
|
-
/** `undefined` means settlement is DISABLED — `/settle` will refuse loudly. */
|
|
41
|
-
readonly relayerPrivateKey?: Hex;
|
|
42
|
-
/** Required whenever a relayer is configured. Guards `POST /settle`. */
|
|
43
|
-
readonly settlementToken?: string;
|
|
44
|
-
/** Token contracts the relayer may be asked to call. Defaults to chain USDC. */
|
|
45
|
-
readonly settlementAssetAllowlist?: readonly string[];
|
|
46
|
-
readonly settlementScope: SettlementScope;
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Env contract:
|
|
50
|
-
* - `METRIK_X402_RPC_URL` (required) — RPC for balance checks and, when a relayer
|
|
51
|
-
* is configured, for broadcasting.
|
|
52
|
-
* - `METRIK_X402_RELAYER_PRIVATE_KEY` (required unless
|
|
53
|
-
* `METRIK_X402_ALLOW_VERIFY_ONLY=true`) — the relayer that broadcasts EIP-3009
|
|
54
|
-
* transfers and pays gas.
|
|
55
|
-
* - `METRIK_X402_ALLOW_VERIFY_ONLY` (optional) — explicit opt-in to booting a
|
|
56
|
-
* verify-only facilitator. Without it, a missing relayer key is a STARTUP
|
|
57
|
-
* FAILURE rather than a server that silently never settles.
|
|
58
|
-
* - `METRIK_X402_CHAIN_ID` (optional) — default `84532`.
|
|
59
|
-
* - `METRIK_X402_ORACLE_URL` (optional) — default the public Metrik oracle.
|
|
60
|
-
* - `METRIK_X402_REGISTRY_URL` (optional) — listing source; default the oracle's
|
|
61
|
-
* public credential-free registry.
|
|
62
|
-
* - `METRIK_X402_FRESHNESS_SECONDS` (optional) — default
|
|
63
|
-
* {@link DEFAULT_DELIVERY_FRESHNESS_SECONDS}.
|
|
64
|
-
* - `METRIK_X402_INDETERMINATE_POLICY` (optional) — `allow` (default) or `deny`.
|
|
65
|
-
* - `PORT` / `METRIK_X402_PORT` (optional) — default `8788`.
|
|
66
|
-
* - `METRIK_X402_HOST` (optional) — default `0.0.0.0`.
|
|
67
|
-
*/
|
|
68
|
-
export declare function parseMetrikFacilitatorEnvConfig(env?: NodeJS.ProcessEnv): MetrikFacilitatorEnvConfig;
|
|
69
|
-
export declare function buildMetrikFacilitatorFromEnvConfig(config: MetrikFacilitatorEnvConfig): MetrikVerifiedDeliveryFacilitator;
|
|
70
|
-
export declare function startMetrikFacilitatorServerFromEnv(env?: NodeJS.ProcessEnv): Promise<MetrikFacilitatorServer & {
|
|
71
|
-
readonly boundPort: number;
|
|
72
|
-
}>;
|
|
73
|
-
//# sourceMappingURL=facilitator-server.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"facilitator-server.d.ts","sourceRoot":"","sources":["../../src/x402/facilitator-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,MAAM,EAEZ,MAAM,WAAW,CAAC;AAKnB,OAAO,EAAoB,KAAK,GAAG,EAAE,MAAM,MAAM,CAAC;AAalD,OAAO,EAEL,iCAAiC,EAEjC,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACrB,MAAM,oCAAoC,CAAC;AAc5C,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,WAAW,EAAE,iCAAiC,CAAC;IACxD,sEAAsE;IACtE,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IACpC;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;CACnC;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7E,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,6BAA6B,GACpC,uBAAuB,CAkCzB;AAsHD,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IACxC,QAAQ,CAAC,mBAAmB,EAAE,mBAAmB,CAAC;IAClD,+EAA+E;IAC/E,QAAQ,CAAC,iBAAiB,CAAC,EAAE,GAAG,CAAC;IACjC,wEAAwE;IACxE,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,gFAAgF;IAChF,QAAQ,CAAC,wBAAwB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACtD,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;CAC3C;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,+BAA+B,CAC7C,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,0BAA0B,CA4G5B;AAED,wBAAgB,mCAAmC,CACjD,MAAM,EAAE,0BAA0B,GACjC,iCAAiC,CA+BnC;AAED,wBAAsB,mCAAmC,CACvD,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAAC,uBAAuB,GAAG;IAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAmCnE"}
|