payid 0.3.9 → 0.4.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,14 +1,29 @@
1
1
  // src/rule/canonicalize.ts
2
2
  function canonicalizeRuleSet(ruleSet) {
3
3
  return {
4
- version: ruleSet.version,
4
+ version: ruleSet.version ?? "1",
5
5
  logic: ruleSet.logic,
6
6
  rules: ruleSet.rules.map((rule) => canonicalizeRule(rule)).sort((a, b) => a.id.localeCompare(b.id))
7
7
  };
8
8
  }
9
9
  function canonicalizeRule(rule) {
10
+ const base = { id: rule.id, ...rule.message ? { message: rule.message } : {} };
11
+ if ("rules" in rule && Array.isArray(rule.rules)) {
12
+ return {
13
+ ...base,
14
+ logic: rule.logic,
15
+ rules: rule.rules.map((r) => canonicalizeRule(r)).sort((a, b) => a.id.localeCompare(b.id))
16
+ };
17
+ }
18
+ if ("conditions" in rule && Array.isArray(rule.conditions)) {
19
+ return {
20
+ ...base,
21
+ logic: rule.logic,
22
+ conditions: rule.conditions.map((c) => canonicalizeObject(c))
23
+ };
24
+ }
10
25
  return {
11
- id: rule.id,
26
+ ...base,
12
27
  if: canonicalizeObject(rule.if)
13
28
  };
14
29
  }
@@ -19,12 +34,8 @@ function canonicalizeObject(obj) {
19
34
  if (typeof obj === "function" || typeof obj === "symbol") {
20
35
  throw new Error("Non-JSON value not allowed in canonical object");
21
36
  }
22
- if (obj instanceof Date) {
23
- return obj.toISOString();
24
- }
25
- if (typeof obj === "bigint") {
26
- return obj.toString();
27
- }
37
+ if (obj instanceof Date) return obj.toISOString();
38
+ if (typeof obj === "bigint") return obj.toString();
28
39
  if (Array.isArray(obj)) {
29
40
  return obj.map(canonicalizeObject);
30
41
  }
@@ -25,19 +25,49 @@ function normalizeContext(ctx) {
25
25
  function toBigIntSafe(v) {
26
26
  try {
27
27
  if (typeof v === "bigint") return v;
28
- if (typeof v === "number" && Number.isFinite(v)) {
29
- return BigInt(Math.trunc(v));
30
- }
31
- if (typeof v === "string" && v !== "") {
32
- return BigInt(v);
33
- }
28
+ if (typeof v === "number" && Number.isFinite(v)) return BigInt(Math.trunc(v));
29
+ if (typeof v === "string" && v !== "") return BigInt(v);
34
30
  return null;
35
31
  } catch {
36
32
  return null;
37
33
  }
38
34
  }
39
- function getValueByPath(obj, path) {
40
- return path.split(".").reduce((o, k) => o?.[k], obj);
35
+ function resolveField(obj, fieldExpr) {
36
+ const [path, ...transforms] = fieldExpr.split("|");
37
+ let value = path?.split(".").reduce((o, k) => o?.[k], obj);
38
+ for (const t of transforms) {
39
+ if (value === void 0 || value === null) break;
40
+ if (t.startsWith("div:")) {
41
+ const n = Number(t.slice(4));
42
+ value = Number(value) / n;
43
+ } else if (t.startsWith("mod:")) {
44
+ const n = BigInt(t.slice(4));
45
+ value = BigInt(value) % n;
46
+ } else if (t === "abs") {
47
+ value = Math.abs(Number(value));
48
+ } else if (t === "hour") {
49
+ value = new Date(Number(value) * 1e3).getUTCHours();
50
+ } else if (t === "day") {
51
+ value = new Date(Number(value) * 1e3).getUTCDay();
52
+ } else if (t === "date") {
53
+ value = new Date(Number(value) * 1e3).getUTCDate();
54
+ } else if (t === "month") {
55
+ value = new Date(Number(value) * 1e3).getUTCMonth() + 1;
56
+ } else if (t === "len") {
57
+ value = String(value).length;
58
+ } else if (t === "lower") {
59
+ value = String(value).toLowerCase();
60
+ } else if (t === "upper") {
61
+ value = String(value).toUpperCase();
62
+ }
63
+ }
64
+ return value;
65
+ }
66
+ function resolveValue(context, value) {
67
+ if (typeof value === "string" && value.startsWith("$")) {
68
+ return resolveField(context, value.slice(1));
69
+ }
70
+ return value;
41
71
  }
42
72
  function evaluateCondition(actual, op, expected) {
43
73
  switch (op) {
@@ -56,32 +86,55 @@ function evaluateCondition(actual, op, expected) {
56
86
  }
57
87
  case "==":
58
88
  return actual == expected;
89
+ case "!=":
90
+ return actual != expected;
59
91
  case "in":
60
92
  return Array.isArray(expected) && expected.includes(actual);
61
93
  case "not_in":
62
94
  return Array.isArray(expected) && !expected.includes(actual);
95
+ case "between":
96
+ return Array.isArray(expected) && actual >= expected[0] && actual <= expected[1];
97
+ case "not_between":
98
+ return Array.isArray(expected) && !(actual >= expected[0] && actual <= expected[1]);
99
+ case "exists":
100
+ return actual !== void 0 && actual !== null;
101
+ case "not_exists":
102
+ return actual === void 0 || actual === null;
63
103
  default:
64
104
  return false;
65
105
  }
66
106
  }
107
+ function traceCondition(context, ruleId, cond) {
108
+ const actual = resolveField(context, cond.field);
109
+ const expected = resolveValue(context, cond.value);
110
+ const pass = evaluateCondition(actual, cond.op, expected);
111
+ return {
112
+ ruleId,
113
+ field: cond.field,
114
+ op: cond.op,
115
+ expected: cond.value,
116
+ actual,
117
+ result: actual === void 0 ? "FAIL" : pass ? "PASS" : "FAIL"
118
+ };
119
+ }
120
+ function traceRule(context, rule) {
121
+ if ("if" in rule) {
122
+ return [traceCondition(context, rule.id, rule.if)];
123
+ }
124
+ if ("conditions" in rule) {
125
+ return rule.conditions.map((cond) => traceCondition(context, rule.id, cond));
126
+ }
127
+ if ("rules" in rule) {
128
+ return rule.rules.flatMap((child) => traceRule(context, child));
129
+ }
130
+ return [];
131
+ }
67
132
  function buildDecisionTrace(context, ruleConfig) {
68
- return ruleConfig.rules.map((rule) => {
69
- const cond = rule.if;
70
- const actual = getValueByPath(context, cond.field);
71
- const pass = evaluateCondition(actual, cond.op, cond.value);
72
- return {
73
- ruleId: rule.id,
74
- field: cond.field,
75
- op: cond.op,
76
- expected: cond.value,
77
- actual,
78
- result: actual === void 0 ? "FAIL" : pass ? "PASS" : "FAIL"
79
- };
80
- });
133
+ return ruleConfig.rules.flatMap((rule) => traceRule(context, rule));
81
134
  }
82
135
 
83
136
  // src/evaluate.ts
84
- async function evaluate(wasmBinary, context, ruleConfig, options) {
137
+ async function evaluate(context, ruleConfig, options, wasmBinary) {
85
138
  if (!context || typeof context !== "object") {
86
139
  throw new Error("evaluate(): context is required");
87
140
  }
@@ -99,11 +152,18 @@ async function evaluate(wasmBinary, context, ruleConfig, options) {
99
152
  options.trustedIssuers
100
153
  ) : context;
101
154
  const normalized = normalizeContext(preparedContext);
102
- const wasmForEngine = typeof Buffer !== "undefined" && !(wasmBinary instanceof Buffer) ? Buffer.from(wasmBinary) : wasmBinary;
155
+ let wasmForEngine;
156
+ if (wasmBinary == null) {
157
+ wasmForEngine = void 0;
158
+ } else if (typeof Buffer !== "undefined") {
159
+ wasmForEngine = Buffer.isBuffer(wasmBinary) ? wasmBinary : Buffer.from(wasmBinary);
160
+ } else {
161
+ wasmForEngine = wasmBinary;
162
+ }
103
163
  result = await executeRule(
104
- wasmForEngine,
105
164
  normalized,
106
- ruleConfig
165
+ ruleConfig,
166
+ wasmForEngine
107
167
  );
108
168
  } catch (err) {
109
169
  return {
@@ -206,8 +266,9 @@ function hashRuleSet(ruleConfig) {
206
266
  import { ethers, ZeroAddress } from "ethers";
207
267
  var hash = (v) => ethers.keccak256(ethers.toUtf8Bytes(v));
208
268
  async function generateDecisionProof(params) {
209
- const now = Math.floor(Date.now() / 1e3);
210
- const expiresAt = now + (params.ttlSeconds ?? 60);
269
+ const now = params.blockTimestamp ?? Math.floor(Date.now() / 1e3);
270
+ const issuedAt = now - 30;
271
+ const expiresAt = now + (params.ttlSeconds ?? 300);
211
272
  const chainId = params.chainId ?? Number((await params.signer.provider.getNetwork()).chainId);
212
273
  const requiresAttestation = Array.isArray(params.ruleConfig?.requires) && params.ruleConfig.requires.length > 0;
213
274
  const payload = {
@@ -220,7 +281,7 @@ async function generateDecisionProof(params) {
220
281
  contextHash: hashContext(params.context),
221
282
  ruleSetHash: hashRuleSet(params.ruleConfig),
222
283
  ruleAuthority: params.ruleAuthority ?? ZeroAddress,
223
- issuedAt: BigInt(now),
284
+ issuedAt: BigInt(issuedAt),
224
285
  expiresAt: BigInt(expiresAt),
225
286
  nonce: randomHex(32),
226
287
  requiresAttestation
@@ -229,7 +290,6 @@ async function generateDecisionProof(params) {
229
290
  name: "PAY.ID Decision",
230
291
  version: "2",
231
292
  chainId,
232
- // FIX: langsung pakai, tidak perlu await lagi
233
293
  verifyingContract: params.verifyingContract
234
294
  };
235
295
  const types = {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  combineRules
3
- } from "./chunk-QYH3FNQ4.js";
3
+ } from "./chunk-GG34PNTF.js";
4
4
  import {
5
5
  decodeSessionPolicy
6
6
  } from "./chunk-MXKZJKXE.js";
@@ -8,7 +8,7 @@ import {
8
8
  evaluate,
9
9
  generateDecisionProof,
10
10
  resolveRule
11
- } from "./chunk-METOE7DV.js";
11
+ } from "./chunk-ANG3SJGI.js";
12
12
  import {
13
13
  __export
14
14
  } from "./chunk-R5U7XKVJ.js";
@@ -25,21 +25,14 @@ function isRuleSource(rule) {
25
25
  return typeof rule === "object" && rule !== null && "uri" in rule;
26
26
  }
27
27
  var PayIDClient = class {
28
- constructor(wasm, debugTrace) {
29
- this.wasm = wasm;
28
+ constructor(debugTrace, wasm) {
30
29
  this.debugTrace = debugTrace;
30
+ this.wasm = wasm;
31
31
  }
32
- /**
33
- * Pure rule evaluation — client-safe, no signing, no server
34
- */
35
32
  async evaluate(context, rule) {
36
33
  const config = isRuleSource(rule) ? (await resolveRule(rule)).config : rule;
37
- return evaluate(this.wasm, context, config, { debug: this.debugTrace });
34
+ return evaluate(context, config, { debug: this.debugTrace }, this.wasm);
38
35
  }
39
- /**
40
- * Evaluate + generate EIP-712 Decision Proof.
41
- * Payer sign sendiri menggunakan wallet mereka — tidak butuh server.
42
- */
43
36
  async evaluateAndProve(params) {
44
37
  const authorityConfig = isRuleSource(params.authorityRule) ? (await resolveRule(params.authorityRule)).config : params.authorityRule;
45
38
  const evalConfig = params.evaluationRule ?? (params.sessionPolicy ? combineRules(
@@ -50,10 +43,10 @@ var PayIDClient = class {
50
43
  ).rules
51
44
  ) : authorityConfig);
52
45
  const result = await evaluate(
53
- this.wasm,
54
46
  params.context,
55
47
  evalConfig,
56
- { debug: this.debugTrace }
48
+ { debug: this.debugTrace },
49
+ this.wasm
57
50
  );
58
51
  if (result.decision !== "ALLOW") {
59
52
  return { result, proof: null };
@@ -69,8 +62,9 @@ var PayIDClient = class {
69
62
  signer: params.signer,
70
63
  verifyingContract: params.verifyingContract,
71
64
  ruleAuthority: params.ruleAuthority,
72
- chainId: params.context?.tx?.chainId,
73
- ttlSeconds: params.ttlSeconds
65
+ chainId: params.chainId ?? params.context?.tx?.chainId,
66
+ ttlSeconds: params.ttlSeconds,
67
+ blockTimestamp: params.blockTimestamp
74
68
  });
75
69
  return { result, proof };
76
70
  }
@@ -79,8 +73,8 @@ var PayIDClient = class {
79
73
  // src/core/client/index.ts
80
74
  function createPayID(params) {
81
75
  return new PayIDClient(
82
- params.wasm,
83
- params.debugTrace ?? false
76
+ params.debugTrace ?? false,
77
+ params.wasm
84
78
  );
85
79
  }
86
80
 
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  canonicalizeRuleSet
3
- } from "./chunk-JJEWYFOV.js";
3
+ } from "./chunk-6VPSJFO4.js";
4
4
 
5
5
  // src/rule/combine.ts
6
6
  function combineRules(defaultRuleSet, sessionRule) {
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  combineRules
3
- } from "./chunk-QYH3FNQ4.js";
3
+ } from "./chunk-GG34PNTF.js";
4
4
  import {
5
5
  canonicalizeRuleSet
6
- } from "./chunk-JJEWYFOV.js";
6
+ } from "./chunk-6VPSJFO4.js";
7
7
  import {
8
8
  __export
9
9
  } from "./chunk-R5U7XKVJ.js";
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-MXKZJKXE.js";
4
4
  import {
5
5
  canonicalizeRuleSet
6
- } from "./chunk-JJEWYFOV.js";
6
+ } from "./chunk-6VPSJFO4.js";
7
7
  import {
8
8
  randomHex
9
9
  } from "./chunk-5ZEKI5Y2.js";
@@ -2,7 +2,7 @@ import {
2
2
  evaluate,
3
3
  generateDecisionProof,
4
4
  resolveRule
5
- } from "./chunk-METOE7DV.js";
5
+ } from "./chunk-ANG3SJGI.js";
6
6
  import {
7
7
  __export
8
8
  } from "./chunk-R5U7XKVJ.js";
@@ -37,9 +37,6 @@ function buildPayERC20CallData(contractAddress, proof, attestationUIDs = []) {
37
37
  attestationUIDs
38
38
  ]);
39
39
  }
40
- function buildPayCallData(contractAddress, proof, attestationUIDs = []) {
41
- return buildPayERC20CallData(contractAddress, proof, attestationUIDs);
42
- }
43
40
 
44
41
  // src/erc4337/userop.ts
45
42
  function buildUserOperation(params) {
@@ -64,26 +61,23 @@ function isRuleSource(rule) {
64
61
  return typeof rule === "object" && rule !== null && "uri" in rule;
65
62
  }
66
63
  var PayIDServer = class {
67
- constructor(wasm, signer, trustedIssuers, debugTrace) {
68
- this.wasm = wasm;
64
+ constructor(signer, trustedIssuers, debugTrace, wasm) {
69
65
  this.signer = signer;
70
66
  this.trustedIssuers = trustedIssuers;
71
67
  this.debugTrace = debugTrace;
68
+ this.wasm = wasm;
72
69
  }
73
- /**
74
- * Evaluate + generate proof dengan signer dari constructor
75
- */
76
70
  async evaluateAndProve(params) {
77
71
  const authorityConfig = isRuleSource(params.authorityRule) ? (await resolveRule(params.authorityRule)).config : params.authorityRule;
78
72
  const evalConfig = params.evaluationRule ?? authorityConfig;
79
73
  const result = await evaluate(
80
- this.wasm,
81
74
  params.context,
82
75
  evalConfig,
83
76
  {
84
77
  debug: this.debugTrace,
85
78
  trustedIssuers: this.trustedIssuers
86
- }
79
+ },
80
+ this.wasm
87
81
  );
88
82
  if (result.decision !== "ALLOW") {
89
83
  return { result, proof: null };
@@ -99,17 +93,18 @@ var PayIDServer = class {
99
93
  signer: this.signer,
100
94
  verifyingContract: params.verifyingContract,
101
95
  ruleAuthority: params.ruleAuthority,
102
- chainId: params.context?.tx?.chainId,
103
- ttlSeconds: params.ttlSeconds
96
+ chainId: params.chainId ?? params.context?.tx?.chainId,
97
+ ttlSeconds: params.ttlSeconds,
98
+ blockTimestamp: params.blockTimestamp
104
99
  });
105
100
  return { result, proof };
106
101
  }
107
- /**
108
- * Build ERC-4337 UserOperation dari Decision Proof
109
- * Untuk bundler/relayer — server only
110
- */
111
102
  buildUserOperation(params) {
112
- const callData = buildPayCallData(params.targetContract, params.proof);
103
+ const callData = buildPayERC20CallData(
104
+ params.targetContract,
105
+ params.proof,
106
+ params.attestationUIDs ?? []
107
+ );
113
108
  return buildUserOperation({
114
109
  sender: params.smartAccount,
115
110
  nonce: params.nonce,
@@ -123,10 +118,10 @@ var PayIDServer = class {
123
118
  // src/core/server/index.ts
124
119
  function createPayID(params) {
125
120
  return new PayIDServer(
126
- params.wasm,
127
121
  params.signer,
128
122
  params.trustedIssuers,
129
- params.debugTrace ?? false
123
+ params.debugTrace ?? false,
124
+ params.wasm
130
125
  );
131
126
  }
132
127
 
@@ -1,5 +1,5 @@
1
- export { c as createPayID } from '../../index-on2SYkvq.js';
1
+ export { c as createPayID } from '../../index-2O3usHUn.js';
2
2
  import 'payid-types';
3
3
  import 'ethers';
4
4
  import '../../types-B8pJQdMQ.js';
5
- import '../../types-DKt-zH0P.js';
5
+ import '../../types-BmMf7udp.js';
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  createPayID
3
- } from "../../chunk-UBGZH6HB.js";
4
- import "../../chunk-QYH3FNQ4.js";
3
+ } from "../../chunk-GB3FSF7K.js";
4
+ import "../../chunk-GG34PNTF.js";
5
5
  import "../../chunk-MXKZJKXE.js";
6
- import "../../chunk-JJEWYFOV.js";
7
- import "../../chunk-METOE7DV.js";
6
+ import "../../chunk-6VPSJFO4.js";
7
+ import "../../chunk-ANG3SJGI.js";
8
8
  import "../../chunk-5ZEKI5Y2.js";
9
9
  import "../../chunk-R5U7XKVJ.js";
10
10
  export {
@@ -1,4 +1,4 @@
1
- export { c as createPayID } from '../../index-CiTDNVSZ.js';
1
+ export { c as createPayID } from '../../index-C1DHMQA0.js';
2
2
  import 'ethers';
3
3
  import 'payid-types';
4
4
  import '../../types-B8pJQdMQ.js';
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createPayID
3
- } from "../../chunk-SIHQPH55.js";
4
- import "../../chunk-METOE7DV.js";
3
+ } from "../../chunk-YUAYDVGX.js";
4
+ import "../../chunk-ANG3SJGI.js";
5
5
  import "../../chunk-5ZEKI5Y2.js";
6
6
  import "../../chunk-R5U7XKVJ.js";
7
7
  export {
@@ -1,7 +1,7 @@
1
1
  import { RuleContext, RuleConfig, RuleResult } from 'payid-types';
2
2
  import { ethers } from 'ethers';
3
3
  import { R as RuleSource, D as DecisionProof } from './types-B8pJQdMQ.js';
4
- import { P as PayIDSessionPolicyPayloadV1 } from './types-DKt-zH0P.js';
4
+ import { P as PayIDSessionPolicyPayloadV1 } from './types-BmMf7udp.js';
5
5
 
6
6
  /**
7
7
  * @class PayIDClient
@@ -35,17 +35,10 @@ import { P as PayIDSessionPolicyPayloadV1 } from './types-DKt-zH0P.js';
35
35
  * ```
36
36
  */
37
37
  declare class PayIDClient {
38
- private readonly wasm;
39
38
  private readonly debugTrace?;
40
- constructor(wasm: Uint8Array, debugTrace?: boolean | undefined);
41
- /**
42
- * Pure rule evaluation — client-safe, no signing, no server
43
- */
39
+ private readonly wasm?;
40
+ constructor(debugTrace?: boolean | undefined, wasm?: Uint8Array | undefined);
44
41
  evaluate(context: RuleContext, rule: RuleConfig | RuleSource): Promise<RuleResult>;
45
- /**
46
- * Evaluate + generate EIP-712 Decision Proof.
47
- * Payer sign sendiri menggunakan wallet mereka — tidak butuh server.
48
- */
49
42
  evaluateAndProve(params: {
50
43
  context: RuleContext;
51
44
  authorityRule: RuleConfig | RuleSource;
@@ -60,6 +53,8 @@ declare class PayIDClient {
60
53
  verifyingContract: string;
61
54
  ruleAuthority: string;
62
55
  ttlSeconds?: number;
56
+ chainId: number;
57
+ blockTimestamp: number;
63
58
  }): Promise<{
64
59
  result: RuleResult;
65
60
  proof: DecisionProof | null;
@@ -102,7 +97,7 @@ declare class PayIDClient {
102
97
  * ```
103
98
  */
104
99
  declare function createPayID(params: {
105
- wasm: Uint8Array;
100
+ wasm?: Uint8Array;
106
101
  debugTrace?: boolean;
107
102
  }): PayIDClient;
108
103
 
@@ -1,6 +1,6 @@
1
1
  import { ethers } from 'ethers';
2
- import { P as PayIDSessionPolicyPayloadV1 } from './types-DKt-zH0P.js';
3
2
  import { RuleConfig } from 'payid-types';
3
+ import { P as PayIDSessionPolicyPayloadV1 } from './types-BmMf7udp.js';
4
4
 
5
5
  /**
6
6
  * Create and sign an ephemeral PayID session policy payload.
@@ -54,11 +54,7 @@ import { RuleConfig } from 'payid-types';
54
54
  */
55
55
  declare function createSessionPolicyPayload(params: {
56
56
  receiver: string;
57
- rule: {
58
- version: string;
59
- logic: "AND";
60
- rules: any[];
61
- };
57
+ rule: RuleConfig;
62
58
  expiresAt: number;
63
59
  signer: ethers.Signer;
64
60
  }): Promise<PayIDSessionPolicyPayloadV1>;
@@ -45,14 +45,11 @@ interface UserOperation {
45
45
  * ```
46
46
  */
47
47
  declare class PayIDServer {
48
- private readonly wasm;
49
48
  private readonly signer;
50
49
  private readonly trustedIssuers?;
51
50
  private readonly debugTrace?;
52
- constructor(wasm: Uint8Array, signer: ethers.Signer, trustedIssuers?: Set<string> | undefined, debugTrace?: boolean | undefined);
53
- /**
54
- * Evaluate + generate proof dengan signer dari constructor
55
- */
51
+ private readonly wasm?;
52
+ constructor(signer: ethers.Signer, trustedIssuers?: Set<string> | undefined, debugTrace?: boolean | undefined, wasm?: Uint8Array | undefined);
56
53
  evaluateAndProve(params: {
57
54
  context: RuleContext;
58
55
  authorityRule: RuleConfig | RuleSource;
@@ -65,14 +62,12 @@ declare class PayIDServer {
65
62
  verifyingContract: string;
66
63
  ruleAuthority: string;
67
64
  ttlSeconds?: number;
65
+ chainId: number;
66
+ blockTimestamp: number;
68
67
  }): Promise<{
69
68
  result: RuleResult;
70
69
  proof: DecisionProof | null;
71
70
  }>;
72
- /**
73
- * Build ERC-4337 UserOperation dari Decision Proof
74
- * Untuk bundler/relayer — server only
75
- */
76
71
  buildUserOperation(params: {
77
72
  proof: DecisionProof;
78
73
  smartAccount: string;
@@ -80,6 +75,7 @@ declare class PayIDServer {
80
75
  gas: any;
81
76
  targetContract: string;
82
77
  paymasterAndData?: string;
78
+ attestationUIDs?: string[];
83
79
  }): UserOperation;
84
80
  }
85
81
 
@@ -144,7 +140,7 @@ declare class PayIDServer {
144
140
  * ```
145
141
  */
146
142
  declare function createPayID(params: {
147
- wasm: Uint8Array;
143
+ wasm?: Uint8Array;
148
144
  signer: ethers.Signer;
149
145
  debugTrace?: boolean;
150
146
  trustedIssuers?: Set<string>;
@@ -1,4 +1,5 @@
1
- import { RuleConfig } from 'payid-types';
1
+ import * as payid_types from 'payid-types';
2
+ import { RuleConfig, AnyRule } from 'payid-types';
2
3
 
3
4
  /**
4
5
  * Combine an authoritative rule set with additional ephemeral rules
@@ -42,66 +43,25 @@ import { RuleConfig } from 'payid-types';
42
43
  declare function combineRules(defaultRuleSet: RuleConfig, sessionRule: any[]): {
43
44
  version: string;
44
45
  logic: "AND" | "OR";
45
- rules: {
46
- id: any;
47
- if: any;
48
- }[];
46
+ rules: payid_types.AnyRule[];
49
47
  };
50
48
 
51
49
  /**
52
50
  * Canonicalize a rule set into a deterministic, order-independent form.
53
51
  *
54
- * Canonicalization ensures that semantically identical rule sets
55
- * always produce the same structural representation, regardless of:
56
- * - Rule insertion order
57
- * - Object key order
58
- * - Nested object layout
59
- *
60
- * This function is CRITICAL for:
61
- * - Rule hashing (`ruleSetHash`)
62
- * - Policy signing (QR / session / intent)
63
- * - Consistent off-chain evaluation
64
- *
65
- * ## Canonicalization rules
66
- *
67
- * - Rules are normalized individually.
68
- * - Rule entries are sorted lexicographically by `id`.
69
- * - All nested objects are recursively sorted by key.
70
- * - Arrays preserve their original order unless explicitly sorted.
71
- *
72
- * ## Security model
73
- *
74
- * - Canonicalization MUST be applied BEFORE hashing or signing.
75
- * - Canonicalization MUST NOT be applied during verification
76
- * (the verified payload must match exactly what was signed).
77
- *
78
- * ## Invariants
79
- *
80
- * - Canonicalization does NOT change rule semantics.
81
- * - Canonicalization does NOT weaken rule constraints.
82
- * - Canonicalization is a pure, deterministic operation.
83
- *
84
- * @param ruleSet
85
- * A rule configuration object containing:
86
- * - `version`: rule schema version
87
- * - `logic`: logical operator ("AND" | "OR")
88
- * - `rules`: list of rule definitions
89
- *
90
- * @returns
91
- * A canonicalized rule configuration suitable for hashing,
92
- * signing, and deterministic evaluation.
52
+ * Supports all three v4 rule formats:
53
+ * - Format A: { id, if, message? }
54
+ * - Format B: { id, logic, conditions[], message? }
55
+ * - Format C: { id, logic, rules[], message? }
93
56
  */
94
57
  declare function canonicalizeRuleSet(ruleSet: {
95
- version: string;
58
+ version?: string;
96
59
  logic: "AND" | "OR";
97
60
  rules: any[];
98
61
  }): {
99
62
  version: string;
100
63
  logic: "AND" | "OR";
101
- rules: {
102
- id: any;
103
- if: any;
104
- }[];
64
+ rules: AnyRule[];
105
65
  };
106
66
 
107
67
  /**
package/dist/index.d.ts CHANGED
@@ -1,14 +1,14 @@
1
1
  import { RuleContext, RuleConfig, RuleResult } from 'payid-types';
2
2
  import { R as RuleSource } from './types-B8pJQdMQ.js';
3
- import { U as UserOperation } from './index-CiTDNVSZ.js';
4
- export { i as server } from './index-CiTDNVSZ.js';
3
+ import { U as UserOperation } from './index-C1DHMQA0.js';
4
+ export { i as server } from './index-C1DHMQA0.js';
5
5
  import { ethers } from 'ethers';
6
- export { i as sessionPolicy } from './index-DuOeYzN2.js';
7
- export { i as rule } from './index-C7vziL_Z.js';
6
+ export { i as sessionPolicy } from './index-BQQnMG2H.js';
7
+ export { i as rule } from './index-DerQdZmf.js';
8
8
  export { i as issuer } from './index-2JCvey4-.js';
9
9
  export { i as context } from './index-BEvnPzzt.js';
10
- export { i as client } from './index-on2SYkvq.js';
11
- import './types-DKt-zH0P.js';
10
+ export { i as client } from './index-2O3usHUn.js';
11
+ import './types-BmMf7udp.js';
12
12
 
13
13
  interface PayIDClient {
14
14
  /**
@@ -54,6 +54,8 @@ interface PayIDServer {
54
54
  verifyingContract: string;
55
55
  ruleAuthority: string;
56
56
  ttlSeconds?: number;
57
+ chainId: number;
58
+ blockTimestamp: number;
57
59
  }): Promise<{
58
60
  result: RuleResult;
59
61
  proof: any | null;
@@ -69,6 +71,7 @@ interface PayIDServer {
69
71
  gas: any;
70
72
  targetContract: string;
71
73
  paymasterAndData?: string;
74
+ attestationUIDs?: string[];
72
75
  }): UserOperation;
73
76
  }
74
77
 
@@ -130,7 +133,7 @@ interface PayIDServer {
130
133
  * ```
131
134
  */
132
135
  declare function createPayID(params: {
133
- wasm: Uint8Array;
136
+ wasm?: Uint8Array;
134
137
  debugTrace?: boolean;
135
138
  trustedIssuers?: Set<string>;
136
139
  }): PayIDClient & PayIDServer;
package/dist/index.js CHANGED
@@ -7,27 +7,27 @@ import {
7
7
  import "./chunk-7U3P7XJE.js";
8
8
  import {
9
9
  rule_exports
10
- } from "./chunk-JRVCGSKK.js";
10
+ } from "./chunk-ILV7Z3IN.js";
11
11
  import {
12
12
  sessionPolicy_exports
13
- } from "./chunk-ATWJEWZH.js";
13
+ } from "./chunk-Y75PSD7U.js";
14
14
  import {
15
15
  client_exports
16
- } from "./chunk-UBGZH6HB.js";
17
- import "./chunk-QYH3FNQ4.js";
16
+ } from "./chunk-GB3FSF7K.js";
17
+ import "./chunk-GG34PNTF.js";
18
18
  import "./chunk-MXKZJKXE.js";
19
- import "./chunk-JJEWYFOV.js";
19
+ import "./chunk-6VPSJFO4.js";
20
20
  import {
21
21
  buildPayERC20CallData,
22
22
  buildPayETHCallData,
23
23
  buildUserOperation,
24
24
  server_exports
25
- } from "./chunk-SIHQPH55.js";
25
+ } from "./chunk-YUAYDVGX.js";
26
26
  import {
27
27
  evaluate,
28
28
  generateDecisionProof,
29
29
  resolveRule
30
- } from "./chunk-METOE7DV.js";
30
+ } from "./chunk-ANG3SJGI.js";
31
31
  import "./chunk-5ZEKI5Y2.js";
32
32
  import {
33
33
  __export
@@ -43,31 +43,24 @@ var PayID = class {
43
43
  this.debugTrace = debugTrace;
44
44
  this.trustedIssuers = trustedIssuers;
45
45
  }
46
- /**
47
- * Pure evaluation — client-safe
48
- */
49
46
  async evaluate(context, rule) {
50
47
  const config = isRuleSource(rule) ? (await resolveRule(rule)).config : rule;
51
- return evaluate(this.wasm, context, config, {
48
+ return evaluate(context, config, {
52
49
  debug: this.debugTrace,
53
50
  trustedIssuers: this.trustedIssuers
54
- });
51
+ }, this.wasm);
55
52
  }
56
- /**
57
- * Evaluate + generate Decision Proof
58
- * FIX: parameter rename ruleRegistryContract → ruleAuthority
59
- */
60
53
  async evaluateAndProve(params) {
61
54
  const authorityConfig = isRuleSource(params.authorityRule) ? (await resolveRule(params.authorityRule)).config : params.authorityRule;
62
55
  const evalConfig = params.evaluationRule ?? authorityConfig;
63
56
  const result = await evaluate(
64
- this.wasm,
65
57
  params.context,
66
58
  evalConfig,
67
59
  {
68
60
  debug: this.debugTrace,
69
61
  trustedIssuers: this.trustedIssuers
70
- }
62
+ },
63
+ this.wasm
71
64
  );
72
65
  if (result.decision !== "ALLOW") {
73
66
  return { result, proof: null };
@@ -83,14 +76,12 @@ var PayID = class {
83
76
  signer: params.signer,
84
77
  verifyingContract: params.verifyingContract,
85
78
  ruleAuthority: params.ruleAuthority,
86
- chainId: params.context?.tx?.chainId,
87
- ttlSeconds: params.ttlSeconds
79
+ chainId: params.chainId ?? params.context?.tx?.chainId,
80
+ ttlSeconds: params.ttlSeconds,
81
+ blockTimestamp: params.blockTimestamp
88
82
  });
89
83
  return { result, proof };
90
84
  }
91
- /**
92
- * Build ERC-4337 UserOperation
93
- */
94
85
  buildUserOperation(params) {
95
86
  const attestationUIDs = params.attestationUIDs ?? [];
96
87
  const isETH = params.paymentType === "eth";
@@ -1,2 +1,2 @@
1
- export { a as canonicalizeRuleSet, c as combineRules, h as hashRuleSet } from '../index-C7vziL_Z.js';
1
+ export { a as canonicalizeRuleSet, c as combineRules, h as hashRuleSet } from '../index-DerQdZmf.js';
2
2
  import 'payid-types';
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  hashRuleSet
3
- } from "../chunk-JRVCGSKK.js";
3
+ } from "../chunk-ILV7Z3IN.js";
4
4
  import {
5
5
  combineRules
6
- } from "../chunk-QYH3FNQ4.js";
6
+ } from "../chunk-GG34PNTF.js";
7
7
  import {
8
8
  canonicalizeRuleSet
9
- } from "../chunk-JJEWYFOV.js";
9
+ } from "../chunk-6VPSJFO4.js";
10
10
  import "../chunk-R5U7XKVJ.js";
11
11
  export {
12
12
  canonicalizeRuleSet,
@@ -1,4 +1,4 @@
1
- export { c as createSessionPolicyPayload, d as decodeSessionPolicy } from '../index-DuOeYzN2.js';
2
- export { P as PayIDSessionPolicyPayloadV1 } from '../types-DKt-zH0P.js';
1
+ export { c as createSessionPolicyPayload, d as decodeSessionPolicy } from '../index-BQQnMG2H.js';
2
+ export { P as PayIDSessionPolicyPayloadV1 } from '../types-BmMf7udp.js';
3
3
  import 'ethers';
4
4
  import 'payid-types';
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  createSessionPolicyPayload
3
- } from "../chunk-ATWJEWZH.js";
3
+ } from "../chunk-Y75PSD7U.js";
4
4
  import {
5
5
  decodeSessionPolicy
6
6
  } from "../chunk-MXKZJKXE.js";
7
- import "../chunk-JJEWYFOV.js";
7
+ import "../chunk-6VPSJFO4.js";
8
8
  import "../chunk-5ZEKI5Y2.js";
9
9
  import "../chunk-R5U7XKVJ.js";
10
10
  export {
@@ -1,11 +1,9 @@
1
+ import { RuleConfig } from 'payid-types';
2
+
1
3
  interface PayIDSessionPolicyPayloadV1 {
2
4
  version: "payid.session.policy.v1" | string;
3
5
  receiver: string;
4
- rule: {
5
- version: string;
6
- logic: "AND" | "OR";
7
- rules: any[];
8
- };
6
+ rule: RuleConfig;
9
7
  expiresAt: number;
10
8
  nonce: string;
11
9
  issuedAt: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payid",
3
- "version": "0.3.9",
3
+ "version": "0.4.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -37,8 +37,8 @@
37
37
  },
38
38
  "dependencies": {
39
39
  "ethers": "^6.16.0",
40
- "payid-rule-engine": "^0.1.7",
41
- "payid-types": "^0.1.7"
40
+ "payid-rule-engine": "^0.2.3",
41
+ "payid-types": "^0.1.9"
42
42
  },
43
43
  "files": [
44
44
  "dist"