@pepu-chain/sdk 0.2.0 → 0.2.2

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 (110) hide show
  1. package/README.md +26 -2
  2. package/dist/aa/kernel.cjs +11 -9
  3. package/dist/aa/kernel.guard.js +15 -0
  4. package/dist/aa/kernel.js +5 -4
  5. package/dist/aa/react-direct.cjs +14 -12
  6. package/dist/aa/react-direct.cjs.map +1 -1
  7. package/dist/aa/react-direct.guard.js +15 -0
  8. package/dist/aa/react-direct.js +7 -6
  9. package/dist/aa/react-direct.js.map +1 -1
  10. package/dist/aa/react.cjs +7 -5
  11. package/dist/aa/react.cjs.map +1 -1
  12. package/dist/aa/react.d.cts +1 -1
  13. package/dist/aa/react.d.ts +1 -1
  14. package/dist/aa/react.guard.js +15 -0
  15. package/dist/aa/react.js +4 -3
  16. package/dist/aa/react.js.map +1 -1
  17. package/dist/aa.cjs +19 -18
  18. package/dist/aa.d.cts +1 -1
  19. package/dist/aa.d.ts +1 -1
  20. package/dist/aa.js +6 -5
  21. package/dist/chunk-4GEC7GUU.cjs +283 -0
  22. package/dist/chunk-4GEC7GUU.cjs.map +1 -0
  23. package/dist/{chunk-PHM3ZORG.cjs → chunk-4L4CHIXE.cjs} +9 -9
  24. package/dist/{chunk-PHM3ZORG.cjs.map → chunk-4L4CHIXE.cjs.map} +1 -1
  25. package/dist/{chunk-A5LP2UCS.cjs → chunk-65Y5UCQ7.cjs} +2 -276
  26. package/dist/chunk-65Y5UCQ7.cjs.map +1 -0
  27. package/dist/{chunk-MBA4CLA5.js → chunk-7PVR7QSE.js} +3 -3
  28. package/dist/{chunk-MBA4CLA5.js.map → chunk-7PVR7QSE.js.map} +1 -1
  29. package/dist/{chunk-7MNJF2OB.cjs → chunk-DNWWZWUW.cjs} +4 -4
  30. package/dist/{chunk-7MNJF2OB.cjs.map → chunk-DNWWZWUW.cjs.map} +1 -1
  31. package/dist/{chunk-D52PADVY.js → chunk-GFKIM7HT.js} +25 -2
  32. package/dist/chunk-GFKIM7HT.js.map +1 -0
  33. package/dist/{chunk-IY3ALPUJ.js → chunk-GIZNH65Q.js} +5 -273
  34. package/dist/chunk-GIZNH65Q.js.map +1 -0
  35. package/dist/{chunk-WANILJZQ.cjs → chunk-HTCX46RJ.cjs} +25 -2
  36. package/dist/chunk-HTCX46RJ.cjs.map +1 -0
  37. package/dist/{chunk-TIEAZYHF.cjs → chunk-K7JSQPZO.cjs} +8 -2
  38. package/dist/chunk-K7JSQPZO.cjs.map +1 -0
  39. package/dist/{chunk-FCXSP2YF.js → chunk-KJYNF5KH.js} +8 -3
  40. package/dist/chunk-KJYNF5KH.js.map +1 -0
  41. package/dist/{chunk-KVG3AYYR.js → chunk-NHPWXIA2.js} +4 -4
  42. package/dist/{chunk-KVG3AYYR.js.map → chunk-NHPWXIA2.js.map} +1 -1
  43. package/dist/{chunk-ZB6SVBK4.js → chunk-QIDMFFAQ.js} +4 -4
  44. package/dist/{chunk-ZB6SVBK4.js.map → chunk-QIDMFFAQ.js.map} +1 -1
  45. package/dist/{chunk-IB2FSPMJ.js → chunk-QZKUPCUD.js} +3 -3
  46. package/dist/{chunk-IB2FSPMJ.js.map → chunk-QZKUPCUD.js.map} +1 -1
  47. package/dist/{chunk-ET3P6TX6.cjs → chunk-RCMKPJZO.cjs} +4 -4
  48. package/dist/{chunk-ET3P6TX6.cjs.map → chunk-RCMKPJZO.cjs.map} +1 -1
  49. package/dist/chunk-RSPAN44L.js +276 -0
  50. package/dist/chunk-RSPAN44L.js.map +1 -0
  51. package/dist/{chunk-NVOPDXTA.cjs → chunk-UQH4ZAXD.cjs} +10 -10
  52. package/dist/{chunk-NVOPDXTA.cjs.map → chunk-UQH4ZAXD.cjs.map} +1 -1
  53. package/dist/{chunk-SLW7FRTL.cjs → chunk-VYMAZVIK.cjs} +52 -22
  54. package/dist/chunk-VYMAZVIK.cjs.map +1 -0
  55. package/dist/{chunk-KIIFL4VM.js → chunk-XR5ONV2Y.js} +42 -12
  56. package/dist/chunk-XR5ONV2Y.js.map +1 -0
  57. package/dist/combo/react.cjs +62 -13
  58. package/dist/combo/react.cjs.map +1 -1
  59. package/dist/combo/react.d.cts +14 -2
  60. package/dist/combo/react.d.ts +14 -2
  61. package/dist/combo/react.guard.js +15 -0
  62. package/dist/combo/react.js +58 -11
  63. package/dist/combo/react.js.map +1 -1
  64. package/dist/combo.cjs +45 -29
  65. package/dist/combo.cjs.map +1 -1
  66. package/dist/combo.d.cts +11 -0
  67. package/dist/combo.d.ts +11 -0
  68. package/dist/combo.guard.js +15 -0
  69. package/dist/combo.js +33 -18
  70. package/dist/combo.js.map +1 -1
  71. package/dist/index.cjs +28 -23
  72. package/dist/index.cjs.map +1 -1
  73. package/dist/index.d.cts +2 -2
  74. package/dist/index.d.ts +2 -2
  75. package/dist/index.js +6 -5
  76. package/dist/index.js.map +1 -1
  77. package/dist/paymaster.cjs +39 -38
  78. package/dist/paymaster.cjs.map +1 -1
  79. package/dist/paymaster.js +4 -3
  80. package/dist/paymaster.js.map +1 -1
  81. package/dist/privy/react.cjs +1 -0
  82. package/dist/privy/react.guard.js +15 -0
  83. package/dist/privy/server.cjs +1 -0
  84. package/dist/privy/server.guard.js +15 -0
  85. package/dist/privy/wagmi.guard.js +15 -0
  86. package/dist/react.cjs +6 -4
  87. package/dist/react.cjs.map +1 -1
  88. package/dist/react.d.cts +1 -1
  89. package/dist/react.d.ts +1 -1
  90. package/dist/react.guard.js +15 -0
  91. package/dist/react.js +4 -3
  92. package/dist/react.js.map +1 -1
  93. package/dist/session/kernel.cjs +19 -17
  94. package/dist/session/kernel.guard.js +15 -0
  95. package/dist/session/kernel.js +6 -5
  96. package/dist/session/react.cjs +1 -0
  97. package/dist/session/react.guard.js +15 -0
  98. package/dist/session/server.cjs +1 -0
  99. package/dist/session/server.guard.js +15 -0
  100. package/dist/{status-DwkkOrGQ.d.ts → status-Dx9zAFo9.d.ts} +42 -10
  101. package/dist/{status-CmOsyPmO.d.cts → status-wgTM26V7.d.cts} +42 -10
  102. package/package.json +38 -2
  103. package/dist/chunk-A5LP2UCS.cjs.map +0 -1
  104. package/dist/chunk-D52PADVY.js.map +0 -1
  105. package/dist/chunk-FCXSP2YF.js.map +0 -1
  106. package/dist/chunk-IY3ALPUJ.js.map +0 -1
  107. package/dist/chunk-KIIFL4VM.js.map +0 -1
  108. package/dist/chunk-SLW7FRTL.cjs.map +0 -1
  109. package/dist/chunk-TIEAZYHF.cjs.map +0 -1
  110. package/dist/chunk-WANILJZQ.cjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/combo/react.ts"],"names":[],"mappings":"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","file":"react.js","sourcesContent":["import { usePrivy } from \"@privy-io/react-auth\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { createWalletClient, custom } from \"viem\";\nimport type { Address, PublicClient } from \"viem\";\nimport { pepuMainnet } from \"../chains.js\";\nimport { getPublicClient } from \"../client.js\";\nimport { PepuAuthError, toPepuError } from \"../errors.js\";\nimport type { PepuError } from \"../errors.js\";\nimport { usePepuAuthFetch, useEmbeddedWallet } from \"../privy/react.js\";\nimport { errorFromResponse } from \"../session/react.js\";\nimport type { AuthFetch } from \"../session/react.js\";\nimport { approveKernelSession, buildKernelSessionPolicies, getKernelAddress } from \"../session/kernel.js\";\nimport type { KernelOwner } from \"../session/kernel.js\";\nimport { describeKernelSessionScope } from \"../session/scope.js\";\nimport type { KernelSessionCall, KernelSessionScope } from \"../session/scope.js\";\n\nexport type { SponsoredActResult } from \"./types.js\";\n\n/**\n * `@pepu-chain/sdk/combo/react` (browser): hooks for the combined flow. Google\n * sign-in (Privy), ONE owner signature for an on-chain session, then actions\n * with no popup and no gas. Pairs with `createSponsoredSessionRoutes` from\n * `@pepu-chain/sdk/combo`.\n *\n * Extracted from templates/sponsored-session-app/components/session-flow.tsx.\n * The browser's only signing job is the grant; everything after it is a request\n * to your own server, authenticated by the Privy access token.\n *\n * Needs `react`, `@privy-io/react-auth` and the `@zerodev/*` peers.\n */\n\n/** The routes {@link useSponsoredSession} calls. */\nexport interface SponsoredSessionEndpoints {\n prepare: string;\n activate: string;\n status: string;\n act: string;\n revoke: string;\n}\n\n/** Defaults match the `app/api/session/<name>/route.ts` convention. */\nexport const DEFAULT_SESSION_ENDPOINTS: SponsoredSessionEndpoints = {\n prepare: \"/api/session/prepare\",\n activate: \"/api/session/activate\",\n status: \"/api/session/status\",\n act: \"/api/session/act\",\n revoke: \"/api/session/revoke\",\n};\n\n/** Where the session flow is, for rendering. */\nexport type SponsoredSessionPhase =\n | \"signed-out\"\n | \"provisioning\"\n | \"ready\"\n | \"granting\"\n | \"active\"\n | \"expired\"\n | \"error\";\n\n/**\n * Derive the phase from plain inputs. Pure.\n *\n * - not signed in: `signed-out`; signed in without an embedded wallet: `provisioning`\n * - a grant in flight: `granting`\n * - an expiry that has passed: `expired`; one still ahead: `active`\n * - an error with nothing active: `error`; otherwise `ready`\n *\n * @example\n * deriveSessionPhase({ authenticated: true, hasWallet: true, validUntil: 100, nowSeconds: 200 }); // \"expired\"\n */\nexport function deriveSessionPhase(p: {\n authenticated: boolean;\n hasWallet: boolean;\n /** The last expiry the server reported for an active session, if any. */\n validUntil?: number | undefined;\n nowSeconds: number;\n granting?: boolean;\n hasError?: boolean;\n}): SponsoredSessionPhase {\n if (!p.authenticated) return \"signed-out\";\n if (!p.hasWallet) return \"provisioning\";\n if (p.granting) return \"granting\";\n if (p.validUntil !== undefined) return p.nowSeconds < p.validUntil ? \"active\" : \"expired\";\n return p.hasError ? \"error\" : \"ready\";\n}\n\n/** What the server's `prepare` route returns. */\nexport interface PreparedSession {\n ownerAddress: Address;\n kernelAddress: Address;\n sessionKeyAddress: Address;\n validUntil: number;\n minutes: number;\n scope: KernelSessionScope;\n}\n\n/** What the server's `status` route returns. */\nexport type SponsoredSessionStatus =\n | { active: false }\n | {\n active: true;\n validUntil: number;\n kernelAddress: Address;\n ownerAddress: Address;\n sessionKeyAddress: Address;\n actions: number;\n };\n\nasync function postJson<T>(authFetch: AuthFetch, url: string, body?: unknown): Promise<T> {\n const res = await authFetch(url, {\n method: \"POST\",\n ...(body === undefined\n ? {}\n : { headers: { \"content-type\": \"application/json\" }, body: JSON.stringify(body) }),\n });\n if (!res.ok) throw await errorFromResponse(res);\n return (await res.json()) as T;\n}\n\n/**\n * The grant, outside React: ask the server to `prepare` a session key, have\n * `owner` sign the ONE EIP-712 approval (no gas), then `activate`. Rebuilds\n * the policies from `scope` and the server's expiry; the server checks the\n * resulting permission id matches what it issued, so a different scope is\n * rejected with `SESSION_APPROVAL_MISMATCH`.\n *\n * @example\n * const prepared = await grantKernelSession({ authFetch, publicClient, owner: walletClient, scope });\n */\nexport async function grantKernelSession(p: {\n authFetch: AuthFetch;\n publicClient: PublicClient;\n owner: KernelOwner;\n scope: { calls: readonly KernelSessionCall[] };\n endpoints?: Partial<SponsoredSessionEndpoints>;\n}): Promise<PreparedSession> {\n const ep = { ...DEFAULT_SESSION_ENDPOINTS, ...p.endpoints };\n const prepared = await postJson<PreparedSession>(p.authFetch, ep.prepare);\n const { approval } = await approveKernelSession({\n publicClient: p.publicClient,\n owner: p.owner,\n sessionKeyAddress: prepared.sessionKeyAddress,\n policies: buildKernelSessionPolicies({ calls: p.scope.calls, validUntil: prepared.validUntil }),\n });\n await postJson<{ active: true; validUntil: number }>(p.authFetch, ep.activate, { approval });\n return prepared;\n}\n\n/** Options for {@link useSponsoredSession}. */\nexport interface UseSponsoredSessionOptions {\n /** The same scope the server uses. The browser rebuilds the policies from it. */\n scope: { calls: readonly KernelSessionCall[] };\n endpoints?: Partial<SponsoredSessionEndpoints>;\n /** Default `usePepuAuthFetch()` (Privy bearer token). */\n authFetch?: AuthFetch;\n /** Default: a viem client on the PEPU RPC. */\n publicClient?: PublicClient;\n /** Re-poll the status route this often. Default 0 (only on mount and after actions). */\n pollMs?: number;\n}\n\nlet sharedClient: PublicClient | undefined;\nfunction defaultPublicClient(): PublicClient {\n sharedClient ??= getPublicClient(pepuMainnet) as unknown as PublicClient;\n return sharedClient;\n}\n\n/**\n * The whole session flow for a component.\n *\n * - `grant()`: prepare, ONE owner signature through the Privy embedded wallet\n * (no gas), activate.\n * - `act(input)`: POST the act route. No popup, no gas.\n * - `revoke()`: deletes the server-side key right away. The on-chain grant\n * lapses at its expiry; only the deleted key could ever use it.\n * - `smartAccount` is the Kernel address that sends and holds assets (a read,\n * known before any session exists); `owner` is the embedded wallet that signs.\n *\n * @example\n * const { phase, grant, act, revoke, smartAccount, expiresAt, error } = useSponsoredSession<{}, { transactionHash: string }>({\n * scope: { calls: [{ target: tapScore, abi: tapScoreAbi, functionName: \"tap\" }] },\n * });\n * if (phase === \"ready\") return <button onClick={grant}>Start session</button>;\n */\nexport function useSponsoredSession<I = undefined, O = unknown>(\n o: UseSponsoredSessionOptions,\n): {\n phase: SponsoredSessionPhase;\n /**\n * True while a signed-in user with a wallet has not yet had the first status\n * response (or failure). While true, `phase` is `ready` only because nothing\n * is known yet: render a spinner instead of the \"start a session\" card.\n */\n statusLoading: boolean;\n owner?: Address;\n smartAccount?: Address;\n scope?: KernelSessionScope;\n expiresAt?: number;\n /** Successful actions in this session, as counted by the server. */\n actions?: number;\n grant(): Promise<void>;\n act(input?: I): Promise<O>;\n revoke(): Promise<void>;\n refetch(): void;\n error?: PepuError;\n} {\n const { authenticated, ready: privyReady } = usePrivy();\n const { wallet, address: owner } = useEmbeddedWallet();\n const pepuAuthFetch = usePepuAuthFetch();\n const customFetch = o.authFetch;\n const authFetch = useCallback<AuthFetch>(\n (url, init) => (customFetch ? customFetch(url, init) : pepuAuthFetch(url, init)),\n [customFetch, pepuAuthFetch],\n );\n const endpointsRef = useRef({ ...DEFAULT_SESSION_ENDPOINTS, ...o.endpoints });\n endpointsRef.current = { ...DEFAULT_SESSION_ENDPOINTS, ...o.endpoints };\n const scopeRef = useRef(o.scope);\n scopeRef.current = o.scope;\n const publicClient = o.publicClient ?? defaultPublicClient();\n\n const [smartAccount, setSmartAccount] = useState<Address | undefined>();\n const [status, setStatus] = useState<SponsoredSessionStatus | undefined>();\n const [statusChecked, setStatusChecked] = useState(false);\n const [prepared, setPrepared] = useState<PreparedSession | undefined>();\n const [granting, setGranting] = useState(false);\n const [error, setError] = useState<PepuError | undefined>();\n const [now, setNow] = useState(() => Math.floor(Date.now() / 1000));\n const [tick, setTick] = useState(0);\n const refetch = useCallback(() => setTick((t) => t + 1), []);\n // The last expiry seen for an active session. The server reports\n // `{ active: false }` once it passes, so this is what makes `expired`.\n const [lastValidUntil, setLastValidUntil] = useState<number | undefined>();\n const grantInFlight = useRef(false);\n\n // The Kernel address depends only on the owner: known before any session.\n useEffect(() => {\n if (!owner) {\n setSmartAccount(undefined);\n return;\n }\n let cancelled = false;\n getKernelAddress(publicClient, owner)\n .then((a) => {\n if (!cancelled) setSmartAccount(a);\n })\n .catch((e: unknown) => {\n if (!cancelled) setError(toPepuError(e, { op: \"derive smart account\" }));\n });\n return () => {\n cancelled = true;\n };\n }, [owner, publicClient]);\n\n useEffect(() => {\n if (!authenticated || !owner) return;\n let cancelled = false;\n void (async () => {\n try {\n const res = await authFetch(endpointsRef.current.status);\n if (!res.ok) throw await errorFromResponse(res);\n const body = (await res.json()) as SponsoredSessionStatus;\n if (cancelled) return;\n setStatus(body);\n if (body.active) setLastValidUntil(body.validUntil);\n } catch (e) {\n if (!cancelled) setError(toPepuError(e, { op: \"session status\" }));\n } finally {\n if (!cancelled) setStatusChecked(true);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [authenticated, owner, authFetch, tick]);\n\n useEffect(() => {\n const id = setInterval(() => setNow(Math.floor(Date.now() / 1000)), 1000);\n return () => clearInterval(id);\n }, []);\n\n useEffect(() => {\n if (!o.pollMs || o.pollMs <= 0) return;\n const id = setInterval(refetch, o.pollMs);\n return () => clearInterval(id);\n }, [o.pollMs, refetch]);\n\n const grant = useCallback(async (): Promise<void> => {\n if (grantInFlight.current) return;\n grantInFlight.current = true;\n setGranting(true);\n setError(undefined);\n try {\n if (!wallet || !owner) {\n throw new PepuAuthError(\"WALLET_NOT_PROVISIONED\", \"No embedded wallet to sign the session grant.\");\n }\n const provider = await wallet.getEthereumProvider();\n const walletClient = createWalletClient({\n account: owner,\n chain: pepuMainnet,\n transport: custom(provider),\n });\n const result = await grantKernelSession({\n authFetch,\n publicClient,\n owner: walletClient,\n scope: scopeRef.current,\n endpoints: endpointsRef.current,\n });\n setPrepared(result);\n setLastValidUntil(result.validUntil);\n setStatus({\n active: true,\n validUntil: result.validUntil,\n kernelAddress: result.kernelAddress,\n ownerAddress: result.ownerAddress,\n sessionKeyAddress: result.sessionKeyAddress,\n actions: 0,\n });\n } catch (e) {\n setError(toPepuError(e, { op: \"session grant\" }));\n } finally {\n grantInFlight.current = false;\n setGranting(false);\n }\n }, [wallet, owner, authFetch, publicClient]);\n\n const act = useCallback(\n async (input?: I): Promise<O> => {\n try {\n const out = await postJson<O>(authFetch, endpointsRef.current.act, input === undefined ? {} : input);\n setError(undefined);\n refetch();\n return out;\n } catch (e) {\n const err = toPepuError(e, { op: \"session act\" });\n setError(err);\n // Only a 409 (SESSION_NONE) means the session is gone; any other failure is a failed action.\n if (err.code === \"SESSION_NONE\") {\n setStatus({ active: false });\n setLastValidUntil(undefined);\n }\n throw err;\n }\n },\n [authFetch, refetch],\n );\n\n const revoke = useCallback(async (): Promise<void> => {\n try {\n await postJson<{ active: false }>(authFetch, endpointsRef.current.revoke);\n setStatus({ active: false });\n setLastValidUntil(undefined);\n setPrepared(undefined);\n setError(undefined);\n } catch (e) {\n const err = toPepuError(e, { op: \"session revoke\" });\n setError(err);\n throw err;\n }\n }, [authFetch]);\n\n // `ready` must not flip to `signed-out` while Privy hydrates.\n const phase = deriveSessionPhase({\n authenticated: privyReady ? authenticated : false,\n hasWallet: owner !== undefined,\n validUntil: status?.active ? status.validUntil : lastValidUntil,\n nowSeconds: now,\n granting,\n hasError: error !== undefined,\n });\n const expiresAt = status?.active ? status.validUntil : lastValidUntil;\n const scope =\n prepared?.scope ??\n (expiresAt !== undefined\n ? describeKernelSessionScope({ calls: o.scope.calls, validUntil: expiresAt })\n : undefined);\n\n const statusLoading = privyReady && authenticated && owner !== undefined && !statusChecked && status === undefined;\n\n return {\n phase,\n statusLoading,\n ...(owner ? { owner } : {}),\n ...(smartAccount ? { smartAccount } : {}),\n ...(scope ? { scope } : {}),\n ...(expiresAt !== undefined ? { expiresAt } : {}),\n ...(status?.active ? { actions: status.actions } : {}),\n grant,\n act,\n revoke,\n refetch,\n ...(error ? { error } : {}),\n };\n}\n"]}
1
+ {"version":3,"sources":["../../src/combo/react.ts"],"names":[],"mappings":"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","file":"react.js","sourcesContent":["import { usePrivy } from \"@privy-io/react-auth\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { createWalletClient, custom } from \"viem\";\nimport type { Address, PublicClient } from \"viem\";\nimport { pepuMainnet } from \"../chains.js\";\nimport { getPublicClient } from \"../client.js\";\nimport { PepuAuthError, toPepuError } from \"../errors.js\";\nimport type { PepuError } from \"../errors.js\";\nimport { usePepuAuthFetch, useEmbeddedWallet } from \"../privy/react.js\";\nimport { errorFromResponse } from \"../session/react.js\";\nimport type { AuthFetch } from \"../session/react.js\";\nimport { approveKernelSession, buildKernelSessionPolicies, getKernelAddress } from \"../session/kernel.js\";\nimport type { KernelOwner } from \"../session/kernel.js\";\nimport { describeKernelSessionScope } from \"../session/scope.js\";\nimport type { KernelSessionCall, KernelSessionScope } from \"../session/scope.js\";\n\nexport type { SponsoredActResult } from \"./types.js\";\n\n/**\n * `@pepu-chain/sdk/combo/react` (browser): hooks for the combined flow. Google\n * sign-in (Privy), ONE owner signature for an on-chain session, then actions\n * with no popup and no gas. Pairs with `createSponsoredSessionRoutes` from\n * `@pepu-chain/sdk/combo`.\n *\n * Extracted from templates/sponsored-session-app/components/session-flow.tsx.\n * The browser's only signing job is the grant; everything after it is a request\n * to your own server, authenticated by the Privy access token.\n *\n * Needs `react`, `@privy-io/react-auth` and the `@zerodev/*` peers.\n */\n\n/** The routes {@link useSponsoredSession} calls. */\nexport interface SponsoredSessionEndpoints {\n prepare: string;\n activate: string;\n status: string;\n act: string;\n revoke: string;\n}\n\n/** Defaults match the `app/api/session/<name>/route.ts` convention. */\nexport const DEFAULT_SESSION_ENDPOINTS: SponsoredSessionEndpoints = {\n prepare: \"/api/session/prepare\",\n activate: \"/api/session/activate\",\n status: \"/api/session/status\",\n act: \"/api/session/act\",\n revoke: \"/api/session/revoke\",\n};\n\n/** Where the session flow is, for rendering. */\nexport type SponsoredSessionPhase =\n | \"signed-out\"\n | \"provisioning\"\n | \"ready\"\n | \"granting\"\n | \"active\"\n | \"expired\"\n | \"error\";\n\n/**\n * Derive the phase from plain inputs. Pure.\n *\n * - not signed in: `signed-out`; signed in without an embedded wallet: `provisioning`\n * - a grant in flight: `granting`\n * - an expiry that has passed: `expired`; one still ahead: `active`\n * - an error with nothing active: `error`; otherwise `ready`\n *\n * @example\n * deriveSessionPhase({ authenticated: true, hasWallet: true, validUntil: 100, nowSeconds: 200 }); // \"expired\"\n */\nexport function deriveSessionPhase(p: {\n authenticated: boolean;\n hasWallet: boolean;\n /** The last expiry the server reported for an active session, if any. */\n validUntil?: number | undefined;\n nowSeconds: number;\n granting?: boolean;\n hasError?: boolean;\n}): SponsoredSessionPhase {\n if (!p.authenticated) return \"signed-out\";\n if (!p.hasWallet) return \"provisioning\";\n if (p.granting) return \"granting\";\n if (p.validUntil !== undefined) return p.nowSeconds < p.validUntil ? \"active\" : \"expired\";\n return p.hasError ? \"error\" : \"ready\";\n}\n\n/** What the server's `prepare` route returns. */\nexport interface PreparedSession {\n ownerAddress: Address;\n kernelAddress: Address;\n sessionKeyAddress: Address;\n validUntil: number;\n minutes: number;\n scope: KernelSessionScope;\n}\n\n/** What the server's `status` route returns. */\nexport type SponsoredSessionStatus =\n /** `provisioning`: signed in, but the server cannot see the new embedded wallet yet. Transient: retry. */\n | { active: false; provisioning?: true }\n | {\n active: true;\n validUntil: number;\n kernelAddress: Address;\n ownerAddress: Address;\n sessionKeyAddress: Address;\n actions: number;\n };\n\n/** Waits between retries while the server cannot see a just-created embedded wallet (total about 6.5 s). */\nexport const PROVISIONING_RETRY_DELAYS_MS: readonly number[] = [500, 1000, 2000, 3000];\n\nconst sleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\nfunction isProvisioning(e: unknown): boolean {\n return (e as { code?: unknown } | null)?.code === \"WALLET_NOT_PROVISIONED\";\n}\n\n/**\n * Run `fn`, retrying with backoff while it fails with `WALLET_NOT_PROVISIONED`. A new user's embedded wallet exists in\n * the browser a moment before Privy's server lists it; that gap is not an error the user should ever see.\n */\nasync function whileProvisioning<T>(fn: () => Promise<T>, delays: readonly number[]): Promise<T> {\n for (let i = 0; ; i++) {\n try {\n return await fn();\n } catch (e) {\n const delay = delays[i];\n if (!isProvisioning(e) || delay === undefined) throw e;\n await sleep(delay);\n }\n }\n}\n\nasync function postJson<T>(authFetch: AuthFetch, url: string, body?: unknown): Promise<T> {\n const res = await authFetch(url, {\n method: \"POST\",\n ...(body === undefined\n ? {}\n : { headers: { \"content-type\": \"application/json\" }, body: JSON.stringify(body) }),\n });\n if (!res.ok) throw await errorFromResponse(res);\n return (await res.json()) as T;\n}\n\n/**\n * The grant, outside React: ask the server to `prepare` a session key, have\n * `owner` sign the ONE EIP-712 approval (no gas), then `activate`. Rebuilds\n * the policies from `scope` and the server's expiry; the server checks the\n * resulting permission id matches what it issued, so a different scope is\n * rejected with `SESSION_APPROVAL_MISMATCH`.\n *\n * @example\n * const prepared = await grantKernelSession({ authFetch, publicClient, owner: walletClient, scope });\n */\nexport async function grantKernelSession(p: {\n authFetch: AuthFetch;\n publicClient: PublicClient;\n owner: KernelOwner;\n scope: { calls: readonly KernelSessionCall[] };\n endpoints?: Partial<SponsoredSessionEndpoints>;\n /** Waits between retries of `prepare` while the server cannot see a new wallet yet. Default {@link PROVISIONING_RETRY_DELAYS_MS}. */\n provisioningRetryDelaysMs?: readonly number[];\n}): Promise<PreparedSession> {\n const ep = { ...DEFAULT_SESSION_ENDPOINTS, ...p.endpoints };\n const prepared = await whileProvisioning(\n () => postJson<PreparedSession>(p.authFetch, ep.prepare),\n p.provisioningRetryDelaysMs ?? PROVISIONING_RETRY_DELAYS_MS,\n );\n const { approval } = await approveKernelSession({\n publicClient: p.publicClient,\n owner: p.owner,\n sessionKeyAddress: prepared.sessionKeyAddress,\n policies: buildKernelSessionPolicies({ calls: p.scope.calls, validUntil: prepared.validUntil }),\n });\n await postJson<{ active: true; validUntil: number }>(p.authFetch, ep.activate, { approval });\n return prepared;\n}\n\n/** Options for {@link useSponsoredSession}. */\nexport interface UseSponsoredSessionOptions {\n /** The same scope the server uses. The browser rebuilds the policies from it. */\n scope: { calls: readonly KernelSessionCall[] };\n endpoints?: Partial<SponsoredSessionEndpoints>;\n /** Default `usePepuAuthFetch()` (Privy bearer token). */\n authFetch?: AuthFetch;\n /** Default: a viem client on the PEPU RPC. */\n publicClient?: PublicClient;\n /** Re-poll the status route this often. Default 0 (only on mount and after actions). */\n pollMs?: number;\n /**\n * Waits between status re-checks while the server cannot see a just-created wallet. During them `statusLoading`\n * stays true and no error is shown. Default {@link PROVISIONING_RETRY_DELAYS_MS} extended to a 5 s tail (about 30 s).\n */\n provisioningRetryDelaysMs?: readonly number[];\n}\n\n/** Status re-checks while a new wallet is not visible to the server yet: 0.5, 1, 2, 3 s, then 5 s x 5 (about 30 s). */\nconst STATUS_PROVISIONING_DELAYS_MS: readonly number[] = [...PROVISIONING_RETRY_DELAYS_MS, 5000, 5000, 5000, 5000, 5000];\n\nlet sharedClient: PublicClient | undefined;\nfunction defaultPublicClient(): PublicClient {\n sharedClient ??= getPublicClient(pepuMainnet) as unknown as PublicClient;\n return sharedClient;\n}\n\n/**\n * The whole session flow for a component.\n *\n * - `grant()`: prepare, ONE owner signature through the Privy embedded wallet\n * (no gas), activate.\n * - `act(input)`: POST the act route. No popup, no gas.\n * - `revoke()`: deletes the server-side key right away. The on-chain grant\n * lapses at its expiry; only the deleted key could ever use it.\n * - `smartAccount` is the Kernel address that sends and holds assets (a read,\n * known before any session exists); `owner` is the embedded wallet that signs.\n *\n * @example\n * const { phase, grant, act, revoke, smartAccount, expiresAt, error } = useSponsoredSession<{}, { transactionHash: string }>({\n * scope: { calls: [{ target: tapScore, abi: tapScoreAbi, functionName: \"tap\" }] },\n * });\n * if (phase === \"ready\") return <button onClick={grant}>Start session</button>;\n */\nexport function useSponsoredSession<I = undefined, O = unknown>(\n o: UseSponsoredSessionOptions,\n): {\n phase: SponsoredSessionPhase;\n /**\n * True while a signed-in user with a wallet has not yet had the first status\n * response (or failure). While true, `phase` is `ready` only because nothing\n * is known yet: render a spinner instead of the \"start a session\" card.\n */\n statusLoading: boolean;\n owner?: Address;\n smartAccount?: Address;\n scope?: KernelSessionScope;\n expiresAt?: number;\n /** Successful actions in this session, as counted by the server. */\n actions?: number;\n grant(): Promise<void>;\n act(input?: I): Promise<O>;\n revoke(): Promise<void>;\n refetch(): void;\n error?: PepuError;\n} {\n const { authenticated, ready: privyReady } = usePrivy();\n const { wallet, address: owner } = useEmbeddedWallet();\n const pepuAuthFetch = usePepuAuthFetch();\n const customFetch = o.authFetch;\n const authFetch = useCallback<AuthFetch>(\n (url, init) => (customFetch ? customFetch(url, init) : pepuAuthFetch(url, init)),\n [customFetch, pepuAuthFetch],\n );\n const endpointsRef = useRef({ ...DEFAULT_SESSION_ENDPOINTS, ...o.endpoints });\n endpointsRef.current = { ...DEFAULT_SESSION_ENDPOINTS, ...o.endpoints };\n const scopeRef = useRef(o.scope);\n scopeRef.current = o.scope;\n const publicClient = o.publicClient ?? defaultPublicClient();\n\n const [smartAccount, setSmartAccount] = useState<Address | undefined>();\n const [status, setStatus] = useState<SponsoredSessionStatus | undefined>();\n const [statusChecked, setStatusChecked] = useState(false);\n const [prepared, setPrepared] = useState<PreparedSession | undefined>();\n const [granting, setGranting] = useState(false);\n const [error, setError] = useState<PepuError | undefined>();\n const [now, setNow] = useState(() => Math.floor(Date.now() / 1000));\n const [tick, setTick] = useState(0);\n const refetch = useCallback(() => setTick((t) => t + 1), []);\n // The last expiry seen for an active session. The server reports\n // `{ active: false }` once it passes, so this is what makes `expired`.\n const [lastValidUntil, setLastValidUntil] = useState<number | undefined>();\n const grantInFlight = useRef(false);\n const provisioningDelays = o.provisioningRetryDelaysMs ?? STATUS_PROVISIONING_DELAYS_MS;\n const delaysRef = useRef(provisioningDelays);\n delaysRef.current = provisioningDelays;\n const provisioningAttempts = useRef(0);\n\n // The Kernel address depends only on the owner: known before any session.\n useEffect(() => {\n if (!owner) {\n setSmartAccount(undefined);\n return;\n }\n let cancelled = false;\n getKernelAddress(publicClient, owner)\n .then((a) => {\n if (!cancelled) setSmartAccount(a);\n })\n .catch((e: unknown) => {\n if (!cancelled) setError(toPepuError(e, { op: \"derive smart account\" }));\n });\n return () => {\n cancelled = true;\n };\n }, [owner, publicClient]);\n\n useEffect(() => {\n if (!authenticated || !owner) return;\n let cancelled = false;\n let timer: ReturnType<typeof setTimeout> | undefined;\n // The server cannot see the new embedded wallet yet: stay in the loading state and ask again, quietly.\n const retryLater = (): boolean => {\n const delay = delaysRef.current[provisioningAttempts.current];\n if (delay === undefined) return false;\n provisioningAttempts.current += 1;\n timer = setTimeout(() => {\n if (!cancelled) refetch();\n }, delay);\n return true;\n };\n void (async () => {\n let waiting = false;\n try {\n const res = await authFetch(endpointsRef.current.status);\n if (!res.ok) throw await errorFromResponse(res);\n const body = (await res.json()) as SponsoredSessionStatus;\n if (cancelled) return;\n if (!body.active && body.provisioning) {\n waiting = retryLater();\n if (!waiting) setStatus({ active: false });\n return;\n }\n provisioningAttempts.current = 0;\n setStatus(body);\n setError(undefined);\n if (body.active) setLastValidUntil(body.validUntil);\n } catch (e) {\n if (cancelled) return;\n if (isProvisioning(e) && (waiting = retryLater())) return;\n setError(toPepuError(e, { op: \"session status\" }));\n } finally {\n if (!cancelled && !waiting) setStatusChecked(true);\n }\n })();\n return () => {\n cancelled = true;\n if (timer) clearTimeout(timer);\n };\n }, [authenticated, owner, authFetch, tick, refetch]);\n\n useEffect(() => {\n const id = setInterval(() => setNow(Math.floor(Date.now() / 1000)), 1000);\n return () => clearInterval(id);\n }, []);\n\n useEffect(() => {\n if (!o.pollMs || o.pollMs <= 0) return;\n const id = setInterval(refetch, o.pollMs);\n return () => clearInterval(id);\n }, [o.pollMs, refetch]);\n\n const grant = useCallback(async (): Promise<void> => {\n if (grantInFlight.current) return;\n grantInFlight.current = true;\n setGranting(true);\n setError(undefined);\n try {\n if (!wallet || !owner) {\n throw new PepuAuthError(\"WALLET_NOT_PROVISIONED\", \"No embedded wallet to sign the session grant.\");\n }\n const provider = await wallet.getEthereumProvider();\n const walletClient = createWalletClient({\n account: owner,\n chain: pepuMainnet,\n transport: custom(provider),\n });\n const result = await grantKernelSession({\n authFetch,\n publicClient,\n owner: walletClient,\n scope: scopeRef.current,\n endpoints: endpointsRef.current,\n provisioningRetryDelaysMs: delaysRef.current,\n });\n setPrepared(result);\n setLastValidUntil(result.validUntil);\n setStatus({\n active: true,\n validUntil: result.validUntil,\n kernelAddress: result.kernelAddress,\n ownerAddress: result.ownerAddress,\n sessionKeyAddress: result.sessionKeyAddress,\n actions: 0,\n });\n } catch (e) {\n setError(toPepuError(e, { op: \"session grant\" }));\n } finally {\n grantInFlight.current = false;\n setGranting(false);\n }\n }, [wallet, owner, authFetch, publicClient]);\n\n const act = useCallback(\n async (input?: I): Promise<O> => {\n try {\n const out = await postJson<O>(authFetch, endpointsRef.current.act, input === undefined ? {} : input);\n setError(undefined);\n refetch();\n return out;\n } catch (e) {\n const err = toPepuError(e, { op: \"session act\" });\n setError(err);\n // Only a 409 (SESSION_NONE) means the session is gone; any other failure is a failed action.\n if (err.code === \"SESSION_NONE\") {\n setStatus({ active: false });\n setLastValidUntil(undefined);\n }\n throw err;\n }\n },\n [authFetch, refetch],\n );\n\n const revoke = useCallback(async (): Promise<void> => {\n try {\n await postJson<{ active: false }>(authFetch, endpointsRef.current.revoke);\n setStatus({ active: false });\n setLastValidUntil(undefined);\n setPrepared(undefined);\n setError(undefined);\n } catch (e) {\n const err = toPepuError(e, { op: \"session revoke\" });\n setError(err);\n throw err;\n }\n }, [authFetch]);\n\n // `ready` must not flip to `signed-out` while Privy hydrates.\n const phase = deriveSessionPhase({\n authenticated: privyReady ? authenticated : false,\n hasWallet: owner !== undefined,\n validUntil: status?.active ? status.validUntil : lastValidUntil,\n nowSeconds: now,\n granting,\n hasError: error !== undefined,\n });\n const expiresAt = status?.active ? status.validUntil : lastValidUntil;\n const scope =\n prepared?.scope ??\n (expiresAt !== undefined\n ? describeKernelSessionScope({ calls: o.scope.calls, validUntil: expiresAt })\n : undefined);\n\n const statusLoading = privyReady && authenticated && owner !== undefined && !statusChecked && status === undefined;\n\n return {\n phase,\n statusLoading,\n ...(owner ? { owner } : {}),\n ...(smartAccount ? { smartAccount } : {}),\n ...(scope ? { scope } : {}),\n ...(expiresAt !== undefined ? { expiresAt } : {}),\n ...(status?.active ? { actions: status.actions } : {}),\n grant,\n act,\n revoke,\n refetch,\n ...(error ? { error } : {}),\n };\n}\n"]}
package/dist/combo.cjs CHANGED
@@ -1,13 +1,15 @@
1
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}}}})();
2
3
 
3
- var chunkPHM3ZORG_cjs = require('./chunk-PHM3ZORG.cjs');
4
- var chunkNVOPDXTA_cjs = require('./chunk-NVOPDXTA.cjs');
5
- require('./chunk-7MNJF2OB.cjs');
4
+ var chunk4L4CHIXE_cjs = require('./chunk-4L4CHIXE.cjs');
5
+ var chunkUQH4ZAXD_cjs = require('./chunk-UQH4ZAXD.cjs');
6
+ require('./chunk-DNWWZWUW.cjs');
6
7
  var chunkAJS4UFQX_cjs = require('./chunk-AJS4UFQX.cjs');
7
- require('./chunk-A5LP2UCS.cjs');
8
- var chunkET3P6TX6_cjs = require('./chunk-ET3P6TX6.cjs');
9
- require('./chunk-WANILJZQ.cjs');
10
- require('./chunk-TIEAZYHF.cjs');
8
+ require('./chunk-4GEC7GUU.cjs');
9
+ var chunkRCMKPJZO_cjs = require('./chunk-RCMKPJZO.cjs');
10
+ require('./chunk-HTCX46RJ.cjs');
11
+ require('./chunk-K7JSQPZO.cjs');
12
+ require('./chunk-65Y5UCQ7.cjs');
11
13
  var chunkJ3O2ZGG3_cjs = require('./chunk-J3O2ZGG3.cjs');
12
14
  require('./chunk-4GINFJO6.cjs');
13
15
  var chunkVF3D6KLQ_cjs = require('./chunk-VF3D6KLQ.cjs');
@@ -40,6 +42,7 @@ async function guard(op, fn) {
40
42
  function bearerToken(request) {
41
43
  return (request.headers.get("authorization") ?? "").replace(/^Bearer\s+/i, "").trim();
42
44
  }
45
+ var PROVISIONING = /* @__PURE__ */ Symbol("wallet-provisioning");
43
46
  var nowSeconds = () => Math.floor(Date.now() / 1e3);
44
47
  function defaultPublicClient() {
45
48
  return viem.createPublicClient({ chain: chunkDPCZJLB3_cjs.pepuMainnet, transport: viem.http(chunkVF3D6KLQ_cjs.resolvePepuEndpoints().rpcUrl) });
@@ -62,26 +65,38 @@ function createSponsoredSessionRoutes(o) {
62
65
  revoke: { POST: unset }
63
66
  };
64
67
  }
65
- chunkPHM3ZORG_cjs.buildKernelSessionPolicies({ calls: o.scope.calls, validUntil: 1 });
68
+ chunk4L4CHIXE_cjs.buildKernelSessionPolicies({ calls: o.scope.calls, validUntil: 1 });
66
69
  let publicClient = o.publicClient;
67
70
  const client = () => publicClient ??= defaultPublicClient();
68
- const authenticate = async (request) => {
71
+ const wait = { attempts: o.provisioningWait?.attempts ?? 3, delayMs: o.provisioningWait?.delayMs ?? 400 };
72
+ const authenticateOrProvisioning = async (request) => {
69
73
  if (o.authenticate) {
70
74
  const user = await o.authenticate(request);
71
75
  if (!user) throw new chunkYQL7NISX_cjs.PepuAuthError("AUTH_INVALID_TOKEN", "Missing or invalid Privy access token.");
72
76
  return user;
73
77
  }
74
- const auth = await chunk45KSZH26_cjs.requireUser(request, { privy: o.privy ?? chunk45KSZH26_cjs.createPrivyServer() });
75
- if (!auth.ok) return auth.response;
76
- if (!auth.user.address) {
77
- throw new chunkYQL7NISX_cjs.PepuAuthError("WALLET_NOT_PROVISIONED", "No embedded wallet yet. Create it first (ensure-wallet route).", {
78
- status: 409
79
- });
78
+ const privy = o.privy ?? chunk45KSZH26_cjs.createPrivyServer();
79
+ for (let attempt = 0; ; attempt++) {
80
+ const auth = await chunk45KSZH26_cjs.requireUser(request, { privy });
81
+ if (!auth.ok) return auth.response;
82
+ if (auth.user.address) return { userId: auth.user.userId, ownerAddress: auth.user.address };
83
+ if (attempt >= wait.attempts) return PROVISIONING;
84
+ await new Promise((resolve) => setTimeout(resolve, wait.delayMs * (attempt + 1)));
85
+ }
86
+ };
87
+ const authenticate = async (request) => {
88
+ const user = await authenticateOrProvisioning(request);
89
+ if (user === PROVISIONING) {
90
+ throw new chunkYQL7NISX_cjs.PepuAuthError(
91
+ "WALLET_NOT_PROVISIONED",
92
+ "Your wallet is still being set up. This usually takes a few seconds; retrying.",
93
+ { status: 409, retryable: true }
94
+ );
80
95
  }
81
- return { userId: auth.user.userId, ownerAddress: auth.user.address };
96
+ return user;
82
97
  };
83
98
  const minutes = () => o.minutes ?? chunkIG7RSL2Y_cjs.resolveSessionMinutes(process.env.SESSION_DURATION_MINUTES);
84
- const policiesFor = (validUntil) => chunkPHM3ZORG_cjs.buildKernelSessionPolicies({ calls: o.scope.calls, validUntil });
99
+ const policiesFor = (validUntil) => chunk4L4CHIXE_cjs.buildKernelSessionPolicies({ calls: o.scope.calls, validUntil });
85
100
  return {
86
101
  prepare: {
87
102
  POST: (request) => guard("combo prepare", async () => {
@@ -90,11 +105,11 @@ function createSponsoredSessionRoutes(o) {
90
105
  const { userId, ownerAddress } = user;
91
106
  const mins = minutes();
92
107
  const validUntil = chunkIG7RSL2Y_cjs.sessionExpiry(nowSeconds(), mins);
93
- const key = chunkPHM3ZORG_cjs.generateSessionKey();
108
+ const key = chunk4L4CHIXE_cjs.generateSessionKey();
94
109
  const policies = policiesFor(validUntil);
95
110
  const [kernelAddress, permissionId] = await Promise.all([
96
- chunkNVOPDXTA_cjs.getKernelAddress(client(), ownerAddress),
97
- chunkPHM3ZORG_cjs.expectedPermissionId({ publicClient: client(), sessionKeyAddress: key.address, policies })
111
+ chunkUQH4ZAXD_cjs.getKernelAddress(client(), ownerAddress),
112
+ chunk4L4CHIXE_cjs.expectedPermissionId({ publicClient: client(), sessionKeyAddress: key.address, policies })
98
113
  ]);
99
114
  const record = {
100
115
  userId,
@@ -145,10 +160,11 @@ function createSponsoredSessionRoutes(o) {
145
160
  },
146
161
  status: {
147
162
  GET: (request) => guard("combo status", async () => {
148
- const user = await authenticate(request);
163
+ const user = await authenticateOrProvisioning(request);
149
164
  if (user instanceof Response) return user;
165
+ if (user === PROVISIONING) return json({ active: false, provisioning: true });
150
166
  const record = await o.store.get(user.userId);
151
- if (!record || !chunkPHM3ZORG_cjs.isLive(record, nowSeconds())) return json({ active: false });
167
+ if (!record || !chunk4L4CHIXE_cjs.isLive(record, nowSeconds())) return json({ active: false });
152
168
  return json({
153
169
  active: true,
154
170
  validUntil: record.validUntil,
@@ -164,7 +180,7 @@ function createSponsoredSessionRoutes(o) {
164
180
  const user = await authenticate(request);
165
181
  if (user instanceof Response) return user;
166
182
  const record = await o.store.get(user.userId);
167
- if (!record || !record.approval || !chunkPHM3ZORG_cjs.isLive(record, nowSeconds())) {
183
+ if (!record || !record.approval || !chunk4L4CHIXE_cjs.isLive(record, nowSeconds())) {
168
184
  throw new chunkYQL7NISX_cjs.PepuSessionError("SESSION_NONE", "No active session. Start one first.");
169
185
  }
170
186
  let input;
@@ -191,20 +207,20 @@ function createSponsoredSessionRoutes(o) {
191
207
  }
192
208
  const privyToken = o.forwardPrivyToken === false ? "" : bearerToken(request);
193
209
  try {
194
- const account = await chunkPHM3ZORG_cjs.loadKernelSessionAccount({
210
+ const account = await chunk4L4CHIXE_cjs.loadKernelSessionAccount({
195
211
  publicClient: client(),
196
212
  approval: record.approval,
197
213
  sessionPrivateKey: record.sessionPrivateKey
198
214
  });
199
- const kernel = chunkNVOPDXTA_cjs.createPepuSponsoredClient({
215
+ const kernel = chunkUQH4ZAXD_cjs.createPepuSponsoredClient({
200
216
  account,
201
217
  publicClient: client(),
202
218
  ...o.endpoints?.bundlerUrl !== void 0 ? { bundlerUrl: o.endpoints.bundlerUrl } : {},
203
219
  ...o.endpoints?.paymasterUrl !== void 0 ? { paymasterUrl: o.endpoints.paymasterUrl } : {},
204
220
  ...o.endpoints?.paymasterToken !== void 0 ? { paymasterToken: o.endpoints.paymasterToken } : {},
205
- ...privyToken ? { paymasterContext: chunkET3P6TX6_cjs.buildPaymasterContext({ privyAccessToken: privyToken }) } : {}
221
+ ...privyToken ? { paymasterContext: chunkRCMKPJZO_cjs.buildPaymasterContext({ privyAccessToken: privyToken }) } : {}
206
222
  });
207
- const result = await chunkNVOPDXTA_cjs.sendSponsored({ client: kernel, calls });
223
+ const result = await chunkUQH4ZAXD_cjs.sendSponsored({ client: kernel, calls });
208
224
  const actions = record.actions + (result.success ? 1 : 0);
209
225
  if (result.success) await o.store.set({ ...record, actions });
210
226
  const out = {
@@ -246,11 +262,11 @@ function assertCallsInScope(scope, calls) {
246
262
 
247
263
  Object.defineProperty(exports, "createMemoryStore", {
248
264
  enumerable: true,
249
- get: function () { return chunkPHM3ZORG_cjs.createMemoryStore; }
265
+ get: function () { return chunk4L4CHIXE_cjs.createMemoryStore; }
250
266
  });
251
267
  Object.defineProperty(exports, "isLive", {
252
268
  enumerable: true,
253
- get: function () { return chunkPHM3ZORG_cjs.isLive; }
269
+ get: function () { return chunk4L4CHIXE_cjs.isLive; }
254
270
  });
255
271
  Object.defineProperty(exports, "resolveSessionMinutes", {
256
272
  enumerable: true,
@@ -1 +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"]}
1
+ {"version":3,"sources":["../src/combo/server.ts"],"names":["assertServerOnly","toPepuError","PepuError","PepuChainError","toErrorResponse","createPublicClient","pepuMainnet","http","resolvePepuEndpoints","PepuConfigError","buildKernelSessionPolicies","PepuAuthError","createPrivyServer","requireUser","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 * A brand-new user's embedded wallet exists in the browser a moment before Privy's server reports it. With the\n * default authentication, a signed-in user whose wallet is not visible yet is looked up again this many times\n * (`attempts`, default 3), waiting `delayMs` * attempt number between lookups (default 400 ms). If it is still\n * not visible, `status` answers `{ active: false, provisioning: true }` (a normal state, not an error) and the other\n * routes answer a retryable 409 `WALLET_NOT_PROVISIONED`.\n */\n provisioningWait?: { attempts?: number; delayMs?: number };\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\n/** Marker: signed in, but Privy's server does not list an embedded wallet yet. */\nconst PROVISIONING = Symbol(\"wallet-provisioning\");\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 wait = { attempts: o.provisioningWait?.attempts ?? 3, delayMs: o.provisioningWait?.delayMs ?? 400 };\n\n /**\n * Authenticate. A signed-in user whose wallet Privy's server does not list yet is looked up again (bounded), then\n * reported as `PROVISIONING` so the caller decides: `status` makes it a normal state, the rest throw a retryable 409.\n */\n const authenticateOrProvisioning = async (request: Request): Promise<ComboUser | Response | typeof PROVISIONING> => {\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 privy = o.privy ?? createPrivyServer();\n for (let attempt = 0; ; attempt++) {\n const auth = await requireUser(request, { privy });\n if (!auth.ok) return auth.response;\n if (auth.user.address) return { userId: auth.user.userId, ownerAddress: auth.user.address };\n if (attempt >= wait.attempts) return PROVISIONING;\n await new Promise((resolve) => setTimeout(resolve, wait.delayMs * (attempt + 1)));\n }\n };\n\n const authenticate = async (request: Request): Promise<ComboUser | Response> => {\n const user = await authenticateOrProvisioning(request);\n if (user === PROVISIONING) {\n throw new PepuAuthError(\n \"WALLET_NOT_PROVISIONED\",\n \"Your wallet is still being set up. This usually takes a few seconds; retrying.\",\n { status: 409, retryable: true },\n );\n }\n return user;\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 authenticateOrProvisioning(request);\n if (user instanceof Response) return user;\n if (user === PROVISIONING) return json({ active: false, provisioning: true });\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"]}
package/dist/combo.d.cts CHANGED
@@ -66,6 +66,17 @@ interface SponsoredSessionRoutesOptions<I> {
66
66
  authenticate?: ComboAuthenticate;
67
67
  /** Chain reads. Default: viem on the PEPU RPC (`PEPU_RPC_URL` aware). */
68
68
  publicClient?: PublicClient;
69
+ /**
70
+ * A brand-new user's embedded wallet exists in the browser a moment before Privy's server reports it. With the
71
+ * default authentication, a signed-in user whose wallet is not visible yet is looked up again this many times
72
+ * (`attempts`, default 3), waiting `delayMs` * attempt number between lookups (default 400 ms). If it is still
73
+ * not visible, `status` answers `{ active: false, provisioning: true }` (a normal state, not an error) and the other
74
+ * routes answer a retryable 409 `WALLET_NOT_PROVISIONED`.
75
+ */
76
+ provisioningWait?: {
77
+ attempts?: number;
78
+ delayMs?: number;
79
+ };
69
80
  }
70
81
  /** The five route handlers returned by {@link createSponsoredSessionRoutes}. */
71
82
  interface SponsoredSessionRoutes {
package/dist/combo.d.ts CHANGED
@@ -66,6 +66,17 @@ interface SponsoredSessionRoutesOptions<I> {
66
66
  authenticate?: ComboAuthenticate;
67
67
  /** Chain reads. Default: viem on the PEPU RPC (`PEPU_RPC_URL` aware). */
68
68
  publicClient?: PublicClient;
69
+ /**
70
+ * A brand-new user's embedded wallet exists in the browser a moment before Privy's server reports it. With the
71
+ * default authentication, a signed-in user whose wallet is not visible yet is looked up again this many times
72
+ * (`attempts`, default 3), waiting `delayMs` * attempt number between lookups (default 400 ms). If it is still
73
+ * not visible, `status` answers `{ active: false, provisioning: true }` (a normal state, not an error) and the other
74
+ * routes answer a retryable 409 `WALLET_NOT_PROVISIONED`.
75
+ */
76
+ provisioningWait?: {
77
+ attempts?: number;
78
+ delayMs?: number;
79
+ };
69
80
  }
70
81
  /** The five route handlers returned by {@link createSponsoredSessionRoutes}. */
71
82
  interface SponsoredSessionRoutes {
@@ -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;
package/dist/combo.js CHANGED
@@ -1,17 +1,18 @@
1
- import { buildKernelSessionPolicies, isLive, loadKernelSessionAccount, generateSessionKey, expectedPermissionId } from './chunk-KVG3AYYR.js';
2
- export { createMemoryStore, isLive } from './chunk-KVG3AYYR.js';
3
- import { createPepuSponsoredClient, sendSponsored, getKernelAddress } from './chunk-ZB6SVBK4.js';
4
- import './chunk-IB2FSPMJ.js';
1
+ import { buildKernelSessionPolicies, isLive, loadKernelSessionAccount, generateSessionKey, expectedPermissionId } from './chunk-NHPWXIA2.js';
2
+ export { createMemoryStore, isLive } from './chunk-NHPWXIA2.js';
3
+ import { createPepuSponsoredClient, sendSponsored, getKernelAddress } from './chunk-QIDMFFAQ.js';
4
+ import './chunk-QZKUPCUD.js';
5
5
  import { normalizeCalls } from './chunk-VBH3JLQ5.js';
6
- import './chunk-IY3ALPUJ.js';
7
- import { buildPaymasterContext } from './chunk-MBA4CLA5.js';
8
- import './chunk-D52PADVY.js';
9
- import './chunk-FCXSP2YF.js';
6
+ import './chunk-RSPAN44L.js';
7
+ import { buildPaymasterContext } from './chunk-7PVR7QSE.js';
8
+ import './chunk-GFKIM7HT.js';
9
+ import './chunk-KJYNF5KH.js';
10
+ import './chunk-GIZNH65Q.js';
10
11
  import { isCallInScope, describeKernelSessionScope, checkApproval } from './chunk-ESMNAXUI.js';
11
12
  import './chunk-J6UXXHBE.js';
12
13
  import { resolvePepuEndpoints } from './chunk-XC4IBCI2.js';
13
14
  import { pepuMainnet } from './chunk-VTQIHMF3.js';
14
- import { requireUser, createPrivyServer } from './chunk-62M2LKQW.js';
15
+ import { createPrivyServer, requireUser } from './chunk-62M2LKQW.js';
15
16
  import { assertServerOnly } from './chunk-W3JN3YIW.js';
16
17
  import './chunk-3XUGQODR.js';
17
18
  import { sessionExpiry, resolveSessionMinutes } from './chunk-YKEWWQEJ.js';
@@ -40,6 +41,7 @@ async function guard(op, fn) {
40
41
  function bearerToken(request) {
41
42
  return (request.headers.get("authorization") ?? "").replace(/^Bearer\s+/i, "").trim();
42
43
  }
44
+ var PROVISIONING = /* @__PURE__ */ Symbol("wallet-provisioning");
43
45
  var nowSeconds = () => Math.floor(Date.now() / 1e3);
44
46
  function defaultPublicClient() {
45
47
  return createPublicClient({ chain: pepuMainnet, transport: http(resolvePepuEndpoints().rpcUrl) });
@@ -65,20 +67,32 @@ function createSponsoredSessionRoutes(o) {
65
67
  buildKernelSessionPolicies({ calls: o.scope.calls, validUntil: 1 });
66
68
  let publicClient = o.publicClient;
67
69
  const client = () => publicClient ??= defaultPublicClient();
68
- const authenticate = async (request) => {
70
+ const wait = { attempts: o.provisioningWait?.attempts ?? 3, delayMs: o.provisioningWait?.delayMs ?? 400 };
71
+ const authenticateOrProvisioning = async (request) => {
69
72
  if (o.authenticate) {
70
73
  const user = await o.authenticate(request);
71
74
  if (!user) throw new PepuAuthError("AUTH_INVALID_TOKEN", "Missing or invalid Privy access token.");
72
75
  return user;
73
76
  }
74
- const auth = await requireUser(request, { privy: o.privy ?? createPrivyServer() });
75
- if (!auth.ok) return auth.response;
76
- if (!auth.user.address) {
77
- throw new PepuAuthError("WALLET_NOT_PROVISIONED", "No embedded wallet yet. Create it first (ensure-wallet route).", {
78
- status: 409
79
- });
77
+ const privy = o.privy ?? createPrivyServer();
78
+ for (let attempt = 0; ; attempt++) {
79
+ const auth = await requireUser(request, { privy });
80
+ if (!auth.ok) return auth.response;
81
+ if (auth.user.address) return { userId: auth.user.userId, ownerAddress: auth.user.address };
82
+ if (attempt >= wait.attempts) return PROVISIONING;
83
+ await new Promise((resolve) => setTimeout(resolve, wait.delayMs * (attempt + 1)));
84
+ }
85
+ };
86
+ const authenticate = async (request) => {
87
+ const user = await authenticateOrProvisioning(request);
88
+ if (user === PROVISIONING) {
89
+ throw new PepuAuthError(
90
+ "WALLET_NOT_PROVISIONED",
91
+ "Your wallet is still being set up. This usually takes a few seconds; retrying.",
92
+ { status: 409, retryable: true }
93
+ );
80
94
  }
81
- return { userId: auth.user.userId, ownerAddress: auth.user.address };
95
+ return user;
82
96
  };
83
97
  const minutes = () => o.minutes ?? resolveSessionMinutes(process.env.SESSION_DURATION_MINUTES);
84
98
  const policiesFor = (validUntil) => buildKernelSessionPolicies({ calls: o.scope.calls, validUntil });
@@ -145,8 +159,9 @@ function createSponsoredSessionRoutes(o) {
145
159
  },
146
160
  status: {
147
161
  GET: (request) => guard("combo status", async () => {
148
- const user = await authenticate(request);
162
+ const user = await authenticateOrProvisioning(request);
149
163
  if (user instanceof Response) return user;
164
+ if (user === PROVISIONING) return json({ active: false, provisioning: true });
150
165
  const record = await o.store.get(user.userId);
151
166
  if (!record || !isLive(record, nowSeconds())) return json({ active: false });
152
167
  return json({