kawasekit 0.1.0-beta.2 → 0.1.0-beta.3
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 +56 -18
- package/dist/{chunk-ZES4UYIQ.js → chunk-2V3W4B64.js} +47 -7
- package/dist/chunk-2V3W4B64.js.map +1 -0
- package/dist/{chunk-DLH2O4MU.js → chunk-6G345P2I.js} +3 -3
- package/dist/{chunk-DLH2O4MU.js.map → chunk-6G345P2I.js.map} +1 -1
- package/dist/{chunk-ZY6RT2DB.js → chunk-CD6SQBZN.js} +211 -30
- package/dist/chunk-CD6SQBZN.js.map +1 -0
- package/dist/chunk-WMFCI6KC.js +333 -0
- package/dist/chunk-WMFCI6KC.js.map +1 -0
- package/dist/cli/index.cjs +3 -3
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +7 -6
- package/dist/cli/index.js.map +1 -1
- package/dist/idempotency/index.cjs +353 -0
- package/dist/idempotency/index.cjs.map +1 -0
- package/dist/idempotency/index.d.cts +203 -0
- package/dist/idempotency/index.d.ts +203 -0
- package/dist/idempotency/index.js +5 -0
- package/dist/idempotency/index.js.map +1 -0
- package/dist/index-NdNKNnZP.d.cts +808 -0
- package/dist/index-kqH78Yms.d.ts +808 -0
- package/dist/index.cjs +575 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +40 -4
- package/dist/index.d.ts +40 -4
- package/dist/index.js +4 -3
- package/dist/observability/index.d.cts +203 -2
- package/dist/observability/index.d.ts +203 -2
- package/dist/observability/otlp/index.d.cts +2 -1
- package/dist/observability/otlp/index.d.ts +2 -1
- package/dist/observability/prometheus/index.d.cts +2 -1
- package/dist/observability/prometheus/index.d.ts +2 -1
- package/dist/{server-t1qVFVnJ.d.ts → server-BMeg_hNB.d.cts} +30 -2
- package/dist/{server-C3XkkTIP.d.cts → server-CSpATNiH.d.ts} +30 -2
- package/dist/store-BY16tCbe.d.cts +166 -0
- package/dist/store-Bd-91QL0.d.ts +166 -0
- package/dist/{index-Bf78wMqn.d.cts → types-A_WwFpcv.d.cts} +1 -200
- package/dist/{index-WQ_Hq4_Z.d.ts → types-DwFfT4E7.d.ts} +1 -200
- package/dist/x402/hono/index.cjs +335 -4
- package/dist/x402/hono/index.cjs.map +1 -1
- package/dist/x402/hono/index.d.cts +4 -2
- package/dist/x402/hono/index.d.ts +4 -2
- package/dist/x402/hono/index.js +2 -1
- package/dist/x402/hono/index.js.map +1 -1
- package/dist/x402/index.cjs +373 -3
- package/dist/x402/index.cjs.map +1 -1
- package/dist/x402/index.d.cts +7 -768
- package/dist/x402/index.d.ts +7 -768
- package/dist/x402/index.js +3 -2
- package/package.json +11 -1
- package/dist/chunk-ZES4UYIQ.js.map +0 -1
- package/dist/chunk-ZY6RT2DB.js.map +0 -1
package/README.md
CHANGED
|
@@ -5,7 +5,11 @@
|
|
|
5
5
|
[](https://www.npmjs.com/package/kawasekit)
|
|
6
6
|
[](https://opensource.org/licenses/Apache-2.0)
|
|
7
7
|
|
|
8
|
-
🚧 **Status**:
|
|
8
|
+
🚧 **Status**: M4 complete — `kawasekit@0.1.0-beta.2` is published on npm (SLSA provenance, `beta` dist-tag) and mainnet-capable, with payment flows verified on Polygon mainnet. **Not yet GA.** Production use is currently constrained to **small per-call values**: the reasoning-step idempotency gap (see [`docs/THREAT_MODEL.md` §6.1](./docs/THREAT_MODEL.md#61-reasoning-step-idempotency-gap)) is not yet closed, so duplicate-payment scenarios are the integrator's responsibility. GA (`0.1.0` on the `latest` tag) is gated on closing the fund-correctness gaps — the §6.1 idempotency layer (or GA explicitly scoped to small per-call values) plus a `maxAmountPerSign` ceiling — and a clean beta soak. Review happens **continuously in the open**: issues and counter-examples are welcome on GitHub and via [SECURITY.md](./SECURITY.md) (the §6.1 gap itself came from public feedback). A formal third-party audit is a goal on the road to `1.0`, not a `0.1.0` GA blocker. Built in public.
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
pnpm add kawasekit@beta # 0.1.0-beta.2 — pre-GA, mainnet-capable
|
|
12
|
+
```
|
|
9
13
|
|
|
10
14
|
## Vision
|
|
11
15
|
|
|
@@ -19,9 +23,9 @@ Built around modern account abstraction (ERC-4337 / Kernel v3.1) and Japan's fir
|
|
|
19
23
|
|
|
20
24
|
- [x] **M1**: Smart account skeleton on Polygon Amoy
|
|
21
25
|
- [x] **M2**: JPYC transfer via UserOp + EIP-3009 signing helpers + Daily Limit spending policy
|
|
22
|
-
- [x] **M3**: x402 v2 server/client/facilitator + session-key lifecycle + Mastra/Hono integration example
|
|
23
|
-
- [
|
|
24
|
-
- [ ] **M5**:
|
|
26
|
+
- [x] **M3**: x402 v2 server/client/facilitator + session-key lifecycle + Mastra/Hono integration example
|
|
27
|
+
- [x] **M4**: Polygon mainnet support + observability (Prometheus / OTLP) + CLI + docs site + npm `0.1.0-alpha`/`0.1.0-beta` release
|
|
28
|
+
- [ ] **M5**: Reasoning-step idempotency layer (§6.1) + `0.1.0` GA promote + Kaia support — the technical prerequisites for first real integrations
|
|
25
29
|
- [ ] **M6**: Managed service alpha + Rust policy engine
|
|
26
30
|
|
|
27
31
|
## Quick Start
|
|
@@ -64,6 +68,28 @@ pays 0.001 JPYC, and the summary prints Polygonscan tx URLs for every
|
|
|
64
68
|
settlement. See the [example README](./examples/agent-x402-jpyc/README.md)
|
|
65
69
|
for the full walkthrough.
|
|
66
70
|
|
|
71
|
+
### CLI (M4-4)
|
|
72
|
+
|
|
73
|
+
Installing the package exposes a `kawasekit` binary (`npx kawasekit <cmd>`, or
|
|
74
|
+
`pnpm exec kawasekit` in a workspace):
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
pnpm add kawasekit@beta
|
|
78
|
+
|
|
79
|
+
npx kawasekit init # scaffold .env + required vars
|
|
80
|
+
npx kawasekit account create --chain polygonAmoy # deploy a Kernel smart account
|
|
81
|
+
npx kawasekit policy create --chain polygonAmoy # build a Daily Limit policy
|
|
82
|
+
npx kawasekit transfer --chain polygonAmoy # send JPYC via a sponsored UserOp
|
|
83
|
+
npx kawasekit session-key issue --chain polygonAmoy # issue a session key + envelope
|
|
84
|
+
npx kawasekit session-key restore --chain polygonAmoy
|
|
85
|
+
npx kawasekit session-key revoke --chain polygonAmoy
|
|
86
|
+
npx kawasekit session-key rotate --chain polygonAmoy
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Every on-chain command takes `--chain "polygon" | "polygonAmoy"`. Mainnet
|
|
90
|
+
(`--chain polygon`) additionally requires `KAWASEKIT_ALLOW_MAINNET=1` in the
|
|
91
|
+
environment as a safety guard against accidental real-funds broadcasts.
|
|
92
|
+
|
|
67
93
|
### Programmatic use (M2)
|
|
68
94
|
|
|
69
95
|
```typescript
|
|
@@ -147,7 +173,9 @@ const app = new Hono();
|
|
|
147
173
|
app.use(
|
|
148
174
|
"/weather/*",
|
|
149
175
|
x402Middleware({
|
|
150
|
-
|
|
176
|
+
// `network` is required (M4-1): it is cross-checked against
|
|
177
|
+
// walletClient.chain.isTestnet and throws on mismatch.
|
|
178
|
+
facilitator: createSelfFacilitator({ network: "testnet", walletClient, publicClient }),
|
|
151
179
|
requirementsFor: () => [
|
|
152
180
|
buildPaymentRequirements({
|
|
153
181
|
chainId: polygonAmoy.id,
|
|
@@ -164,7 +192,8 @@ app.get("/weather/:city", (c) => c.json({ city: c.req.param("city"), weather: "s
|
|
|
164
192
|
Client (any `fetch` becomes x402-aware):
|
|
165
193
|
|
|
166
194
|
```typescript
|
|
167
|
-
import { createX402PaymentSigner, wrapFetch } from "kawasekit";
|
|
195
|
+
import { createX402PaymentSigner, JPYC_DECIMALS, wrapFetch } from "kawasekit";
|
|
196
|
+
import { parseUnits } from "viem";
|
|
168
197
|
import { privateKeyToAccount } from "viem/accounts";
|
|
169
198
|
|
|
170
199
|
const signer = createX402PaymentSigner({
|
|
@@ -178,7 +207,7 @@ const signer = createX402PaymentSigner({
|
|
|
178
207
|
// onPayment is *required* at the type level — kawasekit refuses to default
|
|
179
208
|
// to "always pay" silently. The callback is your budget guard.
|
|
180
209
|
let spent = 0n;
|
|
181
|
-
const MAX_SPEND =
|
|
210
|
+
const MAX_SPEND = parseUnits("100", JPYC_DECIMALS); // 100 JPYC (JPYC has 18 decimals)
|
|
182
211
|
const fetch402 = wrapFetch({
|
|
183
212
|
signer,
|
|
184
213
|
onPayment: (req) => {
|
|
@@ -234,21 +263,30 @@ const restored = await restoreSessionAccount({
|
|
|
234
263
|
|
|
235
264
|
## Supported Chains
|
|
236
265
|
|
|
237
|
-
|
|
266
|
+
JPYC availability and kawasekit support are **two separate axes** — JPYC being
|
|
267
|
+
live on a chain does **not** mean kawasekit has a config or has been tested
|
|
268
|
+
there. Today kawasekit ships a chain config only for **Polygon + Polygon Amoy**
|
|
269
|
+
(`src/chains/`); `getJpycAddress` / `SupportedChainId` accept only those two.
|
|
270
|
+
|
|
271
|
+
| Chain | JPYC availability | kawasekit support |
|
|
238
272
|
|---|---|---|
|
|
239
|
-
| Polygon
|
|
240
|
-
| Polygon Amoy (testnet) |
|
|
241
|
-
| Kaia |
|
|
242
|
-
| Avalanche |
|
|
243
|
-
| Ethereum |
|
|
273
|
+
| Polygon (mainnet) | ✅ Live (`0xE7C3…c29`) | ✅ M4 — config shipped, verified with live mainnet txs |
|
|
274
|
+
| Polygon Amoy (testnet) | ✅ Live (`0xE7C3…c29`) | ✅ primary testnet target |
|
|
275
|
+
| Kaia | ✅ Live (`0xE7C3…c29`, same address)¹ | 🚧 planned M5 (x402 EOA-payer path first) |
|
|
276
|
+
| Avalanche | ✅ Live (`0xE7C3…c29`) | ⬜ not yet — no chain config |
|
|
277
|
+
| Ethereum | ✅ Live (`0xE7C3…c29`) | ⬜ not yet — no chain config |
|
|
278
|
+
|
|
279
|
+
¹ JPYC officially launched on Kaia in 2026-05 (Kaia DLT Foundation; Unifi began
|
|
280
|
+
JPYC support 2026-05-22), same contract address as the other chains. kawasekit
|
|
281
|
+
has no Kaia chain config yet — support is scheduled for M5.
|
|
244
282
|
|
|
245
283
|
## Why Japan-first
|
|
246
284
|
|
|
247
285
|
The Japanese stablecoin ecosystem in 2026 is uniquely positioned:
|
|
248
286
|
|
|
249
287
|
- **JPYC** is a fully regulated yen-pegged stablecoin under the revised Payment Services Act
|
|
250
|
-
- Multi-chain by design (same address on Ethereum, Polygon, Avalanche)
|
|
251
|
-
- Kaia
|
|
288
|
+
- Multi-chain by design (same address on Ethereum, Polygon, Avalanche, and Kaia)
|
|
289
|
+
- Now live on Kaia (2026-05), with LINE NEXT's Unifi supporting JPYC since 2026-05-22
|
|
252
290
|
- Japanese AI startup ecosystem actively seeking modern payment rails
|
|
253
291
|
|
|
254
292
|
kawasekit aims to be the developer-facing layer that connects this stablecoin infrastructure to the global AI agent ecosystem.
|
|
@@ -265,11 +303,11 @@ pnpm install
|
|
|
265
303
|
pnpm dev
|
|
266
304
|
```
|
|
267
305
|
|
|
268
|
-
The site
|
|
306
|
+
The site is live at **[kawasekit.k0yote.dev](https://kawasekit.k0yote.dev)**, auto-deployed from `main` via `.github/workflows/docs.yml`.
|
|
269
307
|
|
|
270
308
|
## Contributing
|
|
271
309
|
|
|
272
|
-
This is currently a solo project, but
|
|
310
|
+
This is currently a solo project, but with M1–M4 shipped and `0.1.0-beta` on npm, contributions are now welcome. See [CONTRIBUTING.md](./CONTRIBUTING.md) and [CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md) for guidelines.
|
|
273
311
|
|
|
274
312
|
For now, feedback, issues, and discussions are the most valuable contributions.
|
|
275
313
|
|
|
@@ -287,4 +325,4 @@ This license includes an explicit patent grant, which is important for working i
|
|
|
287
325
|
|
|
288
326
|
---
|
|
289
327
|
|
|
290
|
-
Follow development progress: [@k0yote](https://github.com/k0yote) · Project home: kawasekit.k0yote.dev
|
|
328
|
+
Follow development progress: [@k0yote](https://github.com/k0yote) · Project home: [kawasekit.k0yote.dev](https://kawasekit.k0yote.dev)
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { JPYC_EIP712_DOMAIN_HINT, JPYC_V2_ADDRESS, X402InvalidPayloadError,
|
|
1
|
+
import { JPYC_EIP712_DOMAIN_HINT, JPYC_V2_ADDRESS, X402InvalidPayloadError, X402_HEADER_PAYMENT_SIGNATURE, encodePaymentSignatureHeader, X402_HEADER_IDEMPOTENCY_KEY, X402_HEADER_PAYMENT_RESPONSE, decodePaymentResponseHeader, X402InvalidConfigError, X402_HEADER_PAYMENT_REQUIRED, decodePaymentRequiredHeader, jpycAbi } from './chunk-CD6SQBZN.js';
|
|
2
|
+
import { X402_VERSION, chainIdToX402Network, x402NetworkToChainId } from './chunk-WMFCI6KC.js';
|
|
2
3
|
import { getChain, isSupportedChainId } from './chunk-SA7LMQFG.js';
|
|
3
4
|
import { invokeHookSafely } from './chunk-LEHWRDVS.js';
|
|
4
|
-
import { getAddress, parseSignature, isAddress, recoverTypedDataAddress } from 'viem';
|
|
5
|
+
import { getAddress, keccak256, stringToHex, parseSignature, isAddress, recoverTypedDataAddress } from 'viem';
|
|
5
6
|
|
|
6
7
|
var transferWithAuthorizationTypes = {
|
|
7
8
|
TransferWithAuthorization: [
|
|
@@ -34,6 +35,20 @@ function generateAuthorizationNonce() {
|
|
|
34
35
|
crypto.getRandomValues(bytes);
|
|
35
36
|
return `0x${Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("")}`;
|
|
36
37
|
}
|
|
38
|
+
var EIP3009_NONCE_DOMAIN_TAG = "kawasekit/eip3009-nonce/1";
|
|
39
|
+
function deriveAuthorizationNonce(input, scope) {
|
|
40
|
+
if (input.idempotencyKey === "") {
|
|
41
|
+
throw new Error("deriveAuthorizationNonce: idempotencyKey must be a non-empty string");
|
|
42
|
+
}
|
|
43
|
+
const preimage = JSON.stringify([
|
|
44
|
+
EIP3009_NONCE_DOMAIN_TAG,
|
|
45
|
+
input.idempotencyKey,
|
|
46
|
+
getAddress(scope.from),
|
|
47
|
+
getAddress(scope.verifyingContract),
|
|
48
|
+
scope.chainId
|
|
49
|
+
]);
|
|
50
|
+
return keccak256(stringToHex(preimage));
|
|
51
|
+
}
|
|
37
52
|
function authorizationDeadlineFromNow(seconds, nowSec) {
|
|
38
53
|
const now = nowSec ?? BigInt(Math.floor(Date.now() / 1e3));
|
|
39
54
|
return now + BigInt(seconds);
|
|
@@ -224,6 +239,13 @@ function createX402PaymentSigner(params) {
|
|
|
224
239
|
`\`defaultLifetimeSeconds\` must be positive, got ${defaultLifetimeSeconds}`
|
|
225
240
|
);
|
|
226
241
|
}
|
|
242
|
+
const maxAmountPerSign = params.maxAmountPerSign;
|
|
243
|
+
if (maxAmountPerSign !== void 0 && maxAmountPerSign <= 0n) {
|
|
244
|
+
throw new X402InvalidPayloadError(
|
|
245
|
+
"X402PaymentSignerConfig",
|
|
246
|
+
`\`maxAmountPerSign\` must be a positive bigint, got ${maxAmountPerSign}`
|
|
247
|
+
);
|
|
248
|
+
}
|
|
227
249
|
const pinnedDomain = resolveAssetParam(params.asset);
|
|
228
250
|
return {
|
|
229
251
|
address: account.address,
|
|
@@ -249,6 +271,12 @@ function createX402PaymentSigner(params) {
|
|
|
249
271
|
`requirements.asset (${getAddress(asset)}) does not match the signer's pinned verifyingContract (${pinnedDomain.verifyingContract}) \u2014 refusing to sign for an asset the signer was not configured to handle`
|
|
250
272
|
);
|
|
251
273
|
}
|
|
274
|
+
if (maxAmountPerSign !== void 0 && value > maxAmountPerSign) {
|
|
275
|
+
throw new X402InvalidPayloadError(
|
|
276
|
+
"PaymentRequirements",
|
|
277
|
+
`requirements.amount (${value}) exceeds the signer's \`maxAmountPerSign\` ceiling (${maxAmountPerSign}) \u2014 refusing to sign a payment above the configured per-signature limit (threat 1.14)`
|
|
278
|
+
);
|
|
279
|
+
}
|
|
252
280
|
const lifetime = Math.min(defaultLifetimeSeconds, paymentRequirements.maxTimeoutSeconds);
|
|
253
281
|
const validAfter = signParams.validAfter ?? 0n;
|
|
254
282
|
const validBefore = signParams.validBefore ?? authorizationDeadlineFromNow(lifetime);
|
|
@@ -258,7 +286,14 @@ function createX402PaymentSigner(params) {
|
|
|
258
286
|
`\`validBefore\` (${validBefore}) must be greater than \`validAfter\` (${validAfter})`
|
|
259
287
|
);
|
|
260
288
|
}
|
|
261
|
-
const nonce =
|
|
289
|
+
const nonce = signParams.idempotencyKey !== void 0 ? deriveAuthorizationNonce(
|
|
290
|
+
{ idempotencyKey: signParams.idempotencyKey },
|
|
291
|
+
{
|
|
292
|
+
from: account.address,
|
|
293
|
+
verifyingContract: pinnedDomain.verifyingContract,
|
|
294
|
+
chainId
|
|
295
|
+
}
|
|
296
|
+
) : generateAuthorizationNonce();
|
|
262
297
|
const signed = await signTransferWithAuthorization(
|
|
263
298
|
account,
|
|
264
299
|
{
|
|
@@ -871,12 +906,17 @@ function wrapFetch(params) {
|
|
|
871
906
|
emitFailure("onPayment_declined", 402);
|
|
872
907
|
return initialResponse;
|
|
873
908
|
}
|
|
909
|
+
const idempotencyKey = params.idempotencyKeyFor?.(input, chosen, paymentRequired);
|
|
874
910
|
const paymentPayload = await params.signer.sign({
|
|
875
911
|
paymentRequirements: chosen,
|
|
876
|
-
...paymentRequired.resource ? { resource: paymentRequired.resource } : {}
|
|
912
|
+
...paymentRequired.resource ? { resource: paymentRequired.resource } : {},
|
|
913
|
+
...idempotencyKey !== void 0 ? { idempotencyKey } : {}
|
|
877
914
|
});
|
|
878
915
|
const retryHeaders = new Headers(init?.headers);
|
|
879
916
|
retryHeaders.set(X402_HEADER_PAYMENT_SIGNATURE, encodePaymentSignatureHeader(paymentPayload));
|
|
917
|
+
if (idempotencyKey !== void 0) {
|
|
918
|
+
retryHeaders.set(X402_HEADER_IDEMPOTENCY_KEY, idempotencyKey);
|
|
919
|
+
}
|
|
880
920
|
const retryResponse = await baseFetch(input, { ...init, headers: retryHeaders });
|
|
881
921
|
if (retryResponse.status >= 200 && retryResponse.status < 300) {
|
|
882
922
|
const settlementHeader = retryResponse.headers.get(X402_HEADER_PAYMENT_RESPONSE);
|
|
@@ -912,6 +952,6 @@ function wrapFetch(params) {
|
|
|
912
952
|
};
|
|
913
953
|
}
|
|
914
954
|
|
|
915
|
-
export { X402_DEFAULT_AUTHORIZATION_LIFETIME_SECONDS, X402_FACILITATOR_ERROR_CODES, authorizationDeadlineFromNow, createCoinbaseFacilitator, createHttpFacilitator, createSelfFacilitator, createX402PaymentSigner, generateAuthorizationNonce, getKnownAssetDomain, listKnownAssetIds, signCancelAuthorization, signReceiveWithAuthorization, signTransferWithAuthorization, wrapFetch };
|
|
916
|
-
//# sourceMappingURL=chunk-
|
|
917
|
-
//# sourceMappingURL=chunk-
|
|
955
|
+
export { X402_DEFAULT_AUTHORIZATION_LIFETIME_SECONDS, X402_FACILITATOR_ERROR_CODES, authorizationDeadlineFromNow, createCoinbaseFacilitator, createHttpFacilitator, createSelfFacilitator, createX402PaymentSigner, deriveAuthorizationNonce, generateAuthorizationNonce, getKnownAssetDomain, listKnownAssetIds, signCancelAuthorization, signReceiveWithAuthorization, signTransferWithAuthorization, wrapFetch };
|
|
956
|
+
//# sourceMappingURL=chunk-2V3W4B64.js.map
|
|
957
|
+
//# sourceMappingURL=chunk-2V3W4B64.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/tokens/eip3009.ts","../src/tokens/known-assets.ts","../src/x402/client.ts","../src/x402/facilitator.ts","../src/x402/fetch.ts"],"names":["getAddress","parseSignature"],"mappings":"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","file":"chunk-2V3W4B64.js","sourcesContent":["/**\n * EIP-3009 typed-data builders and signing helpers.\n *\n * Token-agnostic: works for any EIP-3009-compliant token (JPYC, USDC, USDP,\n * Centre FiatToken family). Pure off-chain construction — no chain RPC, no\n * submission. Submission is the caller's job (M3 x402 flow, or arbitrary\n * gas-paying relayer).\n *\n * @packageDocumentation\n */\n\nimport {\n\ttype Account,\n\ttype Address,\n\tgetAddress,\n\ttype Hex,\n\tkeccak256,\n\tparseSignature,\n\tstringToHex,\n} from \"viem\";\n\n// ---------------------------------------------------------------------------\n// Domain & typed-data shapes\n// ---------------------------------------------------------------------------\n\n/**\n * EIP-712 domain for an EIP-3009-compliant token.\n *\n * `name` and `version` MUST match the values the token used when computing\n * its `DOMAIN_SEPARATOR`. For JPYC see {@link JPYC_EIP712_DOMAIN_HINT}.\n */\nexport interface Eip3009Domain {\n\treadonly name: string;\n\treadonly version: string;\n\treadonly chainId: number;\n\treadonly verifyingContract: Address;\n}\n\n/** Message body for {@link signTransferWithAuthorization}. */\nexport interface TransferWithAuthorizationMessage {\n\treadonly from: Address;\n\treadonly to: Address;\n\treadonly value: bigint;\n\treadonly validAfter: bigint;\n\treadonly validBefore: bigint;\n\t/** 32-byte random nonce. Generate with {@link generateAuthorizationNonce}. */\n\treadonly nonce: Hex;\n}\n\n/** Message body for {@link signReceiveWithAuthorization}. */\nexport type ReceiveWithAuthorizationMessage = TransferWithAuthorizationMessage;\n\n/** Message body for {@link signCancelAuthorization}. */\nexport interface CancelAuthorizationMessage {\n\treadonly authorizer: Address;\n\treadonly nonce: Hex;\n}\n\n/**\n * A signed EIP-3009 authorization, ready to be passed to the token's\n * `*WithAuthorization` entrypoint as `(v, r, s)`.\n */\nexport interface SignedAuthorization<TMessage> {\n\treadonly signature: Hex;\n\treadonly v: number;\n\treadonly r: Hex;\n\treadonly s: Hex;\n\treadonly domain: Eip3009Domain;\n\treadonly message: TMessage;\n}\n\n// ---------------------------------------------------------------------------\n// EIP-712 type definitions (must match EIP-3009 byte-for-byte)\n// ---------------------------------------------------------------------------\n\nconst transferWithAuthorizationTypes = {\n\tTransferWithAuthorization: [\n\t\t{ name: \"from\", type: \"address\" },\n\t\t{ name: \"to\", type: \"address\" },\n\t\t{ name: \"value\", type: \"uint256\" },\n\t\t{ name: \"validAfter\", type: \"uint256\" },\n\t\t{ name: \"validBefore\", type: \"uint256\" },\n\t\t{ name: \"nonce\", type: \"bytes32\" },\n\t],\n} as const;\n\nconst receiveWithAuthorizationTypes = {\n\tReceiveWithAuthorization: [\n\t\t{ name: \"from\", type: \"address\" },\n\t\t{ name: \"to\", type: \"address\" },\n\t\t{ name: \"value\", type: \"uint256\" },\n\t\t{ name: \"validAfter\", type: \"uint256\" },\n\t\t{ name: \"validBefore\", type: \"uint256\" },\n\t\t{ name: \"nonce\", type: \"bytes32\" },\n\t],\n} as const;\n\nconst cancelAuthorizationTypes = {\n\tCancelAuthorization: [\n\t\t{ name: \"authorizer\", type: \"address\" },\n\t\t{ name: \"nonce\", type: \"bytes32\" },\n\t],\n} as const;\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Generates a cryptographically random 32-byte EIP-3009 nonce.\n *\n * The nonce only needs to be unique per `(authorizer, contract)` — duplicates\n * across different tokens are harmless because the contract scopes them.\n *\n * @example\n * ```ts\n * import { generateAuthorizationNonce } from \"kawasekit\";\n *\n * const nonce = generateAuthorizationNonce();\n * ```\n */\nexport function generateAuthorizationNonce(): Hex {\n\tconst bytes = new Uint8Array(32);\n\tcrypto.getRandomValues(bytes);\n\treturn `0x${Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\"\")}` as Hex;\n}\n\n/** Domain tag separating the nonce preimage from any other keccak use in the SDK. */\nconst EIP3009_NONCE_DOMAIN_TAG = \"kawasekit/eip3009-nonce/1\";\n\n/**\n * Derives a **deterministic** 32-byte EIP-3009 nonce from a reasoning-step\n * idempotency key, scoped to `(from, verifyingContract, chainId)` so the same\n * key never collides across tokens or chains (M5-1, Half B).\n *\n * `nonce = keccak256(DOMAIN_TAG ‖ idempotencyKey ‖ from ‖ verifyingContract ‖\n * chainId)`. **No shared secret**: determinism across replicas / sub-agents\n * needs only a shared `conversationId` (the source of the key), not secret\n * distribution. A replayed key ⇒ identical nonce ⇒ the token contract's\n * `authorizationState` rejects the second settlement — the on-chain last line of\n * defence against re-signed same-intent duplicate payments. Use in place of\n * {@link generateAuthorizationNonce} only when a key is available.\n *\n * `chainId` is in the preimage, so the same JPYC address on Polygon / Avalanche\n * / Kaia / Ethereum yields distinct nonces (cross-chain replay safety).\n *\n * @example\n * ```ts\n * import { deriveAuthorizationNonce } from \"kawasekit\";\n *\n * const nonce = deriveAuthorizationNonce(\n * { idempotencyKey },\n * { from: account.address, verifyingContract, chainId },\n * );\n * ```\n */\nexport function deriveAuthorizationNonce(\n\tinput: { readonly idempotencyKey: string },\n\tscope: { readonly from: Address; readonly verifyingContract: Address; readonly chainId: number },\n): Hex {\n\tif (input.idempotencyKey === \"\") {\n\t\tthrow new Error(\"deriveAuthorizationNonce: idempotencyKey must be a non-empty string\");\n\t}\n\tconst preimage = JSON.stringify([\n\t\tEIP3009_NONCE_DOMAIN_TAG,\n\t\tinput.idempotencyKey,\n\t\tgetAddress(scope.from),\n\t\tgetAddress(scope.verifyingContract),\n\t\tscope.chainId,\n\t]);\n\treturn keccak256(stringToHex(preimage));\n}\n\n/**\n * Returns a `validBefore` UNIX timestamp `seconds` in the future.\n *\n * @param seconds - Lifetime of the authorization, in seconds.\n * @param nowSec - Optional override of \"now\" (defaults to {@link Date.now}).\n *\n * @example\n * ```ts\n * import { authorizationDeadlineFromNow } from \"kawasekit\";\n *\n * const validBefore = authorizationDeadlineFromNow(60 * 5); // 5 minutes\n * ```\n */\nexport function authorizationDeadlineFromNow(seconds: number, nowSec?: bigint): bigint {\n\tconst now = nowSec ?? BigInt(Math.floor(Date.now() / 1000));\n\treturn now + BigInt(seconds);\n}\n\nfunction requireSignTypedData(account: Account): NonNullable<Account[\"signTypedData\"]> {\n\tif (!account.signTypedData) {\n\t\tthrow new Error(\n\t\t\t`Account ${account.address} cannot sign typed data — pass a LocalAccount or a JsonRpcAccount bound to a WalletClient.`,\n\t\t);\n\t}\n\treturn account.signTypedData.bind(account);\n}\n\nfunction assertSignerMatches(account: Account, expectedFrom: Address, role: string): void {\n\tif (getAddress(account.address) !== getAddress(expectedFrom)) {\n\t\tthrow new Error(\n\t\t\t`EIP-3009 ${role} signature must come from \\`${role === \"cancel\" ? \"authorizer\" : \"from\"}\\`: account is ${account.address}, message says ${expectedFrom}.`,\n\t\t);\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Signers\n// ---------------------------------------------------------------------------\n\n/**\n * Signs an EIP-3009 `TransferWithAuthorization` message.\n *\n * The signing account MUST equal `message.from` — EIP-3009 rejects signatures\n * from anyone else (the on-chain check is pure `ecrecover` against `from`).\n *\n * @example\n * ```ts\n * import { privateKeyToAccount } from \"viem/accounts\";\n * import {\n * authorizationDeadlineFromNow,\n * generateAuthorizationNonce,\n * JPYC_EIP712_DOMAIN_HINT,\n * polygon,\n * signTransferWithAuthorization,\n * } from \"kawasekit\";\n *\n * const account = privateKeyToAccount(\"0x...\");\n * const signed = await signTransferWithAuthorization(account, {\n * ...JPYC_EIP712_DOMAIN_HINT,\n * chainId: polygon.id,\n * verifyingContract: \"0xE7C3D8C9a439feDe00D2600032D5dB0Be71C3c29\",\n * }, {\n * from: account.address,\n * to: \"0xBeef...\",\n * value: 100n * 10n ** 18n,\n * validAfter: 0n,\n * validBefore: authorizationDeadlineFromNow(300),\n * nonce: generateAuthorizationNonce(),\n * });\n * // → submit (v, r, s) to token.transferWithAuthorization(...)\n * ```\n */\nexport async function signTransferWithAuthorization(\n\taccount: Account,\n\tdomain: Eip3009Domain,\n\tmessage: TransferWithAuthorizationMessage,\n): Promise<SignedAuthorization<TransferWithAuthorizationMessage>> {\n\tassertSignerMatches(account, message.from, \"transfer\");\n\tconst sign = requireSignTypedData(account);\n\tconst signature = await sign({\n\t\tdomain,\n\t\ttypes: transferWithAuthorizationTypes,\n\t\tprimaryType: \"TransferWithAuthorization\",\n\t\tmessage,\n\t});\n\treturn splitAuthorization(signature, domain, message);\n}\n\n/**\n * Signs an EIP-3009 `ReceiveWithAuthorization` message.\n *\n * Differs from {@link signTransferWithAuthorization} in two ways:\n * 1. Uses the `ReceiveWithAuthorization` EIP-712 type.\n * 2. The contract additionally enforces `msg.sender == to` at submission\n * time, so only `to` (or a relayer impersonating `to` — impossible in\n * practice) can land the tx.\n */\nexport async function signReceiveWithAuthorization(\n\taccount: Account,\n\tdomain: Eip3009Domain,\n\tmessage: ReceiveWithAuthorizationMessage,\n): Promise<SignedAuthorization<ReceiveWithAuthorizationMessage>> {\n\tassertSignerMatches(account, message.from, \"receive\");\n\tconst sign = requireSignTypedData(account);\n\tconst signature = await sign({\n\t\tdomain,\n\t\ttypes: receiveWithAuthorizationTypes,\n\t\tprimaryType: \"ReceiveWithAuthorization\",\n\t\tmessage,\n\t});\n\treturn splitAuthorization(signature, domain, message);\n}\n\n/**\n * Signs an EIP-3009 `CancelAuthorization` message.\n *\n * Cancelling consumes the nonce so a later `transferWithAuthorization` or\n * `receiveWithAuthorization` with the same nonce will revert.\n */\nexport async function signCancelAuthorization(\n\taccount: Account,\n\tdomain: Eip3009Domain,\n\tmessage: CancelAuthorizationMessage,\n): Promise<SignedAuthorization<CancelAuthorizationMessage>> {\n\tassertSignerMatches(account, message.authorizer, \"cancel\");\n\tconst sign = requireSignTypedData(account);\n\tconst signature = await sign({\n\t\tdomain,\n\t\ttypes: cancelAuthorizationTypes,\n\t\tprimaryType: \"CancelAuthorization\",\n\t\tmessage,\n\t});\n\treturn splitAuthorization(signature, domain, message);\n}\n\nfunction splitAuthorization<TMessage>(\n\tsignature: Hex,\n\tdomain: Eip3009Domain,\n\tmessage: TMessage,\n): SignedAuthorization<TMessage> {\n\tconst parsed = parseSignature(signature);\n\t// viem's parseSignature returns yParity ∈ {0, 1} as well as v when present.\n\tconst v = parsed.v !== undefined ? Number(parsed.v) : (parsed.yParity ?? 0) + 27;\n\treturn {\n\t\tsignature,\n\t\tv,\n\t\tr: parsed.r,\n\t\ts: parsed.s,\n\t\tdomain,\n\t\tmessage,\n\t};\n}\n","/**\n * Known-asset registry for {@link createX402PaymentSigner}'s\n * `asset: { kind: \"known\", id }` discriminated-union branch.\n *\n * kawasekit only ships pinned EIP-712 domain definitions for assets it has\n * verified empirically against the deployed contracts. Adding a new entry\n * here requires citing the source-file + line reference for the contract\n * that owns the `name` / `version` (so the next reviewer can spot-check the\n * claim, the same discipline `docs/THREAT_MODEL.md` §0 demands of any ✅\n * verdict that delegates to an out-of-scope component).\n *\n * @packageDocumentation\n */\n\nimport type { Address } from \"viem\";\nimport { getAddress } from \"viem\";\nimport { JPYC_EIP712_DOMAIN_HINT, JPYC_V2_ADDRESS } from \"./jpyc\";\n\n/** Known asset identifiers. New entries must update this union AND the table. */\nexport type KnownAssetId = \"jpyc-v2\";\n\n/** Fully-pinned EIP-712 domain for a known asset. */\nexport interface KnownAssetDomain {\n\treadonly id: KnownAssetId;\n\treadonly name: string;\n\treadonly version: string;\n\treadonly verifyingContract: Address;\n}\n\n/**\n * Canonical table. Lookups go through {@link getKnownAssetDomain}, which\n * returns a frozen copy so callers cannot mutate the registry.\n *\n * `verifyingContract` is the multi-chain canonical address — JPYC v2 is the\n * same address on Ethereum / Polygon (mainnet + Amoy) / Avalanche. The\n * signer cross-checks `requirements.asset` against this value at sign time,\n * so a server advertising a different `asset` is rejected before any\n * signature is produced.\n *\n * JPYC v2 domain: `name = \"JPY Coin\"`, `version = \"1\"`. Source of truth is\n * the deployed contract's `eip712Domain()` view — verified empirically and\n * also cached in `src/tokens/jpyc.ts:JPYC_EIP712_DOMAIN_HINT`.\n */\nconst KNOWN_ASSETS: ReadonlyArray<KnownAssetDomain> = [\n\t{\n\t\tid: \"jpyc-v2\",\n\t\tname: JPYC_EIP712_DOMAIN_HINT.name,\n\t\tversion: JPYC_EIP712_DOMAIN_HINT.version,\n\t\tverifyingContract: getAddress(JPYC_V2_ADDRESS),\n\t},\n];\n\n/**\n * Look up a known asset's pinned EIP-712 domain by id.\n *\n * @returns The domain, or `undefined` if the id is not in the registry.\n *\n * @example\n * ```ts\n * import { getKnownAssetDomain } from \"kawasekit\";\n *\n * const jpyc = getKnownAssetDomain(\"jpyc-v2\");\n * if (jpyc === undefined) throw new Error(\"unreachable\");\n * console.log(jpyc.verifyingContract); // 0xE7C3D8C9a439feDe00D2600032D5dB0Be71C3c29\n * ```\n */\nexport function getKnownAssetDomain(id: KnownAssetId): KnownAssetDomain | undefined {\n\treturn KNOWN_ASSETS.find((entry) => entry.id === id);\n}\n\n/** List every known asset id (for diagnostics / error messages). */\nexport function listKnownAssetIds(): readonly KnownAssetId[] {\n\treturn KNOWN_ASSETS.map((entry) => entry.id);\n}\n","/**\n * x402 v2 client-side signer.\n *\n * Given a server-issued {@link X402PaymentRequirements}, produce a\n * {@link X402PaymentPayload} the client can send back in the next request. This\n * is the first runtime consumer of the M2 EIP-3009 helpers\n * ({@link signTransferWithAuthorization}, {@link authorizationDeadlineFromNow},\n * {@link generateAuthorizationNonce}).\n *\n * Scope:\n * - **exact-EVM scheme only.** Permit2 / ERC-7710 are M4+.\n * - **EOA payer only.** EIP-3009 uses pure `ecrecover` (no ERC-1271 fallback)\n * so smart accounts cannot be `from`. The agent-account flow is\n * {@link transferJpyc} (UserOp), not x402.\n *\n * @packageDocumentation\n */\n\nimport type { Account, Address } from \"viem\";\nimport { getAddress, isAddress } from \"viem\";\nimport { getChain, isSupportedChainId } from \"../chains\";\nimport {\n\tauthorizationDeadlineFromNow,\n\tderiveAuthorizationNonce,\n\tgenerateAuthorizationNonce,\n\tsignTransferWithAuthorization,\n} from \"../tokens/eip3009\";\nimport {\n\tgetKnownAssetDomain,\n\ttype KnownAssetDomain,\n\ttype KnownAssetId,\n\tlistKnownAssetIds,\n} from \"../tokens/known-assets\";\nimport { X402InvalidConfigError, X402InvalidPayloadError } from \"./errors\";\nimport type {\n\tX402ExactEvmPayload,\n\tX402PaymentPayload,\n\tX402PaymentRequirements,\n\tX402ResourceInfo,\n} from \"./types\";\nimport { X402_VERSION, x402NetworkToChainId } from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Defaults\n// ---------------------------------------------------------------------------\n\n/**\n * Default authorization lifetime (`validBefore = now + this`) when the caller\n * does not pass an override. Capped per-sign by `paymentRequirements.maxTimeoutSeconds`.\n *\n * 300 s matches the M3 example app's tolerance for Polygon Amoy bundler\n * inclusion latency (see plan risk #6).\n */\nexport const X402_DEFAULT_AUTHORIZATION_LIFETIME_SECONDS = 300;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** EIP-712 token domain `name` / `version` pair. */\nexport interface X402TokenDomain {\n\treadonly name: string;\n\treadonly version: string;\n}\n\n/**\n * Asset binding for {@link createX402PaymentSigner}. Required, discriminated.\n *\n * **Default-on whitelist**: integrators MUST declare which asset they intend\n * to sign for. The `known` branch references a kawasekit-maintained\n * whitelist (see `src/tokens/known-assets.ts`); the `unsafeOverride` branch\n * is the deliberate escape hatch for any other asset and is named loudly so\n * it survives a code review. Either way, the signer pins the EIP-712 domain\n * at construction time and refuses to sign if `paymentRequirements.asset`\n * disagrees with the pinned `verifyingContract`.\n *\n * Closes Threat 1.4 (misadvertised EIP-712 domain): the server's advertised\n * `extra.name` / `extra.version` and `asset` are all ignored for signing\n * purposes — the signer trusts only what the integrator declared here.\n */\nexport type X402AssetParam =\n\t| {\n\t\t\t/** Use a kawasekit-maintained pinned EIP-712 domain. */\n\t\t\treadonly kind: \"known\";\n\t\t\t/** The asset id to pin. See {@link KnownAssetId} for the registry. */\n\t\t\treadonly id: KnownAssetId;\n\t }\n\t| {\n\t\t\t/**\n\t\t\t * Use a caller-supplied EIP-712 domain for an asset NOT on the\n\t\t\t * kawasekit whitelist. The name is deliberately loud — pick this\n\t\t\t * branch only when you have separately audited the contract and its\n\t\t\t * `eip712Domain()` output.\n\t\t\t */\n\t\t\treadonly kind: \"unsafeOverride\";\n\t\t\treadonly domain: {\n\t\t\t\treadonly name: string;\n\t\t\t\treadonly version: string;\n\t\t\t\treadonly verifyingContract: Address;\n\t\t\t};\n\t };\n\n/** Parameters for {@link createX402PaymentSigner}. */\nexport interface CreateX402PaymentSignerParams {\n\t/**\n\t * Declared production-vs-test intent. Each `sign()` call verifies that\n\t * `paymentRequirements.network` resolves to a chain whose `isTestnet`\n\t * agrees with this value, and throws otherwise. The point is to refuse\n\t * to sign a real-funds payment when the signer was configured for testnet\n\t * (e.g. the server unexpectedly demanded `polygon-mainnet` instead of\n\t * `polygon-amoy`).\n\t */\n\treadonly network: \"mainnet\" | \"testnet\";\n\t/**\n\t * EOA / LocalAccount that signs the EIP-3009 `TransferWithAuthorization`.\n\t * MUST be the same address the requirements' `from` will name.\n\t */\n\treadonly account: Account;\n\t/**\n\t * Asset binding (required). Pins the EIP-712 domain at construction time\n\t * and cross-checks `paymentRequirements.asset` at every sign call.\n\t * See {@link X402AssetParam} for the discriminated-union shape.\n\t *\n\t * **Threat 1.4 mitigation**: the wire-format `extra.name` and\n\t * `extra.version` are NOT consulted; a malicious server cannot coerce a\n\t * mismatched signature through them.\n\t */\n\treadonly asset: X402AssetParam;\n\t/**\n\t * Default authorization lifetime in seconds. Bounded by each\n\t * requirement's `maxTimeoutSeconds` at sign time.\n\t * Defaults to {@link X402_DEFAULT_AUTHORIZATION_LIFETIME_SECONDS}.\n\t */\n\treadonly defaultLifetimeSeconds?: number;\n\t/**\n\t * Optional per-signature value ceiling, in the asset's smallest unit\n\t * (`bigint`). When set, `sign()` throws {@link X402InvalidPayloadError} if a\n\t * server advertises `requirements.amount` greater than this — refusing to\n\t * sign an over-budget payment at the primitive.\n\t *\n\t * **Threat 1.14 mitigation.** {@link createX402PaymentSigner} is a public API\n\t * and the direct-signer path bypasses the `wrapFetch` `onPayment` guard; the\n\t * EOA-payer x402 flow is also not bounded by the Layer-4 session-key daily\n\t * limit. This pins the *amount* ceiling the way {@link X402AssetParam} pins\n\t * the *asset* (1.4) — production posture is to set it. Omit it for no ceiling\n\t * (backward-compatible default; the payer EOA balance is the only bound).\n\t */\n\treadonly maxAmountPerSign?: bigint;\n}\n\n/** Parameters for {@link X402PaymentSigner.sign}. */\nexport interface SignX402PaymentParams {\n\t/** The chosen entry from the server's `accepts` array. */\n\treadonly paymentRequirements: X402PaymentRequirements;\n\t/** Optional {@link X402ResourceInfo} to echo back in the payload. */\n\treadonly resource?: X402ResourceInfo;\n\t/** Unix-seconds override of `validAfter`. Defaults to `0n`. */\n\treadonly validAfter?: bigint;\n\t/**\n\t * Unix-seconds override of `validBefore`. Defaults to `now + lifetime`\n\t * where lifetime = `min(signer default, requirements.maxTimeoutSeconds)`.\n\t */\n\treadonly validBefore?: bigint;\n\t/**\n\t * Optional reasoning-step idempotency key (M5-1, Half B). When supplied, the\n\t * EIP-3009 nonce is **derived deterministically** from it (instead of random)\n\t * so a re-signed same-intent payment produces the same on-chain nonce — the\n\t * token contract's `authorizationState` then rejects the duplicate\n\t * settlement. For a byte-identical re-sign, also pin `validBefore`. Build the\n\t * key with `createIdempotencyKeyBuilder` from `kawasekit/idempotency`.\n\t */\n\treadonly idempotencyKey?: string;\n}\n\n/** Signer returned by {@link createX402PaymentSigner}. */\nexport interface X402PaymentSigner {\n\t/** Address of the EOA bound to this signer. */\n\treadonly address: Address;\n\t/** Sign a payment for one {@link X402PaymentRequirements}. */\n\tsign(params: SignX402PaymentParams): Promise<X402PaymentPayload>;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nconst UINT256_MAX = (1n << 256n) - 1n;\nconst UINT256_DECIMAL = /^(0|[1-9][0-9]*)$/;\n\nfunction parseUintString(value: string, field: string): bigint {\n\tif (!UINT256_DECIMAL.test(value)) {\n\t\tthrow new X402InvalidPayloadError(\n\t\t\t\"PaymentRequirements\",\n\t\t\t`\\`${field}\\` must be a non-negative decimal string, got ${JSON.stringify(value)}`,\n\t\t);\n\t}\n\tconst parsed = BigInt(value);\n\tif (parsed > UINT256_MAX) {\n\t\tthrow new X402InvalidPayloadError(\n\t\t\t\"PaymentRequirements\",\n\t\t\t`\\`${field}\\` exceeds uint256, got ${value}`,\n\t\t);\n\t}\n\treturn parsed;\n}\n\nfunction assertAddress(value: string, field: string): Address {\n\tif (!isAddress(value, { strict: false })) {\n\t\tthrow new X402InvalidPayloadError(\n\t\t\t\"PaymentRequirements\",\n\t\t\t`\\`${field}\\` is not a valid address: ${value}`,\n\t\t);\n\t}\n\treturn value as Address;\n}\n\n/** Construction-time resolution of an {@link X402AssetParam} to a pinned domain. */\ninterface ResolvedAsset {\n\treadonly name: string;\n\treadonly version: string;\n\treadonly verifyingContract: Address;\n}\n\nfunction resolveAssetParam(asset: X402AssetParam): ResolvedAsset {\n\tif (asset.kind === \"known\") {\n\t\tconst entry: KnownAssetDomain | undefined = getKnownAssetDomain(asset.id);\n\t\tif (entry === undefined) {\n\t\t\tthrow new X402InvalidConfigError(\n\t\t\t\t\"asset.id\",\n\t\t\t\t`unknown asset id ${JSON.stringify(asset.id)}. Supported: ${listKnownAssetIds()\n\t\t\t\t\t.map((id) => JSON.stringify(id))\n\t\t\t\t\t.join(\", \")}.`,\n\t\t\t);\n\t\t}\n\t\treturn {\n\t\t\tname: entry.name,\n\t\t\tversion: entry.version,\n\t\t\tverifyingContract: entry.verifyingContract,\n\t\t};\n\t}\n\tif (asset.kind === \"unsafeOverride\") {\n\t\tconst { domain } = asset;\n\t\tif (typeof domain.name !== \"string\" || domain.name === \"\") {\n\t\t\tthrow new X402InvalidConfigError(\n\t\t\t\t\"asset.domain.name\",\n\t\t\t\t\"`unsafeOverride.domain.name` must be a non-empty string\",\n\t\t\t);\n\t\t}\n\t\tif (typeof domain.version !== \"string\" || domain.version === \"\") {\n\t\t\tthrow new X402InvalidConfigError(\n\t\t\t\t\"asset.domain.version\",\n\t\t\t\t\"`unsafeOverride.domain.version` must be a non-empty string\",\n\t\t\t);\n\t\t}\n\t\tif (!isAddress(domain.verifyingContract, { strict: false })) {\n\t\t\tthrow new X402InvalidConfigError(\n\t\t\t\t\"asset.domain.verifyingContract\",\n\t\t\t\t`\\`unsafeOverride.domain.verifyingContract\\` must be a valid address, got ${JSON.stringify(domain.verifyingContract)}`,\n\t\t\t);\n\t\t}\n\t\treturn {\n\t\t\tname: domain.name,\n\t\t\tversion: domain.version,\n\t\t\tverifyingContract: getAddress(domain.verifyingContract),\n\t\t};\n\t}\n\t// Defensive: TS exhaustiveness guarantees this is unreachable at compile\n\t// time, but a JS consumer could smuggle through an unknown kind.\n\tconst exhaustive = asset as { kind: string };\n\tthrow new X402InvalidConfigError(\n\t\t\"asset.kind\",\n\t\t`unsupported kind ${JSON.stringify(exhaustive.kind)}. Expected \"known\" or \"unsafeOverride\".`,\n\t);\n}\n\nfunction validateRequirements(requirements: X402PaymentRequirements): {\n\treadonly chainId: number;\n\treadonly value: bigint;\n\treadonly asset: Address;\n\treadonly payTo: Address;\n} {\n\tif (requirements.scheme !== \"exact\") {\n\t\tthrow new X402InvalidPayloadError(\n\t\t\t\"PaymentRequirements\",\n\t\t\t`unsupported scheme: ${requirements.scheme}`,\n\t\t);\n\t}\n\tconst chainId = x402NetworkToChainId(requirements.network);\n\tif (!isSupportedChainId(chainId)) {\n\t\t// Defensive: an inbound payload typed as X402PaymentRequirements that\n\t\t// nonetheless smuggled an unsupported chainId via type-cast.\n\t\tthrow new X402InvalidPayloadError(\n\t\t\t\"PaymentRequirements\",\n\t\t\t`unsupported network: ${requirements.network}`,\n\t\t);\n\t}\n\tconst value = parseUintString(requirements.amount, \"amount\");\n\tif (value === 0n) {\n\t\tthrow new X402InvalidPayloadError(\"PaymentRequirements\", \"`amount` must be positive\");\n\t}\n\tif (requirements.maxTimeoutSeconds <= 0) {\n\t\tthrow new X402InvalidPayloadError(\n\t\t\t\"PaymentRequirements\",\n\t\t\t`\\`maxTimeoutSeconds\\` must be positive, got ${requirements.maxTimeoutSeconds}`,\n\t\t);\n\t}\n\tconst asset = assertAddress(requirements.asset, \"asset\");\n\tconst payTo = assertAddress(requirements.payTo, \"payTo\");\n\treturn { chainId, value, asset, payTo };\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Build an {@link X402PaymentSigner} bound to a single signing account.\n *\n * The returned signer can produce many {@link X402PaymentPayload}s in\n * succession — one per accepted requirement. Each call generates a fresh\n * EIP-3009 nonce.\n *\n * @example\n * ```ts\n * import { privateKeyToAccount } from \"viem/accounts\";\n * import { createX402PaymentSigner } from \"kawasekit\";\n *\n * const account = privateKeyToAccount(\"0x...\");\n * const signer = createX402PaymentSigner({\n * network: \"testnet\",\n * account,\n * asset: { kind: \"known\", id: \"jpyc-v2\" },\n * });\n *\n * // ...after receiving a 402 with PAYMENT-REQUIRED header...\n * const paymentPayload = await signer.sign({ paymentRequirements });\n * ```\n */\nexport function createX402PaymentSigner(params: CreateX402PaymentSignerParams): X402PaymentSigner {\n\tconst { account, network } = params;\n\tconst defaultLifetimeSeconds =\n\t\tparams.defaultLifetimeSeconds ?? X402_DEFAULT_AUTHORIZATION_LIFETIME_SECONDS;\n\tif (defaultLifetimeSeconds <= 0) {\n\t\tthrow new X402InvalidPayloadError(\n\t\t\t\"X402PaymentSignerConfig\",\n\t\t\t`\\`defaultLifetimeSeconds\\` must be positive, got ${defaultLifetimeSeconds}`,\n\t\t);\n\t}\n\tconst maxAmountPerSign = params.maxAmountPerSign;\n\tif (maxAmountPerSign !== undefined && maxAmountPerSign <= 0n) {\n\t\tthrow new X402InvalidPayloadError(\n\t\t\t\"X402PaymentSignerConfig\",\n\t\t\t`\\`maxAmountPerSign\\` must be a positive bigint, got ${maxAmountPerSign}`,\n\t\t);\n\t}\n\tconst pinnedDomain = resolveAssetParam(params.asset);\n\n\treturn {\n\t\taddress: account.address,\n\t\tasync sign(signParams) {\n\t\t\tconst { paymentRequirements } = signParams;\n\t\t\tconst { chainId, value, asset, payTo } = validateRequirements(paymentRequirements);\n\t\t\tconst chain = getChain(chainId);\n\t\t\tif (network === \"mainnet\" && chain.isTestnet) {\n\t\t\t\tthrow new X402InvalidPayloadError(\n\t\t\t\t\t\"PaymentRequirements\",\n\t\t\t\t\t`signer was configured for network=\"mainnet\" but requirements.network=\"${paymentRequirements.network}\" (chainId ${chainId}) is a testnet`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (network === \"testnet\" && !chain.isTestnet) {\n\t\t\t\tthrow new X402InvalidPayloadError(\n\t\t\t\t\t\"PaymentRequirements\",\n\t\t\t\t\t`signer was configured for network=\"testnet\" but requirements.network=\"${paymentRequirements.network}\" (chainId ${chainId}) is a mainnet — refusing to sign payment for real funds`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (getAddress(asset) !== pinnedDomain.verifyingContract) {\n\t\t\t\tthrow new X402InvalidPayloadError(\n\t\t\t\t\t\"PaymentRequirements\",\n\t\t\t\t\t`requirements.asset (${getAddress(asset)}) does not match the signer's pinned verifyingContract (${pinnedDomain.verifyingContract}) — refusing to sign for an asset the signer was not configured to handle`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (maxAmountPerSign !== undefined && value > maxAmountPerSign) {\n\t\t\t\tthrow new X402InvalidPayloadError(\n\t\t\t\t\t\"PaymentRequirements\",\n\t\t\t\t\t`requirements.amount (${value}) exceeds the signer's \\`maxAmountPerSign\\` ceiling (${maxAmountPerSign}) — refusing to sign a payment above the configured per-signature limit (threat 1.14)`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst lifetime = Math.min(defaultLifetimeSeconds, paymentRequirements.maxTimeoutSeconds);\n\t\t\tconst validAfter = signParams.validAfter ?? 0n;\n\t\t\tconst validBefore = signParams.validBefore ?? authorizationDeadlineFromNow(lifetime);\n\t\t\tif (validBefore <= validAfter) {\n\t\t\t\tthrow new X402InvalidPayloadError(\n\t\t\t\t\t\"PaymentRequirements\",\n\t\t\t\t\t`\\`validBefore\\` (${validBefore}) must be greater than \\`validAfter\\` (${validAfter})`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst nonce =\n\t\t\t\tsignParams.idempotencyKey !== undefined\n\t\t\t\t\t? deriveAuthorizationNonce(\n\t\t\t\t\t\t\t{ idempotencyKey: signParams.idempotencyKey },\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tfrom: account.address,\n\t\t\t\t\t\t\t\tverifyingContract: pinnedDomain.verifyingContract,\n\t\t\t\t\t\t\t\tchainId,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t)\n\t\t\t\t\t: generateAuthorizationNonce();\n\t\t\tconst signed = await signTransferWithAuthorization(\n\t\t\t\taccount,\n\t\t\t\t{\n\t\t\t\t\tname: pinnedDomain.name,\n\t\t\t\t\tversion: pinnedDomain.version,\n\t\t\t\t\tchainId,\n\t\t\t\t\tverifyingContract: pinnedDomain.verifyingContract,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tfrom: account.address,\n\t\t\t\t\tto: payTo,\n\t\t\t\t\tvalue,\n\t\t\t\t\tvalidAfter,\n\t\t\t\t\tvalidBefore,\n\t\t\t\t\tnonce,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tconst payload: X402ExactEvmPayload = {\n\t\t\t\tsignature: signed.signature,\n\t\t\t\tauthorization: {\n\t\t\t\t\tfrom: signed.message.from,\n\t\t\t\t\tto: signed.message.to,\n\t\t\t\t\tvalue: signed.message.value.toString(),\n\t\t\t\t\tvalidAfter: signed.message.validAfter.toString(),\n\t\t\t\t\tvalidBefore: signed.message.validBefore.toString(),\n\t\t\t\t\tnonce: signed.message.nonce,\n\t\t\t\t},\n\t\t\t};\n\n\t\t\tconst result: X402PaymentPayload = signParams.resource\n\t\t\t\t? {\n\t\t\t\t\t\tx402Version: X402_VERSION,\n\t\t\t\t\t\tresource: signParams.resource,\n\t\t\t\t\t\taccepted: paymentRequirements,\n\t\t\t\t\t\tpayload: { ...payload },\n\t\t\t\t\t}\n\t\t\t\t: {\n\t\t\t\t\t\tx402Version: X402_VERSION,\n\t\t\t\t\t\taccepted: paymentRequirements,\n\t\t\t\t\t\tpayload: { ...payload },\n\t\t\t\t\t};\n\t\t\treturn result;\n\t\t},\n\t};\n}\n","/**\n * Facilitator implementations: local viem-backed (`createSelfFacilitator`) and\n * HTTP-proxied (`createHttpFacilitator`).\n *\n * Both expose the same {@link Facilitator} interface — `verify` / `settle` /\n * `supported` — so {@link createX402Handler} can swap one for the other based\n * on environment (testnet vs. mainnet, self-hosted vs. Coinbase CDP).\n *\n * Spec references:\n * - Error codes: x402 v2 spec §9 (Error Handling)\n * - Verification steps: scheme_exact_evm.md §1 Phase 2\n * - Facilitator HTTP API: x402 v2 spec §7\n *\n * @packageDocumentation\n */\n\nimport type { Account, Address, Chain, Hex, PublicClient, Transport, WalletClient } from \"viem\";\nimport { getAddress, parseSignature, recoverTypedDataAddress } from \"viem\";\nimport { getChain, isSupportedChainId, type SupportedChainId } from \"../chains\";\nimport {\n\tinvokeHookSafely,\n\ttype ObservabilityHooks,\n\ttype SettleEvent,\n\ttype VerifyEvent,\n} from \"../observability/hooks\";\nimport { JPYC_EIP712_DOMAIN_HINT, JPYC_V2_ADDRESS, jpycAbi } from \"../tokens/jpyc\";\nimport type {\n\tFacilitator,\n\tX402PaymentRequirements,\n\tX402SettleRequest,\n\tX402SettleResponse,\n\tX402SupportedKind,\n\tX402SupportedResponse,\n\tX402VerifyRequest,\n\tX402VerifyResponse,\n} from \"./types\";\nimport { chainIdToX402Network, X402_VERSION, x402NetworkToChainId } from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Error code vocabulary (x402 v2 §9)\n// ---------------------------------------------------------------------------\n\n/**\n * Standard x402 v2 error codes used as `invalidReason` (verify) and\n * `errorReason` (settle). Kept as string literals so that consumers can\n * `switch` on the union; values match the spec verbatim.\n */\nexport const X402_FACILITATOR_ERROR_CODES = {\n\tinsufficient_funds: \"insufficient_funds\",\n\tinvalid_exact_evm_payload_authorization_valid_after:\n\t\t\"invalid_exact_evm_payload_authorization_valid_after\",\n\tinvalid_exact_evm_payload_authorization_valid_before:\n\t\t\"invalid_exact_evm_payload_authorization_valid_before\",\n\tinvalid_exact_evm_payload_authorization_value_mismatch:\n\t\t\"invalid_exact_evm_payload_authorization_value_mismatch\",\n\tinvalid_exact_evm_payload_recipient_mismatch: \"invalid_exact_evm_payload_recipient_mismatch\",\n\tinvalid_exact_evm_payload_signature: \"invalid_exact_evm_payload_signature\",\n\tinvalid_network: \"invalid_network\",\n\tinvalid_payload: \"invalid_payload\",\n\tinvalid_scheme: \"invalid_scheme\",\n\tinvalid_transaction_state: \"invalid_transaction_state\",\n\tunexpected_settle_error: \"unexpected_settle_error\",\n\tunexpected_verify_error: \"unexpected_verify_error\",\n} as const;\n\ntype X402FacilitatorErrorCode =\n\t(typeof X402_FACILITATOR_ERROR_CODES)[keyof typeof X402_FACILITATOR_ERROR_CODES];\n\n// ---------------------------------------------------------------------------\n// Shared helpers\n// ---------------------------------------------------------------------------\n\ninterface NarrowExactEvmPayload {\n\treadonly signature: Hex;\n\treadonly authorization: {\n\t\treadonly from: Address;\n\t\treadonly to: Address;\n\t\treadonly value: string;\n\t\treadonly validAfter: string;\n\t\treadonly validBefore: string;\n\t\treadonly nonce: Hex;\n\t};\n}\n\nfunction isHex(value: unknown): value is Hex {\n\treturn typeof value === \"string\" && /^0x[0-9a-fA-F]*$/.test(value);\n}\n\nfunction isAddressLike(value: unknown): value is Address {\n\treturn typeof value === \"string\" && /^0x[0-9a-fA-F]{40}$/.test(value);\n}\n\nfunction isDecimalString(value: unknown): value is string {\n\treturn typeof value === \"string\" && /^(0|[1-9][0-9]*)$/.test(value);\n}\n\nfunction narrowExactEvmPayload(payload: Record<string, unknown>): NarrowExactEvmPayload | null {\n\tconst p = payload as { signature?: unknown; authorization?: unknown };\n\tif (!isHex(p.signature)) return null;\n\tif (typeof p.authorization !== \"object\" || p.authorization === null) return null;\n\tconst a = p.authorization as {\n\t\tfrom?: unknown;\n\t\tto?: unknown;\n\t\tvalue?: unknown;\n\t\tvalidAfter?: unknown;\n\t\tvalidBefore?: unknown;\n\t\tnonce?: unknown;\n\t};\n\tif (!isAddressLike(a.from)) return null;\n\tif (!isAddressLike(a.to)) return null;\n\tif (!isDecimalString(a.value)) return null;\n\tif (!isDecimalString(a.validAfter)) return null;\n\tif (!isDecimalString(a.validBefore)) return null;\n\tif (!isHex(a.nonce)) return null;\n\treturn {\n\t\tsignature: p.signature,\n\t\tauthorization: {\n\t\t\tfrom: a.from,\n\t\t\tto: a.to,\n\t\t\tvalue: a.value,\n\t\t\tvalidAfter: a.validAfter,\n\t\t\tvalidBefore: a.validBefore,\n\t\t\tnonce: a.nonce,\n\t\t},\n\t};\n}\n\nconst TRANSFER_AUTHORIZATION_TYPES = {\n\tTransferWithAuthorization: [\n\t\t{ name: \"from\", type: \"address\" },\n\t\t{ name: \"to\", type: \"address\" },\n\t\t{ name: \"value\", type: \"uint256\" },\n\t\t{ name: \"validAfter\", type: \"uint256\" },\n\t\t{ name: \"validBefore\", type: \"uint256\" },\n\t\t{ name: \"nonce\", type: \"bytes32\" },\n\t],\n} as const;\n\nfunction resolveDomain(requirements: X402PaymentRequirements): {\n\treadonly name: string;\n\treadonly version: string;\n} {\n\tconst extra = requirements.extra as { name?: unknown; version?: unknown };\n\tif (typeof extra.name === \"string\" && typeof extra.version === \"string\") {\n\t\treturn { name: extra.name, version: extra.version };\n\t}\n\tif (getAddress(requirements.asset) === getAddress(JPYC_V2_ADDRESS)) {\n\t\treturn JPYC_EIP712_DOMAIN_HINT;\n\t}\n\tthrow new Error(\n\t\t\"resolveDomain: `extra.name` and `extra.version` are required for non-JPYC assets\",\n\t);\n}\n\nfunction failVerify(\n\treason: X402FacilitatorErrorCode,\n\tmessage?: string,\n\tpayer?: Address,\n): X402VerifyResponse {\n\tif (message !== undefined && payer !== undefined) {\n\t\treturn { isValid: false, invalidReason: reason, invalidMessage: message, payer };\n\t}\n\tif (message !== undefined) {\n\t\treturn { isValid: false, invalidReason: reason, invalidMessage: message };\n\t}\n\tif (payer !== undefined) {\n\t\treturn { isValid: false, invalidReason: reason, payer };\n\t}\n\treturn { isValid: false, invalidReason: reason };\n}\n\nfunction failSettle(\n\tnetwork: X402SettleResponse[\"network\"],\n\treason: X402FacilitatorErrorCode,\n\toptions: { message?: string; payer?: Address; transaction?: string } = {},\n): X402SettleResponse {\n\tconst transaction = options.transaction ?? \"\";\n\tconst base: X402SettleResponse = {\n\t\tsuccess: false,\n\t\terrorReason: reason,\n\t\ttransaction,\n\t\tnetwork,\n\t};\n\tif (options.message !== undefined && options.payer !== undefined) {\n\t\treturn { ...base, errorMessage: options.message, payer: options.payer };\n\t}\n\tif (options.message !== undefined) {\n\t\treturn { ...base, errorMessage: options.message };\n\t}\n\tif (options.payer !== undefined) {\n\t\treturn { ...base, payer: options.payer };\n\t}\n\treturn base;\n}\n\n// ---------------------------------------------------------------------------\n// Self-facilitator (local viem-backed)\n// ---------------------------------------------------------------------------\n\n/** Parameters for {@link createSelfFacilitator}. */\nexport interface CreateSelfFacilitatorParams {\n\t/**\n\t * Declared production-vs-test intent. MUST agree with `walletClient.chain`:\n\t * - `\"mainnet\"` requires a kawasekit chain with `isTestnet === false`.\n\t * - `\"testnet\"` requires a kawasekit chain with `isTestnet === true`.\n\t *\n\t * The check is enforced at construction time and throws a fatal error on\n\t * disagreement. The point is to make accidentally pointing a testnet\n\t * configuration at a mainnet RPC (or vice versa) impossible — that mistake\n\t * would broadcast real-fund transactions silently.\n\t */\n\treadonly network: \"mainnet\" | \"testnet\";\n\t/**\n\t * Pre-configured wallet client that broadcasts settlement transactions.\n\t * The bound account pays gas. `walletClient.chain.id` determines the only\n\t * chain this facilitator serves, and `walletClient.chain.isTestnet` MUST\n\t * agree with the declared {@link network}.\n\t */\n\treadonly walletClient: WalletClient<Transport, Chain, Account>;\n\t/**\n\t * Pre-configured public client on the same chain as `walletClient`. Used\n\t * for balance and authorization-state reads during verify.\n\t */\n\treadonly publicClient: PublicClient<Transport, Chain>;\n\t/**\n\t * Timeout (ms) for `waitForTransactionReceipt` during settle.\n\t * Defaults to 60_000.\n\t */\n\treadonly receiptTimeoutMs?: number;\n\t/**\n\t * Number of block confirmations to wait past the settle tx inclusion\n\t * before considering settlement final. Mitigates threat 2.8 (settle\n\t * tx reorg producing a \"content delivered, payment reverted\" state)\n\t * by raising the bar past Polygon PoS's typical reorg depth.\n\t *\n\t * Chain-aware defaults if omitted:\n\t * - testnet (Polygon Amoy): `1` — fast feedback for dev loops, no\n\t * real funds at risk\n\t * - mainnet (Polygon): `4` — roughly ~8 s of soft finality at\n\t * Polygon's ~2 s block time, suitable for the small-value paywall\n\t * hits kawasekit targets (sub-100 JPYC per call)\n\t *\n\t * For high-value merchants — or any deployment uncomfortable with\n\t * shallow reorg risk — raise this to 32+ and bump\n\t * {@link receiptTimeoutMs} so the timeout still accommodates the\n\t * wait. See `docs/THREAT_MODEL.md` §2.8 / §6.6.\n\t */\n\treadonly confirmations?: number;\n\t/**\n\t * Optional observability callbacks. Hooks are fire-and-forget — any throw\n\t * or rejection inside a hook is silently discarded and never propagates to\n\t * the verify / settle return path. See {@link ObservabilityHooks}.\n\t *\n\t * The facilitator emits `onVerify` after every `verify()` call (including\n\t * the internal re-verify that runs at the start of `settle()`) and\n\t * `onSettle` after every `settle()` call.\n\t */\n\treadonly hooks?: ObservabilityHooks;\n}\n\n/**\n * Builds a facilitator that verifies and broadcasts exact-EVM EIP-3009\n * payments using a locally-held EOA private key (gas payer).\n *\n * Intended for self-hosted paywalls and testnet (Polygon Amoy) where the\n * Coinbase CDP facilitator is not guaranteed to support the chain.\n *\n * **Concurrent settle() calls**: under any meaningful load (e.g. an LLM\n * agent fan-out) you will issue multiple `transferWithAuthorization`\n * broadcasts from the same facilitator EOA in parallel. Without local nonce\n * sequencing those broadcasts race for the same on-chain nonce and only\n * one lands. Pass viem's `nonceManager` when constructing the facilitator\n * account to make this safe — see `@example` below.\n *\n * @example\n * ```ts\n * import { createPublicClient, createWalletClient, http } from \"viem\";\n * import { nonceManager, privateKeyToAccount } from \"viem/accounts\";\n * import { createSelfFacilitator, polygonAmoy } from \"kawasekit\";\n *\n * // `nonceManager` is REQUIRED whenever you expect concurrent settlements.\n * const account = privateKeyToAccount(\n * process.env.FACILITATOR_PK as `0x${string}`,\n * { nonceManager },\n * );\n * const transport = http(process.env.RPC_URL);\n * const facilitator = createSelfFacilitator({\n * network: \"testnet\", // must agree with polygonAmoy.isTestnet === true\n * walletClient: createWalletClient({ chain: polygonAmoy, transport, account }),\n * publicClient: createPublicClient({ chain: polygonAmoy, transport }),\n * });\n * ```\n */\nexport function createSelfFacilitator(params: CreateSelfFacilitatorParams): Facilitator {\n\tconst { walletClient, publicClient } = params;\n\tconst receiptTimeoutMs = params.receiptTimeoutMs ?? 60_000;\n\t// Chain-aware confirmation depth (threat 2.8 / §6.6 mitigation). Defaults\n\t// kick in only when the operator did not pass an explicit value; the\n\t// network-vs-isTestnet check below has already locked down which side we\n\t// are on.\n\tconst defaultConfirmations = params.network === \"mainnet\" ? 4 : 1;\n\tconst confirmations = params.confirmations ?? defaultConfirmations;\n\tconst facilitatorChainId = walletClient.chain.id;\n\tif (!isSupportedChainId(facilitatorChainId)) {\n\t\tthrow new Error(\n\t\t\t`createSelfFacilitator: walletClient.chain.id ${facilitatorChainId} is not a kawasekit-supported chain`,\n\t\t);\n\t}\n\tconst supportedChainId: SupportedChainId = facilitatorChainId;\n\tconst chain = getChain(supportedChainId);\n\tif (params.network === \"mainnet\" && chain.isTestnet) {\n\t\tthrow new Error(\n\t\t\t`createSelfFacilitator: network=\"mainnet\" but walletClient.chain \"${chain.name}\" (chainId ${supportedChainId}) is a testnet`,\n\t\t);\n\t}\n\tif (params.network === \"testnet\" && !chain.isTestnet) {\n\t\tthrow new Error(\n\t\t\t`createSelfFacilitator: network=\"testnet\" but walletClient.chain \"${chain.name}\" (chainId ${supportedChainId}) is a mainnet — refusing to broadcast with real funds`,\n\t\t);\n\t}\n\n\t// Threat 2.2 (concurrent settle nonce race) enforcement. The facilitator\n\t// will broadcast `transferWithAuthorization` calls in parallel under any\n\t// fan-out workload (LLM agent tool calls are the canonical example).\n\t// Without viem's nonceManager attached, every parallel `writeContract`\n\t// reads the same on-chain nonce and only one tx lands — settlements\n\t// silently dropped. Enforcing this at construction time means the\n\t// failure mode shows up at boot, not at the first parallel hit in\n\t// production. See `docs/THREAT_MODEL.md#22-concurrent-settle-nonce-race`.\n\tif (walletClient.account.nonceManager === undefined) {\n\t\tthrow new Error(\n\t\t\t'createSelfFacilitator: walletClient.account must be constructed with viem\\'s `nonceManager` to serialise nonces under concurrent settle(). Example:\\n import { nonceManager, privateKeyToAccount } from \"viem/accounts\";\\n const account = privateKeyToAccount(pk, { nonceManager });\\n const walletClient = createWalletClient({ chain, transport, account });',\n\t\t);\n\t}\n\n\tconst network = chainIdToX402Network(supportedChainId);\n\tconst hooks = params.hooks;\n\n\tfunction buildVerifyEvent(\n\t\treq: X402VerifyRequest,\n\t\tresponse: X402VerifyResponse,\n\t\tstartedAtMs: number,\n\t): VerifyEvent {\n\t\tconst durationMs = Date.now() - startedAtMs;\n\t\tconst eventNetwork = req.paymentRequirements.network;\n\t\tif (response.isValid && response.payer !== undefined) {\n\t\t\treturn {\n\t\t\t\tkind: \"verify\",\n\t\t\t\tresult: \"success\",\n\t\t\t\tstartedAtMs,\n\t\t\t\tdurationMs,\n\t\t\t\tnetwork: eventNetwork,\n\t\t\t\tpayer: response.payer,\n\t\t\t\tamount: req.paymentRequirements.amount,\n\t\t\t};\n\t\t}\n\t\tif (response.isValid) {\n\t\t\t// verifyCore always sets payer on success, but the X402VerifyResponse\n\t\t\t// type permits it to be absent; downgrade to a synthetic failure\n\t\t\t// event so the discriminated union remains sound for adapters.\n\t\t\treturn {\n\t\t\t\tkind: \"verify\",\n\t\t\t\tresult: \"failure\",\n\t\t\t\tstartedAtMs,\n\t\t\t\tdurationMs,\n\t\t\t\tnetwork: eventNetwork,\n\t\t\t\tinvalidReason: \"unexpected_verify_error\",\n\t\t\t\tinvalidMessage: \"verify succeeded but payer was not surfaced\",\n\t\t\t};\n\t\t}\n\t\tconst base = {\n\t\t\tkind: \"verify\" as const,\n\t\t\tresult: \"failure\" as const,\n\t\t\tstartedAtMs,\n\t\t\tdurationMs,\n\t\t\tnetwork: eventNetwork,\n\t\t\tinvalidReason: response.invalidReason ?? \"unexpected_verify_error\",\n\t\t};\n\t\tif (response.payer !== undefined && response.invalidMessage !== undefined) {\n\t\t\treturn { ...base, payer: response.payer, invalidMessage: response.invalidMessage };\n\t\t}\n\t\tif (response.payer !== undefined) {\n\t\t\treturn { ...base, payer: response.payer };\n\t\t}\n\t\tif (response.invalidMessage !== undefined) {\n\t\t\treturn { ...base, invalidMessage: response.invalidMessage };\n\t\t}\n\t\treturn base;\n\t}\n\n\tfunction buildSettleEvent(\n\t\treq: X402SettleRequest,\n\t\tresponse: X402SettleResponse,\n\t\tstartedAtMs: number,\n\t): SettleEvent {\n\t\tconst durationMs = Date.now() - startedAtMs;\n\t\tconst eventNetwork = req.paymentRequirements.network;\n\t\tif (response.success && response.payer !== undefined) {\n\t\t\treturn {\n\t\t\t\tkind: \"settle\",\n\t\t\t\tresult: \"success\",\n\t\t\t\tstartedAtMs,\n\t\t\t\tdurationMs,\n\t\t\t\tnetwork: eventNetwork,\n\t\t\t\tpayer: response.payer,\n\t\t\t\tamount: req.paymentRequirements.amount,\n\t\t\t\ttransaction: response.transaction as Hex,\n\t\t\t};\n\t\t}\n\t\tif (response.success) {\n\t\t\t// settleCore always sets payer on success; the spec response type\n\t\t\t// permits it to be absent so we downgrade to a synthetic failure\n\t\t\t// rather than emit a malformed event.\n\t\t\treturn {\n\t\t\t\tkind: \"settle\",\n\t\t\t\tresult: \"failure\",\n\t\t\t\tstartedAtMs,\n\t\t\t\tdurationMs,\n\t\t\t\tnetwork: eventNetwork,\n\t\t\t\terrorReason: \"unexpected_settle_error\",\n\t\t\t\terrorMessage: \"settle succeeded but payer was not surfaced\",\n\t\t\t\ttransaction: response.transaction as Hex,\n\t\t\t};\n\t\t}\n\t\tconst base = {\n\t\t\tkind: \"settle\" as const,\n\t\t\tresult: \"failure\" as const,\n\t\t\tstartedAtMs,\n\t\t\tdurationMs,\n\t\t\tnetwork: eventNetwork,\n\t\t\terrorReason: response.errorReason ?? \"unexpected_settle_error\",\n\t\t};\n\t\tconst withPayer = response.payer !== undefined ? { ...base, payer: response.payer } : base;\n\t\tconst withMessage =\n\t\t\tresponse.errorMessage !== undefined\n\t\t\t\t? { ...withPayer, errorMessage: response.errorMessage }\n\t\t\t\t: withPayer;\n\t\tif (response.transaction !== \"\" && response.transaction !== undefined) {\n\t\t\treturn { ...withMessage, transaction: response.transaction as Hex };\n\t\t}\n\t\treturn withMessage;\n\t}\n\n\tasync function verifyCore(req: X402VerifyRequest): Promise<X402VerifyResponse> {\n\t\t// 1. Scheme / network gates\n\t\tif (req.paymentRequirements.scheme !== \"exact\") {\n\t\t\treturn failVerify(\"invalid_scheme\");\n\t\t}\n\t\tif (req.paymentPayload.accepted.scheme !== \"exact\") {\n\t\t\treturn failVerify(\"invalid_scheme\");\n\t\t}\n\t\tconst reqChainId = x402NetworkToChainId(req.paymentRequirements.network);\n\t\tif (reqChainId !== supportedChainId) {\n\t\t\treturn failVerify(\"invalid_network\");\n\t\t}\n\t\tif (req.paymentPayload.accepted.network !== req.paymentRequirements.network) {\n\t\t\treturn failVerify(\"invalid_network\");\n\t\t}\n\n\t\t// 2. Narrow scheme-specific payload\n\t\tconst exact = narrowExactEvmPayload(req.paymentPayload.payload);\n\t\tif (exact === null) {\n\t\t\treturn failVerify(\"invalid_payload\");\n\t\t}\n\t\tconst auth = exact.authorization;\n\n\t\t// 3. Parameter matching against requirements\n\t\tif (auth.value !== req.paymentRequirements.amount) {\n\t\t\treturn failVerify(\n\t\t\t\t\"invalid_exact_evm_payload_authorization_value_mismatch\",\n\t\t\t\tundefined,\n\t\t\t\tauth.from,\n\t\t\t);\n\t\t}\n\t\tif (getAddress(auth.to) !== getAddress(req.paymentRequirements.payTo)) {\n\t\t\treturn failVerify(\"invalid_exact_evm_payload_recipient_mismatch\", undefined, auth.from);\n\t\t}\n\n\t\t// 4. Time window\n\t\tconst now = BigInt(Math.floor(Date.now() / 1000));\n\t\tconst validAfter = BigInt(auth.validAfter);\n\t\tconst validBefore = BigInt(auth.validBefore);\n\t\tif (now < validAfter) {\n\t\t\treturn failVerify(\n\t\t\t\t\"invalid_exact_evm_payload_authorization_valid_after\",\n\t\t\t\tundefined,\n\t\t\t\tauth.from,\n\t\t\t);\n\t\t}\n\t\tif (now >= validBefore) {\n\t\t\treturn failVerify(\n\t\t\t\t\"invalid_exact_evm_payload_authorization_valid_before\",\n\t\t\t\tundefined,\n\t\t\t\tauth.from,\n\t\t\t);\n\t\t}\n\n\t\t// 5. Signature recovery\n\t\tlet recovered: Address;\n\t\ttry {\n\t\t\tconst domain = resolveDomain(req.paymentRequirements);\n\t\t\trecovered = await recoverTypedDataAddress({\n\t\t\t\tdomain: {\n\t\t\t\t\tname: domain.name,\n\t\t\t\t\tversion: domain.version,\n\t\t\t\t\tchainId: reqChainId,\n\t\t\t\t\tverifyingContract: req.paymentRequirements.asset,\n\t\t\t\t},\n\t\t\t\ttypes: TRANSFER_AUTHORIZATION_TYPES,\n\t\t\t\tprimaryType: \"TransferWithAuthorization\",\n\t\t\t\tmessage: {\n\t\t\t\t\tfrom: auth.from,\n\t\t\t\t\tto: auth.to,\n\t\t\t\t\tvalue: BigInt(auth.value),\n\t\t\t\t\tvalidAfter,\n\t\t\t\t\tvalidBefore,\n\t\t\t\t\tnonce: auth.nonce,\n\t\t\t\t},\n\t\t\t\tsignature: exact.signature,\n\t\t\t});\n\t\t} catch (cause) {\n\t\t\treturn failVerify(\n\t\t\t\t\"unexpected_verify_error\",\n\t\t\t\tcause instanceof Error ? cause.message : String(cause),\n\t\t\t\tauth.from,\n\t\t\t);\n\t\t}\n\t\tif (getAddress(recovered) !== getAddress(auth.from)) {\n\t\t\treturn failVerify(\"invalid_exact_evm_payload_signature\", undefined, auth.from);\n\t\t}\n\n\t\t// 6. On-chain reads: balance + nonce-not-used\n\t\ttry {\n\t\t\tconst [balance, used] = await Promise.all([\n\t\t\t\tpublicClient.readContract({\n\t\t\t\t\taddress: req.paymentRequirements.asset,\n\t\t\t\t\tabi: jpycAbi,\n\t\t\t\t\tfunctionName: \"balanceOf\",\n\t\t\t\t\targs: [auth.from],\n\t\t\t\t}),\n\t\t\t\tpublicClient.readContract({\n\t\t\t\t\taddress: req.paymentRequirements.asset,\n\t\t\t\t\tabi: jpycAbi,\n\t\t\t\t\tfunctionName: \"authorizationState\",\n\t\t\t\t\targs: [auth.from, auth.nonce],\n\t\t\t\t}),\n\t\t\t]);\n\t\t\tif (used) {\n\t\t\t\treturn failVerify(\"invalid_payload\", \"authorization nonce already used\", auth.from);\n\t\t\t}\n\t\t\tif ((balance as bigint) < BigInt(auth.value)) {\n\t\t\t\treturn failVerify(\"insufficient_funds\", undefined, auth.from);\n\t\t\t}\n\t\t} catch (cause) {\n\t\t\treturn failVerify(\n\t\t\t\t\"unexpected_verify_error\",\n\t\t\t\tcause instanceof Error ? cause.message : String(cause),\n\t\t\t\tauth.from,\n\t\t\t);\n\t\t}\n\n\t\treturn { isValid: true, payer: auth.from };\n\t}\n\n\tasync function settleCore(req: X402SettleRequest): Promise<X402SettleResponse> {\n\t\t// Re-verify before broadcasting. The wrapped `verify` is used so the\n\t\t// internal re-verify also emits onVerify; operators can dedupe in their\n\t\t// hook if they don't want the extra event.\n\t\tconst verifyResult = await verify(req);\n\t\tif (!verifyResult.isValid) {\n\t\t\treturn failSettle(\n\t\t\t\treq.paymentRequirements.network,\n\t\t\t\t(verifyResult.invalidReason as X402FacilitatorErrorCode) ?? \"unexpected_settle_error\",\n\t\t\t\t{\n\t\t\t\t\t...(verifyResult.invalidMessage !== undefined\n\t\t\t\t\t\t? { message: verifyResult.invalidMessage }\n\t\t\t\t\t\t: {}),\n\t\t\t\t\t...(verifyResult.payer !== undefined ? { payer: verifyResult.payer } : {}),\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\n\t\tconst exact = narrowExactEvmPayload(req.paymentPayload.payload);\n\t\tif (exact === null) {\n\t\t\treturn failSettle(req.paymentRequirements.network, \"invalid_payload\");\n\t\t}\n\t\tconst auth = exact.authorization;\n\t\tconst parsed = parseSignature(exact.signature);\n\t\tconst v = parsed.v !== undefined ? Number(parsed.v) : (parsed.yParity ?? 0) + 27;\n\n\t\tlet txHash: Hex;\n\t\ttry {\n\t\t\ttxHash = await walletClient.writeContract({\n\t\t\t\taddress: req.paymentRequirements.asset,\n\t\t\t\tabi: jpycAbi,\n\t\t\t\tfunctionName: \"transferWithAuthorization\",\n\t\t\t\targs: [\n\t\t\t\t\tauth.from,\n\t\t\t\t\tauth.to,\n\t\t\t\t\tBigInt(auth.value),\n\t\t\t\t\tBigInt(auth.validAfter),\n\t\t\t\t\tBigInt(auth.validBefore),\n\t\t\t\t\tauth.nonce,\n\t\t\t\t\tv,\n\t\t\t\t\tparsed.r,\n\t\t\t\t\tparsed.s,\n\t\t\t\t],\n\t\t\t});\n\t\t} catch (cause) {\n\t\t\treturn failSettle(req.paymentRequirements.network, \"unexpected_settle_error\", {\n\t\t\t\tmessage: cause instanceof Error ? cause.message : String(cause),\n\t\t\t\tpayer: auth.from,\n\t\t\t});\n\t\t}\n\n\t\ttry {\n\t\t\tconst receipt = await publicClient.waitForTransactionReceipt({\n\t\t\t\thash: txHash,\n\t\t\t\ttimeout: receiptTimeoutMs,\n\t\t\t\tconfirmations,\n\t\t\t});\n\t\t\tif (receipt.status !== \"success\") {\n\t\t\t\treturn failSettle(req.paymentRequirements.network, \"invalid_transaction_state\", {\n\t\t\t\t\ttransaction: txHash,\n\t\t\t\t\tpayer: auth.from,\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (cause) {\n\t\t\treturn failSettle(req.paymentRequirements.network, \"unexpected_settle_error\", {\n\t\t\t\tmessage: cause instanceof Error ? cause.message : String(cause),\n\t\t\t\tpayer: auth.from,\n\t\t\t\ttransaction: txHash,\n\t\t\t});\n\t\t}\n\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\ttransaction: txHash,\n\t\t\tnetwork: req.paymentRequirements.network,\n\t\t\tpayer: auth.from,\n\t\t\tamount: auth.value,\n\t\t};\n\t}\n\n\tasync function verify(req: X402VerifyRequest): Promise<X402VerifyResponse> {\n\t\tconst startedAtMs = Date.now();\n\t\tconst result = await verifyCore(req);\n\t\tinvokeHookSafely(hooks?.onVerify, buildVerifyEvent(req, result, startedAtMs));\n\t\treturn result;\n\t}\n\n\tasync function settle(req: X402SettleRequest): Promise<X402SettleResponse> {\n\t\tconst startedAtMs = Date.now();\n\t\tconst result = await settleCore(req);\n\t\tinvokeHookSafely(hooks?.onSettle, buildSettleEvent(req, result, startedAtMs));\n\t\treturn result;\n\t}\n\n\tasync function supportedInternal(): Promise<X402SupportedResponse> {\n\t\tconst kind: X402SupportedKind = {\n\t\t\tx402Version: X402_VERSION,\n\t\t\tscheme: \"exact\",\n\t\t\tnetwork,\n\t\t};\n\t\treturn {\n\t\t\tkinds: [kind],\n\t\t\textensions: [],\n\t\t\tsigners: { \"eip155:*\": [walletClient.account.address] },\n\t\t};\n\t}\n\n\treturn {\n\t\tverify,\n\t\tsettle,\n\t\tsupported: supportedInternal,\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// HTTP-proxied facilitator (Coinbase CDP and any other x402 v2-compliant\n// facilitator endpoint)\n// ---------------------------------------------------------------------------\n\n/** Parameters for {@link createHttpFacilitator}. */\nexport interface CreateHttpFacilitatorParams {\n\t/**\n\t * Base URL of the facilitator service (Coinbase CDP, your own host, any\n\t * x402 v2-compliant endpoint). Endpoints `/verify`, `/settle`, `/supported`\n\t * are POST / POST / GET respectively relative to this URL. Trailing slash\n\t * is stripped.\n\t */\n\treadonly baseUrl: string;\n\t/**\n\t * Optional callback invoked per request that returns headers to merge\n\t * into the outbound request (typically `Authorization`). Receives the\n\t * endpoint name so the caller can compute distinct signatures per route.\n\t */\n\treadonly getAuthHeaders?: (\n\t\tendpoint: \"verify\" | \"settle\" | \"supported\",\n\t) => Promise<Record<string, string>> | Record<string, string>;\n\t/**\n\t * Override the global `fetch` (e.g. for in-process testing or to inject\n\t * an `undici` Agent in Node).\n\t */\n\treadonly fetch?: typeof fetch;\n}\n\n/**\n * Builds a facilitator that proxies all RPC over HTTP to a remote endpoint,\n * matching the request / response shapes of x402 v2 spec §7.\n *\n * Works with any x402 v2-compliant facilitator — Coinbase CDP, your own\n * self-hosted facilitator behind nginx, a regional mirror — as long as it\n * exposes `/verify`, `/settle`, and `/supported` per the spec.\n *\n * If your target facilitator doesn't support the chain you need, fall back\n * to {@link createSelfFacilitator} (in-process viem broadcaster).\n *\n * @example\n * ```ts\n * import { createHttpFacilitator } from \"kawasekit\";\n *\n * const facilitator = createHttpFacilitator({\n * baseUrl: process.env.X402_FACILITATOR_URL!, // e.g. Coinbase CDP endpoint\n * getAuthHeaders: () => ({ Authorization: `Bearer ${apiKey}` }),\n * });\n * ```\n */\nexport function createHttpFacilitator(params: CreateHttpFacilitatorParams): Facilitator {\n\tconst baseUrl = params.baseUrl.replace(/\\/$/, \"\");\n\tconst fetchImpl = params.fetch ?? fetch;\n\tconst getAuthHeaders = params.getAuthHeaders;\n\n\tasync function post<TResponse>(endpoint: \"verify\" | \"settle\", body: unknown): Promise<TResponse> {\n\t\tconst headers: Record<string, string> = { \"content-type\": \"application/json\" };\n\t\tif (getAuthHeaders) {\n\t\t\tObject.assign(headers, await getAuthHeaders(endpoint));\n\t\t}\n\t\tconst response = await fetchImpl(`${baseUrl}/${endpoint}`, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders,\n\t\t\tbody: JSON.stringify(body),\n\t\t});\n\t\tconst text = await response.text();\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = text === \"\" ? null : JSON.parse(text);\n\t\t} catch {\n\t\t\tthrow new Error(\n\t\t\t\t`Facilitator ${endpoint} returned non-JSON (status ${response.status}): ${text.slice(0, 200)}`,\n\t\t\t);\n\t\t}\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(\n\t\t\t\t`Facilitator ${endpoint} failed (status ${response.status}): ${JSON.stringify(parsed).slice(0, 200)}`,\n\t\t\t);\n\t\t}\n\t\treturn parsed as TResponse;\n\t}\n\n\tasync function verifyInternal(req: X402VerifyRequest): Promise<X402VerifyResponse> {\n\t\treturn post<X402VerifyResponse>(\"verify\", {\n\t\t\tx402Version: req.x402Version,\n\t\t\tpaymentPayload: req.paymentPayload,\n\t\t\tpaymentRequirements: req.paymentRequirements,\n\t\t});\n\t}\n\n\tasync function settleInternal(req: X402SettleRequest): Promise<X402SettleResponse> {\n\t\treturn post<X402SettleResponse>(\"settle\", {\n\t\t\tx402Version: req.x402Version,\n\t\t\tpaymentPayload: req.paymentPayload,\n\t\t\tpaymentRequirements: req.paymentRequirements,\n\t\t});\n\t}\n\n\tasync function supportedInternal(): Promise<X402SupportedResponse> {\n\t\tconst headers: Record<string, string> = {};\n\t\tif (getAuthHeaders) {\n\t\t\tObject.assign(headers, await getAuthHeaders(\"supported\"));\n\t\t}\n\t\tconst response = await fetchImpl(`${baseUrl}/supported`, { method: \"GET\", headers });\n\t\tconst text = await response.text();\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = text === \"\" ? null : JSON.parse(text);\n\t\t} catch {\n\t\t\tthrow new Error(\n\t\t\t\t`Facilitator supported returned non-JSON (status ${response.status}): ${text.slice(0, 200)}`,\n\t\t\t);\n\t\t}\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(\n\t\t\t\t`Facilitator supported failed (status ${response.status}): ${JSON.stringify(parsed).slice(0, 200)}`,\n\t\t\t);\n\t\t}\n\t\treturn parsed as X402SupportedResponse;\n\t}\n\n\treturn {\n\t\tverify: verifyInternal,\n\t\tsettle: settleInternal,\n\t\tsupported: supportedInternal,\n\t};\n}\n\n// ---------------------------------------------------------------------------\n// Deprecated aliases (M3-era names)\n//\n// The HTTP-proxied facilitator used to be called `createCoinbaseFacilitator`\n// because the only x402 v2-compliant endpoint we tested against at the time\n// was Coinbase CDP. The function was never Coinbase-specific — it speaks the\n// raw x402 v2 HTTP shape — and the rename to `createHttpFacilitator` lands in\n// v0.1.0-alpha to make that obvious before the npm publish freezes the API.\n//\n// The aliases below preserve M3-era call sites for the v0.1.x line. Calling\n// `createCoinbaseFacilitator` emits a one-shot Node DeprecationWarning. The\n// aliases will be removed in v0.2.0.\n// ---------------------------------------------------------------------------\n\n/**\n * @deprecated Renamed to {@link CreateHttpFacilitatorParams} in v0.1.0-alpha.\n * The HTTP facilitator works with any x402 v2-compliant endpoint, not only\n * Coinbase CDP. This alias will be removed in v0.2.0.\n */\nexport type CreateCoinbaseFacilitatorParams = CreateHttpFacilitatorParams;\n\nlet warnedCreateCoinbaseFacilitator = false;\n\n/**\n * @deprecated Renamed to {@link createHttpFacilitator} in v0.1.0-alpha.\n * This alias delegates to the new function and emits one\n * `DeprecationWarning` per process on first call. It will be removed in\n * v0.2.0.\n */\nexport function createCoinbaseFacilitator(params: CreateHttpFacilitatorParams): Facilitator {\n\tif (!warnedCreateCoinbaseFacilitator) {\n\t\twarnedCreateCoinbaseFacilitator = true;\n\t\tprocess.emitWarning(\n\t\t\t\"createCoinbaseFacilitator() is deprecated and will be removed in kawasekit v0.2.0. Use createHttpFacilitator() instead — the function works with any x402 v2-compliant HTTP endpoint, not only Coinbase CDP.\",\n\t\t\t{ type: \"DeprecationWarning\", code: \"KAWASEKIT_DEP_001\" },\n\t\t);\n\t}\n\treturn createHttpFacilitator(params);\n}\n","/**\n * `wrapFetch()` — turn any WHATWG `fetch` implementation into an x402-aware\n * client.\n *\n * The returned function makes a first request as usual. If the server replies\n * with `402 Payment Required`, the wrapper decodes the `PAYMENT-REQUIRED`\n * header (or response body as a fallback), picks one entry from `accepts`,\n * signs it with the configured {@link X402PaymentSigner}, and retries the\n * same request with a `PAYMENT-SIGNATURE` header. Non-402 responses are\n * returned unchanged.\n *\n * The wrapper does **not** poll or back off — the latency budget (Polygon Amoy\n * bundler inclusion can take ~60 s) lives entirely on the server side, which\n * holds the connection open while it broadcasts and waits for the receipt.\n * If the second attempt still fails the wrapper returns that response so the\n * caller can decide how to recover.\n *\n * Streaming request bodies are not retry-safe; the wrapper passes `init.body`\n * through verbatim, so callers who need retry must pass a buffered body\n * (string / Uint8Array / ArrayBuffer / FormData).\n *\n * @packageDocumentation\n */\n\nimport type { Hex } from \"viem\";\nimport {\n\ttype ClientPaymentEvent,\n\tinvokeHookSafely,\n\ttype ObservabilityHooks,\n} from \"../observability/hooks\";\nimport type { X402PaymentSigner } from \"./client\";\nimport {\n\tdecodePaymentRequiredHeader,\n\tdecodePaymentResponseHeader,\n\tencodePaymentSignatureHeader,\n\tX402_HEADER_IDEMPOTENCY_KEY,\n\tX402_HEADER_PAYMENT_REQUIRED,\n\tX402_HEADER_PAYMENT_RESPONSE,\n\tX402_HEADER_PAYMENT_SIGNATURE,\n} from \"./encoding\";\nimport type { X402PaymentRequiredResponse, X402PaymentRequirements } from \"./types\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Function shape matching the WHATWG `fetch` global. */\nexport type X402Fetch = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;\n\n/** Parameters for {@link wrapFetch}. */\nexport interface WrapFetchParams {\n\t/**\n\t * The signer used to produce {@link X402PaymentPayload}s when the server\n\t * returns 402. Bound to one EOA.\n\t */\n\treadonly signer: X402PaymentSigner;\n\t/**\n\t * Optional underlying fetch implementation. Defaults to `globalThis.fetch`.\n\t */\n\treadonly fetch?: X402Fetch;\n\t/**\n\t * Optional policy for choosing one entry from the server's `accepts` list.\n\t * Defaults to the first entry. Return `null` to abort — the original 402\n\t * response is returned without retry.\n\t */\n\treadonly selectRequirements?: (\n\t\taccepts: readonly X402PaymentRequirements[],\n\t\tresponse: Response,\n\t) => X402PaymentRequirements | null;\n\t/**\n\t * Required gate invoked just before the retry request goes out. Receives\n\t * the chosen requirements and the parsed 402 body so the caller can log\n\t * spending, prompt the user, or enforce a budget.\n\t *\n\t * Returning `false` aborts the retry — the original 402 is returned.\n\t * Returning `true` (or `undefined`) proceeds with the signed retry.\n\t *\n\t * This callback is **required** at the type level: a 402 retry transfers\n\t * real funds, and kawasekit refuses to default to \"always pay\" silently.\n\t * If your caller already enforces a budget elsewhere, return `true`\n\t * explicitly — the empty function `() => true` is a deliberate opt-in.\n\t *\n\t * See `docs/THREAT_MODEL.md` Threat 1.8 / §6.1.\n\t */\n\treadonly onPayment: (\n\t\trequirements: X402PaymentRequirements,\n\t\tpaymentRequired: X402PaymentRequiredResponse,\n\t) => boolean | undefined | Promise<boolean | undefined>;\n\t/**\n\t * Optional observability callbacks. {@link wrapFetch} emits an\n\t * `onClientPayment` event for every paywall round-trip — `success` when the\n\t * retry returns 2xx with a PAYMENT-RESPONSE header, `failure` otherwise\n\t * (including `onPayment` declining the retry).\n\t */\n\treadonly hooks?: ObservabilityHooks;\n\t/**\n\t * Optional mapper from a request to a reasoning-step idempotency key (M5-1).\n\t * When it returns a key, the key is (a) sent as the `Idempotency-Key` request\n\t * header so the server can deduplicate, and (b) forwarded into the signer so\n\t * the EIP-3009 nonce is derived deterministically (on-chain backstop). Return\n\t * `undefined` to fall back to today's random-nonce behaviour. Build keys with\n\t * `createIdempotencyKeyBuilder` from `kawasekit/idempotency` at the agent\n\t * harness's tool-execution boundary, where the reasoning-step intent is visible.\n\t */\n\treadonly idempotencyKeyFor?: (\n\t\tinput: string | URL | Request,\n\t\trequirements: X402PaymentRequirements,\n\t\tpaymentRequired: X402PaymentRequiredResponse,\n\t) => string | undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nasync function readPaymentRequired(\n\tresponse: Response,\n): Promise<X402PaymentRequiredResponse | null> {\n\tconst headerValue = response.headers.get(X402_HEADER_PAYMENT_REQUIRED);\n\tif (headerValue !== null && headerValue !== \"\") {\n\t\ttry {\n\t\t\treturn decodePaymentRequiredHeader(headerValue);\n\t\t} catch {\n\t\t\t// Fall through to body parse — the header was malformed but the\n\t\t\t// body might still be intact (or vice versa).\n\t\t}\n\t}\n\ttry {\n\t\tconst body = await response.clone().text();\n\t\tif (body === \"\") return null;\n\t\tconst parsed = JSON.parse(body) as unknown;\n\t\tif (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\t\treturn null;\n\t\t}\n\t\treturn parsed as X402PaymentRequiredResponse;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction defaultSelectRequirements(\n\taccepts: readonly X402PaymentRequirements[],\n): X402PaymentRequirements | null {\n\treturn accepts[0] ?? null;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Returns an x402-aware `fetch` that pays for `402` responses on the caller's\n * behalf using the provided signer.\n *\n * @example\n * ```ts\n * import { privateKeyToAccount } from \"viem/accounts\";\n * import { createX402PaymentSigner, wrapFetch } from \"kawasekit\";\n *\n * const signer = createX402PaymentSigner({\n * account: privateKeyToAccount(process.env.PAYER_PK as `0x${string}`),\n * });\n *\n * let spent = 0n;\n * const MAX_SPEND = 100_000n; // 100 JPYC (6 decimals)\n * const fetch402 = wrapFetch({\n * signer,\n * onPayment: (req) => {\n * const next = spent + BigInt(req.amount);\n * if (next > MAX_SPEND) return false; // budget exhausted\n * spent = next;\n * return true;\n * },\n * });\n *\n * const res = await fetch402(\"https://api.example.com/weather?city=Tokyo\");\n * console.log(await res.json());\n * ```\n */\nexport function wrapFetch(params: WrapFetchParams): X402Fetch {\n\tconst baseFetch: X402Fetch = params.fetch ?? ((input, init) => fetch(input, init));\n\tconst selectRequirements = params.selectRequirements ?? defaultSelectRequirements;\n\tconst onPayment = params.onPayment;\n\tconst hooks = params.hooks;\n\n\treturn async function x402Fetch(input, init) {\n\t\tconst startedAtMs = Date.now();\n\t\tconst requestUrl =\n\t\t\ttypeof input === \"string\" ? input : input instanceof URL ? input.href : input.url;\n\n\t\tconst emitFailure = (reason: string, httpStatus: number | undefined): void => {\n\t\t\tconst event: ClientPaymentEvent = {\n\t\t\t\tkind: \"client_payment\",\n\t\t\t\tresult: \"failure\",\n\t\t\t\tstartedAtMs,\n\t\t\t\tdurationMs: Date.now() - startedAtMs,\n\t\t\t\trequestUrl,\n\t\t\t\treason,\n\t\t\t\t...(httpStatus !== undefined ? { httpStatus } : {}),\n\t\t\t};\n\t\t\tinvokeHookSafely(hooks?.onClientPayment, event);\n\t\t};\n\n\t\tconst initialResponse = await baseFetch(input, init);\n\t\tif (initialResponse.status !== 402) {\n\t\t\treturn initialResponse;\n\t\t}\n\n\t\tconst paymentRequired = await readPaymentRequired(initialResponse);\n\t\tif (paymentRequired === null || paymentRequired.accepts.length === 0) {\n\t\t\temitFailure(\"no_acceptable_requirement\", 402);\n\t\t\treturn initialResponse;\n\t\t}\n\n\t\tconst chosen = selectRequirements(paymentRequired.accepts, initialResponse);\n\t\tif (chosen === null) {\n\t\t\temitFailure(\"no_acceptable_requirement\", 402);\n\t\t\treturn initialResponse;\n\t\t}\n\n\t\tconst proceed = await onPayment(chosen, paymentRequired);\n\t\tif (proceed === false) {\n\t\t\temitFailure(\"onPayment_declined\", 402);\n\t\t\treturn initialResponse;\n\t\t}\n\n\t\tconst idempotencyKey = params.idempotencyKeyFor?.(input, chosen, paymentRequired);\n\n\t\tconst paymentPayload = await params.signer.sign({\n\t\t\tpaymentRequirements: chosen,\n\t\t\t...(paymentRequired.resource ? { resource: paymentRequired.resource } : {}),\n\t\t\t...(idempotencyKey !== undefined ? { idempotencyKey } : {}),\n\t\t});\n\n\t\tconst retryHeaders = new Headers(init?.headers);\n\t\tretryHeaders.set(X402_HEADER_PAYMENT_SIGNATURE, encodePaymentSignatureHeader(paymentPayload));\n\t\tif (idempotencyKey !== undefined) {\n\t\t\tretryHeaders.set(X402_HEADER_IDEMPOTENCY_KEY, idempotencyKey);\n\t\t}\n\n\t\tconst retryResponse = await baseFetch(input, { ...init, headers: retryHeaders });\n\n\t\tif (retryResponse.status >= 200 && retryResponse.status < 300) {\n\t\t\tconst settlementHeader = retryResponse.headers.get(X402_HEADER_PAYMENT_RESPONSE);\n\t\t\tlet transaction: Hex | undefined;\n\t\t\tif (settlementHeader !== null && settlementHeader !== \"\") {\n\t\t\t\ttry {\n\t\t\t\t\tconst settlement = decodePaymentResponseHeader(settlementHeader);\n\t\t\t\t\tif (settlement.transaction !== \"\") {\n\t\t\t\t\t\ttransaction = settlement.transaction as Hex;\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// PAYMENT-RESPONSE header malformed — the retry still\n\t\t\t\t\t// succeeded so we treat that as a (degraded) success event.\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst successEvent: ClientPaymentEvent = {\n\t\t\t\tkind: \"client_payment\",\n\t\t\t\tresult: \"success\",\n\t\t\t\tstartedAtMs,\n\t\t\t\tdurationMs: Date.now() - startedAtMs,\n\t\t\t\trequestUrl,\n\t\t\t\tpayer: params.signer.address,\n\t\t\t\tamount: chosen.amount,\n\t\t\t\tnetwork: chosen.network,\n\t\t\t\t...(transaction !== undefined ? { transaction } : {}),\n\t\t\t};\n\t\t\tinvokeHookSafely(hooks?.onClientPayment, successEvent);\n\t\t} else {\n\t\t\temitFailure(\n\t\t\t\tretryResponse.status === 402 ? \"settle_rejected\" : \"http_error\",\n\t\t\t\tretryResponse.status,\n\t\t\t);\n\t\t}\n\n\t\treturn retryResponse;\n\t};\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getJpycAddress, jpycAbi } from './chunk-
|
|
1
|
+
import { getJpycAddress, jpycAbi } from './chunk-CD6SQBZN.js';
|
|
2
2
|
import { isSupportedChainId } from './chunk-SA7LMQFG.js';
|
|
3
3
|
import { isAddress, encodeFunctionData } from 'viem';
|
|
4
4
|
import { toCallPolicy, ParamCondition, CallPolicyVersion, toRateLimitPolicy } from '@zerodev/permissions/policies';
|
|
@@ -77,5 +77,5 @@ function createJpycDailyLimitPolicies(params) {
|
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
export { ONE_DAY_SECONDS, TransferJpycInputError, createJpycDailyLimitPolicies, transferJpyc };
|
|
80
|
-
//# sourceMappingURL=chunk-
|
|
81
|
-
//# sourceMappingURL=chunk-
|
|
80
|
+
//# sourceMappingURL=chunk-6G345P2I.js.map
|
|
81
|
+
//# sourceMappingURL=chunk-6G345P2I.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client/transfer-jpyc.ts","../src/policy/daily-limit.ts"],"names":[],"mappings":"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","file":"chunk-DLH2O4MU.js","sourcesContent":["/**\n * High-level helper: transfer JPYC from a Kernel smart account via a sponsored\n * UserOp.\n *\n * This is the canonical \"agent payment\" path for M2. The flow:\n * 1. Resolve the JPYC contract address for `kernelClient.chain`.\n * 2. Encode `JPYC.transfer(to, amount)` calldata.\n * 3. Wrap it as a Kernel call and submit via `sendUserOperation`.\n * 4. Wait for the bundler receipt and return both hashes.\n *\n * EIP-3009 `transferWithAuthorization` cannot be used here: JPYC's signature\n * verification is pure `ecrecover`, so a smart account cannot be `from`. See\n * `src/tokens/eip3009.ts` for the EOA-payer path.\n *\n * @packageDocumentation\n */\n\nimport type { KernelAccountClient } from \"@zerodev/sdk\";\nimport type { Address, Chain, Hex, Transport } from \"viem\";\nimport { encodeFunctionData, isAddress } from \"viem\";\nimport type { SmartAccount } from \"viem/account-abstraction\";\nimport { isSupportedChainId, type SupportedChainId } from \"../chains\";\nimport { getJpycAddress, jpycAbi } from \"../tokens/jpyc\";\n\n/** A {@link KernelAccountClient} that is fully configured (chain + account). */\nexport type ConfiguredKernelClient = KernelAccountClient<Transport, Chain, SmartAccount>;\n\n/** Parameters for {@link transferJpyc}. */\nexport interface TransferJpycParams {\n\t/** Recipient address. */\n\treadonly to: Address;\n\t/**\n\t * Raw token amount in the token's smallest unit (JPYC has 18 decimals).\n\t *\n\t * @example\n\t * ```ts\n\t * import { parseUnits } from \"viem\";\n\t * import { JPYC_DECIMALS } from \"kawasekit\";\n\t *\n\t * parseUnits(\"100\", JPYC_DECIMALS); // 100 JPYC\n\t * ```\n\t */\n\treadonly amount: bigint;\n\t/**\n\t * Optional. Defaults to waiting for the bundler receipt before returning.\n\t * Set to `false` to return after the UserOp is submitted but before it\n\t * lands on chain — useful when the caller wants to do its own polling.\n\t */\n\treadonly waitForReceipt?: boolean;\n}\n\n/** Result of a {@link transferJpyc} call. */\nexport interface TransferJpycResult {\n\treadonly userOpHash: Hex;\n\t/** `null` when `waitForReceipt: false` was requested. */\n\treadonly transactionHash: Hex | null;\n\t/** `true` if the bundler receipt reported success; `null` if not awaited. */\n\treadonly success: boolean | null;\n}\n\n/** Thrown when {@link transferJpyc} is called with invalid arguments. */\nexport class TransferJpycInputError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(`transferJpyc: ${message}`);\n\t\tthis.name = \"TransferJpycInputError\";\n\t}\n}\n\n/**\n * Transfer JPYC from the Kernel smart account to `to` via a sponsored UserOp.\n *\n * @example\n * ```ts\n * import { parseUnits } from \"viem\";\n * import { JPYC_DECIMALS, transferJpyc } from \"kawasekit\";\n *\n * const { userOpHash, transactionHash } = await transferJpyc(kernelClient, {\n * to: \"0xBeef0000000000000000000000000000DEADBEEF\",\n * amount: parseUnits(\"100\", JPYC_DECIMALS),\n * });\n * ```\n */\nexport async function transferJpyc(\n\tkernelClient: ConfiguredKernelClient,\n\tparams: TransferJpycParams,\n): Promise<TransferJpycResult> {\n\tif (!isAddress(params.to, { strict: false })) {\n\t\tthrow new TransferJpycInputError(`\\`to\\` is not a valid address: ${params.to}`);\n\t}\n\tif (params.amount <= 0n) {\n\t\tthrow new TransferJpycInputError(`\\`amount\\` must be positive, got ${params.amount}.`);\n\t}\n\n\tconst chainId = kernelClient.chain.id;\n\tif (!isSupportedChainId(chainId)) {\n\t\tthrow new TransferJpycInputError(`Chain ID ${chainId} is not a kawasekit-supported chain.`);\n\t}\n\tconst jpycAddress = getJpycAddress(chainId satisfies SupportedChainId);\n\n\tconst data = encodeFunctionData({\n\t\tabi: jpycAbi,\n\t\tfunctionName: \"transfer\",\n\t\targs: [params.to, params.amount],\n\t});\n\n\tconst callData = await kernelClient.account.encodeCalls([{ to: jpycAddress, value: 0n, data }]);\n\n\tconst userOpHash = await kernelClient.sendUserOperation({ callData });\n\n\tif (params.waitForReceipt === false) {\n\t\treturn { userOpHash, transactionHash: null, success: null };\n\t}\n\n\tconst receipt = await kernelClient.waitForUserOperationReceipt({ hash: userOpHash });\n\treturn {\n\t\tuserOpHash,\n\t\ttransactionHash: receipt.receipt.transactionHash,\n\t\tsuccess: receipt.success,\n\t};\n}\n","/**\n * Daily-limit spending policy for JPYC, built on ZeroDev's Permission System.\n *\n * Composes two ZeroDev policies:\n * 1. **callPolicy** — locks the session key to `JPYC.transfer(to, value)`\n * with `value ≤ maxPerTransfer`. Recipient is unrestricted in M2;\n * add allowlisting in M3 when use cases firm up.\n * 2. **rateLimitPolicy** — caps userOp count to `maxTransfersPerDay` in any\n * 24-hour rolling window.\n *\n * Effective daily cap = `maxPerTransfer × maxTransfersPerDay`. This is not a\n * cumulative-amount tracker (ZeroDev doesn't ship one), but the agent cannot\n * exceed either dimension, so the spirit of \"daily limit\" holds.\n *\n * @packageDocumentation\n */\n\nimport type { Policy } from \"@zerodev/permissions\";\nimport {\n\tCallPolicyVersion,\n\tParamCondition,\n\ttoCallPolicy,\n\ttoRateLimitPolicy,\n} from \"@zerodev/permissions/policies\";\nimport type { Address } from \"viem\";\nimport { jpycAbi } from \"../tokens/jpyc\";\n\n/** One day in seconds — the period for {@link createJpycDailyLimitPolicies}. */\nexport const ONE_DAY_SECONDS = 86_400;\n\n/** Parameters for {@link createJpycDailyLimitPolicies}. */\nexport interface CreateJpycDailyLimitPoliciesParams {\n\t/** JPYC contract address on the target chain. */\n\treadonly jpycAddress: Address;\n\t/** Maximum JPYC (in raw units) the session key may move in one transfer. */\n\treadonly maxPerTransfer: bigint;\n\t/** Maximum number of transfer userOps the session key may submit per day. */\n\treadonly maxTransfersPerDay: number;\n\t/**\n\t * ZeroDev callPolicy on-chain version. Defaults to V0_0_4 (latest at the\n\t * time of writing). Bump only after auditing the new version's semantics.\n\t */\n\treadonly callPolicyVersion?: CallPolicyVersion;\n}\n\n/**\n * Builds the ZeroDev policy bundle that enforces a JPYC daily spend limit.\n *\n * Plug the returned policies into `toPermissionValidator({ policies, … })`\n * — see {@link createAgentSmartAccount} for the common wiring.\n *\n * @example\n * ```ts\n * import { parseUnits } from \"viem\";\n * import {\n * createJpycDailyLimitPolicies,\n * getJpycAddress,\n * JPYC_DECIMALS,\n * polygonAmoy,\n * } from \"kawasekit\";\n *\n * const policies = createJpycDailyLimitPolicies({\n * jpycAddress: getJpycAddress(polygonAmoy.id),\n * maxPerTransfer: parseUnits(\"100\", JPYC_DECIMALS), // 100 JPYC / tx\n * maxTransfersPerDay: 10, // 10 tx / day\n * // effective daily cap = 1000 JPYC\n * });\n * ```\n */\nexport function createJpycDailyLimitPolicies(\n\tparams: CreateJpycDailyLimitPoliciesParams,\n): readonly [Policy, Policy] {\n\tif (params.maxPerTransfer <= 0n) {\n\t\tthrow new Error(\n\t\t\t`createJpycDailyLimitPolicies: maxPerTransfer must be positive, got ${params.maxPerTransfer}.`,\n\t\t);\n\t}\n\tif (!Number.isInteger(params.maxTransfersPerDay) || params.maxTransfersPerDay < 1) {\n\t\tthrow new Error(\n\t\t\t`createJpycDailyLimitPolicies: maxTransfersPerDay must be a positive integer, got ${params.maxTransfersPerDay}.`,\n\t\t);\n\t}\n\n\tconst callPolicy = toCallPolicy({\n\t\tpolicyVersion: params.callPolicyVersion ?? CallPolicyVersion.V0_0_4,\n\t\tpermissions: [\n\t\t\t{\n\t\t\t\ttarget: params.jpycAddress,\n\t\t\t\tabi: jpycAbi,\n\t\t\t\tfunctionName: \"transfer\",\n\t\t\t\targs: [\n\t\t\t\t\t// Recipient: any address allowed (no allowlist in M2).\n\t\t\t\t\tnull,\n\t\t\t\t\t// value: must be ≤ maxPerTransfer.\n\t\t\t\t\t{\n\t\t\t\t\t\tcondition: ParamCondition.LESS_THAN_OR_EQUAL,\n\t\t\t\t\t\tvalue: params.maxPerTransfer,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t],\n\t});\n\n\tconst rateLimitPolicy = toRateLimitPolicy({\n\t\tinterval: ONE_DAY_SECONDS,\n\t\tcount: params.maxTransfersPerDay,\n\t});\n\n\treturn [callPolicy, rateLimitPolicy] as const;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/client/transfer-jpyc.ts","../src/policy/daily-limit.ts"],"names":[],"mappings":"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","file":"chunk-6G345P2I.js","sourcesContent":["/**\n * High-level helper: transfer JPYC from a Kernel smart account via a sponsored\n * UserOp.\n *\n * This is the canonical \"agent payment\" path for M2. The flow:\n * 1. Resolve the JPYC contract address for `kernelClient.chain`.\n * 2. Encode `JPYC.transfer(to, amount)` calldata.\n * 3. Wrap it as a Kernel call and submit via `sendUserOperation`.\n * 4. Wait for the bundler receipt and return both hashes.\n *\n * EIP-3009 `transferWithAuthorization` cannot be used here: JPYC's signature\n * verification is pure `ecrecover`, so a smart account cannot be `from`. See\n * `src/tokens/eip3009.ts` for the EOA-payer path.\n *\n * @packageDocumentation\n */\n\nimport type { KernelAccountClient } from \"@zerodev/sdk\";\nimport type { Address, Chain, Hex, Transport } from \"viem\";\nimport { encodeFunctionData, isAddress } from \"viem\";\nimport type { SmartAccount } from \"viem/account-abstraction\";\nimport { isSupportedChainId, type SupportedChainId } from \"../chains\";\nimport { getJpycAddress, jpycAbi } from \"../tokens/jpyc\";\n\n/** A {@link KernelAccountClient} that is fully configured (chain + account). */\nexport type ConfiguredKernelClient = KernelAccountClient<Transport, Chain, SmartAccount>;\n\n/** Parameters for {@link transferJpyc}. */\nexport interface TransferJpycParams {\n\t/** Recipient address. */\n\treadonly to: Address;\n\t/**\n\t * Raw token amount in the token's smallest unit (JPYC has 18 decimals).\n\t *\n\t * @example\n\t * ```ts\n\t * import { parseUnits } from \"viem\";\n\t * import { JPYC_DECIMALS } from \"kawasekit\";\n\t *\n\t * parseUnits(\"100\", JPYC_DECIMALS); // 100 JPYC\n\t * ```\n\t */\n\treadonly amount: bigint;\n\t/**\n\t * Optional. Defaults to waiting for the bundler receipt before returning.\n\t * Set to `false` to return after the UserOp is submitted but before it\n\t * lands on chain — useful when the caller wants to do its own polling.\n\t */\n\treadonly waitForReceipt?: boolean;\n}\n\n/** Result of a {@link transferJpyc} call. */\nexport interface TransferJpycResult {\n\treadonly userOpHash: Hex;\n\t/** `null` when `waitForReceipt: false` was requested. */\n\treadonly transactionHash: Hex | null;\n\t/** `true` if the bundler receipt reported success; `null` if not awaited. */\n\treadonly success: boolean | null;\n}\n\n/** Thrown when {@link transferJpyc} is called with invalid arguments. */\nexport class TransferJpycInputError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(`transferJpyc: ${message}`);\n\t\tthis.name = \"TransferJpycInputError\";\n\t}\n}\n\n/**\n * Transfer JPYC from the Kernel smart account to `to` via a sponsored UserOp.\n *\n * @example\n * ```ts\n * import { parseUnits } from \"viem\";\n * import { JPYC_DECIMALS, transferJpyc } from \"kawasekit\";\n *\n * const { userOpHash, transactionHash } = await transferJpyc(kernelClient, {\n * to: \"0xBeef0000000000000000000000000000DEADBEEF\",\n * amount: parseUnits(\"100\", JPYC_DECIMALS),\n * });\n * ```\n */\nexport async function transferJpyc(\n\tkernelClient: ConfiguredKernelClient,\n\tparams: TransferJpycParams,\n): Promise<TransferJpycResult> {\n\tif (!isAddress(params.to, { strict: false })) {\n\t\tthrow new TransferJpycInputError(`\\`to\\` is not a valid address: ${params.to}`);\n\t}\n\tif (params.amount <= 0n) {\n\t\tthrow new TransferJpycInputError(`\\`amount\\` must be positive, got ${params.amount}.`);\n\t}\n\n\tconst chainId = kernelClient.chain.id;\n\tif (!isSupportedChainId(chainId)) {\n\t\tthrow new TransferJpycInputError(`Chain ID ${chainId} is not a kawasekit-supported chain.`);\n\t}\n\tconst jpycAddress = getJpycAddress(chainId satisfies SupportedChainId);\n\n\tconst data = encodeFunctionData({\n\t\tabi: jpycAbi,\n\t\tfunctionName: \"transfer\",\n\t\targs: [params.to, params.amount],\n\t});\n\n\tconst callData = await kernelClient.account.encodeCalls([{ to: jpycAddress, value: 0n, data }]);\n\n\tconst userOpHash = await kernelClient.sendUserOperation({ callData });\n\n\tif (params.waitForReceipt === false) {\n\t\treturn { userOpHash, transactionHash: null, success: null };\n\t}\n\n\tconst receipt = await kernelClient.waitForUserOperationReceipt({ hash: userOpHash });\n\treturn {\n\t\tuserOpHash,\n\t\ttransactionHash: receipt.receipt.transactionHash,\n\t\tsuccess: receipt.success,\n\t};\n}\n","/**\n * Daily-limit spending policy for JPYC, built on ZeroDev's Permission System.\n *\n * Composes two ZeroDev policies:\n * 1. **callPolicy** — locks the session key to `JPYC.transfer(to, value)`\n * with `value ≤ maxPerTransfer`. Recipient is unrestricted in M2;\n * add allowlisting in M3 when use cases firm up.\n * 2. **rateLimitPolicy** — caps userOp count to `maxTransfersPerDay` in any\n * 24-hour rolling window.\n *\n * Effective daily cap = `maxPerTransfer × maxTransfersPerDay`. This is not a\n * cumulative-amount tracker (ZeroDev doesn't ship one), but the agent cannot\n * exceed either dimension, so the spirit of \"daily limit\" holds.\n *\n * @packageDocumentation\n */\n\nimport type { Policy } from \"@zerodev/permissions\";\nimport {\n\tCallPolicyVersion,\n\tParamCondition,\n\ttoCallPolicy,\n\ttoRateLimitPolicy,\n} from \"@zerodev/permissions/policies\";\nimport type { Address } from \"viem\";\nimport { jpycAbi } from \"../tokens/jpyc\";\n\n/** One day in seconds — the period for {@link createJpycDailyLimitPolicies}. */\nexport const ONE_DAY_SECONDS = 86_400;\n\n/** Parameters for {@link createJpycDailyLimitPolicies}. */\nexport interface CreateJpycDailyLimitPoliciesParams {\n\t/** JPYC contract address on the target chain. */\n\treadonly jpycAddress: Address;\n\t/** Maximum JPYC (in raw units) the session key may move in one transfer. */\n\treadonly maxPerTransfer: bigint;\n\t/** Maximum number of transfer userOps the session key may submit per day. */\n\treadonly maxTransfersPerDay: number;\n\t/**\n\t * ZeroDev callPolicy on-chain version. Defaults to V0_0_4 (latest at the\n\t * time of writing). Bump only after auditing the new version's semantics.\n\t */\n\treadonly callPolicyVersion?: CallPolicyVersion;\n}\n\n/**\n * Builds the ZeroDev policy bundle that enforces a JPYC daily spend limit.\n *\n * Plug the returned policies into `toPermissionValidator({ policies, … })`\n * — see {@link createAgentSmartAccount} for the common wiring.\n *\n * @example\n * ```ts\n * import { parseUnits } from \"viem\";\n * import {\n * createJpycDailyLimitPolicies,\n * getJpycAddress,\n * JPYC_DECIMALS,\n * polygonAmoy,\n * } from \"kawasekit\";\n *\n * const policies = createJpycDailyLimitPolicies({\n * jpycAddress: getJpycAddress(polygonAmoy.id),\n * maxPerTransfer: parseUnits(\"100\", JPYC_DECIMALS), // 100 JPYC / tx\n * maxTransfersPerDay: 10, // 10 tx / day\n * // effective daily cap = 1000 JPYC\n * });\n * ```\n */\nexport function createJpycDailyLimitPolicies(\n\tparams: CreateJpycDailyLimitPoliciesParams,\n): readonly [Policy, Policy] {\n\tif (params.maxPerTransfer <= 0n) {\n\t\tthrow new Error(\n\t\t\t`createJpycDailyLimitPolicies: maxPerTransfer must be positive, got ${params.maxPerTransfer}.`,\n\t\t);\n\t}\n\tif (!Number.isInteger(params.maxTransfersPerDay) || params.maxTransfersPerDay < 1) {\n\t\tthrow new Error(\n\t\t\t`createJpycDailyLimitPolicies: maxTransfersPerDay must be a positive integer, got ${params.maxTransfersPerDay}.`,\n\t\t);\n\t}\n\n\tconst callPolicy = toCallPolicy({\n\t\tpolicyVersion: params.callPolicyVersion ?? CallPolicyVersion.V0_0_4,\n\t\tpermissions: [\n\t\t\t{\n\t\t\t\ttarget: params.jpycAddress,\n\t\t\t\tabi: jpycAbi,\n\t\t\t\tfunctionName: \"transfer\",\n\t\t\t\targs: [\n\t\t\t\t\t// Recipient: any address allowed (no allowlist in M2).\n\t\t\t\t\tnull,\n\t\t\t\t\t// value: must be ≤ maxPerTransfer.\n\t\t\t\t\t{\n\t\t\t\t\t\tcondition: ParamCondition.LESS_THAN_OR_EQUAL,\n\t\t\t\t\t\tvalue: params.maxPerTransfer,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t],\n\t});\n\n\tconst rateLimitPolicy = toRateLimitPolicy({\n\t\tinterval: ONE_DAY_SECONDS,\n\t\tcount: params.maxTransfersPerDay,\n\t});\n\n\treturn [callPolicy, rateLimitPolicy] as const;\n}\n"]}
|