@layr-labs/ecloud-sdk 0.2.1-dev → 0.2.2-dev

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/dist/index.cjs CHANGED
@@ -42,6 +42,7 @@ __export(index_exports, {
42
42
  NotFoundError: () => NotFoundError,
43
43
  PRIMARY_LANGUAGES: () => PRIMARY_LANGUAGES,
44
44
  PostHogClient: () => PostHogClient,
45
+ SessionError: () => SessionError,
45
46
  TimeoutError: () => TimeoutError,
46
47
  UserApiClient: () => UserApiClient,
47
48
  addHexPrefix: () => addHexPrefix,
@@ -58,6 +59,7 @@ __export(index_exports, {
58
59
  createComputeModule: () => createComputeModule,
59
60
  createECloudClient: () => createECloudClient,
60
61
  createMetricsContext: () => createMetricsContext,
62
+ createSiweMessage: () => createSiweMessage,
61
63
  createTelemetryClient: () => createTelemetryClient,
62
64
  createViemClients: () => createClients,
63
65
  deleteLegacyPrivateKey: () => deleteLegacyPrivateKey,
@@ -74,6 +76,7 @@ __export(index_exports, {
74
76
  fetchTemplateCatalog: () => fetchTemplateCatalog,
75
77
  formatETH: () => formatETH,
76
78
  generateNewPrivateKey: () => generateNewPrivateKey,
79
+ generateNonce: () => generateNonce,
77
80
  getAddressFromPrivateKey: () => getAddressFromPrivateKey,
78
81
  getAllAppsByDeveloper: () => getAllAppsByDeveloper,
79
82
  getAppLatestReleaseBlockNumbers: () => getAppLatestReleaseBlockNumbers,
@@ -84,6 +87,7 @@ __export(index_exports, {
84
87
  getBuildType: () => getBuildType,
85
88
  getCategoryDescriptions: () => getCategoryDescriptions,
86
89
  getChainFromID: () => getChainFromID,
90
+ getComputeApiSession: () => getComputeApiSession,
87
91
  getCurrentInstanceType: () => getCurrentInstanceType,
88
92
  getEnvironmentConfig: () => getEnvironmentConfig,
89
93
  getLegacyKeys: () => getLegacyKeys,
@@ -96,10 +100,17 @@ __export(index_exports, {
96
100
  isEnvironmentAvailable: () => isEnvironmentAvailable,
97
101
  isMainnet: () => isMainnet,
98
102
  isNoopClient: () => isNoopClient,
103
+ isSessionValid: () => isSessionValid,
104
+ isSiweMessageExpired: () => isSiweMessageExpired,
105
+ isSiweMessageNotYetValid: () => isSiweMessageNotYetValid,
99
106
  isSubscriptionActive: () => isSubscriptionActive,
100
107
  keyExists: () => keyExists,
101
108
  listStoredKeys: () => listStoredKeys,
109
+ loginToComputeApi: () => loginToComputeApi,
110
+ logoutFromComputeApi: () => logoutFromComputeApi,
102
111
  logs: () => logs,
112
+ noopLogger: () => noopLogger,
113
+ parseSiweMessage: () => parseSiweMessage,
103
114
  prepareDeploy: () => prepareDeploy,
104
115
  prepareDeployFromVerifiableBuild: () => prepareDeployFromVerifiableBuild,
105
116
  prepareUpgrade: () => prepareUpgrade,
@@ -1237,6 +1248,18 @@ function extractRegistryNameNoDocker(imageRef) {
1237
1248
  // src/client/common/contract/eip7702.ts
1238
1249
  var import_viem = require("viem");
1239
1250
 
1251
+ // src/client/common/types/index.ts
1252
+ var noopLogger = {
1253
+ debug: () => {
1254
+ },
1255
+ info: () => {
1256
+ },
1257
+ warn: () => {
1258
+ },
1259
+ error: () => {
1260
+ }
1261
+ };
1262
+
1240
1263
  // src/client/common/abis/ERC7702Delegator.json
1241
1264
  var ERC7702Delegator_default = [
1242
1265
  {
@@ -2322,7 +2345,7 @@ async function checkERC7702Delegation(publicClient, account, delegatorAddress) {
2322
2345
  const expectedCode = `0xef0100${delegatorAddress.slice(2)}`;
2323
2346
  return code.toLowerCase() === expectedCode.toLowerCase();
2324
2347
  }
2325
- async function executeBatch(options, logger) {
2348
+ async function executeBatch(options, logger = noopLogger) {
2326
2349
  const { walletClient, publicClient, environmentConfig, executions, pendingMessage, gas } = options;
2327
2350
  const account = walletClient.account;
2328
2351
  if (!account) {
@@ -4027,7 +4050,7 @@ async function calculateAppID(options) {
4027
4050
  });
4028
4051
  return appID;
4029
4052
  }
4030
- async function prepareDeployBatch(options, logger) {
4053
+ async function prepareDeployBatch(options, logger = noopLogger) {
4031
4054
  const { walletClient, publicClient, environmentConfig, salt, release, publicLogs } = options;
4032
4055
  const account = walletClient.account;
4033
4056
  if (!account) {
@@ -4107,7 +4130,7 @@ async function prepareDeployBatch(options, logger) {
4107
4130
  environmentConfig
4108
4131
  };
4109
4132
  }
4110
- async function executeDeployBatch(data, context, gas, logger) {
4133
+ async function executeDeployBatch(data, context, gas, logger = noopLogger) {
4111
4134
  const pendingMessage = "Deploying new app...";
4112
4135
  const txHash = await executeBatch(
4113
4136
  {
@@ -4122,7 +4145,7 @@ async function executeDeployBatch(data, context, gas, logger) {
4122
4145
  );
4123
4146
  return { appId: data.appId, txHash };
4124
4147
  }
4125
- async function deployApp(options, logger) {
4148
+ async function deployApp(options, logger = noopLogger) {
4126
4149
  const prepared = await prepareDeployBatch(options, logger);
4127
4150
  const data = {
4128
4151
  appId: prepared.appId,
@@ -4137,7 +4160,15 @@ async function deployApp(options, logger) {
4137
4160
  return executeDeployBatch(data, context, options.gas, logger);
4138
4161
  }
4139
4162
  async function prepareUpgradeBatch(options) {
4140
- const { walletClient, publicClient, environmentConfig, appID, release, publicLogs, needsPermissionChange } = options;
4163
+ const {
4164
+ walletClient,
4165
+ publicClient,
4166
+ environmentConfig,
4167
+ appID,
4168
+ release,
4169
+ publicLogs,
4170
+ needsPermissionChange
4171
+ } = options;
4141
4172
  const releaseForViem = {
4142
4173
  rmsRelease: {
4143
4174
  artifacts: release.rmsRelease.artifacts.map((artifact) => ({
@@ -4210,7 +4241,7 @@ async function prepareUpgradeBatch(options) {
4210
4241
  environmentConfig
4211
4242
  };
4212
4243
  }
4213
- async function executeUpgradeBatch(data, context, gas, logger) {
4244
+ async function executeUpgradeBatch(data, context, gas, logger = noopLogger) {
4214
4245
  const pendingMessage = `Upgrading app ${data.appId}...`;
4215
4246
  const txHash = await executeBatch(
4216
4247
  {
@@ -4225,7 +4256,7 @@ async function executeUpgradeBatch(data, context, gas, logger) {
4225
4256
  );
4226
4257
  return txHash;
4227
4258
  }
4228
- async function upgradeApp(options, logger) {
4259
+ async function upgradeApp(options, logger = noopLogger) {
4229
4260
  const prepared = await prepareUpgradeBatch(options);
4230
4261
  const data = {
4231
4262
  appId: prepared.appId,
@@ -4238,8 +4269,18 @@ async function upgradeApp(options, logger) {
4238
4269
  };
4239
4270
  return executeUpgradeBatch(data, context, options.gas, logger);
4240
4271
  }
4241
- async function sendAndWaitForTransaction(options, logger) {
4242
- const { walletClient, publicClient, environmentConfig, to, data, value = 0n, pendingMessage, txDescription, gas } = options;
4272
+ async function sendAndWaitForTransaction(options, logger = noopLogger) {
4273
+ const {
4274
+ walletClient,
4275
+ publicClient,
4276
+ environmentConfig,
4277
+ to,
4278
+ data,
4279
+ value = 0n,
4280
+ pendingMessage,
4281
+ txDescription,
4282
+ gas
4283
+ } = options;
4243
4284
  const account = walletClient.account;
4244
4285
  if (!account) {
4245
4286
  throw new Error("WalletClient must have an account attached");
@@ -4359,7 +4400,13 @@ async function getAllAppsByDeveloper(publicClient, env, developer, pageSize = 10
4359
4400
  const allApps = [];
4360
4401
  const allConfigs = [];
4361
4402
  while (true) {
4362
- const { apps, appConfigs } = await getAppsByDeveloper(publicClient, env, developer, offset, pageSize);
4403
+ const { apps, appConfigs } = await getAppsByDeveloper(
4404
+ publicClient,
4405
+ env,
4406
+ developer,
4407
+ offset,
4408
+ pageSize
4409
+ );
4363
4410
  if (apps.length === 0) break;
4364
4411
  allApps.push(...apps);
4365
4412
  allConfigs.push(...appConfigs);
@@ -4415,7 +4462,7 @@ async function isDelegated(options) {
4415
4462
  environmentConfig.erc7702DelegatorAddress
4416
4463
  );
4417
4464
  }
4418
- async function undelegate(options, logger) {
4465
+ async function undelegate(options, logger = noopLogger) {
4419
4466
  const { walletClient, publicClient, environmentConfig } = options;
4420
4467
  const account = walletClient.account;
4421
4468
  if (!account) {
@@ -4513,6 +4560,129 @@ async function calculateBillingAuthSignature(options) {
4513
4560
  return { signature, expiry };
4514
4561
  }
4515
4562
 
4563
+ // src/client/common/auth/session.ts
4564
+ var SessionError = class extends Error {
4565
+ constructor(message, code, statusCode) {
4566
+ super(message);
4567
+ this.code = code;
4568
+ this.statusCode = statusCode;
4569
+ this.name = "SessionError";
4570
+ }
4571
+ };
4572
+ function stripHexPrefix2(hex) {
4573
+ return hex.startsWith("0x") ? hex.slice(2) : hex;
4574
+ }
4575
+ async function parseErrorResponse(response) {
4576
+ try {
4577
+ const data = await response.json();
4578
+ return data.error || response.statusText;
4579
+ } catch {
4580
+ return response.statusText;
4581
+ }
4582
+ }
4583
+ async function loginToComputeApi(config, request) {
4584
+ let response;
4585
+ try {
4586
+ response = await fetch(`${config.baseUrl}/auth/siwe/login`, {
4587
+ method: "POST",
4588
+ credentials: "include",
4589
+ // Include cookies for session management
4590
+ headers: {
4591
+ "Content-Type": "application/json"
4592
+ },
4593
+ body: JSON.stringify({
4594
+ message: request.message,
4595
+ signature: stripHexPrefix2(request.signature)
4596
+ })
4597
+ });
4598
+ } catch (error) {
4599
+ throw new SessionError(
4600
+ `Network error connecting to ${config.baseUrl}: ${error instanceof Error ? error.message : String(error)}`,
4601
+ "NETWORK_ERROR"
4602
+ );
4603
+ }
4604
+ if (!response.ok) {
4605
+ const errorMessage = await parseErrorResponse(response);
4606
+ const status = response.status;
4607
+ if (status === 400) {
4608
+ if (errorMessage.toLowerCase().includes("siwe")) {
4609
+ throw new SessionError(`Invalid SIWE message: ${errorMessage}`, "INVALID_MESSAGE", status);
4610
+ }
4611
+ throw new SessionError(`Bad request: ${errorMessage}`, "INVALID_MESSAGE", status);
4612
+ }
4613
+ if (status === 401) {
4614
+ throw new SessionError(`Invalid signature: ${errorMessage}`, "INVALID_SIGNATURE", status);
4615
+ }
4616
+ throw new SessionError(`Login failed: ${errorMessage}`, "UNKNOWN", status);
4617
+ }
4618
+ const data = await response.json();
4619
+ return {
4620
+ success: data.success,
4621
+ address: data.address
4622
+ };
4623
+ }
4624
+ async function getComputeApiSession(config) {
4625
+ let response;
4626
+ try {
4627
+ response = await fetch(`${config.baseUrl}/auth/session`, {
4628
+ method: "GET",
4629
+ credentials: "include",
4630
+ // Include cookies for session management
4631
+ headers: {
4632
+ "Content-Type": "application/json"
4633
+ }
4634
+ });
4635
+ } catch {
4636
+ return {
4637
+ authenticated: false
4638
+ };
4639
+ }
4640
+ if (response.status === 401) {
4641
+ return {
4642
+ authenticated: false
4643
+ };
4644
+ }
4645
+ if (!response.ok) {
4646
+ const errorMessage = await parseErrorResponse(response);
4647
+ throw new SessionError(`Failed to get session: ${errorMessage}`, "UNKNOWN", response.status);
4648
+ }
4649
+ const data = await response.json();
4650
+ return {
4651
+ authenticated: data.authenticated,
4652
+ address: data.address,
4653
+ chainId: data.chain_id
4654
+ };
4655
+ }
4656
+ async function logoutFromComputeApi(config) {
4657
+ let response;
4658
+ try {
4659
+ response = await fetch(`${config.baseUrl}/auth/logout`, {
4660
+ method: "POST",
4661
+ credentials: "include",
4662
+ // Include cookies for session management
4663
+ headers: {
4664
+ "Content-Type": "application/json"
4665
+ }
4666
+ });
4667
+ } catch (error) {
4668
+ throw new SessionError(
4669
+ `Network error connecting to ${config.baseUrl}: ${error instanceof Error ? error.message : String(error)}`,
4670
+ "NETWORK_ERROR"
4671
+ );
4672
+ }
4673
+ if (response.status === 401) {
4674
+ return;
4675
+ }
4676
+ if (!response.ok) {
4677
+ const errorMessage = await parseErrorResponse(response);
4678
+ throw new SessionError(`Logout failed: ${errorMessage}`, "UNKNOWN", response.status);
4679
+ }
4680
+ }
4681
+ async function isSessionValid(config) {
4682
+ const session = await getComputeApiSession(config);
4683
+ return session.authenticated;
4684
+ }
4685
+
4516
4686
  // src/client/common/utils/userapi.ts
4517
4687
  function isJsonObject(value) {
4518
4688
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -4530,15 +4700,16 @@ var CanViewAppLogsPermission = "0x2fd3f2fe";
4530
4700
  var CanViewSensitiveAppInfoPermission = "0x0e67b22f";
4531
4701
  var CanUpdateAppProfilePermission = "0x036fef61";
4532
4702
  function getDefaultClientId() {
4533
- const version = true ? "0.2.1-dev" : "0.0.0";
4703
+ const version = true ? "0.2.2-dev" : "0.0.0";
4534
4704
  return `ecloud-sdk/v${version}`;
4535
4705
  }
4536
4706
  var UserApiClient = class {
4537
- constructor(config, walletClient, publicClient, clientId) {
4707
+ constructor(config, walletClient, publicClient, options) {
4538
4708
  this.config = config;
4539
4709
  this.walletClient = walletClient;
4540
4710
  this.publicClient = publicClient;
4541
- this.clientId = clientId || getDefaultClientId();
4711
+ this.clientId = options?.clientId || getDefaultClientId();
4712
+ this.useSession = options?.useSession ?? false;
4542
4713
  }
4543
4714
  /**
4544
4715
  * Get the address of the connected wallet
@@ -4626,7 +4797,7 @@ var UserApiClient = class {
4626
4797
  const apps = result.apps || result.Apps || [];
4627
4798
  return apps.map((app, i) => ({
4628
4799
  address: app.address || appIDs[i],
4629
- status: app.status || app.Status || ""
4800
+ status: app.app_status || app.App_Status || ""
4630
4801
  }));
4631
4802
  }
4632
4803
  /**
@@ -4658,9 +4829,11 @@ var UserApiClient = class {
4658
4829
  const headers = {
4659
4830
  "x-client-id": this.clientId
4660
4831
  };
4661
- const expiry = BigInt(Math.floor(Date.now() / 1e3) + 5 * 60);
4662
- const authHeaders = await this.generateAuthHeaders(CanUpdateAppProfilePermission, expiry);
4663
- Object.assign(headers, authHeaders);
4832
+ if (!this.useSession) {
4833
+ const expiry = BigInt(Math.floor(Date.now() / 1e3) + 5 * 60);
4834
+ const authHeaders = await this.generateAuthHeaders(CanUpdateAppProfilePermission, expiry);
4835
+ Object.assign(headers, authHeaders);
4836
+ }
4664
4837
  try {
4665
4838
  const response = await import_axios.default.post(endpoint, formData, {
4666
4839
  headers,
@@ -4669,8 +4842,10 @@ var UserApiClient = class {
4669
4842
  // Don't throw on any status
4670
4843
  maxContentLength: Infinity,
4671
4844
  // Allow large file uploads
4672
- maxBodyLength: Infinity
4845
+ maxBodyLength: Infinity,
4673
4846
  // Allow large file uploads
4847
+ withCredentials: true
4848
+ // Include cookies for session auth
4674
4849
  });
4675
4850
  const status = response.status;
4676
4851
  if (status !== 200 && status !== 201) {
@@ -4704,7 +4879,7 @@ Please check:
4704
4879
  const headers = {
4705
4880
  "x-client-id": this.clientId
4706
4881
  };
4707
- if (permission) {
4882
+ if (permission && !this.useSession) {
4708
4883
  const expiry = BigInt(Math.floor(Date.now() / 1e3) + 5 * 60);
4709
4884
  const authHeaders = await this.generateAuthHeaders(permission, expiry);
4710
4885
  Object.assign(headers, authHeaders);
@@ -4713,8 +4888,10 @@ Please check:
4713
4888
  const response = await import_axios.default.get(url, {
4714
4889
  headers,
4715
4890
  maxRedirects: 0,
4716
- validateStatus: () => true
4891
+ validateStatus: () => true,
4717
4892
  // Don't throw on any status
4893
+ withCredentials: true
4894
+ // Include cookies for session auth
4718
4895
  });
4719
4896
  const status = response.status;
4720
4897
  const statusText = status >= 200 && status < 300 ? "OK" : "Error";
@@ -4756,6 +4933,65 @@ Please check:
4756
4933
  "X-eigenx-expiry": expiry.toString()
4757
4934
  };
4758
4935
  }
4936
+ // ==========================================================================
4937
+ // SIWE Session Management
4938
+ // ==========================================================================
4939
+ /**
4940
+ * Login to the compute API using SIWE (Sign-In with Ethereum)
4941
+ *
4942
+ * This establishes a session with the compute API by verifying the SIWE message
4943
+ * and signature. On success, a session cookie is set in the browser.
4944
+ *
4945
+ * @param request - Login request containing SIWE message and signature
4946
+ * @returns Login result with the authenticated address
4947
+ *
4948
+ * @example
4949
+ * ```typescript
4950
+ * import { createSiweMessage } from "@layr-labs/ecloud-sdk/browser";
4951
+ *
4952
+ * const { message } = createSiweMessage({
4953
+ * address: userAddress,
4954
+ * chainId: 11155111,
4955
+ * domain: window.location.host,
4956
+ * uri: window.location.origin,
4957
+ * });
4958
+ *
4959
+ * const signature = await signMessageAsync({ message });
4960
+ * const result = await client.siweLogin({ message, signature });
4961
+ * ```
4962
+ */
4963
+ async siweLogin(request) {
4964
+ return loginToComputeApi({ baseUrl: this.config.userApiServerURL }, request);
4965
+ }
4966
+ /**
4967
+ * Logout from the compute API
4968
+ *
4969
+ * This destroys the current session and clears the session cookie.
4970
+ *
4971
+ * @example
4972
+ * ```typescript
4973
+ * await client.siweLogout();
4974
+ * ```
4975
+ */
4976
+ async siweLogout() {
4977
+ return logoutFromComputeApi({ baseUrl: this.config.userApiServerURL });
4978
+ }
4979
+ /**
4980
+ * Get the current SIWE session status from the compute API
4981
+ *
4982
+ * @returns Session information including authentication status and address
4983
+ *
4984
+ * @example
4985
+ * ```typescript
4986
+ * const session = await client.getSiweSession();
4987
+ * if (session.authenticated) {
4988
+ * console.log(`Logged in as ${session.address}`);
4989
+ * }
4990
+ * ```
4991
+ */
4992
+ async getSiweSession() {
4993
+ return getComputeApiSession({ baseUrl: this.config.userApiServerURL });
4994
+ }
4759
4995
  };
4760
4996
  function transformAppReleaseBuild(raw) {
4761
4997
  if (!isJsonObject(raw)) return void 0;
@@ -5387,9 +5623,13 @@ var BillingApiClient = class {
5387
5623
  }
5388
5624
  return account.address;
5389
5625
  }
5390
- async createSubscription(productId = "compute") {
5626
+ async createSubscription(productId = "compute", options) {
5391
5627
  const endpoint = `${this.config.billingApiServerURL}/products/${productId}/subscription`;
5392
- const resp = await this.makeAuthenticatedRequest(endpoint, "POST", productId);
5628
+ const body = options ? {
5629
+ success_url: options.successUrl,
5630
+ cancel_url: options.cancelUrl
5631
+ } : void 0;
5632
+ const resp = await this.makeAuthenticatedRequest(endpoint, "POST", productId, body);
5393
5633
  return resp.json();
5394
5634
  }
5395
5635
  async getSubscription(productId = "compute") {
@@ -5404,7 +5644,7 @@ var BillingApiClient = class {
5404
5644
  /**
5405
5645
  * Make an authenticated request to the billing API
5406
5646
  */
5407
- async makeAuthenticatedRequest(url, method, productId) {
5647
+ async makeAuthenticatedRequest(url, method, productId, body) {
5408
5648
  const expiry = BigInt(Math.floor(Date.now() / 1e3) + 5 * 60);
5409
5649
  const { signature } = await calculateBillingAuthSignature({
5410
5650
  walletClient: this.walletClient,
@@ -5416,11 +5656,15 @@ var BillingApiClient = class {
5416
5656
  "X-Account": this.address,
5417
5657
  "X-Expiry": expiry.toString()
5418
5658
  };
5659
+ if (body) {
5660
+ headers["Content-Type"] = "application/json";
5661
+ }
5419
5662
  try {
5420
5663
  const response = await (0, import_axios2.default)({
5421
5664
  method,
5422
5665
  url,
5423
5666
  headers,
5667
+ data: body,
5424
5668
  timeout: 3e4,
5425
5669
  maxRedirects: 0,
5426
5670
  validateStatus: () => true
@@ -5429,8 +5673,8 @@ var BillingApiClient = class {
5429
5673
  const status = response.status;
5430
5674
  const statusText = status >= 200 && status < 300 ? "OK" : "Error";
5431
5675
  if (status < 200 || status >= 300) {
5432
- const body = typeof response.data === "string" ? response.data : JSON.stringify(response.data);
5433
- throw new Error(`BillingAPI request failed: ${status} ${statusText} - ${body}`);
5676
+ const body2 = typeof response.data === "string" ? response.data : JSON.stringify(response.data);
5677
+ throw new Error(`BillingAPI request failed: ${status} ${statusText} - ${body2}`);
5434
5678
  }
5435
5679
  return {
5436
5680
  json: async () => response.data,
@@ -6916,7 +7160,7 @@ async function logs(options, walletClient, publicClient, environmentConfig, logg
6916
7160
  environmentConfig,
6917
7161
  walletClient,
6918
7162
  publicClient,
6919
- options.clientId
7163
+ options.clientId ? { clientId: options.clientId } : void 0
6920
7164
  );
6921
7165
  let logsText;
6922
7166
  let logsError = null;
@@ -7215,7 +7459,7 @@ function createAppModule(ctx) {
7215
7459
  environment,
7216
7460
  walletClient,
7217
7461
  publicClient,
7218
- ctx.clientId
7462
+ ctx.clientId ? { clientId: ctx.clientId } : void 0
7219
7463
  );
7220
7464
  return userApiClient.uploadAppProfile(appId, profile.name, {
7221
7465
  website: profile.website,
@@ -7474,6 +7718,37 @@ function createBillingModule(config) {
7474
7718
 
7475
7719
  // src/client/common/utils/buildapi.ts
7476
7720
  var import_axios3 = __toESM(require("axios"), 1);
7721
+ var MAX_RETRIES = 5;
7722
+ var INITIAL_BACKOFF_MS = 1e3;
7723
+ var MAX_BACKOFF_MS = 3e4;
7724
+ async function sleep2(ms) {
7725
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
7726
+ }
7727
+ function getRetryDelay(res, attempt) {
7728
+ const retryAfter = res.headers["retry-after"];
7729
+ if (retryAfter) {
7730
+ const seconds = parseInt(retryAfter, 10);
7731
+ if (!isNaN(seconds)) {
7732
+ return Math.min(seconds * 1e3, MAX_BACKOFF_MS);
7733
+ }
7734
+ }
7735
+ return Math.min(INITIAL_BACKOFF_MS * Math.pow(2, attempt), MAX_BACKOFF_MS);
7736
+ }
7737
+ async function requestWithRetry(config) {
7738
+ let lastResponse;
7739
+ for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
7740
+ const res = await (0, import_axios3.default)({ ...config, validateStatus: () => true });
7741
+ lastResponse = res;
7742
+ if (res.status !== 429) {
7743
+ return res;
7744
+ }
7745
+ if (attempt < MAX_RETRIES) {
7746
+ const delay = getRetryDelay(res, attempt);
7747
+ await sleep2(delay);
7748
+ }
7749
+ }
7750
+ return lastResponse;
7751
+ }
7477
7752
  var BuildApiClient = class {
7478
7753
  constructor(options) {
7479
7754
  this.baseUrl = options.baseUrl.replace(/\/+$/, "");
@@ -7506,24 +7781,22 @@ var BuildApiClient = class {
7506
7781
  return this.authenticatedTextRequest(`/builds/${encodeURIComponent(buildId)}/logs`);
7507
7782
  }
7508
7783
  async listBuilds(params) {
7509
- const res = await (0, import_axios3.default)({
7784
+ const res = await requestWithRetry({
7510
7785
  url: `${this.baseUrl}/builds`,
7511
7786
  method: "GET",
7512
7787
  params,
7513
7788
  headers: this.clientId ? { "x-client-id": this.clientId } : void 0,
7514
- timeout: 6e4,
7515
- validateStatus: () => true
7789
+ timeout: 6e4
7516
7790
  });
7517
7791
  if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
7518
7792
  return res.data;
7519
7793
  }
7520
7794
  async publicJsonRequest(path8) {
7521
- const res = await (0, import_axios3.default)({
7795
+ const res = await requestWithRetry({
7522
7796
  url: `${this.baseUrl}${path8}`,
7523
7797
  method: "GET",
7524
7798
  headers: this.clientId ? { "x-client-id": this.clientId } : void 0,
7525
- timeout: 6e4,
7526
- validateStatus: () => true
7799
+ timeout: 6e4
7527
7800
  });
7528
7801
  if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
7529
7802
  return res.data;
@@ -7545,13 +7818,12 @@ var BuildApiClient = class {
7545
7818
  headers.Authorization = `Bearer ${signature}`;
7546
7819
  headers["X-eigenx-expiry"] = expiry.toString();
7547
7820
  headers["X-Account"] = this.address;
7548
- const res = await (0, import_axios3.default)({
7821
+ const res = await requestWithRetry({
7549
7822
  url: `${this.baseUrl}${path8}`,
7550
7823
  method,
7551
7824
  headers,
7552
7825
  data: body,
7553
- timeout: 6e4,
7554
- validateStatus: () => true
7826
+ timeout: 6e4
7555
7827
  });
7556
7828
  if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
7557
7829
  return res.data;
@@ -7571,13 +7843,12 @@ var BuildApiClient = class {
7571
7843
  headers.Authorization = `Bearer ${signature}`;
7572
7844
  headers["X-eigenx-expiry"] = expiry.toString();
7573
7845
  headers["X-Account"] = this.address;
7574
- const res = await (0, import_axios3.default)({
7846
+ const res = await requestWithRetry({
7575
7847
  url: `${this.baseUrl}${path8}`,
7576
7848
  method: "GET",
7577
7849
  headers,
7578
7850
  timeout: 6e4,
7579
- responseType: "text",
7580
- validateStatus: () => true
7851
+ responseType: "text"
7581
7852
  });
7582
7853
  if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
7583
7854
  return typeof res.data === "string" ? res.data : JSON.stringify(res.data);
@@ -7766,7 +8037,7 @@ function createBuildModule(config) {
7766
8037
  if (build.status === BUILD_STATUS.FAILED) {
7767
8038
  throw new BuildFailedError(build.errorMessage ?? "Build failed", buildId);
7768
8039
  }
7769
- await sleep2(pollIntervalMs);
8040
+ await sleep3(pollIntervalMs);
7770
8041
  }
7771
8042
  },
7772
8043
  async *streamLogs(buildId, pollIntervalMs = DEFAULT_POLL_INTERVAL) {
@@ -7788,12 +8059,12 @@ function createBuildModule(config) {
7788
8059
  lastLength = logs2.length;
7789
8060
  }
7790
8061
  if (build.status !== BUILD_STATUS.BUILDING) break;
7791
- await sleep2(pollIntervalMs);
8062
+ await sleep3(pollIntervalMs);
7792
8063
  }
7793
8064
  }
7794
8065
  };
7795
8066
  }
7796
- function sleep2(ms) {
8067
+ function sleep3(ms) {
7797
8068
  return new Promise((resolve2) => setTimeout(resolve2, ms));
7798
8069
  }
7799
8070
  function transformBuild(raw) {
@@ -8076,6 +8347,74 @@ function generateNewPrivateKey() {
8076
8347
  };
8077
8348
  }
8078
8349
 
8350
+ // src/client/common/auth/siwe.ts
8351
+ var import_siwe = require("siwe");
8352
+ var generateNonce = import_siwe.generateNonce;
8353
+ function createSiweMessage(params) {
8354
+ const now = /* @__PURE__ */ new Date();
8355
+ const nonce = params.nonce || generateNonce();
8356
+ const issuedAt = params.issuedAt || now;
8357
+ const expirationTime = params.expirationTime || new Date(now.getTime() + 24 * 60 * 60 * 1e3);
8358
+ const siweMessage = new import_siwe.SiweMessage({
8359
+ domain: params.domain,
8360
+ address: params.address,
8361
+ statement: params.statement,
8362
+ uri: params.uri,
8363
+ version: "1",
8364
+ chainId: params.chainId,
8365
+ nonce,
8366
+ issuedAt: issuedAt.toISOString(),
8367
+ expirationTime: expirationTime.toISOString(),
8368
+ notBefore: params.notBefore?.toISOString(),
8369
+ requestId: params.requestId,
8370
+ resources: params.resources
8371
+ });
8372
+ return {
8373
+ message: siweMessage.prepareMessage(),
8374
+ params: {
8375
+ address: params.address,
8376
+ chainId: params.chainId,
8377
+ domain: params.domain,
8378
+ uri: params.uri,
8379
+ nonce,
8380
+ issuedAt,
8381
+ statement: params.statement,
8382
+ expirationTime,
8383
+ notBefore: params.notBefore,
8384
+ requestId: params.requestId,
8385
+ resources: params.resources
8386
+ }
8387
+ };
8388
+ }
8389
+ function parseSiweMessage(message) {
8390
+ try {
8391
+ const siweMessage = new import_siwe.SiweMessage(message);
8392
+ return {
8393
+ address: siweMessage.address,
8394
+ chainId: siweMessage.chainId,
8395
+ domain: siweMessage.domain,
8396
+ uri: siweMessage.uri,
8397
+ nonce: siweMessage.nonce,
8398
+ statement: siweMessage.statement,
8399
+ issuedAt: siweMessage.issuedAt ? new Date(siweMessage.issuedAt) : void 0,
8400
+ expirationTime: siweMessage.expirationTime ? new Date(siweMessage.expirationTime) : void 0,
8401
+ notBefore: siweMessage.notBefore ? new Date(siweMessage.notBefore) : void 0,
8402
+ requestId: siweMessage.requestId,
8403
+ resources: siweMessage.resources
8404
+ };
8405
+ } catch {
8406
+ return null;
8407
+ }
8408
+ }
8409
+ function isSiweMessageExpired(params) {
8410
+ if (!params.expirationTime) return false;
8411
+ return /* @__PURE__ */ new Date() > params.expirationTime;
8412
+ }
8413
+ function isSiweMessageNotYetValid(params) {
8414
+ if (!params.notBefore) return false;
8415
+ return /* @__PURE__ */ new Date() < params.notBefore;
8416
+ }
8417
+
8079
8418
  // src/client/common/utils/instance.ts
8080
8419
  async function getCurrentInstanceType(preflightCtx, appID, logger, clientId) {
8081
8420
  try {
@@ -8083,7 +8422,7 @@ async function getCurrentInstanceType(preflightCtx, appID, logger, clientId) {
8083
8422
  preflightCtx.environmentConfig,
8084
8423
  preflightCtx.walletClient,
8085
8424
  preflightCtx.publicClient,
8086
- clientId
8425
+ clientId ? { clientId } : void 0
8087
8426
  );
8088
8427
  const infos = await userApiClient.getInfos([appID], 1);
8089
8428
  if (infos.length === 0) {
@@ -8147,6 +8486,7 @@ function createECloudClient(cfg) {
8147
8486
  NotFoundError,
8148
8487
  PRIMARY_LANGUAGES,
8149
8488
  PostHogClient,
8489
+ SessionError,
8150
8490
  TimeoutError,
8151
8491
  UserApiClient,
8152
8492
  addHexPrefix,
@@ -8163,6 +8503,7 @@ function createECloudClient(cfg) {
8163
8503
  createComputeModule,
8164
8504
  createECloudClient,
8165
8505
  createMetricsContext,
8506
+ createSiweMessage,
8166
8507
  createTelemetryClient,
8167
8508
  createViemClients,
8168
8509
  deleteLegacyPrivateKey,
@@ -8179,6 +8520,7 @@ function createECloudClient(cfg) {
8179
8520
  fetchTemplateCatalog,
8180
8521
  formatETH,
8181
8522
  generateNewPrivateKey,
8523
+ generateNonce,
8182
8524
  getAddressFromPrivateKey,
8183
8525
  getAllAppsByDeveloper,
8184
8526
  getAppLatestReleaseBlockNumbers,
@@ -8189,6 +8531,7 @@ function createECloudClient(cfg) {
8189
8531
  getBuildType,
8190
8532
  getCategoryDescriptions,
8191
8533
  getChainFromID,
8534
+ getComputeApiSession,
8192
8535
  getCurrentInstanceType,
8193
8536
  getEnvironmentConfig,
8194
8537
  getLegacyKeys,
@@ -8201,10 +8544,17 @@ function createECloudClient(cfg) {
8201
8544
  isEnvironmentAvailable,
8202
8545
  isMainnet,
8203
8546
  isNoopClient,
8547
+ isSessionValid,
8548
+ isSiweMessageExpired,
8549
+ isSiweMessageNotYetValid,
8204
8550
  isSubscriptionActive,
8205
8551
  keyExists,
8206
8552
  listStoredKeys,
8553
+ loginToComputeApi,
8554
+ logoutFromComputeApi,
8207
8555
  logs,
8556
+ noopLogger,
8557
+ parseSiweMessage,
8208
8558
  prepareDeploy,
8209
8559
  prepareDeployFromVerifiableBuild,
8210
8560
  prepareUpgrade,