@pepu-chain/sdk 0.0.0-stage → 0.2.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.
Files changed (244) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +590 -2
  3. package/dist/aa/kernel.cjs +41 -0
  4. package/dist/aa/kernel.cjs.map +1 -0
  5. package/dist/aa/kernel.d.cts +88 -0
  6. package/dist/aa/kernel.d.ts +88 -0
  7. package/dist/aa/kernel.guard.js +15 -0
  8. package/dist/aa/kernel.js +11 -0
  9. package/dist/aa/kernel.js.map +1 -0
  10. package/dist/aa/react-direct.cjs +111 -0
  11. package/dist/aa/react-direct.cjs.map +1 -0
  12. package/dist/aa/react-direct.d.cts +42 -0
  13. package/dist/aa/react-direct.d.ts +42 -0
  14. package/dist/aa/react-direct.guard.js +15 -0
  15. package/dist/aa/react-direct.js +107 -0
  16. package/dist/aa/react-direct.js.map +1 -0
  17. package/dist/aa/react.cjs +152 -0
  18. package/dist/aa/react.cjs.map +1 -0
  19. package/dist/aa/react.d.cts +62 -0
  20. package/dist/aa/react.d.ts +62 -0
  21. package/dist/aa/react.guard.js +15 -0
  22. package/dist/aa/react.js +147 -0
  23. package/dist/aa/react.js.map +1 -0
  24. package/dist/aa.cjs +84 -0
  25. package/dist/aa.cjs.map +1 -0
  26. package/dist/aa.d.cts +85 -0
  27. package/dist/aa.d.ts +85 -0
  28. package/dist/aa.js +11 -0
  29. package/dist/aa.js.map +1 -0
  30. package/dist/api-Dz4sCHH_.d.cts +654 -0
  31. package/dist/api-Dz4sCHH_.d.ts +654 -0
  32. package/dist/calls-BRPjKgjl.d.cts +70 -0
  33. package/dist/calls-z_EQOtFb.d.ts +70 -0
  34. package/dist/chains-DK13zGIp.d.cts +235 -0
  35. package/dist/chains-DK13zGIp.d.ts +235 -0
  36. package/dist/chunk-3XUGQODR.js +194 -0
  37. package/dist/chunk-3XUGQODR.js.map +1 -0
  38. package/dist/chunk-45KSZH26.cjs +145 -0
  39. package/dist/chunk-45KSZH26.cjs.map +1 -0
  40. package/dist/chunk-4GINFJO6.cjs +44 -0
  41. package/dist/chunk-4GINFJO6.cjs.map +1 -0
  42. package/dist/chunk-62M2LKQW.js +136 -0
  43. package/dist/chunk-62M2LKQW.js.map +1 -0
  44. package/dist/chunk-6DSZ4Z2N.js +498 -0
  45. package/dist/chunk-6DSZ4Z2N.js.map +1 -0
  46. package/dist/chunk-7MNJF2OB.cjs +72 -0
  47. package/dist/chunk-7MNJF2OB.cjs.map +1 -0
  48. package/dist/chunk-7PVR7QSE.js +45 -0
  49. package/dist/chunk-7PVR7QSE.js.map +1 -0
  50. package/dist/chunk-A5LP2UCS.cjs +2729 -0
  51. package/dist/chunk-A5LP2UCS.cjs.map +1 -0
  52. package/dist/chunk-AJS4UFQX.cjs +121 -0
  53. package/dist/chunk-AJS4UFQX.cjs.map +1 -0
  54. package/dist/chunk-BGALSKAF.cjs +315 -0
  55. package/dist/chunk-BGALSKAF.cjs.map +1 -0
  56. package/dist/chunk-C2XW44FI.cjs +200 -0
  57. package/dist/chunk-C2XW44FI.cjs.map +1 -0
  58. package/dist/chunk-C7IC36XS.cjs +13 -0
  59. package/dist/chunk-C7IC36XS.cjs.map +1 -0
  60. package/dist/chunk-D52PADVY.js +84 -0
  61. package/dist/chunk-D52PADVY.js.map +1 -0
  62. package/dist/chunk-DH6BFNVJ.cjs +272 -0
  63. package/dist/chunk-DH6BFNVJ.cjs.map +1 -0
  64. package/dist/chunk-DPCZJLB3.cjs +87 -0
  65. package/dist/chunk-DPCZJLB3.cjs.map +1 -0
  66. package/dist/chunk-EHBPIYY4.js +262 -0
  67. package/dist/chunk-EHBPIYY4.js.map +1 -0
  68. package/dist/chunk-ESMNAXUI.js +86 -0
  69. package/dist/chunk-ESMNAXUI.js.map +1 -0
  70. package/dist/chunk-F2R473FR.js +304 -0
  71. package/dist/chunk-F2R473FR.js.map +1 -0
  72. package/dist/chunk-IB2FSPMJ.js +66 -0
  73. package/dist/chunk-IB2FSPMJ.js.map +1 -0
  74. package/dist/chunk-IG7RSL2Y.cjs +178 -0
  75. package/dist/chunk-IG7RSL2Y.cjs.map +1 -0
  76. package/dist/chunk-IY3ALPUJ.js +2716 -0
  77. package/dist/chunk-IY3ALPUJ.js.map +1 -0
  78. package/dist/chunk-J3O2ZGG3.cjs +93 -0
  79. package/dist/chunk-J3O2ZGG3.cjs.map +1 -0
  80. package/dist/chunk-J6UXXHBE.js +37 -0
  81. package/dist/chunk-J6UXXHBE.js.map +1 -0
  82. package/dist/chunk-JLZ4LZ4Z.js +22 -0
  83. package/dist/chunk-JLZ4LZ4Z.js.map +1 -0
  84. package/dist/chunk-K7JSQPZO.cjs +231 -0
  85. package/dist/chunk-K7JSQPZO.cjs.map +1 -0
  86. package/dist/chunk-KJYNF5KH.js +224 -0
  87. package/dist/chunk-KJYNF5KH.js.map +1 -0
  88. package/dist/chunk-KVG3AYYR.js +99 -0
  89. package/dist/chunk-KVG3AYYR.js.map +1 -0
  90. package/dist/chunk-NE3QKDOB.cjs +24 -0
  91. package/dist/chunk-NE3QKDOB.cjs.map +1 -0
  92. package/dist/chunk-NVOPDXTA.cjs +95 -0
  93. package/dist/chunk-NVOPDXTA.cjs.map +1 -0
  94. package/dist/chunk-OH3QMAIB.js +11 -0
  95. package/dist/chunk-OH3QMAIB.js.map +1 -0
  96. package/dist/chunk-PHM3ZORG.cjs +110 -0
  97. package/dist/chunk-PHM3ZORG.cjs.map +1 -0
  98. package/dist/chunk-R5PXQNO3.cjs +209 -0
  99. package/dist/chunk-R5PXQNO3.cjs.map +1 -0
  100. package/dist/chunk-RCMKPJZO.cjs +49 -0
  101. package/dist/chunk-RCMKPJZO.cjs.map +1 -0
  102. package/dist/chunk-SVWRRALU.cjs +17 -0
  103. package/dist/chunk-SVWRRALU.cjs.map +1 -0
  104. package/dist/chunk-T43PQXJD.js +202 -0
  105. package/dist/chunk-T43PQXJD.js.map +1 -0
  106. package/dist/chunk-VBH3JLQ5.js +116 -0
  107. package/dist/chunk-VBH3JLQ5.js.map +1 -0
  108. package/dist/chunk-VF3D6KLQ.cjs +94 -0
  109. package/dist/chunk-VF3D6KLQ.cjs.map +1 -0
  110. package/dist/chunk-VTQIHMF3.js +82 -0
  111. package/dist/chunk-VTQIHMF3.js.map +1 -0
  112. package/dist/chunk-W3JN3YIW.js +15 -0
  113. package/dist/chunk-W3JN3YIW.js.map +1 -0
  114. package/dist/chunk-WANILJZQ.cjs +87 -0
  115. package/dist/chunk-WANILJZQ.cjs.map +1 -0
  116. package/dist/chunk-XC4IBCI2.js +86 -0
  117. package/dist/chunk-XC4IBCI2.js.map +1 -0
  118. package/dist/chunk-YKEWWQEJ.js +165 -0
  119. package/dist/chunk-YKEWWQEJ.js.map +1 -0
  120. package/dist/chunk-YQL7NISX.cjs +515 -0
  121. package/dist/chunk-YQL7NISX.cjs.map +1 -0
  122. package/dist/chunk-ZB6SVBK4.js +89 -0
  123. package/dist/chunk-ZB6SVBK4.js.map +1 -0
  124. package/dist/combo/react.cjs +236 -0
  125. package/dist/combo/react.cjs.map +1 -0
  126. package/dist/combo/react.d.cts +148 -0
  127. package/dist/combo/react.d.ts +148 -0
  128. package/dist/combo/react.guard.js +15 -0
  129. package/dist/combo/react.js +230 -0
  130. package/dist/combo/react.js.map +1 -0
  131. package/dist/combo.cjs +263 -0
  132. package/dist/combo.cjs.map +1 -0
  133. package/dist/combo.d.cts +139 -0
  134. package/dist/combo.d.ts +139 -0
  135. package/dist/combo.guard.js +15 -0
  136. package/dist/combo.js +249 -0
  137. package/dist/combo.js.map +1 -0
  138. package/dist/config-CHjz7ZjZ.d.cts +57 -0
  139. package/dist/config-COjhIZTh.d.ts +57 -0
  140. package/dist/doctor.cjs +354 -0
  141. package/dist/doctor.cjs.map +1 -0
  142. package/dist/doctor.d.cts +177 -0
  143. package/dist/doctor.d.ts +177 -0
  144. package/dist/doctor.js +345 -0
  145. package/dist/doctor.js.map +1 -0
  146. package/dist/erc7677-DOW58QBE.d.cts +111 -0
  147. package/dist/erc7677-DOW58QBE.d.ts +111 -0
  148. package/dist/errors-CgX1vNj7.d.cts +100 -0
  149. package/dist/errors-CgX1vNj7.d.ts +100 -0
  150. package/dist/index.cjs +806 -0
  151. package/dist/index.cjs.map +1 -0
  152. package/dist/index.d.cts +2398 -0
  153. package/dist/index.d.ts +2398 -0
  154. package/dist/index.js +559 -0
  155. package/dist/index.js.map +1 -0
  156. package/dist/paymaster/server.cjs +38 -0
  157. package/dist/paymaster/server.cjs.map +1 -0
  158. package/dist/paymaster/server.d.cts +57 -0
  159. package/dist/paymaster/server.d.ts +57 -0
  160. package/dist/paymaster/server.js +36 -0
  161. package/dist/paymaster/server.js.map +1 -0
  162. package/dist/paymaster.cjs +356 -0
  163. package/dist/paymaster.cjs.map +1 -0
  164. package/dist/paymaster.d.cts +1851 -0
  165. package/dist/paymaster.d.ts +1851 -0
  166. package/dist/paymaster.js +289 -0
  167. package/dist/paymaster.js.map +1 -0
  168. package/dist/privy/react.cjs +49 -0
  169. package/dist/privy/react.cjs.map +1 -0
  170. package/dist/privy/react.d.cts +194 -0
  171. package/dist/privy/react.d.ts +194 -0
  172. package/dist/privy/react.guard.js +15 -0
  173. package/dist/privy/react.js +7 -0
  174. package/dist/privy/react.js.map +1 -0
  175. package/dist/privy/server.cjs +44 -0
  176. package/dist/privy/server.cjs.map +1 -0
  177. package/dist/privy/server.d.cts +192 -0
  178. package/dist/privy/server.d.ts +192 -0
  179. package/dist/privy/server.guard.js +15 -0
  180. package/dist/privy/server.js +6 -0
  181. package/dist/privy/server.js.map +1 -0
  182. package/dist/privy/wagmi.d.ts +90 -0
  183. package/dist/privy/wagmi.guard.js +15 -0
  184. package/dist/privy/wagmi.js +55 -0
  185. package/dist/privy/wagmi.js.map +1 -0
  186. package/dist/privy.cjs +34 -0
  187. package/dist/privy.cjs.map +1 -0
  188. package/dist/privy.d.cts +4 -0
  189. package/dist/privy.d.ts +4 -0
  190. package/dist/privy.js +5 -0
  191. package/dist/privy.js.map +1 -0
  192. package/dist/react.cjs +73 -0
  193. package/dist/react.cjs.map +1 -0
  194. package/dist/react.d.cts +66 -0
  195. package/dist/react.d.ts +66 -0
  196. package/dist/react.guard.js +15 -0
  197. package/dist/react.js +68 -0
  198. package/dist/react.js.map +1 -0
  199. package/dist/requirements-C-QiJkL9.d.cts +134 -0
  200. package/dist/requirements-C-QiJkL9.d.ts +134 -0
  201. package/dist/scope-DBRkN7bR.d.cts +94 -0
  202. package/dist/scope-DBRkN7bR.d.ts +94 -0
  203. package/dist/server.cjs +59 -0
  204. package/dist/server.cjs.map +1 -0
  205. package/dist/server.d.cts +208 -0
  206. package/dist/server.d.ts +208 -0
  207. package/dist/server.js +8 -0
  208. package/dist/server.js.map +1 -0
  209. package/dist/session/kernel.cjs +83 -0
  210. package/dist/session/kernel.cjs.map +1 -0
  211. package/dist/session/kernel.d.cts +131 -0
  212. package/dist/session/kernel.d.ts +131 -0
  213. package/dist/session/kernel.guard.js +15 -0
  214. package/dist/session/kernel.js +13 -0
  215. package/dist/session/kernel.js.map +1 -0
  216. package/dist/session/react.cjs +38 -0
  217. package/dist/session/react.cjs.map +1 -0
  218. package/dist/session/react.d.cts +119 -0
  219. package/dist/session/react.d.ts +119 -0
  220. package/dist/session/react.guard.js +15 -0
  221. package/dist/session/react.js +8 -0
  222. package/dist/session/react.js.map +1 -0
  223. package/dist/session/server.cjs +268 -0
  224. package/dist/session/server.cjs.map +1 -0
  225. package/dist/session/server.d.cts +151 -0
  226. package/dist/session/server.d.ts +151 -0
  227. package/dist/session/server.guard.js +15 -0
  228. package/dist/session/server.js +252 -0
  229. package/dist/session/server.js.map +1 -0
  230. package/dist/session.cjs +74 -0
  231. package/dist/session.cjs.map +1 -0
  232. package/dist/session.d.cts +3 -0
  233. package/dist/session.d.ts +3 -0
  234. package/dist/session.js +5 -0
  235. package/dist/session.js.map +1 -0
  236. package/dist/status-Dx9zAFo9.d.ts +327 -0
  237. package/dist/status-wgTM26V7.d.cts +327 -0
  238. package/dist/store-CjmLgp9g.d.cts +64 -0
  239. package/dist/store-CjmLgp9g.d.ts +64 -0
  240. package/dist/types-BEEM7WdG.d.cts +25 -0
  241. package/dist/types-BEEM7WdG.d.ts +25 -0
  242. package/dist/types-BilBTDqK.d.cts +27 -0
  243. package/dist/types-BilBTDqK.d.ts +27 -0
  244. package/package.json +245 -3
package/dist/combo.cjs ADDED
@@ -0,0 +1,263 @@
1
+ 'use strict';
2
+ /* @pepu-chain/peer-guard */(function(){var p=["@privy-io/node","@zerodev/sdk","@zerodev/permissions","@zerodev/ecdsa-validator"];for(var i=0;i<p.length;i++){try{require.resolve(p[i])}catch(e){if(e&&e.code==="MODULE_NOT_FOUND"){var m="@pepu-chain/sdk/combo needs peer packages that are not installed: @privy-io/node @zerodev/sdk @zerodev/permissions @zerodev/ecdsa-validator. Install with: npm i @privy-io/node @zerodev/sdk @zerodev/permissions @zerodev/ecdsa-validator (or let create-pepu-app scaffold everything).";var x=new Error(m);x.code="PEPU_MISSING_PEER";throw x}}}})();
3
+
4
+ var chunkPHM3ZORG_cjs = require('./chunk-PHM3ZORG.cjs');
5
+ var chunkNVOPDXTA_cjs = require('./chunk-NVOPDXTA.cjs');
6
+ require('./chunk-7MNJF2OB.cjs');
7
+ var chunkAJS4UFQX_cjs = require('./chunk-AJS4UFQX.cjs');
8
+ require('./chunk-A5LP2UCS.cjs');
9
+ var chunkRCMKPJZO_cjs = require('./chunk-RCMKPJZO.cjs');
10
+ require('./chunk-WANILJZQ.cjs');
11
+ require('./chunk-K7JSQPZO.cjs');
12
+ var chunkJ3O2ZGG3_cjs = require('./chunk-J3O2ZGG3.cjs');
13
+ require('./chunk-4GINFJO6.cjs');
14
+ var chunkVF3D6KLQ_cjs = require('./chunk-VF3D6KLQ.cjs');
15
+ var chunkDPCZJLB3_cjs = require('./chunk-DPCZJLB3.cjs');
16
+ var chunk45KSZH26_cjs = require('./chunk-45KSZH26.cjs');
17
+ var chunkSVWRRALU_cjs = require('./chunk-SVWRRALU.cjs');
18
+ require('./chunk-C2XW44FI.cjs');
19
+ var chunkIG7RSL2Y_cjs = require('./chunk-IG7RSL2Y.cjs');
20
+ var chunkYQL7NISX_cjs = require('./chunk-YQL7NISX.cjs');
21
+ var viem = require('viem');
22
+
23
+ chunkSVWRRALU_cjs.assertServerOnly("@pepu-chain/sdk/combo");
24
+ function json(body, status = 200) {
25
+ return new Response(JSON.stringify(body), { status, headers: { "content-type": "application/json" } });
26
+ }
27
+ function upstream(e, op) {
28
+ const err = chunkYQL7NISX_cjs.toPepuError(e, { op });
29
+ if (err.code === "UNKNOWN" && !(e instanceof chunkYQL7NISX_cjs.PepuError)) {
30
+ return new chunkYQL7NISX_cjs.PepuChainError("UNKNOWN", err.message, { status: 502, cause: e });
31
+ }
32
+ return err;
33
+ }
34
+ async function guard(op, fn) {
35
+ try {
36
+ return await fn();
37
+ } catch (e) {
38
+ return chunkYQL7NISX_cjs.toErrorResponse(upstream(e, op));
39
+ }
40
+ }
41
+ function bearerToken(request) {
42
+ return (request.headers.get("authorization") ?? "").replace(/^Bearer\s+/i, "").trim();
43
+ }
44
+ var nowSeconds = () => Math.floor(Date.now() / 1e3);
45
+ function defaultPublicClient() {
46
+ return viem.createPublicClient({ chain: chunkDPCZJLB3_cjs.pepuMainnet, transport: viem.http(chunkVF3D6KLQ_cjs.resolvePepuEndpoints().rpcUrl) });
47
+ }
48
+ function createSponsoredSessionRoutes(o) {
49
+ const unconfigured = o.scope.calls.some((c) => !c.target || String(c.target).trim() === "");
50
+ if (unconfigured) {
51
+ const unset = async () => chunkYQL7NISX_cjs.toErrorResponse(
52
+ new chunkYQL7NISX_cjs.PepuConfigError(
53
+ "CONFIG_MISSING_ENV",
54
+ `${o.scope.targetEnv ?? "A session target contract address"} is not set to a valid address. See .env.example.`,
55
+ { hint: "Set it and restart the server." }
56
+ )
57
+ );
58
+ return {
59
+ prepare: { POST: unset },
60
+ activate: { POST: unset },
61
+ status: { GET: unset },
62
+ act: { POST: unset },
63
+ revoke: { POST: unset }
64
+ };
65
+ }
66
+ chunkPHM3ZORG_cjs.buildKernelSessionPolicies({ calls: o.scope.calls, validUntil: 1 });
67
+ let publicClient = o.publicClient;
68
+ const client = () => publicClient ??= defaultPublicClient();
69
+ const authenticate = async (request) => {
70
+ if (o.authenticate) {
71
+ const user = await o.authenticate(request);
72
+ if (!user) throw new chunkYQL7NISX_cjs.PepuAuthError("AUTH_INVALID_TOKEN", "Missing or invalid Privy access token.");
73
+ return user;
74
+ }
75
+ const auth = await chunk45KSZH26_cjs.requireUser(request, { privy: o.privy ?? chunk45KSZH26_cjs.createPrivyServer() });
76
+ if (!auth.ok) return auth.response;
77
+ if (!auth.user.address) {
78
+ throw new chunkYQL7NISX_cjs.PepuAuthError("WALLET_NOT_PROVISIONED", "No embedded wallet yet. Create it first (ensure-wallet route).", {
79
+ status: 409
80
+ });
81
+ }
82
+ return { userId: auth.user.userId, ownerAddress: auth.user.address };
83
+ };
84
+ const minutes = () => o.minutes ?? chunkIG7RSL2Y_cjs.resolveSessionMinutes(process.env.SESSION_DURATION_MINUTES);
85
+ const policiesFor = (validUntil) => chunkPHM3ZORG_cjs.buildKernelSessionPolicies({ calls: o.scope.calls, validUntil });
86
+ return {
87
+ prepare: {
88
+ POST: (request) => guard("combo prepare", async () => {
89
+ const user = await authenticate(request);
90
+ if (user instanceof Response) return user;
91
+ const { userId, ownerAddress } = user;
92
+ const mins = minutes();
93
+ const validUntil = chunkIG7RSL2Y_cjs.sessionExpiry(nowSeconds(), mins);
94
+ const key = chunkPHM3ZORG_cjs.generateSessionKey();
95
+ const policies = policiesFor(validUntil);
96
+ const [kernelAddress, permissionId] = await Promise.all([
97
+ chunkNVOPDXTA_cjs.getKernelAddress(client(), ownerAddress),
98
+ chunkPHM3ZORG_cjs.expectedPermissionId({ publicClient: client(), sessionKeyAddress: key.address, policies })
99
+ ]);
100
+ const record = {
101
+ userId,
102
+ ownerAddress,
103
+ kernelAddress,
104
+ sessionPrivateKey: key.privateKey,
105
+ sessionKeyAddress: key.address,
106
+ permissionId,
107
+ validUntil,
108
+ approval: null,
109
+ actions: 0
110
+ };
111
+ await o.store.set(record);
112
+ return json({
113
+ ownerAddress,
114
+ kernelAddress,
115
+ sessionKeyAddress: key.address,
116
+ validUntil,
117
+ minutes: mins,
118
+ scope: chunkJ3O2ZGG3_cjs.describeKernelSessionScope({ calls: o.scope.calls, validUntil })
119
+ });
120
+ })
121
+ },
122
+ activate: {
123
+ POST: (request) => guard("combo activate", async () => {
124
+ const user = await authenticate(request);
125
+ if (user instanceof Response) return user;
126
+ const body = await request.json().catch(() => null);
127
+ if (typeof body?.approval !== "string") {
128
+ throw new chunkYQL7NISX_cjs.PepuPolicyError("UNKNOWN", "Missing approval.", { status: 400, hint: "Send { approval }." });
129
+ }
130
+ const record = await o.store.get(user.userId);
131
+ if (!record || record.approval !== null) {
132
+ throw new chunkYQL7NISX_cjs.PepuSessionError("SESSION_NONE", "No pending session. Start again.");
133
+ }
134
+ if (nowSeconds() >= record.validUntil) {
135
+ await o.store.delete(record.userId);
136
+ throw new chunkYQL7NISX_cjs.PepuSessionError("SESSION_EXPIRED", "The session offer expired. Start again.");
137
+ }
138
+ const check = chunkJ3O2ZGG3_cjs.checkApproval(body.approval, {
139
+ kernelAddress: record.kernelAddress,
140
+ permissionId: record.permissionId
141
+ });
142
+ if (!check.ok) throw new chunkYQL7NISX_cjs.PepuSessionError("SESSION_APPROVAL_MISMATCH", check.reason, { status: 400 });
143
+ await o.store.set({ ...record, approval: body.approval });
144
+ return json({ active: true, validUntil: record.validUntil });
145
+ })
146
+ },
147
+ status: {
148
+ GET: (request) => guard("combo status", async () => {
149
+ const user = await authenticate(request);
150
+ if (user instanceof Response) return user;
151
+ const record = await o.store.get(user.userId);
152
+ if (!record || !chunkPHM3ZORG_cjs.isLive(record, nowSeconds())) return json({ active: false });
153
+ return json({
154
+ active: true,
155
+ validUntil: record.validUntil,
156
+ kernelAddress: record.kernelAddress,
157
+ ownerAddress: record.ownerAddress,
158
+ sessionKeyAddress: record.sessionKeyAddress,
159
+ actions: record.actions
160
+ });
161
+ })
162
+ },
163
+ act: {
164
+ POST: (request) => guard("combo act", async () => {
165
+ const user = await authenticate(request);
166
+ if (user instanceof Response) return user;
167
+ const record = await o.store.get(user.userId);
168
+ if (!record || !record.approval || !chunkPHM3ZORG_cjs.isLive(record, nowSeconds())) {
169
+ throw new chunkYQL7NISX_cjs.PepuSessionError("SESSION_NONE", "No active session. Start one first.");
170
+ }
171
+ let input;
172
+ try {
173
+ input = o.act.parse(await request.json().catch(() => ({})));
174
+ } catch (e) {
175
+ throw new chunkYQL7NISX_cjs.PepuPolicyError("UNKNOWN", e instanceof Error ? e.message : "Invalid request body.", {
176
+ status: 400,
177
+ hint: "Fix the request body.",
178
+ cause: e
179
+ });
180
+ }
181
+ const calls = o.act.buildCalls(input, {
182
+ kernelAddress: record.kernelAddress,
183
+ ownerAddress: record.ownerAddress
184
+ });
185
+ assertCallsInScope(chunkJ3O2ZGG3_cjs.describeKernelSessionScope({ calls: o.scope.calls, validUntil: record.validUntil }), calls);
186
+ if (!await o.store.tryLock(user.userId)) {
187
+ throw new chunkYQL7NISX_cjs.PepuChainError("UNKNOWN", "An action is already in flight.", {
188
+ status: 429,
189
+ retryable: true,
190
+ hint: "Wait for the current action to finish."
191
+ });
192
+ }
193
+ const privyToken = o.forwardPrivyToken === false ? "" : bearerToken(request);
194
+ try {
195
+ const account = await chunkPHM3ZORG_cjs.loadKernelSessionAccount({
196
+ publicClient: client(),
197
+ approval: record.approval,
198
+ sessionPrivateKey: record.sessionPrivateKey
199
+ });
200
+ const kernel = chunkNVOPDXTA_cjs.createPepuSponsoredClient({
201
+ account,
202
+ publicClient: client(),
203
+ ...o.endpoints?.bundlerUrl !== void 0 ? { bundlerUrl: o.endpoints.bundlerUrl } : {},
204
+ ...o.endpoints?.paymasterUrl !== void 0 ? { paymasterUrl: o.endpoints.paymasterUrl } : {},
205
+ ...o.endpoints?.paymasterToken !== void 0 ? { paymasterToken: o.endpoints.paymasterToken } : {},
206
+ ...privyToken ? { paymasterContext: chunkRCMKPJZO_cjs.buildPaymasterContext({ privyAccessToken: privyToken }) } : {}
207
+ });
208
+ const result = await chunkNVOPDXTA_cjs.sendSponsored({ client: kernel, calls });
209
+ const actions = record.actions + (result.success ? 1 : 0);
210
+ if (result.success) await o.store.set({ ...record, actions });
211
+ const out = {
212
+ userOpHash: result.userOpHash,
213
+ transactionHash: result.transactionHash,
214
+ kernelAddress: record.kernelAddress,
215
+ success: result.success,
216
+ paymaster: result.paymaster,
217
+ actualGasCostWei: result.actualGasCostWei.toString(),
218
+ explorerUrl: result.explorerUrl,
219
+ actions
220
+ };
221
+ return json(out);
222
+ } finally {
223
+ await o.store.unlock(user.userId);
224
+ }
225
+ })
226
+ },
227
+ revoke: {
228
+ POST: (request) => guard("combo revoke", async () => {
229
+ const user = await authenticate(request);
230
+ if (user instanceof Response) return user;
231
+ await o.store.delete(user.userId);
232
+ return json({ active: false });
233
+ })
234
+ }
235
+ };
236
+ }
237
+ function assertCallsInScope(scope, calls) {
238
+ for (const c of chunkAJS4UFQX_cjs.normalizeCalls(calls)) {
239
+ if (!chunkJ3O2ZGG3_cjs.isCallInScope(scope, c)) {
240
+ throw new chunkYQL7NISX_cjs.PepuPolicyError("POLICY_UNSCOPED", "A call is outside the session scope.", {
241
+ status: 403,
242
+ hint: "Only the contracts and functions the user approved can be called."
243
+ });
244
+ }
245
+ }
246
+ }
247
+
248
+ Object.defineProperty(exports, "createMemoryStore", {
249
+ enumerable: true,
250
+ get: function () { return chunkPHM3ZORG_cjs.createMemoryStore; }
251
+ });
252
+ Object.defineProperty(exports, "isLive", {
253
+ enumerable: true,
254
+ get: function () { return chunkPHM3ZORG_cjs.isLive; }
255
+ });
256
+ Object.defineProperty(exports, "resolveSessionMinutes", {
257
+ enumerable: true,
258
+ get: function () { return chunkIG7RSL2Y_cjs.resolveSessionMinutes; }
259
+ });
260
+ exports.assertCallsInScope = assertCallsInScope;
261
+ exports.createSponsoredSessionRoutes = createSponsoredSessionRoutes;
262
+ //# sourceMappingURL=combo.cjs.map
263
+ //# sourceMappingURL=combo.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/combo/server.ts"],"names":["assertServerOnly","toPepuError","PepuError","PepuChainError","toErrorResponse","createPublicClient","pepuMainnet","http","resolvePepuEndpoints","PepuConfigError","buildKernelSessionPolicies","PepuAuthError","requireUser","createPrivyServer","resolveSessionMinutes","sessionExpiry","generateSessionKey","getKernelAddress","expectedPermissionId","describeKernelSessionScope","PepuPolicyError","PepuSessionError","checkApproval","isLive","loadKernelSessionAccount","createPepuSponsoredClient","buildPaymasterContext","sendSponsored","normalizeCalls","isCallInScope"],"mappings":"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","file":"combo.cjs","sourcesContent":["import type { PrivyClient } from \"@privy-io/node\";\nimport { createPublicClient, http } from \"viem\";\nimport type { Address, PublicClient } from \"viem\";\nimport type { SponsoredActResult } from \"./types.js\";\nimport { createPepuSponsoredClient, sendSponsored } from \"../aa/kernel.js\";\nimport { normalizeCalls } from \"../aa/calls.js\";\nimport type { Call } from \"../aa/types.js\";\nimport { pepuMainnet } from \"../chains.js\";\nimport { resolvePepuEndpoints } from \"../endpoints.js\";\nimport { buildPaymasterContext } from \"../erc7677.js\";\nimport {\n PepuAuthError,\n PepuChainError,\n PepuConfigError,\n PepuError,\n PepuPolicyError,\n PepuSessionError,\n toErrorResponse,\n toPepuError,\n} from \"../errors.js\";\nimport { assertServerOnly } from \"../internal/assert-server.js\";\nimport { createPrivyServer, requireUser } from \"../privy/server.js\";\nimport { resolveSessionMinutes, sessionExpiry } from \"../session/policy.js\";\nimport {\n buildKernelSessionPolicies,\n checkApproval,\n describeKernelSessionScope,\n expectedPermissionId,\n generateSessionKey,\n getKernelAddress,\n isCallInScope,\n loadKernelSessionAccount,\n} from \"../session/kernel.js\";\nimport type { KernelSessionCall, KernelSessionScope } from \"../session/kernel.js\";\nimport { isLive } from \"../session/store.js\";\nimport type { SessionRecord, SessionStore } from \"../session/store.js\";\n\nassertServerOnly(\"@pepu-chain/sdk/combo\");\n\n/**\n * `@pepu-chain/sdk/combo` (server): the combined flow. Google sign-in (Privy),\n * a ONE-TIME on-chain session, and sponsored gas. Route factories for the\n * Kernel session lifecycle: prepare, activate, status, act, revoke.\n *\n * Extracted from templates/sponsored-session-app/app/api/session/* and\n * lib/{kernel,session-auth}.ts.\n *\n * Trust model: the chain, not these routes, enforces scope. The owner's single\n * EIP-712 signature enables a permission whose call policy (targets,\n * selectors, zero value) and timestamp policy the Kernel account verifies on\n * every UserOperation. The checks here only fail fast.\n *\n * Optional peers: `@privy-io/node`, `@zerodev/*`.\n */\n\nexport { createMemoryStore, isLive } from \"../session/store.js\";\nexport type { SessionRecord, SessionStore } from \"../session/store.js\";\nexport type { KernelSessionCall, KernelSessionScope } from \"../session/kernel.js\";\nexport type { SponsoredActResult } from \"./types.js\";\n/** Session length from `SESSION_DURATION_MINUTES` (default 15, clamped to 1..1440), the same rule the routes use. */\nexport { resolveSessionMinutes } from \"../session/policy.js\";\n\n/** The authenticated caller of a combo route. */\nexport interface ComboUser {\n userId: string;\n /** The user's Privy embedded wallet: the owner of their Kernel account. From Privy, never the request. */\n ownerAddress: Address;\n}\n\n/** Authenticate a request. Throw a `PepuError` (or return `null`) when it is not valid. */\nexport type ComboAuthenticate = (request: Request) => Promise<ComboUser | null>;\n\n/** Options for {@link createSponsoredSessionRoutes}. */\nexport interface SponsoredSessionRoutesOptions<I> {\n /** What the session may call. Enforced on-chain by the call policy. */\n scope: {\n calls: readonly KernelSessionCall[];\n /** Env variable named in the `CONFIG_MISSING_ENV` message when a call target is empty (unset). */\n targetEnv?: string;\n };\n /**\n * Where session records (including the session private key) live. Use\n * `createMemoryStore()` for development only: production needs a persistent\n * store with the key encrypted at rest.\n */\n store: SessionStore;\n /**\n * Bundler and paymaster. The bundler defaults to env `PEPU_BUNDLER_URL`, then the hosted bundler. The paymaster\n * needs a complete ERC-7677 URL (env `PEPU_PAYMASTER_URL`, or `paymasterUrl`) or a project `paymasterToken`\n * (built against the hosted paymaster base).\n */\n endpoints?: { bundlerUrl?: string; paymasterUrl?: string; paymasterToken?: string };\n /**\n * Forward the caller's Privy access token (the request's `Authorization: Bearer`) to the paymaster as ERC-7677\n * `context.privyAccessToken`. The v2 FREE TIER requires it; a project paying from its own deposit does not.\n * Default `true`. Set `false` if your paymaster URL is not a PEPU policy service you trust with the token.\n */\n forwardPrivyToken?: boolean;\n /** Session length. Default env `SESSION_DURATION_MINUTES`, then 15; clamped to 1..1440. */\n minutes?: number;\n /** The one action users take with their session. */\n act: {\n /** Validate the client body. Throw to reject with 400. */\n parse(body: unknown): I;\n /** The calls to send. Each is re-checked against `scope` before sponsoring. */\n buildCalls(input: I, ctx: { kernelAddress: Address; ownerAddress: Address }): Call[];\n };\n /** Privy client for the default authentication. Default `createPrivyServer()`. */\n privy?: PrivyClient;\n /**\n * Custom authentication. Default: B1's `requireUser` (verifies the Privy\n * bearer token and reads the user's embedded wallet from Privy).\n */\n authenticate?: ComboAuthenticate;\n /** Chain reads. Default: viem on the PEPU RPC (`PEPU_RPC_URL` aware). */\n publicClient?: PublicClient;\n}\n\n/** The five route handlers returned by {@link createSponsoredSessionRoutes}. */\nexport interface SponsoredSessionRoutes {\n prepare: { POST(request: Request): Promise<Response> };\n activate: { POST(request: Request): Promise<Response> };\n status: { GET(request: Request): Promise<Response> };\n act: { POST(request: Request): Promise<Response> };\n revoke: { POST(request: Request): Promise<Response> };\n}\n\nfunction json(body: unknown, status = 200): Response {\n return new Response(JSON.stringify(body), { status, headers: { \"content-type\": \"application/json\" } });\n}\n\n/** Anything unclassified that reaches a route is an upstream failure, not our 500. */\nfunction upstream(e: unknown, op: string): PepuError {\n const err = toPepuError(e, { op });\n if (err.code === \"UNKNOWN\" && !(e instanceof PepuError)) {\n return new PepuChainError(\"UNKNOWN\", err.message, { status: 502, cause: e });\n }\n return err;\n}\n\nasync function guard(op: string, fn: () => Promise<Response>): Promise<Response> {\n try {\n return await fn();\n } catch (e) {\n return toErrorResponse(upstream(e, op));\n }\n}\n\n/** The bearer token on a request, or `\"\"`. */\nfunction bearerToken(request: Request): string {\n return (request.headers.get(\"authorization\") ?? \"\").replace(/^Bearer\\s+/i, \"\").trim();\n}\n\nconst nowSeconds = (): number => Math.floor(Date.now() / 1000);\n\nfunction defaultPublicClient(): PublicClient {\n return createPublicClient({ chain: pepuMainnet, transport: http(resolvePepuEndpoints().rpcUrl) }) as PublicClient;\n}\n\n/**\n * Route handlers for the Kernel session lifecycle.\n *\n * - `prepare.POST`: the server creates a fresh session key and decides the\n * expiry. The private key stays on the server; the response carries only the\n * key's address, the expiry and the scope, so the browser can ask the owner\n * for the ONE signature that grants exactly that. Calling it again replaces\n * any pending or active session (the old key is dropped).\n * - `activate.POST` `{ approval }`: checks the approval is for this user's\n * smart account and for exactly the key, scope and expiry issued in\n * `prepare`, then stores it. 409 `SESSION_NONE` when nothing is pending,\n * 410 `SESSION_EXPIRED` for an expired offer, 400 `SESSION_APPROVAL_MISMATCH`.\n * - `status.GET`: `{ active: false }` or `{ active: true, validUntil, ... }`.\n * Never returns the session key or approval.\n * - `act.POST`: signs ONE sponsored UserOperation with the session key. 409\n * `SESSION_NONE` without a live session, 429 while another action runs.\n * - `revoke.POST`: deletes the session key and approval from the server, so\n * the app can no longer act, immediately. It does NOT uninstall the\n * permission on-chain: that grant stays valid until its expiry, but only the\n * deleted key can use it and only within the scope. An on-chain uninstall is\n * an owner-signed call to the user's own account, which a paymaster\n * destination allowlist rightly does not sponsor.\n *\n * Gas: the paymaster policy service reserves worst-case cost per operation:\n * about 20.5 PEPU for a session's first operation and about 6.9 PEPU for later\n * ones (`SESSION_GAS_RESERVATION_PEPU`). Size spend caps above that. Fees come\n * from the chain with 20% headroom.\n *\n * @example\n * // lib/session-routes.ts\n * export const routes = createSponsoredSessionRoutes({\n * scope: { calls: [{ target: tapScore, abi: tapScoreAbi, functionName: \"tap\" }] },\n * store: createMemoryStore(), // DEV ONLY\n * act: {\n * parse: () => ({}),\n * buildCalls: () => [{ to: tapScore, abi: tapScoreAbi, functionName: \"tap\" }],\n * },\n * });\n * // app/api/session/prepare/route.ts: export const { POST } = routes.prepare;\n */\nexport function createSponsoredSessionRoutes<I>(o: SponsoredSessionRoutesOptions<I>): SponsoredSessionRoutes {\n // A call whose target is empty or undefined (an unset env variable) is \"not configured yet\":\n // every route then answers CONFIG_MISSING_ENV at request time. A malformed non-empty scope\n // still fails at startup, not on the first request.\n const unconfigured = o.scope.calls.some((c) => !c.target || String(c.target).trim() === \"\");\n if (unconfigured) {\n const unset = async (): Promise<Response> =>\n toErrorResponse(\n new PepuConfigError(\n \"CONFIG_MISSING_ENV\",\n `${o.scope.targetEnv ?? \"A session target contract address\"} is not set to a valid address. See .env.example.`,\n { hint: \"Set it and restart the server.\" },\n ),\n );\n return {\n prepare: { POST: unset },\n activate: { POST: unset },\n status: { GET: unset },\n act: { POST: unset },\n revoke: { POST: unset },\n };\n }\n buildKernelSessionPolicies({ calls: o.scope.calls, validUntil: 1 });\n let publicClient = o.publicClient;\n const client = (): PublicClient => (publicClient ??= defaultPublicClient());\n\n const authenticate = async (request: Request): Promise<ComboUser | Response> => {\n if (o.authenticate) {\n const user = await o.authenticate(request);\n if (!user) throw new PepuAuthError(\"AUTH_INVALID_TOKEN\", \"Missing or invalid Privy access token.\");\n return user;\n }\n const auth = await requireUser(request, { privy: o.privy ?? createPrivyServer() });\n if (!auth.ok) return auth.response;\n if (!auth.user.address) {\n throw new PepuAuthError(\"WALLET_NOT_PROVISIONED\", \"No embedded wallet yet. Create it first (ensure-wallet route).\", {\n status: 409,\n });\n }\n return { userId: auth.user.userId, ownerAddress: auth.user.address };\n };\n\n const minutes = (): number => o.minutes ?? resolveSessionMinutes(process.env.SESSION_DURATION_MINUTES);\n const policiesFor = (validUntil: number) => buildKernelSessionPolicies({ calls: o.scope.calls, validUntil });\n\n return {\n prepare: {\n POST: (request) =>\n guard(\"combo prepare\", async () => {\n const user = await authenticate(request);\n if (user instanceof Response) return user;\n const { userId, ownerAddress } = user;\n const mins = minutes();\n const validUntil = sessionExpiry(nowSeconds(), mins);\n const key = generateSessionKey();\n const policies = policiesFor(validUntil);\n const [kernelAddress, permissionId] = await Promise.all([\n getKernelAddress(client(), ownerAddress),\n expectedPermissionId({ publicClient: client(), sessionKeyAddress: key.address, policies }),\n ]);\n const record: SessionRecord = {\n userId,\n ownerAddress,\n kernelAddress,\n sessionPrivateKey: key.privateKey,\n sessionKeyAddress: key.address,\n permissionId,\n validUntil,\n approval: null,\n actions: 0,\n };\n await o.store.set(record);\n return json({\n ownerAddress,\n kernelAddress,\n sessionKeyAddress: key.address,\n validUntil,\n minutes: mins,\n scope: describeKernelSessionScope({ calls: o.scope.calls, validUntil }),\n });\n }),\n },\n\n activate: {\n POST: (request) =>\n guard(\"combo activate\", async () => {\n const user = await authenticate(request);\n if (user instanceof Response) return user;\n const body = (await request.json().catch(() => null)) as { approval?: unknown } | null;\n if (typeof body?.approval !== \"string\") {\n throw new PepuPolicyError(\"UNKNOWN\", \"Missing approval.\", { status: 400, hint: \"Send { approval }.\" });\n }\n const record = await o.store.get(user.userId);\n if (!record || record.approval !== null) {\n throw new PepuSessionError(\"SESSION_NONE\", \"No pending session. Start again.\");\n }\n if (nowSeconds() >= record.validUntil) {\n await o.store.delete(record.userId);\n throw new PepuSessionError(\"SESSION_EXPIRED\", \"The session offer expired. Start again.\");\n }\n const check = checkApproval(body.approval, {\n kernelAddress: record.kernelAddress,\n permissionId: record.permissionId,\n });\n if (!check.ok) throw new PepuSessionError(\"SESSION_APPROVAL_MISMATCH\", check.reason, { status: 400 });\n await o.store.set({ ...record, approval: body.approval });\n return json({ active: true, validUntil: record.validUntil });\n }),\n },\n\n status: {\n GET: (request) =>\n guard(\"combo status\", async () => {\n const user = await authenticate(request);\n if (user instanceof Response) return user;\n const record = await o.store.get(user.userId);\n if (!record || !isLive(record, nowSeconds())) return json({ active: false });\n return json({\n active: true,\n validUntil: record.validUntil,\n kernelAddress: record.kernelAddress,\n ownerAddress: record.ownerAddress,\n sessionKeyAddress: record.sessionKeyAddress,\n actions: record.actions,\n });\n }),\n },\n\n act: {\n POST: (request) =>\n guard(\"combo act\", async () => {\n const user = await authenticate(request);\n if (user instanceof Response) return user;\n const record = await o.store.get(user.userId);\n if (!record || !record.approval || !isLive(record, nowSeconds())) {\n throw new PepuSessionError(\"SESSION_NONE\", \"No active session. Start one first.\");\n }\n\n let input: I;\n try {\n input = o.act.parse(await request.json().catch(() => ({})));\n } catch (e) {\n throw new PepuPolicyError(\"UNKNOWN\", e instanceof Error ? e.message : \"Invalid request body.\", {\n status: 400,\n hint: \"Fix the request body.\",\n cause: e,\n });\n }\n const calls = o.act.buildCalls(input, {\n kernelAddress: record.kernelAddress,\n ownerAddress: record.ownerAddress,\n });\n // Fail fast; the chain is the real enforcement (see the file comment).\n assertCallsInScope(describeKernelSessionScope({ calls: o.scope.calls, validUntil: record.validUntil }), calls);\n\n if (!(await o.store.tryLock(user.userId))) {\n throw new PepuChainError(\"UNKNOWN\", \"An action is already in flight.\", {\n status: 429,\n retryable: true,\n hint: \"Wait for the current action to finish.\",\n });\n }\n const privyToken = o.forwardPrivyToken === false ? \"\" : bearerToken(request);\n try {\n const account = await loadKernelSessionAccount({\n publicClient: client(),\n approval: record.approval,\n sessionPrivateKey: record.sessionPrivateKey,\n });\n const kernel = createPepuSponsoredClient({\n account,\n publicClient: client(),\n ...(o.endpoints?.bundlerUrl !== undefined ? { bundlerUrl: o.endpoints.bundlerUrl } : {}),\n ...(o.endpoints?.paymasterUrl !== undefined ? { paymasterUrl: o.endpoints.paymasterUrl } : {}),\n ...(o.endpoints?.paymasterToken !== undefined ? { paymasterToken: o.endpoints.paymasterToken } : {}),\n ...(privyToken ? { paymasterContext: buildPaymasterContext({ privyAccessToken: privyToken }) } : {}),\n });\n const result = await sendSponsored({ client: kernel, calls });\n const actions = record.actions + (result.success ? 1 : 0);\n if (result.success) await o.store.set({ ...record, actions });\n const out: SponsoredActResult = {\n userOpHash: result.userOpHash,\n transactionHash: result.transactionHash,\n kernelAddress: record.kernelAddress,\n success: result.success,\n paymaster: result.paymaster,\n actualGasCostWei: result.actualGasCostWei.toString(),\n explorerUrl: result.explorerUrl,\n actions,\n };\n return json(out);\n } finally {\n await o.store.unlock(user.userId);\n }\n }),\n },\n\n revoke: {\n POST: (request) =>\n guard(\"combo revoke\", async () => {\n const user = await authenticate(request);\n if (user instanceof Response) return user;\n await o.store.delete(user.userId);\n return json({ active: false });\n }),\n },\n };\n}\n\n/**\n * Throws `POLICY_UNSCOPED` (403) unless every call targets an allowed contract\n * and function selector with a value within the limit. Pure; used by the act\n * route and exported for custom routes.\n *\n * @example\n * assertCallsInScope(describeKernelSessionScope({ calls, validUntil }), [{ to, abi, functionName: \"tap\" }]);\n */\nexport function assertCallsInScope(scope: Pick<KernelSessionScope, \"calls\">, calls: readonly Call[]): void {\n for (const c of normalizeCalls(calls)) {\n if (!isCallInScope(scope, c)) {\n throw new PepuPolicyError(\"POLICY_UNSCOPED\", \"A call is outside the session scope.\", {\n status: 403,\n hint: \"Only the contracts and functions the user approved can be called.\",\n });\n }\n }\n}\n"]}
@@ -0,0 +1,139 @@
1
+ import { PrivyClient } from '@privy-io/node';
2
+ import { Address, PublicClient } from 'viem';
3
+ import { C as Call } from './types-BilBTDqK.cjs';
4
+ import { K as KernelSessionCall, a as KernelSessionScope } from './scope-DBRkN7bR.cjs';
5
+ import { S as SessionStore } from './store-CjmLgp9g.cjs';
6
+ export { a as SessionRecord, c as createMemoryStore, i as isLive } from './store-CjmLgp9g.cjs';
7
+ export { S as SponsoredActResult } from './types-BEEM7WdG.cjs';
8
+ export { resolveSessionMinutes } from './server.cjs';
9
+
10
+ /** The authenticated caller of a combo route. */
11
+ interface ComboUser {
12
+ userId: string;
13
+ /** The user's Privy embedded wallet: the owner of their Kernel account. From Privy, never the request. */
14
+ ownerAddress: Address;
15
+ }
16
+ /** Authenticate a request. Throw a `PepuError` (or return `null`) when it is not valid. */
17
+ type ComboAuthenticate = (request: Request) => Promise<ComboUser | null>;
18
+ /** Options for {@link createSponsoredSessionRoutes}. */
19
+ interface SponsoredSessionRoutesOptions<I> {
20
+ /** What the session may call. Enforced on-chain by the call policy. */
21
+ scope: {
22
+ calls: readonly KernelSessionCall[];
23
+ /** Env variable named in the `CONFIG_MISSING_ENV` message when a call target is empty (unset). */
24
+ targetEnv?: string;
25
+ };
26
+ /**
27
+ * Where session records (including the session private key) live. Use
28
+ * `createMemoryStore()` for development only: production needs a persistent
29
+ * store with the key encrypted at rest.
30
+ */
31
+ store: SessionStore;
32
+ /**
33
+ * Bundler and paymaster. The bundler defaults to env `PEPU_BUNDLER_URL`, then the hosted bundler. The paymaster
34
+ * needs a complete ERC-7677 URL (env `PEPU_PAYMASTER_URL`, or `paymasterUrl`) or a project `paymasterToken`
35
+ * (built against the hosted paymaster base).
36
+ */
37
+ endpoints?: {
38
+ bundlerUrl?: string;
39
+ paymasterUrl?: string;
40
+ paymasterToken?: string;
41
+ };
42
+ /**
43
+ * Forward the caller's Privy access token (the request's `Authorization: Bearer`) to the paymaster as ERC-7677
44
+ * `context.privyAccessToken`. The v2 FREE TIER requires it; a project paying from its own deposit does not.
45
+ * Default `true`. Set `false` if your paymaster URL is not a PEPU policy service you trust with the token.
46
+ */
47
+ forwardPrivyToken?: boolean;
48
+ /** Session length. Default env `SESSION_DURATION_MINUTES`, then 15; clamped to 1..1440. */
49
+ minutes?: number;
50
+ /** The one action users take with their session. */
51
+ act: {
52
+ /** Validate the client body. Throw to reject with 400. */
53
+ parse(body: unknown): I;
54
+ /** The calls to send. Each is re-checked against `scope` before sponsoring. */
55
+ buildCalls(input: I, ctx: {
56
+ kernelAddress: Address;
57
+ ownerAddress: Address;
58
+ }): Call[];
59
+ };
60
+ /** Privy client for the default authentication. Default `createPrivyServer()`. */
61
+ privy?: PrivyClient;
62
+ /**
63
+ * Custom authentication. Default: B1's `requireUser` (verifies the Privy
64
+ * bearer token and reads the user's embedded wallet from Privy).
65
+ */
66
+ authenticate?: ComboAuthenticate;
67
+ /** Chain reads. Default: viem on the PEPU RPC (`PEPU_RPC_URL` aware). */
68
+ publicClient?: PublicClient;
69
+ }
70
+ /** The five route handlers returned by {@link createSponsoredSessionRoutes}. */
71
+ interface SponsoredSessionRoutes {
72
+ prepare: {
73
+ POST(request: Request): Promise<Response>;
74
+ };
75
+ activate: {
76
+ POST(request: Request): Promise<Response>;
77
+ };
78
+ status: {
79
+ GET(request: Request): Promise<Response>;
80
+ };
81
+ act: {
82
+ POST(request: Request): Promise<Response>;
83
+ };
84
+ revoke: {
85
+ POST(request: Request): Promise<Response>;
86
+ };
87
+ }
88
+ /**
89
+ * Route handlers for the Kernel session lifecycle.
90
+ *
91
+ * - `prepare.POST`: the server creates a fresh session key and decides the
92
+ * expiry. The private key stays on the server; the response carries only the
93
+ * key's address, the expiry and the scope, so the browser can ask the owner
94
+ * for the ONE signature that grants exactly that. Calling it again replaces
95
+ * any pending or active session (the old key is dropped).
96
+ * - `activate.POST` `{ approval }`: checks the approval is for this user's
97
+ * smart account and for exactly the key, scope and expiry issued in
98
+ * `prepare`, then stores it. 409 `SESSION_NONE` when nothing is pending,
99
+ * 410 `SESSION_EXPIRED` for an expired offer, 400 `SESSION_APPROVAL_MISMATCH`.
100
+ * - `status.GET`: `{ active: false }` or `{ active: true, validUntil, ... }`.
101
+ * Never returns the session key or approval.
102
+ * - `act.POST`: signs ONE sponsored UserOperation with the session key. 409
103
+ * `SESSION_NONE` without a live session, 429 while another action runs.
104
+ * - `revoke.POST`: deletes the session key and approval from the server, so
105
+ * the app can no longer act, immediately. It does NOT uninstall the
106
+ * permission on-chain: that grant stays valid until its expiry, but only the
107
+ * deleted key can use it and only within the scope. An on-chain uninstall is
108
+ * an owner-signed call to the user's own account, which a paymaster
109
+ * destination allowlist rightly does not sponsor.
110
+ *
111
+ * Gas: the paymaster policy service reserves worst-case cost per operation:
112
+ * about 20.5 PEPU for a session's first operation and about 6.9 PEPU for later
113
+ * ones (`SESSION_GAS_RESERVATION_PEPU`). Size spend caps above that. Fees come
114
+ * from the chain with 20% headroom.
115
+ *
116
+ * @example
117
+ * // lib/session-routes.ts
118
+ * export const routes = createSponsoredSessionRoutes({
119
+ * scope: { calls: [{ target: tapScore, abi: tapScoreAbi, functionName: "tap" }] },
120
+ * store: createMemoryStore(), // DEV ONLY
121
+ * act: {
122
+ * parse: () => ({}),
123
+ * buildCalls: () => [{ to: tapScore, abi: tapScoreAbi, functionName: "tap" }],
124
+ * },
125
+ * });
126
+ * // app/api/session/prepare/route.ts: export const { POST } = routes.prepare;
127
+ */
128
+ declare function createSponsoredSessionRoutes<I>(o: SponsoredSessionRoutesOptions<I>): SponsoredSessionRoutes;
129
+ /**
130
+ * Throws `POLICY_UNSCOPED` (403) unless every call targets an allowed contract
131
+ * and function selector with a value within the limit. Pure; used by the act
132
+ * route and exported for custom routes.
133
+ *
134
+ * @example
135
+ * assertCallsInScope(describeKernelSessionScope({ calls, validUntil }), [{ to, abi, functionName: "tap" }]);
136
+ */
137
+ declare function assertCallsInScope(scope: Pick<KernelSessionScope, "calls">, calls: readonly Call[]): void;
138
+
139
+ export { type ComboAuthenticate, type ComboUser, KernelSessionCall, KernelSessionScope, SessionStore, type SponsoredSessionRoutes, type SponsoredSessionRoutesOptions, assertCallsInScope, createSponsoredSessionRoutes };
@@ -0,0 +1,139 @@
1
+ import { PrivyClient } from '@privy-io/node';
2
+ import { Address, PublicClient } from 'viem';
3
+ import { C as Call } from './types-BilBTDqK.js';
4
+ import { K as KernelSessionCall, a as KernelSessionScope } from './scope-DBRkN7bR.js';
5
+ import { S as SessionStore } from './store-CjmLgp9g.js';
6
+ export { a as SessionRecord, c as createMemoryStore, i as isLive } from './store-CjmLgp9g.js';
7
+ export { S as SponsoredActResult } from './types-BEEM7WdG.js';
8
+ export { resolveSessionMinutes } from './server.js';
9
+
10
+ /** The authenticated caller of a combo route. */
11
+ interface ComboUser {
12
+ userId: string;
13
+ /** The user's Privy embedded wallet: the owner of their Kernel account. From Privy, never the request. */
14
+ ownerAddress: Address;
15
+ }
16
+ /** Authenticate a request. Throw a `PepuError` (or return `null`) when it is not valid. */
17
+ type ComboAuthenticate = (request: Request) => Promise<ComboUser | null>;
18
+ /** Options for {@link createSponsoredSessionRoutes}. */
19
+ interface SponsoredSessionRoutesOptions<I> {
20
+ /** What the session may call. Enforced on-chain by the call policy. */
21
+ scope: {
22
+ calls: readonly KernelSessionCall[];
23
+ /** Env variable named in the `CONFIG_MISSING_ENV` message when a call target is empty (unset). */
24
+ targetEnv?: string;
25
+ };
26
+ /**
27
+ * Where session records (including the session private key) live. Use
28
+ * `createMemoryStore()` for development only: production needs a persistent
29
+ * store with the key encrypted at rest.
30
+ */
31
+ store: SessionStore;
32
+ /**
33
+ * Bundler and paymaster. The bundler defaults to env `PEPU_BUNDLER_URL`, then the hosted bundler. The paymaster
34
+ * needs a complete ERC-7677 URL (env `PEPU_PAYMASTER_URL`, or `paymasterUrl`) or a project `paymasterToken`
35
+ * (built against the hosted paymaster base).
36
+ */
37
+ endpoints?: {
38
+ bundlerUrl?: string;
39
+ paymasterUrl?: string;
40
+ paymasterToken?: string;
41
+ };
42
+ /**
43
+ * Forward the caller's Privy access token (the request's `Authorization: Bearer`) to the paymaster as ERC-7677
44
+ * `context.privyAccessToken`. The v2 FREE TIER requires it; a project paying from its own deposit does not.
45
+ * Default `true`. Set `false` if your paymaster URL is not a PEPU policy service you trust with the token.
46
+ */
47
+ forwardPrivyToken?: boolean;
48
+ /** Session length. Default env `SESSION_DURATION_MINUTES`, then 15; clamped to 1..1440. */
49
+ minutes?: number;
50
+ /** The one action users take with their session. */
51
+ act: {
52
+ /** Validate the client body. Throw to reject with 400. */
53
+ parse(body: unknown): I;
54
+ /** The calls to send. Each is re-checked against `scope` before sponsoring. */
55
+ buildCalls(input: I, ctx: {
56
+ kernelAddress: Address;
57
+ ownerAddress: Address;
58
+ }): Call[];
59
+ };
60
+ /** Privy client for the default authentication. Default `createPrivyServer()`. */
61
+ privy?: PrivyClient;
62
+ /**
63
+ * Custom authentication. Default: B1's `requireUser` (verifies the Privy
64
+ * bearer token and reads the user's embedded wallet from Privy).
65
+ */
66
+ authenticate?: ComboAuthenticate;
67
+ /** Chain reads. Default: viem on the PEPU RPC (`PEPU_RPC_URL` aware). */
68
+ publicClient?: PublicClient;
69
+ }
70
+ /** The five route handlers returned by {@link createSponsoredSessionRoutes}. */
71
+ interface SponsoredSessionRoutes {
72
+ prepare: {
73
+ POST(request: Request): Promise<Response>;
74
+ };
75
+ activate: {
76
+ POST(request: Request): Promise<Response>;
77
+ };
78
+ status: {
79
+ GET(request: Request): Promise<Response>;
80
+ };
81
+ act: {
82
+ POST(request: Request): Promise<Response>;
83
+ };
84
+ revoke: {
85
+ POST(request: Request): Promise<Response>;
86
+ };
87
+ }
88
+ /**
89
+ * Route handlers for the Kernel session lifecycle.
90
+ *
91
+ * - `prepare.POST`: the server creates a fresh session key and decides the
92
+ * expiry. The private key stays on the server; the response carries only the
93
+ * key's address, the expiry and the scope, so the browser can ask the owner
94
+ * for the ONE signature that grants exactly that. Calling it again replaces
95
+ * any pending or active session (the old key is dropped).
96
+ * - `activate.POST` `{ approval }`: checks the approval is for this user's
97
+ * smart account and for exactly the key, scope and expiry issued in
98
+ * `prepare`, then stores it. 409 `SESSION_NONE` when nothing is pending,
99
+ * 410 `SESSION_EXPIRED` for an expired offer, 400 `SESSION_APPROVAL_MISMATCH`.
100
+ * - `status.GET`: `{ active: false }` or `{ active: true, validUntil, ... }`.
101
+ * Never returns the session key or approval.
102
+ * - `act.POST`: signs ONE sponsored UserOperation with the session key. 409
103
+ * `SESSION_NONE` without a live session, 429 while another action runs.
104
+ * - `revoke.POST`: deletes the session key and approval from the server, so
105
+ * the app can no longer act, immediately. It does NOT uninstall the
106
+ * permission on-chain: that grant stays valid until its expiry, but only the
107
+ * deleted key can use it and only within the scope. An on-chain uninstall is
108
+ * an owner-signed call to the user's own account, which a paymaster
109
+ * destination allowlist rightly does not sponsor.
110
+ *
111
+ * Gas: the paymaster policy service reserves worst-case cost per operation:
112
+ * about 20.5 PEPU for a session's first operation and about 6.9 PEPU for later
113
+ * ones (`SESSION_GAS_RESERVATION_PEPU`). Size spend caps above that. Fees come
114
+ * from the chain with 20% headroom.
115
+ *
116
+ * @example
117
+ * // lib/session-routes.ts
118
+ * export const routes = createSponsoredSessionRoutes({
119
+ * scope: { calls: [{ target: tapScore, abi: tapScoreAbi, functionName: "tap" }] },
120
+ * store: createMemoryStore(), // DEV ONLY
121
+ * act: {
122
+ * parse: () => ({}),
123
+ * buildCalls: () => [{ to: tapScore, abi: tapScoreAbi, functionName: "tap" }],
124
+ * },
125
+ * });
126
+ * // app/api/session/prepare/route.ts: export const { POST } = routes.prepare;
127
+ */
128
+ declare function createSponsoredSessionRoutes<I>(o: SponsoredSessionRoutesOptions<I>): SponsoredSessionRoutes;
129
+ /**
130
+ * Throws `POLICY_UNSCOPED` (403) unless every call targets an allowed contract
131
+ * and function selector with a value within the limit. Pure; used by the act
132
+ * route and exported for custom routes.
133
+ *
134
+ * @example
135
+ * assertCallsInScope(describeKernelSessionScope({ calls, validUntil }), [{ to, abi, functionName: "tap" }]);
136
+ */
137
+ declare function assertCallsInScope(scope: Pick<KernelSessionScope, "calls">, calls: readonly Call[]): void;
138
+
139
+ export { type ComboAuthenticate, type ComboUser, KernelSessionCall, KernelSessionScope, SessionStore, type SponsoredSessionRoutes, type SponsoredSessionRoutesOptions, assertCallsInScope, createSponsoredSessionRoutes };
@@ -0,0 +1,15 @@
1
+ // Generated by scripts/guard-peers.mjs. Used only under the "node" export condition.
2
+ const peers = ["@privy-io/node","@zerodev/sdk","@zerodev/permissions","@zerodev/ecdsa-validator"];
3
+ for (const peer of peers) {
4
+ try {
5
+ import.meta.resolve?.(peer);
6
+ } catch (e) {
7
+ if (e && e.code === "ERR_MODULE_NOT_FOUND") {
8
+ const err = new Error("@pepu-chain/sdk/combo needs peer packages that are not installed: @privy-io/node @zerodev/sdk @zerodev/permissions @zerodev/ecdsa-validator. Install with: npm i @privy-io/node @zerodev/sdk @zerodev/permissions @zerodev/ecdsa-validator (or let create-pepu-app scaffold everything).");
9
+ err.code = "PEPU_MISSING_PEER";
10
+ throw err;
11
+ }
12
+ }
13
+ }
14
+ const mod = await import("./combo.js");
15
+ export const { createMemoryStore, isLive, resolveSessionMinutes, assertCallsInScope, createSponsoredSessionRoutes } = mod;