@absol-labs/agent 0.11.0 → 0.12.0-rc.1
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 +42 -50
- 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.js +1 -1
- 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 +19 -0
- package/dist/cli/commands/pay.d.ts.map +1 -0
- package/dist/cli/commands/pay.js +355 -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 +184 -16
- package/dist/cli/commands/reclaim.js.map +1 -1
- package/dist/cli/commands/refund.d.ts +13 -0
- package/dist/cli/commands/refund.d.ts.map +1 -0
- package/dist/cli/commands/refund.js +224 -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 +10 -1
- 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 +2 -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/deps.d.ts +33 -0
- package/dist/cli/deps.d.ts.map +1 -1
- package/dist/cli/deps.js +37 -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/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 +40 -11
- 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 +3 -1
- package/dist/cli/status.d.ts.map +1 -1
- package/dist/cli/status.js +15 -3
- package/dist/cli/status.js.map +1 -1
- package/dist/cli/wallet.d.ts +1 -1
- package/dist/cli/wallet.js +2 -2
- 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 +111 -44
- package/dist/gateway/http-server.d.ts.map +1 -1
- package/dist/gateway/http-server.js +439 -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 +215 -0
- package/dist/gateway/x402-opener-mode.d.ts.map +1 -0
- package/dist/gateway/x402-opener-mode.js +639 -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 +52 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +228 -37
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/x402-tools.d.ts +104 -0
- package/dist/mcp/x402-tools.d.ts.map +1 -0
- package/dist/mcp/x402-tools.js +434 -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/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 +135 -0
- package/dist/x402-buyer/pay.d.ts.map +1 -0
- package/dist/x402-buyer/pay.js +336 -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 +37 -0
- package/dist/x402-opener/facilitator-entry.js.map +1 -0
- package/dist/x402-opener/facilitator-server.d.ts +180 -0
- package/dist/x402-opener/facilitator-server.d.ts.map +1 -0
- package/dist/x402-opener/facilitator-server.js +696 -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 +240 -0
- package/dist/x402-opener/refund-relay.d.ts.map +1 -0
- package/dist/x402-opener/refund-relay.js +1240 -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 +217 -0
- package/dist/x402-opener/scheme.d.ts.map +1 -0
- package/dist/x402-opener/scheme.js +749 -0
- package/dist/x402-opener/scheme.js.map +1 -0
- package/dist/x402-opener/terms.d.ts +105 -0
- package/dist/x402-opener/terms.d.ts.map +1 -0
- package/dist/x402-opener/terms.js +212 -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 +184 -31
- package/docs/langchain.md +5 -0
- package/docs/mcp-reference.md +75 -5
- package/docs/probe-capability.md +191 -0
- package/docs/quickstart.md +36 -1
- package/docs/threat-model.md +20 -0
- package/docs/x402.md +628 -595
- 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 +1 -1
- 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 +442 -0
- package/src/cli/commands/reclaim-unverified.ts +8 -2
- package/src/cli/commands/reclaim.ts +252 -14
- package/src/cli/commands/refund.ts +277 -0
- package/src/cli/commands/status.ts +17 -1
- package/src/cli/commands/streams.ts +10 -14
- package/src/cli/commands/watch.ts +7 -1
- package/src/cli/config.ts +139 -52
- package/src/cli/deps.ts +74 -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/reclaimability.ts +154 -0
- package/src/cli/run.ts +54 -11
- package/src/cli/scan-range.ts +2 -2
- package/src/cli/status.ts +14 -1
- package/src/cli/wallet.ts +2 -2
- 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 +629 -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 +974 -0
- package/src/index.ts +82 -19
- package/src/mcp/server.ts +319 -42
- package/src/mcp/x402-tools.ts +621 -0
- package/src/network.ts +302 -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 +517 -0
- package/src/x402-opener/abi.ts +881 -0
- package/src/x402-opener/facilitator-entry.ts +45 -0
- package/src/x402-opener/facilitator-server.ts +1014 -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 +1743 -0
- package/src/x402-opener/relayer-queue.ts +18 -0
- package/src/x402-opener/scheme.ts +1133 -0
- package/src/x402-opener/terms.ts +300 -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
|
@@ -0,0 +1,517 @@
|
|
|
1
|
+
import type { MetrikNetwork } from "@absol-labs/sdk";
|
|
2
|
+
import {
|
|
3
|
+
findStreamForAuthorization,
|
|
4
|
+
payWithX402,
|
|
5
|
+
X402PaymentRefusedError,
|
|
6
|
+
type PayWithX402Options,
|
|
7
|
+
type PayWithX402Result,
|
|
8
|
+
type SignedTransferAuthorization,
|
|
9
|
+
type X402PayerSigner,
|
|
10
|
+
type X402QuoteSummary,
|
|
11
|
+
} from "@absol-labs/sdk/x402";
|
|
12
|
+
import { decodePaymentSignatureHeader } from "@x402/core/http";
|
|
13
|
+
import { createPublicClient, getAddress, http, type PublicClient } from "viem";
|
|
14
|
+
|
|
15
|
+
import {
|
|
16
|
+
checkMandate,
|
|
17
|
+
verifySignedMandate,
|
|
18
|
+
type HireRequest,
|
|
19
|
+
type MandateDecision,
|
|
20
|
+
type SignedSpendMandate,
|
|
21
|
+
} from "../mandates/mandate.js";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Buyer-side x402 payments under a spend mandate (metrik-agent#121).
|
|
25
|
+
*
|
|
26
|
+
* The golden rule of this package — no spend without a mandate — applies to an
|
|
27
|
+
* x402 payment exactly as it applies to `metrik open`, because a Metrik x402
|
|
28
|
+
* payment IS a stream open: the opener facilitator settles the payer's EIP-3009
|
|
29
|
+
* authorization with `factory.deployAndSettle`, which opens a `StreamEscrowV2`
|
|
30
|
+
* stream with `deposit = price`. So the payment is mapped onto the SAME
|
|
31
|
+
* {@link HireRequest} a stream open is checked as, from the quote's opener terms
|
|
32
|
+
* (which the SDK has already proven on-chain: `payTo == factory.predict(terms)`):
|
|
33
|
+
*
|
|
34
|
+
* | Mandate field | x402 quote field |
|
|
35
|
+
* | ---------------------- | ------------------------------------------------ |
|
|
36
|
+
* | `maxPerStreamUsdc` | `amount` (the deposit; the price of the call) |
|
|
37
|
+
* | `maxTotalUsdc` | `spentSoFar + amount` |
|
|
38
|
+
* | `maxRatePerSecondUsdc` | `ratePerSecond` (how fast the seller can earn) |
|
|
39
|
+
* | `maxDurationSeconds` | `maxDuration` (the stream's window) |
|
|
40
|
+
* | `allowedOperators` | `operator` (who the stream pays) |
|
|
41
|
+
*
|
|
42
|
+
* The check runs inside the SDK's `onQuote` hook — after every SDK protection
|
|
43
|
+
* (scheme, network, USDC domain, EIP-3009 only, registered factory, on-chain
|
|
44
|
+
* `predict`, authorization lifetime) and BEFORE anything is signed — so a
|
|
45
|
+
* denied payment never produces a signature. It is enforced twice: the mandate's
|
|
46
|
+
* caps are also handed to the SDK as `maxAmount` / `maxRatePerSecond`. A quote
|
|
47
|
+
* that is not a Metrik opener payment (no operator/rate/duration terms) is
|
|
48
|
+
* refused: there would be no stream to bound and nothing to recover.
|
|
49
|
+
*
|
|
50
|
+
* The mandate itself (signature, expiry, revocation) is verified FIRST, before
|
|
51
|
+
* any request reaches the seller.
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
/** A payment refused by the spend mandate. Nothing was signed. */
|
|
55
|
+
export class X402MandateDeniedError extends Error {
|
|
56
|
+
readonly reason:
|
|
57
|
+
| NonNullable<MandateDecision["reason"]>
|
|
58
|
+
| "not-an-opener-quote";
|
|
59
|
+
readonly quote: X402QuoteSummary | null;
|
|
60
|
+
|
|
61
|
+
constructor(
|
|
62
|
+
reason: X402MandateDeniedError["reason"],
|
|
63
|
+
quote: X402QuoteSummary | null,
|
|
64
|
+
detail?: string,
|
|
65
|
+
) {
|
|
66
|
+
super(
|
|
67
|
+
`x402 payment refused by the spend mandate: ${reason}${detail === undefined ? "" : ` (${detail})`}. Nothing was signed.`,
|
|
68
|
+
);
|
|
69
|
+
this.name = "X402MandateDeniedError";
|
|
70
|
+
this.reason = reason;
|
|
71
|
+
this.quote = quote;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* The stream-open request an x402 quote would create, or a refusal reason when
|
|
77
|
+
* the quote does not carry Metrik opener terms.
|
|
78
|
+
*/
|
|
79
|
+
export function x402QuoteToHireRequest(
|
|
80
|
+
quote: X402QuoteSummary,
|
|
81
|
+
): HireRequest | { readonly refused: string } {
|
|
82
|
+
if (
|
|
83
|
+
quote.operator === null ||
|
|
84
|
+
quote.ratePerSecond === null ||
|
|
85
|
+
quote.maxDuration === null
|
|
86
|
+
) {
|
|
87
|
+
return {
|
|
88
|
+
refused:
|
|
89
|
+
"the quote carries no Metrik opener terms (operator, ratePerSecond, maxDuration), so it would not open a recoverable stream",
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
if (quote.maxDuration > BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
93
|
+
return { refused: `maxDuration ${quote.maxDuration} is out of range` };
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
operator: quote.operator,
|
|
97
|
+
budgetUsdc: quote.amount,
|
|
98
|
+
ratePerSecondUsdc: quote.ratePerSecond,
|
|
99
|
+
maxDurationSeconds: Number(quote.maxDuration),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export interface PayX402WithMandateInput {
|
|
104
|
+
readonly url: string | URL;
|
|
105
|
+
readonly init?: RequestInit;
|
|
106
|
+
/** The payer: signs the EIP-3009 authorization. Needs USDC, no gas. */
|
|
107
|
+
readonly signer: X402PayerSigner;
|
|
108
|
+
readonly network: MetrikNetwork;
|
|
109
|
+
readonly signedMandate: SignedSpendMandate;
|
|
110
|
+
/** USDC already spent under this mandate (the cumulative-cap input). */
|
|
111
|
+
readonly spentSoFarUsdc: bigint;
|
|
112
|
+
readonly nowSeconds: number;
|
|
113
|
+
readonly revokedMandateIds?: Iterable<`0x${string}`>;
|
|
114
|
+
/** An explicit price ceiling, tighter than the mandate (never looser). */
|
|
115
|
+
readonly maxAmount?: bigint;
|
|
116
|
+
/** An explicit rate ceiling, tighter than the mandate (never looser). */
|
|
117
|
+
readonly maxRatePerSecond?: bigint;
|
|
118
|
+
/** Refuse a quote the seller can fully earn in fewer verified seconds. */
|
|
119
|
+
readonly minDurationSeconds?: number;
|
|
120
|
+
/** Passed through to the SDK (transport, fetch, publicClient, ...). */
|
|
121
|
+
readonly sdkOptions?: Pick<
|
|
122
|
+
PayWithX402Options,
|
|
123
|
+
| "publicClient"
|
|
124
|
+
| "transport"
|
|
125
|
+
| "fetch"
|
|
126
|
+
| "allowInsecureHttp"
|
|
127
|
+
| "maxAuthorizationSeconds"
|
|
128
|
+
| "allowLegacyFactory"
|
|
129
|
+
>;
|
|
130
|
+
/** Test seam: the SDK payer. Default `payWithX402`. */
|
|
131
|
+
readonly payImpl?: typeof payWithX402;
|
|
132
|
+
/**
|
|
133
|
+
* Called once the mandate APPROVES a quote, BEFORE the SDK signs it. A
|
|
134
|
+
* caller that tracks cumulative spend reserves the payment here, so a
|
|
135
|
+
* failure after the signature is handed out can never leave it uncounted.
|
|
136
|
+
* Throwing refuses the quote (nothing is signed).
|
|
137
|
+
*/
|
|
138
|
+
readonly onApproved?: (approval: {
|
|
139
|
+
readonly request: HireRequest;
|
|
140
|
+
readonly quote: X402QuoteSummary;
|
|
141
|
+
}) => void | Promise<void>;
|
|
142
|
+
/**
|
|
143
|
+
* Chain reads used after a post-signature failure (USDC
|
|
144
|
+
* `authorizationState`, the opener's `StreamOpenedFor` log). Default: the
|
|
145
|
+
* SDK options' `publicClient`, else a client over their `transport`, else
|
|
146
|
+
* the network's first RPC.
|
|
147
|
+
*/
|
|
148
|
+
readonly chainReader?: Pick<
|
|
149
|
+
PublicClient,
|
|
150
|
+
"readContract" | "getLogs" | "getBlockNumber"
|
|
151
|
+
>;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** What is known about a payment whose signature was handed out but that did not complete cleanly. */
|
|
155
|
+
export type X402PostSignatureState =
|
|
156
|
+
/** The authorization was used: the money left the payer. */
|
|
157
|
+
| "used"
|
|
158
|
+
/** It could not be established either way. Treat as used. */
|
|
159
|
+
| "possibly-used"
|
|
160
|
+
/** Not used yet, but still valid until `validBefore`: a holder can still submit it. */
|
|
161
|
+
| "unused-but-valid"
|
|
162
|
+
/** Not used and past `validBefore`: it can never move funds. */
|
|
163
|
+
| "unused-expired";
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* The payment was APPROVED and its authorization signed and handed to the
|
|
167
|
+
* seller, then something failed (a malformed or missing PAYMENT-RESPONSE, a
|
|
168
|
+
* settlement the SDK could not confirm, a dropped connection). The money may
|
|
169
|
+
* have moved: {@link X402PostSignatureError.state} says what is known, and
|
|
170
|
+
* {@link X402PostSignatureError.releasable} is `true` only when the
|
|
171
|
+
* authorization provably can never be used. A spend reservation must be kept
|
|
172
|
+
* otherwise.
|
|
173
|
+
*/
|
|
174
|
+
export class X402PostSignatureError extends Error {
|
|
175
|
+
readonly state: X402PostSignatureState;
|
|
176
|
+
readonly approved: HireRequest;
|
|
177
|
+
readonly quote: X402QuoteSummary;
|
|
178
|
+
readonly authorization: SignedTransferAuthorization | null;
|
|
179
|
+
/** The stream the payment opened, when it could be identified. */
|
|
180
|
+
readonly streamId: `0x${string}` | null;
|
|
181
|
+
readonly opener: `0x${string}`;
|
|
182
|
+
|
|
183
|
+
constructor(context: {
|
|
184
|
+
readonly state: X402PostSignatureState;
|
|
185
|
+
readonly approved: HireRequest;
|
|
186
|
+
readonly quote: X402QuoteSummary;
|
|
187
|
+
readonly authorization: SignedTransferAuthorization | null;
|
|
188
|
+
readonly streamId: `0x${string}` | null;
|
|
189
|
+
readonly cause: unknown;
|
|
190
|
+
}) {
|
|
191
|
+
const what =
|
|
192
|
+
context.state === "used"
|
|
193
|
+
? `the payment SETTLED (the authorization was used)${context.streamId === null ? ", but its stream could not be identified" : ` into stream ${context.streamId}`}`
|
|
194
|
+
: context.state === "possibly-used"
|
|
195
|
+
? "the payment MAY HAVE SETTLED: whether the authorization was used could not be established, so treat it as spent"
|
|
196
|
+
: context.state === "unused-but-valid"
|
|
197
|
+
? `the authorization has not been used, but it stays valid until ${context.authorization?.validBefore.toString() ?? "its validBefore"} and the seller still holds it — treat it as spent until then, or cancel it on USDC (cancelAuthorization)`
|
|
198
|
+
: "the authorization was never used and has expired: nothing moved";
|
|
199
|
+
super(
|
|
200
|
+
`x402 payment of ${context.approved.budgetUsdc.toString()} USDC base units to ${context.quote.payTo} did not complete cleanly: ${what}. Cause: ${context.cause instanceof Error ? context.cause.message : String(context.cause)}`,
|
|
201
|
+
{ cause: context.cause },
|
|
202
|
+
);
|
|
203
|
+
this.name = "X402PostSignatureError";
|
|
204
|
+
this.state = context.state;
|
|
205
|
+
this.approved = context.approved;
|
|
206
|
+
this.quote = context.quote;
|
|
207
|
+
this.authorization = context.authorization;
|
|
208
|
+
this.streamId = context.streamId;
|
|
209
|
+
this.opener = getAddress(context.quote.payTo);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/** Only an authorization that provably can never move funds frees its reservation. */
|
|
213
|
+
get releasable(): boolean {
|
|
214
|
+
return this.state === "unused-expired";
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function headerValue(
|
|
219
|
+
headers: RequestInit["headers"] | undefined,
|
|
220
|
+
name: string,
|
|
221
|
+
): string | null {
|
|
222
|
+
if (headers === undefined) return null;
|
|
223
|
+
if (headers instanceof Headers) return headers.get(name);
|
|
224
|
+
if (Array.isArray(headers)) {
|
|
225
|
+
const hit = headers.find((pair) => pair[0]?.toLowerCase() === name);
|
|
226
|
+
return hit?.[1] ?? null;
|
|
227
|
+
}
|
|
228
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
229
|
+
if (key.toLowerCase() === name) {
|
|
230
|
+
return typeof value === "string" ? value : (value[0] ?? null);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/** The EIP-3009 authorization inside an x402 v2 PAYMENT-SIGNATURE header, if decodable. */
|
|
237
|
+
function authorizationFromHeader(
|
|
238
|
+
header: string,
|
|
239
|
+
): SignedTransferAuthorization | null {
|
|
240
|
+
try {
|
|
241
|
+
const payload = decodePaymentSignatureHeader(header) as {
|
|
242
|
+
payload?: { authorization?: Record<string, string> };
|
|
243
|
+
};
|
|
244
|
+
const auth = payload.payload?.authorization;
|
|
245
|
+
if (auth === undefined) return null;
|
|
246
|
+
return {
|
|
247
|
+
from: getAddress(auth.from as string),
|
|
248
|
+
to: getAddress(auth.to as string),
|
|
249
|
+
value: BigInt(auth.value as string),
|
|
250
|
+
validAfter: BigInt(auth.validAfter as string),
|
|
251
|
+
validBefore: BigInt(auth.validBefore as string),
|
|
252
|
+
nonce: auth.nonce as `0x${string}`,
|
|
253
|
+
};
|
|
254
|
+
} catch {
|
|
255
|
+
return null;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
export interface PayX402WithMandateResult extends PayWithX402Result {
|
|
260
|
+
/** The stream-open request the mandate approved (null if nothing was paid). */
|
|
261
|
+
readonly approved: HireRequest | null;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function smaller(a: bigint, b: bigint | undefined): bigint {
|
|
265
|
+
return b !== undefined && b < a ? b : a;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Pay an x402 v2 endpoint through the SDK's `payWithX402`, gated by
|
|
270
|
+
* `checkMandate()`. Fail closed: a mandate that does not verify, a quote it
|
|
271
|
+
* denies, or a quote without opener terms is a hard stop with nothing signed.
|
|
272
|
+
*/
|
|
273
|
+
export async function payX402WithMandate(
|
|
274
|
+
input: PayX402WithMandateInput,
|
|
275
|
+
): Promise<PayX402WithMandateResult> {
|
|
276
|
+
const mandate = input.signedMandate.mandate;
|
|
277
|
+
// 1. The mandate itself, before the seller is even contacted.
|
|
278
|
+
const verdict = await verifySignedMandate(input.signedMandate, {
|
|
279
|
+
nowSeconds: input.nowSeconds,
|
|
280
|
+
...(input.revokedMandateIds === undefined
|
|
281
|
+
? {}
|
|
282
|
+
: { revokedMandateIds: input.revokedMandateIds }),
|
|
283
|
+
});
|
|
284
|
+
if (!verdict.allowed) {
|
|
285
|
+
throw new X402MandateDeniedError(
|
|
286
|
+
verdict.reason ?? "invalid-signature",
|
|
287
|
+
null,
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
if (
|
|
291
|
+
input.signedMandate.owner.toLowerCase() !==
|
|
292
|
+
input.signer.address.toLowerCase()
|
|
293
|
+
) {
|
|
294
|
+
throw new X402MandateDeniedError(
|
|
295
|
+
"invalid-signature",
|
|
296
|
+
null,
|
|
297
|
+
`the mandate is owned by ${input.signedMandate.owner}, not the payer ${input.signer.address}`,
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
if (input.signedMandate.chainId !== input.network.chain.id) {
|
|
301
|
+
throw new X402MandateDeniedError(
|
|
302
|
+
"invalid-signature",
|
|
303
|
+
null,
|
|
304
|
+
`the mandate is for chain ${input.signedMandate.chainId}, not ${input.network.name} (${input.network.chain.id})`,
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// 2. The SDK's own ceilings, never looser than the mandate.
|
|
309
|
+
const remaining = mandate.maxTotalUsdc - input.spentSoFarUsdc;
|
|
310
|
+
if (remaining <= 0n) {
|
|
311
|
+
throw new X402MandateDeniedError(
|
|
312
|
+
"exceeds-total-cap",
|
|
313
|
+
null,
|
|
314
|
+
"the mandate's total cap is already spent",
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
const maxAmount = smaller(
|
|
318
|
+
smaller(mandate.maxPerStreamUsdc, remaining),
|
|
319
|
+
input.maxAmount,
|
|
320
|
+
);
|
|
321
|
+
const maxRatePerSecond = smaller(
|
|
322
|
+
mandate.maxRatePerSecondUsdc,
|
|
323
|
+
input.maxRatePerSecond,
|
|
324
|
+
);
|
|
325
|
+
|
|
326
|
+
// 3. The per-quote mandate check, before signing.
|
|
327
|
+
let denial: X402MandateDeniedError | null = null;
|
|
328
|
+
let approved: HireRequest | null = null;
|
|
329
|
+
let approvedQuote: X402QuoteSummary | null = null;
|
|
330
|
+
// The authorization exactly as it left this process, read from the
|
|
331
|
+
// PAYMENT-SIGNATURE header on the way out — so a post-signature failure can
|
|
332
|
+
// still be traced on-chain even when the SDK error does not carry it.
|
|
333
|
+
let sentAuthorization: SignedTransferAuthorization | null = null;
|
|
334
|
+
const baseFetch =
|
|
335
|
+
input.sdkOptions?.fetch ?? globalThis.fetch.bind(globalThis);
|
|
336
|
+
const capturingFetch = (async (
|
|
337
|
+
resource: string | URL | Request,
|
|
338
|
+
init?: RequestInit,
|
|
339
|
+
) => {
|
|
340
|
+
const header =
|
|
341
|
+
headerValue(init?.headers, "payment-signature") ??
|
|
342
|
+
(resource instanceof Request
|
|
343
|
+
? resource.headers.get("payment-signature")
|
|
344
|
+
: null);
|
|
345
|
+
if (header !== null) {
|
|
346
|
+
sentAuthorization = authorizationFromHeader(header) ?? sentAuthorization;
|
|
347
|
+
}
|
|
348
|
+
return await baseFetch(resource, init);
|
|
349
|
+
}) as typeof fetch;
|
|
350
|
+
const pay = input.payImpl ?? payWithX402;
|
|
351
|
+
let result: PayWithX402Result;
|
|
352
|
+
try {
|
|
353
|
+
result = await pay(input.url, input.init, {
|
|
354
|
+
...input.sdkOptions,
|
|
355
|
+
fetch: capturingFetch,
|
|
356
|
+
signer: input.signer,
|
|
357
|
+
network: input.network,
|
|
358
|
+
maxAmount,
|
|
359
|
+
maxRatePerSecond,
|
|
360
|
+
...(input.minDurationSeconds === undefined
|
|
361
|
+
? {}
|
|
362
|
+
: { minDurationSeconds: input.minDurationSeconds }),
|
|
363
|
+
onQuote: async (quote) => {
|
|
364
|
+
const request = x402QuoteToHireRequest(quote);
|
|
365
|
+
if ("refused" in request) {
|
|
366
|
+
denial = new X402MandateDeniedError(
|
|
367
|
+
"not-an-opener-quote",
|
|
368
|
+
quote,
|
|
369
|
+
request.refused,
|
|
370
|
+
);
|
|
371
|
+
return false;
|
|
372
|
+
}
|
|
373
|
+
const decision = await checkMandate(
|
|
374
|
+
input.signedMandate,
|
|
375
|
+
request,
|
|
376
|
+
input.spentSoFarUsdc,
|
|
377
|
+
{
|
|
378
|
+
nowSeconds: input.nowSeconds,
|
|
379
|
+
...(input.revokedMandateIds === undefined
|
|
380
|
+
? {}
|
|
381
|
+
: { revokedMandateIds: input.revokedMandateIds }),
|
|
382
|
+
},
|
|
383
|
+
);
|
|
384
|
+
if (!decision.allowed) {
|
|
385
|
+
denial = new X402MandateDeniedError(
|
|
386
|
+
decision.reason ?? "invalid-signature",
|
|
387
|
+
quote,
|
|
388
|
+
);
|
|
389
|
+
return false;
|
|
390
|
+
}
|
|
391
|
+
// Reserve BEFORE the SDK signs: from here on the money can move.
|
|
392
|
+
// A reservation hook that fails refuses the quote.
|
|
393
|
+
await input.onApproved?.({ request, quote });
|
|
394
|
+
approved = request;
|
|
395
|
+
approvedQuote = quote;
|
|
396
|
+
denial = null;
|
|
397
|
+
return true;
|
|
398
|
+
},
|
|
399
|
+
});
|
|
400
|
+
} catch (error) {
|
|
401
|
+
if (error instanceof X402PaymentRefusedError) {
|
|
402
|
+
// The SDK's own statement: nothing was signed or sent. A reservation
|
|
403
|
+
// made in onApproved can be released by the caller.
|
|
404
|
+
if (denial !== null) throw denial;
|
|
405
|
+
throw error;
|
|
406
|
+
}
|
|
407
|
+
if (approved === null || approvedQuote === null) throw error;
|
|
408
|
+
throw await classifyPostSignatureFailure(input, {
|
|
409
|
+
error,
|
|
410
|
+
approved,
|
|
411
|
+
quote: approvedQuote,
|
|
412
|
+
sentAuthorization,
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
return { ...result, approved: result.paid ? approved : null };
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* After a failure past the point of signing, establish what happened from the
|
|
420
|
+
* CHAIN, never from the seller: USDC `authorizationState(from, nonce)` and the
|
|
421
|
+
* opener's `StreamOpenedFor(streamId, payer, authorizationNonce, …)` log.
|
|
422
|
+
*/
|
|
423
|
+
async function classifyPostSignatureFailure(
|
|
424
|
+
input: PayX402WithMandateInput,
|
|
425
|
+
context: {
|
|
426
|
+
readonly error: unknown;
|
|
427
|
+
readonly approved: HireRequest;
|
|
428
|
+
readonly quote: X402QuoteSummary;
|
|
429
|
+
readonly sentAuthorization: SignedTransferAuthorization | null;
|
|
430
|
+
},
|
|
431
|
+
): Promise<X402PostSignatureError> {
|
|
432
|
+
const sdkError = context.error as {
|
|
433
|
+
readonly authorization?: SignedTransferAuthorization;
|
|
434
|
+
readonly authorizationUsed?: boolean | null;
|
|
435
|
+
readonly streamId?: string;
|
|
436
|
+
};
|
|
437
|
+
const authorization =
|
|
438
|
+
sdkError.authorization ?? context.sentAuthorization ?? null;
|
|
439
|
+
let used: boolean | null =
|
|
440
|
+
typeof sdkError.authorizationUsed === "boolean"
|
|
441
|
+
? sdkError.authorizationUsed
|
|
442
|
+
: null;
|
|
443
|
+
let streamId: `0x${string}` | null =
|
|
444
|
+
typeof sdkError.streamId === "string" &&
|
|
445
|
+
/^0x[0-9a-fA-F]{64}$/.test(sdkError.streamId)
|
|
446
|
+
? (sdkError.streamId as `0x${string}`)
|
|
447
|
+
: null;
|
|
448
|
+
|
|
449
|
+
const reader =
|
|
450
|
+
input.chainReader ??
|
|
451
|
+
input.sdkOptions?.publicClient ??
|
|
452
|
+
(createPublicClient({
|
|
453
|
+
transport: input.sdkOptions?.transport ?? http(input.network.rpcUrls[0]),
|
|
454
|
+
}) as unknown as PublicClient);
|
|
455
|
+
|
|
456
|
+
if (authorization !== null) {
|
|
457
|
+
if (used === null) {
|
|
458
|
+
try {
|
|
459
|
+
used = await reader.readContract({
|
|
460
|
+
address: input.network.usdc.address,
|
|
461
|
+
abi: authorizationStateAbi,
|
|
462
|
+
functionName: "authorizationState",
|
|
463
|
+
args: [authorization.from, authorization.nonce],
|
|
464
|
+
});
|
|
465
|
+
} catch {
|
|
466
|
+
used = null;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
if (streamId === null && used !== false) {
|
|
470
|
+
// The SDK's recovery: only a registered factory's opener
|
|
471
|
+
// (factory.isOpener read on-chain) can prove a stream for this nonce.
|
|
472
|
+
try {
|
|
473
|
+
const recovery = await findStreamForAuthorization({
|
|
474
|
+
authorization,
|
|
475
|
+
network: input.network,
|
|
476
|
+
factory: context.quote.factory ?? null,
|
|
477
|
+
publicClient: reader as PublicClient,
|
|
478
|
+
});
|
|
479
|
+
streamId = recovery.streamId;
|
|
480
|
+
} catch {
|
|
481
|
+
streamId = null;
|
|
482
|
+
}
|
|
483
|
+
if (streamId !== null) used = true;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
const nowSeconds = BigInt(Math.floor(Date.now() / 1000));
|
|
488
|
+
const state: X402PostSignatureState =
|
|
489
|
+
streamId !== null || used === true
|
|
490
|
+
? "used"
|
|
491
|
+
: used === false && authorization !== null
|
|
492
|
+
? authorization.validBefore <= nowSeconds
|
|
493
|
+
? "unused-expired"
|
|
494
|
+
: "unused-but-valid"
|
|
495
|
+
: "possibly-used";
|
|
496
|
+
return new X402PostSignatureError({
|
|
497
|
+
state,
|
|
498
|
+
approved: context.approved,
|
|
499
|
+
quote: context.quote,
|
|
500
|
+
authorization,
|
|
501
|
+
streamId,
|
|
502
|
+
cause: context.error,
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
const authorizationStateAbi = [
|
|
507
|
+
{
|
|
508
|
+
type: "function",
|
|
509
|
+
name: "authorizationState",
|
|
510
|
+
stateMutability: "view",
|
|
511
|
+
inputs: [
|
|
512
|
+
{ name: "authorizer", type: "address" },
|
|
513
|
+
{ name: "nonce", type: "bytes32" },
|
|
514
|
+
],
|
|
515
|
+
outputs: [{ name: "", type: "bool" }],
|
|
516
|
+
},
|
|
517
|
+
] as const;
|