@absol-labs/agent 0.9.1 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +184 -26
- package/dist/capability/invocation-capability.d.ts +18 -6
- package/dist/capability/invocation-capability.d.ts.map +1 -1
- package/dist/capability/invocation-capability.js.map +1 -1
- package/dist/cli/amounts.d.ts +26 -0
- package/dist/cli/amounts.d.ts.map +1 -0
- package/dist/cli/amounts.js +71 -0
- package/dist/cli/amounts.js.map +1 -0
- package/dist/cli/args.d.ts +32 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +119 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/attesters.d.ts +51 -0
- package/dist/cli/attesters.d.ts.map +1 -0
- package/dist/cli/attesters.js +58 -0
- package/dist/cli/attesters.js.map +1 -0
- package/dist/cli/bin.d.ts +3 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +5 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/commands/claim.d.ts +13 -0
- package/dist/cli/commands/claim.d.ts.map +1 -0
- package/dist/cli/commands/claim.js +102 -0
- package/dist/cli/commands/claim.js.map +1 -0
- package/dist/cli/commands/close.d.ts +3 -0
- package/dist/cli/commands/close.d.ts.map +1 -0
- package/dist/cli/commands/close.js +55 -0
- package/dist/cli/commands/close.js.map +1 -0
- package/dist/cli/commands/discover.d.ts +3 -0
- package/dist/cli/commands/discover.d.ts.map +1 -0
- package/dist/cli/commands/discover.js +183 -0
- package/dist/cli/commands/discover.js.map +1 -0
- package/dist/cli/commands/invoke.d.ts +3 -0
- package/dist/cli/commands/invoke.d.ts.map +1 -0
- package/dist/cli/commands/invoke.js +142 -0
- package/dist/cli/commands/invoke.js.map +1 -0
- package/dist/cli/commands/mcp.d.ts +3 -0
- package/dist/cli/commands/mcp.d.ts.map +1 -0
- package/dist/cli/commands/mcp.js +113 -0
- package/dist/cli/commands/mcp.js.map +1 -0
- package/dist/cli/commands/open.d.ts +3 -0
- package/dist/cli/commands/open.d.ts.map +1 -0
- package/dist/cli/commands/open.js +331 -0
- package/dist/cli/commands/open.js.map +1 -0
- package/dist/cli/commands/reclaim-unverified.d.ts +3 -0
- package/dist/cli/commands/reclaim-unverified.d.ts.map +1 -0
- package/dist/cli/commands/reclaim-unverified.js +172 -0
- package/dist/cli/commands/reclaim-unverified.js.map +1 -0
- package/dist/cli/commands/reclaim.d.ts +33 -0
- package/dist/cli/commands/reclaim.d.ts.map +1 -0
- package/dist/cli/commands/reclaim.js +308 -0
- package/dist/cli/commands/reclaim.js.map +1 -0
- package/dist/cli/commands/status.d.ts +3 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +43 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/streams.d.ts +3 -0
- package/dist/cli/commands/streams.d.ts.map +1 -0
- package/dist/cli/commands/streams.js +257 -0
- package/dist/cli/commands/streams.js.map +1 -0
- package/dist/cli/commands/watch.d.ts +3 -0
- package/dist/cli/commands/watch.d.ts.map +1 -0
- package/dist/cli/commands/watch.js +55 -0
- package/dist/cli/commands/watch.js.map +1 -0
- package/dist/cli/config.d.ts +61 -0
- package/dist/cli/config.d.ts.map +1 -0
- package/dist/cli/config.js +140 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/context.d.ts +29 -0
- package/dist/cli/context.d.ts.map +1 -0
- package/dist/cli/context.js +2 -0
- package/dist/cli/context.js.map +1 -0
- package/dist/cli/deps.d.ts +191 -0
- package/dist/cli/deps.d.ts.map +1 -0
- package/dist/cli/deps.js +277 -0
- package/dist/cli/deps.js.map +1 -0
- package/dist/cli/descriptor.d.ts +61 -0
- package/dist/cli/descriptor.d.ts.map +1 -0
- package/dist/cli/descriptor.js +78 -0
- package/dist/cli/descriptor.js.map +1 -0
- package/dist/cli/errors.d.ts +48 -0
- package/dist/cli/errors.d.ts.map +1 -0
- package/dist/cli/errors.js +129 -0
- package/dist/cli/errors.js.map +1 -0
- package/dist/cli/escape-hatch.d.ts +50 -0
- package/dist/cli/escape-hatch.d.ts.map +1 -0
- package/dist/cli/escape-hatch.js +45 -0
- package/dist/cli/escape-hatch.js.map +1 -0
- package/dist/cli/index.d.ts +8 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +7 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/listings.d.ts +15 -0
- package/dist/cli/listings.d.ts.map +1 -0
- package/dist/cli/listings.js +56 -0
- package/dist/cli/listings.js.map +1 -0
- package/dist/cli/mandate.d.ts +66 -0
- package/dist/cli/mandate.d.ts.map +1 -0
- package/dist/cli/mandate.js +61 -0
- package/dist/cli/mandate.js.map +1 -0
- package/dist/cli/output.d.ts +33 -0
- package/dist/cli/output.d.ts.map +1 -0
- package/dist/cli/output.js +34 -0
- package/dist/cli/output.js.map +1 -0
- package/dist/cli/preflight.d.ts +38 -0
- package/dist/cli/preflight.d.ts.map +1 -0
- package/dist/cli/preflight.js +72 -0
- package/dist/cli/preflight.js.map +1 -0
- package/dist/cli/privy.d.ts +83 -0
- package/dist/cli/privy.d.ts.map +1 -0
- package/dist/cli/privy.js +230 -0
- package/dist/cli/privy.js.map +1 -0
- package/dist/cli/progress.d.ts +36 -0
- package/dist/cli/progress.d.ts.map +1 -0
- package/dist/cli/progress.js +40 -0
- package/dist/cli/progress.js.map +1 -0
- package/dist/cli/run.d.ts +25 -0
- package/dist/cli/run.d.ts.map +1 -0
- package/dist/cli/run.js +173 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/cli/scan-range.d.ts +55 -0
- package/dist/cli/scan-range.d.ts.map +1 -0
- package/dist/cli/scan-range.js +57 -0
- package/dist/cli/scan-range.js.map +1 -0
- package/dist/cli/spend-policy.d.ts +60 -0
- package/dist/cli/spend-policy.d.ts.map +1 -0
- package/dist/cli/spend-policy.js +65 -0
- package/dist/cli/spend-policy.js.map +1 -0
- package/dist/cli/status.d.ts +90 -0
- package/dist/cli/status.d.ts.map +1 -0
- package/dist/cli/status.js +252 -0
- package/dist/cli/status.js.map +1 -0
- package/dist/cli/timeout.d.ts +30 -0
- package/dist/cli/timeout.d.ts.map +1 -0
- package/dist/cli/timeout.js +55 -0
- package/dist/cli/timeout.js.map +1 -0
- package/dist/cli/version.d.ts +12 -0
- package/dist/cli/version.d.ts.map +1 -0
- package/dist/cli/version.js +22 -0
- package/dist/cli/version.js.map +1 -0
- package/dist/cli/wallet.d.ts +164 -0
- package/dist/cli/wallet.d.ts.map +1 -0
- package/dist/cli/wallet.js +234 -0
- package/dist/cli/wallet.js.map +1 -0
- package/dist/frameworks/crewai.d.ts +10 -0
- package/dist/frameworks/crewai.d.ts.map +1 -1
- package/dist/frameworks/crewai.js +12 -2
- package/dist/frameworks/crewai.js.map +1 -1
- package/dist/gateway/caller-auth-gateway.d.ts +38 -3
- package/dist/gateway/caller-auth-gateway.d.ts.map +1 -1
- package/dist/gateway/caller-auth-gateway.js +25 -1
- package/dist/gateway/caller-auth-gateway.js.map +1 -1
- package/dist/gateway/http-server.d.ts +53 -0
- package/dist/gateway/http-server.d.ts.map +1 -1
- package/dist/gateway/http-server.js +189 -4
- package/dist/gateway/http-server.js.map +1 -1
- package/dist/gateway/server-entry.d.ts +1 -0
- package/dist/gateway/server-entry.js +1 -0
- package/dist/gateway/server-entry.js.map +1 -1
- package/dist/gateway/x402-mode.d.ts +123 -0
- package/dist/gateway/x402-mode.d.ts.map +1 -0
- package/dist/gateway/x402-mode.js +212 -0
- package/dist/gateway/x402-mode.js.map +1 -0
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -3
- package/dist/index.js.map +1 -1
- package/dist/mandates/env.d.ts +3 -2
- package/dist/mandates/env.d.ts.map +1 -1
- package/dist/mandates/env.js +3 -2
- package/dist/mandates/env.js.map +1 -1
- package/dist/mcp/http-server.d.ts +1 -0
- package/dist/mcp/http-server.js +1 -0
- package/dist/mcp/http-server.js.map +1 -1
- package/dist/mcp/server.d.ts +49 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +533 -25
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/service-invoker.d.ts +97 -0
- package/dist/mcp/service-invoker.d.ts.map +1 -0
- package/dist/mcp/service-invoker.js +167 -0
- package/dist/mcp/service-invoker.js.map +1 -0
- package/dist/mcp/stdio.d.ts +1 -0
- package/dist/mcp/stdio.js +1 -0
- package/dist/mcp/stdio.js.map +1 -1
- package/dist/sdk/client.d.ts +25 -1
- package/dist/sdk/client.d.ts.map +1 -1
- package/dist/sdk/client.js +20 -1
- package/dist/sdk/client.js.map +1 -1
- package/dist/sdk/invoke.d.ts +19 -4
- package/dist/sdk/invoke.d.ts.map +1 -1
- package/dist/sdk/invoke.js +69 -5
- package/dist/sdk/invoke.js.map +1 -1
- package/dist/x402/delivery-oracle.d.ts +108 -0
- package/dist/x402/delivery-oracle.d.ts.map +1 -0
- package/dist/x402/delivery-oracle.js +174 -0
- package/dist/x402/delivery-oracle.js.map +1 -0
- package/dist/x402/facilitator-server-entry.d.ts +3 -0
- package/dist/x402/facilitator-server-entry.d.ts.map +1 -0
- package/dist/x402/facilitator-server-entry.js +27 -0
- package/dist/x402/facilitator-server-entry.js.map +1 -0
- package/dist/x402/facilitator-server.d.ts +73 -0
- package/dist/x402/facilitator-server.d.ts.map +1 -0
- package/dist/x402/facilitator-server.js +305 -0
- package/dist/x402/facilitator-server.js.map +1 -0
- package/dist/x402/facilitator.d.ts +69 -17
- package/dist/x402/facilitator.d.ts.map +1 -1
- package/dist/x402/facilitator.js +76 -33
- package/dist/x402/facilitator.js.map +1 -1
- package/dist/x402/payment-requirements.d.ts +106 -0
- package/dist/x402/payment-requirements.d.ts.map +1 -0
- package/dist/x402/payment-requirements.js +138 -0
- package/dist/x402/payment-requirements.js.map +1 -0
- package/dist/x402/relayer.d.ts +41 -0
- package/dist/x402/relayer.d.ts.map +1 -0
- package/dist/x402/relayer.js +64 -0
- package/dist/x402/relayer.js.map +1 -0
- package/dist/x402/resource-index.d.ts +75 -0
- package/dist/x402/resource-index.d.ts.map +1 -0
- package/dist/x402/resource-index.js +126 -0
- package/dist/x402/resource-index.js.map +1 -0
- package/dist/x402/verified-delivery-facilitator.d.ts +285 -0
- package/dist/x402/verified-delivery-facilitator.d.ts.map +1 -0
- package/dist/x402/verified-delivery-facilitator.js +423 -0
- package/dist/x402/verified-delivery-facilitator.js.map +1 -0
- package/dist/zktls/t2-delivery-proof.d.ts +6 -6
- package/docs/agent-layer.md +14 -9
- package/docs/cli.md +705 -0
- package/docs/crewai.md +6 -2
- package/docs/eliza.md +6 -1
- package/docs/mcp-hosted.md +7 -5
- package/docs/mcp-reference.md +175 -0
- package/docs/quickstart.md +36 -9
- package/docs/threat-model.md +4 -3
- package/docs/x402.md +648 -0
- package/package.json +33 -10
- package/src/capability/invocation-capability.ts +17 -1
- package/src/cli/amounts.ts +102 -0
- package/src/cli/args.ts +150 -0
- package/src/cli/attesters.ts +86 -0
- package/src/cli/bin.ts +5 -0
- package/src/cli/commands/claim.ts +126 -0
- package/src/cli/commands/close.ts +69 -0
- package/src/cli/commands/discover.ts +228 -0
- package/src/cli/commands/invoke.ts +178 -0
- package/src/cli/commands/mcp.ts +135 -0
- package/src/cli/commands/open.ts +397 -0
- package/src/cli/commands/reclaim-unverified.ts +218 -0
- package/src/cli/commands/reclaim.ts +377 -0
- package/src/cli/commands/status.ts +56 -0
- package/src/cli/commands/streams.ts +344 -0
- package/src/cli/commands/watch.ts +70 -0
- package/src/cli/config.ts +208 -0
- package/src/cli/context.ts +30 -0
- package/src/cli/deps.ts +528 -0
- package/src/cli/descriptor.ts +133 -0
- package/src/cli/errors.ts +162 -0
- package/src/cli/escape-hatch.ts +92 -0
- package/src/cli/index.ts +27 -0
- package/src/cli/listings.ts +77 -0
- package/src/cli/mandate.ts +126 -0
- package/src/cli/output.ts +63 -0
- package/src/cli/preflight.ts +88 -0
- package/src/cli/privy.ts +396 -0
- package/src/cli/progress.ts +75 -0
- package/src/cli/run.ts +209 -0
- package/src/cli/scan-range.ts +76 -0
- package/src/cli/spend-policy.ts +139 -0
- package/src/cli/status.ts +381 -0
- package/src/cli/timeout.ts +64 -0
- package/src/cli/version.ts +21 -0
- package/src/cli/wallet.ts +372 -0
- package/src/frameworks/crewai.ts +13 -2
- package/src/gateway/caller-auth-gateway.ts +77 -6
- package/src/gateway/http-server.ts +280 -6
- package/src/gateway/server-entry.ts +1 -0
- package/src/gateway/x402-mode.ts +350 -0
- package/src/index.ts +40 -5
- package/src/mandates/env.ts +3 -2
- package/src/mcp/http-server.ts +1 -0
- package/src/mcp/server.ts +706 -30
- package/src/mcp/service-invoker.ts +285 -0
- package/src/mcp/stdio.ts +1 -0
- package/src/sdk/client.ts +33 -1
- package/src/sdk/invoke.ts +90 -12
- package/src/x402/delivery-oracle.ts +285 -0
- package/src/x402/facilitator-server-entry.ts +35 -0
- package/src/x402/facilitator-server.ts +445 -0
- package/src/x402/facilitator.ts +125 -46
- package/src/x402/payment-requirements.ts +231 -0
- package/src/x402/relayer.ts +122 -0
- package/src/x402/resource-index.ts +228 -0
- package/src/x402/verified-delivery-facilitator.ts +744 -0
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
import { getAddress } from "viem";
|
|
2
|
+
import { PaymentPayloadSchema, PaymentRequirementsSchema, } from "x402/types";
|
|
3
|
+
import { X402_NETWORK_BY_CHAIN_ID, X402_USDC_BY_CHAIN_ID, X402_VERSION, } from "./payment-requirements.js";
|
|
4
|
+
export const SETTLEMENT_REFUSAL_DETAIL = Object.freeze({
|
|
5
|
+
"asset-not-allowed": "the settlement asset is not on this facilitator's allowlist. The relayer signs a call to " +
|
|
6
|
+
"`asset`, so an unrestricted asset would let a caller choose which contract the operator's " +
|
|
7
|
+
"key calls and pays gas for.",
|
|
8
|
+
"network-mismatch": "the payload or the requirements name a chain this facilitator does not settle on",
|
|
9
|
+
"zero-amount": "a zero-value settlement moves nothing and would only burn the relayer's gas",
|
|
10
|
+
"resource-not-tracked": "this relayer only pays gas for resources Metrik tracks, and this resource did not resolve " +
|
|
11
|
+
"to exactly one signed Metrik listing. The payment is not refused — any other facilitator " +
|
|
12
|
+
"can settle it; Metrik is declining to spend its own gas on it.",
|
|
13
|
+
});
|
|
14
|
+
export const DEFAULT_SETTLEMENT_SCOPE = "tracked-resources";
|
|
15
|
+
/**
|
|
16
|
+
* The `invalidReason` used when the delivery gate refuses.
|
|
17
|
+
*
|
|
18
|
+
* The enum has no member for "the resource is not delivering", so the choice is
|
|
19
|
+
* between members that are all imperfect. Every payer-side member
|
|
20
|
+
* (`invalid_payload`, `invalid_exact_evm_payload_signature`,
|
|
21
|
+
* `insufficient_funds`) would be an active lie: it sends the developer to debug
|
|
22
|
+
* a wallet that is working correctly. `unexpected_verify_error` is also false —
|
|
23
|
+
* this refusal is deliberate and expected, not an error.
|
|
24
|
+
*
|
|
25
|
+
* `invalid_payment_requirements` is the only member that points at the
|
|
26
|
+
* REQUIREMENTS side of the exchange, which is exactly where the problem is:
|
|
27
|
+
* Metrik will not settle a payment quoted for THIS resource to THIS payee right
|
|
28
|
+
* now. It is the honest member, and the `metrik.detail` string carries the rest.
|
|
29
|
+
*/
|
|
30
|
+
export const DELIVERY_REFUSAL_REASON = "invalid_payment_requirements";
|
|
31
|
+
/**
|
|
32
|
+
* Default: `allow`.
|
|
33
|
+
*
|
|
34
|
+
* The standing Metrik rule is buyer-favouring, and it still is — but it applies
|
|
35
|
+
* where Metrik HOLDS the buyer's money and must decide whether to release it.
|
|
36
|
+
* Here Metrik holds nothing, so refusing does not protect a buyer's funds; it
|
|
37
|
+
* only denies them a service they asked to buy, on a rail that works fine
|
|
38
|
+
* without Metrik. Four things make `allow` the right default:
|
|
39
|
+
*
|
|
40
|
+
* 1. **Absent evidence is the normal case, not the exception.** The oracle's
|
|
41
|
+
* `/services` projection is built from ACTIVE STREAMS. A service with no live
|
|
42
|
+
* Metrik stream has no row at all — on the live oracle today that is every
|
|
43
|
+
* service. Failing closed would refuse 100% of payments, which is a broken
|
|
44
|
+
* facilitator rather than a careful one.
|
|
45
|
+
* 2. **Fail-closed is a censorship lever.** If "oracle down" meant "no payments",
|
|
46
|
+
* anyone who could degrade Metrik's oracle could block payments to a
|
|
47
|
+
* competitor listed on it. `allow` removes that lever entirely.
|
|
48
|
+
* 3. **The harms are asymmetric.** A wrong refusal denies a service outright. A
|
|
49
|
+
* wrong allowance passes one `exact` payment, at a price the buyer already
|
|
50
|
+
* agreed to, which by construction is one call's worth.
|
|
51
|
+
* 4. **A pass never claims anything.** `isValid: true` with
|
|
52
|
+
* `gate: "indeterminate"` says "no fresh evidence", and the annotation says
|
|
53
|
+
* so in the response. Nobody has to infer an endorsement that was not made.
|
|
54
|
+
*
|
|
55
|
+
* Set `indeterminatePolicy: "deny"` for a deployment that would rather refuse
|
|
56
|
+
* than proceed without positive fresh evidence. That is a real, supported
|
|
57
|
+
* choice — it is just not a safe default.
|
|
58
|
+
*/
|
|
59
|
+
export const DEFAULT_INDETERMINATE_POLICY = "allow";
|
|
60
|
+
export class RelayerNotConfiguredError extends Error {
|
|
61
|
+
constructor() {
|
|
62
|
+
super("this facilitator has no settlement relayer configured, so /settle cannot broadcast. " +
|
|
63
|
+
"Set METRIK_X402_RELAYER_PRIVATE_KEY (and METRIK_X402_RPC_URL) to enable settlement. " +
|
|
64
|
+
"Refusing rather than silently returning a fake success.");
|
|
65
|
+
this.name = "RelayerNotConfiguredError";
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export class MetrikVerifiedDeliveryFacilitator {
|
|
69
|
+
paymentVerifier;
|
|
70
|
+
paymentSettler;
|
|
71
|
+
resourceIndex;
|
|
72
|
+
deliveryOracle;
|
|
73
|
+
indeterminatePolicy;
|
|
74
|
+
network;
|
|
75
|
+
settlementAssets;
|
|
76
|
+
settlementScope;
|
|
77
|
+
constructor(options) {
|
|
78
|
+
const chainId = options.chainId ?? 84532;
|
|
79
|
+
const network = X402_NETWORK_BY_CHAIN_ID[chainId];
|
|
80
|
+
if (network === undefined) {
|
|
81
|
+
throw new Error(`x402 v1 has no network name for chain ${chainId} (Metrik settles on Base: 8453, 84532)`);
|
|
82
|
+
}
|
|
83
|
+
this.paymentVerifier = options.paymentVerifier;
|
|
84
|
+
this.paymentSettler = options.paymentSettler;
|
|
85
|
+
this.resourceIndex = options.resourceIndex;
|
|
86
|
+
this.deliveryOracle = options.deliveryOracle;
|
|
87
|
+
this.indeterminatePolicy =
|
|
88
|
+
options.indeterminatePolicy ?? DEFAULT_INDETERMINATE_POLICY;
|
|
89
|
+
this.network = network;
|
|
90
|
+
const defaultAsset = X402_USDC_BY_CHAIN_ID[chainId]?.address;
|
|
91
|
+
const allowlist = options.settlementAssetAllowlist ??
|
|
92
|
+
(defaultAsset === undefined ? [] : [defaultAsset]);
|
|
93
|
+
if (allowlist.length === 0) {
|
|
94
|
+
throw new Error(`no settlement asset allowlist for chain ${chainId} and none supplied. ` +
|
|
95
|
+
"Refusing to construct a facilitator that would either settle nothing or, " +
|
|
96
|
+
"worse, broadcast to a caller-chosen contract.");
|
|
97
|
+
}
|
|
98
|
+
const normalized = new Set();
|
|
99
|
+
for (const candidate of allowlist) {
|
|
100
|
+
let checksummed;
|
|
101
|
+
try {
|
|
102
|
+
checksummed = getAddress(candidate);
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
throw new Error(`settlementAssetAllowlist entry is not an EVM address: ${candidate}`);
|
|
106
|
+
}
|
|
107
|
+
normalized.add(checksummed);
|
|
108
|
+
}
|
|
109
|
+
this.settlementAssets = normalized;
|
|
110
|
+
this.settlementScope = options.settlementScope ?? DEFAULT_SETTLEMENT_SCOPE;
|
|
111
|
+
}
|
|
112
|
+
/** The assets this relayer may be asked to call, for logging at startup. */
|
|
113
|
+
get allowedSettlementAssets() {
|
|
114
|
+
return [...this.settlementAssets];
|
|
115
|
+
}
|
|
116
|
+
supported() {
|
|
117
|
+
return {
|
|
118
|
+
x402Version: X402_VERSION,
|
|
119
|
+
kind: [{ scheme: "exact", networkId: this.network, extra: {} }],
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
/** `POST /verify`. Takes an unvalidated body; never throws on bad input. */
|
|
123
|
+
async verify(body) {
|
|
124
|
+
const parsed = parseFacilitatorRequest(body);
|
|
125
|
+
if (parsed === undefined) {
|
|
126
|
+
return {
|
|
127
|
+
isValid: false,
|
|
128
|
+
invalidReason: "invalid_payload",
|
|
129
|
+
metrik: {
|
|
130
|
+
gate: "not-applicable",
|
|
131
|
+
settleable: false,
|
|
132
|
+
detail: "request body is not a valid x402 {paymentPayload, paymentRequirements} pair",
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
return this.evaluate(parsed.paymentPayload, parsed.paymentRequirements);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* `POST /settle`. Re-runs the full gate before broadcasting: a facilitator
|
|
140
|
+
* must never settle something it would not verify, and `/settle` is reachable
|
|
141
|
+
* without `/verify` ever having been called.
|
|
142
|
+
*/
|
|
143
|
+
async settle(body) {
|
|
144
|
+
const parsed = parseFacilitatorRequest(body);
|
|
145
|
+
if (parsed === undefined) {
|
|
146
|
+
return {
|
|
147
|
+
success: false,
|
|
148
|
+
errorReason: "invalid_payload",
|
|
149
|
+
transaction: "",
|
|
150
|
+
network: this.network,
|
|
151
|
+
metrik: {
|
|
152
|
+
gate: "not-applicable",
|
|
153
|
+
settleable: false,
|
|
154
|
+
detail: "request body is not a valid x402 {paymentPayload, paymentRequirements} pair",
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
// Settlement constraints that need no network round trip run FIRST, so a
|
|
159
|
+
// hostile body never reaches the RPC, the registry or the oracle — let
|
|
160
|
+
// alone the relayer.
|
|
161
|
+
const preflight = this.settlementPreflight(parsed.paymentPayload, parsed.paymentRequirements);
|
|
162
|
+
if (preflight !== undefined) {
|
|
163
|
+
return this.refuseSettlement(parsed.paymentPayload, preflight, undefined);
|
|
164
|
+
}
|
|
165
|
+
const gate = await this.evaluate(parsed.paymentPayload, parsed.paymentRequirements);
|
|
166
|
+
if (!gate.isValid) {
|
|
167
|
+
return {
|
|
168
|
+
success: false,
|
|
169
|
+
...(gate.invalidReason === undefined
|
|
170
|
+
? {}
|
|
171
|
+
: { errorReason: gate.invalidReason }),
|
|
172
|
+
transaction: "",
|
|
173
|
+
network: parsed.paymentPayload.network,
|
|
174
|
+
...(gate.payer === undefined ? {} : { payer: gate.payer }),
|
|
175
|
+
metrik: gate.metrik,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
if (!gate.metrik.settleable) {
|
|
179
|
+
return this.refuseSettlement(parsed.paymentPayload, gate.metrik.settlementRefusal ?? "resource-not-tracked", gate.metrik);
|
|
180
|
+
}
|
|
181
|
+
if (this.paymentSettler === undefined) {
|
|
182
|
+
throw new RelayerNotConfiguredError();
|
|
183
|
+
}
|
|
184
|
+
const settled = await this.paymentSettler.settle(parsed.paymentPayload, parsed.paymentRequirements);
|
|
185
|
+
return { ...settled, metrik: gate.metrik };
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Settlement constraints checkable from the request alone — no RPC, no
|
|
189
|
+
* registry, no oracle. Returns the refusal, or `undefined` if the request
|
|
190
|
+
* clears them.
|
|
191
|
+
*/
|
|
192
|
+
settlementPreflight(payload, requirements) {
|
|
193
|
+
if (payload.network !== this.network ||
|
|
194
|
+
requirements.network !== this.network) {
|
|
195
|
+
return "network-mismatch";
|
|
196
|
+
}
|
|
197
|
+
// THE control. Without it the relayer signs a call to whatever contract
|
|
198
|
+
// address the caller puts here. See `SettlementRefusalReason`.
|
|
199
|
+
let asset;
|
|
200
|
+
try {
|
|
201
|
+
asset = getAddress(requirements.asset);
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
return "asset-not-allowed";
|
|
205
|
+
}
|
|
206
|
+
if (!this.settlementAssets.has(asset)) {
|
|
207
|
+
return "asset-not-allowed";
|
|
208
|
+
}
|
|
209
|
+
let amount;
|
|
210
|
+
try {
|
|
211
|
+
amount = BigInt(requirements.maxAmountRequired);
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
return "zero-amount";
|
|
215
|
+
}
|
|
216
|
+
if (amount <= 0n) {
|
|
217
|
+
return "zero-amount";
|
|
218
|
+
}
|
|
219
|
+
return undefined;
|
|
220
|
+
}
|
|
221
|
+
/** Builds the standard-shaped refusal for a settlement the relayer declines. */
|
|
222
|
+
refuseSettlement(payload, reason, gate) {
|
|
223
|
+
return {
|
|
224
|
+
success: false,
|
|
225
|
+
errorReason: reason === "network-mismatch"
|
|
226
|
+
? "invalid_network"
|
|
227
|
+
: "invalid_payment_requirements",
|
|
228
|
+
transaction: "",
|
|
229
|
+
network: this.network,
|
|
230
|
+
metrik: {
|
|
231
|
+
...(gate ?? { gate: "not-applicable", detail: "" }),
|
|
232
|
+
settleable: false,
|
|
233
|
+
settlementRefusal: reason,
|
|
234
|
+
detail: SETTLEMENT_REFUSAL_DETAIL[reason],
|
|
235
|
+
},
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
async evaluate(payload, requirements) {
|
|
239
|
+
const evaluated = await this.evaluateGate(payload, requirements);
|
|
240
|
+
// `settleable` is computed once, here, from the same facts `/settle`
|
|
241
|
+
// enforces — so a resource server reading `/verify` learns BEFORE it does
|
|
242
|
+
// any work whether this relayer will actually broadcast.
|
|
243
|
+
const refusal = this.settlementPreflight(payload, requirements) ??
|
|
244
|
+
(evaluated.isValid
|
|
245
|
+
? this.scopeRefusal(evaluated.metrik.gate)
|
|
246
|
+
: "resource-not-tracked");
|
|
247
|
+
return {
|
|
248
|
+
...evaluated,
|
|
249
|
+
metrik: {
|
|
250
|
+
...evaluated.metrik,
|
|
251
|
+
settleable: refusal === undefined,
|
|
252
|
+
...(refusal === undefined ? {} : { settlementRefusal: refusal }),
|
|
253
|
+
},
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
/** Does this gate outcome name a resource the relayer will pay gas for? */
|
|
257
|
+
scopeRefusal(gate) {
|
|
258
|
+
if (this.settlementScope === "any-resource") {
|
|
259
|
+
return undefined;
|
|
260
|
+
}
|
|
261
|
+
// Only an origin that resolved to exactly one signed listing counts.
|
|
262
|
+
// "not-applicable" (not ours), "ambiguous" (two claimants) and
|
|
263
|
+
// "registry-unavailable" (cannot tell) are all "we do not know this is
|
|
264
|
+
// ours", and the relayer does not spend gas on that.
|
|
265
|
+
return gate === "passed" ||
|
|
266
|
+
gate === "indeterminate" ||
|
|
267
|
+
gate === "refused" ||
|
|
268
|
+
gate === "payee-mismatch"
|
|
269
|
+
? undefined
|
|
270
|
+
: "resource-not-tracked";
|
|
271
|
+
}
|
|
272
|
+
async evaluateGate(payload, requirements) {
|
|
273
|
+
// 1. Ordinary payment validity first. A malformed or unfunded payment is
|
|
274
|
+
// rejected on its own merits, and never reaches — or leaks — the
|
|
275
|
+
// delivery record of a service.
|
|
276
|
+
const payment = await this.paymentVerifier.verify(payload, requirements);
|
|
277
|
+
if (!payment.isValid) {
|
|
278
|
+
return {
|
|
279
|
+
...payment,
|
|
280
|
+
metrik: {
|
|
281
|
+
gate: "not-applicable",
|
|
282
|
+
detail: "payment rejected on ordinary x402 grounds; the Metrik delivery gate did not run",
|
|
283
|
+
},
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
// 2. Is this resource one of ours? Resolved from Metrik's own verified
|
|
287
|
+
// registry view, keyed on the resource URL's origin.
|
|
288
|
+
const lookup = await this.resourceIndex.lookup(requirements.resource);
|
|
289
|
+
if (lookup.status === "registry-unavailable") {
|
|
290
|
+
return this.applyIndeterminate(payment, {
|
|
291
|
+
gate: "registry-unavailable",
|
|
292
|
+
detail: "Metrik could not read its service registry, so it cannot tell whether this resource is one it tracks",
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
if (lookup.status !== "resolved" || lookup.resource === undefined) {
|
|
296
|
+
// Not a Metrik listing. Behave exactly like any other facilitator.
|
|
297
|
+
return {
|
|
298
|
+
...payment,
|
|
299
|
+
metrik: {
|
|
300
|
+
gate: "not-applicable",
|
|
301
|
+
detail: "resource is not a Metrik-listed service; Metrik has no delivery opinion and applied no gate",
|
|
302
|
+
},
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
const resolved = lookup.resource;
|
|
306
|
+
// 3. The payee must be the operator who SIGNED the listing. This is the one
|
|
307
|
+
// check that protects the payer rather than the seller: without it,
|
|
308
|
+
// anyone could quote a Metrik-listed resource and redirect its payment to
|
|
309
|
+
// their own address.
|
|
310
|
+
if (!addressesEqual(requirements.payTo, resolved.operator)) {
|
|
311
|
+
return {
|
|
312
|
+
isValid: false,
|
|
313
|
+
invalidReason: "invalid_exact_evm_payload_recipient_mismatch",
|
|
314
|
+
...(payment.payer === undefined ? {} : { payer: payment.payer }),
|
|
315
|
+
metrik: {
|
|
316
|
+
gate: "payee-mismatch",
|
|
317
|
+
serviceRef: resolved.serviceRef,
|
|
318
|
+
detail: `payTo ${requirements.payTo} is not the operator ${resolved.operator} who signed the listing ` +
|
|
319
|
+
`for ${resolved.matchedOrigin}; refusing to settle a payment for a Metrik-listed resource to a different address`,
|
|
320
|
+
},
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
// 4. The differentiator.
|
|
324
|
+
const assessment = await this.deliveryOracle.verdictFor(resolved.serviceRef);
|
|
325
|
+
if (assessment.verdict === "failing") {
|
|
326
|
+
return {
|
|
327
|
+
isValid: false,
|
|
328
|
+
invalidReason: DELIVERY_REFUSAL_REASON,
|
|
329
|
+
...(payment.payer === undefined ? {} : { payer: payment.payer }),
|
|
330
|
+
metrik: {
|
|
331
|
+
gate: "refused",
|
|
332
|
+
detail: `Metrik's oracle reports this service as FAILING its delivery checks ` +
|
|
333
|
+
`(verdict recorded ${assessment.ageSeconds ?? "?"}s ago, within the ` +
|
|
334
|
+
`${assessment.freshnessWindowSeconds}s freshness window). The payment itself is valid; ` +
|
|
335
|
+
`Metrik is refusing to settle it. This prevents a payment — it does not recover one.`,
|
|
336
|
+
...assessmentFields(assessment, resolved.serviceRef),
|
|
337
|
+
},
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
if (assessment.verdict === "indeterminate") {
|
|
341
|
+
return this.applyIndeterminate(payment, {
|
|
342
|
+
gate: "indeterminate",
|
|
343
|
+
detail: `Metrik has no fresh delivery evidence for this service (${assessment.reason}; ` +
|
|
344
|
+
`freshness window ${assessment.freshnessWindowSeconds}s). ` +
|
|
345
|
+
`Policy is "${this.indeterminatePolicy}".`,
|
|
346
|
+
...assessmentFields(assessment, resolved.serviceRef),
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
return {
|
|
350
|
+
...payment,
|
|
351
|
+
metrik: {
|
|
352
|
+
gate: "passed",
|
|
353
|
+
detail: `Metrik's oracle recorded a passing delivery check for this service ` +
|
|
354
|
+
`${assessment.ageSeconds ?? "?"}s ago. This is not an endorsement of output correctness — ` +
|
|
355
|
+
`Metrik verifies delivery, not correctness.`,
|
|
356
|
+
...assessmentFields(assessment, resolved.serviceRef),
|
|
357
|
+
},
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
applyIndeterminate(payment, annotation) {
|
|
361
|
+
if (this.indeterminatePolicy === "deny") {
|
|
362
|
+
return {
|
|
363
|
+
isValid: false,
|
|
364
|
+
invalidReason: DELIVERY_REFUSAL_REASON,
|
|
365
|
+
...(payment.payer === undefined ? {} : { payer: payment.payer }),
|
|
366
|
+
metrik: {
|
|
367
|
+
...annotation,
|
|
368
|
+
detail: `${annotation.detail} Refusing because this facilitator is configured to require positive fresh evidence.`,
|
|
369
|
+
},
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
return {
|
|
373
|
+
...payment,
|
|
374
|
+
metrik: {
|
|
375
|
+
...annotation,
|
|
376
|
+
detail: `${annotation.detail} Allowing: Metrik holds none of this money, so refusing would deny the ` +
|
|
377
|
+
`service without protecting anyone. "isValid: true" here asserts only that the payment is ` +
|
|
378
|
+
`well-formed — it is NOT a statement that the service is delivering.`,
|
|
379
|
+
},
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
function assessmentFields(assessment, serviceRef) {
|
|
384
|
+
return {
|
|
385
|
+
serviceRef,
|
|
386
|
+
deliveryVerdict: assessment.verdict,
|
|
387
|
+
deliveryReason: assessment.reason,
|
|
388
|
+
lastCheckedAt: assessment.lastCheckedAt,
|
|
389
|
+
verdictAgeSeconds: assessment.ageSeconds,
|
|
390
|
+
freshnessWindowSeconds: assessment.freshnessWindowSeconds,
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
function addressesEqual(a, b) {
|
|
394
|
+
try {
|
|
395
|
+
return getAddress(a) === getAddress(b);
|
|
396
|
+
}
|
|
397
|
+
catch {
|
|
398
|
+
return false;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Parses the facilitator wire body with the REAL x402 schemas. Both `/verify`
|
|
403
|
+
* and `/settle` take the same `{paymentPayload, paymentRequirements}` pair.
|
|
404
|
+
*/
|
|
405
|
+
export function parseFacilitatorRequest(body) {
|
|
406
|
+
if (typeof body !== "object" || body === null) {
|
|
407
|
+
return undefined;
|
|
408
|
+
}
|
|
409
|
+
const candidate = body;
|
|
410
|
+
const payload = PaymentPayloadSchema.safeParse(candidate.paymentPayload);
|
|
411
|
+
if (!payload.success) {
|
|
412
|
+
return undefined;
|
|
413
|
+
}
|
|
414
|
+
const requirements = PaymentRequirementsSchema.safeParse(candidate.paymentRequirements);
|
|
415
|
+
if (!requirements.success) {
|
|
416
|
+
return undefined;
|
|
417
|
+
}
|
|
418
|
+
return {
|
|
419
|
+
paymentPayload: payload.data,
|
|
420
|
+
paymentRequirements: requirements.data,
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
//# sourceMappingURL=verified-delivery-facilitator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verified-delivery-facilitator.js","sourceRoot":"","sources":["../../src/x402/verified-delivery-facilitator.ts"],"names":[],"mappings":"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"}
|
|
@@ -161,17 +161,17 @@ export declare const deliveryProofRequestBodySchema: z.ZodObject<{
|
|
|
161
161
|
identifier: z.ZodString;
|
|
162
162
|
}, "strict", z.ZodTypeAny, {
|
|
163
163
|
owner: string;
|
|
164
|
-
parameters: string;
|
|
165
164
|
context: string;
|
|
166
165
|
provider: string;
|
|
166
|
+
parameters: string;
|
|
167
167
|
timestampS: number;
|
|
168
168
|
epoch: number;
|
|
169
169
|
identifier: string;
|
|
170
170
|
}, {
|
|
171
171
|
owner: string;
|
|
172
|
-
parameters: string;
|
|
173
172
|
context: string;
|
|
174
173
|
provider: string;
|
|
174
|
+
parameters: string;
|
|
175
175
|
timestampS: number;
|
|
176
176
|
epoch: number;
|
|
177
177
|
identifier: string;
|
|
@@ -181,9 +181,9 @@ export declare const deliveryProofRequestBodySchema: z.ZodObject<{
|
|
|
181
181
|
identifier: string;
|
|
182
182
|
claimData: {
|
|
183
183
|
owner: string;
|
|
184
|
-
parameters: string;
|
|
185
184
|
context: string;
|
|
186
185
|
provider: string;
|
|
186
|
+
parameters: string;
|
|
187
187
|
timestampS: number;
|
|
188
188
|
epoch: number;
|
|
189
189
|
identifier: string;
|
|
@@ -193,9 +193,9 @@ export declare const deliveryProofRequestBodySchema: z.ZodObject<{
|
|
|
193
193
|
identifier: string;
|
|
194
194
|
claimData: {
|
|
195
195
|
owner: string;
|
|
196
|
-
parameters: string;
|
|
197
196
|
context: string;
|
|
198
197
|
provider: string;
|
|
198
|
+
parameters: string;
|
|
199
199
|
timestampS: number;
|
|
200
200
|
epoch: number;
|
|
201
201
|
identifier: string;
|
|
@@ -208,9 +208,9 @@ export declare const deliveryProofRequestBodySchema: z.ZodObject<{
|
|
|
208
208
|
identifier: string;
|
|
209
209
|
claimData: {
|
|
210
210
|
owner: string;
|
|
211
|
-
parameters: string;
|
|
212
211
|
context: string;
|
|
213
212
|
provider: string;
|
|
213
|
+
parameters: string;
|
|
214
214
|
timestampS: number;
|
|
215
215
|
epoch: number;
|
|
216
216
|
identifier: string;
|
|
@@ -236,9 +236,9 @@ export declare const deliveryProofRequestBodySchema: z.ZodObject<{
|
|
|
236
236
|
identifier: string;
|
|
237
237
|
claimData: {
|
|
238
238
|
owner: string;
|
|
239
|
-
parameters: string;
|
|
240
239
|
context: string;
|
|
241
240
|
provider: string;
|
|
241
|
+
parameters: string;
|
|
242
242
|
timestampS: number;
|
|
243
243
|
epoch: number;
|
|
244
244
|
identifier: string;
|
package/docs/agent-layer.md
CHANGED
|
@@ -15,14 +15,18 @@ fills exactly that gap, and the agent layer is where an agent experiences it.
|
|
|
15
15
|
|
|
16
16
|
## The four components
|
|
17
17
|
|
|
18
|
-
### 1.
|
|
18
|
+
### 1. Metrik verified-streaming `402` flow
|
|
19
19
|
|
|
20
|
-
A
|
|
21
|
-
|
|
20
|
+
A Metrik-native HTTP `402` challenge flow: an agent hits a `402`, receives a
|
|
21
|
+
_verified-streaming_ requirement (operator, serviceRef, rate, budget, settlement
|
|
22
22
|
chain/escrow), responds with a signed-mandate payload, and a stream opens through the
|
|
23
|
-
SDK — paying only for oracle-verified delivery
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
SDK — paying only for oracle-verified delivery. It borrows the _shape_ of an x402
|
|
24
|
+
challenge/response and reuses the protocol's existing settlement path. (`src/x402/`)
|
|
25
|
+
|
|
26
|
+
It is **not the x402 protocol**: its scheme string, challenge body, payload and
|
|
27
|
+
`X-METRIK-PAYMENT` header are all Metrik's own, and it does not interoperate with
|
|
28
|
+
`x402-fetch`, `x402-axios`, or `x402-express`. See [docs/x402.md](./x402.md) for the
|
|
29
|
+
evidence and for what real x402 support would require.
|
|
26
30
|
|
|
27
31
|
### 2. MCP server
|
|
28
32
|
|
|
@@ -32,7 +36,8 @@ Every fund-moving tool is gated by a spend mandate, with JSON-serializable manda
|
|
|
32
36
|
payloads and env-driven settlement config. The server also keeps a local stream
|
|
33
37
|
registry so agents can list and reclaim the streams they opened. (`src/mcp/`)
|
|
34
38
|
|
|
35
|
-
The server runs locally over stdio (`
|
|
39
|
+
The server runs locally over stdio (the published `metrik-mcp` executable, or
|
|
40
|
+
`pnpm mcp:stdio` in-repo) or as a hosted,
|
|
36
41
|
multi-tenant, per-caller-authenticated endpoint over Streamable HTTP
|
|
37
42
|
(`pnpm mcp:http`) — see [docs/mcp-hosted.md](./mcp-hosted.md).
|
|
38
43
|
|
|
@@ -124,7 +129,7 @@ proven live. Tracked separately if/when a paymaster is provisioned.
|
|
|
124
129
|
|
|
125
130
|
```mermaid
|
|
126
131
|
flowchart LR
|
|
127
|
-
AGENT[AI agent] -->|MCP tool /
|
|
132
|
+
AGENT[AI agent] -->|MCP tool / Metrik 402| AL[Agent layer]
|
|
128
133
|
AL -->|checkMandate| MND[Spend mandate]
|
|
129
134
|
MND -->|allowed| SDK[@absol-labs/sdk]
|
|
130
135
|
SDK --> ESC[Escrow on settlement chain]
|
|
@@ -146,5 +151,5 @@ flowchart LR
|
|
|
146
151
|
|
|
147
152
|
## Roadmap (see issues)
|
|
148
153
|
|
|
149
|
-
|
|
154
|
+
Metrik `402` flow → MCP server → framework adapters → example agents
|
|
150
155
|
(hire + monitor + close on verification gaps) → wallet/provider integration.
|