@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
@@ -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"]}