twzrd-x402-gate 0.1.0 → 0.3.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 +207 -47
- package/dist/config.d.ts +2 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +16 -6
- package/dist/config.js.map +1 -1
- package/dist/evaluate.d.ts +77 -0
- package/dist/evaluate.d.ts.map +1 -0
- package/dist/evaluate.js +114 -0
- package/dist/evaluate.js.map +1 -0
- package/dist/gate.d.ts +13 -0
- package/dist/gate.d.ts.map +1 -1
- package/dist/gate.js +22 -0
- package/dist/gate.js.map +1 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp-hook.d.ts.map +1 -1
- package/dist/mcp-hook.js +27 -18
- package/dist/mcp-hook.js.map +1 -1
- package/dist/payto.d.ts +6 -0
- package/dist/payto.d.ts.map +1 -1
- package/dist/payto.js +17 -0
- package/dist/payto.js.map +1 -1
- package/dist/policy.d.ts +1 -1
- package/dist/policy.d.ts.map +1 -1
- package/dist/policy.js +46 -7
- package/dist/policy.js.map +1 -1
- package/dist/quick.d.ts +48 -0
- package/dist/quick.d.ts.map +1 -0
- package/dist/quick.js +49 -0
- package/dist/quick.js.map +1 -0
- package/dist/sponsored.d.ts +51 -0
- package/dist/sponsored.d.ts.map +1 -0
- package/dist/sponsored.js +55 -0
- package/dist/sponsored.js.map +1 -0
- package/dist/types.d.ts +37 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/with-guard.d.ts +23 -0
- package/dist/with-guard.d.ts.map +1 -0
- package/dist/with-guard.js +72 -0
- package/dist/with-guard.js.map +1 -0
- package/dist/wrap-fetch.js +2 -2
- package/dist/wrap-fetch.js.map +1 -1
- package/package.json +6 -3
package/README.md
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
# twzrd-x402-gate
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
`onPaymentRequested` hook. Fail-open by default so an unreachable preflight never hard-blocks a payment.
|
|
3
|
+
Agent-side x402 **firewall**. TWZRD sits in the path before any 402 payment leaves your
|
|
4
|
+
agent's wallet — free preflight decides `allow / warn / block` before USDC moves.
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
```typescript
|
|
7
|
+
import { withTwzrdGuard } from "twzrd-x402-gate";
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
AgentCash's `fetch` (it handles 402 internally) — verify before assuming a wrapper sees it. The MCP
|
|
14
|
-
`onPaymentRequested` hook covers clients that expose a payment callback.
|
|
9
|
+
const safeFetch = withTwzrdGuard(myX402Fetch);
|
|
10
|
+
// Every 402 intercepted → free TWZRD preflight → throws on block, proceeds on warn/allow.
|
|
11
|
+
```
|
|
15
12
|
|
|
16
13
|
## Install
|
|
17
14
|
|
|
@@ -19,34 +16,167 @@ AgentCash's `fetch` (it handles 402 internally) — verify before assuming a wra
|
|
|
19
16
|
npm install twzrd-x402-gate
|
|
20
17
|
```
|
|
21
18
|
|
|
22
|
-
##
|
|
19
|
+
## Quickstart: `withTwzrdGuard`
|
|
23
20
|
|
|
24
|
-
|
|
21
|
+
Wrap any fetch that will receive x402 responses. The guard intercepts every HTTP 402, runs a
|
|
22
|
+
free TWZRD preflight on the seller wallet, and throws `[twzrd] blocked: ...` before your
|
|
23
|
+
wallet signs anything.
|
|
25
24
|
|
|
26
|
-
```
|
|
27
|
-
import {
|
|
25
|
+
```typescript
|
|
26
|
+
import { withTwzrdGuard } from "twzrd-x402-gate";
|
|
27
|
+
import { createAgentcashFetch } from "agentcash";
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
// Pass the x402-capable fetch IN — the guard sits upstream of it.
|
|
30
|
+
const x402Fetch = createAgentcashFetch({ apiKey: process.env.AGENTCASH_API_KEY });
|
|
31
|
+
const safeFetch = withTwzrdGuard(x402Fetch);
|
|
30
32
|
|
|
31
|
-
//
|
|
32
|
-
|
|
33
|
-
// x402 client attaches payment and retries as usual.
|
|
34
|
-
const res = await gatedFetch("https://merchant.example/paid");
|
|
33
|
+
// Use safeFetch everywhere you'd call a paid resource:
|
|
34
|
+
const response = await safeFetch("https://api.exa.ai/search");
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
What the guard does on HTTP 402:
|
|
38
|
+
1. Reads the Solana-network entry from `accepts[]` (falls back to first entry) to get the seller wallet.
|
|
39
|
+
2. Calls `POST /v1/intel/preflight` — free, no auth.
|
|
40
|
+
3. `decision=block` - throws `[twzrd] blocked: ...`.
|
|
41
|
+
4. `decision=warn` or `allow` - returns the original 402 for the x402 client to pay.
|
|
38
42
|
|
|
39
|
-
|
|
40
|
-
import { defaultGate } from "twzrd-x402-gate";
|
|
43
|
+
Non-402 responses pass through unchanged.
|
|
41
44
|
|
|
42
|
-
|
|
43
|
-
|
|
45
|
+
### Auto-receipt on warn (revenue path)
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
const safeFetch = withTwzrdGuard(x402Fetch, {
|
|
49
|
+
autoReceipt: true, // on warn or allow, auto-buy the $0.05 TWZRD trust receipt
|
|
50
|
+
x402Fetch, // the paying fetch — TWZRD earns the fee on-chain
|
|
51
|
+
onReceipt: (receipt, tx) => {
|
|
52
|
+
// receipt is a twzrd_receipt (V6 + ERC-8004 reputation_credential)
|
|
53
|
+
console.log("Trust receipt captured:", tx);
|
|
54
|
+
},
|
|
44
55
|
});
|
|
45
56
|
```
|
|
46
57
|
|
|
47
|
-
|
|
58
|
+
`autoReceipt` is **off by default** — it spends the **buyer's** USDC, so you opt in. When on,
|
|
59
|
+
every warn/allow verdict settles $0.05 USDC to TWZRD and returns a signed V6 trust credential
|
|
60
|
+
for the counterparty before you pay the resource.
|
|
61
|
+
|
|
62
|
+
**`x402Fetch` is yours to supply** (this package is dependency-free). Wire the proven
|
|
63
|
+
`@x402/svm` sponsored-feePayer client — the same one `twzrd-mcp-server` uses:
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
import { wrapFetchWithPayment } from "@x402/svm";
|
|
67
|
+
const x402Fetch = wrapFetchWithPayment(fetch, buyerWallet); // settles 402 challenges
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Gate it behind your own ROI policy (e.g. only auto-buy the receipt for payments above a
|
|
71
|
+
threshold). Runnable, no-spend demo: [`examples/auto-receipt.ts`](./examples/auto-receipt.ts)
|
|
72
|
+
(`npm run autoreceipt-demo`). A bundled/sponsored `x402Fetch` (so integrators need no wallet)
|
|
73
|
+
is the next step.
|
|
74
|
+
|
|
75
|
+
### Quick tier ($0.001) — cheap paid qualify
|
|
76
|
+
|
|
77
|
+
The reputation ladder has three rungs: **free** preflight (`allow/warn/block`), **$0.001**
|
|
78
|
+
`quickCheck` (tier + score, no receipt), **$0.05** `autoReceipt` (full intel + signed V6
|
|
79
|
+
receipt). When the free preflight is inconclusive (`warn` / unknown seller) and you want a
|
|
80
|
+
cheap *paid* confirmation before committing — without paying 50× for the portable receipt —
|
|
81
|
+
use `quickCheck`:
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
import { quickCheck } from "twzrd-x402-gate";
|
|
85
|
+
|
|
86
|
+
const q = await quickCheck(sellerWallet, { x402Fetch }); // settles $0.001 to /v1/intel/quick
|
|
87
|
+
if (q.available && (q.tier === "Gold" || q.tier === "Platinum")) {
|
|
88
|
+
// tier is high enough — proceed with the larger payment
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
`quickCheck` is **fail-soft** — it never throws; any gap (no `x402Fetch`, unreachable, settle
|
|
93
|
+
failure) returns `available: false`, so a quick-tier hiccup can't break your flow. The hard
|
|
94
|
+
allow/warn/block decision stays the free preflight's job.
|
|
95
|
+
|
|
96
|
+
### Autonomous risk-escalation — `escalateOnWarn` (pay-to-confirm on warn)
|
|
97
|
+
|
|
98
|
+
The free preflight leaves an unknown/uncertain seller at `warn`, which **proceeds** by
|
|
99
|
+
default. `escalateOnWarn` closes the loop autonomously: on a proceeding `warn`, the guard
|
|
100
|
+
settles the cheap **$0.001** quick tier and **re-decides on the paid score** — below the
|
|
101
|
+
floor the payment is **blocked**, at/above it proceeds. The paid call fires from your
|
|
102
|
+
agent's own risk policy (no human), and the paid signal actually gates the spend (unlike
|
|
103
|
+
`autoReceipt`, which is upsell-only and never changes the decision).
|
|
48
104
|
|
|
49
105
|
```ts
|
|
106
|
+
const safeFetch = withTwzrdGuard(x402Fetch, {
|
|
107
|
+
escalateOnWarn: {
|
|
108
|
+
minSpendUsdc: 0.01, // don't pay $0.001 to vet a sub-cent buy
|
|
109
|
+
blockBelowScore: 40, // block when the paid quick score is below this (default: preflightMinScore)
|
|
110
|
+
},
|
|
111
|
+
x402Fetch, // settles the $0.001 quick charge
|
|
112
|
+
});
|
|
113
|
+
// warn + paid score < 40 -> throws "[twzrd-guard] payment blocked: twzrd_escalated_warn_block ..."
|
|
114
|
+
// warn + paid score >= 40 -> proceeds (result.escalated=true, result.escalatedScore set)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Opt-in, **fail-soft** (if the quick tier can't answer, the base `warn` is preserved), and it
|
|
118
|
+
**only tightens** — a `warn` may become a block, but an `allow` or `block` is never changed.
|
|
119
|
+
This is the autonomous demand loop: an uncertain counterparty is vetted with real paid intel,
|
|
120
|
+
automatically, before your agent commits.
|
|
121
|
+
|
|
122
|
+
### Sponsored payer — use the paid rungs with no wallet (prototype)
|
|
123
|
+
|
|
124
|
+
`createSponsoredX402Fetch` lets a **sponsor** settle the paid rungs on the agent's behalf, so
|
|
125
|
+
an integrator can call `quickCheck` / `autoReceipt` with **no wallet of their own**:
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
import { createSponsoredX402Fetch, quickCheck } from "twzrd-x402-gate";
|
|
129
|
+
|
|
130
|
+
// `settle` = the funded backend (your @x402/svm fetch, or a TWZRD treasury sponsor endpoint).
|
|
131
|
+
const x402Fetch = createSponsoredX402Fetch({ settle });
|
|
132
|
+
const q = await quickCheck(seller, { x402Fetch }); // sponsor pays — caller holds no wallet
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Two backends plug into `settle`: **gas-sponsored** (live via `@x402/svm` — agent pays USDC, the
|
|
136
|
+
resource server's `feePayer` covers SOL gas, the model `twzrd-mcp-server` uses) and
|
|
137
|
+
**full-sponsor** (a TWZRD treasury endpoint pays on the agent's behalf — the true no-wallet
|
|
138
|
+
path). The full-sponsor endpoint + treasury is **founder-gated** (who funds it + per-agent
|
|
139
|
+
budget caps); this ships the client seam + a dry-run so the wiring is ready.
|
|
140
|
+
No-spend demo: [`examples/sponsored-payer.ts`](./examples/sponsored-payer.ts) (`npm run sponsored-demo`).
|
|
141
|
+
|
|
142
|
+
## `evaluate_x402_resource` — standalone preflight
|
|
143
|
+
|
|
144
|
+
Use when you already have the `paymentRequirements` object from a parsed 402 body:
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
import { evaluate_x402_resource } from "twzrd-x402-gate";
|
|
148
|
+
|
|
149
|
+
const result = await evaluate_x402_resource(
|
|
150
|
+
"https://api.exa.ai/search",
|
|
151
|
+
paymentRequirements, // X402PaymentRequirements from the 402 body
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
console.log(result.decision); // "allow" | "warn" | "block"
|
|
155
|
+
console.log(result.trustScore); // number | null
|
|
156
|
+
console.log(result.approved); // boolean
|
|
157
|
+
console.log(result.receiptUrl); // "https://intel.twzrd.xyz/v1/intel/trust/<payTo>"
|
|
158
|
+
|
|
159
|
+
if (!result.approved) throw new Error(`Blocked: ${result.reason}`);
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
With `autoReceipt`:
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
const result = await evaluate_x402_resource(url, requirements, {
|
|
166
|
+
autoReceipt: true,
|
|
167
|
+
x402Fetch: myPayingFetch,
|
|
168
|
+
onReceipt: (receipt, tx) => storeCredential(receipt),
|
|
169
|
+
});
|
|
170
|
+
// result.receipt — twzrd_receipt (V6 + ERC-8004 reputation_credential)
|
|
171
|
+
// result.receiptTx — on-chain settlement tx
|
|
172
|
+
// result.receiptFeeCaptured — true when fee landed
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Lower-level APIs
|
|
176
|
+
|
|
177
|
+
### Direct approval call
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
50
180
|
import { createTwzrdGate } from "twzrd-x402-gate";
|
|
51
181
|
|
|
52
182
|
const gate = createTwzrdGate();
|
|
@@ -58,38 +188,68 @@ const { approved, reason, card } = await gate.approvePayment({
|
|
|
58
188
|
if (!approved) abort(reason);
|
|
59
189
|
```
|
|
60
190
|
|
|
191
|
+
### `@x402/mcp` payment hook
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
import { defaultGate } from "twzrd-x402-gate";
|
|
195
|
+
|
|
196
|
+
const client = createX402MCPClient({
|
|
197
|
+
onPaymentRequested: defaultGate.onPaymentRequested, // returns false to deny
|
|
198
|
+
});
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### `wrapFetchWithTwzrdGate`
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
import { wrapFetchWithTwzrdGate, resolveConfig } from "twzrd-x402-gate";
|
|
205
|
+
|
|
206
|
+
// Alternative fetch wrapper — same interception logic, no autoReceipt.
|
|
207
|
+
const gatedFetch = wrapFetchWithTwzrdGate(fetch, resolveConfig());
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
`withTwzrdGuard` is preferred — it composes with `autoReceipt` and `onReceipt`.
|
|
211
|
+
`wrapFetchWithTwzrdGate` remains for codebases that can't migrate.
|
|
212
|
+
|
|
61
213
|
## Policy
|
|
62
214
|
|
|
63
|
-
A payment is **
|
|
215
|
+
A payment is **blocked** when:
|
|
216
|
+
1. `decision ∈ blockDecisions` (default: `["block"]`)
|
|
217
|
+
2. `trust_score < preflightMinScore` (default: `40`)
|
|
218
|
+
3. `can_spend === false` — **only** when `gateOnCanSpend: true` (default `false`, opt-in)
|
|
219
|
+
|
|
220
|
+
`warn` is allowed unless overridden. Preflight network failure **fails closed** by default (a preflight outage blocks the payment, so an intel hiccup never silently approves a spend); set `failOpen: true` / `TWZRD_FAIL_OPEN=true` to opt into legacy allow-on-outage.
|
|
64
221
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
222
|
+
> **`can_spend` note:** the free preflight returns `can_spend=false` for most sellers
|
|
223
|
+
> not yet in the TWZRD corpus, including legitimate ones. The default is decision-only
|
|
224
|
+
> gating so unknown sellers on platforms like Agentic.Market are not blocked by default.
|
|
225
|
+
> Set `gateOnCanSpend: true` for strict mode.
|
|
68
226
|
|
|
69
|
-
|
|
70
|
-
failure the gate **fails open** (approves) unless `failOpen` is disabled.
|
|
227
|
+
## Config
|
|
71
228
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
229
|
+
| Option | Env | Default | Description |
|
|
230
|
+
|---|---|---|---|
|
|
231
|
+
| `intelBase` | `TWZRD_INTEL_BASE` | `https://intel.twzrd.xyz` | Preflight API base |
|
|
232
|
+
| `preflightMinScore` | `TWZRD_PREFLIGHT_MIN_SCORE` | `40` | Block below this score |
|
|
233
|
+
| `blockDecisions` | `TWZRD_BLOCK_DECISIONS` | `block` | Decisions that throw |
|
|
234
|
+
| `failOpen` | `TWZRD_FAIL_OPEN` | `false` | `true` opts into legacy allow-on-outage; default blocks (fail-closed) |
|
|
235
|
+
| `gateOnCanSpend` | `TWZRD_GATE_ON_CAN_SPEND` | `false` | Also block when `can_spend=false` |
|
|
236
|
+
| `autoReceipt` | — | `false` | Auto-buy $0.05 TWZRD receipt on warn/allow |
|
|
237
|
+
| `x402Fetch` | — | — | x402-capable fetch for `autoReceipt` |
|
|
238
|
+
| `onReceipt` | — | — | Callback after receipt is captured |
|
|
76
239
|
|
|
77
|
-
##
|
|
240
|
+
## Compatibility note
|
|
78
241
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
| `blockDecisions` | `TWZRD_BLOCK_DECISIONS` | `block` |
|
|
84
|
-
| `failOpen` | `TWZRD_FAIL_OPEN` | `true` (`false`/`0` to disable) |
|
|
85
|
-
| `gateOnCanSpend` | `TWZRD_GATE_ON_CAN_SPEND` | `true` (`false`/`0` = gate only on `decision`) |
|
|
86
|
-
| `fetch` | — | global `fetch` |
|
|
242
|
+
**Proxied x402 clients** (AgentCash's `.fetch`, ClawRouter `:8402`): these clients handle
|
|
243
|
+
402 internally and return 200. The guard never sees a 402. Pass the raw (non-paying) fetch
|
|
244
|
+
to `withTwzrdGuard`, then wrap its output in your x402 client. Or call
|
|
245
|
+
`evaluate_x402_resource` explicitly before routing through the proxy.
|
|
87
246
|
|
|
88
247
|
## Why pre-spend, not post-pay
|
|
89
248
|
|
|
90
|
-
`GET /v1/intel/trust/{wallet}` is the **paid** (0.05 USDC) deep-intel surface —
|
|
91
|
-
`POST /v1/intel/preflight` is the **free** `ReadinessCard` for the pre-spend decision.
|
|
92
|
-
only ever calls the free preflight; you decide whether to proceed before any
|
|
249
|
+
`GET /v1/intel/trust/{wallet}` is the **paid** ($0.05 USDC) deep-intel surface — not a gate.
|
|
250
|
+
`POST /v1/intel/preflight` is the **free** `ReadinessCard` for the pre-spend decision.
|
|
251
|
+
This package only ever calls the free preflight; you decide whether to proceed before any
|
|
252
|
+
USDC leaves your wallet.
|
|
93
253
|
|
|
94
254
|
## License
|
|
95
255
|
|
package/dist/config.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { TwzrdGateConfig } from "./types.js";
|
|
1
|
+
import type { TwzrdGateConfig, TwzrdUpsellContext } from "./types.js";
|
|
2
2
|
export type ResolvedTwzrdGateConfig = {
|
|
3
3
|
intelBase: string;
|
|
4
4
|
preflightMinScore: number;
|
|
@@ -6,6 +6,7 @@ export type ResolvedTwzrdGateConfig = {
|
|
|
6
6
|
failOpen: boolean;
|
|
7
7
|
gateOnCanSpend: boolean;
|
|
8
8
|
fetch: typeof fetch;
|
|
9
|
+
onWarnUpsell?: (ctx: TwzrdUpsellContext) => void | Promise<void>;
|
|
9
10
|
};
|
|
10
11
|
export declare function resolveConfig(overrides?: TwzrdGateConfig): ResolvedTwzrdGateConfig;
|
|
11
12
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEtE,MAAM,MAAM,uBAAuB,GAAG;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC5B,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,EAAE,OAAO,CAAC;IACxB,KAAK,EAAE,OAAO,KAAK,CAAC;IACpB,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,kBAAkB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClE,CAAC;AAYF,wBAAgB,aAAa,CAAC,SAAS,CAAC,EAAE,eAAe,GAAG,uBAAuB,CAiDlF"}
|
package/dist/config.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
function parseBlockDecisions(raw) {
|
|
2
|
-
const source = raw
|
|
2
|
+
const source = raw?.trim() || "block";
|
|
3
3
|
return new Set(source
|
|
4
4
|
.split(",")
|
|
5
5
|
.map((s) => s.trim())
|
|
@@ -9,17 +9,26 @@ export function resolveConfig(overrides) {
|
|
|
9
9
|
const intelBase = (overrides?.intelBase ??
|
|
10
10
|
process.env.TWZRD_INTEL_BASE ??
|
|
11
11
|
"https://intel.twzrd.xyz").replace(/\/+$/, "");
|
|
12
|
-
const
|
|
12
|
+
const rawMin = overrides?.preflightMinScore ??
|
|
13
13
|
Number(process.env.TWZRD_PREFLIGHT_MIN_SCORE ?? "40");
|
|
14
|
+
const preflightMinScore = (Number.isFinite(rawMin) && rawMin >= 0) ? rawMin : 40;
|
|
14
15
|
const blockDecisions = overrides?.blockDecisions != null
|
|
15
16
|
? new Set([...overrides.blockDecisions].map((s) => s.trim()).filter(Boolean))
|
|
16
17
|
: parseBlockDecisions(process.env.TWZRD_BLOCK_DECISIONS);
|
|
18
|
+
// Default false (fail-closed): block and log loudly on preflight outage.
|
|
19
|
+
// Opt in to legacy fail-open with TWZRD_FAIL_OPEN=true or TWZRD_FAIL_OPEN=1.
|
|
17
20
|
const failOpen = overrides?.failOpen ??
|
|
18
|
-
(process.env.TWZRD_FAIL_OPEN
|
|
19
|
-
process.env.TWZRD_FAIL_OPEN
|
|
21
|
+
(process.env.TWZRD_FAIL_OPEN === "true" ||
|
|
22
|
+
process.env.TWZRD_FAIL_OPEN === "1");
|
|
23
|
+
// Default false (decision-only): an unknown seller (warn / can_spend=false,
|
|
24
|
+
// which is EVERY not-yet-seen merchant at score 45) is NOT blocked by default —
|
|
25
|
+
// only an explicit decision=block (a real wash/sybil flag) blocks. This matches
|
|
26
|
+
// the sister package @wzrd_sol/plugin-trustgate and the preflight's own
|
|
27
|
+
// warn-not-block intent, and keeps the gate usable for discovery. Opt in to
|
|
28
|
+
// strict can_spend gating with TWZRD_GATE_ON_CAN_SPEND=true or =1.
|
|
20
29
|
const gateOnCanSpend = overrides?.gateOnCanSpend ??
|
|
21
|
-
(process.env.TWZRD_GATE_ON_CAN_SPEND
|
|
22
|
-
process.env.TWZRD_GATE_ON_CAN_SPEND
|
|
30
|
+
(process.env.TWZRD_GATE_ON_CAN_SPEND === "true" ||
|
|
31
|
+
process.env.TWZRD_GATE_ON_CAN_SPEND === "1");
|
|
23
32
|
const fetchFn = overrides?.fetch ?? globalThis.fetch;
|
|
24
33
|
if (typeof fetchFn !== "function") {
|
|
25
34
|
throw new Error("[twzrd-x402-gate] fetch is not available; pass config.fetch");
|
|
@@ -31,6 +40,7 @@ export function resolveConfig(overrides) {
|
|
|
31
40
|
failOpen,
|
|
32
41
|
gateOnCanSpend,
|
|
33
42
|
fetch: fetchFn,
|
|
43
|
+
onWarnUpsell: overrides?.onWarnUpsell,
|
|
34
44
|
};
|
|
35
45
|
}
|
|
36
46
|
//# sourceMappingURL=config.js.map
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAYA,SAAS,mBAAmB,CAAC,GAAuB;IAClD,MAAM,MAAM,GAAG,GAAG,EAAE,IAAI,EAAE,IAAI,OAAO,CAAC;IACtC,OAAO,IAAI,GAAG,CACZ,MAAM;SACH,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,OAAO,CAAC,CACnB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,SAA2B;IACvD,MAAM,SAAS,GAAG,CAChB,SAAS,EAAE,SAAS;QACpB,OAAO,CAAC,GAAG,CAAC,gBAAgB;QAC5B,yBAAyB,CAC1B,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAEtB,MAAM,MAAM,GACV,SAAS,EAAE,iBAAiB;QAC5B,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,IAAI,CAAC,CAAC;IACxD,MAAM,iBAAiB,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IAEjF,MAAM,cAAc,GAClB,SAAS,EAAE,cAAc,IAAI,IAAI;QAC/B,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC,cAAc,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC7E,CAAC,CAAC,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;IAE7D,yEAAyE;IACzE,6EAA6E;IAC7E,MAAM,QAAQ,GACZ,SAAS,EAAE,QAAQ;QACnB,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,KAAK,MAAM;YACrC,OAAO,CAAC,GAAG,CAAC,eAAe,KAAK,GAAG,CAAC,CAAC;IAEzC,4EAA4E;IAC5E,gFAAgF;IAChF,gFAAgF;IAChF,wEAAwE;IACxE,4EAA4E;IAC5E,mEAAmE;IACnE,MAAM,cAAc,GAClB,SAAS,EAAE,cAAc;QACzB,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,KAAK,MAAM;YAC7C,OAAO,CAAC,GAAG,CAAC,uBAAuB,KAAK,GAAG,CAAC,CAAC;IAEjD,MAAM,OAAO,GAAG,SAAS,EAAE,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC;IACrD,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;IACjF,CAAC;IAED,OAAO;QACL,SAAS;QACT,iBAAiB;QACjB,cAAc;QACd,QAAQ;QACR,cAAc;QACd,KAAK,EAAE,OAAO;QACd,YAAY,EAAE,SAAS,EAAE,YAAY;KACtC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { type TwzrdTier } from "./quick.js";
|
|
2
|
+
import type { TwzrdDecision, TwzrdGateConfig, TwzrdReadinessCard, X402PaymentRequirements } from "./types.js";
|
|
3
|
+
export type EvaluateX402Options = TwzrdGateConfig & {
|
|
4
|
+
/**
|
|
5
|
+
* When true, automatically fetches the paid TWZRD trust receipt (via x402)
|
|
6
|
+
* after a warn/allow decision. Requires x402Fetch to be provided.
|
|
7
|
+
* Default: false.
|
|
8
|
+
*/
|
|
9
|
+
autoReceipt?: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* x402-capable fetch that can settle USDC payments. Used by autoReceipt (the
|
|
12
|
+
* $0.05 receipt) and by escalateOnWarn (the $0.001 quick tier). The caller wires
|
|
13
|
+
* in a Solana wallet + x402 payer.
|
|
14
|
+
*/
|
|
15
|
+
x402Fetch?: typeof fetch;
|
|
16
|
+
/**
|
|
17
|
+
* Called immediately after a receipt is captured on-chain.
|
|
18
|
+
* Provides the raw twzrd_receipt object and the settlement tx hash (if present).
|
|
19
|
+
*/
|
|
20
|
+
onReceipt?: (receipt: unknown, tx: string | undefined) => void;
|
|
21
|
+
/**
|
|
22
|
+
* Autonomous risk-escalation. When the free preflight is inconclusive
|
|
23
|
+
* (decision="warn" and otherwise proceeding), the gate autonomously settles the
|
|
24
|
+
* cheap $0.001 quick tier and RE-DECIDES on the paid score: below `blockBelowScore`
|
|
25
|
+
* (default: preflightMinScore) the payment is denied (approved=false); at/above it
|
|
26
|
+
* proceeds. The paid call fires from the agent's own risk policy - no human - and
|
|
27
|
+
* the paid signal actually gates the spend (unlike autoReceipt, which is upsell-only
|
|
28
|
+
* and never changes the decision). Opt-in; requires x402Fetch. Fail-soft: if the
|
|
29
|
+
* quick tier cannot answer, the base warn decision is preserved. Only tightens
|
|
30
|
+
* (warn -> maybe block); never loosens a block or allow. Short-circuits the
|
|
31
|
+
* autoReceipt path for the warn case (no double settle).
|
|
32
|
+
*/
|
|
33
|
+
escalateOnWarn?: {
|
|
34
|
+
/** Skip escalation when the resource price is below this - don't pay $0.001 to vet a sub-cent buy. Default 0. */
|
|
35
|
+
minSpendUsdc?: number;
|
|
36
|
+
/** Deny when the paid quick score is below this. Default: preflightMinScore (40). */
|
|
37
|
+
blockBelowScore?: number;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
export type EvaluateX402Result = {
|
|
41
|
+
decision: TwzrdDecision | "unknown";
|
|
42
|
+
trustScore: number | null;
|
|
43
|
+
approved: boolean;
|
|
44
|
+
reason: string;
|
|
45
|
+
card: TwzrdReadinessCard;
|
|
46
|
+
/** true when the preflight was unreachable and fail-open allowed the resource */
|
|
47
|
+
failOpen?: boolean;
|
|
48
|
+
/** URL of the paid TWZRD trust endpoint for this seller (for manual upsell) */
|
|
49
|
+
receiptUrl?: string;
|
|
50
|
+
/** Present when autoReceipt=true and the x402 trust call succeeded */
|
|
51
|
+
receipt?: unknown;
|
|
52
|
+
/** On-chain settlement tx from the receipt payment */
|
|
53
|
+
receiptTx?: string;
|
|
54
|
+
/** true when a fee was captured on-chain */
|
|
55
|
+
receiptFeeCaptured?: boolean;
|
|
56
|
+
/** true when a `warn` triggered an autonomous paid quick-tier re-decision (escalateOnWarn) */
|
|
57
|
+
escalated?: boolean;
|
|
58
|
+
/** the paid quick-tier score that drove the escalated decision; null when the quick tier could not answer */
|
|
59
|
+
escalatedScore?: number | null;
|
|
60
|
+
/** the paid quick-tier label (Bronze/Silver/Gold/Platinum) from the escalation */
|
|
61
|
+
escalatedTier?: TwzrdTier | null;
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Evaluate an x402 resource before the buyer pays:
|
|
65
|
+
* 1. Run free TWZRD preflight on the seller (no auth, no cost).
|
|
66
|
+
* 2. Return decision + trust score.
|
|
67
|
+
* 3. If escalateOnWarn is set and decision=warn: autonomously settle the cheap
|
|
68
|
+
* $0.001 quick tier and re-decide on the paid score (the autonomous risk loop).
|
|
69
|
+
* 4. Else if autoReceipt=true and decision !== block: auto-fetch the paid TWZRD
|
|
70
|
+
* trust receipt via x402Fetch (TWZRD earns the receipt fee on-chain).
|
|
71
|
+
*
|
|
72
|
+
* Defaults to gateOnCanSpend=false (decision-only) — the free-tier preflight
|
|
73
|
+
* returns can_spend=false for most unknown sellers, which would block too eagerly
|
|
74
|
+
* on platforms like Agentic.Market where sellers are not yet in the corpus.
|
|
75
|
+
*/
|
|
76
|
+
export declare function evaluate_x402_resource(resourceUrl: string, paymentRequirements: X402PaymentRequirements, opts?: EvaluateX402Options): Promise<EvaluateX402Result>;
|
|
77
|
+
//# sourceMappingURL=evaluate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evaluate.d.ts","sourceRoot":"","sources":["../src/evaluate.ts"],"names":[],"mappings":"AAGA,OAAO,EAAc,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EACf,kBAAkB,EAClB,uBAAuB,EACxB,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,mBAAmB,GAAG,eAAe,GAAG;IAClD;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAC/D;;;;;;;;;;;OAWG;IACH,cAAc,CAAC,EAAE;QACf,iHAAiH;QACjH,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,qFAAqF;QACrF,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,aAAa,GAAG,SAAS,CAAC;IACpC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,kBAAkB,CAAC;IACzB,iFAAiF;IACjF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,8FAA8F;IAC9F,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,6GAA6G;IAC7G,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,kFAAkF;IAClF,aAAa,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;CAClC,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,wBAAsB,sBAAsB,CAC1C,WAAW,EAAE,MAAM,EACnB,mBAAmB,EAAE,uBAAuB,EAC5C,IAAI,GAAE,mBAAwB,GAC7B,OAAO,CAAC,kBAAkB,CAAC,CAmH7B"}
|
package/dist/evaluate.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { resolveConfig } from "./config.js";
|
|
2
|
+
import { twzrdApprovePayment } from "./policy.js";
|
|
3
|
+
import { payToFromRequirements, priceUsdcFromAmountMicro } from "./payto.js";
|
|
4
|
+
import { quickCheck } from "./quick.js";
|
|
5
|
+
/**
|
|
6
|
+
* Evaluate an x402 resource before the buyer pays:
|
|
7
|
+
* 1. Run free TWZRD preflight on the seller (no auth, no cost).
|
|
8
|
+
* 2. Return decision + trust score.
|
|
9
|
+
* 3. If escalateOnWarn is set and decision=warn: autonomously settle the cheap
|
|
10
|
+
* $0.001 quick tier and re-decide on the paid score (the autonomous risk loop).
|
|
11
|
+
* 4. Else if autoReceipt=true and decision !== block: auto-fetch the paid TWZRD
|
|
12
|
+
* trust receipt via x402Fetch (TWZRD earns the receipt fee on-chain).
|
|
13
|
+
*
|
|
14
|
+
* Defaults to gateOnCanSpend=false (decision-only) — the free-tier preflight
|
|
15
|
+
* returns can_spend=false for most unknown sellers, which would block too eagerly
|
|
16
|
+
* on platforms like Agentic.Market where sellers are not yet in the corpus.
|
|
17
|
+
*/
|
|
18
|
+
export async function evaluate_x402_resource(resourceUrl, paymentRequirements, opts = {}) {
|
|
19
|
+
const config = resolveConfig({
|
|
20
|
+
intelBase: opts.intelBase,
|
|
21
|
+
preflightMinScore: opts.preflightMinScore,
|
|
22
|
+
blockDecisions: opts.blockDecisions,
|
|
23
|
+
failOpen: opts.failOpen,
|
|
24
|
+
// Decision-only gate: unknown sellers score warn (~45), not block.
|
|
25
|
+
// Gating on can_spend would block every Agentic.Market seller not in corpus.
|
|
26
|
+
gateOnCanSpend: opts.gateOnCanSpend,
|
|
27
|
+
fetch: opts.fetch,
|
|
28
|
+
});
|
|
29
|
+
const { payTo, amountMicro, resource } = payToFromRequirements(paymentRequirements);
|
|
30
|
+
const priceUsdc = priceUsdcFromAmountMicro(amountMicro);
|
|
31
|
+
const approval = await twzrdApprovePayment({
|
|
32
|
+
resourceUrl: resource ?? resourceUrl,
|
|
33
|
+
payTo,
|
|
34
|
+
priceUsdc,
|
|
35
|
+
agentIntent: "evaluate_x402_resource",
|
|
36
|
+
}, config);
|
|
37
|
+
const decision = (approval.card.decision ?? "unknown");
|
|
38
|
+
const receiptUrl = payTo
|
|
39
|
+
? `${config.intelBase}/v1/intel/trust/${encodeURIComponent(payTo)}`
|
|
40
|
+
: undefined;
|
|
41
|
+
const base = {
|
|
42
|
+
decision,
|
|
43
|
+
trustScore: approval.card.trust_score ?? null,
|
|
44
|
+
approved: approval.approved,
|
|
45
|
+
reason: approval.reason,
|
|
46
|
+
card: approval.card,
|
|
47
|
+
failOpen: approval.failOpen,
|
|
48
|
+
receiptUrl,
|
|
49
|
+
};
|
|
50
|
+
// Autonomous risk-escalation: a *proceeding* `warn` (uncertain / unknown seller)
|
|
51
|
+
// is vetted by settling the cheap $0.001 quick tier and re-deciding on the paid
|
|
52
|
+
// score. This is the autonomous demand loop - the paid call fires from the agent's
|
|
53
|
+
// own risk policy, and the paid signal gates the spend (only tightens). Fail-soft:
|
|
54
|
+
// if the quick tier cannot answer, the base warn decision is preserved.
|
|
55
|
+
if (opts.escalateOnWarn &&
|
|
56
|
+
typeof opts.x402Fetch === "function" &&
|
|
57
|
+
payTo &&
|
|
58
|
+
decision === "warn" &&
|
|
59
|
+
base.approved &&
|
|
60
|
+
(priceUsdc ?? 0) >= (opts.escalateOnWarn.minSpendUsdc ?? 0)) {
|
|
61
|
+
const floor = opts.escalateOnWarn.blockBelowScore ?? config.preflightMinScore;
|
|
62
|
+
const quick = await quickCheck(payTo, {
|
|
63
|
+
intelBase: config.intelBase,
|
|
64
|
+
fetch: config.fetch,
|
|
65
|
+
x402Fetch: opts.x402Fetch,
|
|
66
|
+
});
|
|
67
|
+
if (quick.available && quick.score !== null) {
|
|
68
|
+
const escApproved = quick.score >= floor;
|
|
69
|
+
return {
|
|
70
|
+
...base,
|
|
71
|
+
approved: escApproved,
|
|
72
|
+
trustScore: quick.score,
|
|
73
|
+
escalated: true,
|
|
74
|
+
escalatedScore: quick.score,
|
|
75
|
+
escalatedTier: quick.tier,
|
|
76
|
+
reason: escApproved
|
|
77
|
+
? `twzrd_escalated_warn_allow (paid quick score ${quick.score} >= ${floor})`
|
|
78
|
+
: `twzrd_escalated_warn_block (paid quick score ${quick.score} < ${floor})`,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
// Quick tier could not answer (fail-soft) - preserve the base warn decision.
|
|
82
|
+
return { ...base, escalated: true, escalatedScore: null };
|
|
83
|
+
}
|
|
84
|
+
// Auto-upsell: on warn or allow, fetch the paid TWZRD trust receipt.
|
|
85
|
+
// This is the revenue capture path: x402Fetch settles $0.05 USDC to TWZRD.
|
|
86
|
+
if (opts.autoReceipt &&
|
|
87
|
+
typeof opts.x402Fetch === "function" &&
|
|
88
|
+
payTo &&
|
|
89
|
+
decision !== "block") {
|
|
90
|
+
try {
|
|
91
|
+
// Echo the verify->act funnel link so this paid call is attributed to its preflight.
|
|
92
|
+
const headers = { accept: "application/json" };
|
|
93
|
+
if (typeof approval.preflightId === "number") {
|
|
94
|
+
headers["x-twzrd-preflight-id"] = String(approval.preflightId);
|
|
95
|
+
}
|
|
96
|
+
const resp = await opts.x402Fetch(`${config.intelBase}/v1/intel/trust/${encodeURIComponent(payTo)}`, { method: "GET", headers });
|
|
97
|
+
if (resp.ok) {
|
|
98
|
+
const body = (await resp.json());
|
|
99
|
+
const receipt = body.twzrd_receipt;
|
|
100
|
+
const preimage = receipt?.preimage;
|
|
101
|
+
const tx = body.tx ?? body.tx_pending ?? (typeof preimage?.settlement_tx === "string" ? preimage.settlement_tx : undefined);
|
|
102
|
+
const feeCaptured = !!tx || body.charged === true;
|
|
103
|
+
if (opts.onReceipt)
|
|
104
|
+
opts.onReceipt(receipt, tx);
|
|
105
|
+
return { ...base, receipt, receiptTx: tx, receiptFeeCaptured: feeCaptured };
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
// Fail-open: receipt upsell failure does not block access to the resource.
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return base;
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=evaluate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evaluate.js","sourceRoot":"","sources":["../src/evaluate.ts"],"names":[],"mappings":"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"}
|
package/dist/gate.d.ts
CHANGED
|
@@ -16,4 +16,17 @@ export type TwzrdGate = {
|
|
|
16
16
|
export declare function createTwzrdGate(overrides?: TwzrdGateConfig): TwzrdGate;
|
|
17
17
|
/** Default gate using process.env / global fetch */
|
|
18
18
|
export declare const defaultGate: TwzrdGate;
|
|
19
|
+
/**
|
|
20
|
+
* Decorator-style guard for agent payment flows.
|
|
21
|
+
* Runs TWZRD preflight on the seller before invoking `fn`.
|
|
22
|
+
* Throws if policy denies; passes through on allow/warn.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* const safePay = withTwzrdGuard(
|
|
26
|
+
* (seller) => agentcashFetch(`https://api.seller.xyz/paid`),
|
|
27
|
+
* { preflightMinScore: 50 }
|
|
28
|
+
* );
|
|
29
|
+
* const result = await safePay("SELLER_WALLET_BASE58");
|
|
30
|
+
*/
|
|
31
|
+
export declare function withTwzrdGuard<TArgs extends unknown[], TReturn>(fn: (sellerWallet: string, ...args: TArgs) => Promise<TReturn>, config?: TwzrdGateConfig): (sellerWallet: string, ...args: TArgs) => Promise<TReturn>;
|
|
19
32
|
//# sourceMappingURL=gate.d.ts.map
|
package/dist/gate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAE1E,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACf,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAE7E,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEnH,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAC;IACzC,SAAS,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;IAC7E,cAAc,EAAE,CAAC,GAAG,EAAE,mBAAmB,KAAK,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;IACrF,kBAAkB,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACrE,SAAS,EAAE,CAAC,UAAU,EAAE,OAAO,KAAK,KAAK,OAAO,KAAK,CAAC;IACtD,qBAAqB,EAAE,OAAO,qBAAqB,CAAC;IACpD,mBAAmB,EAAE,OAAO,mBAAmB,CAAC;IAChD,qBAAqB,EAAE,OAAO,qBAAqB,CAAC;IACpD,wBAAwB,EAAE,OAAO,wBAAwB,CAAC;CAC3D,CAAC;AAEF,wBAAgB,eAAe,CAAC,SAAS,CAAC,EAAE,eAAe,GAAG,SAAS,CAatE;AAED,oDAAoD;AACpD,eAAO,MAAM,WAAW,EAAE,SAA6B,CAAC"}
|
|
1
|
+
{"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAE1E,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACf,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAE7E,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEnH,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAC;IACzC,SAAS,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;IAC7E,cAAc,EAAE,CAAC,GAAG,EAAE,mBAAmB,KAAK,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;IACrF,kBAAkB,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACrE,SAAS,EAAE,CAAC,UAAU,EAAE,OAAO,KAAK,KAAK,OAAO,KAAK,CAAC;IACtD,qBAAqB,EAAE,OAAO,qBAAqB,CAAC;IACpD,mBAAmB,EAAE,OAAO,mBAAmB,CAAC;IAChD,qBAAqB,EAAE,OAAO,qBAAqB,CAAC;IACpD,wBAAwB,EAAE,OAAO,wBAAwB,CAAC;CAC3D,CAAC;AAEF,wBAAgB,eAAe,CAAC,SAAS,CAAC,EAAE,eAAe,GAAG,SAAS,CAatE;AAED,oDAAoD;AACpD,eAAO,MAAM,WAAW,EAAE,SAA6B,CAAC;AAExD;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,KAAK,SAAS,OAAO,EAAE,EAAE,OAAO,EAC7D,EAAE,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,OAAO,CAAC,EAC9D,MAAM,CAAC,EAAE,eAAe,GACvB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,OAAO,CAAC,CAc5D"}
|
package/dist/gate.js
CHANGED
|
@@ -19,4 +19,26 @@ export function createTwzrdGate(overrides) {
|
|
|
19
19
|
}
|
|
20
20
|
/** Default gate using process.env / global fetch */
|
|
21
21
|
export const defaultGate = createTwzrdGate();
|
|
22
|
+
/**
|
|
23
|
+
* Decorator-style guard for agent payment flows.
|
|
24
|
+
* Runs TWZRD preflight on the seller before invoking `fn`.
|
|
25
|
+
* Throws if policy denies; passes through on allow/warn.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* const safePay = withTwzrdGuard(
|
|
29
|
+
* (seller) => agentcashFetch(`https://api.seller.xyz/paid`),
|
|
30
|
+
* { preflightMinScore: 50 }
|
|
31
|
+
* );
|
|
32
|
+
* const result = await safePay("SELLER_WALLET_BASE58");
|
|
33
|
+
*/
|
|
34
|
+
export function withTwzrdGuard(fn, config) {
|
|
35
|
+
const cfg = resolveConfig(config);
|
|
36
|
+
return async (sellerWallet, ...args) => {
|
|
37
|
+
const { approved, verdict, score, reason } = await twzrdApprovePayment({ sellerWallet, agentIntent: "withTwzrdGuard" }, cfg);
|
|
38
|
+
if (!approved) {
|
|
39
|
+
throw new Error(`[twzrd] withTwzrdGuard blocked: ${reason} (verdict=${verdict}, score=${score})`);
|
|
40
|
+
}
|
|
41
|
+
return fn(sellerWallet, ...args);
|
|
42
|
+
};
|
|
43
|
+
}
|
|
22
44
|
//# sourceMappingURL=gate.js.map
|