@getpara/cli 2.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (331) hide show
  1. package/README.md +97 -0
  2. package/dist/api/client.d.ts +49 -0
  3. package/dist/api/client.d.ts.map +1 -0
  4. package/dist/api/client.js +247 -0
  5. package/dist/api/errors.d.ts +9 -0
  6. package/dist/api/errors.d.ts.map +1 -0
  7. package/dist/api/errors.js +29 -0
  8. package/dist/api/types.d.ts +155 -0
  9. package/dist/api/types.d.ts.map +1 -0
  10. package/dist/api/types.js +58 -0
  11. package/dist/auth/polling-flow.d.ts +7 -0
  12. package/dist/auth/polling-flow.d.ts.map +1 -0
  13. package/dist/auth/polling-flow.js +94 -0
  14. package/dist/auth/session-manager.d.ts +7 -0
  15. package/dist/auth/session-manager.d.ts.map +1 -0
  16. package/dist/auth/session-manager.js +42 -0
  17. package/dist/cli.d.ts +16 -0
  18. package/dist/cli.d.ts.map +1 -0
  19. package/dist/cli.js +151 -0
  20. package/dist/commands/auth/index.d.ts +3 -0
  21. package/dist/commands/auth/index.d.ts.map +1 -0
  22. package/dist/commands/auth/index.js +18 -0
  23. package/dist/commands/auth/login.d.ts +3 -0
  24. package/dist/commands/auth/login.d.ts.map +1 -0
  25. package/dist/commands/auth/login.js +70 -0
  26. package/dist/commands/auth/logout.d.ts +3 -0
  27. package/dist/commands/auth/logout.d.ts.map +1 -0
  28. package/dist/commands/auth/logout.js +45 -0
  29. package/dist/commands/auth/status.d.ts +3 -0
  30. package/dist/commands/auth/status.d.ts.map +1 -0
  31. package/dist/commands/auth/status.js +54 -0
  32. package/dist/commands/config.d.ts +3 -0
  33. package/dist/commands/config.d.ts.map +1 -0
  34. package/dist/commands/config.js +122 -0
  35. package/dist/commands/create.d.ts +3 -0
  36. package/dist/commands/create.d.ts.map +1 -0
  37. package/dist/commands/create.js +587 -0
  38. package/dist/commands/doctor.d.ts +3 -0
  39. package/dist/commands/doctor.d.ts.map +1 -0
  40. package/dist/commands/doctor.js +67 -0
  41. package/dist/commands/init.d.ts +3 -0
  42. package/dist/commands/init.d.ts.map +1 -0
  43. package/dist/commands/init.js +45 -0
  44. package/dist/commands/keys/archive.d.ts +3 -0
  45. package/dist/commands/keys/archive.d.ts.map +1 -0
  46. package/dist/commands/keys/archive.js +49 -0
  47. package/dist/commands/keys/config/branding.d.ts +23 -0
  48. package/dist/commands/keys/config/branding.d.ts.map +1 -0
  49. package/dist/commands/keys/config/branding.js +246 -0
  50. package/dist/commands/keys/config/categories.d.ts +15 -0
  51. package/dist/commands/keys/config/categories.d.ts.map +1 -0
  52. package/dist/commands/keys/config/categories.js +67 -0
  53. package/dist/commands/keys/config/index.d.ts +3 -0
  54. package/dist/commands/keys/config/index.d.ts.map +1 -0
  55. package/dist/commands/keys/config/index.js +56 -0
  56. package/dist/commands/keys/config/ramps.d.ts +18 -0
  57. package/dist/commands/keys/config/ramps.d.ts.map +1 -0
  58. package/dist/commands/keys/config/ramps.js +185 -0
  59. package/dist/commands/keys/config/security.d.ts +15 -0
  60. package/dist/commands/keys/config/security.d.ts.map +1 -0
  61. package/dist/commands/keys/config/security.js +212 -0
  62. package/dist/commands/keys/config/setup.d.ts +16 -0
  63. package/dist/commands/keys/config/setup.d.ts.map +1 -0
  64. package/dist/commands/keys/config/setup.js +235 -0
  65. package/dist/commands/keys/config/webhooks.d.ts +18 -0
  66. package/dist/commands/keys/config/webhooks.d.ts.map +1 -0
  67. package/dist/commands/keys/config/webhooks.js +279 -0
  68. package/dist/commands/keys/create.d.ts +3 -0
  69. package/dist/commands/keys/create.d.ts.map +1 -0
  70. package/dist/commands/keys/create.js +64 -0
  71. package/dist/commands/keys/get.d.ts +3 -0
  72. package/dist/commands/keys/get.d.ts.map +1 -0
  73. package/dist/commands/keys/get.js +91 -0
  74. package/dist/commands/keys/index.d.ts +3 -0
  75. package/dist/commands/keys/index.d.ts.map +1 -0
  76. package/dist/commands/keys/index.js +22 -0
  77. package/dist/commands/keys/list.d.ts +3 -0
  78. package/dist/commands/keys/list.d.ts.map +1 -0
  79. package/dist/commands/keys/list.js +66 -0
  80. package/dist/commands/keys/rotate.d.ts +3 -0
  81. package/dist/commands/keys/rotate.d.ts.map +1 -0
  82. package/dist/commands/keys/rotate.js +59 -0
  83. package/dist/commands/orgs/index.d.ts +3 -0
  84. package/dist/commands/orgs/index.d.ts.map +1 -0
  85. package/dist/commands/orgs/index.js +15 -0
  86. package/dist/commands/orgs/list.d.ts +3 -0
  87. package/dist/commands/orgs/list.d.ts.map +1 -0
  88. package/dist/commands/orgs/list.js +53 -0
  89. package/dist/commands/orgs/switch.d.ts +3 -0
  90. package/dist/commands/orgs/switch.d.ts.map +1 -0
  91. package/dist/commands/orgs/switch.js +61 -0
  92. package/dist/commands/projects/archive.d.ts +3 -0
  93. package/dist/commands/projects/archive.d.ts.map +1 -0
  94. package/dist/commands/projects/archive.js +51 -0
  95. package/dist/commands/projects/create.d.ts +3 -0
  96. package/dist/commands/projects/create.d.ts.map +1 -0
  97. package/dist/commands/projects/create.js +48 -0
  98. package/dist/commands/projects/index.d.ts +3 -0
  99. package/dist/commands/projects/index.d.ts.map +1 -0
  100. package/dist/commands/projects/index.js +25 -0
  101. package/dist/commands/projects/list.d.ts +3 -0
  102. package/dist/commands/projects/list.d.ts.map +1 -0
  103. package/dist/commands/projects/list.js +52 -0
  104. package/dist/commands/projects/restore.d.ts +3 -0
  105. package/dist/commands/projects/restore.d.ts.map +1 -0
  106. package/dist/commands/projects/restore.js +36 -0
  107. package/dist/commands/projects/switch.d.ts +3 -0
  108. package/dist/commands/projects/switch.d.ts.map +1 -0
  109. package/dist/commands/projects/switch.js +57 -0
  110. package/dist/commands/projects/update.d.ts +3 -0
  111. package/dist/commands/projects/update.d.ts.map +1 -0
  112. package/dist/commands/projects/update.js +67 -0
  113. package/dist/commands/whoami.d.ts +3 -0
  114. package/dist/commands/whoami.d.ts.map +1 -0
  115. package/dist/commands/whoami.js +61 -0
  116. package/dist/config/config-manager.d.ts +3 -0
  117. package/dist/config/config-manager.d.ts.map +1 -0
  118. package/dist/config/config-manager.js +32 -0
  119. package/dist/config/config-store.d.ts +10 -0
  120. package/dist/config/config-store.d.ts.map +1 -0
  121. package/dist/config/config-store.js +37 -0
  122. package/dist/config/credential-store.d.ts +12 -0
  123. package/dist/config/credential-store.d.ts.map +1 -0
  124. package/dist/config/credential-store.js +94 -0
  125. package/dist/config/paths.d.ts +5 -0
  126. package/dist/config/paths.d.ts.map +1 -0
  127. package/dist/config/paths.js +29 -0
  128. package/dist/config/project-config.d.ts +8 -0
  129. package/dist/config/project-config.d.ts.map +1 -0
  130. package/dist/config/project-config.js +41 -0
  131. package/dist/core/constants.d.ts +27 -0
  132. package/dist/core/constants.d.ts.map +1 -0
  133. package/dist/core/constants.js +60 -0
  134. package/dist/core/error-handler.d.ts +24 -0
  135. package/dist/core/error-handler.d.ts.map +1 -0
  136. package/dist/core/error-handler.js +83 -0
  137. package/dist/core/types.d.ts +21 -0
  138. package/dist/core/types.d.ts.map +1 -0
  139. package/dist/core/types.js +0 -0
  140. package/dist/core/update-check.d.ts +6 -0
  141. package/dist/core/update-check.d.ts.map +1 -0
  142. package/dist/core/update-check.js +78 -0
  143. package/dist/diagnostics/checks/chain-dependencies.d.ts +2 -0
  144. package/dist/diagnostics/checks/chain-dependencies.d.ts.map +1 -0
  145. package/dist/diagnostics/checks/chain-dependencies.js +130 -0
  146. package/dist/diagnostics/checks/css-import.d.ts +2 -0
  147. package/dist/diagnostics/checks/css-import.d.ts.map +1 -0
  148. package/dist/diagnostics/checks/css-import.js +57 -0
  149. package/dist/diagnostics/checks/deprecated-packages.d.ts +2 -0
  150. package/dist/diagnostics/checks/deprecated-packages.d.ts.map +1 -0
  151. package/dist/diagnostics/checks/deprecated-packages.js +93 -0
  152. package/dist/diagnostics/checks/env-api-key.d.ts +2 -0
  153. package/dist/diagnostics/checks/env-api-key.d.ts.map +1 -0
  154. package/dist/diagnostics/checks/env-api-key.js +75 -0
  155. package/dist/diagnostics/checks/env-var-prefix.d.ts +2 -0
  156. package/dist/diagnostics/checks/env-var-prefix.d.ts.map +1 -0
  157. package/dist/diagnostics/checks/env-var-prefix.js +52 -0
  158. package/dist/diagnostics/checks/index.d.ts +13 -0
  159. package/dist/diagnostics/checks/index.d.ts.map +1 -0
  160. package/dist/diagnostics/checks/index.js +32 -0
  161. package/dist/diagnostics/checks/para-provider.d.ts +2 -0
  162. package/dist/diagnostics/checks/para-provider.d.ts.map +1 -0
  163. package/dist/diagnostics/checks/para-provider.js +42 -0
  164. package/dist/diagnostics/checks/query-client.d.ts +2 -0
  165. package/dist/diagnostics/checks/query-client.d.ts.map +1 -0
  166. package/dist/diagnostics/checks/query-client.js +58 -0
  167. package/dist/diagnostics/checks/use-client-directive.d.ts +2 -0
  168. package/dist/diagnostics/checks/use-client-directive.d.ts.map +1 -0
  169. package/dist/diagnostics/checks/use-client-directive.js +81 -0
  170. package/dist/diagnostics/checks/version-consistency.d.ts +2 -0
  171. package/dist/diagnostics/checks/version-consistency.d.ts.map +1 -0
  172. package/dist/diagnostics/checks/version-consistency.js +93 -0
  173. package/dist/diagnostics/context.d.ts +3 -0
  174. package/dist/diagnostics/context.d.ts.map +1 -0
  175. package/dist/diagnostics/context.js +56 -0
  176. package/dist/diagnostics/detectors/framework.d.ts +5 -0
  177. package/dist/diagnostics/detectors/framework.d.ts.map +1 -0
  178. package/dist/diagnostics/detectors/framework.js +73 -0
  179. package/dist/diagnostics/detectors/package-manager.d.ts +3 -0
  180. package/dist/diagnostics/detectors/package-manager.d.ts.map +1 -0
  181. package/dist/diagnostics/detectors/package-manager.js +17 -0
  182. package/dist/diagnostics/detectors/sdk.d.ts +7 -0
  183. package/dist/diagnostics/detectors/sdk.d.ts.map +1 -0
  184. package/dist/diagnostics/detectors/sdk.js +48 -0
  185. package/dist/diagnostics/runner.d.ts +3 -0
  186. package/dist/diagnostics/runner.d.ts.map +1 -0
  187. package/dist/diagnostics/runner.js +44 -0
  188. package/dist/diagnostics/types.d.ts +70 -0
  189. package/dist/diagnostics/types.d.ts.map +1 -0
  190. package/dist/diagnostics/types.js +14 -0
  191. package/dist/diagnostics/utils/code-search.d.ts +10 -0
  192. package/dist/diagnostics/utils/code-search.d.ts.map +1 -0
  193. package/dist/diagnostics/utils/code-search.js +98 -0
  194. package/dist/diagnostics/utils/file-system.d.ts +7 -0
  195. package/dist/diagnostics/utils/file-system.d.ts.map +1 -0
  196. package/dist/diagnostics/utils/file-system.js +72 -0
  197. package/dist/diagnostics/utils/package-json.d.ts +12 -0
  198. package/dist/diagnostics/utils/package-json.d.ts.map +1 -0
  199. package/dist/diagnostics/utils/package-json.js +51 -0
  200. package/dist/index.d.ts +2 -0
  201. package/dist/index.d.ts.map +1 -0
  202. package/dist/index.js +20 -0
  203. package/dist/output/formatter.d.ts +25 -0
  204. package/dist/output/formatter.d.ts.map +1 -0
  205. package/dist/output/formatter.js +76 -0
  206. package/dist/output/mask.d.ts +2 -0
  207. package/dist/output/mask.d.ts.map +1 -0
  208. package/dist/output/mask.js +15 -0
  209. package/dist/output/prompts.d.ts +25 -0
  210. package/dist/output/prompts.d.ts.map +1 -0
  211. package/dist/output/prompts.js +86 -0
  212. package/dist/output/spinner.d.ts +6 -0
  213. package/dist/output/spinner.d.ts.map +1 -0
  214. package/dist/output/spinner.js +7 -0
  215. package/dist/output/table.d.ts +9 -0
  216. package/dist/output/table.d.ts.map +1 -0
  217. package/dist/output/table.js +21 -0
  218. package/dist/scaffolding/scaffolder.d.ts +3 -0
  219. package/dist/scaffolding/scaffolder.d.ts.map +1 -0
  220. package/dist/scaffolding/scaffolder.js +78 -0
  221. package/dist/scaffolding/strategies/expo-template.d.ts +16 -0
  222. package/dist/scaffolding/strategies/expo-template.d.ts.map +1 -0
  223. package/dist/scaffolding/strategies/expo-template.js +160 -0
  224. package/dist/scaffolding/strategies/index.d.ts +5 -0
  225. package/dist/scaffolding/strategies/index.d.ts.map +1 -0
  226. package/dist/scaffolding/strategies/index.js +25 -0
  227. package/dist/scaffolding/strategies/nextjs-template.d.ts +12 -0
  228. package/dist/scaffolding/strategies/nextjs-template.d.ts.map +1 -0
  229. package/dist/scaffolding/strategies/nextjs-template.js +122 -0
  230. package/dist/scaffolding/template-renderer.d.ts +11 -0
  231. package/dist/scaffolding/template-renderer.d.ts.map +1 -0
  232. package/dist/scaffolding/template-renderer.js +99 -0
  233. package/dist/scaffolding/types.d.ts +69 -0
  234. package/dist/scaffolding/types.d.ts.map +1 -0
  235. package/dist/scaffolding/types.js +21 -0
  236. package/dist/scaffolding/utils/detect-package-manager.d.ts +23 -0
  237. package/dist/scaffolding/utils/detect-package-manager.d.ts.map +1 -0
  238. package/dist/scaffolding/utils/detect-package-manager.js +57 -0
  239. package/dist/scaffolding/utils/fs.d.ts +11 -0
  240. package/dist/scaffolding/utils/fs.d.ts.map +1 -0
  241. package/dist/scaffolding/utils/fs.js +45 -0
  242. package/dist/scaffolding/utils/resolve-para-version.d.ts +7 -0
  243. package/dist/scaffolding/utils/resolve-para-version.d.ts.map +1 -0
  244. package/dist/scaffolding/utils/resolve-para-version.js +21 -0
  245. package/dist/validation/auth-methods.d.ts +14 -0
  246. package/dist/validation/auth-methods.d.ts.map +1 -0
  247. package/dist/validation/auth-methods.js +23 -0
  248. package/dist/validation/cidr.d.ts +11 -0
  249. package/dist/validation/cidr.d.ts.map +1 -0
  250. package/dist/validation/cidr.js +35 -0
  251. package/dist/validation/hex-color.d.ts +7 -0
  252. package/dist/validation/hex-color.d.ts.map +1 -0
  253. package/dist/validation/hex-color.js +10 -0
  254. package/dist/validation/index.d.ts +9 -0
  255. package/dist/validation/index.d.ts.map +1 -0
  256. package/dist/validation/index.js +49 -0
  257. package/dist/validation/native-passkey.d.ts +31 -0
  258. package/dist/validation/native-passkey.d.ts.map +1 -0
  259. package/dist/validation/native-passkey.js +45 -0
  260. package/dist/validation/session-length.d.ts +18 -0
  261. package/dist/validation/session-length.d.ts.map +1 -0
  262. package/dist/validation/session-length.js +30 -0
  263. package/dist/validation/url.d.ts +26 -0
  264. package/dist/validation/url.d.ts.map +1 -0
  265. package/dist/validation/url.js +50 -0
  266. package/dist/validation/wallet-types.d.ts +14 -0
  267. package/dist/validation/wallet-types.d.ts.map +1 -0
  268. package/dist/validation/wallet-types.js +22 -0
  269. package/dist/validation/webhook.d.ts +4 -0
  270. package/dist/validation/webhook.d.ts.map +1 -0
  271. package/dist/validation/webhook.js +33 -0
  272. package/package.json +60 -0
  273. package/templates/expo/_env.example +3 -0
  274. package/templates/expo/_gitignore +48 -0
  275. package/templates/expo/_yarnrc.yml +1 -0
  276. package/templates/expo/app/(auth)/_layout.tsx +12 -0
  277. package/templates/expo/app/(auth)/index.tsx.template +86 -0
  278. package/templates/expo/app/(tabs)/_layout.tsx +16 -0
  279. package/templates/expo/app/(tabs)/index.tsx +112 -0
  280. package/templates/expo/app/(tabs)/send.tsx +111 -0
  281. package/templates/expo/app/_layout.tsx +17 -0
  282. package/templates/expo/app/index.tsx +22 -0
  283. package/templates/expo/app.json.template +32 -0
  284. package/templates/expo/assets/adaptive-icon.png +0 -0
  285. package/templates/expo/assets/favicon.png +0 -0
  286. package/templates/expo/assets/icon.png +0 -0
  287. package/templates/expo/assets/splash.png +0 -0
  288. package/templates/expo/babel.config.cjs +12 -0
  289. package/templates/expo/components/features/AuthForm.tsx.template +138 -0
  290. package/templates/expo/components/features/OAuthButtons.tsx.template +27 -0
  291. package/templates/expo/components/features/index.ts.template +4 -0
  292. package/templates/expo/components/ui/Button.tsx +58 -0
  293. package/templates/expo/components/ui/Card.tsx +11 -0
  294. package/templates/expo/components/ui/Divider.tsx +19 -0
  295. package/templates/expo/components/ui/Input.tsx +23 -0
  296. package/templates/expo/components/ui/WalletCard.tsx +44 -0
  297. package/templates/expo/components/ui/index.ts +5 -0
  298. package/templates/expo/eslint.config.cjs +15 -0
  299. package/templates/expo/global.css +3 -0
  300. package/templates/expo/hooks/useOneClickLogin.ts.template +161 -0
  301. package/templates/expo/hooks/useViemClient.ts +118 -0
  302. package/templates/expo/hooks/useWallets.ts +52 -0
  303. package/templates/expo/index.js +2 -0
  304. package/templates/expo/lib/auth.ts +54 -0
  305. package/templates/expo/lib/constants.ts.template +2 -0
  306. package/templates/expo/lib/para.ts +14 -0
  307. package/templates/expo/metro.config.cjs +14 -0
  308. package/templates/expo/nativewind-env.d.ts +2 -0
  309. package/templates/expo/prettier.config.cjs +10 -0
  310. package/templates/expo/providers/ParaProvider.tsx +140 -0
  311. package/templates/expo/tailwind.config.cjs +23 -0
  312. package/templates/expo/tsconfig.json +11 -0
  313. package/templates/expo/types/index.ts +28 -0
  314. package/templates/nextjs/README.md +69 -0
  315. package/templates/nextjs/_env.example +8 -0
  316. package/templates/nextjs/_gitignore +36 -0
  317. package/templates/nextjs/_yarnrc.yml +1 -0
  318. package/templates/nextjs/eslint.config.mjs +10 -0
  319. package/templates/nextjs/next.config.ts +5 -0
  320. package/templates/nextjs/postcss.config.mjs +7 -0
  321. package/templates/nextjs/public/para.svg +3 -0
  322. package/templates/nextjs/src/app/layout.tsx +30 -0
  323. package/templates/nextjs/src/app/page.tsx +40 -0
  324. package/templates/nextjs/src/components/ParaProvider.tsx +116 -0
  325. package/templates/nextjs/src/components/layout/Header.tsx +44 -0
  326. package/templates/nextjs/src/components/ui/ConnectCard.tsx +24 -0
  327. package/templates/nextjs/src/components/ui/SignMessage.tsx +53 -0
  328. package/templates/nextjs/src/components/ui/WalletInfo.tsx +22 -0
  329. package/templates/nextjs/src/hooks/useSignHelloWorld.ts +23 -0
  330. package/templates/nextjs/src/styles/globals.css +1 -0
  331. package/templates/nextjs/tsconfig.json +27 -0
@@ -0,0 +1,185 @@
1
+ import { getGlobalOptions, createFormatter, helpText } from "../../../cli.js";
2
+ import { ensureAuthenticated } from "../../../auth/session-manager.js";
3
+ import { resolveConfig } from "../../../config/config-manager.js";
4
+ import { ParaApiClient } from "../../../api/client.js";
5
+ import { CliError } from "../../../core/error-handler.js";
6
+ import { OnRampProvider } from "../../../api/types.js";
7
+ import { text, confirm, p } from "../../../output/prompts.js";
8
+ import { resolveKeyId } from "./categories.js";
9
+ const VALID_PROVIDERS = Object.values(OnRampProvider);
10
+ const MIN_BUY_AMOUNT = 1e-4;
11
+ const MAX_BUY_AMOUNT = 999999;
12
+ function validateProviders(providers) {
13
+ for (const provider of providers) {
14
+ if (!VALID_PROVIDERS.includes(provider)) {
15
+ return `Invalid provider: "${provider}". Valid options: ${VALID_PROVIDERS.join(", ")}`;
16
+ }
17
+ }
18
+ if (providers.length === 0) {
19
+ return "At least one provider is required.";
20
+ }
21
+ return void 0;
22
+ }
23
+ function validateBuyAmount(value) {
24
+ const num = parseFloat(value);
25
+ if (isNaN(num)) {
26
+ return "Default buy amount must be a number.";
27
+ }
28
+ if (num < MIN_BUY_AMOUNT || num > MAX_BUY_AMOUNT) {
29
+ return `Default buy amount must be between ${MIN_BUY_AMOUNT} and ${MAX_BUY_AMOUNT}.`;
30
+ }
31
+ return void 0;
32
+ }
33
+ function registerRampsConfigCommand(parent) {
34
+ parent.command("ramps").description("Configure on/off ramp settings for an API key").argument("[key-id]", "API key ID (prompted if not given)").option("--buy-enabled", "Enable buy").option("--no-buy-enabled", "Disable buy").option("--receive-enabled", "Enable receive").option("--no-receive-enabled", "Disable receive").option("--withdraw-enabled", "Enable withdraw").option("--no-withdraw-enabled", "Disable withdraw").option("--providers <list>", `Comma-separated ordered provider list: ${VALID_PROVIDERS.join(", ")}`).option("--ramp-api-key <key>", "Ramp API key").option("--default-buy-amount <amount>", `Default buy amount (${MIN_BUY_AMOUNT}-${MAX_BUY_AMOUNT})`).option("--default-on-ramp-asset <asset>", "Default on-ramp asset").option("--default-on-ramp-network <network>", "Default on-ramp network").addHelpText(
35
+ "after",
36
+ helpText(`Examples:
37
+ $ para keys config ramps Interactive ramp settings
38
+ $ para keys config ramps --buy-enabled --no-withdraw-enabled
39
+ $ para keys config ramps --providers "STRIPE,MOONPAY" Set provider order
40
+ $ para keys config ramps --default-buy-amount 100 Set default buy amount`)
41
+ ).action(async (keyIdArg, cmdOpts, cmd) => {
42
+ const opts = await getGlobalOptions(cmd);
43
+ const formatter = createFormatter(opts);
44
+ const config = await resolveConfig(opts);
45
+ const session = await ensureAuthenticated(config.environment);
46
+ if (!config.organizationId || !config.projectId) {
47
+ throw new CliError(
48
+ "Organization and project required. Run `para orgs switch` and `para projects switch`, or pass --org and --project."
49
+ );
50
+ }
51
+ const client = new ParaApiClient({
52
+ environment: config.environment,
53
+ sessionId: session.sessionId
54
+ });
55
+ const { keyId, key } = await resolveKeyId(
56
+ client,
57
+ config.organizationId,
58
+ config.projectId,
59
+ config.environment,
60
+ keyIdArg
61
+ );
62
+ await runRampsAction(
63
+ client,
64
+ config.organizationId,
65
+ config.projectId,
66
+ config.environment,
67
+ keyId,
68
+ key,
69
+ formatter,
70
+ cmdOpts
71
+ );
72
+ });
73
+ }
74
+ function hasAnyFlag(flags) {
75
+ if (!flags) return false;
76
+ return Object.keys(flags).some((k) => flags[k] !== void 0);
77
+ }
78
+ async function runRampsAction(client, orgId, projectId, environment, keyId, currentKey, formatter, flags) {
79
+ const updates = {};
80
+ const isInteractive = !hasAnyFlag(flags);
81
+ if (flags?.buyEnabled !== void 0) {
82
+ updates.isBuyEnabled = flags.buyEnabled;
83
+ } else if (isInteractive) {
84
+ p.log.info(`Buy: ${currentKey.isBuyEnabled ? "enabled" : "disabled"}`);
85
+ updates.isBuyEnabled = await confirm("Enable buy?");
86
+ }
87
+ if (flags?.receiveEnabled !== void 0) {
88
+ updates.isReceiveEnabled = flags.receiveEnabled;
89
+ } else if (isInteractive) {
90
+ p.log.info(`Receive: ${currentKey.isReceiveEnabled ? "enabled" : "disabled"}`);
91
+ updates.isReceiveEnabled = await confirm("Enable receive?");
92
+ }
93
+ if (flags?.withdrawEnabled !== void 0) {
94
+ updates.isWithdrawEnabled = flags.withdrawEnabled;
95
+ } else if (isInteractive) {
96
+ p.log.info(`Withdraw: ${currentKey.isWithdrawEnabled ? "enabled" : "disabled"}`);
97
+ updates.isWithdrawEnabled = await confirm("Enable withdraw?");
98
+ }
99
+ if (flags?.providers !== void 0) {
100
+ const providers = flags.providers.split(",").map((s) => s.trim().toUpperCase()).filter(Boolean);
101
+ const err = validateProviders(providers);
102
+ if (err) throw new CliError(err);
103
+ updates.onRampProviders = providers;
104
+ } else if (isInteractive) {
105
+ const currentProviders = currentKey.onRampProviders ?? [];
106
+ p.log.info(`Current providers: ${currentProviders.length ? currentProviders.join(", ") : "(none)"}`);
107
+ const providersInput = await text("Providers (comma-separated, order matters):", {
108
+ placeholder: VALID_PROVIDERS.join(", "),
109
+ initialValue: currentProviders.join(", "),
110
+ validate: (v) => {
111
+ if (!v.trim()) return void 0;
112
+ const providers = v.split(",").map((s) => s.trim().toUpperCase()).filter(Boolean);
113
+ return validateProviders(providers);
114
+ }
115
+ });
116
+ if (providersInput.trim()) {
117
+ updates.onRampProviders = providersInput.split(",").map((s) => s.trim().toUpperCase()).filter(Boolean);
118
+ }
119
+ }
120
+ if (flags?.rampApiKey !== void 0) {
121
+ updates.rampApiKey = flags.rampApiKey;
122
+ } else if (isInteractive) {
123
+ p.log.info(`Ramp API key: ${currentKey.rampApiKey ? "(set)" : "(not set)"}`);
124
+ const rampKey = await text("Ramp API key (empty to skip):", {
125
+ placeholder: "ramp_..."
126
+ });
127
+ if (rampKey.trim()) {
128
+ updates.rampApiKey = rampKey.trim();
129
+ }
130
+ }
131
+ if (flags?.defaultBuyAmount !== void 0) {
132
+ const err = validateBuyAmount(flags.defaultBuyAmount);
133
+ if (err) throw new CliError(err);
134
+ updates.defaultBuyAmount = flags.defaultBuyAmount;
135
+ } else if (isInteractive) {
136
+ p.log.info(`Default buy amount: ${currentKey.defaultBuyAmount ?? "(not set)"}`);
137
+ const amount = await text("Default buy amount (empty to skip):", {
138
+ placeholder: "100",
139
+ initialValue: currentKey.defaultBuyAmount ?? "",
140
+ validate: (v) => {
141
+ if (v.trim()) return validateBuyAmount(v.trim());
142
+ }
143
+ });
144
+ if (amount.trim()) {
145
+ updates.defaultBuyAmount = amount.trim();
146
+ }
147
+ }
148
+ if (flags?.defaultOnRampAsset !== void 0) {
149
+ updates.defaultOnRampAsset = flags.defaultOnRampAsset;
150
+ } else if (isInteractive) {
151
+ p.log.info(`Default on-ramp asset: ${currentKey.defaultOnRampAsset ?? "(not set)"}`);
152
+ const asset = await text("Default on-ramp asset (empty to skip):", {
153
+ placeholder: "ETH",
154
+ initialValue: currentKey.defaultOnRampAsset ?? ""
155
+ });
156
+ if (asset.trim()) {
157
+ updates.defaultOnRampAsset = asset.trim();
158
+ }
159
+ }
160
+ if (flags?.defaultOnRampNetwork !== void 0) {
161
+ updates.defaultOnRampNetwork = flags.defaultOnRampNetwork;
162
+ } else if (isInteractive) {
163
+ p.log.info(`Default on-ramp network: ${currentKey.defaultOnRampNetwork ?? "(not set)"}`);
164
+ const network = await text("Default on-ramp network (empty to skip):", {
165
+ placeholder: "ethereum",
166
+ initialValue: currentKey.defaultOnRampNetwork ?? ""
167
+ });
168
+ if (network.trim()) {
169
+ updates.defaultOnRampNetwork = network.trim();
170
+ }
171
+ }
172
+ if (Object.keys(updates).length === 0) {
173
+ formatter.info("No changes made.");
174
+ formatter.flush();
175
+ return;
176
+ }
177
+ await client.updateApiKey(orgId, projectId, environment, keyId, updates);
178
+ formatter.json({ keyId, updated: updates });
179
+ formatter.success("Updated ramp settings.");
180
+ formatter.flush();
181
+ }
182
+ export {
183
+ registerRampsConfigCommand,
184
+ runRampsAction
185
+ };
@@ -0,0 +1,15 @@
1
+ import type { Command } from 'commander';
2
+ import { ParaApiClient } from '../../../api/client.js';
3
+ import type { ApiKey } from '../../../api/types.js';
4
+ import type { OutputFormatter } from '../../../output/formatter.js';
5
+ interface SecurityFlags {
6
+ origins?: string;
7
+ authMethods?: string;
8
+ sessionLength?: string;
9
+ transactionPopups?: boolean;
10
+ ipAllowlist?: string;
11
+ }
12
+ export declare function registerSecurityConfigCommand(parent: Command): void;
13
+ export declare function runSecurityAction(client: ParaApiClient, orgId: string, projectId: string, environment: string, keyId: string, currentKey: ApiKey, formatter: OutputFormatter, flags?: SecurityFlags): Promise<void>;
14
+ export {};
15
+ //# sourceMappingURL=security.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../../../src/commands/keys/config/security.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIzC,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAEvD,OAAO,KAAK,EAAE,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAElE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAgBpE,UAAU,aAAa;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAyDnE;AAcD,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,eAAe,EAC1B,KAAK,CAAC,EAAE,aAAa,GACpB,OAAO,CAAC,IAAI,CAAC,CAsLf"}
@@ -0,0 +1,212 @@
1
+ import { getGlobalOptions, createFormatter, helpText } from "../../../cli.js";
2
+ import { ensureAuthenticated } from "../../../auth/session-manager.js";
3
+ import { resolveConfig } from "../../../config/config-manager.js";
4
+ import { ParaApiClient } from "../../../api/client.js";
5
+ import { CliError } from "../../../core/error-handler.js";
6
+ import { AuthMethod } from "../../../api/types.js";
7
+ import { text, multiselect, select, confirm, p } from "../../../output/prompts.js";
8
+ import { resolveKeyId } from "./categories.js";
9
+ import {
10
+ validateOriginUrl,
11
+ validateAuthMethods,
12
+ AUTH_METHOD_DISPLAY_VALUES,
13
+ validateSessionLength,
14
+ minutesToMs,
15
+ msToMinutes,
16
+ SESSION_PRESETS,
17
+ MIN_SESSION_MINUTES,
18
+ MAX_SESSION_MINUTES,
19
+ validateCidrList
20
+ } from "../../../validation/index.js";
21
+ function registerSecurityConfigCommand(parent) {
22
+ parent.command("security").description("Configure security settings for an API key").argument("[key-id]", "API key ID (prompted if not given)").option("--origins <urls>", "Comma-separated allowed origins (empty string to clear)").option("--auth-methods <methods>", "Comma-separated auth methods: PASSKEY, PASSWORD, PIN (empty to reset)").option("--session-length <minutes>", "Session length in minutes (5-43200)").option("--transaction-popups", "Enable transaction popups").option("--no-transaction-popups", "Disable transaction popups").option("--ip-allowlist <cidrs>", "Comma-separated CIDR blocks (empty string to clear)").addHelpText(
23
+ "after",
24
+ helpText(`Examples:
25
+ $ para keys config security Interactive security settings
26
+ $ para keys config security abc-123 --origins "https://example.com" Set allowed origins
27
+ $ para keys config security --auth-methods "PASSKEY,PIN" Set auth methods
28
+ $ para keys config security --session-length 1440 Set session to 24 hours
29
+ $ para keys config security --ip-allowlist "10.0.0.0/8" Set IP allowlist
30
+ $ para keys config security --ip-allowlist "" Clear IP allowlist`)
31
+ ).action(async (keyIdArg, cmdOpts, cmd) => {
32
+ const opts = await getGlobalOptions(cmd);
33
+ const formatter = createFormatter(opts);
34
+ const config = await resolveConfig(opts);
35
+ const session = await ensureAuthenticated(config.environment);
36
+ if (!config.organizationId || !config.projectId) {
37
+ throw new CliError(
38
+ "Organization and project required. Run `para orgs switch` and `para projects switch`, or pass --org and --project."
39
+ );
40
+ }
41
+ const client = new ParaApiClient({
42
+ environment: config.environment,
43
+ sessionId: session.sessionId
44
+ });
45
+ const { keyId, key } = await resolveKeyId(
46
+ client,
47
+ config.organizationId,
48
+ config.projectId,
49
+ config.environment,
50
+ keyIdArg
51
+ );
52
+ await runSecurityAction(
53
+ client,
54
+ config.organizationId,
55
+ config.projectId,
56
+ config.environment,
57
+ keyId,
58
+ key,
59
+ formatter,
60
+ cmdOpts
61
+ );
62
+ });
63
+ }
64
+ function hasAnyFlag(flags) {
65
+ if (!flags) return false;
66
+ return flags.origins !== void 0 || flags.authMethods !== void 0 || flags.sessionLength !== void 0 || flags.ipAllowlist !== void 0;
67
+ }
68
+ async function runSecurityAction(client, orgId, projectId, environment, keyId, currentKey, formatter, flags) {
69
+ const updates = {};
70
+ let ipUpdates;
71
+ const isInteractive = !hasAnyFlag(flags) && flags?.transactionPopups === void 0;
72
+ if (flags?.origins !== void 0) {
73
+ if (flags.origins === "") {
74
+ updates.origins = [];
75
+ } else {
76
+ const origins = flags.origins.split(",").map((s) => s.trim()).filter(Boolean);
77
+ for (const origin of origins) {
78
+ const err = validateOriginUrl(origin);
79
+ if (err) throw new CliError(`Invalid origin "${origin}": ${err}`);
80
+ }
81
+ updates.origins = origins;
82
+ }
83
+ } else if (isInteractive) {
84
+ p.log.info(`Current origins: ${currentKey.origins?.length ? currentKey.origins.join(", ") : "(none)"}`);
85
+ const originsInput = await text("Allowed origins (comma-separated, empty to skip):", {
86
+ placeholder: "https://example.com, https://app.example.com",
87
+ initialValue: currentKey.origins?.join(", ") ?? ""
88
+ });
89
+ if (originsInput.trim()) {
90
+ const origins = originsInput.split(",").map((s) => s.trim()).filter(Boolean);
91
+ for (const origin of origins) {
92
+ const err = validateOriginUrl(origin);
93
+ if (err) throw new CliError(`Invalid origin "${origin}": ${err}`);
94
+ }
95
+ updates.origins = origins;
96
+ }
97
+ }
98
+ if (flags?.authMethods !== void 0) {
99
+ if (flags.authMethods === "") {
100
+ updates.supportedAuthMethods = [AuthMethod.BASIC_LOGIN];
101
+ } else {
102
+ const methods = flags.authMethods.split(",").map((s) => s.trim().toUpperCase()).filter(Boolean);
103
+ const err = validateAuthMethods(methods);
104
+ if (err) throw new CliError(err);
105
+ updates.supportedAuthMethods = methods;
106
+ }
107
+ } else if (isInteractive) {
108
+ const currentMethods = (currentKey.supportedAuthMethods ?? []).filter((m) => m !== AuthMethod.BASIC_LOGIN);
109
+ p.log.info(`Current auth methods: ${currentMethods.length ? currentMethods.join(", ") : "(basic only)"}`);
110
+ const selected = await multiselect(
111
+ "Authentication methods:",
112
+ AUTH_METHOD_DISPLAY_VALUES.map((m) => ({
113
+ value: m,
114
+ label: m,
115
+ hint: m === AuthMethod.PASSKEY ? "Biometric / device passkey" : m === AuthMethod.PASSWORD ? "Email + password" : "Numeric PIN"
116
+ })),
117
+ { initialValues: currentMethods }
118
+ );
119
+ if (selected.length > 0) {
120
+ const err = validateAuthMethods(selected);
121
+ if (err) throw new CliError(err);
122
+ updates.supportedAuthMethods = selected;
123
+ }
124
+ }
125
+ if (flags?.sessionLength !== void 0) {
126
+ const minutes = parseInt(flags.sessionLength, 10);
127
+ const err = validateSessionLength(minutes);
128
+ if (err) throw new CliError(err);
129
+ updates.sessionMaxAge = minutesToMs(minutes);
130
+ } else if (isInteractive) {
131
+ const currentMinutes = currentKey.sessionMaxAge ? msToMinutes(currentKey.sessionMaxAge) : void 0;
132
+ p.log.info(`Current session length: ${currentMinutes ? `${currentMinutes} minutes` : "(default)"}`);
133
+ const presetOptions = SESSION_PRESETS.map((m) => ({
134
+ value: String(m),
135
+ label: `${m} minutes${m === 120 ? " (2 hours)" : m === 1440 ? " (1 day)" : m === 10080 ? " (7 days)" : " (30 days)"}`
136
+ }));
137
+ const choice = await select("Session length:", [
138
+ ...presetOptions,
139
+ { value: "custom", label: "Custom value" },
140
+ { value: "skip", label: "Skip (keep current)" }
141
+ ]);
142
+ if (choice !== "skip") {
143
+ let minutes;
144
+ if (choice === "custom") {
145
+ const input = await text(`Session length in minutes (${MIN_SESSION_MINUTES}-${MAX_SESSION_MINUTES}):`, {
146
+ placeholder: "1440",
147
+ validate: (v) => {
148
+ const n = parseInt(v, 10);
149
+ if (isNaN(n)) return "Must be a number.";
150
+ return validateSessionLength(n);
151
+ }
152
+ });
153
+ minutes = parseInt(input, 10);
154
+ } else {
155
+ minutes = parseInt(choice, 10);
156
+ }
157
+ updates.sessionMaxAge = minutesToMs(minutes);
158
+ }
159
+ }
160
+ if (flags?.transactionPopups !== void 0) {
161
+ updates.forceTransactionPopups = flags.transactionPopups;
162
+ } else if (isInteractive) {
163
+ p.log.info(`Transaction popups: ${currentKey.forceTransactionPopups ? "enabled" : "disabled"}`);
164
+ const enabled = await confirm("Enable transaction popups?");
165
+ updates.forceTransactionPopups = enabled;
166
+ }
167
+ if (flags?.ipAllowlist !== void 0) {
168
+ if (flags.ipAllowlist === "") {
169
+ ipUpdates = [];
170
+ } else {
171
+ const cidrs = flags.ipAllowlist.split(",").map((s) => s.trim()).filter(Boolean);
172
+ const err = validateCidrList(cidrs);
173
+ if (err) throw new CliError(err);
174
+ ipUpdates = cidrs;
175
+ }
176
+ } else if (isInteractive) {
177
+ const currentCidrs = currentKey.ipAllowlistCidrs ?? [];
178
+ p.log.info(`Current IP allowlist: ${currentCidrs.length ? currentCidrs.join(", ") : "(none \u2014 all IPs allowed)"}`);
179
+ const cidrsInput = await text("IP allowlist CIDR blocks (comma-separated, empty to skip):", {
180
+ placeholder: "10.0.0.0/8, 192.168.1.0/24",
181
+ initialValue: currentCidrs.join(", "),
182
+ validate: (v) => {
183
+ if (!v.trim()) return void 0;
184
+ const cidrs = v.split(",").map((s) => s.trim()).filter(Boolean);
185
+ return validateCidrList(cidrs);
186
+ }
187
+ });
188
+ if (cidrsInput.trim()) {
189
+ ipUpdates = cidrsInput.split(",").map((s) => s.trim()).filter(Boolean);
190
+ }
191
+ }
192
+ const hasKeyUpdates = Object.keys(updates).length > 0;
193
+ const hasIpUpdates = ipUpdates !== void 0;
194
+ if (!hasKeyUpdates && !hasIpUpdates) {
195
+ formatter.info("No changes made.");
196
+ formatter.flush();
197
+ return;
198
+ }
199
+ if (hasKeyUpdates) {
200
+ await client.updateApiKey(orgId, projectId, environment, keyId, updates);
201
+ }
202
+ if (hasIpUpdates) {
203
+ await client.updateIpAllowlist(orgId, projectId, environment, keyId, ipUpdates);
204
+ }
205
+ formatter.json({ keyId, updated: { ...updates, ...hasIpUpdates ? { ipAllowlistCidrs: ipUpdates } : {} } });
206
+ formatter.success("Updated security settings.");
207
+ formatter.flush();
208
+ }
209
+ export {
210
+ registerSecurityConfigCommand,
211
+ runSecurityAction
212
+ };
@@ -0,0 +1,16 @@
1
+ import type { Command } from 'commander';
2
+ import { ParaApiClient } from '../../../api/client.js';
3
+ import type { ApiKey } from '../../../api/types.js';
4
+ import type { OutputFormatter } from '../../../output/formatter.js';
5
+ interface SetupFlags {
6
+ walletTypes?: string;
7
+ cosmosPrefix?: string;
8
+ teamId?: string;
9
+ bundleId?: string;
10
+ androidPackage?: string;
11
+ androidFingerprints?: string;
12
+ }
13
+ export declare function registerSetupConfigCommand(parent: Command): void;
14
+ export declare function runSetupAction(client: ParaApiClient, orgId: string, projectId: string, environment: string, keyId: string, currentKey: ApiKey, formatter: OutputFormatter, flags?: SetupFlags): Promise<void>;
15
+ export {};
16
+ //# sourceMappingURL=setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../../src/commands/keys/config/setup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIzC,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAEvD,OAAO,KAAK,EAAE,MAAM,EAAkC,MAAM,uBAAuB,CAAC;AAEpF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAapE,UAAU,UAAU;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAcD,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAuDhE;AAOD,wBAAsB,cAAc,CAClC,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,eAAe,EAC1B,KAAK,CAAC,EAAE,UAAU,GACjB,OAAO,CAAC,IAAI,CAAC,CA6Lf"}
@@ -0,0 +1,235 @@
1
+ import { getGlobalOptions, createFormatter, helpText } from "../../../cli.js";
2
+ import { ensureAuthenticated } from "../../../auth/session-manager.js";
3
+ import { resolveConfig } from "../../../config/config-manager.js";
4
+ import { ParaApiClient } from "../../../api/client.js";
5
+ import { CliError } from "../../../core/error-handler.js";
6
+ import { WalletType } from "../../../api/types.js";
7
+ import { text, multiselect, confirm, p } from "../../../output/prompts.js";
8
+ import { resolveKeyId } from "./categories.js";
9
+ import {
10
+ validateWalletTypes,
11
+ WALLET_TYPE_VALUES,
12
+ validateCosmosPrefix,
13
+ validateTeamId,
14
+ validateBundleIdentifier,
15
+ validateAndroidPackageName,
16
+ validateAndroidFingerprint
17
+ } from "../../../validation/index.js";
18
+ function parseWalletTypesFlag(input) {
19
+ return input.split(",").map((s) => {
20
+ const trimmed = s.trim();
21
+ const optional = trimmed.startsWith("~");
22
+ const type = optional ? trimmed.slice(1) : trimmed;
23
+ return { type, optional };
24
+ }).filter((c) => c.type);
25
+ }
26
+ function registerSetupConfigCommand(parent) {
27
+ parent.command("setup").description("Configure wallet types and native passkey settings").argument("[key-id]", "API key ID (prompted if not given)").option("--wallet-types <types>", 'Comma-separated wallet types, ~ prefix for optional: "EVM,~SOLANA,~COSMOS"').option("--cosmos-prefix <prefix>", "Cosmos address prefix").option("--team-id <id>", "Apple Team ID (10 chars, or empty to clear)").option("--bundle-id <id>", "Apple bundle identifier").option("--android-package <name>", "Android package name").option("--android-fingerprints <fps>", "Comma-separated SHA256 fingerprints").addHelpText(
28
+ "after",
29
+ helpText(`Examples:
30
+ $ para keys config setup Interactive setup
31
+ $ para keys config setup --wallet-types "EVM,~SOLANA" Set wallet types (SOLANA optional)
32
+ $ para keys config setup --team-id "ABCDE12345" Set Apple Team ID
33
+ $ para keys config setup --android-package "com.example.app" Set Android package name`)
34
+ ).action(async (keyIdArg, cmdOpts, cmd) => {
35
+ const opts = await getGlobalOptions(cmd);
36
+ const formatter = createFormatter(opts);
37
+ const config = await resolveConfig(opts);
38
+ const session = await ensureAuthenticated(config.environment);
39
+ if (!config.organizationId || !config.projectId) {
40
+ throw new CliError(
41
+ "Organization and project required. Run `para orgs switch` and `para projects switch`, or pass --org and --project."
42
+ );
43
+ }
44
+ const client = new ParaApiClient({
45
+ environment: config.environment,
46
+ sessionId: session.sessionId
47
+ });
48
+ const { keyId, key } = await resolveKeyId(
49
+ client,
50
+ config.organizationId,
51
+ config.projectId,
52
+ config.environment,
53
+ keyIdArg
54
+ );
55
+ await runSetupAction(
56
+ client,
57
+ config.organizationId,
58
+ config.projectId,
59
+ config.environment,
60
+ keyId,
61
+ key,
62
+ formatter,
63
+ cmdOpts
64
+ );
65
+ });
66
+ }
67
+ function hasAnyFlag(flags) {
68
+ if (!flags) return false;
69
+ return Object.keys(flags).some((k) => flags[k] !== void 0);
70
+ }
71
+ async function runSetupAction(client, orgId, projectId, environment, keyId, currentKey, formatter, flags) {
72
+ const updates = {};
73
+ const isInteractive = !hasAnyFlag(flags);
74
+ if (flags?.walletTypes !== void 0) {
75
+ const types = parseWalletTypesFlag(flags.walletTypes);
76
+ const err = validateWalletTypes(types);
77
+ if (err) throw new CliError(err);
78
+ updates.supportedWalletTypes = types;
79
+ } else if (isInteractive) {
80
+ const currentTypes = currentKey.supportedWalletTypes ?? [];
81
+ const display = currentTypes.map((t) => `${t.type}${t.optional ? " (optional)" : ""}`).join(", ") || "(none)";
82
+ p.log.info(`Current wallet types: ${display}`);
83
+ const selectedTypes = await multiselect(
84
+ "Required wallet types:",
85
+ WALLET_TYPE_VALUES.map((t) => ({
86
+ value: t,
87
+ label: t,
88
+ hint: t === WalletType.EVM ? "Ethereum & EVM chains" : t === WalletType.SOLANA ? "Solana" : "Cosmos ecosystem"
89
+ })),
90
+ {
91
+ required: true,
92
+ initialValues: currentTypes.filter((t) => !t.optional).map((t) => t.type)
93
+ }
94
+ );
95
+ const remainingTypes = WALLET_TYPE_VALUES.filter((t) => !selectedTypes.includes(t));
96
+ let optionalTypes = [];
97
+ if (remainingTypes.length > 0) {
98
+ optionalTypes = await multiselect(
99
+ "Optional wallet types (users can opt in):",
100
+ remainingTypes.map((t) => ({
101
+ value: t,
102
+ label: t,
103
+ hint: "Optional for users"
104
+ })),
105
+ {
106
+ initialValues: currentTypes.filter((t) => t.optional).map((t) => t.type)
107
+ }
108
+ );
109
+ }
110
+ const walletConfigs = [
111
+ ...selectedTypes.map((t) => ({ type: t })),
112
+ ...optionalTypes.map((t) => ({ type: t, optional: true }))
113
+ ];
114
+ const err = validateWalletTypes(walletConfigs);
115
+ if (err) throw new CliError(err);
116
+ updates.supportedWalletTypes = walletConfigs;
117
+ }
118
+ if (flags?.cosmosPrefix !== void 0) {
119
+ const err = validateCosmosPrefix(flags.cosmosPrefix);
120
+ if (err) throw new CliError(err);
121
+ updates.cosmosPrefix = flags.cosmosPrefix;
122
+ } else if (isInteractive) {
123
+ p.log.info(`Current cosmos prefix: ${currentKey.cosmosPrefix ?? "(default)"}`);
124
+ const prefix = await text("Cosmos address prefix (empty to skip):", {
125
+ placeholder: "cosmos",
126
+ initialValue: currentKey.cosmosPrefix ?? "",
127
+ validate: (v) => {
128
+ if (v.trim()) return validateCosmosPrefix(v.trim());
129
+ return void 0;
130
+ }
131
+ });
132
+ if (prefix.trim()) {
133
+ updates.cosmosPrefix = prefix.trim();
134
+ }
135
+ }
136
+ if (flags?.teamId !== void 0) {
137
+ if (flags.teamId === "") {
138
+ updates.teamId = null;
139
+ } else {
140
+ const err = validateTeamId(flags.teamId);
141
+ if (err) throw new CliError(err);
142
+ updates.teamId = flags.teamId;
143
+ }
144
+ } else if (isInteractive) {
145
+ p.log.info(`Current Apple Team ID: ${currentKey.teamId ?? "(not set)"}`);
146
+ const configureApple = await confirm("Configure Apple native passkey settings?");
147
+ if (configureApple) {
148
+ const teamId = await text("Apple Team ID (10 characters, empty to clear):", {
149
+ placeholder: "ABCDE12345",
150
+ initialValue: currentKey.teamId ?? "",
151
+ validate: (v) => {
152
+ if (v.trim()) return validateTeamId(v.trim());
153
+ }
154
+ });
155
+ if (teamId.trim()) {
156
+ updates.teamId = teamId.trim();
157
+ } else {
158
+ updates.teamId = null;
159
+ }
160
+ const bundleId = await text("Apple bundle identifier (empty to skip):", {
161
+ placeholder: "com.example.app",
162
+ initialValue: currentKey.bundleIdentifier ?? "",
163
+ validate: (v) => {
164
+ if (v.trim()) return validateBundleIdentifier(v.trim());
165
+ }
166
+ });
167
+ if (bundleId.trim()) {
168
+ updates.bundleIdentifier = bundleId.trim();
169
+ }
170
+ }
171
+ }
172
+ if (flags?.bundleId !== void 0) {
173
+ const err = validateBundleIdentifier(flags.bundleId);
174
+ if (err) throw new CliError(err);
175
+ updates.bundleIdentifier = flags.bundleId;
176
+ }
177
+ if (flags?.androidPackage !== void 0) {
178
+ const err = validateAndroidPackageName(flags.androidPackage);
179
+ if (err) throw new CliError(err);
180
+ updates.androidPackageName = flags.androidPackage;
181
+ }
182
+ if (flags?.androidFingerprints !== void 0) {
183
+ const fps = flags.androidFingerprints.split(",").map((s) => s.trim()).filter(Boolean);
184
+ for (const fp of fps) {
185
+ const err = validateAndroidFingerprint(fp);
186
+ if (err) throw new CliError(err);
187
+ }
188
+ updates.androidSha256CertFingerprints = fps;
189
+ }
190
+ if (isInteractive && flags?.androidPackage === void 0 && flags?.androidFingerprints === void 0) {
191
+ p.log.info(`Current Android package: ${currentKey.androidPackageName ?? "(not set)"}`);
192
+ const configureAndroid = await confirm("Configure Android native passkey settings?");
193
+ if (configureAndroid) {
194
+ const pkg = await text("Android package name (empty to skip):", {
195
+ placeholder: "com.example.app",
196
+ initialValue: currentKey.androidPackageName ?? "",
197
+ validate: (v) => {
198
+ if (v.trim()) return validateAndroidPackageName(v.trim());
199
+ }
200
+ });
201
+ if (pkg.trim()) {
202
+ updates.androidPackageName = pkg.trim();
203
+ }
204
+ const currentFps = currentKey.androidSha256CertFingerprints ?? [];
205
+ const fpsInput = await text("SHA256 fingerprints (comma-separated, empty to skip):", {
206
+ placeholder: "AA:BB:CC:...",
207
+ initialValue: currentFps.join(", "),
208
+ validate: (v) => {
209
+ if (!v.trim()) return void 0;
210
+ const fps = v.split(",").map((s) => s.trim()).filter(Boolean);
211
+ for (const fp of fps) {
212
+ const err = validateAndroidFingerprint(fp);
213
+ if (err) return err;
214
+ }
215
+ }
216
+ });
217
+ if (fpsInput.trim()) {
218
+ updates.androidSha256CertFingerprints = fpsInput.split(",").map((s) => s.trim()).filter(Boolean);
219
+ }
220
+ }
221
+ }
222
+ if (Object.keys(updates).length === 0) {
223
+ formatter.info("No changes made.");
224
+ formatter.flush();
225
+ return;
226
+ }
227
+ await client.updateApiKey(orgId, projectId, environment, keyId, updates);
228
+ formatter.json({ keyId, updated: updates });
229
+ formatter.success("Updated setup settings.");
230
+ formatter.flush();
231
+ }
232
+ export {
233
+ registerSetupConfigCommand,
234
+ runSetupAction
235
+ };