@layr-labs/ecloud-sdk 0.0.1-dev-rfc.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.
@@ -0,0 +1,566 @@
1
+ import { Address, Hex } from 'viem';
2
+
3
+ /**
4
+ * Core types for ECloud SDK
5
+ */
6
+
7
+ type AppId = Address;
8
+ type logVisibility = "public" | "private" | "off";
9
+ interface DeployAppOpts {
10
+ name?: string;
11
+ dockerfile?: string;
12
+ envFile?: string;
13
+ imageRef?: string;
14
+ instanceType?: string;
15
+ logVisibility?: logVisibility;
16
+ }
17
+ interface UpgradeAppOpts {
18
+ /** Path to Dockerfile (if building from Dockerfile) */
19
+ dockerfile?: string;
20
+ /** Image reference (registry/path:tag) - optional, will prompt if not provided */
21
+ imageRef?: string;
22
+ /** Path to .env file - optional, will use .env if exists or prompt */
23
+ envFile?: string;
24
+ /** Instance type - optional, will prompt if not provided */
25
+ instanceType?: string;
26
+ /** Log visibility setting - optional, will prompt if not provided */
27
+ logVisibility?: logVisibility;
28
+ gas?: {
29
+ maxFeePerGas?: bigint;
30
+ maxPriorityFeePerGas?: bigint;
31
+ };
32
+ }
33
+ interface LifecycleOpts {
34
+ gas?: {
35
+ maxFeePerGas?: bigint;
36
+ maxPriorityFeePerGas?: bigint;
37
+ };
38
+ force?: boolean;
39
+ }
40
+ interface AppRecord {
41
+ id: AppId;
42
+ owner: `0x${string}`;
43
+ image: string;
44
+ status: "starting" | "running" | "stopped" | "terminated";
45
+ createdAt: number;
46
+ lastUpdatedAt: number;
47
+ }
48
+ interface DeployOptions {
49
+ /** Private key for signing transactions (hex string with or without 0x prefix) - optional, will prompt if not provided */
50
+ privateKey?: string;
51
+ /** RPC URL for blockchain connection - optional, uses environment default if not provided */
52
+ rpcUrl?: string;
53
+ /** Environment name (e.g., 'sepolia', 'mainnet-alpha') - optional, defaults to 'sepolia' */
54
+ environment?: string;
55
+ /** Path to Dockerfile (if building from Dockerfile) */
56
+ dockerfilePath?: string;
57
+ /** Image reference (registry/path:tag) - optional, will prompt if not provided */
58
+ imageRef?: string;
59
+ /** Path to .env file - optional, will use .env if exists or prompt */
60
+ envFilePath?: string;
61
+ /** App name - optional, will prompt if not provided */
62
+ appName?: string;
63
+ /** Instance type - optional, will prompt if not provided */
64
+ instanceType?: string;
65
+ /** Log visibility setting - optional, will prompt if not provided */
66
+ logVisibility?: logVisibility;
67
+ }
68
+ interface DeployResult {
69
+ /** App ID (contract address) */
70
+ appID: string;
71
+ /** App name */
72
+ appName: string;
73
+ /** Final image reference */
74
+ imageRef: string;
75
+ /** IP address (if available) */
76
+ ipAddress?: string;
77
+ /** Transaction hash */
78
+ txHash: `0x${string}`;
79
+ }
80
+ interface EnvironmentConfig {
81
+ name: string;
82
+ build: "dev" | "prod";
83
+ chainID: bigint;
84
+ appControllerAddress: string;
85
+ permissionControllerAddress: string;
86
+ erc7702DelegatorAddress: string;
87
+ kmsServerURL: string;
88
+ userApiServerURL: string;
89
+ defaultRPCURL: string;
90
+ }
91
+ interface Release {
92
+ rmsRelease: {
93
+ artifacts: Array<{
94
+ digest: Uint8Array;
95
+ registry: string;
96
+ }>;
97
+ upgradeByTime: number;
98
+ };
99
+ publicEnv: Uint8Array;
100
+ encryptedEnv: Uint8Array;
101
+ }
102
+ interface ParsedEnvironment {
103
+ public: Record<string, string>;
104
+ private: Record<string, string>;
105
+ }
106
+ interface ImageDigestResult {
107
+ digest: Uint8Array;
108
+ registry: string;
109
+ platform: string;
110
+ }
111
+ interface DockerImageConfig {
112
+ cmd: string[];
113
+ entrypoint: string[];
114
+ user: string;
115
+ labels: Record<string, string>;
116
+ }
117
+ interface Logger {
118
+ debug(message: string, ...args: any[]): void;
119
+ info(message: string, ...args: any[]): void;
120
+ warn(message: string, ...args: any[]): void;
121
+ error(message: string, ...args: any[]): void;
122
+ }
123
+ /**
124
+ * Profile information for an app
125
+ */
126
+ interface AppProfile {
127
+ /** App name (required) */
128
+ name: string;
129
+ /** Website URL (optional) */
130
+ website?: string;
131
+ /** Description (optional) */
132
+ description?: string;
133
+ /** X (Twitter) URL (optional) */
134
+ xURL?: string;
135
+ /** Path to image file (optional) */
136
+ imagePath?: string;
137
+ }
138
+ /**
139
+ * Profile response from API
140
+ */
141
+ interface AppProfileResponse {
142
+ name: string;
143
+ website?: string;
144
+ description?: string;
145
+ xURL?: string;
146
+ imageURL?: string;
147
+ }
148
+ type ProductID = "compute";
149
+ type ChainID = "ethereum-mainnet" | "ethereum-sepolia";
150
+ type SubscriptionStatus = "incomplete" | "incomplete_expired" | "trialing" | "active" | "past_due" | "canceled" | "unpaid" | "paused" | "inactive";
151
+ interface SubscriptionLineItem {
152
+ description: string;
153
+ price: number;
154
+ quantity: number;
155
+ currency: string;
156
+ subtotal: number;
157
+ }
158
+ interface CreateSubscriptionResponse {
159
+ checkoutUrl: string;
160
+ }
161
+ interface CheckoutCreatedResponse {
162
+ type: "checkout_created";
163
+ checkoutUrl: string;
164
+ }
165
+ interface AlreadyActiveResponse {
166
+ type: "already_active";
167
+ status: SubscriptionStatus;
168
+ }
169
+ interface PaymentIssueResponse {
170
+ type: "payment_issue";
171
+ status: SubscriptionStatus;
172
+ portalUrl?: string;
173
+ }
174
+ type SubscribeResponse = CheckoutCreatedResponse | AlreadyActiveResponse | PaymentIssueResponse;
175
+ interface CancelSuccessResponse {
176
+ type: "canceled";
177
+ }
178
+ interface NoActiveSubscriptionResponse {
179
+ type: "no_active_subscription";
180
+ status: SubscriptionStatus;
181
+ }
182
+ type CancelResponse = CancelSuccessResponse | NoActiveSubscriptionResponse;
183
+ interface ProductSubscriptionResponse {
184
+ productId: ProductID;
185
+ subscriptionStatus: SubscriptionStatus;
186
+ currentPeriodStart?: string;
187
+ currentPeriodEnd?: string;
188
+ lineItems?: SubscriptionLineItem[];
189
+ upcomingInvoiceSubtotal?: number;
190
+ upcomingInvoiceTotal?: number;
191
+ creditsApplied?: number;
192
+ remainingCredits?: number;
193
+ nextCreditExpiry?: number;
194
+ cancelAtPeriodEnd?: boolean;
195
+ canceledAt?: string;
196
+ portalUrl?: string;
197
+ }
198
+ interface SubscriptionOpts {
199
+ productId?: ProductID;
200
+ }
201
+ interface BillingEnvironmentConfig {
202
+ billingApiServerURL: string;
203
+ }
204
+ interface BillingEnvironmentConfig {
205
+ billingApiServerURL: string;
206
+ }
207
+
208
+ /**
209
+ * Create command
210
+ *
211
+ * Creates a new app project from a template
212
+ */
213
+
214
+ interface CreateAppOpts {
215
+ name?: string;
216
+ language?: string;
217
+ template?: string;
218
+ templateVersion?: string;
219
+ verbose?: boolean;
220
+ }
221
+ /**
222
+ * Create a new app project from template
223
+ */
224
+ declare function createApp(options: CreateAppOpts, logger?: Logger): Promise<void>;
225
+
226
+ /**
227
+ * Logs command
228
+ *
229
+ * View app logs with optional watch mode
230
+ */
231
+
232
+ interface LogsOptions {
233
+ appID?: string | Address;
234
+ watch?: boolean;
235
+ environment?: string;
236
+ privateKey?: string;
237
+ rpcUrl?: string;
238
+ }
239
+ /**
240
+ * View app logs
241
+ */
242
+ declare function logs(options: LogsOptions, logger?: Logger): Promise<void>;
243
+
244
+ /**
245
+ * Main App namespace entry point
246
+ */
247
+
248
+ interface AppModule {
249
+ create: (opts: CreateAppOpts) => Promise<void>;
250
+ deploy: (opts: DeployAppOpts) => Promise<{
251
+ appID: AppId;
252
+ tx: `0x${string}`;
253
+ appName: string;
254
+ imageRef: string;
255
+ ipAddress?: string;
256
+ }>;
257
+ upgrade: (appID: AppId, opts: UpgradeAppOpts) => Promise<{
258
+ tx: `0x${string}`;
259
+ appID: string;
260
+ imageRef: string;
261
+ }>;
262
+ logs: (opts: LogsOptions) => Promise<void>;
263
+ start: (appId: AppId, opts?: LifecycleOpts) => Promise<{
264
+ tx: `0x${string}` | false;
265
+ }>;
266
+ stop: (appId: AppId, opts?: LifecycleOpts) => Promise<{
267
+ tx: `0x${string}` | false;
268
+ }>;
269
+ terminate: (appId: AppId, opts?: LifecycleOpts) => Promise<{
270
+ tx: `0x${string}` | false;
271
+ }>;
272
+ }
273
+ interface AppModuleConfig {
274
+ verbose?: boolean;
275
+ privateKey: `0x${string}`;
276
+ rpcUrl: string;
277
+ environment: string;
278
+ }
279
+ declare function createAppModule(ctx: AppModuleConfig): AppModule;
280
+
281
+ /**
282
+ * Main Billing namespace entry point
283
+ */
284
+
285
+ interface BillingModule {
286
+ subscribe: (opts?: SubscriptionOpts) => Promise<SubscribeResponse>;
287
+ getStatus: (opts?: SubscriptionOpts) => Promise<ProductSubscriptionResponse>;
288
+ cancel: (opts?: SubscriptionOpts) => Promise<CancelResponse>;
289
+ }
290
+ interface BillingModuleConfig {
291
+ verbose?: boolean;
292
+ privateKey: Hex;
293
+ }
294
+ declare function createBillingModule(config: BillingModuleConfig): BillingModule;
295
+
296
+ /**
297
+ * Interactive prompts using @inquirer/prompts
298
+ */
299
+
300
+ /**
301
+ * Prompt for Dockerfile selection
302
+ */
303
+ declare function getDockerfileInteractive(dockerfilePath?: string): Promise<string>;
304
+ /**
305
+ * Prompt for image reference
306
+ */
307
+ declare function getImageReferenceInteractive(imageRef?: string, buildFromDockerfile?: boolean): Promise<string>;
308
+ /**
309
+ * Prompt for app name
310
+ */
311
+ declare function getOrPromptAppName(appName: string | undefined, environment: string, imageRef: string): Promise<string>;
312
+ /**
313
+ * Prompt for environment file
314
+ */
315
+ declare function getEnvFileInteractive(envFilePath?: string): Promise<string>;
316
+ /**
317
+ * Prompt for instance type
318
+ */
319
+ declare function getInstanceTypeInteractive(instanceType: string | undefined, defaultSKU: string, availableTypes: Array<{
320
+ sku: string;
321
+ description: string;
322
+ }>): Promise<string>;
323
+ /**
324
+ * Prompt for app ID (supports app name or address)
325
+ */
326
+ interface GetAppIDOptions {
327
+ appID?: string | Address;
328
+ environment: string;
329
+ privateKey?: string;
330
+ rpcUrl?: string;
331
+ action?: string;
332
+ }
333
+ /**
334
+ * Prompt for app ID (supports app name or address)
335
+ */
336
+ declare function getOrPromptAppID(appIDOrOptions: string | Address | GetAppIDOptions | undefined, environment?: string): Promise<Address>;
337
+ /**
338
+ * Prompt for log settings
339
+ */
340
+ declare function getLogSettingsInteractive(logVisibility?: "public" | "private" | "off"): Promise<{
341
+ logRedirect: string;
342
+ publicLogs: boolean;
343
+ }>;
344
+ declare function extractAppNameFromImage(imageRef: string): string;
345
+ /**
346
+ * Confirm prompts the user to confirm an action with a yes/no question.
347
+ */
348
+ declare function confirm(prompt: string): Promise<boolean>;
349
+ /**
350
+ * ConfirmWithDefault prompts the user to confirm an action with a yes/no question and a default value.
351
+ */
352
+ declare function confirmWithDefault(prompt: string, defaultValue?: boolean): Promise<boolean>;
353
+ /**
354
+ * Prompt for RPC URL
355
+ * Matches Go's getRPCURL() behavior with interactive prompt
356
+ */
357
+ declare function getRPCUrlInteractive(rpcUrl?: string, defaultRpcUrl?: string): Promise<string>;
358
+ /**
359
+ * Prompt for environment selection
360
+ * Matches Go's GetEnvironmentConfig() behavior with interactive prompt
361
+ */
362
+ declare function getEnvironmentInteractive(environment?: string): Promise<string>;
363
+ /**
364
+ * Prompt for private key with hidden input
365
+ * Matches Go's output.InputHiddenString() function
366
+ */
367
+ declare function getPrivateKeyInteractive(privateKey?: string): Promise<string>;
368
+
369
+ /**
370
+ * Collect app profile information interactively
371
+ * If defaultName is provided, it will be used as the suggested name
372
+ * If allowRetry is true, user can re-enter information on rejection (deploy flow)
373
+ * If allowRetry is false, rejection returns an error (profile set flow)
374
+ */
375
+ declare function getAppProfileInteractive(defaultName?: string, allowRetry?: boolean): Promise<AppProfile | null>;
376
+
377
+ /**
378
+ * Environment configuration for different networks
379
+ */
380
+
381
+ /**
382
+ * Get environment configuration
383
+ */
384
+ declare function getEnvironmentConfig(environment: string, chainID?: bigint): EnvironmentConfig;
385
+ /**
386
+ * Get available environments based on build type
387
+ * - dev: only "sepolia-dev"
388
+ * - prod: "sepolia" and "mainnet-alpha"
389
+ */
390
+ declare function getAvailableEnvironments(): string[];
391
+ /**
392
+ * Check if an environment is available in the current build
393
+ */
394
+ declare function isEnvironmentAvailable(environment: string): boolean;
395
+
396
+ /**
397
+ * Billing utility functions
398
+ */
399
+
400
+ /**
401
+ * Check if subscription status allows deploying apps
402
+ */
403
+ declare function isSubscriptionActive(status: SubscriptionStatus): boolean;
404
+
405
+ /**
406
+ * OS Keyring Integration
407
+ *
408
+ * Provides secure storage for private keys using native OS keychains:
409
+ * - macOS: Keychain
410
+ * - Linux: Secret Service API (libsecret/gnome-keyring)
411
+ * - Windows: Credential Manager
412
+ *
413
+ * Uses a single key for all environments.
414
+ */
415
+ interface StoredKey {
416
+ address: string;
417
+ }
418
+ interface LegacyKey {
419
+ environment: string;
420
+ address: string;
421
+ source: "eigenx" | "eigenx-dev";
422
+ }
423
+ /**
424
+ * Store a private key in OS keyring
425
+ *
426
+ * Note: Stores a single key for all environments.
427
+ * The environment parameter is kept for API compatibility but is ignored.
428
+ */
429
+ declare function storePrivateKey(privateKey: string): Promise<void>;
430
+ /**
431
+ * Get a private key from OS keyring
432
+ *
433
+ * Note: Returns the single stored key for all environments.
434
+ * The environment parameter is kept for API compatibility but is ignored.
435
+ */
436
+ declare function getPrivateKey(): Promise<string | null>;
437
+ /**
438
+ * Delete a private key from OS keyring
439
+ * Returns true if deletion was successful, false otherwise
440
+ *
441
+ * Note: Deletes the single stored key.
442
+ * The environment parameter is kept for API compatibility but is ignored.
443
+ */
444
+ declare function deletePrivateKey(): Promise<boolean>;
445
+ /**
446
+ * List all stored keys
447
+ * Returns an array with the single stored key (if it exists)
448
+ */
449
+ declare function listStoredKeys(): Promise<StoredKey[]>;
450
+ /**
451
+ * Check if a key exists
452
+ *
453
+ * Note: Checks for the single stored key.
454
+ * The environment parameter is kept for API compatibility but is ignored.
455
+ */
456
+ declare function keyExists(): Promise<boolean>;
457
+ /**
458
+ * Get legacy keys from eigenx-cli
459
+ * Returns an array of keys found in eigenx-cli keyring formats
460
+ */
461
+ declare function getLegacyKeys(): Promise<LegacyKey[]>;
462
+ /**
463
+ * Get a specific legacy private key from eigenx-cli keyring
464
+ */
465
+ declare function getLegacyPrivateKey(environment: string, source: "eigenx" | "eigenx-dev"): Promise<string | null>;
466
+ /**
467
+ * Delete a specific legacy private key from eigenx-cli keyring
468
+ * Returns true if deletion was successful, false otherwise
469
+ */
470
+ declare function deleteLegacyPrivateKey(environment: string, source: "eigenx" | "eigenx-dev"): Promise<boolean>;
471
+ /**
472
+ * Validate private key format
473
+ */
474
+ declare function validatePrivateKey(privateKey: string): boolean;
475
+ /**
476
+ * Get address from private key
477
+ */
478
+ declare function getAddressFromPrivateKey(privateKey: string): string;
479
+
480
+ /**
481
+ * Private Key Resolution
482
+ *
483
+ * Implements 3-tier priority system for private key retrieval:
484
+ * 1. Command-line flag (--private-key)
485
+ * 2. Environment variable (ECLOUD_PRIVATE_KEY)
486
+ * 3. OS keyring (stored via `ecloud auth login`)
487
+ */
488
+ interface PrivateKeySource {
489
+ key: string;
490
+ source: string;
491
+ }
492
+ /**
493
+ * Get private key from any available source
494
+ *
495
+ * Priority order:
496
+ * 1. Direct parameter (from --private-key flag)
497
+ * 2. Environment variable (ECLOUD_PRIVATE_KEY)
498
+ * 3. OS keyring (single key for all environments)
499
+ *
500
+ * Returns null if no key found
501
+ */
502
+ declare function getPrivateKeyWithSource(options: {
503
+ privateKey?: string;
504
+ }): Promise<PrivateKeySource | null>;
505
+ /**
506
+ * Get private key with source or throw error
507
+ */
508
+ declare function requirePrivateKey(options: {
509
+ privateKey?: string;
510
+ }): Promise<PrivateKeySource>;
511
+
512
+ /**
513
+ * Security Utilities
514
+ *
515
+ * Provides secure display and input handling for sensitive data like private keys
516
+ */
517
+ /**
518
+ * Display sensitive content using system pager (less/more)
519
+ * Returns true if content was displayed, false if user aborted
520
+ */
521
+ declare function showPrivateKey(content: string): Promise<boolean>;
522
+ /**
523
+ * Clear terminal screen
524
+ */
525
+ declare function clearTerminal(): void;
526
+ /**
527
+ * Get hidden input (password-style)
528
+ */
529
+ declare function getHiddenInput(message: string): Promise<string>;
530
+ /**
531
+ * Display multi-line warning for destructive operations
532
+ */
533
+ declare function displayWarning(lines: string[]): void;
534
+
535
+ /**
536
+ * Private Key Generation
537
+ *
538
+ * Generate new secp256k1 private keys for Ethereum
539
+ */
540
+ interface GeneratedKey {
541
+ privateKey: string;
542
+ address: string;
543
+ }
544
+ /**
545
+ * Generate a new secp256k1 private key
546
+ */
547
+ declare function generateNewPrivateKey(): GeneratedKey;
548
+
549
+ /**
550
+ * Main SDK Client entry point
551
+ */
552
+
553
+ type Environment = "sepolia" | "sepolia-dev" | "mainnet-alpha";
554
+ interface ClientConfig {
555
+ verbose: boolean;
556
+ privateKey: `0x${string}`;
557
+ environment: Environment | string;
558
+ rpcUrl?: string;
559
+ }
560
+ interface ECloudClient {
561
+ app: AppModule;
562
+ billing: BillingModule;
563
+ }
564
+ declare function createECloudClient(cfg: ClientConfig): ECloudClient;
565
+
566
+ export { type AlreadyActiveResponse, type AppId, type AppModuleConfig, type AppProfile, type AppProfileResponse, type AppRecord, type BillingEnvironmentConfig, type BillingModuleConfig, type CancelResponse, type CancelSuccessResponse, type ChainID, type CheckoutCreatedResponse, type ClientConfig, type CreateAppOpts, type CreateSubscriptionResponse, type DeployAppOpts, type DeployOptions, type DeployResult, type DockerImageConfig, type ECloudClient, type Environment, type EnvironmentConfig, type GeneratedKey, type GetAppIDOptions, type ImageDigestResult, type LegacyKey, type LifecycleOpts, type Logger, type LogsOptions, type NoActiveSubscriptionResponse, type ParsedEnvironment, type PaymentIssueResponse, type PrivateKeySource, type ProductID, type ProductSubscriptionResponse, type Release, type StoredKey, type SubscribeResponse, type SubscriptionLineItem, type SubscriptionOpts, type SubscriptionStatus, type UpgradeAppOpts, clearTerminal, confirm, confirmWithDefault, createApp, createAppModule, createBillingModule, createECloudClient, deleteLegacyPrivateKey, deletePrivateKey, displayWarning, extractAppNameFromImage, generateNewPrivateKey, getAddressFromPrivateKey, getAppProfileInteractive, getAvailableEnvironments, getDockerfileInteractive, getEnvFileInteractive, getEnvironmentConfig, getEnvironmentInteractive, getHiddenInput, getImageReferenceInteractive, getInstanceTypeInteractive, getLegacyKeys, getLegacyPrivateKey, getLogSettingsInteractive, getOrPromptAppID, getOrPromptAppName, getPrivateKey, getPrivateKeyInteractive, getPrivateKeyWithSource, getRPCUrlInteractive, isEnvironmentAvailable, isSubscriptionActive, keyExists, listStoredKeys, type logVisibility, logs, requirePrivateKey, showPrivateKey, storePrivateKey, validatePrivateKey };