@pepu-chain/sdk 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +565 -2
- package/dist/aa/kernel.cjs +40 -0
- package/dist/aa/kernel.cjs.map +1 -0
- package/dist/aa/kernel.d.cts +88 -0
- package/dist/aa/kernel.d.ts +88 -0
- package/dist/aa/kernel.js +11 -0
- package/dist/aa/kernel.js.map +1 -0
- package/dist/aa/react-direct.cjs +110 -0
- package/dist/aa/react-direct.cjs.map +1 -0
- package/dist/aa/react-direct.d.cts +42 -0
- package/dist/aa/react-direct.d.ts +42 -0
- package/dist/aa/react-direct.js +107 -0
- package/dist/aa/react-direct.js.map +1 -0
- package/dist/aa/react.cjs +151 -0
- package/dist/aa/react.cjs.map +1 -0
- package/dist/aa/react.d.cts +62 -0
- package/dist/aa/react.d.ts +62 -0
- package/dist/aa/react.js +147 -0
- package/dist/aa/react.js.map +1 -0
- package/dist/aa.cjs +84 -0
- package/dist/aa.cjs.map +1 -0
- package/dist/aa.d.cts +85 -0
- package/dist/aa.d.ts +85 -0
- package/dist/aa.js +11 -0
- package/dist/aa.js.map +1 -0
- package/dist/api-Dz4sCHH_.d.cts +654 -0
- package/dist/api-Dz4sCHH_.d.ts +654 -0
- package/dist/calls-BRPjKgjl.d.cts +70 -0
- package/dist/calls-z_EQOtFb.d.ts +70 -0
- package/dist/chains-DK13zGIp.d.cts +235 -0
- package/dist/chains-DK13zGIp.d.ts +235 -0
- package/dist/chunk-3XUGQODR.js +194 -0
- package/dist/chunk-3XUGQODR.js.map +1 -0
- package/dist/chunk-45KSZH26.cjs +145 -0
- package/dist/chunk-45KSZH26.cjs.map +1 -0
- package/dist/chunk-4GINFJO6.cjs +44 -0
- package/dist/chunk-4GINFJO6.cjs.map +1 -0
- package/dist/chunk-62M2LKQW.js +136 -0
- package/dist/chunk-62M2LKQW.js.map +1 -0
- package/dist/chunk-6DSZ4Z2N.js +498 -0
- package/dist/chunk-6DSZ4Z2N.js.map +1 -0
- package/dist/chunk-7MNJF2OB.cjs +72 -0
- package/dist/chunk-7MNJF2OB.cjs.map +1 -0
- package/dist/chunk-A5LP2UCS.cjs +2729 -0
- package/dist/chunk-A5LP2UCS.cjs.map +1 -0
- package/dist/chunk-AJS4UFQX.cjs +121 -0
- package/dist/chunk-AJS4UFQX.cjs.map +1 -0
- package/dist/chunk-C2XW44FI.cjs +200 -0
- package/dist/chunk-C2XW44FI.cjs.map +1 -0
- package/dist/chunk-C7IC36XS.cjs +13 -0
- package/dist/chunk-C7IC36XS.cjs.map +1 -0
- package/dist/chunk-D52PADVY.js +84 -0
- package/dist/chunk-D52PADVY.js.map +1 -0
- package/dist/chunk-DH6BFNVJ.cjs +272 -0
- package/dist/chunk-DH6BFNVJ.cjs.map +1 -0
- package/dist/chunk-DPCZJLB3.cjs +87 -0
- package/dist/chunk-DPCZJLB3.cjs.map +1 -0
- package/dist/chunk-EHBPIYY4.js +262 -0
- package/dist/chunk-EHBPIYY4.js.map +1 -0
- package/dist/chunk-ESMNAXUI.js +86 -0
- package/dist/chunk-ESMNAXUI.js.map +1 -0
- package/dist/chunk-ET3P6TX6.cjs +49 -0
- package/dist/chunk-ET3P6TX6.cjs.map +1 -0
- package/dist/chunk-FCXSP2YF.js +219 -0
- package/dist/chunk-FCXSP2YF.js.map +1 -0
- package/dist/chunk-IB2FSPMJ.js +66 -0
- package/dist/chunk-IB2FSPMJ.js.map +1 -0
- package/dist/chunk-IG7RSL2Y.cjs +178 -0
- package/dist/chunk-IG7RSL2Y.cjs.map +1 -0
- package/dist/chunk-IY3ALPUJ.js +2716 -0
- package/dist/chunk-IY3ALPUJ.js.map +1 -0
- package/dist/chunk-J3O2ZGG3.cjs +93 -0
- package/dist/chunk-J3O2ZGG3.cjs.map +1 -0
- package/dist/chunk-J6UXXHBE.js +37 -0
- package/dist/chunk-J6UXXHBE.js.map +1 -0
- package/dist/chunk-JLZ4LZ4Z.js +22 -0
- package/dist/chunk-JLZ4LZ4Z.js.map +1 -0
- package/dist/chunk-KIIFL4VM.js +274 -0
- package/dist/chunk-KIIFL4VM.js.map +1 -0
- package/dist/chunk-KVG3AYYR.js +99 -0
- package/dist/chunk-KVG3AYYR.js.map +1 -0
- package/dist/chunk-MBA4CLA5.js +45 -0
- package/dist/chunk-MBA4CLA5.js.map +1 -0
- package/dist/chunk-NE3QKDOB.cjs +24 -0
- package/dist/chunk-NE3QKDOB.cjs.map +1 -0
- package/dist/chunk-NVOPDXTA.cjs +95 -0
- package/dist/chunk-NVOPDXTA.cjs.map +1 -0
- package/dist/chunk-OH3QMAIB.js +11 -0
- package/dist/chunk-OH3QMAIB.js.map +1 -0
- package/dist/chunk-PHM3ZORG.cjs +110 -0
- package/dist/chunk-PHM3ZORG.cjs.map +1 -0
- package/dist/chunk-R5PXQNO3.cjs +209 -0
- package/dist/chunk-R5PXQNO3.cjs.map +1 -0
- package/dist/chunk-SLW7FRTL.cjs +285 -0
- package/dist/chunk-SLW7FRTL.cjs.map +1 -0
- package/dist/chunk-SVWRRALU.cjs +17 -0
- package/dist/chunk-SVWRRALU.cjs.map +1 -0
- package/dist/chunk-T43PQXJD.js +202 -0
- package/dist/chunk-T43PQXJD.js.map +1 -0
- package/dist/chunk-TIEAZYHF.cjs +225 -0
- package/dist/chunk-TIEAZYHF.cjs.map +1 -0
- package/dist/chunk-VBH3JLQ5.js +116 -0
- package/dist/chunk-VBH3JLQ5.js.map +1 -0
- package/dist/chunk-VF3D6KLQ.cjs +94 -0
- package/dist/chunk-VF3D6KLQ.cjs.map +1 -0
- package/dist/chunk-VTQIHMF3.js +82 -0
- package/dist/chunk-VTQIHMF3.js.map +1 -0
- package/dist/chunk-W3JN3YIW.js +15 -0
- package/dist/chunk-W3JN3YIW.js.map +1 -0
- package/dist/chunk-WANILJZQ.cjs +87 -0
- package/dist/chunk-WANILJZQ.cjs.map +1 -0
- package/dist/chunk-XC4IBCI2.js +86 -0
- package/dist/chunk-XC4IBCI2.js.map +1 -0
- package/dist/chunk-YKEWWQEJ.js +165 -0
- package/dist/chunk-YKEWWQEJ.js.map +1 -0
- package/dist/chunk-YQL7NISX.cjs +515 -0
- package/dist/chunk-YQL7NISX.cjs.map +1 -0
- package/dist/chunk-ZB6SVBK4.js +89 -0
- package/dist/chunk-ZB6SVBK4.js.map +1 -0
- package/dist/combo/react.cjs +235 -0
- package/dist/combo/react.cjs.map +1 -0
- package/dist/combo/react.d.cts +148 -0
- package/dist/combo/react.d.ts +148 -0
- package/dist/combo/react.js +230 -0
- package/dist/combo/react.js.map +1 -0
- package/dist/combo.cjs +262 -0
- package/dist/combo.cjs.map +1 -0
- package/dist/combo.d.cts +139 -0
- package/dist/combo.d.ts +139 -0
- package/dist/combo.js +249 -0
- package/dist/combo.js.map +1 -0
- package/dist/config-CHjz7ZjZ.d.cts +57 -0
- package/dist/config-COjhIZTh.d.ts +57 -0
- package/dist/doctor.cjs +354 -0
- package/dist/doctor.cjs.map +1 -0
- package/dist/doctor.d.cts +177 -0
- package/dist/doctor.d.ts +177 -0
- package/dist/doctor.js +345 -0
- package/dist/doctor.js.map +1 -0
- package/dist/erc7677-DOW58QBE.d.cts +111 -0
- package/dist/erc7677-DOW58QBE.d.ts +111 -0
- package/dist/errors-CgX1vNj7.d.cts +100 -0
- package/dist/errors-CgX1vNj7.d.ts +100 -0
- package/dist/index.cjs +802 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2398 -0
- package/dist/index.d.ts +2398 -0
- package/dist/index.js +559 -0
- package/dist/index.js.map +1 -0
- package/dist/paymaster/server.cjs +38 -0
- package/dist/paymaster/server.cjs.map +1 -0
- package/dist/paymaster/server.d.cts +57 -0
- package/dist/paymaster/server.d.ts +57 -0
- package/dist/paymaster/server.js +36 -0
- package/dist/paymaster/server.js.map +1 -0
- package/dist/paymaster.cjs +356 -0
- package/dist/paymaster.cjs.map +1 -0
- package/dist/paymaster.d.cts +1851 -0
- package/dist/paymaster.d.ts +1851 -0
- package/dist/paymaster.js +289 -0
- package/dist/paymaster.js.map +1 -0
- package/dist/privy/react.cjs +48 -0
- package/dist/privy/react.cjs.map +1 -0
- package/dist/privy/react.d.cts +194 -0
- package/dist/privy/react.d.ts +194 -0
- package/dist/privy/react.js +7 -0
- package/dist/privy/react.js.map +1 -0
- package/dist/privy/server.cjs +43 -0
- package/dist/privy/server.cjs.map +1 -0
- package/dist/privy/server.d.cts +192 -0
- package/dist/privy/server.d.ts +192 -0
- package/dist/privy/server.js +6 -0
- package/dist/privy/server.js.map +1 -0
- package/dist/privy/wagmi.d.ts +90 -0
- package/dist/privy/wagmi.js +55 -0
- package/dist/privy/wagmi.js.map +1 -0
- package/dist/privy.cjs +34 -0
- package/dist/privy.cjs.map +1 -0
- package/dist/privy.d.cts +4 -0
- package/dist/privy.d.ts +4 -0
- package/dist/privy.js +5 -0
- package/dist/privy.js.map +1 -0
- package/dist/react.cjs +72 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +66 -0
- package/dist/react.d.ts +66 -0
- package/dist/react.js +68 -0
- package/dist/react.js.map +1 -0
- package/dist/requirements-C-QiJkL9.d.cts +134 -0
- package/dist/requirements-C-QiJkL9.d.ts +134 -0
- package/dist/scope-DBRkN7bR.d.cts +94 -0
- package/dist/scope-DBRkN7bR.d.ts +94 -0
- package/dist/server.cjs +59 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.cts +208 -0
- package/dist/server.d.ts +208 -0
- package/dist/server.js +8 -0
- package/dist/server.js.map +1 -0
- package/dist/session/kernel.cjs +82 -0
- package/dist/session/kernel.cjs.map +1 -0
- package/dist/session/kernel.d.cts +131 -0
- package/dist/session/kernel.d.ts +131 -0
- package/dist/session/kernel.js +13 -0
- package/dist/session/kernel.js.map +1 -0
- package/dist/session/react.cjs +37 -0
- package/dist/session/react.cjs.map +1 -0
- package/dist/session/react.d.cts +119 -0
- package/dist/session/react.d.ts +119 -0
- package/dist/session/react.js +8 -0
- package/dist/session/react.js.map +1 -0
- package/dist/session/server.cjs +267 -0
- package/dist/session/server.cjs.map +1 -0
- package/dist/session/server.d.cts +151 -0
- package/dist/session/server.d.ts +151 -0
- package/dist/session/server.js +252 -0
- package/dist/session/server.js.map +1 -0
- package/dist/session.cjs +74 -0
- package/dist/session.cjs.map +1 -0
- package/dist/session.d.cts +3 -0
- package/dist/session.d.ts +3 -0
- package/dist/session.js +5 -0
- package/dist/session.js.map +1 -0
- package/dist/status-CmOsyPmO.d.cts +295 -0
- package/dist/status-DwkkOrGQ.d.ts +295 -0
- package/dist/store-CjmLgp9g.d.cts +64 -0
- package/dist/store-CjmLgp9g.d.ts +64 -0
- package/dist/types-BEEM7WdG.d.cts +25 -0
- package/dist/types-BEEM7WdG.d.ts +25 -0
- package/dist/types-BilBTDqK.d.cts +27 -0
- package/dist/types-BilBTDqK.d.ts +27 -0
- package/package.json +209 -3
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { PepuConfigError } from './chunk-6DSZ4Z2N.js';
|
|
2
|
+
|
|
3
|
+
// src/internal/assert-server.ts
|
|
4
|
+
function assertServerOnly(entry) {
|
|
5
|
+
if (globalThis.window !== void 0) {
|
|
6
|
+
throw new PepuConfigError(
|
|
7
|
+
"CONFIG_SERVER_ONLY",
|
|
8
|
+
`${entry} is server-only and was imported in a browser bundle. Import it from a route handler, server action or script, never from client code.`
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export { assertServerOnly };
|
|
14
|
+
//# sourceMappingURL=chunk-W3JN3YIW.js.map
|
|
15
|
+
//# sourceMappingURL=chunk-W3JN3YIW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/internal/assert-server.ts"],"names":[],"mappings":";;;AAUO,SAAS,iBAAiB,KAAA,EAAqB;AACpD,EAAA,IAAK,UAAA,CAAoC,WAAW,MAAA,EAAW;AAC7D,IAAA,MAAM,IAAI,eAAA;AAAA,MACR,oBAAA;AAAA,MACA,GAAG,KAAK,CAAA,sIAAA;AAAA,KACV;AAAA,EACF;AACF","file":"chunk-W3JN3YIW.js","sourcesContent":["import { PepuConfigError } from \"../errors.js\";\n\n/**\n * Called at import time by every server-only entry point\n * (`@pepu-chain/sdk/server`, `/privy/server`, `/session/server`,\n * `/paymaster/server`, `/combo`). Those entries sit next to secrets (Privy app\n * secret, authorization key, paymaster server keys) and must never be bundled\n * for the browser. A browser bundle that reaches one fails loudly here instead\n * of silently shipping the module.\n */\nexport function assertServerOnly(entry: string): void {\n if ((globalThis as { window?: unknown }).window !== undefined) {\n throw new PepuConfigError(\n \"CONFIG_SERVER_ONLY\",\n `${entry} is server-only and was imported in a browser bundle. Import it from a route handler, server action or script, never from client code.`,\n );\n }\n}\n"]}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkYQL7NISX_cjs = require('./chunk-YQL7NISX.cjs');
|
|
4
|
+
|
|
5
|
+
// src/aa/describe.ts
|
|
6
|
+
var AA_HINTS = {
|
|
7
|
+
AA10: { code: "BUNDLER_AA_FAILED", hint: "The sender is already deployed but initCode was sent. Drop the factory fields." },
|
|
8
|
+
AA13: { code: "BUNDLER_AA_FAILED", hint: "initCode (account factory) reverted. Check the Kernel factory address and the owner." },
|
|
9
|
+
AA14: { code: "BUNDLER_AA_FAILED", hint: "initCode deployed a different address than the sender. Rebuild the account with the same owner and index." },
|
|
10
|
+
AA20: { code: "BUNDLER_AA_FAILED", hint: "The account is not deployed and no initCode was sent. Use a fresh account object so the factory fields are included." },
|
|
11
|
+
AA21: { code: "BUNDLER_AA_FAILED", hint: "The account cannot pay its prefund. Use the paymaster, or fund the account." },
|
|
12
|
+
AA22: { code: "BUNDLER_AA_FAILED", hint: "The UserOperation's validity window expired. Resend a fresh one." },
|
|
13
|
+
AA23: { code: "BUNDLER_AA_FAILED", hint: "Account validation reverted: wrong signer, wrong signature format, or a session policy rejected the call." },
|
|
14
|
+
AA24: { code: "BUNDLER_AA_FAILED", hint: "Signature rejected by the account. Sign with the owner the account was built for." },
|
|
15
|
+
AA25: { code: "BUNDLER_AA_FAILED", hint: "Invalid nonce: another UserOperation from this account is pending. Wait for it, then retry." },
|
|
16
|
+
AA26: { code: "BUNDLER_AA_FAILED", hint: "verificationGasLimit too low. Re-estimate gas." },
|
|
17
|
+
AA31: { code: "PAYMASTER_NO_BALANCE", paymaster: true, hint: "The paymaster's EntryPoint deposit is too low. Deposit more PEPU to the paymaster." },
|
|
18
|
+
AA32: { code: "PAYMASTER_DENIED", paymaster: true, hint: "The paymaster signature expired. Request paymaster data again." },
|
|
19
|
+
AA33: { code: "PAYMASTER_DENIED", paymaster: true, hint: "Paymaster validation reverted. Check the paymaster contract and that its signer matches the policy service." },
|
|
20
|
+
AA34: { code: "PAYMASTER_DENIED", paymaster: true, hint: "Paymaster signature rejected. The policy service signer does not match the paymaster contract." },
|
|
21
|
+
AA36: { code: "BUNDLER_AA_FAILED", paymaster: true, hint: "Paymaster gas limits too low. Re-estimate with the paymaster stub data." },
|
|
22
|
+
AA40: { code: "BUNDLER_AA_FAILED", hint: "Verification used more gas than verificationGasLimit. Re-estimate gas." },
|
|
23
|
+
AA41: { code: "BUNDLER_AA_FAILED", hint: "Paymaster verification used more gas than its limit. Re-estimate gas." },
|
|
24
|
+
AA50: { code: "BUNDLER_AA_FAILED", hint: "The postOp reverted. Check the paymaster's postOp path." },
|
|
25
|
+
AA51: { code: "BUNDLER_AA_FAILED", hint: "Prefund below actualGasCost. Re-estimate fees; PEPU needs fee headroom (the SDK applies 20%)." },
|
|
26
|
+
AA90: { code: "BUNDLER_AA_FAILED", hint: "Invalid beneficiary on handleOps. This is a bundler configuration problem." },
|
|
27
|
+
AA91: { code: "BUNDLER_AA_FAILED", hint: "Failed to send funds to the beneficiary. This is a bundler configuration problem." },
|
|
28
|
+
AA95: { code: "BUNDLER_AA_FAILED", hint: "Out of gas in handleOps. Raise the gas limits." }
|
|
29
|
+
};
|
|
30
|
+
function redactSecrets(text) {
|
|
31
|
+
return text.replace(/\/paymaster\/[^\s/"'`)\]?#]+/gi, "/paymaster/[redacted]").replace(/(bearer\s+)[A-Za-z0-9._~+/=-]+/gi, "$1[redacted]").replace(/(x-api-key["']?\s*[:=]\s*["']?)[^\s"',}]+/gi, "$1[redacted]").replace(/(privyAccessToken["']?\s*[:=]\s*["']?)[^\s"',}]+/gi, "$1[redacted]").replace(/\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]*/g, "[redacted-jwt]").replace(/(https?:\/\/)[^\s/@]+:[^\s/@]+@/gi, "$1[redacted]@");
|
|
32
|
+
}
|
|
33
|
+
function collect(e) {
|
|
34
|
+
const seen = /* @__PURE__ */ new Set();
|
|
35
|
+
const parts = [];
|
|
36
|
+
let cur = e;
|
|
37
|
+
for (let d = 0; d < 8 && cur !== void 0 && cur !== null && !seen.has(cur); d++) {
|
|
38
|
+
seen.add(cur);
|
|
39
|
+
if (typeof cur === "object") {
|
|
40
|
+
const o = cur;
|
|
41
|
+
for (const k of ["shortMessage", "message", "details", "reason"]) {
|
|
42
|
+
const v = o[k];
|
|
43
|
+
if (typeof v === "string" && v.length > 0 && !parts.includes(v)) parts.push(v);
|
|
44
|
+
}
|
|
45
|
+
const data = o["data"];
|
|
46
|
+
if (data && typeof data === "object") {
|
|
47
|
+
const r = data["reason"];
|
|
48
|
+
if (typeof r === "string") parts.push(r);
|
|
49
|
+
}
|
|
50
|
+
cur = o["cause"];
|
|
51
|
+
} else {
|
|
52
|
+
parts.push(String(cur));
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return parts.join("\n");
|
|
57
|
+
}
|
|
58
|
+
function describeUserOpFailure(e) {
|
|
59
|
+
const text = redactSecrets(collect(e));
|
|
60
|
+
const headline = text.split("\n")[0]?.trim() || "UserOperation failed";
|
|
61
|
+
const opts = (hint) => ({ ...hint ? { hint } : {}, cause: e });
|
|
62
|
+
const aa = /\bAA(\d{2})\b/.exec(text);
|
|
63
|
+
if (aa) {
|
|
64
|
+
const key = `AA${aa[1]}`;
|
|
65
|
+
const info = AA_HINTS[key];
|
|
66
|
+
if (info) {
|
|
67
|
+
const msg = `${key}: ${headline}`;
|
|
68
|
+
return info.paymaster && info.code !== "BUNDLER_AA_FAILED" ? new chunkYQL7NISX_cjs.PepuPaymasterError(info.code, msg, opts(info.hint)) : new chunkYQL7NISX_cjs.PepuBundlerError(info.code, msg, opts(info.hint));
|
|
69
|
+
}
|
|
70
|
+
return new chunkYQL7NISX_cjs.PepuBundlerError("BUNDLER_AA_FAILED", `${key}: ${headline}`, opts());
|
|
71
|
+
}
|
|
72
|
+
const explained = chunkYQL7NISX_cjs.explainError(text);
|
|
73
|
+
if (explained.code.startsWith("PAYMASTER_")) {
|
|
74
|
+
return new chunkYQL7NISX_cjs.PepuPaymasterError(explained.code, headline, opts(explained.fix));
|
|
75
|
+
}
|
|
76
|
+
if (explained.code !== "UNKNOWN") {
|
|
77
|
+
return new chunkYQL7NISX_cjs.PepuBundlerError(explained.code, headline, opts(explained.fix));
|
|
78
|
+
}
|
|
79
|
+
const pe = chunkYQL7NISX_cjs.toPepuError(e);
|
|
80
|
+
if (pe.code !== "UNKNOWN") return new chunkYQL7NISX_cjs.PepuBundlerError(pe.code, redactSecrets(pe.message), opts(pe.hint));
|
|
81
|
+
return new chunkYQL7NISX_cjs.PepuBundlerError("UNKNOWN", headline, opts(chunkYQL7NISX_cjs.getErrorEntry("UNKNOWN").fix));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
exports.describeUserOpFailure = describeUserOpFailure;
|
|
85
|
+
exports.redactSecrets = redactSecrets;
|
|
86
|
+
//# sourceMappingURL=chunk-WANILJZQ.cjs.map
|
|
87
|
+
//# sourceMappingURL=chunk-WANILJZQ.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/aa/describe.ts"],"names":["PepuPaymasterError","PepuBundlerError","explainError","toPepuError","getErrorEntry"],"mappings":"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","file":"chunk-WANILJZQ.cjs","sourcesContent":["import { PepuBundlerError, PepuPaymasterError, explainError, getErrorEntry, toPepuError } from \"../errors.js\";\nimport type { PepuErrorCode } from \"../errors.js\";\n\ninterface AaInfo {\n code: PepuErrorCode;\n paymaster?: boolean;\n hint: string;\n}\n\n/**\n * AAxx meaning, per the EntryPoint v0.7 revert reasons, with the PEPU-specific\n * fix. Ported from the sponsored-demo and sponsored-session-app runs.\n */\nconst AA_HINTS: Readonly<Record<string, AaInfo>> = {\n AA10: { code: \"BUNDLER_AA_FAILED\", hint: \"The sender is already deployed but initCode was sent. Drop the factory fields.\" },\n AA13: { code: \"BUNDLER_AA_FAILED\", hint: \"initCode (account factory) reverted. Check the Kernel factory address and the owner.\" },\n AA14: { code: \"BUNDLER_AA_FAILED\", hint: \"initCode deployed a different address than the sender. Rebuild the account with the same owner and index.\" },\n AA20: { code: \"BUNDLER_AA_FAILED\", hint: \"The account is not deployed and no initCode was sent. Use a fresh account object so the factory fields are included.\" },\n AA21: { code: \"BUNDLER_AA_FAILED\", hint: \"The account cannot pay its prefund. Use the paymaster, or fund the account.\" },\n AA22: { code: \"BUNDLER_AA_FAILED\", hint: \"The UserOperation's validity window expired. Resend a fresh one.\" },\n AA23: { code: \"BUNDLER_AA_FAILED\", hint: \"Account validation reverted: wrong signer, wrong signature format, or a session policy rejected the call.\" },\n AA24: { code: \"BUNDLER_AA_FAILED\", hint: \"Signature rejected by the account. Sign with the owner the account was built for.\" },\n AA25: { code: \"BUNDLER_AA_FAILED\", hint: \"Invalid nonce: another UserOperation from this account is pending. Wait for it, then retry.\" },\n AA26: { code: \"BUNDLER_AA_FAILED\", hint: \"verificationGasLimit too low. Re-estimate gas.\" },\n AA31: { code: \"PAYMASTER_NO_BALANCE\", paymaster: true, hint: \"The paymaster's EntryPoint deposit is too low. Deposit more PEPU to the paymaster.\" },\n AA32: { code: \"PAYMASTER_DENIED\", paymaster: true, hint: \"The paymaster signature expired. Request paymaster data again.\" },\n AA33: { code: \"PAYMASTER_DENIED\", paymaster: true, hint: \"Paymaster validation reverted. Check the paymaster contract and that its signer matches the policy service.\" },\n AA34: { code: \"PAYMASTER_DENIED\", paymaster: true, hint: \"Paymaster signature rejected. The policy service signer does not match the paymaster contract.\" },\n AA36: { code: \"BUNDLER_AA_FAILED\", paymaster: true, hint: \"Paymaster gas limits too low. Re-estimate with the paymaster stub data.\" },\n AA40: { code: \"BUNDLER_AA_FAILED\", hint: \"Verification used more gas than verificationGasLimit. Re-estimate gas.\" },\n AA41: { code: \"BUNDLER_AA_FAILED\", hint: \"Paymaster verification used more gas than its limit. Re-estimate gas.\" },\n AA50: { code: \"BUNDLER_AA_FAILED\", hint: \"The postOp reverted. Check the paymaster's postOp path.\" },\n AA51: { code: \"BUNDLER_AA_FAILED\", hint: \"Prefund below actualGasCost. Re-estimate fees; PEPU needs fee headroom (the SDK applies 20%).\" },\n AA90: { code: \"BUNDLER_AA_FAILED\", hint: \"Invalid beneficiary on handleOps. This is a bundler configuration problem.\" },\n AA91: { code: \"BUNDLER_AA_FAILED\", hint: \"Failed to send funds to the beneficiary. This is a bundler configuration problem.\" },\n AA95: { code: \"BUNDLER_AA_FAILED\", hint: \"Out of gas in handleOps. Raise the gas limits.\" },\n};\n\n/**\n * Remove anything credential-shaped from text that may reach a message:\n * `/paymaster/<token>` URL paths, bearer tokens, API keys, JWTs and URL\n * credentials.\n *\n * @example\n * redactSecrets(\"POST https://pm.example/paymaster/sk_live_123 failed\");\n * // \"POST https://pm.example/paymaster/[redacted] failed\"\n */\nexport function redactSecrets(text: string): string {\n return text\n .replace(/\\/paymaster\\/[^\\s/\"'`)\\]?#]+/gi, \"/paymaster/[redacted]\")\n .replace(/(bearer\\s+)[A-Za-z0-9._~+/=-]+/gi, \"$1[redacted]\")\n .replace(/(x-api-key[\"']?\\s*[:=]\\s*[\"']?)[^\\s\"',}]+/gi, \"$1[redacted]\")\n .replace(/(privyAccessToken[\"']?\\s*[:=]\\s*[\"']?)[^\\s\"',}]+/gi, \"$1[redacted]\")\n .replace(/\\beyJ[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]{8,}\\.[A-Za-z0-9_-]*/g, \"[redacted-jwt]\")\n .replace(/(https?:\\/\\/)[^\\s/@]+:[^\\s/@]+@/gi, \"$1[redacted]@\");\n}\n\nfunction collect(e: unknown): string {\n const seen = new Set<unknown>();\n const parts: string[] = [];\n let cur: unknown = e;\n for (let d = 0; d < 8 && cur !== undefined && cur !== null && !seen.has(cur); d++) {\n seen.add(cur);\n if (typeof cur === \"object\") {\n const o = cur as Record<string, unknown>;\n for (const k of [\"shortMessage\", \"message\", \"details\", \"reason\"]) {\n const v = o[k];\n if (typeof v === \"string\" && v.length > 0 && !parts.includes(v)) parts.push(v);\n }\n const data = o[\"data\"];\n if (data && typeof data === \"object\") {\n const r = (data as Record<string, unknown>)[\"reason\"];\n if (typeof r === \"string\") parts.push(r);\n }\n cur = o[\"cause\"];\n } else {\n parts.push(String(cur));\n break;\n }\n }\n return parts.join(\"\\n\");\n}\n\n/**\n * Turn anything thrown by the bundler, paymaster or viem/Privy stack into a\n * typed PepuError. Walks the `cause` chain (viem's `details` is where the\n * paymaster's real denial reason lives; Privy's own log prints\n * `[object Error]`), maps `AA10`..`AA9x` to a fix, maps paymaster reason codes\n * through the error catalog, and redacts tokens and URL credentials.\n * Port of `templates/sponsored-demo/lib/describe-error.ts`.\n *\n * @example\n * try { await sendSponsored({ client, calls }); }\n * catch (e) { const err = describeUserOpFailure(e); console.log(err.code, err.hint); }\n */\nexport function describeUserOpFailure(e: unknown): PepuBundlerError | PepuPaymasterError {\n const text = redactSecrets(collect(e));\n const headline = text.split(\"\\n\")[0]?.trim() || \"UserOperation failed\";\n const opts = (hint?: string) => ({ ...(hint ? { hint } : {}), cause: e });\n\n const aa = /\\bAA(\\d{2})\\b/.exec(text);\n if (aa) {\n const key = `AA${aa[1]}`;\n const info = AA_HINTS[key];\n if (info) {\n const msg = `${key}: ${headline}`;\n return info.paymaster && info.code !== \"BUNDLER_AA_FAILED\"\n ? new PepuPaymasterError(info.code, msg, opts(info.hint))\n : new PepuBundlerError(info.code, msg, opts(info.hint));\n }\n return new PepuBundlerError(\"BUNDLER_AA_FAILED\", `${key}: ${headline}`, opts());\n }\n\n const explained = explainError(text);\n if (explained.code.startsWith(\"PAYMASTER_\")) {\n return new PepuPaymasterError(explained.code, headline, opts(explained.fix));\n }\n if (explained.code !== \"UNKNOWN\") {\n return new PepuBundlerError(explained.code, headline, opts(explained.fix));\n }\n const pe = toPepuError(e);\n if (pe.code !== \"UNKNOWN\") return new PepuBundlerError(pe.code, redactSecrets(pe.message), opts(pe.hint));\n return new PepuBundlerError(\"UNKNOWN\", headline, opts(getErrorEntry(\"UNKNOWN\").fix));\n}\n"]}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { pepuMainnet } from './chunk-VTQIHMF3.js';
|
|
2
|
+
import { PepuConfigError } from './chunk-6DSZ4Z2N.js';
|
|
3
|
+
|
|
4
|
+
// src/endpoints.ts
|
|
5
|
+
var PEPU_HOSTED = {
|
|
6
|
+
bundlerUrl: "https://bundler.pepeunchained.com",
|
|
7
|
+
paymasterBaseUrl: "https://paymaster.pepeunchained.com",
|
|
8
|
+
paymasterUrl: null
|
|
9
|
+
};
|
|
10
|
+
var PEPU_ENV = {
|
|
11
|
+
bundlerUrl: "PEPU_BUNDLER_URL",
|
|
12
|
+
paymasterUrl: "PEPU_PAYMASTER_URL",
|
|
13
|
+
rpcUrl: "PEPU_RPC_URL"
|
|
14
|
+
};
|
|
15
|
+
var PEPU_PUBLIC_ENV = {
|
|
16
|
+
bundlerUrl: "NEXT_PUBLIC_PEPU_BUNDLER_URL",
|
|
17
|
+
paymasterUrl: "NEXT_PUBLIC_PEPU_PAYMASTER_URL",
|
|
18
|
+
rpcUrl: "NEXT_PUBLIC_PEPU_RPC_URL"
|
|
19
|
+
};
|
|
20
|
+
function clean(value) {
|
|
21
|
+
const v = value?.trim();
|
|
22
|
+
return v === void 0 || v === "" ? void 0 : v;
|
|
23
|
+
}
|
|
24
|
+
function validate(url, label) {
|
|
25
|
+
let parsed;
|
|
26
|
+
try {
|
|
27
|
+
parsed = new URL(url);
|
|
28
|
+
} catch {
|
|
29
|
+
throw new PepuConfigError("CONFIG_BAD_URL", `${label} is not a valid URL.`);
|
|
30
|
+
}
|
|
31
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
32
|
+
throw new PepuConfigError("CONFIG_BAD_URL", `${label} must be an http(s) URL.`);
|
|
33
|
+
}
|
|
34
|
+
return url;
|
|
35
|
+
}
|
|
36
|
+
function paymasterBaseOf(url) {
|
|
37
|
+
return url.replace(/\/+$/, "").replace(/\/(?:v2\/)?paymaster\/[^/]+$/, "");
|
|
38
|
+
}
|
|
39
|
+
function defaultEnv() {
|
|
40
|
+
return typeof process !== "undefined" && process.env ? process.env : {};
|
|
41
|
+
}
|
|
42
|
+
function resolvePepuEndpoints(options = {}) {
|
|
43
|
+
const env = options.env ?? defaultEnv();
|
|
44
|
+
const rank = { explicit: 2, env: 1, "hosted-default": 0 };
|
|
45
|
+
let source = "hosted-default";
|
|
46
|
+
const bump = (s) => {
|
|
47
|
+
if (rank[s] > rank[source]) source = s;
|
|
48
|
+
};
|
|
49
|
+
const pick = (key, explicit, hosted) => {
|
|
50
|
+
const e = clean(explicit);
|
|
51
|
+
if (e !== void 0) {
|
|
52
|
+
bump("explicit");
|
|
53
|
+
return validate(e, `Option ${key}`);
|
|
54
|
+
}
|
|
55
|
+
for (const name of [PEPU_ENV[key], PEPU_PUBLIC_ENV[key]]) {
|
|
56
|
+
const v = clean(env[name]);
|
|
57
|
+
if (v !== void 0) {
|
|
58
|
+
bump("env");
|
|
59
|
+
return validate(v, name);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return hosted;
|
|
63
|
+
};
|
|
64
|
+
const rpcDefault = pepuMainnet.rpcUrls.default.http[0];
|
|
65
|
+
const paymasterUrl = pick("paymasterUrl", options.paymasterUrl, PEPU_HOSTED.paymasterUrl);
|
|
66
|
+
return {
|
|
67
|
+
rpcUrl: pick("rpcUrl", options.rpcUrl, rpcDefault) ?? rpcDefault,
|
|
68
|
+
bundlerUrl: pick("bundlerUrl", options.bundlerUrl, PEPU_HOSTED.bundlerUrl),
|
|
69
|
+
paymasterUrl,
|
|
70
|
+
paymasterBaseUrl: paymasterUrl !== null ? paymasterBaseOf(paymasterUrl) : PEPU_HOSTED.paymasterBaseUrl,
|
|
71
|
+
source
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function isHostedSponsorshipLive() {
|
|
75
|
+
return PEPU_HOSTED.bundlerUrl !== null && PEPU_HOSTED.paymasterBaseUrl !== null;
|
|
76
|
+
}
|
|
77
|
+
function hostedFreeTierUrl() {
|
|
78
|
+
if (PEPU_HOSTED.paymasterBaseUrl === null) {
|
|
79
|
+
throw new PepuConfigError("CONFIG_MISSING_ENV", "No hosted paymaster base URL is set.");
|
|
80
|
+
}
|
|
81
|
+
return `${PEPU_HOSTED.paymasterBaseUrl.replace(/\/+$/, "")}/v2/free-tier`;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export { PEPU_ENV, PEPU_HOSTED, PEPU_PUBLIC_ENV, hostedFreeTierUrl, isHostedSponsorshipLive, paymasterBaseOf, resolvePepuEndpoints };
|
|
85
|
+
//# sourceMappingURL=chunk-XC4IBCI2.js.map
|
|
86
|
+
//# sourceMappingURL=chunk-XC4IBCI2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/endpoints.ts"],"names":[],"mappings":"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","file":"chunk-XC4IBCI2.js","sourcesContent":["import { pepuMainnet } from \"./chains.js\";\nimport { PepuConfigError } from \"./errors.js\";\n\n/**\n * Hosted-URL swap point. The hosted PEPU bundler and paymaster service run at\n * bundler.pepeunchained.com and paymaster.pepeunchained.com. Set here, the SDK,\n * MCP server and docs flip together. Apps can still point at their own\n * services with the env vars below.\n *\n * - `bundlerUrl` is a complete JSON-RPC URL.\n * - `paymasterBaseUrl` is the paymaster SERVICE base (REST API, `/health`,\n * `/v2/free-tier`). It is NOT an ERC-7677 URL: v2 serves ERC-7677 at\n * `<base>/v2/paymaster/<client token>`, so build that with\n * `hostedErc7677Url` (or `buildErc7677Url`).\n * - `paymasterUrl` is the default complete ERC-7677 URL. It stays `null`\n * because every ERC-7677 URL embeds a per-project token; set\n * `PEPU_PAYMASTER_URL` (or pass a token) to supply one.\n */\nexport const PEPU_HOSTED: {\n readonly bundlerUrl: string | null;\n readonly paymasterBaseUrl: string | null;\n readonly paymasterUrl: string | null;\n} = {\n bundlerUrl: \"https://bundler.pepeunchained.com\",\n paymasterBaseUrl: \"https://paymaster.pepeunchained.com\",\n paymasterUrl: null,\n};\n\n/** Server-side (and script) environment variable names. */\nexport const PEPU_ENV = {\n bundlerUrl: \"PEPU_BUNDLER_URL\",\n paymasterUrl: \"PEPU_PAYMASTER_URL\",\n rpcUrl: \"PEPU_RPC_URL\",\n} as const;\n\n/** Browser-exposed variants (Next.js `NEXT_PUBLIC_` convention). */\nexport const PEPU_PUBLIC_ENV = {\n bundlerUrl: \"NEXT_PUBLIC_PEPU_BUNDLER_URL\",\n paymasterUrl: \"NEXT_PUBLIC_PEPU_PAYMASTER_URL\",\n rpcUrl: \"NEXT_PUBLIC_PEPU_RPC_URL\",\n} as const;\n\nexport interface ResolvePepuEndpointsOptions {\n bundlerUrl?: string;\n paymasterUrl?: string;\n rpcUrl?: string;\n /**\n * Environment to read. Defaults to `process.env` when it exists. In browser\n * bundles frameworks only inline literal `process.env.NEXT_PUBLIC_X`\n * accesses, so pass them explicitly there.\n */\n env?: Record<string, string | undefined>;\n}\n\nexport interface PepuEndpoints {\n rpcUrl: string;\n bundlerUrl: string | null;\n /** Complete ERC-7677 URL from the option or env, else `null` (it needs a project token). */\n paymasterUrl: string | null;\n /**\n * Paymaster service base for the REST API, probes and ERC-7677 URL building.\n * From the option or env (a full ERC-7677 URL is reduced to its base), else the hosted base.\n */\n paymasterBaseUrl: string | null;\n /** Highest-precedence origin used for any of the three values. */\n source: \"explicit\" | \"env\" | \"hosted-default\";\n}\n\nfunction clean(value: string | undefined): string | undefined {\n const v = value?.trim();\n return v === undefined || v === \"\" ? undefined : v;\n}\n\nfunction validate(url: string, label: string): string {\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n throw new PepuConfigError(\"CONFIG_BAD_URL\", `${label} is not a valid URL.`);\n }\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n throw new PepuConfigError(\"CONFIG_BAD_URL\", `${label} must be an http(s) URL.`);\n }\n return url;\n}\n\n/** Strip a trailing `/v2/paymaster/<token>` or `/paymaster/<token>` and slashes, leaving the service base. */\nexport function paymasterBaseOf(url: string): string {\n return url.replace(/\\/+$/, \"\").replace(/\\/(?:v2\\/)?paymaster\\/[^/]+$/, \"\");\n}\n\nfunction defaultEnv(): Record<string, string | undefined> {\n return typeof process !== \"undefined\" && process.env ? process.env : {};\n}\n\n/**\n * Resolve endpoints. Precedence per value: explicit option, then env\n * (server variable, then `NEXT_PUBLIC_` variable), then {@link PEPU_HOSTED}.\n * Throws PepuConfigError (CONFIG_BAD_URL) naming the variable, never its value.\n */\nexport function resolvePepuEndpoints(options: ResolvePepuEndpointsOptions = {}): PepuEndpoints {\n const env = options.env ?? defaultEnv();\n const rank = { explicit: 2, env: 1, \"hosted-default\": 0 } as const;\n let source: PepuEndpoints[\"source\"] = \"hosted-default\";\n const bump = (s: PepuEndpoints[\"source\"]): void => {\n if (rank[s] > rank[source]) source = s;\n };\n\n const pick = (key: keyof typeof PEPU_ENV, explicit: string | undefined, hosted: string | null): string | null => {\n const e = clean(explicit);\n if (e !== undefined) {\n bump(\"explicit\");\n return validate(e, `Option ${key}`);\n }\n for (const name of [PEPU_ENV[key], PEPU_PUBLIC_ENV[key]]) {\n const v = clean(env[name]);\n if (v !== undefined) {\n bump(\"env\");\n return validate(v, name);\n }\n }\n return hosted;\n };\n\n const rpcDefault = pepuMainnet.rpcUrls.default.http[0];\n const paymasterUrl = pick(\"paymasterUrl\", options.paymasterUrl, PEPU_HOSTED.paymasterUrl);\n return {\n rpcUrl: pick(\"rpcUrl\", options.rpcUrl, rpcDefault) ?? rpcDefault,\n bundlerUrl: pick(\"bundlerUrl\", options.bundlerUrl, PEPU_HOSTED.bundlerUrl),\n paymasterUrl,\n paymasterBaseUrl: paymasterUrl !== null ? paymasterBaseOf(paymasterUrl) : PEPU_HOSTED.paymasterBaseUrl,\n source,\n };\n}\n\n/** True once the hosted bundler and the hosted paymaster service have URLs in {@link PEPU_HOSTED}. */\nexport function isHostedSponsorshipLive(): boolean {\n return PEPU_HOSTED.bundlerUrl !== null && PEPU_HOSTED.paymasterBaseUrl !== null;\n}\n\n/** The public free-tier state route on the hosted paymaster (`GET`, no credentials). */\nexport function hostedFreeTierUrl(): string {\n if (PEPU_HOSTED.paymasterBaseUrl === null) {\n throw new PepuConfigError(\"CONFIG_MISSING_ENV\", \"No hosted paymaster base URL is set.\");\n }\n return `${PEPU_HOSTED.paymasterBaseUrl.replace(/\\/+$/, \"\")}/v2/free-tier`;\n}\n"]}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { PepuPolicyError } from './chunk-6DSZ4Z2N.js';
|
|
2
|
+
import { isAddress, isHex, encodeFunctionData, toHex, toFunctionSelector, toFunctionSignature } from 'viem';
|
|
3
|
+
|
|
4
|
+
var PRIVY_POLICY_NAME_MAX_LENGTH = 49;
|
|
5
|
+
function assertWithinPolicyNameLimit(value, field) {
|
|
6
|
+
if (value.length > PRIVY_POLICY_NAME_MAX_LENGTH) {
|
|
7
|
+
throw new PepuPolicyError(
|
|
8
|
+
"POLICY_NAME_TOO_LONG",
|
|
9
|
+
`${field} is ${value.length} characters ("${value}"), but Privy rejects policy/rule names of ${PRIVY_POLICY_NAME_MAX_LENGTH + 1} or more (max ${PRIVY_POLICY_NAME_MAX_LENGTH}). Shorten it.`
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
function truncateAddress(address) {
|
|
15
|
+
return `${address.slice(0, 6)}...${address.slice(-4)}`;
|
|
16
|
+
}
|
|
17
|
+
function buildSessionPolicy({
|
|
18
|
+
contractAddress,
|
|
19
|
+
functions,
|
|
20
|
+
expiresAtUnixSeconds,
|
|
21
|
+
name
|
|
22
|
+
}) {
|
|
23
|
+
if (!isAddress(contractAddress, { strict: false })) {
|
|
24
|
+
throw new PepuPolicyError(
|
|
25
|
+
"POLICY_UNSCOPED",
|
|
26
|
+
"buildSessionPolicy: contractAddress must be a valid 0x address; refusing to build an unscoped policy."
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
if (functions.length === 0) {
|
|
30
|
+
throw new PepuPolicyError(
|
|
31
|
+
"POLICY_UNSCOPED",
|
|
32
|
+
"buildSessionPolicy: at least one function is required; refusing to build an unscoped policy."
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
for (const fn of functions) {
|
|
36
|
+
if (fn.type !== "function" || !fn.name) {
|
|
37
|
+
throw new PepuPolicyError(
|
|
38
|
+
"POLICY_UNSCOPED",
|
|
39
|
+
"buildSessionPolicy: every entry in `functions` must be an ABI function fragment with a name."
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (!Number.isInteger(expiresAtUnixSeconds) || expiresAtUnixSeconds <= 0) {
|
|
44
|
+
throw new PepuPolicyError(
|
|
45
|
+
"POLICY_UNSCOPED",
|
|
46
|
+
"buildSessionPolicy: expiresAtUnixSeconds must be a positive integer (unix seconds); refusing to build a policy with no expiry."
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
const short = truncateAddress(contractAddress);
|
|
50
|
+
const policyName = assertWithinPolicyNameLimit(
|
|
51
|
+
name ?? `session: ${functions.map((f) => f.name).join("/")} on ${short}`,
|
|
52
|
+
"Policy name"
|
|
53
|
+
);
|
|
54
|
+
const rules = functions.map((fn, index) => ({
|
|
55
|
+
name: assertWithinPolicyNameLimit(
|
|
56
|
+
`Allow ${fn.name}() on ${short}, 0 value, expires`,
|
|
57
|
+
`Rule name ("rules[${index}].name")`
|
|
58
|
+
),
|
|
59
|
+
method: "eth_signTransaction",
|
|
60
|
+
action: "ALLOW",
|
|
61
|
+
conditions: [
|
|
62
|
+
{ field_source: "ethereum_transaction", field: "to", operator: "eq", value: contractAddress },
|
|
63
|
+
{
|
|
64
|
+
field_source: "ethereum_calldata",
|
|
65
|
+
field: "function_name",
|
|
66
|
+
abi: [fn],
|
|
67
|
+
operator: "eq",
|
|
68
|
+
value: fn.name
|
|
69
|
+
},
|
|
70
|
+
{ field_source: "ethereum_transaction", field: "value", operator: "eq", value: "0x0" },
|
|
71
|
+
{
|
|
72
|
+
field_source: "system",
|
|
73
|
+
field: "current_unix_timestamp",
|
|
74
|
+
operator: "lte",
|
|
75
|
+
value: String(expiresAtUnixSeconds)
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
|
+
}));
|
|
79
|
+
return { version: "1.0", name: policyName, chain_type: "ethereum", rules };
|
|
80
|
+
}
|
|
81
|
+
function withGasLimitBuffer(estimatedGas) {
|
|
82
|
+
return estimatedGas + estimatedGas * 20n / 100n;
|
|
83
|
+
}
|
|
84
|
+
async function broadcastSignedTransaction(client, signed) {
|
|
85
|
+
const raw = typeof signed === "string" ? signed : signed.signed_transaction;
|
|
86
|
+
if (!isHex(raw) || raw.length <= 2) {
|
|
87
|
+
throw new Error("broadcastSignedTransaction: expected a 0x-prefixed hex signed transaction.");
|
|
88
|
+
}
|
|
89
|
+
return client.sendRawTransaction({ serializedTransaction: raw });
|
|
90
|
+
}
|
|
91
|
+
async function signAndBroadcast(params) {
|
|
92
|
+
const { client, from, to, chainId, sign } = params;
|
|
93
|
+
const value = params.value ?? 0n;
|
|
94
|
+
const data = params.data ?? (params.abi && params.functionName ? encodeFunctionData({
|
|
95
|
+
abi: params.abi,
|
|
96
|
+
functionName: params.functionName,
|
|
97
|
+
...params.args ? { args: params.args } : {}
|
|
98
|
+
}) : void 0);
|
|
99
|
+
if (!data) {
|
|
100
|
+
throw new Error("signAndBroadcast: provide `data`, or `abi` + `functionName`.");
|
|
101
|
+
}
|
|
102
|
+
const [nonce, estimatedGas, gasPrice] = await Promise.all([
|
|
103
|
+
client.getTransactionCount({ address: from, blockTag: "pending" }),
|
|
104
|
+
client.estimateGas({ account: from, to, data, value }),
|
|
105
|
+
client.getGasPrice()
|
|
106
|
+
]);
|
|
107
|
+
const transaction = {
|
|
108
|
+
to,
|
|
109
|
+
data,
|
|
110
|
+
value: toHex(value),
|
|
111
|
+
chain_id: chainId,
|
|
112
|
+
type: 0,
|
|
113
|
+
nonce,
|
|
114
|
+
gas_limit: toHex(withGasLimitBuffer(estimatedGas)),
|
|
115
|
+
gas_price: toHex(gasPrice)
|
|
116
|
+
};
|
|
117
|
+
return broadcastSignedTransaction(client, await sign(transaction));
|
|
118
|
+
}
|
|
119
|
+
var DEFAULT_SESSION_MINUTES = 15;
|
|
120
|
+
var MAX_SESSION_MINUTES = 1440;
|
|
121
|
+
function resolveSessionMinutes(raw) {
|
|
122
|
+
if (raw === null || raw === void 0 || typeof raw === "string" && raw.trim() === "") {
|
|
123
|
+
return DEFAULT_SESSION_MINUTES;
|
|
124
|
+
}
|
|
125
|
+
const n = Number(raw);
|
|
126
|
+
if (!Number.isFinite(n) || n <= 0) return DEFAULT_SESSION_MINUTES;
|
|
127
|
+
return Math.min(n, MAX_SESSION_MINUTES);
|
|
128
|
+
}
|
|
129
|
+
function sessionExpiry(nowSeconds, minutes) {
|
|
130
|
+
return Math.floor(nowSeconds + minutes * 60);
|
|
131
|
+
}
|
|
132
|
+
function describeSessionScope(p) {
|
|
133
|
+
if (!isAddress(p.contractAddress, { strict: false })) {
|
|
134
|
+
throw new PepuPolicyError("POLICY_UNSCOPED", "describeSessionScope: contractAddress must be a valid 0x address.");
|
|
135
|
+
}
|
|
136
|
+
if (p.functions.length === 0) {
|
|
137
|
+
throw new PepuPolicyError("POLICY_UNSCOPED", "describeSessionScope: at least one function is required.");
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
contractAddress: p.contractAddress,
|
|
141
|
+
expiresAtUnixSeconds: p.expiresAtUnixSeconds,
|
|
142
|
+
functions: p.functions.map((fn) => {
|
|
143
|
+
if (fn.type !== "function" || !fn.name) {
|
|
144
|
+
throw new PepuPolicyError(
|
|
145
|
+
"POLICY_UNSCOPED",
|
|
146
|
+
"describeSessionScope: every entry in `functions` must be an ABI function fragment with a name."
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
return {
|
|
150
|
+
name: fn.name,
|
|
151
|
+
signature: toFunctionSignature(fn).replace(/^function /, ""),
|
|
152
|
+
selector: toFunctionSelector(fn),
|
|
153
|
+
valueWei: "0"
|
|
154
|
+
};
|
|
155
|
+
})
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
var SESSION_TRUST_NOTICE = {
|
|
159
|
+
"privy-offchain": "This scope is enforced by Privy's backend policy engine when it receives each transaction request, not by an on-chain contract. You are trusting Privy's policy engine and this app's policy configuration to enforce the limits correctly. Gas is paid by your wallet and is not capped by the policy.",
|
|
160
|
+
"kernel-onchain": "This scope is enforced on-chain by your smart account's permission validator (call and timestamp policies). The limits hold even if this app's backend is compromised, but the session key can still act within them until it expires or you revoke it."
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
export { DEFAULT_SESSION_MINUTES, MAX_SESSION_MINUTES, PRIVY_POLICY_NAME_MAX_LENGTH, SESSION_TRUST_NOTICE, assertWithinPolicyNameLimit, broadcastSignedTransaction, buildSessionPolicy, describeSessionScope, resolveSessionMinutes, sessionExpiry, signAndBroadcast, withGasLimitBuffer };
|
|
164
|
+
//# sourceMappingURL=chunk-YKEWWQEJ.js.map
|
|
165
|
+
//# sourceMappingURL=chunk-YKEWWQEJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/session/policy.ts"],"names":[],"mappings":"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","file":"chunk-YKEWWQEJ.js","sourcesContent":["import { encodeFunctionData, isAddress, isHex, toFunctionSelector, toFunctionSignature, toHex } from \"viem\";\nimport type { Abi, AbiFunction, Address, Hash, Hex } from \"viem\";\nimport { PepuPolicyError } from \"../errors.js\";\n\n/**\n * SERVER-ONLY helpers (`@pepu-chain/sdk/server`). Nothing here holds a secret,\n * but these run on a backend that does hold Privy's app secret and\n * authorization key; keep this entry point out of client bundles. No module\n * in `src/` imports the `./server` barrel (enforced by a test). This file is the pure policy builder; it is re-exported from `@pepu-chain/sdk/session` and `@pepu-chain/sdk/server`.\n */\n\n/**\n * Privy rejects policy and rule names of 50 characters or more. Its published\n * OpenAPI spec says `maxLength: 50`, but the live validator says \"must be\n * fewer than 50 characters\", so the real limit is 49 (measured on a real\n * `POST /policies` 400). Using 49 is safe under both readings.\n */\nexport const PRIVY_POLICY_NAME_MAX_LENGTH = 49;\n\n/** Throws if `value` is over {@link PRIVY_POLICY_NAME_MAX_LENGTH}; returns it otherwise. */\nexport function assertWithinPolicyNameLimit(value: string, field: string): string {\n if (value.length > PRIVY_POLICY_NAME_MAX_LENGTH) {\n throw new PepuPolicyError(\"POLICY_NAME_TOO_LONG\", \n `${field} is ${value.length} characters (\"${value}\"), but Privy rejects policy/rule names ` +\n `of ${PRIVY_POLICY_NAME_MAX_LENGTH + 1} or more (max ${PRIVY_POLICY_NAME_MAX_LENGTH}). Shorten it.`,\n );\n }\n return value;\n}\n\nexport type SessionPolicyCondition =\n | { field_source: \"ethereum_transaction\"; field: \"to\" | \"value\"; operator: \"eq\"; value: string }\n | {\n field_source: \"ethereum_calldata\";\n field: \"function_name\";\n abi: AbiFunction[];\n operator: \"eq\";\n value: string;\n }\n | { field_source: \"system\"; field: \"current_unix_timestamp\"; operator: \"lte\"; value: string };\n\nexport interface SessionPolicyRule {\n name: string;\n method: \"eth_signTransaction\";\n action: \"ALLOW\";\n conditions: SessionPolicyCondition[];\n}\n\n/** Body for `privy.policies().create(...)`. */\nexport interface SessionPolicy {\n version: \"1.0\";\n name: string;\n chain_type: \"ethereum\";\n rules: SessionPolicyRule[];\n}\n\nexport interface BuildSessionPolicyParams {\n /** The one contract the session may call. */\n contractAddress: Address;\n /** The function(s) the session may call, as ABI function fragments. At least one. */\n functions: readonly AbiFunction[];\n /** Unix seconds after which Privy's engine denies every request. */\n expiresAtUnixSeconds: number;\n /** Optional dashboard label; must be at most 49 characters. */\n name?: string;\n}\n\nfunction truncateAddress(address: string): string {\n return `${address.slice(0, 6)}...${address.slice(-4)}`;\n}\n\n/**\n * Build the scoped Privy session-signer policy: ONE `ALLOW` rule per function,\n * each requiring `to` equals the contract, calldata decodes to that function,\n * `value` is exactly zero, and the clock is before expiry. Privy ANDs the\n * conditions in a rule, ORs the rules, and denies by default.\n *\n * Refuses to build an unscoped policy: it throws on an invalid contract\n * address, no functions, a non-function ABI item, or a bad expiry. Names are\n * checked against {@link PRIVY_POLICY_NAME_MAX_LENGTH}. The method is\n * `eth_signTransaction` (a rule for `eth_sendTransaction` never matches the\n * sign-and-broadcast flow).\n *\n * The scope is enforced by Privy's backend policy engine, not on-chain.\n */\nexport function buildSessionPolicy({\n contractAddress,\n functions,\n expiresAtUnixSeconds,\n name,\n}: BuildSessionPolicyParams): SessionPolicy {\n if (!isAddress(contractAddress, { strict: false })) {\n throw new PepuPolicyError(\"POLICY_UNSCOPED\", \n \"buildSessionPolicy: contractAddress must be a valid 0x address; refusing to build an unscoped policy.\",\n );\n }\n if (functions.length === 0) {\n throw new PepuPolicyError(\"POLICY_UNSCOPED\", \n \"buildSessionPolicy: at least one function is required; refusing to build an unscoped policy.\",\n );\n }\n for (const fn of functions) {\n if (fn.type !== \"function\" || !fn.name) {\n throw new PepuPolicyError(\"POLICY_UNSCOPED\", \n \"buildSessionPolicy: every entry in `functions` must be an ABI function fragment with a name.\",\n );\n }\n }\n if (!Number.isInteger(expiresAtUnixSeconds) || expiresAtUnixSeconds <= 0) {\n throw new PepuPolicyError(\"POLICY_UNSCOPED\", \n \"buildSessionPolicy: expiresAtUnixSeconds must be a positive integer (unix seconds); refusing to build a policy with no expiry.\",\n );\n }\n\n const short = truncateAddress(contractAddress);\n const policyName = assertWithinPolicyNameLimit(\n name ?? `session: ${functions.map((f) => f.name).join(\"/\")} on ${short}`,\n \"Policy name\",\n );\n\n const rules: SessionPolicyRule[] = functions.map((fn, index) => ({\n name: assertWithinPolicyNameLimit(\n `Allow ${fn.name}() on ${short}, 0 value, expires`,\n `Rule name (\"rules[${index}].name\")`,\n ),\n method: \"eth_signTransaction\",\n action: \"ALLOW\",\n conditions: [\n { field_source: \"ethereum_transaction\", field: \"to\", operator: \"eq\", value: contractAddress },\n {\n field_source: \"ethereum_calldata\",\n field: \"function_name\",\n abi: [fn],\n operator: \"eq\",\n value: fn.name,\n },\n { field_source: \"ethereum_transaction\", field: \"value\", operator: \"eq\", value: \"0x0\" },\n {\n field_source: \"system\",\n field: \"current_unix_timestamp\",\n operator: \"lte\",\n value: String(expiresAtUnixSeconds),\n },\n ],\n }));\n\n return { version: \"1.0\", name: policyName, chain_type: \"ethereum\", rules };\n}\n\n/** The unsigned legacy transaction body Privy's `eth_signTransaction` takes (snake_case, hex quantities). */\nexport interface PrivyUnsignedTransaction {\n readonly to: Address;\n readonly data: Hex;\n readonly value: Hex;\n readonly chain_id: number;\n readonly type: 0;\n readonly nonce: number;\n readonly gas_limit: Hex;\n readonly gas_price: Hex;\n}\n\n/** What Privy's `signTransaction` returns, or just the raw hex. */\nexport type SignedTransactionLike = Hex | { signed_transaction: string };\n\n/** Minimal viem client surface needed to broadcast. */\nexport interface BroadcastClient {\n sendRawTransaction(args: { serializedTransaction: Hex }): Promise<Hash>;\n}\n\n/** Minimal viem client surface needed to resolve nonce/gas and broadcast. */\nexport interface SignAndBroadcastClient extends BroadcastClient {\n getTransactionCount(args: { address: Address; blockTag: \"pending\" }): Promise<number>;\n estimateGas(args: { account: Address; to: Address; data: Hex; value: bigint }): Promise<bigint>;\n getGasPrice(): Promise<bigint>;\n}\n\n/** Estimate plus 20%: Nitro gas estimates can undershoot slightly. */\nexport function withGasLimitBuffer(estimatedGas: bigint): bigint {\n return estimatedGas + (estimatedGas * 20n) / 100n;\n}\n\n/**\n * Broadcast a raw signed transaction (from Privy `eth_signTransaction`) to\n * PEPU through a viem client and return the transaction hash. Accepts the raw\n * hex or Privy's `{ signed_transaction }` object. A failure here is a failed\n * TRANSACTION (revert, nonce race), not proof the session signer is gone.\n */\nexport async function broadcastSignedTransaction(\n client: BroadcastClient,\n signed: SignedTransactionLike,\n): Promise<Hash> {\n const raw = typeof signed === \"string\" ? signed : signed.signed_transaction;\n if (!isHex(raw) || raw.length <= 2) {\n throw new Error(\"broadcastSignedTransaction: expected a 0x-prefixed hex signed transaction.\");\n }\n return client.sendRawTransaction({ serializedTransaction: raw });\n}\n\nexport interface SignAndBroadcastParams {\n client: SignAndBroadcastClient;\n /** The wallet that signs (the session-signer wallet's address). */\n from: Address;\n to: Address;\n /** Pre-encoded calldata, or use `abi` + `functionName` + `args`. */\n data?: Hex;\n abi?: Abi;\n functionName?: string;\n args?: readonly unknown[];\n /** Native value in wei. Default 0n. */\n value?: bigint;\n chainId: number;\n /**\n * Performs the signing, e.g. a call to\n * `privy.wallets().ethereum().signTransaction(walletId, { params: { transaction }, authorization_context })`\n * and returns its result. Injected so this package has no Privy dependency.\n */\n sign: (transaction: PrivyUnsignedTransaction) => Promise<SignedTransactionLike>;\n}\n\n/**\n * The full sign-with-Privy, broadcast-yourself flow: resolve nonce (pending),\n * gas (+20%) and gas price against PEPU's RPC, build the unsigned legacy\n * transaction, hand it to `sign`, then broadcast the result and return the hash.\n * Privy's server-side `eth_sendTransaction` rejects chain 97741, which is why\n * this exists.\n */\nexport async function signAndBroadcast(params: SignAndBroadcastParams): Promise<Hash> {\n const { client, from, to, chainId, sign } = params;\n const value = params.value ?? 0n;\n const data =\n params.data ??\n (params.abi && params.functionName\n ? encodeFunctionData({\n abi: params.abi,\n functionName: params.functionName,\n ...(params.args ? { args: params.args } : {}),\n } as Parameters<typeof encodeFunctionData>[0])\n : undefined);\n if (!data) {\n throw new Error(\"signAndBroadcast: provide `data`, or `abi` + `functionName`.\");\n }\n\n const [nonce, estimatedGas, gasPrice] = await Promise.all([\n client.getTransactionCount({ address: from, blockTag: \"pending\" }),\n client.estimateGas({ account: from, to, data, value }),\n client.getGasPrice(),\n ]);\n\n const transaction: PrivyUnsignedTransaction = {\n to,\n data,\n value: toHex(value),\n chain_id: chainId,\n type: 0,\n nonce,\n gas_limit: toHex(withGasLimitBuffer(estimatedGas)),\n gas_price: toHex(gasPrice),\n };\n\n return broadcastSignedTransaction(client, await sign(transaction));\n}\n\n/** Default session length when `SESSION_DURATION_MINUTES` is unset or invalid. */\nexport const DEFAULT_SESSION_MINUTES = 15;\n/** Upper bound for a session: 24 hours. Larger requests are clamped. */\nexport const MAX_SESSION_MINUTES = 1440;\n\n/**\n * Parse a session duration (an env value or number) into minutes: anything\n * missing, non-numeric, zero or negative falls back to\n * {@link DEFAULT_SESSION_MINUTES}; anything above {@link MAX_SESSION_MINUTES} is clamped.\n * Lifted from templates/game-app/lib/env.server.ts.\n *\n * @example\n * resolveSessionMinutes(process.env.SESSION_DURATION_MINUTES); // 15 when unset\n * resolveSessionMinutes(\"99999\"); // 1440\n */\nexport function resolveSessionMinutes(raw: string | number | null | undefined): number {\n if (raw === null || raw === undefined || (typeof raw === \"string\" && raw.trim() === \"\")) {\n return DEFAULT_SESSION_MINUTES;\n }\n const n = Number(raw);\n if (!Number.isFinite(n) || n <= 0) return DEFAULT_SESSION_MINUTES;\n return Math.min(n, MAX_SESSION_MINUTES);\n}\n\n/**\n * The unix-seconds expiry for a session that starts at `nowSeconds` and lasts\n * `minutes`. Whole seconds, rounded down.\n *\n * @example\n * sessionExpiry(1_700_000_000, 15); // 1_700_000_900\n */\nexport function sessionExpiry(nowSeconds: number, minutes: number): number {\n return Math.floor(nowSeconds + minutes * 60);\n}\n\n/** One callable function in a session's scope, ready for a consent screen. */\nexport interface SessionScopeFunction {\n name: string;\n /** e.g. `tap()` or `transfer(address,uint256)`. */\n signature: string;\n /** 4-byte selector. */\n selector: Hex;\n /** Always `\"0\"`: a session call never carries native value. */\n valueWei: \"0\";\n}\n\n/** What a session may do, as plain data for a consent screen. */\nexport interface SessionScope {\n contractAddress: Address;\n functions: SessionScopeFunction[];\n expiresAtUnixSeconds: number;\n}\n\n/**\n * Consent-screen data for a session: the one contract, each allowed function\n * (name, signature, selector), zero value, and the expiry. Throws on an\n * invalid address or an empty or non-function list, same as {@link buildSessionPolicy}.\n *\n * @example\n * const scope = describeSessionScope({ contractAddress, functions: [tapAbi], expiresAtUnixSeconds });\n * scope.functions[0]?.signature; // \"tap()\"\n */\nexport function describeSessionScope(p: {\n contractAddress: Address;\n functions: readonly AbiFunction[];\n expiresAtUnixSeconds: number;\n}): SessionScope {\n if (!isAddress(p.contractAddress, { strict: false })) {\n throw new PepuPolicyError(\"POLICY_UNSCOPED\", \"describeSessionScope: contractAddress must be a valid 0x address.\");\n }\n if (p.functions.length === 0) {\n throw new PepuPolicyError(\"POLICY_UNSCOPED\", \"describeSessionScope: at least one function is required.\");\n }\n return {\n contractAddress: p.contractAddress,\n expiresAtUnixSeconds: p.expiresAtUnixSeconds,\n functions: p.functions.map((fn) => {\n if (fn.type !== \"function\" || !fn.name) {\n throw new PepuPolicyError(\"POLICY_UNSCOPED\", \n \"describeSessionScope: every entry in `functions` must be an ABI function fragment with a name.\",\n );\n }\n return {\n name: fn.name,\n signature: toFunctionSignature(fn).replace(/^function /, \"\"),\n selector: toFunctionSelector(fn),\n valueWei: \"0\" as const,\n };\n }),\n };\n}\n\n/**\n * The mandatory honest statements about who enforces a session's limits. Show\n * the one for the mode in use on the consent screen. Adapted from\n * templates/game-app/components/session-consent-screen.tsx.\n *\n * @example\n * <p>{SESSION_TRUST_NOTICE[\"privy-offchain\"]}</p>\n */\nexport const SESSION_TRUST_NOTICE: Record<\"privy-offchain\" | \"kernel-onchain\", string> = {\n \"privy-offchain\":\n \"This scope is enforced by Privy's backend policy engine when it receives each transaction request, not by an on-chain contract. You are trusting Privy's policy engine and this app's policy configuration to enforce the limits correctly. Gas is paid by your wallet and is not capped by the policy.\",\n \"kernel-onchain\":\n \"This scope is enforced on-chain by your smart account's permission validator (call and timestamp policies). The limits hold even if this app's backend is compromised, but the session key can still act within them until it expires or you revoke it.\",\n};\n"]}
|