@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.
- package/LICENSE +21 -0
- package/README.md +590 -2
- package/dist/aa/kernel.cjs +41 -0
- package/dist/aa/kernel.cjs.map +1 -0
- package/dist/aa/kernel.d.cts +88 -0
- package/dist/aa/kernel.d.ts +88 -0
- package/dist/aa/kernel.guard.js +15 -0
- package/dist/aa/kernel.js +11 -0
- package/dist/aa/kernel.js.map +1 -0
- package/dist/aa/react-direct.cjs +111 -0
- package/dist/aa/react-direct.cjs.map +1 -0
- package/dist/aa/react-direct.d.cts +42 -0
- package/dist/aa/react-direct.d.ts +42 -0
- package/dist/aa/react-direct.guard.js +15 -0
- package/dist/aa/react-direct.js +107 -0
- package/dist/aa/react-direct.js.map +1 -0
- package/dist/aa/react.cjs +152 -0
- package/dist/aa/react.cjs.map +1 -0
- package/dist/aa/react.d.cts +62 -0
- package/dist/aa/react.d.ts +62 -0
- package/dist/aa/react.guard.js +15 -0
- package/dist/aa/react.js +147 -0
- package/dist/aa/react.js.map +1 -0
- package/dist/aa.cjs +84 -0
- package/dist/aa.cjs.map +1 -0
- package/dist/aa.d.cts +85 -0
- package/dist/aa.d.ts +85 -0
- package/dist/aa.js +11 -0
- package/dist/aa.js.map +1 -0
- package/dist/api-Dz4sCHH_.d.cts +654 -0
- package/dist/api-Dz4sCHH_.d.ts +654 -0
- package/dist/calls-BRPjKgjl.d.cts +70 -0
- package/dist/calls-z_EQOtFb.d.ts +70 -0
- package/dist/chains-DK13zGIp.d.cts +235 -0
- package/dist/chains-DK13zGIp.d.ts +235 -0
- package/dist/chunk-3XUGQODR.js +194 -0
- package/dist/chunk-3XUGQODR.js.map +1 -0
- package/dist/chunk-45KSZH26.cjs +145 -0
- package/dist/chunk-45KSZH26.cjs.map +1 -0
- package/dist/chunk-4GINFJO6.cjs +44 -0
- package/dist/chunk-4GINFJO6.cjs.map +1 -0
- package/dist/chunk-62M2LKQW.js +136 -0
- package/dist/chunk-62M2LKQW.js.map +1 -0
- package/dist/chunk-6DSZ4Z2N.js +498 -0
- package/dist/chunk-6DSZ4Z2N.js.map +1 -0
- package/dist/chunk-7MNJF2OB.cjs +72 -0
- package/dist/chunk-7MNJF2OB.cjs.map +1 -0
- package/dist/chunk-7PVR7QSE.js +45 -0
- package/dist/chunk-7PVR7QSE.js.map +1 -0
- package/dist/chunk-A5LP2UCS.cjs +2729 -0
- package/dist/chunk-A5LP2UCS.cjs.map +1 -0
- package/dist/chunk-AJS4UFQX.cjs +121 -0
- package/dist/chunk-AJS4UFQX.cjs.map +1 -0
- package/dist/chunk-BGALSKAF.cjs +315 -0
- package/dist/chunk-BGALSKAF.cjs.map +1 -0
- package/dist/chunk-C2XW44FI.cjs +200 -0
- package/dist/chunk-C2XW44FI.cjs.map +1 -0
- package/dist/chunk-C7IC36XS.cjs +13 -0
- package/dist/chunk-C7IC36XS.cjs.map +1 -0
- package/dist/chunk-D52PADVY.js +84 -0
- package/dist/chunk-D52PADVY.js.map +1 -0
- package/dist/chunk-DH6BFNVJ.cjs +272 -0
- package/dist/chunk-DH6BFNVJ.cjs.map +1 -0
- package/dist/chunk-DPCZJLB3.cjs +87 -0
- package/dist/chunk-DPCZJLB3.cjs.map +1 -0
- package/dist/chunk-EHBPIYY4.js +262 -0
- package/dist/chunk-EHBPIYY4.js.map +1 -0
- package/dist/chunk-ESMNAXUI.js +86 -0
- package/dist/chunk-ESMNAXUI.js.map +1 -0
- package/dist/chunk-F2R473FR.js +304 -0
- package/dist/chunk-F2R473FR.js.map +1 -0
- package/dist/chunk-IB2FSPMJ.js +66 -0
- package/dist/chunk-IB2FSPMJ.js.map +1 -0
- package/dist/chunk-IG7RSL2Y.cjs +178 -0
- package/dist/chunk-IG7RSL2Y.cjs.map +1 -0
- package/dist/chunk-IY3ALPUJ.js +2716 -0
- package/dist/chunk-IY3ALPUJ.js.map +1 -0
- package/dist/chunk-J3O2ZGG3.cjs +93 -0
- package/dist/chunk-J3O2ZGG3.cjs.map +1 -0
- package/dist/chunk-J6UXXHBE.js +37 -0
- package/dist/chunk-J6UXXHBE.js.map +1 -0
- package/dist/chunk-JLZ4LZ4Z.js +22 -0
- package/dist/chunk-JLZ4LZ4Z.js.map +1 -0
- package/dist/chunk-K7JSQPZO.cjs +231 -0
- package/dist/chunk-K7JSQPZO.cjs.map +1 -0
- package/dist/chunk-KJYNF5KH.js +224 -0
- package/dist/chunk-KJYNF5KH.js.map +1 -0
- package/dist/chunk-KVG3AYYR.js +99 -0
- package/dist/chunk-KVG3AYYR.js.map +1 -0
- package/dist/chunk-NE3QKDOB.cjs +24 -0
- package/dist/chunk-NE3QKDOB.cjs.map +1 -0
- package/dist/chunk-NVOPDXTA.cjs +95 -0
- package/dist/chunk-NVOPDXTA.cjs.map +1 -0
- package/dist/chunk-OH3QMAIB.js +11 -0
- package/dist/chunk-OH3QMAIB.js.map +1 -0
- package/dist/chunk-PHM3ZORG.cjs +110 -0
- package/dist/chunk-PHM3ZORG.cjs.map +1 -0
- package/dist/chunk-R5PXQNO3.cjs +209 -0
- package/dist/chunk-R5PXQNO3.cjs.map +1 -0
- package/dist/chunk-RCMKPJZO.cjs +49 -0
- package/dist/chunk-RCMKPJZO.cjs.map +1 -0
- package/dist/chunk-SVWRRALU.cjs +17 -0
- package/dist/chunk-SVWRRALU.cjs.map +1 -0
- package/dist/chunk-T43PQXJD.js +202 -0
- package/dist/chunk-T43PQXJD.js.map +1 -0
- package/dist/chunk-VBH3JLQ5.js +116 -0
- package/dist/chunk-VBH3JLQ5.js.map +1 -0
- package/dist/chunk-VF3D6KLQ.cjs +94 -0
- package/dist/chunk-VF3D6KLQ.cjs.map +1 -0
- package/dist/chunk-VTQIHMF3.js +82 -0
- package/dist/chunk-VTQIHMF3.js.map +1 -0
- package/dist/chunk-W3JN3YIW.js +15 -0
- package/dist/chunk-W3JN3YIW.js.map +1 -0
- package/dist/chunk-WANILJZQ.cjs +87 -0
- package/dist/chunk-WANILJZQ.cjs.map +1 -0
- package/dist/chunk-XC4IBCI2.js +86 -0
- package/dist/chunk-XC4IBCI2.js.map +1 -0
- package/dist/chunk-YKEWWQEJ.js +165 -0
- package/dist/chunk-YKEWWQEJ.js.map +1 -0
- package/dist/chunk-YQL7NISX.cjs +515 -0
- package/dist/chunk-YQL7NISX.cjs.map +1 -0
- package/dist/chunk-ZB6SVBK4.js +89 -0
- package/dist/chunk-ZB6SVBK4.js.map +1 -0
- package/dist/combo/react.cjs +236 -0
- package/dist/combo/react.cjs.map +1 -0
- package/dist/combo/react.d.cts +148 -0
- package/dist/combo/react.d.ts +148 -0
- package/dist/combo/react.guard.js +15 -0
- package/dist/combo/react.js +230 -0
- package/dist/combo/react.js.map +1 -0
- package/dist/combo.cjs +263 -0
- package/dist/combo.cjs.map +1 -0
- package/dist/combo.d.cts +139 -0
- package/dist/combo.d.ts +139 -0
- package/dist/combo.guard.js +15 -0
- package/dist/combo.js +249 -0
- package/dist/combo.js.map +1 -0
- package/dist/config-CHjz7ZjZ.d.cts +57 -0
- package/dist/config-COjhIZTh.d.ts +57 -0
- package/dist/doctor.cjs +354 -0
- package/dist/doctor.cjs.map +1 -0
- package/dist/doctor.d.cts +177 -0
- package/dist/doctor.d.ts +177 -0
- package/dist/doctor.js +345 -0
- package/dist/doctor.js.map +1 -0
- package/dist/erc7677-DOW58QBE.d.cts +111 -0
- package/dist/erc7677-DOW58QBE.d.ts +111 -0
- package/dist/errors-CgX1vNj7.d.cts +100 -0
- package/dist/errors-CgX1vNj7.d.ts +100 -0
- package/dist/index.cjs +806 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2398 -0
- package/dist/index.d.ts +2398 -0
- package/dist/index.js +559 -0
- package/dist/index.js.map +1 -0
- package/dist/paymaster/server.cjs +38 -0
- package/dist/paymaster/server.cjs.map +1 -0
- package/dist/paymaster/server.d.cts +57 -0
- package/dist/paymaster/server.d.ts +57 -0
- package/dist/paymaster/server.js +36 -0
- package/dist/paymaster/server.js.map +1 -0
- package/dist/paymaster.cjs +356 -0
- package/dist/paymaster.cjs.map +1 -0
- package/dist/paymaster.d.cts +1851 -0
- package/dist/paymaster.d.ts +1851 -0
- package/dist/paymaster.js +289 -0
- package/dist/paymaster.js.map +1 -0
- package/dist/privy/react.cjs +49 -0
- package/dist/privy/react.cjs.map +1 -0
- package/dist/privy/react.d.cts +194 -0
- package/dist/privy/react.d.ts +194 -0
- package/dist/privy/react.guard.js +15 -0
- package/dist/privy/react.js +7 -0
- package/dist/privy/react.js.map +1 -0
- package/dist/privy/server.cjs +44 -0
- package/dist/privy/server.cjs.map +1 -0
- package/dist/privy/server.d.cts +192 -0
- package/dist/privy/server.d.ts +192 -0
- package/dist/privy/server.guard.js +15 -0
- package/dist/privy/server.js +6 -0
- package/dist/privy/server.js.map +1 -0
- package/dist/privy/wagmi.d.ts +90 -0
- package/dist/privy/wagmi.guard.js +15 -0
- package/dist/privy/wagmi.js +55 -0
- package/dist/privy/wagmi.js.map +1 -0
- package/dist/privy.cjs +34 -0
- package/dist/privy.cjs.map +1 -0
- package/dist/privy.d.cts +4 -0
- package/dist/privy.d.ts +4 -0
- package/dist/privy.js +5 -0
- package/dist/privy.js.map +1 -0
- package/dist/react.cjs +73 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +66 -0
- package/dist/react.d.ts +66 -0
- package/dist/react.guard.js +15 -0
- package/dist/react.js +68 -0
- package/dist/react.js.map +1 -0
- package/dist/requirements-C-QiJkL9.d.cts +134 -0
- package/dist/requirements-C-QiJkL9.d.ts +134 -0
- package/dist/scope-DBRkN7bR.d.cts +94 -0
- package/dist/scope-DBRkN7bR.d.ts +94 -0
- package/dist/server.cjs +59 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.cts +208 -0
- package/dist/server.d.ts +208 -0
- package/dist/server.js +8 -0
- package/dist/server.js.map +1 -0
- package/dist/session/kernel.cjs +83 -0
- package/dist/session/kernel.cjs.map +1 -0
- package/dist/session/kernel.d.cts +131 -0
- package/dist/session/kernel.d.ts +131 -0
- package/dist/session/kernel.guard.js +15 -0
- package/dist/session/kernel.js +13 -0
- package/dist/session/kernel.js.map +1 -0
- package/dist/session/react.cjs +38 -0
- package/dist/session/react.cjs.map +1 -0
- package/dist/session/react.d.cts +119 -0
- package/dist/session/react.d.ts +119 -0
- package/dist/session/react.guard.js +15 -0
- package/dist/session/react.js +8 -0
- package/dist/session/react.js.map +1 -0
- package/dist/session/server.cjs +268 -0
- package/dist/session/server.cjs.map +1 -0
- package/dist/session/server.d.cts +151 -0
- package/dist/session/server.d.ts +151 -0
- package/dist/session/server.guard.js +15 -0
- package/dist/session/server.js +252 -0
- package/dist/session/server.js.map +1 -0
- package/dist/session.cjs +74 -0
- package/dist/session.cjs.map +1 -0
- package/dist/session.d.cts +3 -0
- package/dist/session.d.ts +3 -0
- package/dist/session.js +5 -0
- package/dist/session.js.map +1 -0
- package/dist/status-Dx9zAFo9.d.ts +327 -0
- package/dist/status-wgTM26V7.d.cts +327 -0
- package/dist/store-CjmLgp9g.d.cts +64 -0
- package/dist/store-CjmLgp9g.d.ts +64 -0
- package/dist/types-BEEM7WdG.d.cts +25 -0
- package/dist/types-BEEM7WdG.d.ts +25 -0
- package/dist/types-BilBTDqK.d.cts +27 -0
- package/dist/types-BilBTDqK.d.ts +27 -0
- package/package.json +245 -3
package/dist/doctor.d.ts
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/** Shared types for `@pepu-chain/sdk/doctor`. */
|
|
2
|
+
/** A capability a template demonstrates. Used to scope readiness checks. */
|
|
3
|
+
type Pillar = "login" | "wallet" | "session" | "sponsorship" | "gate" | "mint";
|
|
4
|
+
/**
|
|
5
|
+
* Key into the Privy dashboard requirements table owned by WP-B1
|
|
6
|
+
* (`@pepu-chain/sdk/privy`). Doctor only carries the keys; it never
|
|
7
|
+
* duplicates what each key means. Unknown keys must be reported by the
|
|
8
|
+
* injected checker, not silently dropped.
|
|
9
|
+
*/
|
|
10
|
+
type PrivyDashboardRequirementKey = string;
|
|
11
|
+
interface TemplateRequirement {
|
|
12
|
+
/** Env vars the template cannot run without. */
|
|
13
|
+
requiredEnv: string[];
|
|
14
|
+
/** Env vars with a working default or a degraded fallback. */
|
|
15
|
+
optionalEnv: string[];
|
|
16
|
+
/** Groups where at least one var must be valid (for example the gate addresses). */
|
|
17
|
+
requiredAnyOf?: string[][];
|
|
18
|
+
pillars: Pillar[];
|
|
19
|
+
/** Privy dashboard settings the template needs, by WP-B1 requirement key. */
|
|
20
|
+
privyDashboard: PrivyDashboardRequirementKey[];
|
|
21
|
+
}
|
|
22
|
+
type EnvItemStatus = "ok" | "missing" | "placeholder" | "malformed";
|
|
23
|
+
/** One env var verdict. Reports presence and length only, never the value. */
|
|
24
|
+
interface EnvItem {
|
|
25
|
+
key: string;
|
|
26
|
+
status: EnvItemStatus;
|
|
27
|
+
/** True when the variable holds a credential. */
|
|
28
|
+
secret: boolean;
|
|
29
|
+
/** Character count of the trimmed value (0 when missing). Never the value. */
|
|
30
|
+
length: number;
|
|
31
|
+
required: boolean;
|
|
32
|
+
fix: string;
|
|
33
|
+
}
|
|
34
|
+
interface EnvCheckResult {
|
|
35
|
+
ok: boolean;
|
|
36
|
+
items: EnvItem[];
|
|
37
|
+
}
|
|
38
|
+
type CheckStatus = "pass" | "fail" | "warn" | "skip";
|
|
39
|
+
interface DoctorCheck {
|
|
40
|
+
id: string;
|
|
41
|
+
status: CheckStatus;
|
|
42
|
+
/** Never contains env values or URLs (paymaster URLs embed credentials). */
|
|
43
|
+
message: string;
|
|
44
|
+
fix?: string;
|
|
45
|
+
}
|
|
46
|
+
interface DoctorReport {
|
|
47
|
+
ok: boolean;
|
|
48
|
+
checks: DoctorCheck[];
|
|
49
|
+
env: EnvCheckResult | null;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Injection point for WP-B1's `checkPrivyDashboardConfig`. It receives the
|
|
53
|
+
* requirement keys this template needs and returns checks to merge in.
|
|
54
|
+
*/
|
|
55
|
+
type PrivyDashboardChecker = (input: {
|
|
56
|
+
appId: string;
|
|
57
|
+
requirementKeys: PrivyDashboardRequirementKey[];
|
|
58
|
+
/** Present only when PRIVY_APP_SECRET is set. Never log it. */
|
|
59
|
+
appSecret?: string;
|
|
60
|
+
/** The page origin to verify against Privy's Allowed origins, for example `http://localhost:3000`. */
|
|
61
|
+
origin?: string;
|
|
62
|
+
fetch: typeof fetch;
|
|
63
|
+
}) => Promise<DoctorCheck[]>;
|
|
64
|
+
|
|
65
|
+
/** Privy app ids are cuid-style: a leading `c` then 20-29 lowercase alphanumerics. */
|
|
66
|
+
declare const PRIVY_APP_ID_PATTERN: RegExp;
|
|
67
|
+
/**
|
|
68
|
+
* Check an env map against a template's requirements. Reports presence and
|
|
69
|
+
* length only: values are never returned, logged or placed in messages.
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```ts
|
|
73
|
+
* const r = checkPepuEnv({ env: process.env, template: "game-app" });
|
|
74
|
+
* r.items.filter((i) => i.status !== "ok").map((i) => i.fix);
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
declare function checkPepuEnv(o: {
|
|
78
|
+
env: Record<string, string | undefined>;
|
|
79
|
+
template?: string;
|
|
80
|
+
pillars?: Pillar[];
|
|
81
|
+
}): EnvCheckResult;
|
|
82
|
+
|
|
83
|
+
/** Privy app id format check. Never echoes the value. */
|
|
84
|
+
declare function checkPrivyAppIdFormat(appId: string | undefined): DoctorCheck;
|
|
85
|
+
/**
|
|
86
|
+
* Check the chain RPC answers and reports chainId 97741.
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```ts
|
|
90
|
+
* const c = await checkChainRpc({ rpcUrl: "https://rpc-pepu-v2-mainnet-0.t.conduit.xyz" });
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
declare function checkChainRpc(o?: {
|
|
94
|
+
rpcUrl?: string;
|
|
95
|
+
fetch?: typeof fetch;
|
|
96
|
+
}): Promise<DoctorCheck>;
|
|
97
|
+
/**
|
|
98
|
+
* Check the bundler and paymaster URLs resolved by the endpoints registry.
|
|
99
|
+
* Unset (nothing to reach) is a skip; set but unreachable is a failure.
|
|
100
|
+
* URLs are never included in messages: paymaster URLs embed credentials.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```ts
|
|
104
|
+
* const checks = await checkSponsorshipEndpoints({ env: process.env });
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
declare function checkSponsorshipEndpoints(o?: {
|
|
108
|
+
env?: Record<string, string | undefined>;
|
|
109
|
+
fetch?: typeof fetch;
|
|
110
|
+
}): Promise<DoctorCheck[]>;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Per-template env and Privy dashboard requirements, read from each
|
|
114
|
+
* template's `.env.example` and `lib/env*.ts`. Keep in step with them.
|
|
115
|
+
* `privyDashboard` holds requirement keys resolved by WP-B1's table.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```ts
|
|
119
|
+
* TEMPLATE_REQUIREMENTS["game-app"].requiredEnv; // includes PRIVY_AUTHORIZATION_KEY
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
declare const TEMPLATE_REQUIREMENTS: Record<string, TemplateRequirement>;
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* P-256 authorization key generator for Privy session signers. Ported from
|
|
126
|
+
* templates/game-app/scripts/generate-authorization-key.mjs, which used
|
|
127
|
+
* `@privy-io/node`'s `generateP256KeyPair()`. Same output format, implemented
|
|
128
|
+
* with WebCrypto so this entry needs no peer dependency.
|
|
129
|
+
*/
|
|
130
|
+
interface PrivyAuthorizationKeyPair {
|
|
131
|
+
/** Base64 SPKI, no PEM headers. Paste into the Privy dashboard "New key" form. */
|
|
132
|
+
publicKey: string;
|
|
133
|
+
/** Base64 PKCS8, no PEM headers. A real secret: put it in PRIVY_AUTHORIZATION_KEY. */
|
|
134
|
+
privateKey: string;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Generate a P-256 key pair in the exact format Privy expects. Writes and
|
|
138
|
+
* logs nothing; the caller decides where each half goes. Register the public
|
|
139
|
+
* half in the Privy dashboard, keep the private half in server env only.
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```ts
|
|
143
|
+
* const { publicKey, privateKey } = await generatePrivyAuthorizationKey();
|
|
144
|
+
* // show publicKey; write privateKey straight to .env.local, never print it
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
declare function generatePrivyAuthorizationKey(): Promise<PrivyAuthorizationKeyPair>;
|
|
148
|
+
|
|
149
|
+
interface RunDoctorOptions {
|
|
150
|
+
env: Record<string, string | undefined>;
|
|
151
|
+
template?: string;
|
|
152
|
+
pillars?: Pillar[];
|
|
153
|
+
/** Override fetch (tests, proxies). */
|
|
154
|
+
fetch?: typeof fetch;
|
|
155
|
+
/** Skip network checks (RPC, bundler, paymaster, Privy dashboard). */
|
|
156
|
+
offline?: boolean;
|
|
157
|
+
/** WP-B1's `checkPrivyDashboardConfig`, wrapped to this signature. Skipped when absent. */
|
|
158
|
+
checkPrivyDashboard?: PrivyDashboardChecker;
|
|
159
|
+
/**
|
|
160
|
+
* The page origin (scheme, host and port) to check against Privy's Allowed
|
|
161
|
+
* origins, for example `http://localhost:3000`. Without it the
|
|
162
|
+
* allowed-origins check can only warn.
|
|
163
|
+
*/
|
|
164
|
+
origin?: string;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Run every readiness check and return a report. Env values never appear in it.
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* ```ts
|
|
171
|
+
* const report = await runDoctor({ env: process.env, template: "sponsored-session-app" });
|
|
172
|
+
* if (!report.ok) console.log(report.checks.filter((c) => c.status === "fail"));
|
|
173
|
+
* ```
|
|
174
|
+
*/
|
|
175
|
+
declare function runDoctor(o: RunDoctorOptions): Promise<DoctorReport>;
|
|
176
|
+
|
|
177
|
+
export { type CheckStatus, type DoctorCheck, type DoctorReport, type EnvCheckResult, type EnvItem, type EnvItemStatus, PRIVY_APP_ID_PATTERN, type Pillar, type PrivyAuthorizationKeyPair, type PrivyDashboardChecker, type PrivyDashboardRequirementKey, type RunDoctorOptions, TEMPLATE_REQUIREMENTS, type TemplateRequirement, checkChainRpc, checkPepuEnv, checkPrivyAppIdFormat, checkSponsorshipEndpoints, generatePrivyAuthorizationKey, runDoctor };
|
package/dist/doctor.js
ADDED
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
import { PEPU_ENV, resolvePepuEndpoints, PEPU_PUBLIC_ENV } from './chunk-XC4IBCI2.js';
|
|
2
|
+
import { pepuMainnet } from './chunk-VTQIHMF3.js';
|
|
3
|
+
import { PepuConfigError } from './chunk-6DSZ4Z2N.js';
|
|
4
|
+
|
|
5
|
+
// src/doctor/requirements.ts
|
|
6
|
+
var PRIVY_ID = "NEXT_PUBLIC_PRIVY_APP_ID";
|
|
7
|
+
var PRIVY_SECRET = "PRIVY_APP_SECRET";
|
|
8
|
+
var RPC = "PEPU_RPC_URL";
|
|
9
|
+
var TEMPLATE_REQUIREMENTS = {
|
|
10
|
+
"consumer-app": {
|
|
11
|
+
requiredEnv: [PRIVY_ID, PRIVY_SECRET],
|
|
12
|
+
optionalEnv: [],
|
|
13
|
+
pillars: ["login", "wallet"],
|
|
14
|
+
privyDashboard: ["login-methods", "allowed-origins", "embedded-wallets"]
|
|
15
|
+
},
|
|
16
|
+
"game-app": {
|
|
17
|
+
requiredEnv: [
|
|
18
|
+
PRIVY_ID,
|
|
19
|
+
PRIVY_SECRET,
|
|
20
|
+
"NEXT_PUBLIC_PRIVY_KEY_QUORUM_ID",
|
|
21
|
+
"PRIVY_AUTHORIZATION_KEY",
|
|
22
|
+
"NEXT_PUBLIC_GAME_CONTRACT_ADDRESS"
|
|
23
|
+
],
|
|
24
|
+
optionalEnv: ["SESSION_DURATION_MINUTES", RPC],
|
|
25
|
+
pillars: ["login", "wallet", "session"],
|
|
26
|
+
privyDashboard: ["login-methods", "allowed-origins", "embedded-wallets", "authorization-key-quorum"]
|
|
27
|
+
},
|
|
28
|
+
"token-gated-app": {
|
|
29
|
+
requiredEnv: [PRIVY_ID, PRIVY_SECRET],
|
|
30
|
+
optionalEnv: ["NEXT_PUBLIC_GATE_ERC20_ADDRESS", "NEXT_PUBLIC_GATE_ERC721_ADDRESS"],
|
|
31
|
+
requiredAnyOf: [["NEXT_PUBLIC_GATE_ERC20_ADDRESS", "NEXT_PUBLIC_GATE_ERC721_ADDRESS"]],
|
|
32
|
+
pillars: ["login", "wallet", "gate"],
|
|
33
|
+
privyDashboard: ["login-methods", "allowed-origins", "embedded-wallets"]
|
|
34
|
+
},
|
|
35
|
+
"nft-mint": {
|
|
36
|
+
requiredEnv: [PRIVY_ID, PRIVY_SECRET, "NEXT_PUBLIC_NFT_CONTRACT_ADDRESS"],
|
|
37
|
+
optionalEnv: [],
|
|
38
|
+
pillars: ["login", "wallet", "mint"],
|
|
39
|
+
privyDashboard: ["login-methods", "allowed-origins", "embedded-wallets"]
|
|
40
|
+
},
|
|
41
|
+
"sponsored-demo": {
|
|
42
|
+
requiredEnv: [PRIVY_ID, PRIVY_SECRET],
|
|
43
|
+
optionalEnv: ["NEXT_PUBLIC_PAYMASTER_CONTRACT_ADDRESS"],
|
|
44
|
+
pillars: ["login", "wallet", "sponsorship"],
|
|
45
|
+
// Smart Wallets: chain 97741, provider Kernel, bundler and paymaster URLs.
|
|
46
|
+
privyDashboard: ["login-methods", "allowed-origins", "embedded-wallets", "smart-wallets"]
|
|
47
|
+
},
|
|
48
|
+
"sponsored-session-app": {
|
|
49
|
+
requiredEnv: [PRIVY_ID, PRIVY_SECRET, "PEPU_BUNDLER_URL", "PEPU_PAYMASTER_URL"],
|
|
50
|
+
optionalEnv: ["SESSION_DURATION_MINUTES", RPC],
|
|
51
|
+
pillars: ["login", "wallet", "session", "sponsorship"],
|
|
52
|
+
// Google login on; Smart Wallets deliberately NOT needed (own Kernel account).
|
|
53
|
+
privyDashboard: ["login-methods", "login-methods.google", "allowed-origins", "embedded-wallets"]
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// src/doctor/env.ts
|
|
58
|
+
var PRIVY_APP_ID_PATTERN = /^c[a-z0-9]{20,29}$/;
|
|
59
|
+
var ADDRESS = /^0x[0-9a-fA-F]{40}$/;
|
|
60
|
+
var SECRET_KEYS = /* @__PURE__ */ new Set([
|
|
61
|
+
"PRIVY_APP_SECRET",
|
|
62
|
+
"PRIVY_AUTHORIZATION_KEY",
|
|
63
|
+
"CONDUIT_API_KEY",
|
|
64
|
+
"PEPU_BUNDLER_URL",
|
|
65
|
+
"PEPU_PAYMASTER_URL"
|
|
66
|
+
]);
|
|
67
|
+
function isHttpUrl(v) {
|
|
68
|
+
try {
|
|
69
|
+
const p = new URL(v);
|
|
70
|
+
return p.protocol === "http:" || p.protocol === "https:";
|
|
71
|
+
} catch {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function isPlaceholder(v) {
|
|
76
|
+
return /^(<.*>|your[-_ ].*|changeme|change-me|todo|xxx+|\.\.\.|replace[-_ ]?me.*)$/i.test(v);
|
|
77
|
+
}
|
|
78
|
+
function shapeOk(key, v) {
|
|
79
|
+
if (key === "NEXT_PUBLIC_PRIVY_APP_ID") return PRIVY_APP_ID_PATTERN.test(v);
|
|
80
|
+
if (key.endsWith("_ADDRESS")) return ADDRESS.test(v);
|
|
81
|
+
if (key === "PEPU_BUNDLER_URL" || key === "PEPU_PAYMASTER_URL") return isHttpUrl(v);
|
|
82
|
+
if (key === "SESSION_DURATION_MINUTES") return Number.isFinite(Number(v)) && Number(v) > 0;
|
|
83
|
+
if (key === "NEXT_PUBLIC_PEPU_NETWORK") return v === "mainnet";
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
function fixFor(key, status) {
|
|
87
|
+
if (status === "ok") return "";
|
|
88
|
+
const verb = status === "missing" ? "Set" : "Replace the value of";
|
|
89
|
+
const hints = {
|
|
90
|
+
NEXT_PUBLIC_PRIVY_APP_ID: "the App ID from the Privy dashboard (Settings)",
|
|
91
|
+
PRIVY_APP_SECRET: "the app secret from the Privy dashboard (server only)",
|
|
92
|
+
PRIVY_AUTHORIZATION_KEY: "the private key from generatePrivyAuthorizationKey (server only)",
|
|
93
|
+
NEXT_PUBLIC_PRIVY_KEY_QUORUM_ID: "the key quorum id Privy returns after registering the public key",
|
|
94
|
+
NEXT_PUBLIC_PEPU_NETWORK: 'the value "mainnet" (the only supported network)'
|
|
95
|
+
};
|
|
96
|
+
const detail = hints[key] ?? (key.endsWith("_ADDRESS") ? "a 0x-prefixed 20-byte contract address" : key.endsWith("_URL") ? "an http(s) URL" : "a valid value");
|
|
97
|
+
return `${verb} ${key} in .env.local to ${detail}.`;
|
|
98
|
+
}
|
|
99
|
+
function checkPepuEnv(o) {
|
|
100
|
+
const req = o.template ? TEMPLATE_REQUIREMENTS[o.template] : void 0;
|
|
101
|
+
const keys = [];
|
|
102
|
+
const seen = /* @__PURE__ */ new Set();
|
|
103
|
+
const add = (key, required) => {
|
|
104
|
+
if (!seen.has(key)) {
|
|
105
|
+
seen.add(key);
|
|
106
|
+
keys.push({ key, required });
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
if (req) {
|
|
110
|
+
req.requiredEnv.forEach((k) => add(k, true));
|
|
111
|
+
req.optionalEnv.forEach((k) => add(k, false));
|
|
112
|
+
} else {
|
|
113
|
+
add("NEXT_PUBLIC_PRIVY_APP_ID", true);
|
|
114
|
+
add("PRIVY_APP_SECRET", true);
|
|
115
|
+
}
|
|
116
|
+
const pillars = o.pillars ?? req?.pillars;
|
|
117
|
+
if (pillars?.includes("sponsorship")) {
|
|
118
|
+
add("PEPU_BUNDLER_URL", true);
|
|
119
|
+
add("PEPU_PAYMASTER_URL", true);
|
|
120
|
+
}
|
|
121
|
+
const items = keys.map(({ key, required }) => {
|
|
122
|
+
const v = (o.env[key] ?? "").trim();
|
|
123
|
+
let status;
|
|
124
|
+
if (v === "") status = "missing";
|
|
125
|
+
else if (isPlaceholder(v)) status = "placeholder";
|
|
126
|
+
else if (!shapeOk(key, v)) status = "malformed";
|
|
127
|
+
else status = "ok";
|
|
128
|
+
return { key, status, secret: SECRET_KEYS.has(key), length: v.length, required, fix: fixFor(key, status) };
|
|
129
|
+
});
|
|
130
|
+
let anyOfOk = true;
|
|
131
|
+
for (const group of req?.requiredAnyOf ?? []) {
|
|
132
|
+
const satisfied = group.some((k) => items.find((i) => i.key === k)?.status === "ok");
|
|
133
|
+
if (!satisfied) {
|
|
134
|
+
anyOfOk = false;
|
|
135
|
+
for (const k of group) {
|
|
136
|
+
const it = items.find((i) => i.key === k);
|
|
137
|
+
if (it) it.fix = `Set at least one of ${group.join(" / ")} to a valid 0x address.`;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
const ok = anyOfOk && items.every((i) => i.required ? i.status === "ok" : i.status === "ok" || i.status === "missing");
|
|
142
|
+
return { ok, items };
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// src/doctor/checks.ts
|
|
146
|
+
var TIMEOUT_MS = 8e3;
|
|
147
|
+
async function rpc(f, url, method) {
|
|
148
|
+
const res = await f(url, {
|
|
149
|
+
method: "POST",
|
|
150
|
+
headers: { "content-type": "application/json" },
|
|
151
|
+
body: JSON.stringify({ jsonrpc: "2.0", id: 1, method, params: [] }),
|
|
152
|
+
signal: AbortSignal.timeout(TIMEOUT_MS)
|
|
153
|
+
});
|
|
154
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
155
|
+
const json = await res.json();
|
|
156
|
+
if (json.error !== void 0) throw new Error("JSON-RPC error");
|
|
157
|
+
return json.result;
|
|
158
|
+
}
|
|
159
|
+
function checkPrivyAppIdFormat(appId) {
|
|
160
|
+
const v = (appId ?? "").trim();
|
|
161
|
+
if (v === "") {
|
|
162
|
+
return {
|
|
163
|
+
id: "privy.app-id",
|
|
164
|
+
status: "fail",
|
|
165
|
+
message: "NEXT_PUBLIC_PRIVY_APP_ID is not set.",
|
|
166
|
+
fix: "Copy the App ID from the Privy dashboard (Settings)."
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
if (!PRIVY_APP_ID_PATTERN.test(v)) {
|
|
170
|
+
return {
|
|
171
|
+
id: "privy.app-id",
|
|
172
|
+
status: "fail",
|
|
173
|
+
message: `NEXT_PUBLIC_PRIVY_APP_ID does not look like a Privy app id (length ${v.length}).`,
|
|
174
|
+
fix: "Use the App ID, not the app secret or client id."
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
return { id: "privy.app-id", status: "pass", message: "Privy app id format looks right." };
|
|
178
|
+
}
|
|
179
|
+
async function checkChainRpc(o = {}) {
|
|
180
|
+
const url = o.rpcUrl ?? pepuMainnet.rpcUrls.default.http[0];
|
|
181
|
+
try {
|
|
182
|
+
const result = await rpc(o.fetch ?? fetch, url, "eth_chainId");
|
|
183
|
+
const id = typeof result === "string" ? Number.parseInt(result, 16) : Number.NaN;
|
|
184
|
+
if (id !== pepuMainnet.id) {
|
|
185
|
+
return {
|
|
186
|
+
id: "chain.rpc",
|
|
187
|
+
status: "fail",
|
|
188
|
+
message: `RPC reports chainId ${String(id)}, expected ${pepuMainnet.id}.`,
|
|
189
|
+
fix: `Point ${PEPU_ENV.rpcUrl} at a Pepe Unchained V2 mainnet RPC.`
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
return { id: "chain.rpc", status: "pass", message: `RPC reachable, chainId ${pepuMainnet.id}.` };
|
|
193
|
+
} catch {
|
|
194
|
+
return {
|
|
195
|
+
id: "chain.rpc",
|
|
196
|
+
status: "fail",
|
|
197
|
+
message: "Chain RPC is unreachable.",
|
|
198
|
+
fix: `Check ${PEPU_ENV.rpcUrl} and your network.`
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
async function checkSponsorshipEndpoints(o = {}) {
|
|
203
|
+
const f = o.fetch ?? fetch;
|
|
204
|
+
let eps;
|
|
205
|
+
try {
|
|
206
|
+
eps = resolvePepuEndpoints(o.env ? { env: o.env } : {});
|
|
207
|
+
} catch (e) {
|
|
208
|
+
const msg = e instanceof PepuConfigError ? e.message : "Endpoint configuration is invalid.";
|
|
209
|
+
return [
|
|
210
|
+
{
|
|
211
|
+
id: "sponsorship.endpoints",
|
|
212
|
+
status: "fail",
|
|
213
|
+
message: msg,
|
|
214
|
+
fix: `Fix ${PEPU_ENV.bundlerUrl} / ${PEPU_ENV.paymasterUrl}.`
|
|
215
|
+
}
|
|
216
|
+
];
|
|
217
|
+
}
|
|
218
|
+
const out = [];
|
|
219
|
+
if (eps.bundlerUrl === null) {
|
|
220
|
+
out.push({
|
|
221
|
+
id: "sponsorship.bundler",
|
|
222
|
+
status: "skip",
|
|
223
|
+
message: "No bundler URL configured.",
|
|
224
|
+
fix: `Set ${PEPU_ENV.bundlerUrl} to https://bundler.pepeunchained.com or your own bundler (${PEPU_PUBLIC_ENV.bundlerUrl} for browser use).`
|
|
225
|
+
});
|
|
226
|
+
} else {
|
|
227
|
+
try {
|
|
228
|
+
const r = await rpc(f, eps.bundlerUrl, "eth_supportedEntryPoints");
|
|
229
|
+
out.push(
|
|
230
|
+
Array.isArray(r) && r.length > 0 ? { id: "sponsorship.bundler", status: "pass", message: "Bundler reachable and reports supported entry points." } : { id: "sponsorship.bundler", status: "warn", message: "Bundler answered but reported no entry points." }
|
|
231
|
+
);
|
|
232
|
+
} catch {
|
|
233
|
+
out.push({
|
|
234
|
+
id: "sponsorship.bundler",
|
|
235
|
+
status: "fail",
|
|
236
|
+
message: "Bundler is unreachable.",
|
|
237
|
+
fix: `Check ${PEPU_ENV.bundlerUrl} and that the bundler is running.`
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
const paymasterTarget = eps.paymasterUrl ?? (eps.paymasterBaseUrl === null ? null : `${eps.paymasterBaseUrl}/health`);
|
|
242
|
+
if (paymasterTarget === null) {
|
|
243
|
+
out.push({
|
|
244
|
+
id: "sponsorship.paymaster",
|
|
245
|
+
status: "skip",
|
|
246
|
+
message: "No paymaster URL configured.",
|
|
247
|
+
fix: `Set ${PEPU_ENV.paymasterUrl} to https://paymaster.pepeunchained.com/v2/paymaster/<client token> or your own paymaster.`
|
|
248
|
+
});
|
|
249
|
+
} else {
|
|
250
|
+
try {
|
|
251
|
+
await f(paymasterTarget, { method: "GET", signal: AbortSignal.timeout(TIMEOUT_MS) });
|
|
252
|
+
out.push({ id: "sponsorship.paymaster", status: "pass", message: "Paymaster endpoint reachable." });
|
|
253
|
+
} catch {
|
|
254
|
+
out.push({
|
|
255
|
+
id: "sponsorship.paymaster",
|
|
256
|
+
status: "fail",
|
|
257
|
+
message: "Paymaster is unreachable.",
|
|
258
|
+
fix: `Check ${PEPU_ENV.paymasterUrl} and that the paymaster service is running.`
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return out;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// src/doctor/auth-key.ts
|
|
266
|
+
function toBase64(bytes) {
|
|
267
|
+
let bin = "";
|
|
268
|
+
for (const b of new Uint8Array(bytes)) bin += String.fromCharCode(b);
|
|
269
|
+
return btoa(bin);
|
|
270
|
+
}
|
|
271
|
+
async function generatePrivyAuthorizationKey() {
|
|
272
|
+
const pair = await globalThis.crypto.subtle.generateKey({ name: "ECDSA", namedCurve: "P-256" }, true, [
|
|
273
|
+
"sign",
|
|
274
|
+
"verify"
|
|
275
|
+
]);
|
|
276
|
+
const [spki, pkcs8] = await Promise.all([
|
|
277
|
+
globalThis.crypto.subtle.exportKey("spki", pair.publicKey),
|
|
278
|
+
globalThis.crypto.subtle.exportKey("pkcs8", pair.privateKey)
|
|
279
|
+
]);
|
|
280
|
+
return { publicKey: toBase64(spki), privateKey: toBase64(pkcs8) };
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// src/doctor.ts
|
|
284
|
+
async function runDoctor(o) {
|
|
285
|
+
const f = o.fetch ?? fetch;
|
|
286
|
+
const req = o.template ? TEMPLATE_REQUIREMENTS[o.template] : void 0;
|
|
287
|
+
const checks = [];
|
|
288
|
+
if (o.template && !req) {
|
|
289
|
+
checks.push({
|
|
290
|
+
id: "template",
|
|
291
|
+
status: "fail",
|
|
292
|
+
message: `Unknown template "${o.template}".`,
|
|
293
|
+
fix: `Use one of: ${Object.keys(TEMPLATE_REQUIREMENTS).join(", ")}.`
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
const env = checkPepuEnv({
|
|
297
|
+
env: o.env,
|
|
298
|
+
...req && o.template ? { template: o.template } : {},
|
|
299
|
+
...o.pillars ? { pillars: o.pillars } : {}
|
|
300
|
+
});
|
|
301
|
+
for (const i of env.items) {
|
|
302
|
+
if (i.status === "ok" || i.status === "missing" && !i.required) continue;
|
|
303
|
+
checks.push({
|
|
304
|
+
id: `env.${i.key}`,
|
|
305
|
+
status: i.required ? "fail" : "warn",
|
|
306
|
+
message: `${i.key} is ${i.status} (length ${i.length}).`,
|
|
307
|
+
fix: i.fix
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
checks.push(checkPrivyAppIdFormat(o.env.NEXT_PUBLIC_PRIVY_APP_ID));
|
|
311
|
+
const pillars = o.pillars ?? req?.pillars ?? [];
|
|
312
|
+
if (o.offline) {
|
|
313
|
+
checks.push({ id: "network", status: "skip", message: "Network checks skipped (offline)." });
|
|
314
|
+
} else {
|
|
315
|
+
const rpcUrl = o.env.PEPU_RPC_URL?.trim() || o.env.NEXT_PUBLIC_PEPU_RPC_URL?.trim() || void 0;
|
|
316
|
+
checks.push(await checkChainRpc({ ...rpcUrl ? { rpcUrl } : {}, fetch: f }));
|
|
317
|
+
if (pillars.includes("sponsorship")) {
|
|
318
|
+
checks.push(...await checkSponsorshipEndpoints({ env: o.env, fetch: f }));
|
|
319
|
+
}
|
|
320
|
+
const appId = o.env.NEXT_PUBLIC_PRIVY_APP_ID?.trim();
|
|
321
|
+
if (o.checkPrivyDashboard && req && appId) {
|
|
322
|
+
const secret = o.env.PRIVY_APP_SECRET?.trim();
|
|
323
|
+
checks.push(
|
|
324
|
+
...await o.checkPrivyDashboard({
|
|
325
|
+
appId,
|
|
326
|
+
requirementKeys: req.privyDashboard,
|
|
327
|
+
...secret ? { appSecret: secret } : {},
|
|
328
|
+
...o.origin ? { origin: o.origin } : {},
|
|
329
|
+
fetch: f
|
|
330
|
+
})
|
|
331
|
+
);
|
|
332
|
+
} else {
|
|
333
|
+
checks.push({
|
|
334
|
+
id: "privy.dashboard",
|
|
335
|
+
status: "skip",
|
|
336
|
+
message: "Privy dashboard check not run (no checker injected, unknown template, or no app id)."
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
return { ok: checks.every((c) => c.status !== "fail"), checks, env };
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
export { PRIVY_APP_ID_PATTERN, TEMPLATE_REQUIREMENTS, checkChainRpc, checkPepuEnv, checkPrivyAppIdFormat, checkSponsorshipEndpoints, generatePrivyAuthorizationKey, runDoctor };
|
|
344
|
+
//# sourceMappingURL=doctor.js.map
|
|
345
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/doctor/requirements.ts","../src/doctor/env.ts","../src/doctor/checks.ts","../src/doctor/auth-key.ts","../src/doctor.ts"],"names":[],"mappings":"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","file":"doctor.js","sourcesContent":["import type { TemplateRequirement } from \"./types.js\";\n\nconst PRIVY_ID = \"NEXT_PUBLIC_PRIVY_APP_ID\";\nconst PRIVY_SECRET = \"PRIVY_APP_SECRET\";\nconst RPC = \"PEPU_RPC_URL\";\n\n/**\n * Per-template env and Privy dashboard requirements, read from each\n * template's `.env.example` and `lib/env*.ts`. Keep in step with them.\n * `privyDashboard` holds requirement keys resolved by WP-B1's table.\n *\n * @example\n * ```ts\n * TEMPLATE_REQUIREMENTS[\"game-app\"].requiredEnv; // includes PRIVY_AUTHORIZATION_KEY\n * ```\n */\nexport const TEMPLATE_REQUIREMENTS: Record<string, TemplateRequirement> = {\n \"consumer-app\": {\n requiredEnv: [PRIVY_ID, PRIVY_SECRET],\n optionalEnv: [],\n pillars: [\"login\", \"wallet\"],\n privyDashboard: [\"login-methods\", \"allowed-origins\", \"embedded-wallets\"],\n },\n \"game-app\": {\n requiredEnv: [\n PRIVY_ID,\n PRIVY_SECRET,\n \"NEXT_PUBLIC_PRIVY_KEY_QUORUM_ID\",\n \"PRIVY_AUTHORIZATION_KEY\",\n \"NEXT_PUBLIC_GAME_CONTRACT_ADDRESS\",\n ],\n optionalEnv: [\"SESSION_DURATION_MINUTES\", RPC],\n pillars: [\"login\", \"wallet\", \"session\"],\n privyDashboard: [\"login-methods\", \"allowed-origins\", \"embedded-wallets\", \"authorization-key-quorum\"],\n },\n \"token-gated-app\": {\n requiredEnv: [PRIVY_ID, PRIVY_SECRET],\n optionalEnv: [\"NEXT_PUBLIC_GATE_ERC20_ADDRESS\", \"NEXT_PUBLIC_GATE_ERC721_ADDRESS\"],\n requiredAnyOf: [[\"NEXT_PUBLIC_GATE_ERC20_ADDRESS\", \"NEXT_PUBLIC_GATE_ERC721_ADDRESS\"]],\n pillars: [\"login\", \"wallet\", \"gate\"],\n privyDashboard: [\"login-methods\", \"allowed-origins\", \"embedded-wallets\"],\n },\n \"nft-mint\": {\n requiredEnv: [PRIVY_ID, PRIVY_SECRET, \"NEXT_PUBLIC_NFT_CONTRACT_ADDRESS\"],\n optionalEnv: [],\n pillars: [\"login\", \"wallet\", \"mint\"],\n privyDashboard: [\"login-methods\", \"allowed-origins\", \"embedded-wallets\"],\n },\n \"sponsored-demo\": {\n requiredEnv: [PRIVY_ID, PRIVY_SECRET],\n optionalEnv: [\"NEXT_PUBLIC_PAYMASTER_CONTRACT_ADDRESS\"],\n pillars: [\"login\", \"wallet\", \"sponsorship\"],\n // Smart Wallets: chain 97741, provider Kernel, bundler and paymaster URLs.\n privyDashboard: [\"login-methods\", \"allowed-origins\", \"embedded-wallets\", \"smart-wallets\"],\n },\n \"sponsored-session-app\": {\n requiredEnv: [PRIVY_ID, PRIVY_SECRET, \"PEPU_BUNDLER_URL\", \"PEPU_PAYMASTER_URL\"],\n optionalEnv: [\"SESSION_DURATION_MINUTES\", RPC],\n pillars: [\"login\", \"wallet\", \"session\", \"sponsorship\"],\n // Google login on; Smart Wallets deliberately NOT needed (own Kernel account).\n privyDashboard: [\"login-methods\", \"login-methods.google\", \"allowed-origins\", \"embedded-wallets\"],\n },\n};\n","import { TEMPLATE_REQUIREMENTS } from \"./requirements.js\";\nimport type { EnvCheckResult, EnvItem, EnvItemStatus, Pillar } from \"./types.js\";\n\n/** Privy app ids are cuid-style: a leading `c` then 20-29 lowercase alphanumerics. */\nexport const PRIVY_APP_ID_PATTERN = /^c[a-z0-9]{20,29}$/;\n\nconst ADDRESS = /^0x[0-9a-fA-F]{40}$/;\nconst SECRET_KEYS = new Set([\n \"PRIVY_APP_SECRET\",\n \"PRIVY_AUTHORIZATION_KEY\",\n \"CONDUIT_API_KEY\",\n \"PEPU_BUNDLER_URL\",\n \"PEPU_PAYMASTER_URL\",\n]);\n\nfunction isHttpUrl(v: string): boolean {\n try {\n const p = new URL(v);\n return p.protocol === \"http:\" || p.protocol === \"https:\";\n } catch {\n return false;\n }\n}\n\nfunction isPlaceholder(v: string): boolean {\n return /^(<.*>|your[-_ ].*|changeme|change-me|todo|xxx+|\\.\\.\\.|replace[-_ ]?me.*)$/i.test(v);\n}\n\nfunction shapeOk(key: string, v: string): boolean {\n if (key === \"NEXT_PUBLIC_PRIVY_APP_ID\") return PRIVY_APP_ID_PATTERN.test(v);\n if (key.endsWith(\"_ADDRESS\")) return ADDRESS.test(v);\n if (key === \"PEPU_BUNDLER_URL\" || key === \"PEPU_PAYMASTER_URL\") return isHttpUrl(v);\n if (key === \"SESSION_DURATION_MINUTES\") return Number.isFinite(Number(v)) && Number(v) > 0;\n if (key === \"NEXT_PUBLIC_PEPU_NETWORK\") return v === \"mainnet\";\n return true;\n}\n\nfunction fixFor(key: string, status: EnvItemStatus): string {\n if (status === \"ok\") return \"\";\n const verb = status === \"missing\" ? \"Set\" : \"Replace the value of\";\n const hints: Record<string, string> = {\n NEXT_PUBLIC_PRIVY_APP_ID: \"the App ID from the Privy dashboard (Settings)\",\n PRIVY_APP_SECRET: \"the app secret from the Privy dashboard (server only)\",\n PRIVY_AUTHORIZATION_KEY: \"the private key from generatePrivyAuthorizationKey (server only)\",\n NEXT_PUBLIC_PRIVY_KEY_QUORUM_ID: \"the key quorum id Privy returns after registering the public key\",\n NEXT_PUBLIC_PEPU_NETWORK: 'the value \"mainnet\" (the only supported network)',\n };\n const detail =\n hints[key] ??\n (key.endsWith(\"_ADDRESS\")\n ? \"a 0x-prefixed 20-byte contract address\"\n : key.endsWith(\"_URL\")\n ? \"an http(s) URL\"\n : \"a valid value\");\n return `${verb} ${key} in .env.local to ${detail}.`;\n}\n\n/**\n * Check an env map against a template's requirements. Reports presence and\n * length only: values are never returned, logged or placed in messages.\n *\n * @example\n * ```ts\n * const r = checkPepuEnv({ env: process.env, template: \"game-app\" });\n * r.items.filter((i) => i.status !== \"ok\").map((i) => i.fix);\n * ```\n */\nexport function checkPepuEnv(o: {\n env: Record<string, string | undefined>;\n template?: string;\n pillars?: Pillar[];\n}): EnvCheckResult {\n const req = o.template ? TEMPLATE_REQUIREMENTS[o.template] : undefined;\n const keys: { key: string; required: boolean }[] = [];\n const seen = new Set<string>();\n const add = (key: string, required: boolean): void => {\n if (!seen.has(key)) {\n seen.add(key);\n keys.push({ key, required });\n }\n };\n if (req) {\n req.requiredEnv.forEach((k) => add(k, true));\n req.optionalEnv.forEach((k) => add(k, false));\n } else {\n add(\"NEXT_PUBLIC_PRIVY_APP_ID\", true);\n add(\"PRIVY_APP_SECRET\", true);\n }\n const pillars = o.pillars ?? req?.pillars;\n if (pillars?.includes(\"sponsorship\")) {\n add(\"PEPU_BUNDLER_URL\", true);\n add(\"PEPU_PAYMASTER_URL\", true);\n }\n\n const items: EnvItem[] = keys.map(({ key, required }) => {\n const v = (o.env[key] ?? \"\").trim();\n let status: EnvItemStatus;\n if (v === \"\") status = \"missing\";\n else if (isPlaceholder(v)) status = \"placeholder\";\n else if (!shapeOk(key, v)) status = \"malformed\";\n else status = \"ok\";\n return { key, status, secret: SECRET_KEYS.has(key), length: v.length, required, fix: fixFor(key, status) };\n });\n\n let anyOfOk = true;\n for (const group of req?.requiredAnyOf ?? []) {\n const satisfied = group.some((k) => items.find((i) => i.key === k)?.status === \"ok\");\n if (!satisfied) {\n anyOfOk = false;\n for (const k of group) {\n const it = items.find((i) => i.key === k);\n if (it) it.fix = `Set at least one of ${group.join(\" / \")} to a valid 0x address.`;\n }\n }\n }\n\n // Required vars must be ok; an optional var that is present must also be valid.\n const ok =\n anyOfOk && items.every((i) => (i.required ? i.status === \"ok\" : i.status === \"ok\" || i.status === \"missing\"));\n return { ok, items };\n}\n","import { pepuMainnet } from \"../chains.js\";\nimport { PEPU_ENV, PEPU_PUBLIC_ENV, resolvePepuEndpoints } from \"../endpoints.js\";\nimport { PepuConfigError } from \"../errors.js\";\nimport { PRIVY_APP_ID_PATTERN } from \"./env.js\";\nimport type { DoctorCheck } from \"./types.js\";\n\nconst TIMEOUT_MS = 8000;\n\nasync function rpc(f: typeof fetch, url: string, method: string): Promise<unknown> {\n const res = await f(url, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ jsonrpc: \"2.0\", id: 1, method, params: [] }),\n signal: AbortSignal.timeout(TIMEOUT_MS),\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const json = (await res.json()) as { result?: unknown; error?: unknown };\n if (json.error !== undefined) throw new Error(\"JSON-RPC error\");\n return json.result;\n}\n\n/** Privy app id format check. Never echoes the value. */\nexport function checkPrivyAppIdFormat(appId: string | undefined): DoctorCheck {\n const v = (appId ?? \"\").trim();\n if (v === \"\") {\n return {\n id: \"privy.app-id\",\n status: \"fail\",\n message: \"NEXT_PUBLIC_PRIVY_APP_ID is not set.\",\n fix: \"Copy the App ID from the Privy dashboard (Settings).\",\n };\n }\n if (!PRIVY_APP_ID_PATTERN.test(v)) {\n return {\n id: \"privy.app-id\",\n status: \"fail\",\n message: `NEXT_PUBLIC_PRIVY_APP_ID does not look like a Privy app id (length ${v.length}).`,\n fix: \"Use the App ID, not the app secret or client id.\",\n };\n }\n return { id: \"privy.app-id\", status: \"pass\", message: \"Privy app id format looks right.\" };\n}\n\n/**\n * Check the chain RPC answers and reports chainId 97741.\n *\n * @example\n * ```ts\n * const c = await checkChainRpc({ rpcUrl: \"https://rpc-pepu-v2-mainnet-0.t.conduit.xyz\" });\n * ```\n */\nexport async function checkChainRpc(o: { rpcUrl?: string; fetch?: typeof fetch } = {}): Promise<DoctorCheck> {\n const url = o.rpcUrl ?? pepuMainnet.rpcUrls.default.http[0];\n try {\n const result = await rpc(o.fetch ?? fetch, url, \"eth_chainId\");\n const id = typeof result === \"string\" ? Number.parseInt(result, 16) : Number.NaN;\n if (id !== pepuMainnet.id) {\n return {\n id: \"chain.rpc\",\n status: \"fail\",\n message: `RPC reports chainId ${String(id)}, expected ${pepuMainnet.id}.`,\n fix: `Point ${PEPU_ENV.rpcUrl} at a Pepe Unchained V2 mainnet RPC.`,\n };\n }\n return { id: \"chain.rpc\", status: \"pass\", message: `RPC reachable, chainId ${pepuMainnet.id}.` };\n } catch {\n return {\n id: \"chain.rpc\",\n status: \"fail\",\n message: \"Chain RPC is unreachable.\",\n fix: `Check ${PEPU_ENV.rpcUrl} and your network.`,\n };\n }\n}\n\n/**\n * Check the bundler and paymaster URLs resolved by the endpoints registry.\n * Unset (nothing to reach) is a skip; set but unreachable is a failure.\n * URLs are never included in messages: paymaster URLs embed credentials.\n *\n * @example\n * ```ts\n * const checks = await checkSponsorshipEndpoints({ env: process.env });\n * ```\n */\nexport async function checkSponsorshipEndpoints(\n o: { env?: Record<string, string | undefined>; fetch?: typeof fetch } = {},\n): Promise<DoctorCheck[]> {\n const f = o.fetch ?? fetch;\n let eps;\n try {\n eps = resolvePepuEndpoints(o.env ? { env: o.env } : {});\n } catch (e) {\n const msg = e instanceof PepuConfigError ? e.message : \"Endpoint configuration is invalid.\";\n return [\n {\n id: \"sponsorship.endpoints\",\n status: \"fail\",\n message: msg,\n fix: `Fix ${PEPU_ENV.bundlerUrl} / ${PEPU_ENV.paymasterUrl}.`,\n },\n ];\n }\n const out: DoctorCheck[] = [];\n if (eps.bundlerUrl === null) {\n out.push({\n id: \"sponsorship.bundler\",\n status: \"skip\",\n message: \"No bundler URL configured.\",\n fix: `Set ${PEPU_ENV.bundlerUrl} to https://bundler.pepeunchained.com or your own bundler (${PEPU_PUBLIC_ENV.bundlerUrl} for browser use).`,\n });\n } else {\n try {\n const r = await rpc(f, eps.bundlerUrl, \"eth_supportedEntryPoints\");\n out.push(\n Array.isArray(r) && r.length > 0\n ? { id: \"sponsorship.bundler\", status: \"pass\", message: \"Bundler reachable and reports supported entry points.\" }\n : { id: \"sponsorship.bundler\", status: \"warn\", message: \"Bundler answered but reported no entry points.\" },\n );\n } catch {\n out.push({\n id: \"sponsorship.bundler\",\n status: \"fail\",\n message: \"Bundler is unreachable.\",\n fix: `Check ${PEPU_ENV.bundlerUrl} and that the bundler is running.`,\n });\n }\n }\n // No token URL: reach the service base through its /health route.\n const paymasterTarget = eps.paymasterUrl ?? (eps.paymasterBaseUrl === null ? null : `${eps.paymasterBaseUrl}/health`);\n if (paymasterTarget === null) {\n out.push({\n id: \"sponsorship.paymaster\",\n status: \"skip\",\n message: \"No paymaster URL configured.\",\n fix: `Set ${PEPU_ENV.paymasterUrl} to https://paymaster.pepeunchained.com/v2/paymaster/<client token> or your own paymaster.`,\n });\n } else {\n try {\n // Any HTTP response proves reachability; auth or method errors are expected.\n await f(paymasterTarget, { method: \"GET\", signal: AbortSignal.timeout(TIMEOUT_MS) });\n out.push({ id: \"sponsorship.paymaster\", status: \"pass\", message: \"Paymaster endpoint reachable.\" });\n } catch {\n out.push({\n id: \"sponsorship.paymaster\",\n status: \"fail\",\n message: \"Paymaster is unreachable.\",\n fix: `Check ${PEPU_ENV.paymasterUrl} and that the paymaster service is running.`,\n });\n }\n }\n return out;\n}\n","/**\n * P-256 authorization key generator for Privy session signers. Ported from\n * templates/game-app/scripts/generate-authorization-key.mjs, which used\n * `@privy-io/node`'s `generateP256KeyPair()`. Same output format, implemented\n * with WebCrypto so this entry needs no peer dependency.\n */\n\nfunction toBase64(bytes: ArrayBuffer): string {\n let bin = \"\";\n for (const b of new Uint8Array(bytes)) bin += String.fromCharCode(b);\n return btoa(bin);\n}\n\nexport interface PrivyAuthorizationKeyPair {\n /** Base64 SPKI, no PEM headers. Paste into the Privy dashboard \"New key\" form. */\n publicKey: string;\n /** Base64 PKCS8, no PEM headers. A real secret: put it in PRIVY_AUTHORIZATION_KEY. */\n privateKey: string;\n}\n\n/**\n * Generate a P-256 key pair in the exact format Privy expects. Writes and\n * logs nothing; the caller decides where each half goes. Register the public\n * half in the Privy dashboard, keep the private half in server env only.\n *\n * @example\n * ```ts\n * const { publicKey, privateKey } = await generatePrivyAuthorizationKey();\n * // show publicKey; write privateKey straight to .env.local, never print it\n * ```\n */\nexport async function generatePrivyAuthorizationKey(): Promise<PrivyAuthorizationKeyPair> {\n const pair = await globalThis.crypto.subtle.generateKey({ name: \"ECDSA\", namedCurve: \"P-256\" }, true, [\n \"sign\",\n \"verify\",\n ]);\n const [spki, pkcs8] = await Promise.all([\n globalThis.crypto.subtle.exportKey(\"spki\", pair.publicKey),\n globalThis.crypto.subtle.exportKey(\"pkcs8\", pair.privateKey),\n ]);\n return { publicKey: toBase64(spki), privateKey: toBase64(pkcs8) };\n}\n","/**\n * @pepu-chain/sdk/doctor (node/any). Project readiness checks. Never returns\n * or logs env values: presence and length only.\n */\nimport { checkChainRpc, checkPrivyAppIdFormat, checkSponsorshipEndpoints } from \"./doctor/checks.js\";\nimport { checkPepuEnv } from \"./doctor/env.js\";\nimport { TEMPLATE_REQUIREMENTS } from \"./doctor/requirements.js\";\nimport type { DoctorCheck, DoctorReport, Pillar, PrivyDashboardChecker } from \"./doctor/types.js\";\n\nexport { checkPepuEnv, PRIVY_APP_ID_PATTERN } from \"./doctor/env.js\";\nexport { checkChainRpc, checkPrivyAppIdFormat, checkSponsorshipEndpoints } from \"./doctor/checks.js\";\nexport { TEMPLATE_REQUIREMENTS } from \"./doctor/requirements.js\";\nexport { generatePrivyAuthorizationKey } from \"./doctor/auth-key.js\";\nexport type { PrivyAuthorizationKeyPair } from \"./doctor/auth-key.js\";\nexport type {\n CheckStatus,\n DoctorCheck,\n DoctorReport,\n EnvCheckResult,\n EnvItem,\n EnvItemStatus,\n Pillar,\n PrivyDashboardChecker,\n PrivyDashboardRequirementKey,\n TemplateRequirement,\n} from \"./doctor/types.js\";\n\nexport interface RunDoctorOptions {\n env: Record<string, string | undefined>;\n template?: string;\n pillars?: Pillar[];\n /** Override fetch (tests, proxies). */\n fetch?: typeof fetch;\n /** Skip network checks (RPC, bundler, paymaster, Privy dashboard). */\n offline?: boolean;\n /** WP-B1's `checkPrivyDashboardConfig`, wrapped to this signature. Skipped when absent. */\n checkPrivyDashboard?: PrivyDashboardChecker;\n /**\n * The page origin (scheme, host and port) to check against Privy's Allowed\n * origins, for example `http://localhost:3000`. Without it the\n * allowed-origins check can only warn.\n */\n origin?: string;\n}\n\n/**\n * Run every readiness check and return a report. Env values never appear in it.\n *\n * @example\n * ```ts\n * const report = await runDoctor({ env: process.env, template: \"sponsored-session-app\" });\n * if (!report.ok) console.log(report.checks.filter((c) => c.status === \"fail\"));\n * ```\n */\nexport async function runDoctor(o: RunDoctorOptions): Promise<DoctorReport> {\n const f = o.fetch ?? fetch;\n const req = o.template ? TEMPLATE_REQUIREMENTS[o.template] : undefined;\n const checks: DoctorCheck[] = [];\n if (o.template && !req) {\n checks.push({\n id: \"template\",\n status: \"fail\",\n message: `Unknown template \"${o.template}\".`,\n fix: `Use one of: ${Object.keys(TEMPLATE_REQUIREMENTS).join(\", \")}.`,\n });\n }\n const env = checkPepuEnv({\n env: o.env,\n ...(req && o.template ? { template: o.template } : {}),\n ...(o.pillars ? { pillars: o.pillars } : {}),\n });\n for (const i of env.items) {\n if (i.status === \"ok\" || (i.status === \"missing\" && !i.required)) continue;\n checks.push({\n id: `env.${i.key}`,\n status: i.required ? \"fail\" : \"warn\",\n message: `${i.key} is ${i.status} (length ${i.length}).`,\n fix: i.fix,\n });\n }\n checks.push(checkPrivyAppIdFormat(o.env.NEXT_PUBLIC_PRIVY_APP_ID));\n\n const pillars = o.pillars ?? req?.pillars ?? [];\n if (o.offline) {\n checks.push({ id: \"network\", status: \"skip\", message: \"Network checks skipped (offline).\" });\n } else {\n const rpcUrl = o.env.PEPU_RPC_URL?.trim() || o.env.NEXT_PUBLIC_PEPU_RPC_URL?.trim() || undefined;\n checks.push(await checkChainRpc({ ...(rpcUrl ? { rpcUrl } : {}), fetch: f }));\n if (pillars.includes(\"sponsorship\")) {\n checks.push(...(await checkSponsorshipEndpoints({ env: o.env, fetch: f })));\n }\n const appId = o.env.NEXT_PUBLIC_PRIVY_APP_ID?.trim();\n if (o.checkPrivyDashboard && req && appId) {\n const secret = o.env.PRIVY_APP_SECRET?.trim();\n checks.push(\n ...(await o.checkPrivyDashboard({\n appId,\n requirementKeys: req.privyDashboard,\n ...(secret ? { appSecret: secret } : {}),\n ...(o.origin ? { origin: o.origin } : {}),\n fetch: f,\n })),\n );\n } else {\n checks.push({\n id: \"privy.dashboard\",\n status: \"skip\",\n message: \"Privy dashboard check not run (no checker injected, unknown template, or no app id).\",\n });\n }\n }\n return { ok: checks.every((c) => c.status !== \"fail\"), checks, env };\n}\n"]}
|