payid 0.3.6 → 0.3.7

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.
@@ -8,7 +8,7 @@ import {
8
8
  evaluate,
9
9
  generateDecisionProof,
10
10
  resolveRule
11
- } from "./chunk-4MPVXPLM.js";
11
+ } from "./chunk-AXFEJV2K.js";
12
12
  import {
13
13
  __export
14
14
  } from "./chunk-R5U7XKVJ.js";
@@ -29,15 +29,26 @@ var PayIDClient = class {
29
29
  this.wasm = wasm;
30
30
  this.debugTrace = debugTrace;
31
31
  }
32
+ /**
33
+ * Pure rule evaluation — client-safe, no signing, no server
34
+ */
35
+ async evaluate(context, rule) {
36
+ const config = isRuleSource(rule) ? (await resolveRule(rule)).config : rule;
37
+ return evaluate(this.wasm, context, config, { debug: this.debugTrace });
38
+ }
39
+ /**
40
+ * Evaluate + generate EIP-712 Decision Proof.
41
+ * Payer sign sendiri menggunakan wallet mereka — tidak butuh server.
42
+ */
32
43
  async evaluateAndProve(params) {
33
44
  const authorityConfig = isRuleSource(params.authorityRule) ? (await resolveRule(params.authorityRule)).config : params.authorityRule;
34
45
  const evalConfig = params.evaluationRule ?? (params.sessionPolicy ? combineRules(
35
- params.authorityRule,
46
+ authorityConfig,
36
47
  decodeSessionPolicy(
37
48
  params.sessionPolicy,
38
49
  Math.floor(Date.now() / 1e3)
39
50
  ).rules
40
- ) : params.authorityRule);
51
+ ) : authorityConfig);
41
52
  const result = await evaluate(
42
53
  this.wasm,
43
54
  params.context,
@@ -57,7 +68,7 @@ var PayIDClient = class {
57
68
  ruleConfig: authorityConfig,
58
69
  signer: params.signer,
59
70
  verifyingContract: params.verifyingContract,
60
- ruleRegistryContract: params.ruleRegistryContract,
71
+ ruleAuthority: params.ruleAuthority,
61
72
  ttlSeconds: params.ttlSeconds
62
73
  });
63
74
  return { result, proof };
@@ -219,7 +219,7 @@ async function generateDecisionProof(params) {
219
219
  amount: params.amount,
220
220
  contextHash: hashContext(params.context),
221
221
  ruleSetHash: hashRuleSet(params.ruleConfig),
222
- ruleAuthority: params.ruleRegistryContract ?? ZeroAddress,
222
+ ruleAuthority: params.ruleAuthority ?? ZeroAddress,
223
223
  issuedAt: BigInt(now),
224
224
  expiresAt: BigInt(expiresAt),
225
225
  nonce: randomHex(32),
@@ -248,17 +248,8 @@ async function generateDecisionProof(params) {
248
248
  { name: "requiresAttestation", type: "bool" }
249
249
  ]
250
250
  };
251
- const signature = await params.signer.signTypedData(
252
- domain,
253
- types,
254
- payload
255
- );
256
- const recovered = ethers.verifyTypedData(
257
- domain,
258
- types,
259
- payload,
260
- signature
261
- );
251
+ const signature = await params.signer.signTypedData(domain, types, payload);
252
+ const recovered = ethers.verifyTypedData(domain, types, payload, signature);
262
253
  if (recovered.toLowerCase() !== params.payer.toLowerCase()) {
263
254
  throw new Error("SIGNATURE_MISMATCH");
264
255
  }
@@ -0,0 +1,138 @@
1
+ import {
2
+ evaluate,
3
+ generateDecisionProof,
4
+ resolveRule
5
+ } from "./chunk-AXFEJV2K.js";
6
+ import {
7
+ __export
8
+ } from "./chunk-R5U7XKVJ.js";
9
+
10
+ // src/core/server/index.ts
11
+ var server_exports = {};
12
+ __export(server_exports, {
13
+ createPayID: () => createPayID
14
+ });
15
+
16
+ // src/erc4337/build.ts
17
+ import { ethers } from "ethers";
18
+ var PAY_WITH_PAYID_ABI = [
19
+ // ETH payment — attestationUIDs adalah EAS UIDs, pass [] jika tidak perlu
20
+ "function payETH((bytes32 version, bytes32 payId, address payer, address receiver, address asset, uint256 amount, bytes32 contextHash, bytes32 ruleSetHash, address ruleAuthority, uint64 issuedAt, uint64 expiresAt, bytes32 nonce, bool requiresAttestation) d, bytes sig, bytes32[] attestationUIDs) payable",
21
+ // ERC20 payment
22
+ "function payERC20((bytes32 version, bytes32 payId, address payer, address receiver, address asset, uint256 amount, bytes32 contextHash, bytes32 ruleSetHash, address ruleAuthority, uint64 issuedAt, uint64 expiresAt, bytes32 nonce, bool requiresAttestation) d, bytes sig, bytes32[] attestationUIDs)"
23
+ ];
24
+ function buildPayETHCallData(contractAddress, proof, attestationUIDs = []) {
25
+ const iface = new ethers.Interface(PAY_WITH_PAYID_ABI);
26
+ return iface.encodeFunctionData("payETH", [
27
+ proof.payload,
28
+ proof.signature,
29
+ attestationUIDs
30
+ ]);
31
+ }
32
+ function buildPayERC20CallData(contractAddress, proof, attestationUIDs = []) {
33
+ const iface = new ethers.Interface(PAY_WITH_PAYID_ABI);
34
+ return iface.encodeFunctionData("payERC20", [
35
+ proof.payload,
36
+ proof.signature,
37
+ attestationUIDs
38
+ ]);
39
+ }
40
+ function buildPayCallData(contractAddress, proof, attestationUIDs = []) {
41
+ return buildPayERC20CallData(contractAddress, proof, attestationUIDs);
42
+ }
43
+
44
+ // src/erc4337/userop.ts
45
+ function buildUserOperation(params) {
46
+ return {
47
+ sender: params.sender,
48
+ nonce: params.nonce,
49
+ initCode: params.initCode ?? "0x",
50
+ callData: params.callData,
51
+ callGasLimit: params.gas.callGasLimit,
52
+ verificationGasLimit: params.gas.verificationGasLimit,
53
+ preVerificationGas: params.gas.preVerificationGas,
54
+ maxFeePerGas: params.gas.maxFeePerGas,
55
+ maxPriorityFeePerGas: params.gas.maxPriorityFeePerGas,
56
+ paymasterAndData: params.paymasterAndData ?? "0x",
57
+ signature: "0x"
58
+ // signed later by smart account
59
+ };
60
+ }
61
+
62
+ // src/core/server/server.ts
63
+ function isRuleSource(rule) {
64
+ return typeof rule === "object" && rule !== null && "uri" in rule;
65
+ }
66
+ var PayIDServer = class {
67
+ constructor(wasm, signer, trustedIssuers, debugTrace) {
68
+ this.wasm = wasm;
69
+ this.signer = signer;
70
+ this.trustedIssuers = trustedIssuers;
71
+ this.debugTrace = debugTrace;
72
+ }
73
+ /**
74
+ * Evaluate + generate proof dengan signer dari constructor
75
+ */
76
+ async evaluateAndProve(params) {
77
+ const authorityConfig = isRuleSource(params.authorityRule) ? (await resolveRule(params.authorityRule)).config : params.authorityRule;
78
+ const evalConfig = params.evaluationRule ?? authorityConfig;
79
+ const result = await evaluate(
80
+ this.wasm,
81
+ params.context,
82
+ evalConfig,
83
+ {
84
+ debug: this.debugTrace,
85
+ trustedIssuers: this.trustedIssuers
86
+ }
87
+ );
88
+ if (result.decision !== "ALLOW") {
89
+ return { result, proof: null };
90
+ }
91
+ const proof = await generateDecisionProof({
92
+ payId: params.payId,
93
+ payer: params.payer,
94
+ receiver: params.receiver,
95
+ asset: params.asset,
96
+ amount: params.amount,
97
+ context: params.context,
98
+ ruleConfig: authorityConfig,
99
+ signer: this.signer,
100
+ verifyingContract: params.verifyingContract,
101
+ ruleAuthority: params.ruleAuthority,
102
+ ttlSeconds: params.ttlSeconds
103
+ });
104
+ return { result, proof };
105
+ }
106
+ /**
107
+ * Build ERC-4337 UserOperation dari Decision Proof
108
+ * Untuk bundler/relayer — server only
109
+ */
110
+ buildUserOperation(params) {
111
+ const callData = buildPayCallData(params.targetContract, params.proof);
112
+ return buildUserOperation({
113
+ sender: params.smartAccount,
114
+ nonce: params.nonce,
115
+ callData,
116
+ gas: params.gas,
117
+ paymasterAndData: params.paymasterAndData
118
+ });
119
+ }
120
+ };
121
+
122
+ // src/core/server/index.ts
123
+ function createPayID(params) {
124
+ return new PayIDServer(
125
+ params.wasm,
126
+ params.signer,
127
+ params.trustedIssuers,
128
+ params.debugTrace ?? false
129
+ );
130
+ }
131
+
132
+ export {
133
+ buildPayETHCallData,
134
+ buildPayERC20CallData,
135
+ buildUserOperation,
136
+ createPayID,
137
+ server_exports
138
+ };
@@ -1,5 +1,5 @@
1
- export { c as createPayID } from '../../index-BrD4MTYK.js';
1
+ export { c as createPayID } from '../../index-on2SYkvq.js';
2
2
  import 'payid-types';
3
3
  import 'ethers';
4
- import '../../types-B5dv7L-8.js';
4
+ import '../../types-B8pJQdMQ.js';
5
5
  import '../../types-DKt-zH0P.js';
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  createPayID
3
- } from "../../chunk-XWOB3JVE.js";
3
+ } from "../../chunk-2PDWRUBU.js";
4
4
  import "../../chunk-QYH3FNQ4.js";
5
5
  import "../../chunk-MXKZJKXE.js";
6
6
  import "../../chunk-JJEWYFOV.js";
7
- import "../../chunk-4MPVXPLM.js";
7
+ import "../../chunk-AXFEJV2K.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-DY-T49uU.js';
1
+ export { c as createPayID } from '../../index-CiTDNVSZ.js';
2
2
  import 'ethers';
3
3
  import 'payid-types';
4
- import '../../types-B5dv7L-8.js';
4
+ import '../../types-B8pJQdMQ.js';
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createPayID
3
- } from "../../chunk-FIMJNWJ3.js";
4
- import "../../chunk-4MPVXPLM.js";
3
+ } from "../../chunk-VJDL2PUS.js";
4
+ import "../../chunk-AXFEJV2K.js";
5
5
  import "../../chunk-5ZEKI5Y2.js";
6
6
  import "../../chunk-R5U7XKVJ.js";
7
7
  export {
@@ -1,29 +1,86 @@
1
1
  import { ethers } from 'ethers';
2
2
  import { RuleContext, RuleConfig, RuleResult } from 'payid-types';
3
- import { D as DecisionProof } from './types-B5dv7L-8.js';
3
+ import { R as RuleSource, D as DecisionProof } from './types-B8pJQdMQ.js';
4
4
 
5
+ interface UserOperation {
6
+ sender: string;
7
+ nonce: string;
8
+ initCode: string;
9
+ callData: string;
10
+ callGasLimit: string;
11
+ verificationGasLimit: string;
12
+ preVerificationGas: string;
13
+ maxFeePerGas: string;
14
+ maxPriorityFeePerGas: string;
15
+ paymasterAndData: string;
16
+ signature: string;
17
+ }
18
+
19
+ /**
20
+ * @class PayIDServer
21
+ * @description Server-side PayID engine.
22
+ *
23
+ * Digunakan ketika butuh:
24
+ * - Context V2 (env, state, oracle, risk) dengan trusted issuers
25
+ * - Build ERC-4337 UserOperation untuk bundler
26
+ *
27
+ * Signer di-inject saat construct — jangan pakai ini di browser.
28
+ *
29
+ * @example
30
+ * ```ts
31
+ * // Server/bundler side
32
+ * const server = new PayIDServer(wasmBinary, serverSigner, trustedIssuers)
33
+ *
34
+ * const { result, proof } = await server.evaluateAndProve({
35
+ * context: contextV2, // ← Context V2 dengan attestations
36
+ * authorityRule,
37
+ * payId: "pay.id/merchant",
38
+ * payer: "0xPAYER",
39
+ * receiver: "0xRECEIVER",
40
+ * asset: USDT_ADDRESS,
41
+ * amount: parseUnits("100", 6),
42
+ * verifyingContract: PAYID_VERIFIER_ADDRESS,
43
+ * ruleAuthority: RULE_AUTHORITY_ADDRESS,
44
+ * })
45
+ * ```
46
+ */
5
47
  declare class PayIDServer {
6
48
  private readonly wasm;
7
49
  private readonly signer;
8
50
  private readonly trustedIssuers?;
9
51
  private readonly debugTrace?;
10
52
  constructor(wasm: Uint8Array, signer: ethers.Signer, trustedIssuers?: Set<string> | undefined, debugTrace?: boolean | undefined);
53
+ /**
54
+ * Evaluate + generate proof dengan signer dari constructor
55
+ */
11
56
  evaluateAndProve(params: {
12
57
  context: RuleContext;
13
- authorityRule: RuleConfig;
58
+ authorityRule: RuleConfig | RuleSource;
14
59
  evaluationRule?: RuleConfig;
15
60
  payId: string;
16
61
  payer: string;
17
62
  receiver: string;
18
63
  asset: string;
19
64
  amount: bigint;
20
- ruleRegistryContract: string;
21
65
  verifyingContract: string;
66
+ ruleAuthority: string;
22
67
  ttlSeconds?: number;
23
68
  }): Promise<{
24
69
  result: RuleResult;
25
70
  proof: DecisionProof | null;
26
71
  }>;
72
+ /**
73
+ * Build ERC-4337 UserOperation dari Decision Proof
74
+ * Untuk bundler/relayer — server only
75
+ */
76
+ buildUserOperation(params: {
77
+ proof: DecisionProof;
78
+ smartAccount: string;
79
+ nonce: string;
80
+ gas: any;
81
+ targetContract: string;
82
+ paymasterAndData?: string;
83
+ }): UserOperation;
27
84
  }
28
85
 
29
86
  /**
@@ -98,4 +155,4 @@ declare namespace index {
98
155
  export { index_createPayID as createPayID };
99
156
  }
100
157
 
101
- export { createPayID as c, index as i };
158
+ export { type UserOperation as U, createPayID as c, index as i };
@@ -1,15 +1,54 @@
1
1
  import { RuleContext, RuleConfig, RuleResult } from 'payid-types';
2
2
  import { ethers } from 'ethers';
3
- import { D as DecisionProof } from './types-B5dv7L-8.js';
3
+ import { R as RuleSource, D as DecisionProof } from './types-B8pJQdMQ.js';
4
4
  import { P as PayIDSessionPolicyPayloadV1 } from './types-DKt-zH0P.js';
5
5
 
6
+ /**
7
+ * @class PayIDClient
8
+ * @description Client-side PayID engine.
9
+ *
10
+ * Fully serverless — aman dipakai di browser, mobile, edge.
11
+ * Tidak butuh issuer wallet, tidak butuh server.
12
+ *
13
+ * Untuk attestation, gunakan EAS UIDs yang di-fetch via `eas.EASClient`.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * const client = new PayIDClient(wasmBinary)
18
+ *
19
+ * // 1. Evaluate rule
20
+ * const result = await client.evaluate(context, ruleConfig)
21
+ *
22
+ * // 2. Evaluate + generate proof (payer sign sendiri)
23
+ * const { result, proof } = await client.evaluateAndProve({
24
+ * context,
25
+ * authorityRule: ruleConfig,
26
+ * payId: "pay.id/merchant",
27
+ * payer: await signer.getAddress(),
28
+ * receiver: "0xRECEIVER",
29
+ * asset: USDT_ADDRESS,
30
+ * amount: parseUnits("100", 6),
31
+ * signer,
32
+ * verifyingContract: PAYID_VERIFIER_ADDRESS,
33
+ * ruleAuthority: RULE_AUTHORITY_ADDRESS,
34
+ * })
35
+ * ```
36
+ */
6
37
  declare class PayIDClient {
7
38
  private readonly wasm;
8
39
  private readonly debugTrace?;
9
40
  constructor(wasm: Uint8Array, debugTrace?: boolean | undefined);
41
+ /**
42
+ * Pure rule evaluation — client-safe, no signing, no server
43
+ */
44
+ 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
+ */
10
49
  evaluateAndProve(params: {
11
50
  context: RuleContext;
12
- authorityRule: RuleConfig;
51
+ authorityRule: RuleConfig | RuleSource;
13
52
  evaluationRule?: RuleConfig;
14
53
  sessionPolicy?: PayIDSessionPolicyPayloadV1;
15
54
  payId: string;
@@ -18,8 +57,8 @@ declare class PayIDClient {
18
57
  asset: string;
19
58
  amount: bigint;
20
59
  signer: ethers.Signer;
21
- ruleRegistryContract: string;
22
60
  verifyingContract: string;
61
+ ruleAuthority: string;
23
62
  ttlSeconds?: number;
24
63
  }): Promise<{
25
64
  result: RuleResult;
package/dist/index.d.ts CHANGED
@@ -1,54 +1,67 @@
1
1
  import { RuleContext, RuleConfig, RuleResult } from 'payid-types';
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';
2
5
  import { ethers } from 'ethers';
3
6
  export { i as sessionPolicy } from './index-DuOeYzN2.js';
4
7
  export { i as rule } from './index-C7vziL_Z.js';
5
8
  export { i as issuer } from './index-2JCvey4-.js';
6
9
  export { i as context } from './index-BEvnPzzt.js';
7
- export { i as server } from './index-BrD4MTYK.js';
8
- export { i as client } from './index-DY-T49uU.js';
10
+ export { i as client } from './index-on2SYkvq.js';
9
11
  import './types-DKt-zH0P.js';
10
- import './types-B5dv7L-8.js';
11
-
12
- interface RuleSource {
13
- uri: string;
14
- hash?: string;
15
- }
16
-
17
- interface UserOperation {
18
- sender: string;
19
- nonce: string;
20
- initCode: string;
21
- callData: string;
22
- callGasLimit: string;
23
- verificationGasLimit: string;
24
- preVerificationGas: string;
25
- maxFeePerGas: string;
26
- maxPriorityFeePerGas: string;
27
- paymasterAndData: string;
28
- signature: string;
29
- }
30
12
 
31
13
  interface PayIDClient {
14
+ /**
15
+ * Pure rule evaluation — client-safe, no signing
16
+ */
32
17
  evaluate(context: RuleContext, rule: RuleConfig | RuleSource): Promise<RuleResult>;
18
+ /**
19
+ * Evaluate + generate EIP-712 Decision Proof
20
+ * Client sign sendiri pakai wallet mereka
21
+ */
22
+ evaluateAndProve(params: {
23
+ context: RuleContext;
24
+ authorityRule: RuleConfig | RuleSource;
25
+ evaluationRule?: RuleConfig;
26
+ payId: string;
27
+ payer: string;
28
+ receiver: string;
29
+ asset: string;
30
+ amount: bigint;
31
+ signer: ethers.Signer;
32
+ verifyingContract: string;
33
+ ruleAuthority: string;
34
+ ttlSeconds?: number;
35
+ }): Promise<{
36
+ result: RuleResult;
37
+ proof: any | null;
38
+ }>;
33
39
  }
34
40
  interface PayIDServer {
41
+ /**
42
+ * Evaluate + generate proof dengan trusted issuers
43
+ * Signer sudah di-inject saat construct PayIDServer
44
+ */
35
45
  evaluateAndProve(params: {
36
46
  context: RuleContext;
37
- authorityRule: RuleConfig;
47
+ authorityRule: RuleConfig | RuleSource;
38
48
  evaluationRule?: RuleConfig;
39
49
  payId: string;
40
50
  payer: string;
41
51
  receiver: string;
42
52
  asset: string;
43
53
  amount: bigint;
44
- signer: ethers.Signer;
45
54
  verifyingContract: string;
46
- ruleRegistryContract: string;
55
+ ruleAuthority: string;
47
56
  ttlSeconds?: number;
48
57
  }): Promise<{
49
58
  result: RuleResult;
50
59
  proof: any | null;
51
60
  }>;
61
+ /**
62
+ * Build ERC-4337 UserOperation dari Decision Proof
63
+ * Server/bundler only
64
+ */
52
65
  buildUserOperation(params: {
53
66
  proof: any;
54
67
  smartAccount: string;
@@ -122,4 +135,69 @@ declare function createPayID(params: {
122
135
  trustedIssuers?: Set<string>;
123
136
  }): PayIDClient & PayIDServer;
124
137
 
125
- export { type PayIDClient, type PayIDServer, createPayID };
138
+ /**
139
+ * @module eas
140
+ * @description EAS (Ethereum Attestation Service) helper untuk client-side.
141
+ * Fully serverless — fetch attestation UIDs langsung dari chain.
142
+ *
143
+ * EAS addresses:
144
+ * Mainnet : 0xA1207F3BBa224E2c9c3c6D5aF63D0eb1582Ce587
145
+ * Base : 0x4200000000000000000000000000000000000021
146
+ * Optimism : 0x4200000000000000000000000000000000000020
147
+ * Arbitrum : 0xbD75f629A22Dc1ceD33dDA0b68c546A1c035c458
148
+ * Sepolia : 0xC2679fBD37d54388Ce493F1DB75320D236e1815e
149
+ */
150
+
151
+ interface EASAttestation {
152
+ uid: string;
153
+ schema: string;
154
+ time: bigint;
155
+ expirationTime: bigint;
156
+ revocationTime: bigint;
157
+ attester: string;
158
+ recipient: string;
159
+ revocable: boolean;
160
+ data: string;
161
+ }
162
+ interface EASClientOptions {
163
+ easAddress: string;
164
+ provider: ethers.Provider;
165
+ }
166
+ declare class EASClient {
167
+ private readonly contract;
168
+ constructor(options: EASClientOptions);
169
+ getAttestation(uid: string): Promise<EASAttestation>;
170
+ isValid(uid: string): Promise<boolean>;
171
+ getAttestationUIDs(params: {
172
+ recipient: string;
173
+ schemaUID: string;
174
+ attester?: string;
175
+ fromBlock?: number;
176
+ }): Promise<string[]>;
177
+ /**
178
+ * One-liner: dapat valid UIDs siap di-pass ke payETH/payERC20
179
+ *
180
+ * @example
181
+ * const eas = new EASClient({ easAddress: EAS_ADDRESSES[11155111], provider })
182
+ * const uids = await eas.getValidUIDs({ recipient: payerAddress, schemaUID: KYC_SCHEMA_UID })
183
+ * await payWithPayID.payERC20(decision, sig, uids)
184
+ */
185
+ getValidUIDs(params: {
186
+ recipient: string;
187
+ schemaUID: string;
188
+ attester?: string;
189
+ fromBlock?: number;
190
+ }): Promise<string[]>;
191
+ }
192
+ declare const EAS_ADDRESSES: Record<number, string>;
193
+
194
+ type eas_EASAttestation = EASAttestation;
195
+ type eas_EASClient = EASClient;
196
+ declare const eas_EASClient: typeof EASClient;
197
+ type eas_EASClientOptions = EASClientOptions;
198
+ declare const eas_EAS_ADDRESSES: typeof EAS_ADDRESSES;
199
+ declare namespace eas {
200
+ export { type eas_EASAttestation as EASAttestation, eas_EASClient as EASClient, type eas_EASClientOptions as EASClientOptions, eas_EAS_ADDRESSES as EAS_ADDRESSES };
201
+ }
202
+
203
+ export { type PayIDClient, type PayIDServer, createPayID, eas };
package/dist/index.js CHANGED
@@ -13,50 +13,25 @@ import {
13
13
  } from "./chunk-ATWJEWZH.js";
14
14
  import {
15
15
  client_exports
16
- } from "./chunk-XWOB3JVE.js";
16
+ } from "./chunk-2PDWRUBU.js";
17
17
  import "./chunk-QYH3FNQ4.js";
18
18
  import "./chunk-MXKZJKXE.js";
19
19
  import "./chunk-JJEWYFOV.js";
20
20
  import {
21
+ buildPayERC20CallData,
22
+ buildPayETHCallData,
23
+ buildUserOperation,
21
24
  server_exports
22
- } from "./chunk-FIMJNWJ3.js";
25
+ } from "./chunk-VJDL2PUS.js";
23
26
  import {
24
27
  evaluate,
25
28
  generateDecisionProof,
26
29
  resolveRule
27
- } from "./chunk-4MPVXPLM.js";
30
+ } from "./chunk-AXFEJV2K.js";
28
31
  import "./chunk-5ZEKI5Y2.js";
29
- import "./chunk-R5U7XKVJ.js";
30
-
31
- // src/erc4337/build.ts
32
- import { ethers } from "ethers";
33
- function buildPayCallData(contractAddress, proof) {
34
- const iface = new ethers.Interface([
35
- "function pay(bytes payload, bytes signature)"
36
- ]);
37
- return iface.encodeFunctionData("pay", [
38
- ethers.toUtf8Bytes(JSON.stringify(proof.payload)),
39
- proof.signature
40
- ]);
41
- }
42
-
43
- // src/erc4337/userop.ts
44
- function buildUserOperation(params) {
45
- return {
46
- sender: params.sender,
47
- nonce: params.nonce,
48
- initCode: params.initCode ?? "0x",
49
- callData: params.callData,
50
- callGasLimit: params.gas.callGasLimit,
51
- verificationGasLimit: params.gas.verificationGasLimit,
52
- preVerificationGas: params.gas.preVerificationGas,
53
- maxFeePerGas: params.gas.maxFeePerGas,
54
- maxPriorityFeePerGas: params.gas.maxPriorityFeePerGas,
55
- paymasterAndData: params.paymasterAndData ?? "0x",
56
- signature: "0x"
57
- // signed later by smart account
58
- };
59
- }
32
+ import {
33
+ __export
34
+ } from "./chunk-R5U7XKVJ.js";
60
35
 
61
36
  // src/core/payid.ts
62
37
  function isRuleSource(rule) {
@@ -69,118 +44,18 @@ var PayID = class {
69
44
  this.trustedIssuers = trustedIssuers;
70
45
  }
71
46
  /**
72
- * Evaluate a rule set against a given context using the PayID WASM engine.
73
- *
74
- * ## Responsibility
75
- *
76
- * This method performs **pure rule evaluation only**:
77
- * - Resolves the rule configuration (inline or via RuleSource)
78
- * - Executes the rule engine
79
- * - Returns an ALLOW / REJECT decision
80
- *
81
- * This method does NOT:
82
- * - Generate decision proofs
83
- * - Interact with on-chain rule registries
84
- * - Enforce rule ownership or authority
85
- * - Perform any signing
86
- *
87
- * ## Environment
88
- *
89
- * This method is **client-safe** and may be called from:
90
- * - Browsers
91
- * - Mobile apps
92
- * - Edge runtimes
93
- * - Backend services
94
- *
95
- * ## Rule source behavior
96
- *
97
- * - If `rule` is a `RuleConfig`, it is evaluated directly.
98
- * - If `rule` is a `RuleSource`, it is resolved off-chain
99
- * before evaluation.
100
- *
101
- * @param context
102
- * Rule execution context (transaction data, payId, etc.).
103
- *
104
- * @param rule
105
- * Rule configuration to evaluate, either:
106
- * - An inline `RuleConfig`, or
107
- * - A `RuleSource` that resolves to a `RuleConfig`.
108
- *
109
- * @returns
110
- * A `RuleResult` indicating whether the rule allows or
111
- * rejects the given context.
112
- *
113
- * @throws
114
- * May throw if rule resolution or evaluation fails.
47
+ * Pure evaluation client-safe
115
48
  */
116
49
  async evaluate(context, rule) {
117
50
  const config = isRuleSource(rule) ? (await resolveRule(rule)).config : rule;
118
- return evaluate(this.wasm, context, config, { debug: this.debugTrace, trustedIssuers: this.trustedIssuers });
51
+ return evaluate(this.wasm, context, config, {
52
+ debug: this.debugTrace,
53
+ trustedIssuers: this.trustedIssuers
54
+ });
119
55
  }
120
56
  /**
121
- * Evaluate a payment intent against PayID rules and (if allowed)
122
- * generate an off-chain Decision Proof for on-chain verification.
123
- *
124
- * ## Conceptual model
125
- *
126
- * - `authorityRule` defines the **authoritative rule set**
127
- * registered on-chain (NFT / combined rule).
128
- * - `evaluationRule` (optional) is an **off-chain override**
129
- * used only for evaluation (e.g. QR / session / intent rule).
130
- * - On-chain verification ALWAYS references `authorityRule`.
131
- *
132
- * Invariant:
133
- * - Evaluation may use `authorityRule ∧ evaluationRule`
134
- * - Proof MUST reference `authorityRule` only
135
- *
136
- * @param params
137
- * @param params.context
138
- * Normalized rule execution context (tx, payId, etc.)
139
- *
140
- * @param params.authorityRule
141
- * The authoritative rule set owned by the receiver and
142
- * registered in the on-chain rule registry.
143
- * This rule defines on-chain sovereignty.
144
- *
145
- * @param params.evaluationRule
146
- * Optional evaluation override applied off-chain only
147
- * (e.g. QR rule, ephemeral constraint).
148
- * If omitted, `authorityRule` is used for evaluation.
149
- *
150
- * @param params.payId
151
- * PayID identifier associated with the receiver.
152
- *
153
- * @param params.payer
154
- * Address initiating the payment and signing the decision proof.
155
- *
156
- * @param params.receiver
157
- * Address receiving the payment and owning the authoritative rule.
158
- *
159
- * @param params.asset
160
- * Asset address to be transferred (address(0) for native ETH).
161
- *
162
- * @param params.amount
163
- * Amount to be transferred (uint256 semantics).
164
- *
165
- * @param params.signer
166
- * Signer corresponding to `payer`, used to sign the EIP-712
167
- * decision proof payload.
168
- *
169
- * @param params.ruleRegistryContract
170
- * Address of the on-chain rule registry / storage contract
171
- * used by the verifier to resolve `ruleSetHash`.
172
- *
173
- * @param params.ttlSeconds
174
- * Optional proof validity duration (seconds).
175
- * Defaults to implementation-defined TTL.
176
- *
177
- * @returns
178
- * An object containing:
179
- * - `result`: rule evaluation result (ALLOW / REJECT)
180
- * - `proof`: signed decision proof if allowed, otherwise `null`
181
- *
182
- * @throws
183
- * May throw if rule resolution, evaluation, or signing fails.
57
+ * Evaluate + generate Decision Proof
58
+ * FIX: parameter rename ruleRegistryContract ruleAuthority
184
59
  */
185
60
  async evaluateAndProve(params) {
186
61
  const authorityConfig = isRuleSource(params.authorityRule) ? (await resolveRule(params.authorityRule)).config : params.authorityRule;
@@ -207,73 +82,18 @@ var PayID = class {
207
82
  ruleConfig: authorityConfig,
208
83
  signer: params.signer,
209
84
  verifyingContract: params.verifyingContract,
210
- ruleRegistryContract: params.ruleRegistryContract,
85
+ ruleAuthority: params.ruleAuthority,
211
86
  ttlSeconds: params.ttlSeconds
212
87
  });
213
88
  return { result, proof };
214
89
  }
215
90
  /**
216
- * Build an ERC-4337 UserOperation that executes a PayID payment
217
- * using a previously generated Decision Proof.
218
- *
219
- * ## Responsibility
220
- *
221
- * This function:
222
- * - Encodes the PayID `pay(...)` calldata using the provided proof
223
- * - Wraps it into an ERC-4337 UserOperation
224
- *
225
- * This function does NOT:
226
- * - Evaluate rules
227
- * - Generate decision proofs
228
- * - Perform any signature validation
229
- *
230
- * ## Environment constraint
231
- *
232
- * This function is **server-only** and MUST NOT be called in a browser:
233
- * - It is intended for bundlers, relayers, or backend services
234
- * - Client-side apps should only generate the proof
235
- *
236
- * A runtime guard is enforced to prevent accidental browser usage.
237
- *
238
- * @param params
239
- * @param params.proof
240
- * A valid Decision Proof generated by `evaluateAndProve`.
241
- *
242
- * @param params.smartAccount
243
- * The ERC-4337 smart account address that will submit the UserOperation.
244
- *
245
- * @param params.nonce
246
- * Current nonce of the smart account.
247
- *
248
- * @param params.gas
249
- * Gas parameters for the UserOperation
250
- * (callGasLimit, verificationGasLimit, preVerificationGas,
251
- * maxFeePerGas, maxPriorityFeePerGas).
252
- *
253
- * @param params.targetContract
254
- * Address of the PayID-compatible payment contract
255
- * (e.g. PayWithPayID).
256
- *
257
- * @param params.paymasterAndData
258
- * Optional paymaster data for sponsored transactions.
259
- *
260
- * @returns
261
- * A fully constructed ERC-4337 UserOperation ready to be
262
- * submitted to a bundler.
263
- *
264
- * @throws
265
- * Throws if called in a browser environment.
91
+ * Build ERC-4337 UserOperation
266
92
  */
267
93
  buildUserOperation(params) {
268
- if (typeof globalThis !== "undefined" && "document" in globalThis) {
269
- throw new Error(
270
- "buildUserOperation must not be called in browser"
271
- );
272
- }
273
- const callData = buildPayCallData(
274
- params.targetContract,
275
- params.proof
276
- );
94
+ const attestationUIDs = params.attestationUIDs ?? [];
95
+ const isETH = params.paymentType === "eth";
96
+ const callData = isETH ? buildPayETHCallData(params.targetContract, params.proof, attestationUIDs) : buildPayERC20CallData(params.targetContract, params.proof, attestationUIDs);
277
97
  return buildUserOperation({
278
98
  sender: params.smartAccount,
279
99
  nonce: params.nonce,
@@ -292,12 +112,104 @@ function createPayID(params) {
292
112
  params.trustedIssuers
293
113
  );
294
114
  }
115
+
116
+ // src/eas.ts
117
+ var eas_exports = {};
118
+ __export(eas_exports, {
119
+ EASClient: () => EASClient,
120
+ EAS_ADDRESSES: () => EAS_ADDRESSES
121
+ });
122
+ import { ethers } from "ethers";
123
+ var EAS_ABI = [
124
+ "function getAttestation(bytes32 uid) external view returns (tuple(bytes32 uid, bytes32 schema, uint64 time, uint64 expirationTime, uint64 revocationTime, bytes32 refUID, address attester, address recipient, bool revocable, bytes data))",
125
+ "function isAttestationValid(bytes32 uid) external view returns (bool)",
126
+ "event Attested(address indexed recipient, address indexed attester, bytes32 uid, bytes32 indexed schema)"
127
+ ];
128
+ var EASClient = class {
129
+ contract;
130
+ constructor(options) {
131
+ this.contract = new ethers.Contract(
132
+ options.easAddress,
133
+ EAS_ABI,
134
+ options.provider
135
+ );
136
+ }
137
+ async getAttestation(uid) {
138
+ const raw = await this.contract.getFunction("getAttestation")(uid);
139
+ return {
140
+ uid: raw.uid,
141
+ schema: raw.schema,
142
+ time: raw.time,
143
+ expirationTime: raw.expirationTime,
144
+ revocationTime: raw.revocationTime,
145
+ attester: raw.attester,
146
+ recipient: raw.recipient,
147
+ revocable: raw.revocable,
148
+ data: raw.data
149
+ };
150
+ }
151
+ async isValid(uid) {
152
+ const result = await this.contract.getFunction("isAttestationValid")(uid);
153
+ return result;
154
+ }
155
+ async getAttestationUIDs(params) {
156
+ const attestedFilter = this.contract.filters["Attested"];
157
+ if (!attestedFilter) {
158
+ throw new Error("EAS: Attested event not found in ABI");
159
+ }
160
+ const filter = attestedFilter(
161
+ params.recipient,
162
+ params.attester ?? null,
163
+ null,
164
+ params.schemaUID
165
+ );
166
+ const events = await this.contract.queryFilter(
167
+ filter,
168
+ params.fromBlock ?? 0
169
+ );
170
+ const uids = events.map(
171
+ (e) => e.args["uid"]
172
+ );
173
+ const validUids = [];
174
+ for (const uid of uids) {
175
+ const valid = await this.isValid(uid);
176
+ if (valid) validUids.push(uid);
177
+ }
178
+ return validUids;
179
+ }
180
+ /**
181
+ * One-liner: dapat valid UIDs siap di-pass ke payETH/payERC20
182
+ *
183
+ * @example
184
+ * const eas = new EASClient({ easAddress: EAS_ADDRESSES[11155111], provider })
185
+ * const uids = await eas.getValidUIDs({ recipient: payerAddress, schemaUID: KYC_SCHEMA_UID })
186
+ * await payWithPayID.payERC20(decision, sig, uids)
187
+ */
188
+ async getValidUIDs(params) {
189
+ return this.getAttestationUIDs(params);
190
+ }
191
+ };
192
+ var EAS_ADDRESSES = {
193
+ 1: "0xA1207F3BBa224E2c9c3c6D5aF63D0eb1582Ce587",
194
+ // Ethereum Mainnet
195
+ 8453: "0x4200000000000000000000000000000000000021",
196
+ // Base
197
+ 10: "0x4200000000000000000000000000000000000020",
198
+ // Optimism
199
+ 42161: "0xbD75f629A22Dc1ceD33dDA0b68c546A1c035c458",
200
+ // Arbitrum One
201
+ 11155111: "0xC2679fBD37d54388Ce493F1DB75320D236e1815e",
202
+ // Sepolia
203
+ 4202: "0xC2679fBD37d54388Ce493F1DB75320D236e1815e"
204
+ // Lisk Sepolia
205
+ };
295
206
  export {
296
- server_exports as client,
207
+ client_exports as client,
297
208
  context_exports as context,
298
209
  createPayID,
210
+ eas_exports as eas,
299
211
  issuer_exports as issuer,
300
212
  rule_exports as rule,
301
- client_exports as server,
213
+ server_exports as server,
302
214
  sessionPolicy_exports as sessionPolicy
303
215
  };
@@ -1,3 +1,8 @@
1
+ interface RuleSource {
2
+ uri: string;
3
+ hash?: string;
4
+ }
5
+
1
6
  interface DecisionPayload {
2
7
  version: string;
3
8
  payId: string;
@@ -18,4 +23,4 @@ interface DecisionProof {
18
23
  signature: string;
19
24
  }
20
25
 
21
- export type { DecisionProof as D };
26
+ export type { DecisionProof as D, RuleSource as R };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payid",
3
- "version": "0.3.6",
3
+ "version": "0.3.7",
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.5",
41
- "payid-types": "^0.1.5"
40
+ "payid-rule-engine": "^0.1.6",
41
+ "payid-types": "^0.1.7"
42
42
  },
43
43
  "files": [
44
44
  "dist"
@@ -1,72 +0,0 @@
1
- import {
2
- evaluate,
3
- generateDecisionProof,
4
- resolveRule
5
- } from "./chunk-4MPVXPLM.js";
6
- import {
7
- __export
8
- } from "./chunk-R5U7XKVJ.js";
9
-
10
- // src/core/server/index.ts
11
- var server_exports = {};
12
- __export(server_exports, {
13
- createPayID: () => createPayID
14
- });
15
-
16
- // src/core/server/server.ts
17
- function isRuleSource(rule) {
18
- return typeof rule === "object" && rule !== null && "uri" in rule;
19
- }
20
- var PayIDServer = class {
21
- constructor(wasm, signer, trustedIssuers, debugTrace) {
22
- this.wasm = wasm;
23
- this.signer = signer;
24
- this.trustedIssuers = trustedIssuers;
25
- this.debugTrace = debugTrace;
26
- }
27
- async evaluateAndProve(params) {
28
- const authorityConfig = isRuleSource(params.authorityRule) ? (await resolveRule(params.authorityRule)).config : params.authorityRule;
29
- const evalConfig = params.evaluationRule ?? authorityConfig;
30
- const result = await evaluate(
31
- this.wasm,
32
- params.context,
33
- evalConfig,
34
- {
35
- debug: this.debugTrace,
36
- trustedIssuers: this.trustedIssuers
37
- }
38
- );
39
- if (result.decision !== "ALLOW") {
40
- return { result, proof: null };
41
- }
42
- const proof = await generateDecisionProof({
43
- payId: params.payId,
44
- payer: params.payer,
45
- receiver: params.receiver,
46
- asset: params.asset,
47
- amount: params.amount,
48
- context: params.context,
49
- ruleConfig: params.authorityRule,
50
- signer: this.signer,
51
- verifyingContract: params.verifyingContract,
52
- ruleRegistryContract: params.ruleRegistryContract,
53
- ttlSeconds: params.ttlSeconds
54
- });
55
- return { result, proof };
56
- }
57
- };
58
-
59
- // src/core/server/index.ts
60
- function createPayID(params) {
61
- return new PayIDServer(
62
- params.wasm,
63
- params.signer,
64
- params.trustedIssuers,
65
- params.debugTrace ?? false
66
- );
67
- }
68
-
69
- export {
70
- createPayID,
71
- server_exports
72
- };