@aifinpay/agent 1.6.0 → 1.8.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.
@@ -0,0 +1,301 @@
1
+ import { AiFinPayError } from "./errors.js";
2
+ export declare class Aifp1Error extends AiFinPayError {
3
+ }
4
+ /** /v1/quote refused, or answered something that is not a quote. */
5
+ export declare class Aifp1QuoteError extends Aifp1Error {
6
+ }
7
+ /** The quote cannot be settled by this SDK (no asset we can send). */
8
+ export declare class Aifp1SettlementUnsupportedError extends Aifp1Error {
9
+ }
10
+ /**
11
+ * Money moved on-chain but /v1/pay did not issue a receipt.
12
+ *
13
+ * Carries the tx hash because that is the only thing standing between the
14
+ * caller and a lost payment: the quote is still settleable through
15
+ * `POST /v1/pay` by hand with the same Idempotency-Key, and without the hash
16
+ * in the error there is nothing to retry with.
17
+ */
18
+ export declare class Aifp1PayError extends Aifp1Error {
19
+ readonly txRef?: string | undefined;
20
+ readonly quoteId?: string | undefined;
21
+ constructor(msg: string, txRef?: string | undefined, quoteId?: string | undefined);
22
+ }
23
+ /** The gateway rejected a receipt we believed covered the request. */
24
+ export declare class Aifp1ReceiptRejectedError extends Aifp1Error {
25
+ }
26
+ export type Aifp1Scope = "exact" | "prefix" | "merchant";
27
+ /** The 402 body — routes/gateway.js payChallenge(). */
28
+ export interface Aifp1Challenge {
29
+ error: string;
30
+ protocol: string;
31
+ detail?: string;
32
+ merchant_id: string;
33
+ resource: string;
34
+ unit_weight: number;
35
+ base_unit_price_usd?: string;
36
+ how_to_pay?: string[];
37
+ scopes?: {
38
+ note?: string;
39
+ examples?: string[];
40
+ };
41
+ }
42
+ /** POST /v1/quote 200 body — routes/aifp.js (`used` is stripped server-side). */
43
+ export interface Aifp1Quote {
44
+ quote_id: string;
45
+ merchant_id: string;
46
+ resource: string;
47
+ scope: Aifp1Scope;
48
+ tier: string;
49
+ unit_price: string;
50
+ requests: number;
51
+ units: number;
52
+ unit_quota: number;
53
+ amount: string;
54
+ currency: string;
55
+ accepted_assets: string[];
56
+ accepted_chains: string[];
57
+ pay_to: Record<string, string>;
58
+ /** Present only when the backend had a live POL rate at quote time. */
59
+ native_settlement?: {
60
+ asset: string;
61
+ decimals: number;
62
+ rate_usd: string;
63
+ total_wei: string;
64
+ merchant_wei: string;
65
+ treasury_wei: string;
66
+ creator_wei: string;
67
+ };
68
+ settlement: {
69
+ batch_units: string;
70
+ total_units: string;
71
+ fee_on_top: {
72
+ provider: string;
73
+ treasury: string;
74
+ creator: string;
75
+ };
76
+ };
77
+ nonce: string;
78
+ expires_at: string;
79
+ }
80
+ /** POST /v1/pay 200 body — routes/aifp.js. */
81
+ export interface Aifp1PayResult {
82
+ receipt_id: string;
83
+ receipt: string;
84
+ status: string;
85
+ tx_ref: string;
86
+ merchant_id: string;
87
+ resource: string;
88
+ scope: Aifp1Scope;
89
+ amount: string;
90
+ currency: string;
91
+ quota: number;
92
+ unit_quota: number;
93
+ asset: string;
94
+ chain: string;
95
+ settled_at: string;
96
+ expires_at: string;
97
+ policy_exceeded?: boolean;
98
+ policy_reason?: string;
99
+ }
100
+ /** Mirror of scope.js scopeCovers(). */
101
+ export declare function scopeCovers(scope: string | undefined, resource: string, path: string): boolean;
102
+ /**
103
+ * Mirror of routes/gateway.js prefixHint(): /articles/2026/thing → /articles/,
104
+ * and a single-segment path → "/" (the whole site).
105
+ */
106
+ export declare function prefixHint(path: string): string;
107
+ /**
108
+ * Split a gateway URL the way routes/gateway.js splits it: first path segment
109
+ * is the merchant slug, the rest is the merchant-relative resource, and the
110
+ * query string is not part of either.
111
+ *
112
+ * `site` (origin + slug) is the cache key. It is the only merchant identity
113
+ * available before the first 402 answers with a merchant_id, and slug →
114
+ * merchant is a 1:1 lookup server-side (gw.resolveSlug).
115
+ */
116
+ /**
117
+ * Gateway origins this client will settle against.
118
+ *
119
+ * Without this the client paid whoever answered. parseGatewayUrl looked only
120
+ * at the path, so ANY host could return {error:"AIFP-402", protocol:"AIFP-1",
121
+ * merchant_id:"mrch_theirs"} and the agent would quote, settle real POL to the
122
+ * address in that quote, and hand over a receipt. The 402 is unauthenticated
123
+ * by construction — it is the answer to a request that carried no credentials —
124
+ * so the only thing separating a paywall from a trap is knowing whose paywall
125
+ * it is.
126
+ *
127
+ * Override for self-hosted gateways; an empty list is refused rather than
128
+ * treated as "allow all", because that is the shape a config bug takes.
129
+ */
130
+ export declare const DEFAULT_GATEWAY_ORIGINS: readonly ["https://gateway.aifinpay.io"];
131
+ export declare function parseGatewayUrl(url: string, allowedOrigins?: readonly string[]): {
132
+ site: string;
133
+ slug: string;
134
+ restPath: string;
135
+ };
136
+ /**
137
+ * The `exp` of a receipt JWT, in ms, without verifying it — we are not
138
+ * authenticating the token here, only recovering a expiry the response failed
139
+ * to state. Returns null if the claim is absent or unreadable.
140
+ */
141
+ export declare function jwtExpiryMs(jwt: string): number | null;
142
+ /**
143
+ * The Idempotency-Key for one /v1/pay call. Required by the server
144
+ * (routes/aifp.js: 400 without it) and load-bearing here for a different
145
+ * reason: it is what stops one settled transaction being turned into two
146
+ * receipts, or a network blip during /v1/pay from becoming a second on-chain
147
+ * payment on retry.
148
+ *
149
+ * Derived from exactly the four fields the server itself hashes into its
150
+ * idempotency record — quote_id, asset, chain, tx_ref. That equivalence is the
151
+ * point:
152
+ *
153
+ * • the same payment retried ⇒ the same key ⇒ the server replays the first
154
+ * response instead of issuing a second receipt;
155
+ * • a different payment ⇒ a different key, because a different payment must
156
+ * differ in at least one of those four (quote_id alone is single-use —
157
+ * `quote.used` makes a second settlement of one quote a 409);
158
+ * • and the server's "same key, different body → 409" branch is unreachable
159
+ * from this client, since the key is a pure function of that body.
160
+ *
161
+ * A random key would satisfy the header requirement and none of the above.
162
+ */
163
+ export declare function idempotencyKeyFor(p: {
164
+ quoteId: string;
165
+ chain: string;
166
+ asset: string;
167
+ txRef: string;
168
+ }): string;
169
+ export interface Aifp1CachedReceipt {
170
+ /** origin + slug, as parseGatewayUrl() computes it. */
171
+ site: string;
172
+ merchantId: string;
173
+ receiptId: string;
174
+ /** The bearer JWT. Never log this. */
175
+ jwt: string;
176
+ scope: Aifp1Scope;
177
+ resource: string;
178
+ unitQuota: number;
179
+ /** Billing units we believe are left. Corrected from AIFP-Quota-Remaining. */
180
+ remaining: number;
181
+ /** JWT expiry, ms epoch. */
182
+ expiresAt: number;
183
+ amountUsd: number;
184
+ }
185
+ /**
186
+ * The receipts this agent holds, and the rules for spending them.
187
+ *
188
+ * In-memory and per-agent-instance: a receipt is a bearer credential, and
189
+ * writing one to disk by default would be a bigger decision than a cache
190
+ * deserves. An agent that wants batches to survive a restart can hold the
191
+ * entries itself (they are plain data) and re-seed a cache.
192
+ */
193
+ export declare class Aifp1ReceiptCache {
194
+ private readonly entries;
195
+ /**
196
+ * Batch purchases in flight, keyed by site.
197
+ *
198
+ * The cache is empty between deciding to buy and the receipt arriving, so
199
+ * ten workers sharing one agent all missed, all got a 402, and all settled
200
+ * their own batch — ten on-chain payments and ten minimum charges where one
201
+ * would have covered every worker. It recurred at each quota boundary, so
202
+ * the more traffic an agent had the more it overpaid.
203
+ *
204
+ * Second and later callers await the first purchase, then re-check the
205
+ * cache: whoever wins buys a batch wide enough that the rest find it
206
+ * covering their path too. If it does not cover them (a different prefix)
207
+ * they fall through and buy their own, which is correct — that is a
208
+ * different batch, not a duplicate.
209
+ */
210
+ private readonly inflight;
211
+ /** Run `buy` for `site`, or await the purchase already running for it. */
212
+ coalesce<T>(site: string, buy: () => Promise<T>): Promise<T | "retry">;
213
+ /**
214
+ * The receipt to send for this request, if we hold one.
215
+ *
216
+ * Three conditions, all necessary:
217
+ * • same merchant — a receipt's `aud` is the merchant id, so sending one
218
+ * elsewhere is at best a 403 and at worst paying the wrong party;
219
+ * • the scope covers the path — the same test the gateway will apply;
220
+ * • quota left and not expired.
221
+ *
222
+ * `remaining > 0` rather than `remaining >= weight`: we only learn a route's
223
+ * weight from a 402 refusing it, so the weight of a path we have not been
224
+ * refused on is genuinely unknown here. The gateway's meter is authoritative
225
+ * and answers 402 "quota exhausted" when the batch cannot cover the call —
226
+ * at which point we re-quote. Guessing a weight would only add a way to be
227
+ * wrong in the direction of not spending a batch we own.
228
+ */
229
+ find(site: string, restPath: string, merchantId?: string): Aifp1CachedReceipt | undefined;
230
+ put(entry: Aifp1CachedReceipt): void;
231
+ /** The gateway's own count wins over ours — it is the one doing the metering. */
232
+ noteQuotaRemaining(entry: Aifp1CachedReceipt, remaining: number): void;
233
+ evict(entry: Aifp1CachedReceipt): void;
234
+ /** Everything we still hold, expired entries dropped. Plain data, copyable. */
235
+ list(): Aifp1CachedReceipt[];
236
+ get size(): number;
237
+ }
238
+ export interface Aifp1FetchOptions {
239
+ /**
240
+ * How wide a batch to buy. Default "prefix" — see the comment on
241
+ * resolveScope() for why the default is not "exact".
242
+ */
243
+ scope?: Aifp1Scope;
244
+ /** Override the resource the batch is scoped to (ignored for "merchant"). */
245
+ resource?: string;
246
+ /** Billing units to prepay. Default 1000 = $0.10 at the base unit price. */
247
+ units?: number;
248
+ /** Where /v1/quote and /v1/pay live. Default https://api.aifinpay.io */
249
+ apiBaseUrl?: string;
250
+ /**
251
+ * Gateway origins this client will settle against. Defaults to
252
+ * DEFAULT_GATEWAY_ORIGINS — set it only for a self-hosted gateway, and
253
+ * never to a host you do not control the paywall of.
254
+ */
255
+ gatewayOrigins?: readonly string[];
256
+ /** Value for the AIFP-Agent-Id header; defaults to the agent's EVM address. */
257
+ agentId?: string;
258
+ /** How long to keep retrying /v1/pay while the chain catches up (AIFP-425). */
259
+ settlementConfirmMs?: number;
260
+ }
261
+ /**
262
+ * Everything the flow needs that is not the AIFP-1 protocol itself. The
263
+ * settlement and the budget hooks are AiFinPayAgent's; splitting them out is
264
+ * what lets the protocol be tested without a chain.
265
+ */
266
+ export interface Aifp1Deps {
267
+ fetchImpl: typeof fetch;
268
+ cache: Aifp1ReceiptCache;
269
+ /** AIFP-Agent-Id / agent_id — a 0x address, or agent policies cannot key on it. */
270
+ agentId: string;
271
+ /**
272
+ * Settle `totalWei` to `merchantWallet` with `orderId`, returning a hash
273
+ * whose transaction was included AND succeeded.
274
+ */
275
+ settle(p: {
276
+ merchantWallet: `0x${string}`;
277
+ totalWei: bigint;
278
+ orderId: string;
279
+ }): Promise<`0x${string}`>;
280
+ /** Per-call cap. false ⇒ the caller asked to skip rather than throw. */
281
+ checkPerCall(usd: number): boolean;
282
+ /** Daily cap. "skip" ⇒ drop the call; a string is a reservation to resolve. */
283
+ reserveDaily(usd: number): Promise<string | null | "skip">;
284
+ commit(reservationId: string, usd: number): Promise<void>;
285
+ release(reservationId: string): Promise<void>;
286
+ onPaid?(info: {
287
+ merchantId: string;
288
+ amountUsd: number;
289
+ txRef: string;
290
+ receiptId: string;
291
+ }): void;
292
+ }
293
+ /**
294
+ * Fetch a gateway URL, paying the AIFP-1 paywall if it asks.
295
+ *
296
+ * Returns the merchant's response. Returns null only when a budget cap was hit
297
+ * and `on_limit_exceeded` is "skip" — the same contract AiFinPayAgent.call()
298
+ * already has.
299
+ */
300
+ export declare function aifp1Fetch(deps: Aifp1Deps, url: string, init?: RequestInit, opts?: Aifp1FetchOptions): Promise<Response | null>;
301
+ //# sourceMappingURL=aifp1.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aifp1.d.ts","sourceRoot":"","sources":["../src/aifp1.ts"],"names":[],"mappings":"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"}