payid 0.3.9 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +689 -18
- package/dist/index.js +780 -52
- package/package.json +3 -3
- package/dist/chunk-5ZEKI5Y2.js +0 -18
- package/dist/chunk-7U3P7XJE.js +0 -67
- package/dist/chunk-AOKLY2QN.js +0 -24
- package/dist/chunk-ATWJEWZH.js +0 -47
- package/dist/chunk-JJEWYFOV.js +0 -42
- package/dist/chunk-JRVCGSKK.js +0 -30
- package/dist/chunk-METOE7DV.js +0 -264
- package/dist/chunk-MXKZJKXE.js +0 -33
- package/dist/chunk-QYH3FNQ4.js +0 -19
- package/dist/chunk-R5U7XKVJ.js +0 -16
- package/dist/chunk-RCXMRX4F.js +0 -54
- package/dist/chunk-SIHQPH55.js +0 -139
- package/dist/chunk-UBGZH6HB.js +0 -90
- package/dist/context/index.d.ts +0 -3
- package/dist/context/index.js +0 -8
- package/dist/core/client/index.d.ts +0 -5
- package/dist/core/client/index.js +0 -12
- package/dist/core/server/index.d.ts +0 -4
- package/dist/core/server/index.js +0 -9
- package/dist/index-2JCvey4-.d.ts +0 -23
- package/dist/index-BEvnPzzt.d.ts +0 -160
- package/dist/index-C7vziL_Z.d.ts +0 -150
- package/dist/index-CiTDNVSZ.d.ts +0 -158
- package/dist/index-DuOeYzN2.d.ts +0 -118
- package/dist/index-on2SYkvq.d.ts +0 -114
- package/dist/issuer/index.d.ts +0 -3
- package/dist/issuer/index.js +0 -16
- package/dist/rule/index.d.ts +0 -2
- package/dist/rule/index.js +0 -15
- package/dist/sessionPolicy/index.d.ts +0 -4
- package/dist/sessionPolicy/index.js +0 -13
- package/dist/types-B8pJQdMQ.d.ts +0 -26
- package/dist/types-DKt-zH0P.d.ts +0 -15
package/dist/index.js
CHANGED
|
@@ -1,37 +1,382 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
3
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
4
|
+
}) : x)(function(x) {
|
|
5
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
6
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
|
+
});
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
// src/evaluate.ts
|
|
14
|
+
import { executeRule, preprocessContextV2 } from "payid-rule-engine";
|
|
15
|
+
|
|
16
|
+
// src/normalize.ts
|
|
17
|
+
function normalizeContext(ctx) {
|
|
18
|
+
return {
|
|
19
|
+
...ctx,
|
|
20
|
+
tx: {
|
|
21
|
+
...ctx.tx,
|
|
22
|
+
sender: ctx.tx.sender?.toLowerCase(),
|
|
23
|
+
receiver: ctx.tx.receiver?.toLowerCase(),
|
|
24
|
+
asset: ctx.tx.asset.toUpperCase()
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// src/core/dicisionTrace.ts
|
|
30
|
+
function toBigIntSafe(v) {
|
|
31
|
+
try {
|
|
32
|
+
if (typeof v === "bigint") return v;
|
|
33
|
+
if (typeof v === "number" && Number.isFinite(v)) return BigInt(Math.trunc(v));
|
|
34
|
+
if (typeof v === "string" && v !== "") return BigInt(v);
|
|
35
|
+
return null;
|
|
36
|
+
} catch {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function resolveField(obj, fieldExpr) {
|
|
41
|
+
const [path, ...transforms] = fieldExpr.split("|");
|
|
42
|
+
let value = path?.split(".").reduce((o, k) => o?.[k], obj);
|
|
43
|
+
for (const t of transforms) {
|
|
44
|
+
if (value === void 0 || value === null) break;
|
|
45
|
+
if (t.startsWith("div:")) {
|
|
46
|
+
const n = Number(t.slice(4));
|
|
47
|
+
value = Number(value) / n;
|
|
48
|
+
} else if (t.startsWith("mod:")) {
|
|
49
|
+
const n = BigInt(t.slice(4));
|
|
50
|
+
value = BigInt(value) % n;
|
|
51
|
+
} else if (t === "abs") {
|
|
52
|
+
value = Math.abs(Number(value));
|
|
53
|
+
} else if (t === "hour") {
|
|
54
|
+
value = new Date(Number(value) * 1e3).getUTCHours();
|
|
55
|
+
} else if (t === "day") {
|
|
56
|
+
value = new Date(Number(value) * 1e3).getUTCDay();
|
|
57
|
+
} else if (t === "date") {
|
|
58
|
+
value = new Date(Number(value) * 1e3).getUTCDate();
|
|
59
|
+
} else if (t === "month") {
|
|
60
|
+
value = new Date(Number(value) * 1e3).getUTCMonth() + 1;
|
|
61
|
+
} else if (t === "len") {
|
|
62
|
+
value = String(value).length;
|
|
63
|
+
} else if (t === "lower") {
|
|
64
|
+
value = String(value).toLowerCase();
|
|
65
|
+
} else if (t === "upper") {
|
|
66
|
+
value = String(value).toUpperCase();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return value;
|
|
70
|
+
}
|
|
71
|
+
function resolveValue(context, value) {
|
|
72
|
+
if (typeof value === "string" && value.startsWith("$")) {
|
|
73
|
+
return resolveField(context, value.slice(1));
|
|
74
|
+
}
|
|
75
|
+
return value;
|
|
76
|
+
}
|
|
77
|
+
function evaluateCondition(actual, op, expected) {
|
|
78
|
+
switch (op) {
|
|
79
|
+
case ">=":
|
|
80
|
+
case "<=":
|
|
81
|
+
case ">":
|
|
82
|
+
case "<": {
|
|
83
|
+
const a = toBigIntSafe(actual);
|
|
84
|
+
const b = toBigIntSafe(expected);
|
|
85
|
+
if (a === null || b === null) return false;
|
|
86
|
+
if (op === ">=") return a >= b;
|
|
87
|
+
if (op === "<=") return a <= b;
|
|
88
|
+
if (op === ">") return a > b;
|
|
89
|
+
if (op === "<") return a < b;
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
case "==":
|
|
93
|
+
return actual == expected;
|
|
94
|
+
case "!=":
|
|
95
|
+
return actual != expected;
|
|
96
|
+
case "in":
|
|
97
|
+
return Array.isArray(expected) && expected.includes(actual);
|
|
98
|
+
case "not_in":
|
|
99
|
+
return Array.isArray(expected) && !expected.includes(actual);
|
|
100
|
+
case "between":
|
|
101
|
+
return Array.isArray(expected) && actual >= expected[0] && actual <= expected[1];
|
|
102
|
+
case "not_between":
|
|
103
|
+
return Array.isArray(expected) && !(actual >= expected[0] && actual <= expected[1]);
|
|
104
|
+
case "exists":
|
|
105
|
+
return actual !== void 0 && actual !== null;
|
|
106
|
+
case "not_exists":
|
|
107
|
+
return actual === void 0 || actual === null;
|
|
108
|
+
default:
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function traceCondition(context, ruleId, cond) {
|
|
113
|
+
const actual = resolveField(context, cond.field);
|
|
114
|
+
const expected = resolveValue(context, cond.value);
|
|
115
|
+
const pass = evaluateCondition(actual, cond.op, expected);
|
|
116
|
+
return {
|
|
117
|
+
ruleId,
|
|
118
|
+
field: cond.field,
|
|
119
|
+
op: cond.op,
|
|
120
|
+
expected: cond.value,
|
|
121
|
+
actual,
|
|
122
|
+
result: actual === void 0 ? "FAIL" : pass ? "PASS" : "FAIL"
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
function traceRule(context, rule) {
|
|
126
|
+
if ("if" in rule) {
|
|
127
|
+
return [traceCondition(context, rule.id, rule.if)];
|
|
128
|
+
}
|
|
129
|
+
if ("conditions" in rule) {
|
|
130
|
+
return rule.conditions.map((cond) => traceCondition(context, rule.id, cond));
|
|
131
|
+
}
|
|
132
|
+
if ("rules" in rule) {
|
|
133
|
+
return rule.rules.flatMap((child) => traceRule(context, child));
|
|
134
|
+
}
|
|
135
|
+
return [];
|
|
136
|
+
}
|
|
137
|
+
function buildDecisionTrace(context, ruleConfig) {
|
|
138
|
+
return ruleConfig.rules.flatMap((rule) => traceRule(context, rule));
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// src/evaluate.ts
|
|
142
|
+
async function evaluate(context, ruleConfig, options, wasmBinary) {
|
|
143
|
+
if (!context || typeof context !== "object") {
|
|
144
|
+
throw new Error("evaluate(): context is required");
|
|
145
|
+
}
|
|
146
|
+
if (!context.tx) {
|
|
147
|
+
throw new Error("evaluate(): context.tx is required");
|
|
148
|
+
}
|
|
149
|
+
if (!ruleConfig || typeof ruleConfig !== "object") {
|
|
150
|
+
throw new Error("evaluate(): ruleConfig is required");
|
|
151
|
+
}
|
|
152
|
+
let result;
|
|
153
|
+
try {
|
|
154
|
+
const preparedContext = options?.trustedIssuers ? preprocessContextV2(
|
|
155
|
+
context,
|
|
156
|
+
ruleConfig,
|
|
157
|
+
options.trustedIssuers
|
|
158
|
+
) : context;
|
|
159
|
+
const normalized = normalizeContext(preparedContext);
|
|
160
|
+
let wasmForEngine;
|
|
161
|
+
if (wasmBinary == null) {
|
|
162
|
+
wasmForEngine = void 0;
|
|
163
|
+
} else if (typeof Buffer !== "undefined") {
|
|
164
|
+
wasmForEngine = Buffer.isBuffer(wasmBinary) ? wasmBinary : Buffer.from(wasmBinary);
|
|
165
|
+
} else {
|
|
166
|
+
wasmForEngine = wasmBinary;
|
|
167
|
+
}
|
|
168
|
+
result = await executeRule(
|
|
169
|
+
normalized,
|
|
170
|
+
ruleConfig,
|
|
171
|
+
wasmForEngine
|
|
172
|
+
);
|
|
173
|
+
} catch (err) {
|
|
174
|
+
return {
|
|
175
|
+
decision: "REJECT",
|
|
176
|
+
code: "CONTEXT_OR_ENGINE_ERROR",
|
|
177
|
+
reason: err?.message ?? "rule evaluation failed"
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
if (result.decision !== "ALLOW" && result.decision !== "REJECT") {
|
|
181
|
+
return {
|
|
182
|
+
decision: "REJECT",
|
|
183
|
+
code: "INVALID_ENGINE_OUTPUT",
|
|
184
|
+
reason: "invalid decision value"
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
const baseResult = {
|
|
188
|
+
decision: result.decision,
|
|
189
|
+
code: result.code || "UNKNOWN",
|
|
190
|
+
reason: result.reason
|
|
191
|
+
};
|
|
192
|
+
if (options?.debug) {
|
|
193
|
+
return {
|
|
194
|
+
...baseResult,
|
|
195
|
+
debug: {
|
|
196
|
+
trace: buildDecisionTrace(context, ruleConfig)
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
return baseResult;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// src/utils/subtle.ts
|
|
204
|
+
var subtleCrypto = globalThis.crypto?.subtle ?? __require("crypto").webcrypto.subtle;
|
|
205
|
+
|
|
206
|
+
// src/utils/fetchJson.ts
|
|
207
|
+
async function fetchJsonWithHashCheck(url, expectedHash) {
|
|
208
|
+
const res = await fetch(url);
|
|
209
|
+
if (!res.ok) {
|
|
210
|
+
throw new Error("RULE_FETCH_FAILED");
|
|
211
|
+
}
|
|
212
|
+
const buffer = await res.arrayBuffer();
|
|
213
|
+
if (expectedHash) {
|
|
214
|
+
const digest = await subtleCrypto.digest(
|
|
215
|
+
"SHA-256",
|
|
216
|
+
buffer
|
|
217
|
+
);
|
|
218
|
+
const actualHash = bufferToHex(digest);
|
|
219
|
+
if (actualHash !== expectedHash) {
|
|
220
|
+
throw new Error("RULE_HASH_MISMATCH");
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return JSON.parse(new TextDecoder().decode(buffer));
|
|
224
|
+
}
|
|
225
|
+
function bufferToHex(buffer) {
|
|
226
|
+
return [...new Uint8Array(buffer)].map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// src/resolver/resolver.ts
|
|
230
|
+
async function resolveRule(source) {
|
|
231
|
+
const { uri, hash: hash2 } = source;
|
|
232
|
+
if (uri.startsWith("inline://")) {
|
|
233
|
+
const encoded = uri.replace("inline://", "");
|
|
234
|
+
const json = JSON.parse(atob(encoded));
|
|
235
|
+
return { config: json, source };
|
|
236
|
+
}
|
|
237
|
+
if (uri.startsWith("ipfs://")) {
|
|
238
|
+
const cid = uri.replace("ipfs://", "");
|
|
239
|
+
const url = `https://ipfs.io/ipfs/${cid}`;
|
|
240
|
+
const config = await fetchJsonWithHashCheck(url, hash2);
|
|
241
|
+
return { config, source };
|
|
242
|
+
}
|
|
243
|
+
if (uri.startsWith("http://") || uri.startsWith("https://")) {
|
|
244
|
+
const config = await fetchJsonWithHashCheck(uri, hash2);
|
|
245
|
+
return { config, source };
|
|
246
|
+
}
|
|
247
|
+
throw new Error("UNSUPPORTED_RULE_URI");
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// src/decision-proof/hash.ts
|
|
251
|
+
import { keccak256 } from "ethers";
|
|
252
|
+
function stableStringify(obj) {
|
|
253
|
+
if (Array.isArray(obj)) {
|
|
254
|
+
return `[${obj.map(stableStringify).join(",")}]`;
|
|
255
|
+
}
|
|
256
|
+
if (obj && typeof obj === "object") {
|
|
257
|
+
return `{${Object.keys(obj).sort().map(
|
|
258
|
+
(k) => `"${k}":${stableStringify(obj[k])}`
|
|
259
|
+
).join(",")}}`;
|
|
260
|
+
}
|
|
261
|
+
return JSON.stringify(obj);
|
|
262
|
+
}
|
|
263
|
+
function hashContext(context) {
|
|
264
|
+
return keccak256(Buffer.from(stableStringify(context)));
|
|
265
|
+
}
|
|
266
|
+
function hashRuleSet(ruleConfig) {
|
|
267
|
+
return keccak256(Buffer.from(stableStringify(ruleConfig)));
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// src/decision-proof/generate.ts
|
|
271
|
+
import { ethers, ZeroAddress } from "ethers";
|
|
272
|
+
|
|
273
|
+
// src/utils/randomHex.ts
|
|
274
|
+
function randomHex(bytes) {
|
|
275
|
+
if (typeof globalThis.crypto !== "undefined" && crypto.getRandomValues) {
|
|
276
|
+
const arr = new Uint8Array(bytes);
|
|
277
|
+
crypto.getRandomValues(arr);
|
|
278
|
+
return "0x" + Array.from(arr, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
279
|
+
}
|
|
280
|
+
const { randomBytes } = __require("crypto");
|
|
281
|
+
return "0x" + randomBytes(bytes).toString("hex");
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// src/decision-proof/generate.ts
|
|
285
|
+
var hash = (v) => ethers.keccak256(ethers.toUtf8Bytes(v));
|
|
286
|
+
async function generateDecisionProof(params) {
|
|
287
|
+
const now = params.blockTimestamp ?? Math.floor(Date.now() / 1e3);
|
|
288
|
+
const issuedAt = now - 30;
|
|
289
|
+
const expiresAt = now + (params.ttlSeconds ?? 300);
|
|
290
|
+
const chainId = params.chainId ?? Number((await params.signer.provider.getNetwork()).chainId);
|
|
291
|
+
const requiresAttestation = Array.isArray(params.ruleConfig?.requires) && params.ruleConfig.requires.length > 0;
|
|
292
|
+
const payload = {
|
|
293
|
+
version: hash("2"),
|
|
294
|
+
payId: hash(params.payId),
|
|
295
|
+
payer: params.payer,
|
|
296
|
+
receiver: params.receiver,
|
|
297
|
+
asset: params.asset,
|
|
298
|
+
amount: params.amount,
|
|
299
|
+
contextHash: hashContext(params.context),
|
|
300
|
+
ruleSetHash: hashRuleSet(params.ruleConfig),
|
|
301
|
+
ruleAuthority: params.ruleAuthority ?? ZeroAddress,
|
|
302
|
+
issuedAt: BigInt(issuedAt),
|
|
303
|
+
expiresAt: BigInt(expiresAt),
|
|
304
|
+
nonce: randomHex(32),
|
|
305
|
+
requiresAttestation
|
|
306
|
+
};
|
|
307
|
+
const domain = {
|
|
308
|
+
name: "PAY.ID Decision",
|
|
309
|
+
version: "2",
|
|
310
|
+
chainId,
|
|
311
|
+
verifyingContract: params.verifyingContract
|
|
312
|
+
};
|
|
313
|
+
const types = {
|
|
314
|
+
Decision: [
|
|
315
|
+
{ name: "version", type: "bytes32" },
|
|
316
|
+
{ name: "payId", type: "bytes32" },
|
|
317
|
+
{ name: "payer", type: "address" },
|
|
318
|
+
{ name: "receiver", type: "address" },
|
|
319
|
+
{ name: "asset", type: "address" },
|
|
320
|
+
{ name: "amount", type: "uint256" },
|
|
321
|
+
{ name: "contextHash", type: "bytes32" },
|
|
322
|
+
{ name: "ruleSetHash", type: "bytes32" },
|
|
323
|
+
{ name: "ruleAuthority", type: "address" },
|
|
324
|
+
{ name: "issuedAt", type: "uint64" },
|
|
325
|
+
{ name: "expiresAt", type: "uint64" },
|
|
326
|
+
{ name: "nonce", type: "bytes32" },
|
|
327
|
+
{ name: "requiresAttestation", type: "bool" }
|
|
328
|
+
]
|
|
329
|
+
};
|
|
330
|
+
const signature = await params.signer.signTypedData(domain, types, payload);
|
|
331
|
+
const recovered = ethers.verifyTypedData(domain, types, payload, signature);
|
|
332
|
+
if (recovered.toLowerCase() !== params.payer.toLowerCase()) {
|
|
333
|
+
throw new Error("SIGNATURE_MISMATCH");
|
|
334
|
+
}
|
|
335
|
+
return { payload, signature };
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// src/erc4337/build.ts
|
|
339
|
+
import { ethers as ethers2 } from "ethers";
|
|
340
|
+
var PAY_WITH_PAYID_ABI = [
|
|
341
|
+
// ETH payment — attestationUIDs adalah EAS UIDs, pass [] jika tidak perlu
|
|
342
|
+
"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",
|
|
343
|
+
// ERC20 payment
|
|
344
|
+
"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)"
|
|
345
|
+
];
|
|
346
|
+
function buildPayETHCallData(contractAddress, proof, attestationUIDs = []) {
|
|
347
|
+
const iface = new ethers2.Interface(PAY_WITH_PAYID_ABI);
|
|
348
|
+
return iface.encodeFunctionData("payETH", [
|
|
349
|
+
proof.payload,
|
|
350
|
+
proof.signature,
|
|
351
|
+
attestationUIDs
|
|
352
|
+
]);
|
|
353
|
+
}
|
|
354
|
+
function buildPayERC20CallData(contractAddress, proof, attestationUIDs = []) {
|
|
355
|
+
const iface = new ethers2.Interface(PAY_WITH_PAYID_ABI);
|
|
356
|
+
return iface.encodeFunctionData("payERC20", [
|
|
357
|
+
proof.payload,
|
|
358
|
+
proof.signature,
|
|
359
|
+
attestationUIDs
|
|
360
|
+
]);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// src/erc4337/userop.ts
|
|
364
|
+
function buildUserOperation(params) {
|
|
365
|
+
return {
|
|
366
|
+
sender: params.sender,
|
|
367
|
+
nonce: params.nonce,
|
|
368
|
+
initCode: params.initCode ?? "0x",
|
|
369
|
+
callData: params.callData,
|
|
370
|
+
callGasLimit: params.gas.callGasLimit,
|
|
371
|
+
verificationGasLimit: params.gas.verificationGasLimit,
|
|
372
|
+
preVerificationGas: params.gas.preVerificationGas,
|
|
373
|
+
maxFeePerGas: params.gas.maxFeePerGas,
|
|
374
|
+
maxPriorityFeePerGas: params.gas.maxPriorityFeePerGas,
|
|
375
|
+
paymasterAndData: params.paymasterAndData ?? "0x",
|
|
376
|
+
signature: "0x"
|
|
377
|
+
// signed later by smart account
|
|
378
|
+
};
|
|
379
|
+
}
|
|
35
380
|
|
|
36
381
|
// src/core/payid.ts
|
|
37
382
|
function isRuleSource(rule) {
|
|
@@ -43,31 +388,24 @@ var PayID = class {
|
|
|
43
388
|
this.debugTrace = debugTrace;
|
|
44
389
|
this.trustedIssuers = trustedIssuers;
|
|
45
390
|
}
|
|
46
|
-
/**
|
|
47
|
-
* Pure evaluation — client-safe
|
|
48
|
-
*/
|
|
49
391
|
async evaluate(context, rule) {
|
|
50
392
|
const config = isRuleSource(rule) ? (await resolveRule(rule)).config : rule;
|
|
51
|
-
return evaluate(
|
|
393
|
+
return evaluate(context, config, {
|
|
52
394
|
debug: this.debugTrace,
|
|
53
395
|
trustedIssuers: this.trustedIssuers
|
|
54
|
-
});
|
|
396
|
+
}, this.wasm);
|
|
55
397
|
}
|
|
56
|
-
/**
|
|
57
|
-
* Evaluate + generate Decision Proof
|
|
58
|
-
* FIX: parameter rename ruleRegistryContract → ruleAuthority
|
|
59
|
-
*/
|
|
60
398
|
async evaluateAndProve(params) {
|
|
61
399
|
const authorityConfig = isRuleSource(params.authorityRule) ? (await resolveRule(params.authorityRule)).config : params.authorityRule;
|
|
62
400
|
const evalConfig = params.evaluationRule ?? authorityConfig;
|
|
63
401
|
const result = await evaluate(
|
|
64
|
-
this.wasm,
|
|
65
402
|
params.context,
|
|
66
403
|
evalConfig,
|
|
67
404
|
{
|
|
68
405
|
debug: this.debugTrace,
|
|
69
406
|
trustedIssuers: this.trustedIssuers
|
|
70
|
-
}
|
|
407
|
+
},
|
|
408
|
+
this.wasm
|
|
71
409
|
);
|
|
72
410
|
if (result.decision !== "ALLOW") {
|
|
73
411
|
return { result, proof: null };
|
|
@@ -83,14 +421,12 @@ var PayID = class {
|
|
|
83
421
|
signer: params.signer,
|
|
84
422
|
verifyingContract: params.verifyingContract,
|
|
85
423
|
ruleAuthority: params.ruleAuthority,
|
|
86
|
-
chainId: params.context?.tx?.chainId,
|
|
87
|
-
ttlSeconds: params.ttlSeconds
|
|
424
|
+
chainId: params.chainId ?? params.context?.tx?.chainId,
|
|
425
|
+
ttlSeconds: params.ttlSeconds,
|
|
426
|
+
blockTimestamp: params.blockTimestamp
|
|
88
427
|
});
|
|
89
428
|
return { result, proof };
|
|
90
429
|
}
|
|
91
|
-
/**
|
|
92
|
-
* Build ERC-4337 UserOperation
|
|
93
|
-
*/
|
|
94
430
|
buildUserOperation(params) {
|
|
95
431
|
const attestationUIDs = params.attestationUIDs ?? [];
|
|
96
432
|
const isETH = params.paymentType === "eth";
|
|
@@ -114,13 +450,265 @@ function createPayID(params) {
|
|
|
114
450
|
);
|
|
115
451
|
}
|
|
116
452
|
|
|
453
|
+
// src/sessionPolicy/index.ts
|
|
454
|
+
var sessionPolicy_exports = {};
|
|
455
|
+
__export(sessionPolicy_exports, {
|
|
456
|
+
createSessionPolicyPayload: () => createSessionPolicyPayload,
|
|
457
|
+
decodeSessionPolicy: () => decodeSessionPolicy
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
// src/sessionPolicy/create.ts
|
|
461
|
+
import { ethers as ethers3 } from "ethers";
|
|
462
|
+
|
|
463
|
+
// src/rule/canonicalize.ts
|
|
464
|
+
function canonicalizeRuleSet(ruleSet) {
|
|
465
|
+
return {
|
|
466
|
+
version: ruleSet.version ?? "1",
|
|
467
|
+
logic: ruleSet.logic,
|
|
468
|
+
rules: ruleSet.rules.map((rule) => canonicalizeRule(rule)).sort((a, b) => a.id.localeCompare(b.id))
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
function canonicalizeRule(rule) {
|
|
472
|
+
const base = { id: rule.id, ...rule.message ? { message: rule.message } : {} };
|
|
473
|
+
if ("rules" in rule && Array.isArray(rule.rules)) {
|
|
474
|
+
return {
|
|
475
|
+
...base,
|
|
476
|
+
logic: rule.logic,
|
|
477
|
+
rules: rule.rules.map((r) => canonicalizeRule(r)).sort((a, b) => a.id.localeCompare(b.id))
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
if ("conditions" in rule && Array.isArray(rule.conditions)) {
|
|
481
|
+
return {
|
|
482
|
+
...base,
|
|
483
|
+
logic: rule.logic,
|
|
484
|
+
conditions: rule.conditions.map((c) => canonicalizeObject(c))
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
return {
|
|
488
|
+
...base,
|
|
489
|
+
if: canonicalizeObject(rule.if)
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
function canonicalizeObject(obj) {
|
|
493
|
+
if (obj === void 0) {
|
|
494
|
+
throw new Error("Undefined value not allowed in canonical object");
|
|
495
|
+
}
|
|
496
|
+
if (typeof obj === "function" || typeof obj === "symbol") {
|
|
497
|
+
throw new Error("Non-JSON value not allowed in canonical object");
|
|
498
|
+
}
|
|
499
|
+
if (obj instanceof Date) return obj.toISOString();
|
|
500
|
+
if (typeof obj === "bigint") return obj.toString();
|
|
501
|
+
if (Array.isArray(obj)) {
|
|
502
|
+
return obj.map(canonicalizeObject);
|
|
503
|
+
}
|
|
504
|
+
if (typeof obj === "object" && obj !== null) {
|
|
505
|
+
return Object.keys(obj).sort().reduce((acc, key) => {
|
|
506
|
+
acc[key] = canonicalizeObject(obj[key]);
|
|
507
|
+
return acc;
|
|
508
|
+
}, {});
|
|
509
|
+
}
|
|
510
|
+
return obj;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// src/sessionPolicy/create.ts
|
|
514
|
+
async function createSessionPolicyPayload(params) {
|
|
515
|
+
const issuedAt = Math.floor(Date.now() / 1e3);
|
|
516
|
+
const nonce = randomHex(16);
|
|
517
|
+
const payload = {
|
|
518
|
+
version: "payid.session.policy.v1",
|
|
519
|
+
receiver: params.receiver,
|
|
520
|
+
rule: canonicalizeRuleSet(params.rule),
|
|
521
|
+
issuedAt,
|
|
522
|
+
expiresAt: params.expiresAt,
|
|
523
|
+
nonce
|
|
524
|
+
};
|
|
525
|
+
const message = ethers3.keccak256(
|
|
526
|
+
ethers3.toUtf8Bytes(JSON.stringify(payload))
|
|
527
|
+
);
|
|
528
|
+
const signature = await params.signer.signMessage(message);
|
|
529
|
+
return {
|
|
530
|
+
...payload,
|
|
531
|
+
signature
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// src/sessionPolicy/decode.ts
|
|
536
|
+
import { ethers as ethers4 } from "ethers";
|
|
537
|
+
function decodeSessionPolicy(sessionPolicy, now) {
|
|
538
|
+
if (sessionPolicy.version !== "payid.session.policy.v1") {
|
|
539
|
+
throw new Error("INVALID_SESSION_POLICY_VERSION");
|
|
540
|
+
}
|
|
541
|
+
if (now > sessionPolicy.expiresAt) {
|
|
542
|
+
throw new Error("SESSION_POLICY_EXPIRED");
|
|
543
|
+
}
|
|
544
|
+
const payload = {
|
|
545
|
+
version: sessionPolicy.version,
|
|
546
|
+
receiver: sessionPolicy.receiver,
|
|
547
|
+
rule: sessionPolicy.rule,
|
|
548
|
+
issuedAt: sessionPolicy.issuedAt,
|
|
549
|
+
expiresAt: sessionPolicy.expiresAt,
|
|
550
|
+
nonce: sessionPolicy.nonce
|
|
551
|
+
};
|
|
552
|
+
const message = ethers4.keccak256(
|
|
553
|
+
ethers4.toUtf8Bytes(JSON.stringify(payload))
|
|
554
|
+
);
|
|
555
|
+
const recovered = ethers4.verifyMessage(
|
|
556
|
+
message,
|
|
557
|
+
sessionPolicy.signature
|
|
558
|
+
);
|
|
559
|
+
if (recovered.toLowerCase() !== sessionPolicy.receiver.toLowerCase()) {
|
|
560
|
+
throw new Error("INVALID_SESSION_POLICY_SIGNATURE");
|
|
561
|
+
}
|
|
562
|
+
return sessionPolicy.rule;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// src/rule/index.ts
|
|
566
|
+
var rule_exports = {};
|
|
567
|
+
__export(rule_exports, {
|
|
568
|
+
canonicalizeRuleSet: () => canonicalizeRuleSet,
|
|
569
|
+
combineRules: () => combineRules,
|
|
570
|
+
hashRuleSet: () => hashRuleSet2
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
// src/rule/combine.ts
|
|
574
|
+
function combineRules(defaultRuleSet, sessionRule) {
|
|
575
|
+
return canonicalizeRuleSet({
|
|
576
|
+
version: defaultRuleSet.version ?? "1",
|
|
577
|
+
logic: "AND",
|
|
578
|
+
rules: [
|
|
579
|
+
...defaultRuleSet.rules,
|
|
580
|
+
...sessionRule
|
|
581
|
+
]
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
// src/rule/hash.ts
|
|
586
|
+
import { keccak256 as keccak2562, toUtf8Bytes } from "ethers";
|
|
587
|
+
function hashRuleSet2(ruleSet) {
|
|
588
|
+
return keccak2562(
|
|
589
|
+
toUtf8Bytes(JSON.stringify(ruleSet))
|
|
590
|
+
);
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
// src/issuer/index.ts
|
|
594
|
+
var issuer_exports = {};
|
|
595
|
+
__export(issuer_exports, {
|
|
596
|
+
issueEnvContext: () => issueEnvContext,
|
|
597
|
+
issueOracleContext: () => issueOracleContext,
|
|
598
|
+
issueRiskContext: () => issueRiskContext,
|
|
599
|
+
issueStateContext: () => issueStateContext,
|
|
600
|
+
signAttestation: () => signAttestation
|
|
601
|
+
});
|
|
602
|
+
|
|
603
|
+
// src/issuer/issueEnvContext.ts
|
|
604
|
+
import "ethers";
|
|
605
|
+
|
|
606
|
+
// src/issuer/signAttestation.ts
|
|
607
|
+
import { keccak256 as keccak2563, toUtf8Bytes as toUtf8Bytes2 } from "ethers";
|
|
608
|
+
async function signAttestation(issuerWallet, payload, ttlSeconds = 60) {
|
|
609
|
+
const issuedAt = Math.floor(Date.now() / 1e3);
|
|
610
|
+
const expiresAt = issuedAt + ttlSeconds;
|
|
611
|
+
const hash2 = keccak2563(
|
|
612
|
+
toUtf8Bytes2(JSON.stringify(payload))
|
|
613
|
+
);
|
|
614
|
+
const signature = await issuerWallet.signMessage(
|
|
615
|
+
Buffer.from(hash2.slice(2), "hex")
|
|
616
|
+
);
|
|
617
|
+
return {
|
|
618
|
+
issuer: issuerWallet.address,
|
|
619
|
+
issuedAt,
|
|
620
|
+
expiresAt,
|
|
621
|
+
signature
|
|
622
|
+
};
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
// src/issuer/issueEnvContext.ts
|
|
626
|
+
async function issueEnvContext(wallet) {
|
|
627
|
+
const payload = {
|
|
628
|
+
timestamp: Math.floor(Date.now() / 1e3)
|
|
629
|
+
};
|
|
630
|
+
return {
|
|
631
|
+
...payload,
|
|
632
|
+
proof: await signAttestation(wallet, payload, 30)
|
|
633
|
+
};
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
// src/issuer/issueOracleContext.ts
|
|
637
|
+
async function issueOracleContext(wallet, data) {
|
|
638
|
+
const proof = await signAttestation(wallet, data, 120);
|
|
639
|
+
return { ...data, proof };
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
// src/issuer/issueRiskContext.ts
|
|
643
|
+
async function issueRiskContext(wallet, score, category, modelHash) {
|
|
644
|
+
const payload = { score, category, modelHash };
|
|
645
|
+
const signAttestationData = await signAttestation(wallet, payload, 120);
|
|
646
|
+
return {
|
|
647
|
+
score,
|
|
648
|
+
category,
|
|
649
|
+
proof: {
|
|
650
|
+
...signAttestationData,
|
|
651
|
+
modelHash
|
|
652
|
+
}
|
|
653
|
+
};
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
// src/issuer/issueStateContext.ts
|
|
657
|
+
async function issueStateContext(wallet, spentToday, period) {
|
|
658
|
+
const payload = { spentToday, period };
|
|
659
|
+
return {
|
|
660
|
+
...payload,
|
|
661
|
+
proof: await signAttestation(wallet, payload, 60)
|
|
662
|
+
};
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
// src/context/index.ts
|
|
666
|
+
var context_exports = {};
|
|
667
|
+
__export(context_exports, {
|
|
668
|
+
buildContextV2: () => buildContextV2
|
|
669
|
+
});
|
|
670
|
+
|
|
671
|
+
// src/context/contextV2.ts
|
|
672
|
+
async function buildContextV2(params) {
|
|
673
|
+
const ctx = {
|
|
674
|
+
...params.baseContext
|
|
675
|
+
};
|
|
676
|
+
if (params.env) {
|
|
677
|
+
ctx.env = await issueEnvContext(
|
|
678
|
+
params.env.issuer
|
|
679
|
+
);
|
|
680
|
+
}
|
|
681
|
+
if (params.state) {
|
|
682
|
+
ctx.state = await issueStateContext(
|
|
683
|
+
params.state.issuer,
|
|
684
|
+
params.state.spentToday,
|
|
685
|
+
params.state.period
|
|
686
|
+
);
|
|
687
|
+
}
|
|
688
|
+
if (params.oracle) {
|
|
689
|
+
ctx.oracle = await issueOracleContext(
|
|
690
|
+
params.oracle.issuer,
|
|
691
|
+
params.oracle.data
|
|
692
|
+
);
|
|
693
|
+
}
|
|
694
|
+
if (params.risk) {
|
|
695
|
+
ctx.risk = await issueRiskContext(
|
|
696
|
+
params.risk.issuer,
|
|
697
|
+
params.risk.score,
|
|
698
|
+
params.risk.category,
|
|
699
|
+
params.risk.modelHash
|
|
700
|
+
);
|
|
701
|
+
}
|
|
702
|
+
return ctx;
|
|
703
|
+
}
|
|
704
|
+
|
|
117
705
|
// src/eas.ts
|
|
118
706
|
var eas_exports = {};
|
|
119
707
|
__export(eas_exports, {
|
|
120
708
|
EASClient: () => EASClient,
|
|
121
709
|
EAS_ADDRESSES: () => EAS_ADDRESSES
|
|
122
710
|
});
|
|
123
|
-
import { ethers } from "ethers";
|
|
711
|
+
import { ethers as ethers5 } from "ethers";
|
|
124
712
|
var EAS_ABI = [
|
|
125
713
|
"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))",
|
|
126
714
|
"function isAttestationValid(bytes32 uid) external view returns (bool)",
|
|
@@ -129,7 +717,7 @@ var EAS_ABI = [
|
|
|
129
717
|
var EASClient = class {
|
|
130
718
|
contract;
|
|
131
719
|
constructor(options) {
|
|
132
|
-
this.contract = new
|
|
720
|
+
this.contract = new ethers5.Contract(
|
|
133
721
|
options.easAddress,
|
|
134
722
|
EAS_ABI,
|
|
135
723
|
options.provider
|
|
@@ -204,6 +792,146 @@ var EAS_ADDRESSES = {
|
|
|
204
792
|
4202: "0xC2679fBD37d54388Ce493F1DB75320D236e1815e"
|
|
205
793
|
// Lisk Sepolia
|
|
206
794
|
};
|
|
795
|
+
|
|
796
|
+
// src/core/client/index.ts
|
|
797
|
+
var client_exports = {};
|
|
798
|
+
__export(client_exports, {
|
|
799
|
+
createPayID: () => createPayID2
|
|
800
|
+
});
|
|
801
|
+
|
|
802
|
+
// src/core/client/client.ts
|
|
803
|
+
import "ethers";
|
|
804
|
+
function isRuleSource2(rule) {
|
|
805
|
+
return typeof rule === "object" && rule !== null && "uri" in rule;
|
|
806
|
+
}
|
|
807
|
+
var PayIDClient = class {
|
|
808
|
+
constructor(debugTrace, wasm) {
|
|
809
|
+
this.debugTrace = debugTrace;
|
|
810
|
+
this.wasm = wasm;
|
|
811
|
+
}
|
|
812
|
+
async evaluate(context, rule) {
|
|
813
|
+
const config = isRuleSource2(rule) ? (await resolveRule(rule)).config : rule;
|
|
814
|
+
return evaluate(context, config, { debug: this.debugTrace }, this.wasm);
|
|
815
|
+
}
|
|
816
|
+
async evaluateAndProve(params) {
|
|
817
|
+
const authorityConfig = isRuleSource2(params.authorityRule) ? (await resolveRule(params.authorityRule)).config : params.authorityRule;
|
|
818
|
+
const evalConfig = params.evaluationRule ?? (params.sessionPolicy ? combineRules(
|
|
819
|
+
authorityConfig,
|
|
820
|
+
decodeSessionPolicy(
|
|
821
|
+
params.sessionPolicy,
|
|
822
|
+
Math.floor(Date.now() / 1e3)
|
|
823
|
+
).rules
|
|
824
|
+
) : authorityConfig);
|
|
825
|
+
const result = await evaluate(
|
|
826
|
+
params.context,
|
|
827
|
+
evalConfig,
|
|
828
|
+
{ debug: this.debugTrace },
|
|
829
|
+
this.wasm
|
|
830
|
+
);
|
|
831
|
+
if (result.decision !== "ALLOW") {
|
|
832
|
+
return { result, proof: null };
|
|
833
|
+
}
|
|
834
|
+
const proof = await generateDecisionProof({
|
|
835
|
+
payId: params.payId,
|
|
836
|
+
payer: params.payer,
|
|
837
|
+
receiver: params.receiver,
|
|
838
|
+
asset: params.asset,
|
|
839
|
+
amount: params.amount,
|
|
840
|
+
context: params.context,
|
|
841
|
+
ruleConfig: authorityConfig,
|
|
842
|
+
signer: params.signer,
|
|
843
|
+
verifyingContract: params.verifyingContract,
|
|
844
|
+
ruleAuthority: params.ruleAuthority,
|
|
845
|
+
chainId: params.chainId ?? params.context?.tx?.chainId,
|
|
846
|
+
ttlSeconds: params.ttlSeconds,
|
|
847
|
+
blockTimestamp: params.blockTimestamp
|
|
848
|
+
});
|
|
849
|
+
return { result, proof };
|
|
850
|
+
}
|
|
851
|
+
};
|
|
852
|
+
|
|
853
|
+
// src/core/client/index.ts
|
|
854
|
+
function createPayID2(params) {
|
|
855
|
+
return new PayIDClient(
|
|
856
|
+
params.debugTrace ?? false,
|
|
857
|
+
params.wasm
|
|
858
|
+
);
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
// src/core/server/index.ts
|
|
862
|
+
var server_exports = {};
|
|
863
|
+
__export(server_exports, {
|
|
864
|
+
createPayID: () => createPayID3
|
|
865
|
+
});
|
|
866
|
+
|
|
867
|
+
// src/core/server/server.ts
|
|
868
|
+
function isRuleSource3(rule) {
|
|
869
|
+
return typeof rule === "object" && rule !== null && "uri" in rule;
|
|
870
|
+
}
|
|
871
|
+
var PayIDServer = class {
|
|
872
|
+
constructor(signer, trustedIssuers, debugTrace, wasm) {
|
|
873
|
+
this.signer = signer;
|
|
874
|
+
this.trustedIssuers = trustedIssuers;
|
|
875
|
+
this.debugTrace = debugTrace;
|
|
876
|
+
this.wasm = wasm;
|
|
877
|
+
}
|
|
878
|
+
async evaluateAndProve(params) {
|
|
879
|
+
const authorityConfig = isRuleSource3(params.authorityRule) ? (await resolveRule(params.authorityRule)).config : params.authorityRule;
|
|
880
|
+
const evalConfig = params.evaluationRule ?? authorityConfig;
|
|
881
|
+
const result = await evaluate(
|
|
882
|
+
params.context,
|
|
883
|
+
evalConfig,
|
|
884
|
+
{
|
|
885
|
+
debug: this.debugTrace,
|
|
886
|
+
trustedIssuers: this.trustedIssuers
|
|
887
|
+
},
|
|
888
|
+
this.wasm
|
|
889
|
+
);
|
|
890
|
+
if (result.decision !== "ALLOW") {
|
|
891
|
+
return { result, proof: null };
|
|
892
|
+
}
|
|
893
|
+
const proof = await generateDecisionProof({
|
|
894
|
+
payId: params.payId,
|
|
895
|
+
payer: params.payer,
|
|
896
|
+
receiver: params.receiver,
|
|
897
|
+
asset: params.asset,
|
|
898
|
+
amount: params.amount,
|
|
899
|
+
context: params.context,
|
|
900
|
+
ruleConfig: authorityConfig,
|
|
901
|
+
signer: this.signer,
|
|
902
|
+
verifyingContract: params.verifyingContract,
|
|
903
|
+
ruleAuthority: params.ruleAuthority,
|
|
904
|
+
chainId: params.chainId ?? params.context?.tx?.chainId,
|
|
905
|
+
ttlSeconds: params.ttlSeconds,
|
|
906
|
+
blockTimestamp: params.blockTimestamp
|
|
907
|
+
});
|
|
908
|
+
return { result, proof };
|
|
909
|
+
}
|
|
910
|
+
buildUserOperation(params) {
|
|
911
|
+
const callData = buildPayERC20CallData(
|
|
912
|
+
params.targetContract,
|
|
913
|
+
params.proof,
|
|
914
|
+
params.attestationUIDs ?? []
|
|
915
|
+
);
|
|
916
|
+
return buildUserOperation({
|
|
917
|
+
sender: params.smartAccount,
|
|
918
|
+
nonce: params.nonce,
|
|
919
|
+
callData,
|
|
920
|
+
gas: params.gas,
|
|
921
|
+
paymasterAndData: params.paymasterAndData
|
|
922
|
+
});
|
|
923
|
+
}
|
|
924
|
+
};
|
|
925
|
+
|
|
926
|
+
// src/core/server/index.ts
|
|
927
|
+
function createPayID3(params) {
|
|
928
|
+
return new PayIDServer(
|
|
929
|
+
params.signer,
|
|
930
|
+
params.trustedIssuers,
|
|
931
|
+
params.debugTrace ?? false,
|
|
932
|
+
params.wasm
|
|
933
|
+
);
|
|
934
|
+
}
|
|
207
935
|
export {
|
|
208
936
|
client_exports as client,
|
|
209
937
|
context_exports as context,
|