kawasekit 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-X54U6GU4.js → chunk-UIDDRHLW.js} +24 -16
- package/dist/chunk-UIDDRHLW.js.map +1 -0
- package/dist/chunk-Y2LOACWO.js +88 -0
- package/dist/chunk-Y2LOACWO.js.map +1 -0
- package/dist/cli/index.cjs +21 -15
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +3 -3
- package/dist/index.cjs +66 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +77 -2
- package/dist/index.d.ts +77 -2
- package/dist/index.js +2 -2
- package/dist/policy/index.cjs +22 -14
- package/dist/policy/index.cjs.map +1 -1
- package/dist/policy/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-RJLDKDWL.js +0 -43
- package/dist/chunk-RJLDKDWL.js.map +0 -1
- package/dist/chunk-X54U6GU4.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -6,6 +6,7 @@ import { PublicClient, Transport, Chain, LocalAccount, Address } from 'viem';
|
|
|
6
6
|
import { S as SupportedChainId } from './index-2fEOL83n.cjs';
|
|
7
7
|
export { C as ChainNotSupportedError, g as getChain, i as isSupportedChainId, s as supportedChains } from './index-2fEOL83n.cjs';
|
|
8
8
|
export { C as ConfiguredKernelClient, I as IssueSessionKeyParams, K as KAWASEKIT_SESSION_ENVELOPE_VERSION, a as KawasekitSessionEnvelope, b as KawasekitSessionEnvelopeVersion, c as KawasekitSessionPolicySummary, R as RestoreSessionAccountParams, d as RevokeSessionKeyParams, e as RevokeSessionKeyResult, f as RotateSessionKeyParams, g as RotateSessionKeyResult, S as SessionEnvelopeChainMismatchError, h as SessionEnvelopeParseError, i as SessionEnvelopeSignerMismatchError, j as SessionEnvelopeVersionError, T as TransferJpycInputError, k as TransferJpycParams, l as TransferJpycResult, m as issueSessionKey, p as parseSessionEnvelope, r as restoreSessionAccount, n as revokeSessionKey, o as rotateSessionKey, s as serializeSessionEnvelope, t as transferJpyc } from './index-DFChv_fT.cjs';
|
|
9
|
+
import { CallPolicyVersion } from '@zerodev/permissions/policies';
|
|
9
10
|
export { CreateJpycDailyLimitPoliciesParams, ONE_DAY_SECONDS, createJpycDailyLimitPolicies } from './policy/index.cjs';
|
|
10
11
|
export { C as CreateSpendingPolicyParams, P as PolicyDecision, S as SpendState, a as SpendingPolicy, b as SpendingPolicyConfigError, T as TokenLimit, c as createSpendingPolicy, e as evaluateSpendingPolicy, m as mergeSpendState } from './spending-policy-CwXcTFD_.cjs';
|
|
11
12
|
export { CoSignConnection, CoSignFrame, CoSignRequestAuthenticator, CoSignRequestEnvelope, CoSignTransport, CoSignUnavailableError, CreateLocalPolicyGatedSignerParams, Mpc2pCoSignAgent, Mpc2pSignerParams, Mpc2pStepOutcome, PolicyGatedSignerConfigError, WIRE_VERSION, WireIntent, assertNonBypassable, canonicalRequestBytes, createLocalPolicyGatedSigner, createMpc2pPolicyGatedSigner, requireNonBypassable, toWireIntent } from './signer/index.cjs';
|
|
@@ -18,7 +19,6 @@ export { ClientPaymentEvent, HookCallback, ObservabilityEvent, ObservabilityEven
|
|
|
18
19
|
export { CanonicalRequestIdentity, CreateIdempotencyKeyBuilderParams, IdempotencyConfigError, IdempotencyKeyBuilder, IdempotencyRecordParseError, IdempotencyRecordVersionError, createIdempotencyKeyBuilder, deriveIdempotencyKey, normalizeIntentText } from './idempotency/index.cjs';
|
|
19
20
|
export { C as CreateInMemoryIdempotencyStoreParams, I as IdempotencyLease, a as IdempotencyLookupResult, b as IdempotencyRecord, c as IdempotencyResponseSnapshot, d as IdempotencyStore, K as KAWASEKIT_IDEMPOTENCY_RECORD_VERSION, e as KawasekitIdempotencyRecordVersion, f as createInMemoryIdempotencyStore, p as parseIdempotencyRecord, s as serializeIdempotencyRecord } from './store-DPOLS6yp.cjs';
|
|
20
21
|
import 'viem/account-abstraction';
|
|
21
|
-
import '@zerodev/permissions/policies';
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* Agent smart account = Kernel v3.1 + ECDSA sudo validator + session-key
|
|
@@ -553,6 +553,81 @@ declare const polygonAmoy: {
|
|
|
553
553
|
verifyHash?: ((client: viem.Client, parameters: viem.VerifyHashActionParameters) => Promise<viem.VerifyHashActionReturnType>) | undefined;
|
|
554
554
|
};
|
|
555
555
|
|
|
556
|
+
/**
|
|
557
|
+
* Buy-list → ZeroDev policy bundle for a **disposable, scoped session key**
|
|
558
|
+
* (the Agent Commerce Hub authorization flow).
|
|
559
|
+
*
|
|
560
|
+
* A user's resolved buy-list (its merchants + a per-transfer cap + a total
|
|
561
|
+
* transfer count + a schedule window) is baked into a single-use session key by
|
|
562
|
+
* composing three on-chain policies:
|
|
563
|
+
* 1. **callPolicy** — `JPYC.transfer(to, value)` with `value ≤ maxPerTransfer`
|
|
564
|
+
* and `to ∈ merchants` (the allowlist; shared with
|
|
565
|
+
* {@link createJpycDailyLimitPolicies} via {@link buildJpycTransferCallPolicy}).
|
|
566
|
+
* 2. **rateLimitPolicy** — a **total** cap of `maxTransfers` over the whole
|
|
567
|
+
* schedule window (the rate window is set to span `[validAfter, validUntil]`,
|
|
568
|
+
* so `count` does NOT reset within the session — it is a session total, not a
|
|
569
|
+
* per-day limit).
|
|
570
|
+
* 3. **timestampPolicy** — the session key is only valid within
|
|
571
|
+
* `[validAfter, validUntil]`.
|
|
572
|
+
*
|
|
573
|
+
* Cumulative budget ("spend ≤ ¥X total") is NOT a policy field — it is the
|
|
574
|
+
* amount the user funds the account with (funding is the user's responsibility,
|
|
575
|
+
* out of the SDK's scope). These policies bound *who* (allowlist), *how much per
|
|
576
|
+
* transfer* (cap), *how many* (count), and *when* (window).
|
|
577
|
+
*
|
|
578
|
+
* @packageDocumentation
|
|
579
|
+
*/
|
|
580
|
+
|
|
581
|
+
/** Parameters for {@link createBuyListPolicies}. */
|
|
582
|
+
interface CreateBuyListPoliciesParams {
|
|
583
|
+
/** JPYC contract address on the target chain. */
|
|
584
|
+
readonly jpycAddress: Address;
|
|
585
|
+
/**
|
|
586
|
+
* The buy-list's resolved merchant recipient addresses — the allowlist the
|
|
587
|
+
* session key may pay. **Required and non-empty** (a buy-list always targets
|
|
588
|
+
* specific merchants); checksum-normalized + de-duplicated.
|
|
589
|
+
*/
|
|
590
|
+
readonly merchants: readonly Address[];
|
|
591
|
+
/** Maximum JPYC (raw units) per single transfer. Must be positive. */
|
|
592
|
+
readonly maxPerTransfer: bigint;
|
|
593
|
+
/**
|
|
594
|
+
* Maximum number of transfers over the WHOLE window — a session total, not a
|
|
595
|
+
* per-day limit. Must be a positive integer.
|
|
596
|
+
*/
|
|
597
|
+
readonly maxTransfers: number;
|
|
598
|
+
/** Schedule-window end (unix seconds); the key is invalid after this. Must be a positive integer. */
|
|
599
|
+
readonly validUntil: number;
|
|
600
|
+
/**
|
|
601
|
+
* Optional schedule-window start (unix seconds); the key is invalid before
|
|
602
|
+
* this. Defaults to 0 (valid immediately). Must be `< validUntil`.
|
|
603
|
+
*/
|
|
604
|
+
readonly validAfter?: number;
|
|
605
|
+
/** ZeroDev callPolicy on-chain version. Defaults to V0_0_4. */
|
|
606
|
+
readonly callPolicyVersion?: CallPolicyVersion;
|
|
607
|
+
}
|
|
608
|
+
/**
|
|
609
|
+
* Build the ZeroDev policy bundle for a buy-list-scoped, single-use session key.
|
|
610
|
+
*
|
|
611
|
+
* Plug the returned policies into `toPermissionValidator({ policies, … })` and
|
|
612
|
+
* issue the session key via {@link issueSessionKey}.
|
|
613
|
+
*
|
|
614
|
+
* @example
|
|
615
|
+
* ```ts
|
|
616
|
+
* import { parseUnits } from "viem";
|
|
617
|
+
* import { createBuyListPolicies, getJpycAddress, JPYC_DECIMALS, polygonAmoy } from "kawasekit";
|
|
618
|
+
*
|
|
619
|
+
* const policies = createBuyListPolicies({
|
|
620
|
+
* jpycAddress: getJpycAddress(polygonAmoy.id),
|
|
621
|
+
* merchants: [merchantA, merchantB], // pay ONLY these (allowlist)
|
|
622
|
+
* maxPerTransfer: parseUnits("500", JPYC_DECIMALS),
|
|
623
|
+
* maxTransfers: 3, // at most 3 transfers, total
|
|
624
|
+
* validUntil: Math.floor(Date.now() / 1000) + 3 * 86_400, // valid 3 days
|
|
625
|
+
* });
|
|
626
|
+
* // user funds the account with their budget; the policies bound who/how-much/how-many/when.
|
|
627
|
+
* ```
|
|
628
|
+
*/
|
|
629
|
+
declare function createBuyListPolicies(params: CreateBuyListPoliciesParams): readonly [Policy, Policy, Policy];
|
|
630
|
+
|
|
556
631
|
/**
|
|
557
632
|
* JPYC stablecoin metadata, deployments, and ABI.
|
|
558
633
|
*
|
|
@@ -919,4 +994,4 @@ declare const jpycAbi: readonly [{
|
|
|
919
994
|
}];
|
|
920
995
|
}];
|
|
921
996
|
|
|
922
|
-
export { type CreateAgentSmartAccountParams, JPYC_DECIMALS, JPYC_EIP712_DOMAIN_HINT, JPYC_V2_ADDRESS, type JpycDeployment, JpycNotAvailableError, SupportedChainId, avalanche, avalancheFuji, createAgentSmartAccount, ethereum, getJpycAddress, jpycAbi, jpycDeployments, kaia, kairos, polygon, polygonAmoy, sepolia };
|
|
997
|
+
export { type CreateAgentSmartAccountParams, type CreateBuyListPoliciesParams, JPYC_DECIMALS, JPYC_EIP712_DOMAIN_HINT, JPYC_V2_ADDRESS, type JpycDeployment, JpycNotAvailableError, SupportedChainId, avalanche, avalancheFuji, createAgentSmartAccount, createBuyListPolicies, ethereum, getJpycAddress, jpycAbi, jpycDeployments, kaia, kairos, polygon, polygonAmoy, sepolia };
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { PublicClient, Transport, Chain, LocalAccount, Address } from 'viem';
|
|
|
6
6
|
import { S as SupportedChainId } from './index-2fEOL83n.js';
|
|
7
7
|
export { C as ChainNotSupportedError, g as getChain, i as isSupportedChainId, s as supportedChains } from './index-2fEOL83n.js';
|
|
8
8
|
export { C as ConfiguredKernelClient, I as IssueSessionKeyParams, K as KAWASEKIT_SESSION_ENVELOPE_VERSION, a as KawasekitSessionEnvelope, b as KawasekitSessionEnvelopeVersion, c as KawasekitSessionPolicySummary, R as RestoreSessionAccountParams, d as RevokeSessionKeyParams, e as RevokeSessionKeyResult, f as RotateSessionKeyParams, g as RotateSessionKeyResult, S as SessionEnvelopeChainMismatchError, h as SessionEnvelopeParseError, i as SessionEnvelopeSignerMismatchError, j as SessionEnvelopeVersionError, T as TransferJpycInputError, k as TransferJpycParams, l as TransferJpycResult, m as issueSessionKey, p as parseSessionEnvelope, r as restoreSessionAccount, n as revokeSessionKey, o as rotateSessionKey, s as serializeSessionEnvelope, t as transferJpyc } from './index-CSpNGigO.js';
|
|
9
|
+
import { CallPolicyVersion } from '@zerodev/permissions/policies';
|
|
9
10
|
export { CreateJpycDailyLimitPoliciesParams, ONE_DAY_SECONDS, createJpycDailyLimitPolicies } from './policy/index.js';
|
|
10
11
|
export { C as CreateSpendingPolicyParams, P as PolicyDecision, S as SpendState, a as SpendingPolicy, b as SpendingPolicyConfigError, T as TokenLimit, c as createSpendingPolicy, e as evaluateSpendingPolicy, m as mergeSpendState } from './spending-policy-BBgXDrVD.js';
|
|
11
12
|
export { CoSignConnection, CoSignFrame, CoSignRequestAuthenticator, CoSignRequestEnvelope, CoSignTransport, CoSignUnavailableError, CreateLocalPolicyGatedSignerParams, Mpc2pCoSignAgent, Mpc2pSignerParams, Mpc2pStepOutcome, PolicyGatedSignerConfigError, WIRE_VERSION, WireIntent, assertNonBypassable, canonicalRequestBytes, createLocalPolicyGatedSigner, createMpc2pPolicyGatedSigner, requireNonBypassable, toWireIntent } from './signer/index.js';
|
|
@@ -18,7 +19,6 @@ export { ClientPaymentEvent, HookCallback, ObservabilityEvent, ObservabilityEven
|
|
|
18
19
|
export { CanonicalRequestIdentity, CreateIdempotencyKeyBuilderParams, IdempotencyConfigError, IdempotencyKeyBuilder, IdempotencyRecordParseError, IdempotencyRecordVersionError, createIdempotencyKeyBuilder, deriveIdempotencyKey, normalizeIntentText } from './idempotency/index.js';
|
|
19
20
|
export { C as CreateInMemoryIdempotencyStoreParams, I as IdempotencyLease, a as IdempotencyLookupResult, b as IdempotencyRecord, c as IdempotencyResponseSnapshot, d as IdempotencyStore, K as KAWASEKIT_IDEMPOTENCY_RECORD_VERSION, e as KawasekitIdempotencyRecordVersion, f as createInMemoryIdempotencyStore, p as parseIdempotencyRecord, s as serializeIdempotencyRecord } from './store-DmdoV3Ii.js';
|
|
20
21
|
import 'viem/account-abstraction';
|
|
21
|
-
import '@zerodev/permissions/policies';
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* Agent smart account = Kernel v3.1 + ECDSA sudo validator + session-key
|
|
@@ -553,6 +553,81 @@ declare const polygonAmoy: {
|
|
|
553
553
|
verifyHash?: ((client: viem.Client, parameters: viem.VerifyHashActionParameters) => Promise<viem.VerifyHashActionReturnType>) | undefined;
|
|
554
554
|
};
|
|
555
555
|
|
|
556
|
+
/**
|
|
557
|
+
* Buy-list → ZeroDev policy bundle for a **disposable, scoped session key**
|
|
558
|
+
* (the Agent Commerce Hub authorization flow).
|
|
559
|
+
*
|
|
560
|
+
* A user's resolved buy-list (its merchants + a per-transfer cap + a total
|
|
561
|
+
* transfer count + a schedule window) is baked into a single-use session key by
|
|
562
|
+
* composing three on-chain policies:
|
|
563
|
+
* 1. **callPolicy** — `JPYC.transfer(to, value)` with `value ≤ maxPerTransfer`
|
|
564
|
+
* and `to ∈ merchants` (the allowlist; shared with
|
|
565
|
+
* {@link createJpycDailyLimitPolicies} via {@link buildJpycTransferCallPolicy}).
|
|
566
|
+
* 2. **rateLimitPolicy** — a **total** cap of `maxTransfers` over the whole
|
|
567
|
+
* schedule window (the rate window is set to span `[validAfter, validUntil]`,
|
|
568
|
+
* so `count` does NOT reset within the session — it is a session total, not a
|
|
569
|
+
* per-day limit).
|
|
570
|
+
* 3. **timestampPolicy** — the session key is only valid within
|
|
571
|
+
* `[validAfter, validUntil]`.
|
|
572
|
+
*
|
|
573
|
+
* Cumulative budget ("spend ≤ ¥X total") is NOT a policy field — it is the
|
|
574
|
+
* amount the user funds the account with (funding is the user's responsibility,
|
|
575
|
+
* out of the SDK's scope). These policies bound *who* (allowlist), *how much per
|
|
576
|
+
* transfer* (cap), *how many* (count), and *when* (window).
|
|
577
|
+
*
|
|
578
|
+
* @packageDocumentation
|
|
579
|
+
*/
|
|
580
|
+
|
|
581
|
+
/** Parameters for {@link createBuyListPolicies}. */
|
|
582
|
+
interface CreateBuyListPoliciesParams {
|
|
583
|
+
/** JPYC contract address on the target chain. */
|
|
584
|
+
readonly jpycAddress: Address;
|
|
585
|
+
/**
|
|
586
|
+
* The buy-list's resolved merchant recipient addresses — the allowlist the
|
|
587
|
+
* session key may pay. **Required and non-empty** (a buy-list always targets
|
|
588
|
+
* specific merchants); checksum-normalized + de-duplicated.
|
|
589
|
+
*/
|
|
590
|
+
readonly merchants: readonly Address[];
|
|
591
|
+
/** Maximum JPYC (raw units) per single transfer. Must be positive. */
|
|
592
|
+
readonly maxPerTransfer: bigint;
|
|
593
|
+
/**
|
|
594
|
+
* Maximum number of transfers over the WHOLE window — a session total, not a
|
|
595
|
+
* per-day limit. Must be a positive integer.
|
|
596
|
+
*/
|
|
597
|
+
readonly maxTransfers: number;
|
|
598
|
+
/** Schedule-window end (unix seconds); the key is invalid after this. Must be a positive integer. */
|
|
599
|
+
readonly validUntil: number;
|
|
600
|
+
/**
|
|
601
|
+
* Optional schedule-window start (unix seconds); the key is invalid before
|
|
602
|
+
* this. Defaults to 0 (valid immediately). Must be `< validUntil`.
|
|
603
|
+
*/
|
|
604
|
+
readonly validAfter?: number;
|
|
605
|
+
/** ZeroDev callPolicy on-chain version. Defaults to V0_0_4. */
|
|
606
|
+
readonly callPolicyVersion?: CallPolicyVersion;
|
|
607
|
+
}
|
|
608
|
+
/**
|
|
609
|
+
* Build the ZeroDev policy bundle for a buy-list-scoped, single-use session key.
|
|
610
|
+
*
|
|
611
|
+
* Plug the returned policies into `toPermissionValidator({ policies, … })` and
|
|
612
|
+
* issue the session key via {@link issueSessionKey}.
|
|
613
|
+
*
|
|
614
|
+
* @example
|
|
615
|
+
* ```ts
|
|
616
|
+
* import { parseUnits } from "viem";
|
|
617
|
+
* import { createBuyListPolicies, getJpycAddress, JPYC_DECIMALS, polygonAmoy } from "kawasekit";
|
|
618
|
+
*
|
|
619
|
+
* const policies = createBuyListPolicies({
|
|
620
|
+
* jpycAddress: getJpycAddress(polygonAmoy.id),
|
|
621
|
+
* merchants: [merchantA, merchantB], // pay ONLY these (allowlist)
|
|
622
|
+
* maxPerTransfer: parseUnits("500", JPYC_DECIMALS),
|
|
623
|
+
* maxTransfers: 3, // at most 3 transfers, total
|
|
624
|
+
* validUntil: Math.floor(Date.now() / 1000) + 3 * 86_400, // valid 3 days
|
|
625
|
+
* });
|
|
626
|
+
* // user funds the account with their budget; the policies bound who/how-much/how-many/when.
|
|
627
|
+
* ```
|
|
628
|
+
*/
|
|
629
|
+
declare function createBuyListPolicies(params: CreateBuyListPoliciesParams): readonly [Policy, Policy, Policy];
|
|
630
|
+
|
|
556
631
|
/**
|
|
557
632
|
* JPYC stablecoin metadata, deployments, and ABI.
|
|
558
633
|
*
|
|
@@ -919,4 +994,4 @@ declare const jpycAbi: readonly [{
|
|
|
919
994
|
}];
|
|
920
995
|
}];
|
|
921
996
|
|
|
922
|
-
export { type CreateAgentSmartAccountParams, JPYC_DECIMALS, JPYC_EIP712_DOMAIN_HINT, JPYC_V2_ADDRESS, type JpycDeployment, JpycNotAvailableError, SupportedChainId, avalanche, avalancheFuji, createAgentSmartAccount, ethereum, getJpycAddress, jpycAbi, jpycDeployments, kaia, kairos, polygon, polygonAmoy, sepolia };
|
|
997
|
+
export { type CreateAgentSmartAccountParams, type CreateBuyListPoliciesParams, JPYC_DECIMALS, JPYC_EIP712_DOMAIN_HINT, JPYC_V2_ADDRESS, type JpycDeployment, JpycNotAvailableError, SupportedChainId, avalanche, avalancheFuji, createAgentSmartAccount, createBuyListPolicies, ethereum, getJpycAddress, jpycAbi, jpycDeployments, kaia, kairos, polygon, polygonAmoy, sepolia };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { TransferJpycInputError, transferJpyc } from './chunk-
|
|
1
|
+
export { TransferJpycInputError, createBuyListPolicies, transferJpyc } from './chunk-Y2LOACWO.js';
|
|
2
2
|
export { X402_DEFAULT_AUTHORIZATION_LIFETIME_SECONDS, X402_FACILITATOR_ERROR_CODES, createCoinbaseFacilitator, createHttpFacilitator, createSelfFacilitator, createX402PaymentSigner, deriveReceiptTimeoutMs, wrapFetch } from './chunk-P5563RGP.js';
|
|
3
3
|
export { X402_DEFAULT_MAX_TIMEOUT_SECONDS, X402_HEADER_IDEMPOTENCY_KEY, X402_HEADER_PAYMENT_REQUIRED, X402_HEADER_PAYMENT_RESPONSE, X402_HEADER_PAYMENT_SIGNATURE, buildPaymentRequiredResponse, buildPaymentRequirements, createX402Handler, decodePaymentRequiredHeader, decodePaymentResponseHeader, decodePaymentSignatureHeader, encodePaymentRequiredHeader, encodePaymentResponseHeader, encodePaymentSignatureHeader } from './chunk-PVUKX6IF.js';
|
|
4
4
|
export { extractAcceptedNetworks, invokeHookSafely } from './chunk-LEHWRDVS.js';
|
|
@@ -8,7 +8,7 @@ export { KAWASEKIT_SESSION_ENVELOPE_VERSION, SessionEnvelopeChainMismatchError,
|
|
|
8
8
|
export { WIRE_VERSION, canonicalRequestBytes, createLocalPolicyGatedSigner, createMpc2pPolicyGatedSigner, toWireIntent } from './chunk-NY6VLXQB.js';
|
|
9
9
|
export { CoSignUnavailableError, PolicyGatedSignerConfigError, assertNonBypassable, authorizationDeadlineFromNow, cancelAuthorizationTypes, deriveAuthorizationNonce, generateAuthorizationNonce, getKnownAssetDomain, listKnownAssetIds, receiveWithAuthorizationTypes, requireNonBypassable, resolvedAssetToEip3009Domain, signCancelAuthorization, signReceiveWithAuthorization, signTransferWithAuthorization, transferWithAuthorizationTypes } from './chunk-VJUXTVSW.js';
|
|
10
10
|
export { X402InvalidConfigError, X402InvalidPayloadError, X402PolicyRejectedError } from './chunk-WMVJNPX2.js';
|
|
11
|
-
export { ONE_DAY_SECONDS, createJpycDailyLimitPolicies } from './chunk-
|
|
11
|
+
export { ONE_DAY_SECONDS, createJpycDailyLimitPolicies } from './chunk-UIDDRHLW.js';
|
|
12
12
|
export { SpendingPolicyConfigError, createSpendingPolicy, evaluateSpendingPolicy, mergeSpendState } from './chunk-7YKRKV6D.js';
|
|
13
13
|
export { JPYC_DECIMALS, JPYC_EIP712_DOMAIN_HINT, JPYC_V2_ADDRESS, JpycNotAvailableError, getJpycAddress, jpycAbi, jpycDeployments } from './chunk-KT7XDT2T.js';
|
|
14
14
|
export { ChainNotSupportedError, avalanche, avalancheFuji, ethereum, getChain, isSupportedChainId, kaia, kairos, polygon, polygonAmoy, sepolia, supportedChains, zerodevRpcUrl } from './chunk-SOTYGX67.js';
|
package/dist/policy/index.cjs
CHANGED
|
@@ -264,31 +264,23 @@ function normalizeRecipientAllowlist(allowlist) {
|
|
|
264
264
|
return normalized;
|
|
265
265
|
}
|
|
266
266
|
|
|
267
|
-
// src/policy/
|
|
268
|
-
|
|
269
|
-
function createJpycDailyLimitPolicies(params) {
|
|
267
|
+
// src/policy/jpyc-call-policy.ts
|
|
268
|
+
function buildJpycTransferCallPolicy(params) {
|
|
270
269
|
if (params.maxPerTransfer <= 0n) {
|
|
271
|
-
throw new Error(
|
|
272
|
-
`createJpycDailyLimitPolicies: maxPerTransfer must be positive, got ${params.maxPerTransfer}.`
|
|
273
|
-
);
|
|
274
|
-
}
|
|
275
|
-
if (!Number.isInteger(params.maxTransfersPerDay) || params.maxTransfersPerDay < 1) {
|
|
276
|
-
throw new Error(
|
|
277
|
-
`createJpycDailyLimitPolicies: maxTransfersPerDay must be a positive integer, got ${params.maxTransfersPerDay}.`
|
|
278
|
-
);
|
|
270
|
+
throw new Error(`maxPerTransfer must be positive, got ${params.maxPerTransfer}.`);
|
|
279
271
|
}
|
|
280
272
|
const recipients = params.recipientAllowlist === void 0 || params.recipientAllowlist === "any" ? null : normalizeRecipientAllowlist(params.recipientAllowlist);
|
|
281
273
|
if (recipients !== null && recipients.length === 0) {
|
|
282
274
|
throw new Error(
|
|
283
|
-
'
|
|
275
|
+
'recipientAllowlist must not be empty \u2014 omit it or pass "any" to allow any recipient.'
|
|
284
276
|
);
|
|
285
277
|
}
|
|
286
278
|
if (recipients !== null && params.callPolicyVersion === policies.CallPolicyVersion.V0_0_1) {
|
|
287
279
|
throw new Error(
|
|
288
|
-
"
|
|
280
|
+
"recipientAllowlist requires callPolicyVersion V0_0_2 or later (the ONE_OF condition is unsupported on V0_0_1)."
|
|
289
281
|
);
|
|
290
282
|
}
|
|
291
|
-
|
|
283
|
+
return policies.toCallPolicy({
|
|
292
284
|
policyVersion: params.callPolicyVersion ?? policies.CallPolicyVersion.V0_0_4,
|
|
293
285
|
permissions: [
|
|
294
286
|
{
|
|
@@ -308,6 +300,22 @@ function createJpycDailyLimitPolicies(params) {
|
|
|
308
300
|
}
|
|
309
301
|
]
|
|
310
302
|
});
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// src/policy/daily-limit.ts
|
|
306
|
+
var ONE_DAY_SECONDS = 86400;
|
|
307
|
+
function createJpycDailyLimitPolicies(params) {
|
|
308
|
+
if (!Number.isInteger(params.maxTransfersPerDay) || params.maxTransfersPerDay < 1) {
|
|
309
|
+
throw new Error(
|
|
310
|
+
`createJpycDailyLimitPolicies: maxTransfersPerDay must be a positive integer, got ${params.maxTransfersPerDay}.`
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
const callPolicy = buildJpycTransferCallPolicy({
|
|
314
|
+
jpycAddress: params.jpycAddress,
|
|
315
|
+
maxPerTransfer: params.maxPerTransfer,
|
|
316
|
+
recipientAllowlist: params.recipientAllowlist,
|
|
317
|
+
callPolicyVersion: params.callPolicyVersion
|
|
318
|
+
});
|
|
311
319
|
const rateLimitPolicy = policies.toRateLimitPolicy({
|
|
312
320
|
interval: ONE_DAY_SECONDS,
|
|
313
321
|
count: params.maxTransfersPerDay
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/chains/avalanche.ts","../../src/chains/ethereum.ts","../../src/chains/kaia.ts","../../src/chains/polygon.ts","../../src/chains/index.ts","../../src/tokens/jpyc.ts","../../src/policy/normalize-allowlist.ts","../../src/policy/daily-limit.ts","../../src/policy/spending-policy.ts"],"names":["viemAvalanche","viemAvalancheFuji","viemMainnet","viemSepolia","viemKaia","viemKairos","viemPolygon","viemPolygonAmoy","getAddress","CallPolicyVersion","toCallPolicy","ParamCondition","toRateLimitPolicy"],"mappings":"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","file":"index.cjs","sourcesContent":["import { avalanche as viemAvalanche, avalancheFuji as viemAvalancheFuji } from \"viem/chains\";\nimport type { KawaseChain } from \"./types\";\n\n/**\n * Avalanche C-Chain — priority 3 production chain.\n *\n * Snowman BFT gives sub-`2 s` **deterministic finality**, so\n * `defaultConfirmations` of `2` is ample — deep confirmations add latency for\n * no extra safety. JPYC is live at the same address as the other chains.\n *\n * The x402 EOA-payer path works today; the smart-account path via ZeroDev is\n * not yet verified on Avalanche.\n */\nexport const avalanche = {\n\t...viemAvalanche,\n\tisTestnet: false,\n\tdefaultConfirmations: 2,\n\tblockTimeMs: 2_000,\n} satisfies KawaseChain;\n\n/**\n * Avalanche Fuji testnet. JPYC is live at the same address as the other chains\n * (confirmed via a read-only on-chain `name()` == \"JPY Coin\" / `symbol()` ==\n * \"JPYC\" check, 2026-05-31). Real x402 settlement here has not been exercised.\n */\nexport const avalancheFuji = {\n\t...viemAvalancheFuji,\n\tisTestnet: true,\n\tdefaultConfirmations: 1,\n\tblockTimeMs: 2_000,\n} satisfies KawaseChain;\n","import { mainnet as viemMainnet, sepolia as viemSepolia } from \"viem/chains\";\nimport type { KawaseChain } from \"./types\";\n\n/**\n * Ethereum mainnet — priority 4 production chain (institutional use cases).\n *\n * Casper FFG finalises in epochs (~12.8 min). `defaultConfirmations` of `32`\n * (~6.4 min at ~12 s blocks) gives finalised-grade safety. **Do NOT use\n * Polygon's `4` here** — 4 blocks (~48 s) is nowhere near finalised, and would\n * re-open the settle-reorg gap (threat 2.8). The facilitator auto-sizes\n * `receiptTimeoutMs` from this depth (~10 min), so the default does not time\n * out. JPYC is live at the same address as the other chains.\n */\nexport const ethereum = {\n\t...viemMainnet,\n\tisTestnet: false,\n\tdefaultConfirmations: 32,\n\tblockTimeMs: 12_000,\n} satisfies KawaseChain;\n\n/**\n * Sepolia — Ethereum testnet. JPYC is live at the same address as the other\n * chains (confirmed via a read-only on-chain `name()` == \"JPY Coin\" / `symbol()`\n * == \"JPYC\" check, 2026-05-31). Real x402 settlement here has not been exercised.\n */\nexport const sepolia = {\n\t...viemSepolia,\n\tisTestnet: true,\n\tdefaultConfirmations: 4,\n\tblockTimeMs: 12_000,\n} satisfies KawaseChain;\n","import { kaia as viemKaia, kairos as viemKairos } from \"viem/chains\";\nimport type { KawaseChain } from \"./types\";\n\n/**\n * Kaia mainnet — priority 2 production chain.\n *\n * Kaia (Klaytn + Finschia) runs IBFT consensus with **immediate finality** — a\n * single confirmed block is final — so `defaultConfirmations` is `1` (do NOT\n * copy Polygon's `4`). JPYC is live at the same address as the other chains\n * (`src/tokens/jpyc.ts`).\n *\n * Note: ZeroDev does not support Kaia, so the **smart-account path** (session\n * keys, sponsored UserOps) is not yet available here — it is planned via\n * Pimlico (M5-3 Phase 2). The **x402 EOA-payer path** works today.\n */\nexport const kaia = {\n\t...viemKaia,\n\tisTestnet: false,\n\tdefaultConfirmations: 1,\n\tblockTimeMs: 1_000,\n} satisfies KawaseChain;\n\n/**\n * Kairos — Kaia testnet. JPYC is available via the Kaia faucet at the same\n * address as mainnet; suitable for the same Amoy→Polygon-style testnet→mainnet\n * verification pattern.\n */\nexport const kairos = {\n\t...viemKairos,\n\tisTestnet: true,\n\tdefaultConfirmations: 1,\n\tblockTimeMs: 1_000,\n} satisfies KawaseChain;\n","import { polygon as viemPolygon, polygonAmoy as viemPolygonAmoy } from \"viem/chains\";\nimport type { KawaseChain } from \"./types\";\n\n/**\n * Polygon mainnet — priority 1 production chain.\n *\n * Built on viem's `polygon` definition (official RPC URLs, block explorers,\n * and `POL` native currency) plus kawasekit metadata. Polygon PoS is\n * probabilistic; the default `4` confirmations ≈ ~8 s of soft finality.\n */\nexport const polygon = {\n\t...viemPolygon,\n\tisTestnet: false,\n\tdefaultConfirmations: 4,\n\tblockTimeMs: 2_000,\n} satisfies KawaseChain;\n\n/**\n * Polygon Amoy testnet — the primary kawasekit development target.\n *\n * Built on viem's `polygonAmoy` definition. JPYC is also live on Amoy at the\n * same address as mainnet; see `src/tokens/jpyc.ts`.\n */\nexport const polygonAmoy = {\n\t...viemPolygonAmoy,\n\tisTestnet: true,\n\tdefaultConfirmations: 1,\n\tblockTimeMs: 2_000,\n} satisfies KawaseChain;\n","import { avalanche, avalancheFuji } from \"./avalanche\";\nimport { ethereum, sepolia } from \"./ethereum\";\nimport { kaia, kairos } from \"./kaia\";\nimport { polygon, polygonAmoy } from \"./polygon\";\nimport { type KawaseChain, zerodevRpcUrl } from \"./types\";\n\nexport {\n\tavalanche,\n\tavalancheFuji,\n\tethereum,\n\ttype KawaseChain,\n\tkaia,\n\tkairos,\n\tpolygon,\n\tpolygonAmoy,\n\tsepolia,\n\tzerodevRpcUrl,\n};\n\n/**\n * All chains kawasekit supports, in priority order (CLAUDE.md chain priority:\n * Polygon → Kaia → Avalanche → Ethereum, each with its testnet).\n *\n * Exposed as a `readonly` tuple — **not** a `Map` — so that bundlers can\n * tree-shake chains a consumer never references.\n *\n * JPYC liveness is a separate axis (`src/tokens/jpyc.ts`): a chain can be\n * supported here while JPYC is not yet live on it (Avalanche Fuji / Sepolia).\n *\n * @example\n * ```ts\n * import { supportedChains } from \"kawasekit\";\n *\n * for (const chain of supportedChains) {\n * \tconsole.log(chain.id, chain.name);\n * }\n * ```\n */\nexport const supportedChains = [\n\tpolygon,\n\tpolygonAmoy,\n\tkaia,\n\tkairos,\n\tavalanche,\n\tavalancheFuji,\n\tethereum,\n\tsepolia,\n] as const;\n\n/**\n * Union of every chain ID kawasekit supports\n * (`137 | 80002 | 8217 | 1001 | 43114 | 43113 | 1 | 11155111`).\n *\n * Derived from {@link supportedChains}, so adding a chain there extends this\n * type automatically.\n */\nexport type SupportedChainId = (typeof supportedChains)[number][\"id\"];\n\n/** A single member of {@link supportedChains}, with its literal `id`. */\ntype SupportedChain = (typeof supportedChains)[number];\n\n/**\n * Internal chain lookup, built once at module scope.\n *\n * This `Map` is an implementation detail and is intentionally **not**\n * exported: the public API exposes the {@link supportedChains} tuple instead,\n * so importing one chain does not pull in all of them.\n */\nconst chainsById: ReadonlyMap<number, SupportedChain> = new Map(\n\tsupportedChains.map((chain) => [chain.id, chain]),\n);\n\n/**\n * Error thrown when a chain ID kawasekit does not support is requested.\n *\n * @example\n * ```ts\n * import { ChainNotSupportedError, getChain } from \"kawasekit\";\n *\n * try {\n * \tgetChain(1);\n * } catch (error) {\n * \tif (error instanceof ChainNotSupportedError) {\n * \t\tconsole.error(error.message);\n * \t}\n * }\n * ```\n */\nexport class ChainNotSupportedError extends Error {\n\tconstructor(chainId: number) {\n\t\tconst supported = supportedChains.map((chain) => chain.id).join(\", \");\n\t\tsuper(\n\t\t\t`Chain ID ${chainId} is not supported by kawasekit. ` + `Supported chain IDs: ${supported}.`,\n\t\t);\n\t\tthis.name = \"ChainNotSupportedError\";\n\t}\n}\n\n/**\n * Type guard that narrows an arbitrary chain ID to a {@link SupportedChainId}.\n *\n * @param chainId - The numeric chain ID to test.\n * @returns `true` if kawasekit supports this chain ID.\n *\n * @example\n * ```ts\n * import { isSupportedChainId } from \"kawasekit\";\n *\n * const id = 80002;\n * if (isSupportedChainId(id)) {\n * \t// `id` is now narrowed to SupportedChainId\n * }\n * ```\n */\nexport function isSupportedChainId(chainId: number): chainId is SupportedChainId {\n\treturn chainsById.has(chainId);\n}\n\n/**\n * Looks up a supported chain by its numeric chain ID.\n *\n * The returned chain's `id` is narrowed to {@link SupportedChainId}.\n *\n * @param chainId - The numeric chain ID to look up.\n * @returns The matching {@link KawaseChain}.\n * @throws {ChainNotSupportedError} If `chainId` is not supported.\n *\n * @example\n * ```ts\n * import { getChain } from \"kawasekit\";\n *\n * const chain = getChain(80002); // Polygon Amoy\n * console.log(chain.name);\n * ```\n */\nexport function getChain(chainId: number): SupportedChain {\n\tconst chain = chainsById.get(chainId);\n\tif (chain === undefined) {\n\t\tthrow new ChainNotSupportedError(chainId);\n\t}\n\treturn chain;\n}\n","/**\n * JPYC stablecoin metadata, deployments, and ABI.\n *\n * JPYC is a Japanese yen-pegged stablecoin issued by JPYC Inc. under the\n * revised Payment Services Act as 電子決済手段 (electronic payment\n * instrument). The new (\"v2\") JPYC, launched 2025-10, lives at the same\n * address on every chain where it is deployed.\n *\n * @packageDocumentation\n */\n\nimport type { Address } from \"viem\";\nimport type { SupportedChainId } from \"../chains\";\nimport {\n\tavalanche,\n\tavalancheFuji,\n\tethereum,\n\tkaia,\n\tkairos,\n\tpolygon,\n\tpolygonAmoy,\n\tsepolia,\n} from \"../chains\";\n\n/** ERC-20 decimals for JPYC. Constant across every chain. */\nexport const JPYC_DECIMALS = 18;\n\n/**\n * EIP-712 domain hint for off-chain authorization signing (EIP-3009, EIP-2612).\n *\n * The real JPYC contract does not expose `version()` publicly — it lives in an\n * `internal VERSION` state variable set during proxy initialization. The\n * canonical value is `\"1\"`, matching the FiatToken lineage; the\n * {@link signTransferWithAuthorization} helper accepts an override if a future\n * deployment changes this.\n *\n * `name` is \"JPY Coin\" — the on-chain `name()` value on every live deployment.\n */\nexport const JPYC_EIP712_DOMAIN_HINT = {\n\tname: \"JPY Coin\",\n\tversion: \"1\",\n} as const;\n\n/**\n * Address shared by every live JPYC deployment.\n *\n * Verified on:\n * - Ethereum : https://etherscan.io/token/0xE7C3D8C9a439feDe00D2600032D5dB0Be71C3c29\n * - Polygon : https://polygonscan.com/token/0xe7c3d8c9a439fede00d2600032d5db0be71c3c29\n * - Polygon Amoy : https://amoy.polygonscan.com/token/0xe7c3d8c9a439fede00d2600032d5db0be71c3c29\n * - Avalanche : https://snowtrace.io/token/0xE7C3D8C9a439feDe00D2600032D5dB0Be71C3c29\n *\n * Do NOT confuse with the legacy 前払式支払手段 JPYC at `0x431D5dFF...`.\n */\nexport const JPYC_V2_ADDRESS: Address = \"0xE7C3D8C9a439feDe00D2600032D5dB0Be71C3c29\";\n\n/** A JPYC deployment on a single chain. */\nexport interface JpycDeployment {\n\treadonly chainId: SupportedChainId;\n\treadonly address: Address;\n\t/** `true` if the token is live on this chain right now. */\n\treadonly isLive: boolean;\n}\n\n/**\n * JPYC deployments keyed by chain.\n *\n * JPYC v2 uses the **same address** (`JPYC_V2_ADDRESS`) on every chain where it\n * is live. `isLive` is the separate \"is JPYC actually deployed here yet?\" axis.\n * All eight supported chains are live at this address: the four mainnets\n * (Polygon, Kaia, Avalanche, Ethereum) + Amoy + Kairos + Avalanche Fuji +\n * Sepolia. Kaia/Kairos/Avalanche/Fuji/Sepolia were confirmed by a read-only\n * on-chain check (`name() == \"JPY Coin\"`, `symbol() == \"JPYC\"` at `0xE7C3…`,\n * 2026-05-31); Polygon/Amoy/Ethereum are established. `isLive: false` + the\n * {@link JpycNotAvailableError} path remain for any future chain added before\n * its JPYC deployment lands.\n */\nexport const jpycDeployments: { readonly [chainId in SupportedChainId]: JpycDeployment } = {\n\t[polygon.id]: { chainId: polygon.id, address: JPYC_V2_ADDRESS, isLive: true },\n\t[polygonAmoy.id]: { chainId: polygonAmoy.id, address: JPYC_V2_ADDRESS, isLive: true },\n\t[kaia.id]: { chainId: kaia.id, address: JPYC_V2_ADDRESS, isLive: true },\n\t[kairos.id]: { chainId: kairos.id, address: JPYC_V2_ADDRESS, isLive: true },\n\t[avalanche.id]: { chainId: avalanche.id, address: JPYC_V2_ADDRESS, isLive: true },\n\t[ethereum.id]: { chainId: ethereum.id, address: JPYC_V2_ADDRESS, isLive: true },\n\t[avalancheFuji.id]: { chainId: avalancheFuji.id, address: JPYC_V2_ADDRESS, isLive: true },\n\t[sepolia.id]: { chainId: sepolia.id, address: JPYC_V2_ADDRESS, isLive: true },\n};\n\n/**\n * Thrown when JPYC is not deployed on the requested chain.\n *\n * Today this is unreachable (every {@link SupportedChainId} has a live\n * deployment), but the error class is exported for future chains (Kaia) where\n * JPYC is still in development.\n */\nexport class JpycNotAvailableError extends Error {\n\tconstructor(chainId: number) {\n\t\tsuper(`JPYC is not yet deployed on chain ID ${chainId}.`);\n\t\tthis.name = \"JpycNotAvailableError\";\n\t}\n}\n\n/**\n * Returns the JPYC contract address for a kawasekit-supported chain.\n *\n * @param chainId - A {@link SupportedChainId}.\n * @returns The JPYC contract address on that chain.\n * @throws {JpycNotAvailableError} If JPYC is not live on the chain.\n *\n * @example\n * ```ts\n * import { getJpycAddress, polygonAmoy } from \"kawasekit\";\n *\n * const address = getJpycAddress(polygonAmoy.id);\n * ```\n */\nexport function getJpycAddress(chainId: SupportedChainId): Address {\n\tconst deployment = jpycDeployments[chainId];\n\tif (!deployment.isLive) {\n\t\tthrow new JpycNotAvailableError(chainId);\n\t}\n\treturn deployment.address;\n}\n\n/**\n * Minimal JPYC ABI: ERC-20 + EIP-3009 surface that kawasekit needs.\n *\n * Excludes permit / mint / blocklist / pause — kawasekit only reads balance,\n * sends `transfer()` via UserOp, and constructs / submits EIP-3009\n * authorizations. Bringing in the full FiatTokenV1 ABI would be wasted bytes.\n */\nexport const jpycAbi = [\n\t// ----- ERC-20 read -----\n\t{\n\t\ttype: \"function\",\n\t\tname: \"name\",\n\t\tstateMutability: \"view\",\n\t\tinputs: [],\n\t\toutputs: [{ name: \"\", type: \"string\" }],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"symbol\",\n\t\tstateMutability: \"view\",\n\t\tinputs: [],\n\t\toutputs: [{ name: \"\", type: \"string\" }],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"decimals\",\n\t\tstateMutability: \"view\",\n\t\tinputs: [],\n\t\toutputs: [{ name: \"\", type: \"uint8\" }],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"totalSupply\",\n\t\tstateMutability: \"view\",\n\t\tinputs: [],\n\t\toutputs: [{ name: \"\", type: \"uint256\" }],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"balanceOf\",\n\t\tstateMutability: \"view\",\n\t\tinputs: [{ name: \"account\", type: \"address\" }],\n\t\toutputs: [{ name: \"\", type: \"uint256\" }],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"allowance\",\n\t\tstateMutability: \"view\",\n\t\tinputs: [\n\t\t\t{ name: \"owner\", type: \"address\" },\n\t\t\t{ name: \"spender\", type: \"address\" },\n\t\t],\n\t\toutputs: [{ name: \"\", type: \"uint256\" }],\n\t},\n\t// ----- ERC-20 write -----\n\t{\n\t\ttype: \"function\",\n\t\tname: \"transfer\",\n\t\tstateMutability: \"nonpayable\",\n\t\tinputs: [\n\t\t\t{ name: \"to\", type: \"address\" },\n\t\t\t{ name: \"value\", type: \"uint256\" },\n\t\t],\n\t\toutputs: [{ name: \"\", type: \"bool\" }],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"transferFrom\",\n\t\tstateMutability: \"nonpayable\",\n\t\tinputs: [\n\t\t\t{ name: \"from\", type: \"address\" },\n\t\t\t{ name: \"to\", type: \"address\" },\n\t\t\t{ name: \"value\", type: \"uint256\" },\n\t\t],\n\t\toutputs: [{ name: \"\", type: \"bool\" }],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"approve\",\n\t\tstateMutability: \"nonpayable\",\n\t\tinputs: [\n\t\t\t{ name: \"spender\", type: \"address\" },\n\t\t\t{ name: \"value\", type: \"uint256\" },\n\t\t],\n\t\toutputs: [{ name: \"\", type: \"bool\" }],\n\t},\n\t// ----- EIP-3009 -----\n\t{\n\t\ttype: \"function\",\n\t\tname: \"transferWithAuthorization\",\n\t\tstateMutability: \"nonpayable\",\n\t\tinputs: [\n\t\t\t{ name: \"from\", type: \"address\" },\n\t\t\t{ name: \"to\", type: \"address\" },\n\t\t\t{ name: \"value\", type: \"uint256\" },\n\t\t\t{ name: \"validAfter\", type: \"uint256\" },\n\t\t\t{ name: \"validBefore\", type: \"uint256\" },\n\t\t\t{ name: \"nonce\", type: \"bytes32\" },\n\t\t\t{ name: \"v\", type: \"uint8\" },\n\t\t\t{ name: \"r\", type: \"bytes32\" },\n\t\t\t{ name: \"s\", type: \"bytes32\" },\n\t\t],\n\t\toutputs: [],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"receiveWithAuthorization\",\n\t\tstateMutability: \"nonpayable\",\n\t\tinputs: [\n\t\t\t{ name: \"from\", type: \"address\" },\n\t\t\t{ name: \"to\", type: \"address\" },\n\t\t\t{ name: \"value\", type: \"uint256\" },\n\t\t\t{ name: \"validAfter\", type: \"uint256\" },\n\t\t\t{ name: \"validBefore\", type: \"uint256\" },\n\t\t\t{ name: \"nonce\", type: \"bytes32\" },\n\t\t\t{ name: \"v\", type: \"uint8\" },\n\t\t\t{ name: \"r\", type: \"bytes32\" },\n\t\t\t{ name: \"s\", type: \"bytes32\" },\n\t\t],\n\t\toutputs: [],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"cancelAuthorization\",\n\t\tstateMutability: \"nonpayable\",\n\t\tinputs: [\n\t\t\t{ name: \"authorizer\", type: \"address\" },\n\t\t\t{ name: \"nonce\", type: \"bytes32\" },\n\t\t\t{ name: \"v\", type: \"uint8\" },\n\t\t\t{ name: \"r\", type: \"bytes32\" },\n\t\t\t{ name: \"s\", type: \"bytes32\" },\n\t\t],\n\t\toutputs: [],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"authorizationState\",\n\t\tstateMutability: \"view\",\n\t\tinputs: [\n\t\t\t{ name: \"authorizer\", type: \"address\" },\n\t\t\t{ name: \"nonce\", type: \"bytes32\" },\n\t\t],\n\t\toutputs: [{ name: \"\", type: \"bool\" }],\n\t},\n\t// ----- Events kawasekit needs to decode -----\n\t{\n\t\ttype: \"event\",\n\t\tname: \"Transfer\",\n\t\tinputs: [\n\t\t\t{ name: \"from\", type: \"address\", indexed: true },\n\t\t\t{ name: \"to\", type: \"address\", indexed: true },\n\t\t\t{ name: \"value\", type: \"uint256\", indexed: false },\n\t\t],\n\t},\n\t{\n\t\ttype: \"event\",\n\t\tname: \"Approval\",\n\t\tinputs: [\n\t\t\t{ name: \"owner\", type: \"address\", indexed: true },\n\t\t\t{ name: \"spender\", type: \"address\", indexed: true },\n\t\t\t{ name: \"value\", type: \"uint256\", indexed: false },\n\t\t],\n\t},\n\t{\n\t\ttype: \"event\",\n\t\tname: \"AuthorizationUsed\",\n\t\tinputs: [\n\t\t\t{ name: \"authorizer\", type: \"address\", indexed: true },\n\t\t\t{ name: \"nonce\", type: \"bytes32\", indexed: true },\n\t\t],\n\t},\n\t{\n\t\ttype: \"event\",\n\t\tname: \"AuthorizationCanceled\",\n\t\tinputs: [\n\t\t\t{ name: \"authorizer\", type: \"address\", indexed: true },\n\t\t\t{ name: \"nonce\", type: \"bytes32\", indexed: true },\n\t\t],\n\t},\n] as const;\n","/**\n * Shared recipient-allowlist normalization for the two policy paths — the\n * off-chain {@link createSpendingPolicy} (`./spending-policy`) and the on-chain\n * {@link createJpycDailyLimitPolicies} (`./daily-limit`). Keeping one normalizer\n * means both agree on what \"the same allowlist\" is: a future change (e.g.\n * rejecting the zero address) lands in one place, not two that can drift.\n *\n * @packageDocumentation\n */\n\nimport type { Address } from \"viem\";\nimport { getAddress } from \"viem\";\n\n/**\n * Checksum-normalize ({@link getAddress}) and de-duplicate an address allowlist,\n * preserving first-seen order. `getAddress` rejects a malformed address.\n *\n * This does **not** decide what an empty list means — `[]` returns `[]`. Each\n * caller owns that policy: the off-chain `SpendingPolicy` treats `[]` as\n * deny-all, while the on-chain `createJpycDailyLimitPolicies` rejects it (an\n * on-chain allowlist cannot encode \"match nothing\").\n */\nexport function normalizeRecipientAllowlist(allowlist: readonly Address[]): Address[] {\n\tconst seen = new Set<Address>();\n\tconst normalized: Address[] = [];\n\tfor (const entry of allowlist) {\n\t\tconst checksummed = getAddress(entry);\n\t\tif (!seen.has(checksummed)) {\n\t\t\tseen.add(checksummed);\n\t\t\tnormalized.push(checksummed);\n\t\t}\n\t}\n\treturn normalized;\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`, and — when {@link\n * CreateJpycDailyLimitPoliciesParams.recipientAllowlist} is provided —\n * restricts `to` to the allowlisted recipients (otherwise any recipient is\n * allowed). This is the on-chain enforcement behind the \"pay only registered\n * merchants\" model: a buy-list resolves to its merchants' addresses, which\n * are baked into a disposable session key here.\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\";\nimport { normalizeRecipientAllowlist } from \"./normalize-allowlist\";\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\t/**\n\t * Recipient restriction. An address list restricts the session key to\n\t * `transfer` JPYC only to those recipients (enforced on-chain via the\n\t * callPolicy `to` argument, condition `ONE_OF`); every other recipient is\n\t * rejected before any funds move. `\"any\"` (or omitting the field) leaves the\n\t * recipient unrestricted.\n\t *\n\t * The type mirrors the off-chain {@link SpendingPolicy.recipientAllowlist}\n\t * (`Address[] | \"any\"`) so a buy-list's resolved allowlist can feed both the\n\t * off-chain and on-chain policy paths unchanged. Two **deliberate** differences\n\t * from that sibling, forced by on-chain semantics:\n\t * - it is **optional** here (omitted = `\"any\"`) for backward compatibility —\n\t * the pre-allowlist policy left the recipient unrestricted;\n\t * - an **empty** array `[]` **throws** (rather than meaning deny-all as it does\n\t * off-chain) — an on-chain allowlist cannot encode \"match nothing\"; omit it\n\t * or pass `\"any\"` for unrestricted, or list ≥1 recipient.\n\t *\n\t * Entries are checksum-normalized and de-duplicated (shared with the off-chain\n\t * path via {@link normalizeRecipientAllowlist}). An address list requires\n\t * `callPolicyVersion` ≥ `V0_0_2` (the `ONE_OF` condition is unsupported on\n\t * `V0_0_1`); the default `V0_0_4` is fine.\n\t */\n\treadonly recipientAllowlist?: readonly Address[] | \"any\";\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 *\n * @example Restrict the session key to a buy-list's merchants only\n * ```ts\n * const policies = createJpycDailyLimitPolicies({\n * jpycAddress: getJpycAddress(polygonAmoy.id),\n * maxPerTransfer: parseUnits(\"100\", JPYC_DECIMALS),\n * maxTransfersPerDay: 5,\n * // on-chain: any transfer to a non-allowlisted address reverts before funds move\n * recipientAllowlist: [merchantA, merchantB],\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\t// Resolve the recipient constraint up-front. Omitted or \"any\" => unrestricted\n\t// (a `null` arg); an address list => checksum-normalized + de-duped (shared\n\t// with the off-chain SpendingPolicy). Unlike off-chain, an empty list is a\n\t// caller bug here — an on-chain allowlist cannot encode \"deny all\".\n\tconst recipients =\n\t\tparams.recipientAllowlist === undefined || params.recipientAllowlist === \"any\"\n\t\t\t? null\n\t\t\t: normalizeRecipientAllowlist(params.recipientAllowlist);\n\tif (recipients !== null && recipients.length === 0) {\n\t\tthrow new Error(\n\t\t\t'createJpycDailyLimitPolicies: recipientAllowlist must not be empty — omit it or pass \"any\" to allow any recipient.',\n\t\t);\n\t}\n\t// The ONE_OF condition (used to encode an address list) is only supported by\n\t// the V0_0_2+ CallPolicy contract; catch the incompatible combination here\n\t// with a typed message rather than a bare error from deep inside toCallPolicy.\n\tif (recipients !== null && params.callPolicyVersion === CallPolicyVersion.V0_0_1) {\n\t\tthrow new Error(\n\t\t\t\"createJpycDailyLimitPolicies: recipientAllowlist requires callPolicyVersion V0_0_2 or later (the ONE_OF condition is unsupported on V0_0_1).\",\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 (`to`): unrestricted (`null`) unless an allowlist resolved\n\t\t\t\t\t// above, in which case it is constrained via the ONE_OF condition.\n\t\t\t\t\trecipients === null ? null : { condition: ParamCondition.ONE_OF, value: recipients },\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","/**\n * Spending policy — policy-as-data for the x402 / EIP-3009 PolicyGatedSigner\n * (M6). One declarative {@link SpendingPolicy} (session + expiry, per-token\n * `maxPerSign` + cumulative cap, recipient allowlist, `revoked`) and one pure,\n * deny-closed evaluator {@link evaluateSpendingPolicy}.\n *\n * The same specification is enforced SDK-side (the `local` adapter) and, for the\n * `mpc-2p` adapter, re-implemented backend-side in Rust (the `kawasekit-mpc-2p`\n * co-signer); a shared conformance corpus\n * (`__fixtures__/spending-policy.vectors.json`) keeps the two in lockstep.\n * The evaluator is **check-only** — it reads `SpendState` and never mutates it;\n * the cumulative-cap *commit* (folding a successful spend back in via\n * {@link mergeSpendState}) is the adapter's job, and atomic+authoritative\n * commit is a property of the `cryptographic` adapter only.\n *\n * This is the **x402-EOA** policy path. The smart-account / ZeroDev session-key\n * path is `createJpycDailyLimitPolicies` (`./daily-limit`) — a sibling, not a\n * replacement.\n *\n * @packageDocumentation\n */\n\nimport type { Address } from \"viem\";\nimport { getAddress } from \"viem\";\nimport type { PaymentIntent, PolicyRejection } from \"../signer/types\";\nimport { normalizeRecipientAllowlist } from \"./normalize-allowlist\";\n\n/** Per-token spend limits. A token absent from the policy's `perToken` is NOT allowed. */\nexport interface TokenLimit {\n\treadonly token: Address;\n\t/** Max value per single signature, token base units. Generalizes `maxAmountPerSign` (threat 1.14). */\n\treadonly maxPerSign: bigint;\n\t/** Optional total across the session. `undefined` = uncapped. MUST be `>= maxPerSign`. */\n\treadonly cumulativeCap?: bigint;\n}\n\n/**\n * Policy-as-data evaluated for every {@link PaymentIntent}. Deny-closed\n * throughout: a token not listed in `perToken` is rejected, and\n * `recipientAllowlist` is **required** — `\"any\"` (unrestricted) is a conscious,\n * greppable choice, never a silent default.\n */\nexport interface SpendingPolicy {\n\treadonly version: \"1\";\n\t/** Session id + expiry (unix seconds). An authorization may not outlive the session. */\n\treadonly session: { readonly id: string; readonly notAfter: bigint };\n\treadonly perToken: readonly TokenLimit[];\n\t/**\n\t * Recipient restriction (**required** — no silent allow-open default):\n\t * `\"any\"` = unrestricted, `[]` = deny-all, `[...]` = allowlist. Making\n\t * `\"any\"` explicit keeps the policy deny-closed like `perToken`.\n\t *\n\t * The on-chain {@link createJpycDailyLimitPolicies} takes the same\n\t * `Address[] | \"any\"` shape, with two on-chain-forced differences: it is\n\t * optional (omitted = `\"any\"`), and `[]` throws there (an on-chain allowlist\n\t * cannot encode deny-all).\n\t */\n\treadonly recipientAllowlist: readonly Address[] | \"any\";\n\treadonly revoked: boolean;\n}\n\n/**\n * Cross-call cumulative spend, per token. Injected into the evaluator (never a\n * module global). For the `local` adapter this is a single-process, caller-managed\n * **read-only view**; the authoritative ledger lives in the `cryptographic`\n * adapter's backend.\n */\nexport interface SpendState {\n\treadonly spentPerToken: readonly { readonly token: Address; readonly spent: bigint }[];\n}\n\n/** The outcome of {@link evaluateSpendingPolicy}. */\nexport type PolicyDecision =\n\t| { readonly ok: true }\n\t| { readonly ok: false; readonly rejection: PolicyRejection };\n\n/** Thrown by {@link createSpendingPolicy} on a malformed policy. */\nexport class SpendingPolicyConfigError extends Error {\n\treadonly field: string;\n\treadonly reason: string;\n\n\tconstructor(field: string, reason: string, options?: { cause?: unknown }) {\n\t\tsuper(`Invalid SpendingPolicy (${field}): ${reason}`, options);\n\t\tthis.name = \"SpendingPolicyConfigError\";\n\t\tthis.field = field;\n\t\tthis.reason = reason;\n\t}\n}\n\nfunction deny(reason: PolicyRejection[\"reason\"], detail: string): PolicyDecision {\n\treturn { ok: false, rejection: { reason, detail } };\n}\n\n/**\n * Evaluate a {@link SpendingPolicy} against a decoded {@link PaymentIntent}.\n *\n * Pure, deterministic, no I/O. Deny-closed; the first failing check wins. All\n * amount comparisons are `bigint`; all address equality uses `getAddress()` on\n * both sides. **Reads `state`, never mutates it** — see {@link mergeSpendState}.\n * `detail` strings never contain the nonce or any signature.\n *\n * @example\n * ```ts\n * const decision = evaluateSpendingPolicy(policy, intent, state, BigInt(Math.floor(Date.now() / 1000)));\n * if (!decision.ok) console.warn(decision.rejection.reason);\n * ```\n */\nexport function evaluateSpendingPolicy(\n\tpolicy: SpendingPolicy,\n\tintent: PaymentIntent,\n\tstate: SpendState,\n\tnowSeconds: bigint,\n): PolicyDecision {\n\tif (policy.revoked) {\n\t\treturn deny(\"revoked\", \"the spending policy has been revoked\");\n\t}\n\tif (nowSeconds > policy.session.notAfter) {\n\t\treturn deny(\"expired\", `session expired at ${policy.session.notAfter} (now ${nowSeconds})`);\n\t}\n\tif (intent.validBefore > policy.session.notAfter) {\n\t\treturn deny(\n\t\t\t\"expired\",\n\t\t\t`authorization validBefore ${intent.validBefore} outlives the session (notAfter ${policy.session.notAfter})`,\n\t\t);\n\t}\n\n\tconst intentToken = getAddress(intent.token);\n\tconst limit = policy.perToken.find((l) => getAddress(l.token) === intentToken);\n\tif (limit === undefined) {\n\t\treturn deny(\"token_not_allowed\", `token ${intentToken} is not in the policy`);\n\t}\n\n\tif (policy.recipientAllowlist !== \"any\") {\n\t\tconst to = getAddress(intent.to);\n\t\tconst allowed = policy.recipientAllowlist.some((a) => getAddress(a) === to);\n\t\tif (!allowed) {\n\t\t\treturn deny(\"recipient_not_allowed\", `recipient ${to} is not on the allowlist`);\n\t\t}\n\t}\n\n\tif (intent.value > limit.maxPerSign) {\n\t\treturn deny(\n\t\t\t\"amount_exceeds_per_sign\",\n\t\t\t`value ${intent.value} exceeds maxPerSign ${limit.maxPerSign}`,\n\t\t);\n\t}\n\n\tif (limit.cumulativeCap !== undefined) {\n\t\tconst spent = state.spentPerToken.find((s) => getAddress(s.token) === intentToken)?.spent ?? 0n;\n\t\tif (spent + intent.value > limit.cumulativeCap) {\n\t\t\treturn deny(\n\t\t\t\t\"amount_exceeds_cumulative\",\n\t\t\t\t`spent ${spent} + value ${intent.value} exceeds cumulativeCap ${limit.cumulativeCap}`,\n\t\t\t);\n\t\t}\n\t}\n\n\treturn { ok: true };\n}\n\n/** Parameters for {@link createSpendingPolicy}. */\nexport interface CreateSpendingPolicyParams {\n\treadonly session: { readonly id: string; readonly notAfter: bigint };\n\treadonly perToken: readonly TokenLimit[];\n\t/** Required: `\"any\"` (unrestricted), `[]` (deny-all), or an allowlist. No silent default. */\n\treadonly recipientAllowlist: readonly Address[] | \"any\";\n\t/** Defaults to `false`. */\n\treadonly revoked?: boolean;\n}\n\n/**\n * Validate + normalize a {@link SpendingPolicy}. Checksums all addresses\n * (`getAddress`), de-dupes the recipient allowlist (shared\n * {@link normalizeRecipientAllowlist}; `[]` stays deny-all), rejects an empty\n * `perToken` (deny-closed), a non-positive `maxPerSign`/`cumulativeCap`, a\n * `cumulativeCap < maxPerSign`, and duplicate tokens. Throws\n * {@link SpendingPolicyConfigError} on violation.\n *\n * @example\n * ```ts\n * const policy = createSpendingPolicy({\n * session: { id: conversationId, notAfter: BigInt(deadline) },\n * perToken: [{ token: JPYC, maxPerSign: 1_000n, cumulativeCap: 10_000n }],\n * recipientAllowlist: [merchant],\n * });\n * ```\n */\nexport function createSpendingPolicy(params: CreateSpendingPolicyParams): SpendingPolicy {\n\tif (typeof params.session.id !== \"string\" || params.session.id === \"\") {\n\t\tthrow new SpendingPolicyConfigError(\"session.id\", \"must be a non-empty string\");\n\t}\n\tif (params.session.notAfter <= 0n) {\n\t\tthrow new SpendingPolicyConfigError(\n\t\t\t\"session.notAfter\",\n\t\t\t`must be a positive unix-seconds bigint, got ${params.session.notAfter}`,\n\t\t);\n\t}\n\tif (params.perToken.length === 0) {\n\t\tthrow new SpendingPolicyConfigError(\n\t\t\t\"perToken\",\n\t\t\t\"must list at least one token (the policy is deny-closed)\",\n\t\t);\n\t}\n\n\tconst seen = new Set<string>();\n\tconst perToken: readonly TokenLimit[] = params.perToken.map((l) => {\n\t\tconst token = getAddress(l.token);\n\t\tif (seen.has(token)) {\n\t\t\tthrow new SpendingPolicyConfigError(\"perToken\", `duplicate token ${token}`);\n\t\t}\n\t\tseen.add(token);\n\t\tif (l.maxPerSign <= 0n) {\n\t\t\tthrow new SpendingPolicyConfigError(\n\t\t\t\t\"perToken.maxPerSign\",\n\t\t\t\t`must be positive, got ${l.maxPerSign} for ${token}`,\n\t\t\t);\n\t\t}\n\t\tif (l.cumulativeCap !== undefined) {\n\t\t\tif (l.cumulativeCap <= 0n) {\n\t\t\t\tthrow new SpendingPolicyConfigError(\n\t\t\t\t\t\"perToken.cumulativeCap\",\n\t\t\t\t\t`must be positive, got ${l.cumulativeCap} for ${token}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (l.cumulativeCap < l.maxPerSign) {\n\t\t\t\tthrow new SpendingPolicyConfigError(\n\t\t\t\t\t\"perToken.cumulativeCap\",\n\t\t\t\t\t`cumulativeCap (${l.cumulativeCap}) must be >= maxPerSign (${l.maxPerSign}) for ${token}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn { token, maxPerSign: l.maxPerSign, cumulativeCap: l.cumulativeCap };\n\t\t}\n\t\treturn { token, maxPerSign: l.maxPerSign };\n\t});\n\n\t// Checksum-normalize + de-dupe the allowlist (shared with the on-chain\n\t// daily-limit path). `[]` stays `[]` — deny-all is a valid off-chain policy.\n\tconst recipientAllowlist =\n\t\tparams.recipientAllowlist === \"any\"\n\t\t\t? \"any\"\n\t\t\t: normalizeRecipientAllowlist(params.recipientAllowlist);\n\n\treturn {\n\t\tversion: \"1\",\n\t\tsession: { id: params.session.id, notAfter: params.session.notAfter },\n\t\tperToken,\n\t\trecipientAllowlist,\n\t\trevoked: params.revoked ?? false,\n\t};\n}\n\n/**\n * Fold a successful spend back into a {@link SpendState} (pure; returns a new\n * state). The caller of the `local` adapter uses this to keep `cumulativeCap`\n * meaningful across calls — `local` does not own an authoritative ledger.\n */\nexport function mergeSpendState(\n\tstate: SpendState,\n\tspend: { readonly token: Address; readonly value: bigint },\n): SpendState {\n\tconst token = getAddress(spend.token);\n\tconst exists = state.spentPerToken.some((s) => getAddress(s.token) === token);\n\tconst spentPerToken = exists\n\t\t? state.spentPerToken.map((s) =>\n\t\t\t\tgetAddress(s.token) === token ? { token, spent: s.spent + spend.value } : s,\n\t\t\t)\n\t\t: [...state.spentPerToken, { token, spent: spend.value }];\n\treturn { spentPerToken };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/chains/avalanche.ts","../../src/chains/ethereum.ts","../../src/chains/kaia.ts","../../src/chains/polygon.ts","../../src/chains/index.ts","../../src/tokens/jpyc.ts","../../src/policy/normalize-allowlist.ts","../../src/policy/jpyc-call-policy.ts","../../src/policy/daily-limit.ts","../../src/policy/spending-policy.ts"],"names":["viemAvalanche","viemAvalancheFuji","viemMainnet","viemSepolia","viemKaia","viemKairos","viemPolygon","viemPolygonAmoy","getAddress","CallPolicyVersion","toCallPolicy","ParamCondition","toRateLimitPolicy"],"mappings":"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","file":"index.cjs","sourcesContent":["import { avalanche as viemAvalanche, avalancheFuji as viemAvalancheFuji } from \"viem/chains\";\nimport type { KawaseChain } from \"./types\";\n\n/**\n * Avalanche C-Chain — priority 3 production chain.\n *\n * Snowman BFT gives sub-`2 s` **deterministic finality**, so\n * `defaultConfirmations` of `2` is ample — deep confirmations add latency for\n * no extra safety. JPYC is live at the same address as the other chains.\n *\n * The x402 EOA-payer path works today; the smart-account path via ZeroDev is\n * not yet verified on Avalanche.\n */\nexport const avalanche = {\n\t...viemAvalanche,\n\tisTestnet: false,\n\tdefaultConfirmations: 2,\n\tblockTimeMs: 2_000,\n} satisfies KawaseChain;\n\n/**\n * Avalanche Fuji testnet. JPYC is live at the same address as the other chains\n * (confirmed via a read-only on-chain `name()` == \"JPY Coin\" / `symbol()` ==\n * \"JPYC\" check, 2026-05-31). Real x402 settlement here has not been exercised.\n */\nexport const avalancheFuji = {\n\t...viemAvalancheFuji,\n\tisTestnet: true,\n\tdefaultConfirmations: 1,\n\tblockTimeMs: 2_000,\n} satisfies KawaseChain;\n","import { mainnet as viemMainnet, sepolia as viemSepolia } from \"viem/chains\";\nimport type { KawaseChain } from \"./types\";\n\n/**\n * Ethereum mainnet — priority 4 production chain (institutional use cases).\n *\n * Casper FFG finalises in epochs (~12.8 min). `defaultConfirmations` of `32`\n * (~6.4 min at ~12 s blocks) gives finalised-grade safety. **Do NOT use\n * Polygon's `4` here** — 4 blocks (~48 s) is nowhere near finalised, and would\n * re-open the settle-reorg gap (threat 2.8). The facilitator auto-sizes\n * `receiptTimeoutMs` from this depth (~10 min), so the default does not time\n * out. JPYC is live at the same address as the other chains.\n */\nexport const ethereum = {\n\t...viemMainnet,\n\tisTestnet: false,\n\tdefaultConfirmations: 32,\n\tblockTimeMs: 12_000,\n} satisfies KawaseChain;\n\n/**\n * Sepolia — Ethereum testnet. JPYC is live at the same address as the other\n * chains (confirmed via a read-only on-chain `name()` == \"JPY Coin\" / `symbol()`\n * == \"JPYC\" check, 2026-05-31). Real x402 settlement here has not been exercised.\n */\nexport const sepolia = {\n\t...viemSepolia,\n\tisTestnet: true,\n\tdefaultConfirmations: 4,\n\tblockTimeMs: 12_000,\n} satisfies KawaseChain;\n","import { kaia as viemKaia, kairos as viemKairos } from \"viem/chains\";\nimport type { KawaseChain } from \"./types\";\n\n/**\n * Kaia mainnet — priority 2 production chain.\n *\n * Kaia (Klaytn + Finschia) runs IBFT consensus with **immediate finality** — a\n * single confirmed block is final — so `defaultConfirmations` is `1` (do NOT\n * copy Polygon's `4`). JPYC is live at the same address as the other chains\n * (`src/tokens/jpyc.ts`).\n *\n * Note: ZeroDev does not support Kaia, so the **smart-account path** (session\n * keys, sponsored UserOps) is not yet available here — it is planned via\n * Pimlico (M5-3 Phase 2). The **x402 EOA-payer path** works today.\n */\nexport const kaia = {\n\t...viemKaia,\n\tisTestnet: false,\n\tdefaultConfirmations: 1,\n\tblockTimeMs: 1_000,\n} satisfies KawaseChain;\n\n/**\n * Kairos — Kaia testnet. JPYC is available via the Kaia faucet at the same\n * address as mainnet; suitable for the same Amoy→Polygon-style testnet→mainnet\n * verification pattern.\n */\nexport const kairos = {\n\t...viemKairos,\n\tisTestnet: true,\n\tdefaultConfirmations: 1,\n\tblockTimeMs: 1_000,\n} satisfies KawaseChain;\n","import { polygon as viemPolygon, polygonAmoy as viemPolygonAmoy } from \"viem/chains\";\nimport type { KawaseChain } from \"./types\";\n\n/**\n * Polygon mainnet — priority 1 production chain.\n *\n * Built on viem's `polygon` definition (official RPC URLs, block explorers,\n * and `POL` native currency) plus kawasekit metadata. Polygon PoS is\n * probabilistic; the default `4` confirmations ≈ ~8 s of soft finality.\n */\nexport const polygon = {\n\t...viemPolygon,\n\tisTestnet: false,\n\tdefaultConfirmations: 4,\n\tblockTimeMs: 2_000,\n} satisfies KawaseChain;\n\n/**\n * Polygon Amoy testnet — the primary kawasekit development target.\n *\n * Built on viem's `polygonAmoy` definition. JPYC is also live on Amoy at the\n * same address as mainnet; see `src/tokens/jpyc.ts`.\n */\nexport const polygonAmoy = {\n\t...viemPolygonAmoy,\n\tisTestnet: true,\n\tdefaultConfirmations: 1,\n\tblockTimeMs: 2_000,\n} satisfies KawaseChain;\n","import { avalanche, avalancheFuji } from \"./avalanche\";\nimport { ethereum, sepolia } from \"./ethereum\";\nimport { kaia, kairos } from \"./kaia\";\nimport { polygon, polygonAmoy } from \"./polygon\";\nimport { type KawaseChain, zerodevRpcUrl } from \"./types\";\n\nexport {\n\tavalanche,\n\tavalancheFuji,\n\tethereum,\n\ttype KawaseChain,\n\tkaia,\n\tkairos,\n\tpolygon,\n\tpolygonAmoy,\n\tsepolia,\n\tzerodevRpcUrl,\n};\n\n/**\n * All chains kawasekit supports, in priority order (CLAUDE.md chain priority:\n * Polygon → Kaia → Avalanche → Ethereum, each with its testnet).\n *\n * Exposed as a `readonly` tuple — **not** a `Map` — so that bundlers can\n * tree-shake chains a consumer never references.\n *\n * JPYC liveness is a separate axis (`src/tokens/jpyc.ts`): a chain can be\n * supported here while JPYC is not yet live on it (Avalanche Fuji / Sepolia).\n *\n * @example\n * ```ts\n * import { supportedChains } from \"kawasekit\";\n *\n * for (const chain of supportedChains) {\n * \tconsole.log(chain.id, chain.name);\n * }\n * ```\n */\nexport const supportedChains = [\n\tpolygon,\n\tpolygonAmoy,\n\tkaia,\n\tkairos,\n\tavalanche,\n\tavalancheFuji,\n\tethereum,\n\tsepolia,\n] as const;\n\n/**\n * Union of every chain ID kawasekit supports\n * (`137 | 80002 | 8217 | 1001 | 43114 | 43113 | 1 | 11155111`).\n *\n * Derived from {@link supportedChains}, so adding a chain there extends this\n * type automatically.\n */\nexport type SupportedChainId = (typeof supportedChains)[number][\"id\"];\n\n/** A single member of {@link supportedChains}, with its literal `id`. */\ntype SupportedChain = (typeof supportedChains)[number];\n\n/**\n * Internal chain lookup, built once at module scope.\n *\n * This `Map` is an implementation detail and is intentionally **not**\n * exported: the public API exposes the {@link supportedChains} tuple instead,\n * so importing one chain does not pull in all of them.\n */\nconst chainsById: ReadonlyMap<number, SupportedChain> = new Map(\n\tsupportedChains.map((chain) => [chain.id, chain]),\n);\n\n/**\n * Error thrown when a chain ID kawasekit does not support is requested.\n *\n * @example\n * ```ts\n * import { ChainNotSupportedError, getChain } from \"kawasekit\";\n *\n * try {\n * \tgetChain(1);\n * } catch (error) {\n * \tif (error instanceof ChainNotSupportedError) {\n * \t\tconsole.error(error.message);\n * \t}\n * }\n * ```\n */\nexport class ChainNotSupportedError extends Error {\n\tconstructor(chainId: number) {\n\t\tconst supported = supportedChains.map((chain) => chain.id).join(\", \");\n\t\tsuper(\n\t\t\t`Chain ID ${chainId} is not supported by kawasekit. ` + `Supported chain IDs: ${supported}.`,\n\t\t);\n\t\tthis.name = \"ChainNotSupportedError\";\n\t}\n}\n\n/**\n * Type guard that narrows an arbitrary chain ID to a {@link SupportedChainId}.\n *\n * @param chainId - The numeric chain ID to test.\n * @returns `true` if kawasekit supports this chain ID.\n *\n * @example\n * ```ts\n * import { isSupportedChainId } from \"kawasekit\";\n *\n * const id = 80002;\n * if (isSupportedChainId(id)) {\n * \t// `id` is now narrowed to SupportedChainId\n * }\n * ```\n */\nexport function isSupportedChainId(chainId: number): chainId is SupportedChainId {\n\treturn chainsById.has(chainId);\n}\n\n/**\n * Looks up a supported chain by its numeric chain ID.\n *\n * The returned chain's `id` is narrowed to {@link SupportedChainId}.\n *\n * @param chainId - The numeric chain ID to look up.\n * @returns The matching {@link KawaseChain}.\n * @throws {ChainNotSupportedError} If `chainId` is not supported.\n *\n * @example\n * ```ts\n * import { getChain } from \"kawasekit\";\n *\n * const chain = getChain(80002); // Polygon Amoy\n * console.log(chain.name);\n * ```\n */\nexport function getChain(chainId: number): SupportedChain {\n\tconst chain = chainsById.get(chainId);\n\tif (chain === undefined) {\n\t\tthrow new ChainNotSupportedError(chainId);\n\t}\n\treturn chain;\n}\n","/**\n * JPYC stablecoin metadata, deployments, and ABI.\n *\n * JPYC is a Japanese yen-pegged stablecoin issued by JPYC Inc. under the\n * revised Payment Services Act as 電子決済手段 (electronic payment\n * instrument). The new (\"v2\") JPYC, launched 2025-10, lives at the same\n * address on every chain where it is deployed.\n *\n * @packageDocumentation\n */\n\nimport type { Address } from \"viem\";\nimport type { SupportedChainId } from \"../chains\";\nimport {\n\tavalanche,\n\tavalancheFuji,\n\tethereum,\n\tkaia,\n\tkairos,\n\tpolygon,\n\tpolygonAmoy,\n\tsepolia,\n} from \"../chains\";\n\n/** ERC-20 decimals for JPYC. Constant across every chain. */\nexport const JPYC_DECIMALS = 18;\n\n/**\n * EIP-712 domain hint for off-chain authorization signing (EIP-3009, EIP-2612).\n *\n * The real JPYC contract does not expose `version()` publicly — it lives in an\n * `internal VERSION` state variable set during proxy initialization. The\n * canonical value is `\"1\"`, matching the FiatToken lineage; the\n * {@link signTransferWithAuthorization} helper accepts an override if a future\n * deployment changes this.\n *\n * `name` is \"JPY Coin\" — the on-chain `name()` value on every live deployment.\n */\nexport const JPYC_EIP712_DOMAIN_HINT = {\n\tname: \"JPY Coin\",\n\tversion: \"1\",\n} as const;\n\n/**\n * Address shared by every live JPYC deployment.\n *\n * Verified on:\n * - Ethereum : https://etherscan.io/token/0xE7C3D8C9a439feDe00D2600032D5dB0Be71C3c29\n * - Polygon : https://polygonscan.com/token/0xe7c3d8c9a439fede00d2600032d5db0be71c3c29\n * - Polygon Amoy : https://amoy.polygonscan.com/token/0xe7c3d8c9a439fede00d2600032d5db0be71c3c29\n * - Avalanche : https://snowtrace.io/token/0xE7C3D8C9a439feDe00D2600032D5dB0Be71C3c29\n *\n * Do NOT confuse with the legacy 前払式支払手段 JPYC at `0x431D5dFF...`.\n */\nexport const JPYC_V2_ADDRESS: Address = \"0xE7C3D8C9a439feDe00D2600032D5dB0Be71C3c29\";\n\n/** A JPYC deployment on a single chain. */\nexport interface JpycDeployment {\n\treadonly chainId: SupportedChainId;\n\treadonly address: Address;\n\t/** `true` if the token is live on this chain right now. */\n\treadonly isLive: boolean;\n}\n\n/**\n * JPYC deployments keyed by chain.\n *\n * JPYC v2 uses the **same address** (`JPYC_V2_ADDRESS`) on every chain where it\n * is live. `isLive` is the separate \"is JPYC actually deployed here yet?\" axis.\n * All eight supported chains are live at this address: the four mainnets\n * (Polygon, Kaia, Avalanche, Ethereum) + Amoy + Kairos + Avalanche Fuji +\n * Sepolia. Kaia/Kairos/Avalanche/Fuji/Sepolia were confirmed by a read-only\n * on-chain check (`name() == \"JPY Coin\"`, `symbol() == \"JPYC\"` at `0xE7C3…`,\n * 2026-05-31); Polygon/Amoy/Ethereum are established. `isLive: false` + the\n * {@link JpycNotAvailableError} path remain for any future chain added before\n * its JPYC deployment lands.\n */\nexport const jpycDeployments: { readonly [chainId in SupportedChainId]: JpycDeployment } = {\n\t[polygon.id]: { chainId: polygon.id, address: JPYC_V2_ADDRESS, isLive: true },\n\t[polygonAmoy.id]: { chainId: polygonAmoy.id, address: JPYC_V2_ADDRESS, isLive: true },\n\t[kaia.id]: { chainId: kaia.id, address: JPYC_V2_ADDRESS, isLive: true },\n\t[kairos.id]: { chainId: kairos.id, address: JPYC_V2_ADDRESS, isLive: true },\n\t[avalanche.id]: { chainId: avalanche.id, address: JPYC_V2_ADDRESS, isLive: true },\n\t[ethereum.id]: { chainId: ethereum.id, address: JPYC_V2_ADDRESS, isLive: true },\n\t[avalancheFuji.id]: { chainId: avalancheFuji.id, address: JPYC_V2_ADDRESS, isLive: true },\n\t[sepolia.id]: { chainId: sepolia.id, address: JPYC_V2_ADDRESS, isLive: true },\n};\n\n/**\n * Thrown when JPYC is not deployed on the requested chain.\n *\n * Today this is unreachable (every {@link SupportedChainId} has a live\n * deployment), but the error class is exported for future chains (Kaia) where\n * JPYC is still in development.\n */\nexport class JpycNotAvailableError extends Error {\n\tconstructor(chainId: number) {\n\t\tsuper(`JPYC is not yet deployed on chain ID ${chainId}.`);\n\t\tthis.name = \"JpycNotAvailableError\";\n\t}\n}\n\n/**\n * Returns the JPYC contract address for a kawasekit-supported chain.\n *\n * @param chainId - A {@link SupportedChainId}.\n * @returns The JPYC contract address on that chain.\n * @throws {JpycNotAvailableError} If JPYC is not live on the chain.\n *\n * @example\n * ```ts\n * import { getJpycAddress, polygonAmoy } from \"kawasekit\";\n *\n * const address = getJpycAddress(polygonAmoy.id);\n * ```\n */\nexport function getJpycAddress(chainId: SupportedChainId): Address {\n\tconst deployment = jpycDeployments[chainId];\n\tif (!deployment.isLive) {\n\t\tthrow new JpycNotAvailableError(chainId);\n\t}\n\treturn deployment.address;\n}\n\n/**\n * Minimal JPYC ABI: ERC-20 + EIP-3009 surface that kawasekit needs.\n *\n * Excludes permit / mint / blocklist / pause — kawasekit only reads balance,\n * sends `transfer()` via UserOp, and constructs / submits EIP-3009\n * authorizations. Bringing in the full FiatTokenV1 ABI would be wasted bytes.\n */\nexport const jpycAbi = [\n\t// ----- ERC-20 read -----\n\t{\n\t\ttype: \"function\",\n\t\tname: \"name\",\n\t\tstateMutability: \"view\",\n\t\tinputs: [],\n\t\toutputs: [{ name: \"\", type: \"string\" }],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"symbol\",\n\t\tstateMutability: \"view\",\n\t\tinputs: [],\n\t\toutputs: [{ name: \"\", type: \"string\" }],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"decimals\",\n\t\tstateMutability: \"view\",\n\t\tinputs: [],\n\t\toutputs: [{ name: \"\", type: \"uint8\" }],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"totalSupply\",\n\t\tstateMutability: \"view\",\n\t\tinputs: [],\n\t\toutputs: [{ name: \"\", type: \"uint256\" }],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"balanceOf\",\n\t\tstateMutability: \"view\",\n\t\tinputs: [{ name: \"account\", type: \"address\" }],\n\t\toutputs: [{ name: \"\", type: \"uint256\" }],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"allowance\",\n\t\tstateMutability: \"view\",\n\t\tinputs: [\n\t\t\t{ name: \"owner\", type: \"address\" },\n\t\t\t{ name: \"spender\", type: \"address\" },\n\t\t],\n\t\toutputs: [{ name: \"\", type: \"uint256\" }],\n\t},\n\t// ----- ERC-20 write -----\n\t{\n\t\ttype: \"function\",\n\t\tname: \"transfer\",\n\t\tstateMutability: \"nonpayable\",\n\t\tinputs: [\n\t\t\t{ name: \"to\", type: \"address\" },\n\t\t\t{ name: \"value\", type: \"uint256\" },\n\t\t],\n\t\toutputs: [{ name: \"\", type: \"bool\" }],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"transferFrom\",\n\t\tstateMutability: \"nonpayable\",\n\t\tinputs: [\n\t\t\t{ name: \"from\", type: \"address\" },\n\t\t\t{ name: \"to\", type: \"address\" },\n\t\t\t{ name: \"value\", type: \"uint256\" },\n\t\t],\n\t\toutputs: [{ name: \"\", type: \"bool\" }],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"approve\",\n\t\tstateMutability: \"nonpayable\",\n\t\tinputs: [\n\t\t\t{ name: \"spender\", type: \"address\" },\n\t\t\t{ name: \"value\", type: \"uint256\" },\n\t\t],\n\t\toutputs: [{ name: \"\", type: \"bool\" }],\n\t},\n\t// ----- EIP-3009 -----\n\t{\n\t\ttype: \"function\",\n\t\tname: \"transferWithAuthorization\",\n\t\tstateMutability: \"nonpayable\",\n\t\tinputs: [\n\t\t\t{ name: \"from\", type: \"address\" },\n\t\t\t{ name: \"to\", type: \"address\" },\n\t\t\t{ name: \"value\", type: \"uint256\" },\n\t\t\t{ name: \"validAfter\", type: \"uint256\" },\n\t\t\t{ name: \"validBefore\", type: \"uint256\" },\n\t\t\t{ name: \"nonce\", type: \"bytes32\" },\n\t\t\t{ name: \"v\", type: \"uint8\" },\n\t\t\t{ name: \"r\", type: \"bytes32\" },\n\t\t\t{ name: \"s\", type: \"bytes32\" },\n\t\t],\n\t\toutputs: [],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"receiveWithAuthorization\",\n\t\tstateMutability: \"nonpayable\",\n\t\tinputs: [\n\t\t\t{ name: \"from\", type: \"address\" },\n\t\t\t{ name: \"to\", type: \"address\" },\n\t\t\t{ name: \"value\", type: \"uint256\" },\n\t\t\t{ name: \"validAfter\", type: \"uint256\" },\n\t\t\t{ name: \"validBefore\", type: \"uint256\" },\n\t\t\t{ name: \"nonce\", type: \"bytes32\" },\n\t\t\t{ name: \"v\", type: \"uint8\" },\n\t\t\t{ name: \"r\", type: \"bytes32\" },\n\t\t\t{ name: \"s\", type: \"bytes32\" },\n\t\t],\n\t\toutputs: [],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"cancelAuthorization\",\n\t\tstateMutability: \"nonpayable\",\n\t\tinputs: [\n\t\t\t{ name: \"authorizer\", type: \"address\" },\n\t\t\t{ name: \"nonce\", type: \"bytes32\" },\n\t\t\t{ name: \"v\", type: \"uint8\" },\n\t\t\t{ name: \"r\", type: \"bytes32\" },\n\t\t\t{ name: \"s\", type: \"bytes32\" },\n\t\t],\n\t\toutputs: [],\n\t},\n\t{\n\t\ttype: \"function\",\n\t\tname: \"authorizationState\",\n\t\tstateMutability: \"view\",\n\t\tinputs: [\n\t\t\t{ name: \"authorizer\", type: \"address\" },\n\t\t\t{ name: \"nonce\", type: \"bytes32\" },\n\t\t],\n\t\toutputs: [{ name: \"\", type: \"bool\" }],\n\t},\n\t// ----- Events kawasekit needs to decode -----\n\t{\n\t\ttype: \"event\",\n\t\tname: \"Transfer\",\n\t\tinputs: [\n\t\t\t{ name: \"from\", type: \"address\", indexed: true },\n\t\t\t{ name: \"to\", type: \"address\", indexed: true },\n\t\t\t{ name: \"value\", type: \"uint256\", indexed: false },\n\t\t],\n\t},\n\t{\n\t\ttype: \"event\",\n\t\tname: \"Approval\",\n\t\tinputs: [\n\t\t\t{ name: \"owner\", type: \"address\", indexed: true },\n\t\t\t{ name: \"spender\", type: \"address\", indexed: true },\n\t\t\t{ name: \"value\", type: \"uint256\", indexed: false },\n\t\t],\n\t},\n\t{\n\t\ttype: \"event\",\n\t\tname: \"AuthorizationUsed\",\n\t\tinputs: [\n\t\t\t{ name: \"authorizer\", type: \"address\", indexed: true },\n\t\t\t{ name: \"nonce\", type: \"bytes32\", indexed: true },\n\t\t],\n\t},\n\t{\n\t\ttype: \"event\",\n\t\tname: \"AuthorizationCanceled\",\n\t\tinputs: [\n\t\t\t{ name: \"authorizer\", type: \"address\", indexed: true },\n\t\t\t{ name: \"nonce\", type: \"bytes32\", indexed: true },\n\t\t],\n\t},\n] as const;\n","/**\n * Shared recipient-allowlist normalization for the two policy paths — the\n * off-chain {@link createSpendingPolicy} (`./spending-policy`) and the on-chain\n * {@link createJpycDailyLimitPolicies} (`./daily-limit`). Keeping one normalizer\n * means both agree on what \"the same allowlist\" is: a future change (e.g.\n * rejecting the zero address) lands in one place, not two that can drift.\n *\n * @packageDocumentation\n */\n\nimport type { Address } from \"viem\";\nimport { getAddress } from \"viem\";\n\n/**\n * Checksum-normalize ({@link getAddress}) and de-duplicate an address allowlist,\n * preserving first-seen order. `getAddress` rejects a malformed address.\n *\n * This does **not** decide what an empty list means — `[]` returns `[]`. Each\n * caller owns that policy: the off-chain `SpendingPolicy` treats `[]` as\n * deny-all, while the on-chain `createJpycDailyLimitPolicies` rejects it (an\n * on-chain allowlist cannot encode \"match nothing\").\n */\nexport function normalizeRecipientAllowlist(allowlist: readonly Address[]): Address[] {\n\tconst seen = new Set<Address>();\n\tconst normalized: Address[] = [];\n\tfor (const entry of allowlist) {\n\t\tconst checksummed = getAddress(entry);\n\t\tif (!seen.has(checksummed)) {\n\t\t\tseen.add(checksummed);\n\t\t\tnormalized.push(checksummed);\n\t\t}\n\t}\n\treturn normalized;\n}\n","/**\n * Shared builder for the JPYC `transfer` callPolicy — the on-chain rule that\n * locks a ZeroDev session key to `JPYC.transfer(to, value)` with\n * `value ≤ maxPerTransfer` and an optional recipient allowlist (condition\n * `ONE_OF`). Used by BOTH {@link createJpycDailyLimitPolicies} (`./daily-limit`)\n * and {@link createBuyListPolicies} (`./buy-list`) so the recipient/amount\n * constraint is built identically; each caller composes its own rate-limit /\n * timestamp policy on top.\n *\n * @packageDocumentation\n */\n\nimport type { Policy } from \"@zerodev/permissions\";\nimport { CallPolicyVersion, ParamCondition, toCallPolicy } from \"@zerodev/permissions/policies\";\nimport type { Address } from \"viem\";\nimport { jpycAbi } from \"../tokens/jpyc\";\nimport { normalizeRecipientAllowlist } from \"./normalize-allowlist\";\n\n/** Parameters for {@link buildJpycTransferCallPolicy}. */\nexport interface JpycTransferCallPolicyParams {\n\t/** JPYC contract address on the target chain. */\n\treadonly jpycAddress: Address;\n\t/** Maximum JPYC (raw units) per single `transfer`. Must be positive. */\n\treadonly maxPerTransfer: bigint;\n\t/**\n\t * Recipient restriction. An address list constrains `to` to those recipients\n\t * (`ONE_OF`); `\"any\"` (or `undefined`) leaves it unrestricted. Entries are\n\t * checksum-normalized + de-duplicated ({@link normalizeRecipientAllowlist}).\n\t * An **empty** array throws (an on-chain allowlist cannot encode \"match\n\t * nothing\"). An address list requires `callPolicyVersion` ≥ `V0_0_2`.\n\t */\n\treadonly recipientAllowlist?: readonly Address[] | \"any\" | undefined;\n\t/** ZeroDev callPolicy on-chain version. Defaults to V0_0_4. */\n\treadonly callPolicyVersion?: CallPolicyVersion | undefined;\n}\n\n/**\n * Build the single ZeroDev callPolicy for a JPYC `transfer`, enforcing the\n * per-transfer amount cap and (optionally) the recipient allowlist. Throws on a\n * non-positive `maxPerTransfer`, an empty allowlist, or an allowlist combined\n * with `callPolicyVersion` `V0_0_1` (which lacks `ONE_OF`).\n */\nexport function buildJpycTransferCallPolicy(params: JpycTransferCallPolicyParams): Policy {\n\tif (params.maxPerTransfer <= 0n) {\n\t\tthrow new Error(`maxPerTransfer must be positive, got ${params.maxPerTransfer}.`);\n\t}\n\t// Resolve the recipient constraint up-front. Omitted or \"any\" => unrestricted\n\t// (a `null` arg); an address list => checksum-normalized + de-duped (shared\n\t// with the off-chain SpendingPolicy). Unlike off-chain, an empty list is a\n\t// caller bug here — an on-chain allowlist cannot encode \"deny all\".\n\tconst recipients =\n\t\tparams.recipientAllowlist === undefined || params.recipientAllowlist === \"any\"\n\t\t\t? null\n\t\t\t: normalizeRecipientAllowlist(params.recipientAllowlist);\n\tif (recipients !== null && recipients.length === 0) {\n\t\tthrow new Error(\n\t\t\t'recipientAllowlist must not be empty — omit it or pass \"any\" to allow any recipient.',\n\t\t);\n\t}\n\t// The ONE_OF condition (used to encode an address list) is only supported by\n\t// the V0_0_2+ CallPolicy contract; catch the incompatible combination here\n\t// with a typed message rather than a bare error from deep inside toCallPolicy.\n\tif (recipients !== null && params.callPolicyVersion === CallPolicyVersion.V0_0_1) {\n\t\tthrow new Error(\n\t\t\t\"recipientAllowlist requires callPolicyVersion V0_0_2 or later (the ONE_OF condition is unsupported on V0_0_1).\",\n\t\t);\n\t}\n\n\treturn 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 (`to`): unrestricted (`null`) unless an allowlist resolved\n\t\t\t\t\t// above, in which case it is constrained via the ONE_OF condition.\n\t\t\t\t\trecipients === null ? null : { condition: ParamCondition.ONE_OF, value: recipients },\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","/**\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`, and — when {@link\n * CreateJpycDailyLimitPoliciesParams.recipientAllowlist} is provided —\n * restricts `to` to the allowlisted recipients (otherwise any recipient is\n * allowed). This is the on-chain enforcement behind the \"pay only registered\n * merchants\" model: a buy-list resolves to its merchants' addresses, which\n * are baked into a disposable session key here.\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 { type CallPolicyVersion, toRateLimitPolicy } from \"@zerodev/permissions/policies\";\nimport type { Address } from \"viem\";\nimport { buildJpycTransferCallPolicy } from \"./jpyc-call-policy\";\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\t/**\n\t * Recipient restriction. An address list restricts the session key to\n\t * `transfer` JPYC only to those recipients (enforced on-chain via the\n\t * callPolicy `to` argument, condition `ONE_OF`); every other recipient is\n\t * rejected before any funds move. `\"any\"` (or omitting the field) leaves the\n\t * recipient unrestricted.\n\t *\n\t * The type mirrors the off-chain {@link SpendingPolicy.recipientAllowlist}\n\t * (`Address[] | \"any\"`) so a buy-list's resolved allowlist can feed both the\n\t * off-chain and on-chain policy paths unchanged. Two **deliberate** differences\n\t * from that sibling, forced by on-chain semantics:\n\t * - it is **optional** here (omitted = `\"any\"`) for backward compatibility —\n\t * the pre-allowlist policy left the recipient unrestricted;\n\t * - an **empty** array `[]` **throws** (rather than meaning deny-all as it does\n\t * off-chain) — an on-chain allowlist cannot encode \"match nothing\"; omit it\n\t * or pass `\"any\"` for unrestricted, or list ≥1 recipient.\n\t *\n\t * Entries are checksum-normalized and de-duplicated (shared with the off-chain\n\t * path via {@link normalizeRecipientAllowlist}). An address list requires\n\t * `callPolicyVersion` ≥ `V0_0_2` (the `ONE_OF` condition is unsupported on\n\t * `V0_0_1`); the default `V0_0_4` is fine.\n\t */\n\treadonly recipientAllowlist?: readonly Address[] | \"any\";\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 *\n * @example Restrict the session key to a buy-list's merchants only\n * ```ts\n * const policies = createJpycDailyLimitPolicies({\n * jpycAddress: getJpycAddress(polygonAmoy.id),\n * maxPerTransfer: parseUnits(\"100\", JPYC_DECIMALS),\n * maxTransfersPerDay: 5,\n * // on-chain: any transfer to a non-allowlisted address reverts before funds move\n * recipientAllowlist: [merchantA, merchantB],\n * });\n * ```\n */\nexport function createJpycDailyLimitPolicies(\n\tparams: CreateJpycDailyLimitPoliciesParams,\n): readonly [Policy, Policy] {\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\t// callPolicy (amount cap + optional recipient allowlist) is the shared builder;\n\t// this function adds the daily-window rate limit on top.\n\tconst callPolicy = buildJpycTransferCallPolicy({\n\t\tjpycAddress: params.jpycAddress,\n\t\tmaxPerTransfer: params.maxPerTransfer,\n\t\trecipientAllowlist: params.recipientAllowlist,\n\t\tcallPolicyVersion: params.callPolicyVersion,\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","/**\n * Spending policy — policy-as-data for the x402 / EIP-3009 PolicyGatedSigner\n * (M6). One declarative {@link SpendingPolicy} (session + expiry, per-token\n * `maxPerSign` + cumulative cap, recipient allowlist, `revoked`) and one pure,\n * deny-closed evaluator {@link evaluateSpendingPolicy}.\n *\n * The same specification is enforced SDK-side (the `local` adapter) and, for the\n * `mpc-2p` adapter, re-implemented backend-side in Rust (the `kawasekit-mpc-2p`\n * co-signer); a shared conformance corpus\n * (`__fixtures__/spending-policy.vectors.json`) keeps the two in lockstep.\n * The evaluator is **check-only** — it reads `SpendState` and never mutates it;\n * the cumulative-cap *commit* (folding a successful spend back in via\n * {@link mergeSpendState}) is the adapter's job, and atomic+authoritative\n * commit is a property of the `cryptographic` adapter only.\n *\n * This is the **x402-EOA** policy path. The smart-account / ZeroDev session-key\n * path is `createJpycDailyLimitPolicies` (`./daily-limit`) — a sibling, not a\n * replacement.\n *\n * @packageDocumentation\n */\n\nimport type { Address } from \"viem\";\nimport { getAddress } from \"viem\";\nimport type { PaymentIntent, PolicyRejection } from \"../signer/types\";\nimport { normalizeRecipientAllowlist } from \"./normalize-allowlist\";\n\n/** Per-token spend limits. A token absent from the policy's `perToken` is NOT allowed. */\nexport interface TokenLimit {\n\treadonly token: Address;\n\t/** Max value per single signature, token base units. Generalizes `maxAmountPerSign` (threat 1.14). */\n\treadonly maxPerSign: bigint;\n\t/** Optional total across the session. `undefined` = uncapped. MUST be `>= maxPerSign`. */\n\treadonly cumulativeCap?: bigint;\n}\n\n/**\n * Policy-as-data evaluated for every {@link PaymentIntent}. Deny-closed\n * throughout: a token not listed in `perToken` is rejected, and\n * `recipientAllowlist` is **required** — `\"any\"` (unrestricted) is a conscious,\n * greppable choice, never a silent default.\n */\nexport interface SpendingPolicy {\n\treadonly version: \"1\";\n\t/** Session id + expiry (unix seconds). An authorization may not outlive the session. */\n\treadonly session: { readonly id: string; readonly notAfter: bigint };\n\treadonly perToken: readonly TokenLimit[];\n\t/**\n\t * Recipient restriction (**required** — no silent allow-open default):\n\t * `\"any\"` = unrestricted, `[]` = deny-all, `[...]` = allowlist. Making\n\t * `\"any\"` explicit keeps the policy deny-closed like `perToken`.\n\t *\n\t * The on-chain {@link createJpycDailyLimitPolicies} takes the same\n\t * `Address[] | \"any\"` shape, with two on-chain-forced differences: it is\n\t * optional (omitted = `\"any\"`), and `[]` throws there (an on-chain allowlist\n\t * cannot encode deny-all).\n\t */\n\treadonly recipientAllowlist: readonly Address[] | \"any\";\n\treadonly revoked: boolean;\n}\n\n/**\n * Cross-call cumulative spend, per token. Injected into the evaluator (never a\n * module global). For the `local` adapter this is a single-process, caller-managed\n * **read-only view**; the authoritative ledger lives in the `cryptographic`\n * adapter's backend.\n */\nexport interface SpendState {\n\treadonly spentPerToken: readonly { readonly token: Address; readonly spent: bigint }[];\n}\n\n/** The outcome of {@link evaluateSpendingPolicy}. */\nexport type PolicyDecision =\n\t| { readonly ok: true }\n\t| { readonly ok: false; readonly rejection: PolicyRejection };\n\n/** Thrown by {@link createSpendingPolicy} on a malformed policy. */\nexport class SpendingPolicyConfigError extends Error {\n\treadonly field: string;\n\treadonly reason: string;\n\n\tconstructor(field: string, reason: string, options?: { cause?: unknown }) {\n\t\tsuper(`Invalid SpendingPolicy (${field}): ${reason}`, options);\n\t\tthis.name = \"SpendingPolicyConfigError\";\n\t\tthis.field = field;\n\t\tthis.reason = reason;\n\t}\n}\n\nfunction deny(reason: PolicyRejection[\"reason\"], detail: string): PolicyDecision {\n\treturn { ok: false, rejection: { reason, detail } };\n}\n\n/**\n * Evaluate a {@link SpendingPolicy} against a decoded {@link PaymentIntent}.\n *\n * Pure, deterministic, no I/O. Deny-closed; the first failing check wins. All\n * amount comparisons are `bigint`; all address equality uses `getAddress()` on\n * both sides. **Reads `state`, never mutates it** — see {@link mergeSpendState}.\n * `detail` strings never contain the nonce or any signature.\n *\n * @example\n * ```ts\n * const decision = evaluateSpendingPolicy(policy, intent, state, BigInt(Math.floor(Date.now() / 1000)));\n * if (!decision.ok) console.warn(decision.rejection.reason);\n * ```\n */\nexport function evaluateSpendingPolicy(\n\tpolicy: SpendingPolicy,\n\tintent: PaymentIntent,\n\tstate: SpendState,\n\tnowSeconds: bigint,\n): PolicyDecision {\n\tif (policy.revoked) {\n\t\treturn deny(\"revoked\", \"the spending policy has been revoked\");\n\t}\n\tif (nowSeconds > policy.session.notAfter) {\n\t\treturn deny(\"expired\", `session expired at ${policy.session.notAfter} (now ${nowSeconds})`);\n\t}\n\tif (intent.validBefore > policy.session.notAfter) {\n\t\treturn deny(\n\t\t\t\"expired\",\n\t\t\t`authorization validBefore ${intent.validBefore} outlives the session (notAfter ${policy.session.notAfter})`,\n\t\t);\n\t}\n\n\tconst intentToken = getAddress(intent.token);\n\tconst limit = policy.perToken.find((l) => getAddress(l.token) === intentToken);\n\tif (limit === undefined) {\n\t\treturn deny(\"token_not_allowed\", `token ${intentToken} is not in the policy`);\n\t}\n\n\tif (policy.recipientAllowlist !== \"any\") {\n\t\tconst to = getAddress(intent.to);\n\t\tconst allowed = policy.recipientAllowlist.some((a) => getAddress(a) === to);\n\t\tif (!allowed) {\n\t\t\treturn deny(\"recipient_not_allowed\", `recipient ${to} is not on the allowlist`);\n\t\t}\n\t}\n\n\tif (intent.value > limit.maxPerSign) {\n\t\treturn deny(\n\t\t\t\"amount_exceeds_per_sign\",\n\t\t\t`value ${intent.value} exceeds maxPerSign ${limit.maxPerSign}`,\n\t\t);\n\t}\n\n\tif (limit.cumulativeCap !== undefined) {\n\t\tconst spent = state.spentPerToken.find((s) => getAddress(s.token) === intentToken)?.spent ?? 0n;\n\t\tif (spent + intent.value > limit.cumulativeCap) {\n\t\t\treturn deny(\n\t\t\t\t\"amount_exceeds_cumulative\",\n\t\t\t\t`spent ${spent} + value ${intent.value} exceeds cumulativeCap ${limit.cumulativeCap}`,\n\t\t\t);\n\t\t}\n\t}\n\n\treturn { ok: true };\n}\n\n/** Parameters for {@link createSpendingPolicy}. */\nexport interface CreateSpendingPolicyParams {\n\treadonly session: { readonly id: string; readonly notAfter: bigint };\n\treadonly perToken: readonly TokenLimit[];\n\t/** Required: `\"any\"` (unrestricted), `[]` (deny-all), or an allowlist. No silent default. */\n\treadonly recipientAllowlist: readonly Address[] | \"any\";\n\t/** Defaults to `false`. */\n\treadonly revoked?: boolean;\n}\n\n/**\n * Validate + normalize a {@link SpendingPolicy}. Checksums all addresses\n * (`getAddress`), de-dupes the recipient allowlist (shared\n * {@link normalizeRecipientAllowlist}; `[]` stays deny-all), rejects an empty\n * `perToken` (deny-closed), a non-positive `maxPerSign`/`cumulativeCap`, a\n * `cumulativeCap < maxPerSign`, and duplicate tokens. Throws\n * {@link SpendingPolicyConfigError} on violation.\n *\n * @example\n * ```ts\n * const policy = createSpendingPolicy({\n * session: { id: conversationId, notAfter: BigInt(deadline) },\n * perToken: [{ token: JPYC, maxPerSign: 1_000n, cumulativeCap: 10_000n }],\n * recipientAllowlist: [merchant],\n * });\n * ```\n */\nexport function createSpendingPolicy(params: CreateSpendingPolicyParams): SpendingPolicy {\n\tif (typeof params.session.id !== \"string\" || params.session.id === \"\") {\n\t\tthrow new SpendingPolicyConfigError(\"session.id\", \"must be a non-empty string\");\n\t}\n\tif (params.session.notAfter <= 0n) {\n\t\tthrow new SpendingPolicyConfigError(\n\t\t\t\"session.notAfter\",\n\t\t\t`must be a positive unix-seconds bigint, got ${params.session.notAfter}`,\n\t\t);\n\t}\n\tif (params.perToken.length === 0) {\n\t\tthrow new SpendingPolicyConfigError(\n\t\t\t\"perToken\",\n\t\t\t\"must list at least one token (the policy is deny-closed)\",\n\t\t);\n\t}\n\n\tconst seen = new Set<string>();\n\tconst perToken: readonly TokenLimit[] = params.perToken.map((l) => {\n\t\tconst token = getAddress(l.token);\n\t\tif (seen.has(token)) {\n\t\t\tthrow new SpendingPolicyConfigError(\"perToken\", `duplicate token ${token}`);\n\t\t}\n\t\tseen.add(token);\n\t\tif (l.maxPerSign <= 0n) {\n\t\t\tthrow new SpendingPolicyConfigError(\n\t\t\t\t\"perToken.maxPerSign\",\n\t\t\t\t`must be positive, got ${l.maxPerSign} for ${token}`,\n\t\t\t);\n\t\t}\n\t\tif (l.cumulativeCap !== undefined) {\n\t\t\tif (l.cumulativeCap <= 0n) {\n\t\t\t\tthrow new SpendingPolicyConfigError(\n\t\t\t\t\t\"perToken.cumulativeCap\",\n\t\t\t\t\t`must be positive, got ${l.cumulativeCap} for ${token}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (l.cumulativeCap < l.maxPerSign) {\n\t\t\t\tthrow new SpendingPolicyConfigError(\n\t\t\t\t\t\"perToken.cumulativeCap\",\n\t\t\t\t\t`cumulativeCap (${l.cumulativeCap}) must be >= maxPerSign (${l.maxPerSign}) for ${token}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn { token, maxPerSign: l.maxPerSign, cumulativeCap: l.cumulativeCap };\n\t\t}\n\t\treturn { token, maxPerSign: l.maxPerSign };\n\t});\n\n\t// Checksum-normalize + de-dupe the allowlist (shared with the on-chain\n\t// daily-limit path). `[]` stays `[]` — deny-all is a valid off-chain policy.\n\tconst recipientAllowlist =\n\t\tparams.recipientAllowlist === \"any\"\n\t\t\t? \"any\"\n\t\t\t: normalizeRecipientAllowlist(params.recipientAllowlist);\n\n\treturn {\n\t\tversion: \"1\",\n\t\tsession: { id: params.session.id, notAfter: params.session.notAfter },\n\t\tperToken,\n\t\trecipientAllowlist,\n\t\trevoked: params.revoked ?? false,\n\t};\n}\n\n/**\n * Fold a successful spend back into a {@link SpendState} (pure; returns a new\n * state). The caller of the `local` adapter uses this to keep `cumulativeCap`\n * meaningful across calls — `local` does not own an authoritative ledger.\n */\nexport function mergeSpendState(\n\tstate: SpendState,\n\tspend: { readonly token: Address; readonly value: bigint },\n): SpendState {\n\tconst token = getAddress(spend.token);\n\tconst exists = state.spentPerToken.some((s) => getAddress(s.token) === token);\n\tconst spentPerToken = exists\n\t\t? state.spentPerToken.map((s) =>\n\t\t\t\tgetAddress(s.token) === token ? { token, spent: s.spent + spend.value } : s,\n\t\t\t)\n\t\t: [...state.spentPerToken, { token, spent: spend.value }];\n\treturn { spentPerToken };\n}\n"]}
|
package/dist/policy/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { ONE_DAY_SECONDS, createJpycDailyLimitPolicies } from '../chunk-
|
|
1
|
+
export { ONE_DAY_SECONDS, createJpycDailyLimitPolicies } from '../chunk-UIDDRHLW.js';
|
|
2
2
|
export { SpendingPolicyConfigError, createSpendingPolicy, evaluateSpendingPolicy, mergeSpendState } from '../chunk-7YKRKV6D.js';
|
|
3
3
|
import '../chunk-KT7XDT2T.js';
|
|
4
4
|
import '../chunk-SOTYGX67.js';
|
package/package.json
CHANGED
package/dist/chunk-RJLDKDWL.js
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { getJpycAddress, jpycAbi } from './chunk-KT7XDT2T.js';
|
|
2
|
-
import { isSupportedChainId } from './chunk-SOTYGX67.js';
|
|
3
|
-
import { isAddress, encodeFunctionData } from 'viem';
|
|
4
|
-
|
|
5
|
-
var TransferJpycInputError = class extends Error {
|
|
6
|
-
constructor(message) {
|
|
7
|
-
super(`transferJpyc: ${message}`);
|
|
8
|
-
this.name = "TransferJpycInputError";
|
|
9
|
-
}
|
|
10
|
-
};
|
|
11
|
-
async function transferJpyc(kernelClient, params) {
|
|
12
|
-
if (!isAddress(params.to, { strict: false })) {
|
|
13
|
-
throw new TransferJpycInputError(`\`to\` is not a valid address: ${params.to}`);
|
|
14
|
-
}
|
|
15
|
-
if (params.amount <= 0n) {
|
|
16
|
-
throw new TransferJpycInputError(`\`amount\` must be positive, got ${params.amount}.`);
|
|
17
|
-
}
|
|
18
|
-
const chainId = kernelClient.chain.id;
|
|
19
|
-
if (!isSupportedChainId(chainId)) {
|
|
20
|
-
throw new TransferJpycInputError(`Chain ID ${chainId} is not a kawasekit-supported chain.`);
|
|
21
|
-
}
|
|
22
|
-
const jpycAddress = getJpycAddress(chainId);
|
|
23
|
-
const data = encodeFunctionData({
|
|
24
|
-
abi: jpycAbi,
|
|
25
|
-
functionName: "transfer",
|
|
26
|
-
args: [params.to, params.amount]
|
|
27
|
-
});
|
|
28
|
-
const callData = await kernelClient.account.encodeCalls([{ to: jpycAddress, value: 0n, data }]);
|
|
29
|
-
const userOpHash = await kernelClient.sendUserOperation({ callData });
|
|
30
|
-
if (params.waitForReceipt === false) {
|
|
31
|
-
return { userOpHash, transactionHash: null, success: null };
|
|
32
|
-
}
|
|
33
|
-
const receipt = await kernelClient.waitForUserOperationReceipt({ hash: userOpHash });
|
|
34
|
-
return {
|
|
35
|
-
userOpHash,
|
|
36
|
-
transactionHash: receipt.receipt.transactionHash,
|
|
37
|
-
success: receipt.success
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export { TransferJpycInputError, transferJpyc };
|
|
42
|
-
//# sourceMappingURL=chunk-RJLDKDWL.js.map
|
|
43
|
-
//# sourceMappingURL=chunk-RJLDKDWL.js.map
|