kawasekit 0.1.0-beta.5 → 0.1.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.
@@ -1,5 +1,5 @@
1
1
  import { PolicyGatedSignerConfigError, resolveAssetParam, signTransferWithAuthorization } from './chunk-VPRR3TNA.js';
2
- import { evaluateSpendingPolicy } from './chunk-MTMJNYOD.js';
2
+ import { evaluateSpendingPolicy } from './chunk-YMABXRCK.js';
3
3
  import { getAddress } from 'viem';
4
4
 
5
5
  function createLocalPolicyGatedSigner(params) {
@@ -72,5 +72,5 @@ function createLocalPolicyGatedSigner(params) {
72
72
  }
73
73
 
74
74
  export { createLocalPolicyGatedSigner };
75
- //# sourceMappingURL=chunk-DYTONQW2.js.map
76
- //# sourceMappingURL=chunk-DYTONQW2.js.map
75
+ //# sourceMappingURL=chunk-RUWCCP37.js.map
76
+ //# sourceMappingURL=chunk-RUWCCP37.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/signer/local.ts"],"names":[],"mappings":";;;;AAgEO,SAAS,6BACf,MAAA,EACgC;AAChC,EAAA,IAAI,MAAA,CAAO,wBAAwB,IAAA,EAAM;AACxC,IAAA,MAAM,IAAI,4BAAA;AAAA,MACT,qBAAA;AAAA,MACA;AAAA,KACD;AAAA,EACD;AAEA,EAAA,MAAM,EAAE,OAAA,EAAS,MAAA,EAAQ,UAAA,EAAW,GAAI,MAAA;AACxC,EAAA,MAAM,MAAA,GAAS,iBAAA,CAAkB,MAAA,CAAO,KAAK,CAAA;AAC7C,EAAA,MAAM,IAAA,GAAO,UAAA,CAAW,OAAA,CAAQ,OAAO,CAAA;AAEvC,EAAA,OAAO;AAAA,IACN,WAAA,EAAa,UAAA;AAAA,IACb,IAAA;AAAA,IACA,MAAM,KAAK,MAAA,EAA4C;AACtD,MAAA,IAAI,UAAA,CAAW,MAAA,CAAO,IAAI,CAAA,KAAM,IAAA,EAAM;AACrC,QAAA,OAAO;AAAA,UACN,EAAA,EAAI,KAAA;AAAA,UACJ,SAAA,EAAW;AAAA,YACV,MAAA,EAAQ,eAAA;AAAA,YACR,QAAQ,CAAA,YAAA,EAAe,UAAA,CAAW,OAAO,IAAI,CAAC,+BAA+B,IAAI,CAAA;AAAA;AAClF,SACD;AAAA,MACD;AACA,MAAA,IAAI,UAAA,CAAW,MAAA,CAAO,KAAK,CAAA,KAAM,OAAO,iBAAA,EAAmB;AAC1D,QAAA,OAAO;AAAA,UACN,EAAA,EAAI,KAAA;AAAA,UACJ,SAAA,EAAW;AAAA,YACV,MAAA,EAAQ,mBAAA;AAAA,YACR,MAAA,EAAQ,gBAAgB,UAAA,CAAW,MAAA,CAAO,KAAK,CAAC,CAAA,sDAAA,EAAyD,OAAO,iBAAiB,CAAA;AAAA;AAClI,SACD;AAAA,MACD;AAEA,MAAA,MAAM,QAAqB,MAAM,UAAA,QAAmB,EAAE,aAAA,EAAe,EAAC,EAAE;AACxE,MAAA,MAAM,UAAA,GAAa,OAAO,IAAA,CAAK,KAAA,CAAM,KAAK,GAAA,EAAI,GAAI,GAAI,CAAC,CAAA;AACvD,MAAA,MAAM,QAAA,GAAW,sBAAA,CAAuB,MAAA,EAAQ,MAAA,EAAQ,OAAO,UAAU,CAAA;AACzE,MAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AACjB,QAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,SAAA,EAAW,SAAS,SAAA,EAAU;AAAA,MACnD;AAEA,MAAA,MAAM,SAAS,MAAM,6BAAA;AAAA,QACpB,OAAA;AAAA,QACA;AAAA,UACC,MAAM,MAAA,CAAO,IAAA;AAAA,UACb,SAAS,MAAA,CAAO,OAAA;AAAA,UAChB,SAAS,MAAA,CAAO,OAAA;AAAA,UAChB,mBAAmB,MAAA,CAAO;AAAA,SAC3B;AAAA,QACA;AAAA,UACC,IAAA;AAAA,UACA,IAAI,MAAA,CAAO,EAAA;AAAA,UACX,OAAO,MAAA,CAAO,KAAA;AAAA,UACd,YAAY,MAAA,CAAO,UAAA;AAAA,UACnB,aAAa,MAAA,CAAO,WAAA;AAAA,UACpB,OAAO,MAAA,CAAO;AAAA;AACf,OACD;AACA,MAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,SAAA,EAAW,MAAA,CAAO,WAAW,MAAA,EAAO;AAAA,IACxD,CAAA;AAAA,IACA,QAAA,GAA8B;AAC7B,MAAA,OAAO;AAAA,QACN,WAAA,EAAa,UAAA;AAAA,QACb,IAAA;AAAA,QACA,QAAA,EAAU,OAAO,OAAA,CAAQ,EAAA;AAAA,QACzB,QAAA,EAAU,OAAO,OAAA,CAAQ,QAAA;AAAA,QACzB,SAAS,MAAA,CAAO;AAAA,OACjB;AAAA,IACD;AAAA,GACD;AACD","file":"chunk-DYTONQW2.js","sourcesContent":["/**\n * The `local` PolicyGatedSigner adapter — `enforcement: \"advisory\"`.\n *\n * Wraps a viem {@link Account} + a {@link SpendingPolicy} + a pinned EIP-712\n * domain. `sign(intent)` evaluates the policy SDK-side and, on pass, produces a\n * real EIP-3009 authorization via {@link signTransferWithAuthorization}. It is\n * **advisory** because the wrapped key can still sign anything elsewhere — the\n * gate is only reached if the caller chooses to call *this* `sign()`. Use it for\n * dev, the A1 cross-language fallback, and any flow that is explicitly not\n * bounded/regulated; the type-gate (`requireNonBypassable`) keeps it out of\n * flows that require non-bypassable enforcement.\n *\n * @packageDocumentation\n */\n\nimport type { Account } from \"viem\";\nimport { getAddress } from \"viem\";\nimport type { SpendingPolicy, SpendState } from \"../policy/spending-policy\";\nimport { evaluateSpendingPolicy } from \"../policy/spending-policy\";\nimport type { X402AssetParam } from \"../tokens/asset-domain\";\nimport { resolveAssetParam } from \"../tokens/asset-domain\";\nimport { signTransferWithAuthorization } from \"../tokens/eip3009\";\nimport { PolicyGatedSignerConfigError } from \"./errors\";\nimport type { PaymentIntent, PolicyGatedSigner, SignerDescription, SignResult } from \"./types\";\n\n/** Parameters for {@link createLocalPolicyGatedSigner}. */\nexport interface CreateLocalPolicyGatedSignerParams {\n\t/** EOA / LocalAccount that signs the EIP-3009 authorization. */\n\treadonly account: Account;\n\t/** The spending policy this signer enforces (SDK-side, advisory). */\n\treadonly policy: SpendingPolicy;\n\t/** Asset binding — pins the EIP-712 domain `name`/`version`/`verifyingContract`. */\n\treadonly asset: X402AssetParam;\n\t/**\n\t * Required literal acknowledgement that this signer is **advisory** (a\n\t * key-holder can bypass its policy). Omitting it is a compile error (TS) and\n\t * a construction-time throw (JS) — so constructing an advisory signer is a\n\t * conscious, greppable act. For bounded/regulated flows use a cryptographic\n\t * adapter instead.\n\t */\n\treadonly acknowledgeAdvisory: true;\n\t/**\n\t * Optional cumulative-spend view (read-only) the adapter evaluates\n\t * `cumulativeCap` against. `local` does not own an authoritative ledger; the\n\t * caller folds a successful spend back in (e.g. via `mergeSpendState`) before\n\t * the next call. Default: empty.\n\t */\n\treadonly spendState?: () => SpendState | Promise<SpendState>;\n}\n\n/**\n * Construct a `local` (advisory) PolicyGatedSigner.\n *\n * @example\n * ```ts\n * const signer = createLocalPolicyGatedSigner({\n * account,\n * policy: createSpendingPolicy({ session: { id, notAfter }, perToken: [{ token: JPYC, maxPerSign: 1_000n }] }),\n * asset: { kind: \"known\", id: \"jpyc-v2\" },\n * acknowledgeAdvisory: true,\n * });\n * const result = await signer.sign(intent);\n * ```\n */\nexport function createLocalPolicyGatedSigner(\n\tparams: CreateLocalPolicyGatedSignerParams,\n): PolicyGatedSigner<\"advisory\"> {\n\tif (params.acknowledgeAdvisory !== true) {\n\t\tthrow new PolicyGatedSignerConfigError(\n\t\t\t\"acknowledgeAdvisory\",\n\t\t\t\"a local signer is advisory (a key-holder can bypass its policy); pass `acknowledgeAdvisory: true` to construct one consciously, or use a cryptographic adapter for bounded/regulated flows\",\n\t\t);\n\t}\n\n\tconst { account, policy, spendState } = params;\n\tconst pinned = resolveAssetParam(params.asset);\n\tconst from = getAddress(account.address);\n\n\treturn {\n\t\tenforcement: \"advisory\",\n\t\tfrom,\n\t\tasync sign(intent: PaymentIntent): Promise<SignResult> {\n\t\t\tif (getAddress(intent.from) !== from) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\trejection: {\n\t\t\t\t\t\treason: \"from_mismatch\",\n\t\t\t\t\t\tdetail: `intent.from ${getAddress(intent.from)} does not equal signer.from ${from}`,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (getAddress(intent.token) !== pinned.verifyingContract) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\trejection: {\n\t\t\t\t\t\treason: \"token_not_allowed\",\n\t\t\t\t\t\tdetail: `intent.token ${getAddress(intent.token)} does not equal the signer's pinned verifyingContract ${pinned.verifyingContract}`,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst state: SpendState = (await spendState?.()) ?? { spentPerToken: [] };\n\t\t\tconst nowSeconds = BigInt(Math.floor(Date.now() / 1000));\n\t\t\tconst decision = evaluateSpendingPolicy(policy, intent, state, nowSeconds);\n\t\t\tif (!decision.ok) {\n\t\t\t\treturn { ok: false, rejection: decision.rejection };\n\t\t\t}\n\n\t\t\tconst signed = await signTransferWithAuthorization(\n\t\t\t\taccount,\n\t\t\t\t{\n\t\t\t\t\tname: pinned.name,\n\t\t\t\t\tversion: pinned.version,\n\t\t\t\t\tchainId: intent.chainId,\n\t\t\t\t\tverifyingContract: pinned.verifyingContract,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tfrom,\n\t\t\t\t\tto: intent.to,\n\t\t\t\t\tvalue: intent.value,\n\t\t\t\t\tvalidAfter: intent.validAfter,\n\t\t\t\t\tvalidBefore: intent.validBefore,\n\t\t\t\t\tnonce: intent.nonce,\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn { ok: true, signature: signed.signature, intent };\n\t\t},\n\t\tdescribe(): SignerDescription {\n\t\t\treturn {\n\t\t\t\tenforcement: \"advisory\",\n\t\t\t\tfrom,\n\t\t\t\tpolicyId: policy.session.id,\n\t\t\t\tnotAfter: policy.session.notAfter,\n\t\t\t\trevoked: policy.revoked,\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"sources":["../src/signer/local.ts"],"names":[],"mappings":";;;;AAgEO,SAAS,6BACf,MAAA,EACgC;AAChC,EAAA,IAAI,MAAA,CAAO,wBAAwB,IAAA,EAAM;AACxC,IAAA,MAAM,IAAI,4BAAA;AAAA,MACT,qBAAA;AAAA,MACA;AAAA,KACD;AAAA,EACD;AAEA,EAAA,MAAM,EAAE,OAAA,EAAS,MAAA,EAAQ,UAAA,EAAW,GAAI,MAAA;AACxC,EAAA,MAAM,MAAA,GAAS,iBAAA,CAAkB,MAAA,CAAO,KAAK,CAAA;AAC7C,EAAA,MAAM,IAAA,GAAO,UAAA,CAAW,OAAA,CAAQ,OAAO,CAAA;AAEvC,EAAA,OAAO;AAAA,IACN,WAAA,EAAa,UAAA;AAAA,IACb,IAAA;AAAA,IACA,MAAM,KAAK,MAAA,EAA4C;AACtD,MAAA,IAAI,UAAA,CAAW,MAAA,CAAO,IAAI,CAAA,KAAM,IAAA,EAAM;AACrC,QAAA,OAAO;AAAA,UACN,EAAA,EAAI,KAAA;AAAA,UACJ,SAAA,EAAW;AAAA,YACV,MAAA,EAAQ,eAAA;AAAA,YACR,QAAQ,CAAA,YAAA,EAAe,UAAA,CAAW,OAAO,IAAI,CAAC,+BAA+B,IAAI,CAAA;AAAA;AAClF,SACD;AAAA,MACD;AACA,MAAA,IAAI,UAAA,CAAW,MAAA,CAAO,KAAK,CAAA,KAAM,OAAO,iBAAA,EAAmB;AAC1D,QAAA,OAAO;AAAA,UACN,EAAA,EAAI,KAAA;AAAA,UACJ,SAAA,EAAW;AAAA,YACV,MAAA,EAAQ,mBAAA;AAAA,YACR,MAAA,EAAQ,gBAAgB,UAAA,CAAW,MAAA,CAAO,KAAK,CAAC,CAAA,sDAAA,EAAyD,OAAO,iBAAiB,CAAA;AAAA;AAClI,SACD;AAAA,MACD;AAEA,MAAA,MAAM,QAAqB,MAAM,UAAA,QAAmB,EAAE,aAAA,EAAe,EAAC,EAAE;AACxE,MAAA,MAAM,UAAA,GAAa,OAAO,IAAA,CAAK,KAAA,CAAM,KAAK,GAAA,EAAI,GAAI,GAAI,CAAC,CAAA;AACvD,MAAA,MAAM,QAAA,GAAW,sBAAA,CAAuB,MAAA,EAAQ,MAAA,EAAQ,OAAO,UAAU,CAAA;AACzE,MAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AACjB,QAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,SAAA,EAAW,SAAS,SAAA,EAAU;AAAA,MACnD;AAEA,MAAA,MAAM,SAAS,MAAM,6BAAA;AAAA,QACpB,OAAA;AAAA,QACA;AAAA,UACC,MAAM,MAAA,CAAO,IAAA;AAAA,UACb,SAAS,MAAA,CAAO,OAAA;AAAA,UAChB,SAAS,MAAA,CAAO,OAAA;AAAA,UAChB,mBAAmB,MAAA,CAAO;AAAA,SAC3B;AAAA,QACA;AAAA,UACC,IAAA;AAAA,UACA,IAAI,MAAA,CAAO,EAAA;AAAA,UACX,OAAO,MAAA,CAAO,KAAA;AAAA,UACd,YAAY,MAAA,CAAO,UAAA;AAAA,UACnB,aAAa,MAAA,CAAO,WAAA;AAAA,UACpB,OAAO,MAAA,CAAO;AAAA;AACf,OACD;AACA,MAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,SAAA,EAAW,MAAA,CAAO,WAAW,MAAA,EAAO;AAAA,IACxD,CAAA;AAAA,IACA,QAAA,GAA8B;AAC7B,MAAA,OAAO;AAAA,QACN,WAAA,EAAa,UAAA;AAAA,QACb,IAAA;AAAA,QACA,QAAA,EAAU,OAAO,OAAA,CAAQ,EAAA;AAAA,QACzB,QAAA,EAAU,OAAO,OAAA,CAAQ,QAAA;AAAA,QACzB,SAAS,MAAA,CAAO;AAAA,OACjB;AAAA,IACD;AAAA,GACD;AACD","file":"chunk-RUWCCP37.js","sourcesContent":["/**\n * The `local` PolicyGatedSigner adapter — `enforcement: \"advisory\"`.\n *\n * Wraps a viem {@link Account} + a {@link SpendingPolicy} + a pinned EIP-712\n * domain. `sign(intent)` evaluates the policy SDK-side and, on pass, produces a\n * real EIP-3009 authorization via {@link signTransferWithAuthorization}. It is\n * **advisory** because the wrapped key can still sign anything elsewhere — the\n * gate is only reached if the caller chooses to call *this* `sign()`. Use it for\n * dev, the A1 cross-language fallback, and any flow that is explicitly not\n * bounded/regulated; the type-gate (`requireNonBypassable`) keeps it out of\n * flows that require non-bypassable enforcement.\n *\n * @packageDocumentation\n */\n\nimport type { Account } from \"viem\";\nimport { getAddress } from \"viem\";\nimport type { SpendingPolicy, SpendState } from \"../policy/spending-policy\";\nimport { evaluateSpendingPolicy } from \"../policy/spending-policy\";\nimport type { X402AssetParam } from \"../tokens/asset-domain\";\nimport { resolveAssetParam } from \"../tokens/asset-domain\";\nimport { signTransferWithAuthorization } from \"../tokens/eip3009\";\nimport { PolicyGatedSignerConfigError } from \"./errors\";\nimport type { PaymentIntent, PolicyGatedSigner, SignerDescription, SignResult } from \"./types\";\n\n/** Parameters for {@link createLocalPolicyGatedSigner}. */\nexport interface CreateLocalPolicyGatedSignerParams {\n\t/** EOA / LocalAccount that signs the EIP-3009 authorization. */\n\treadonly account: Account;\n\t/** The spending policy this signer enforces (SDK-side, advisory). */\n\treadonly policy: SpendingPolicy;\n\t/** Asset binding — pins the EIP-712 domain `name`/`version`/`verifyingContract`. */\n\treadonly asset: X402AssetParam;\n\t/**\n\t * Required literal acknowledgement that this signer is **advisory** (a\n\t * key-holder can bypass its policy). Omitting it is a compile error (TS) and\n\t * a construction-time throw (JS) — so constructing an advisory signer is a\n\t * conscious, greppable act. For bounded/regulated flows use a cryptographic\n\t * adapter instead.\n\t */\n\treadonly acknowledgeAdvisory: true;\n\t/**\n\t * Optional cumulative-spend view (read-only) the adapter evaluates\n\t * `cumulativeCap` against. `local` does not own an authoritative ledger; the\n\t * caller folds a successful spend back in (e.g. via `mergeSpendState`) before\n\t * the next call. Default: empty.\n\t */\n\treadonly spendState?: () => SpendState | Promise<SpendState>;\n}\n\n/**\n * Construct a `local` (advisory) PolicyGatedSigner.\n *\n * @example\n * ```ts\n * const signer = createLocalPolicyGatedSigner({\n * account,\n * policy: createSpendingPolicy({ session: { id, notAfter }, perToken: [{ token: JPYC, maxPerSign: 1_000n }], recipientAllowlist: \"any\" }),\n * asset: { kind: \"known\", id: \"jpyc-v2\" },\n * acknowledgeAdvisory: true,\n * });\n * const result = await signer.sign(intent);\n * ```\n */\nexport function createLocalPolicyGatedSigner(\n\tparams: CreateLocalPolicyGatedSignerParams,\n): PolicyGatedSigner<\"advisory\"> {\n\tif (params.acknowledgeAdvisory !== true) {\n\t\tthrow new PolicyGatedSignerConfigError(\n\t\t\t\"acknowledgeAdvisory\",\n\t\t\t\"a local signer is advisory (a key-holder can bypass its policy); pass `acknowledgeAdvisory: true` to construct one consciously, or use a cryptographic adapter for bounded/regulated flows\",\n\t\t);\n\t}\n\n\tconst { account, policy, spendState } = params;\n\tconst pinned = resolveAssetParam(params.asset);\n\tconst from = getAddress(account.address);\n\n\treturn {\n\t\tenforcement: \"advisory\",\n\t\tfrom,\n\t\tasync sign(intent: PaymentIntent): Promise<SignResult> {\n\t\t\tif (getAddress(intent.from) !== from) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\trejection: {\n\t\t\t\t\t\treason: \"from_mismatch\",\n\t\t\t\t\t\tdetail: `intent.from ${getAddress(intent.from)} does not equal signer.from ${from}`,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (getAddress(intent.token) !== pinned.verifyingContract) {\n\t\t\t\treturn {\n\t\t\t\t\tok: false,\n\t\t\t\t\trejection: {\n\t\t\t\t\t\treason: \"token_not_allowed\",\n\t\t\t\t\t\tdetail: `intent.token ${getAddress(intent.token)} does not equal the signer's pinned verifyingContract ${pinned.verifyingContract}`,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst state: SpendState = (await spendState?.()) ?? { spentPerToken: [] };\n\t\t\tconst nowSeconds = BigInt(Math.floor(Date.now() / 1000));\n\t\t\tconst decision = evaluateSpendingPolicy(policy, intent, state, nowSeconds);\n\t\t\tif (!decision.ok) {\n\t\t\t\treturn { ok: false, rejection: decision.rejection };\n\t\t\t}\n\n\t\t\tconst signed = await signTransferWithAuthorization(\n\t\t\t\taccount,\n\t\t\t\t{\n\t\t\t\t\tname: pinned.name,\n\t\t\t\t\tversion: pinned.version,\n\t\t\t\t\tchainId: intent.chainId,\n\t\t\t\t\tverifyingContract: pinned.verifyingContract,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tfrom,\n\t\t\t\t\tto: intent.to,\n\t\t\t\t\tvalue: intent.value,\n\t\t\t\t\tvalidAfter: intent.validAfter,\n\t\t\t\t\tvalidBefore: intent.validBefore,\n\t\t\t\t\tnonce: intent.nonce,\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn { ok: true, signature: signed.signature, intent };\n\t\t},\n\t\tdescribe(): SignerDescription {\n\t\t\treturn {\n\t\t\t\tenforcement: \"advisory\",\n\t\t\t\tfrom,\n\t\t\t\tpolicyId: policy.session.id,\n\t\t\t\tnotAfter: policy.session.notAfter,\n\t\t\t\trevoked: policy.revoked,\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
@@ -32,7 +32,7 @@ function evaluateSpendingPolicy(policy, intent, state, nowSeconds) {
32
32
  if (limit === void 0) {
33
33
  return deny("token_not_allowed", `token ${intentToken} is not in the policy`);
34
34
  }
35
- if (policy.recipientAllowlist !== void 0) {
35
+ if (policy.recipientAllowlist !== "any") {
36
36
  const to = getAddress(intent.to);
37
37
  const allowed = policy.recipientAllowlist.some((a) => getAddress(a) === to);
38
38
  if (!allowed) {
@@ -102,12 +102,12 @@ function createSpendingPolicy(params) {
102
102
  }
103
103
  return { token, maxPerSign: l.maxPerSign };
104
104
  });
105
- const recipientAllowlist = params.recipientAllowlist?.map((a) => getAddress(a));
105
+ const recipientAllowlist = params.recipientAllowlist === "any" ? "any" : params.recipientAllowlist.map((a) => getAddress(a));
106
106
  return {
107
107
  version: "1",
108
108
  session: { id: params.session.id, notAfter: params.session.notAfter },
109
109
  perToken,
110
- ...recipientAllowlist !== void 0 ? { recipientAllowlist } : {},
110
+ recipientAllowlist,
111
111
  revoked: params.revoked ?? false
112
112
  };
113
113
  }
@@ -121,5 +121,5 @@ function mergeSpendState(state, spend) {
121
121
  }
122
122
 
123
123
  export { SpendingPolicyConfigError, createSpendingPolicy, evaluateSpendingPolicy, mergeSpendState };
124
- //# sourceMappingURL=chunk-MTMJNYOD.js.map
125
- //# sourceMappingURL=chunk-MTMJNYOD.js.map
124
+ //# sourceMappingURL=chunk-YMABXRCK.js.map
125
+ //# sourceMappingURL=chunk-YMABXRCK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/policy/spending-policy.ts"],"names":[],"mappings":"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","file":"chunk-YMABXRCK.js","sourcesContent":["/**\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 Go; a shared conformance\n * corpus (`__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\";\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\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`), rejects an empty `perToken` (deny-closed), a non-positive\n * `maxPerSign`/`cumulativeCap`, a `cumulativeCap < maxPerSign`, and duplicate\n * tokens. Throws {@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\tconst recipientAllowlist =\n\t\tparams.recipientAllowlist === \"any\"\n\t\t\t? \"any\"\n\t\t\t: params.recipientAllowlist.map((a) => getAddress(a));\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"]}
@@ -1643,7 +1643,7 @@ function registerTransferCommand(program2) {
1643
1643
  }
1644
1644
 
1645
1645
  // cli/index.ts
1646
- var CLI_VERSION = "0.1.0-beta.5" ;
1646
+ var CLI_VERSION = "0.1.0" ;
1647
1647
  var program = new commander.Command();
1648
1648
  program.name("kawasekit").description(
1649
1649
  "kawasekit \u2014 CLI for the kawasekit SDK (AI-agent stablecoin payments, Japan-first, JPYC-native)."