@layr-labs/ecloud-sdk 0.2.2-dev → 0.3.0-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/browser.js CHANGED
@@ -1,3 +1,150 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropNames = Object.getOwnPropertyNames;
3
+ var __esm = (fn, res) => function __init() {
4
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
5
+ };
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+
11
+ // src/client/common/auth/session.ts
12
+ var session_exports = {};
13
+ __export(session_exports, {
14
+ SessionError: () => SessionError,
15
+ getComputeApiSession: () => getComputeApiSession,
16
+ isSessionValid: () => isSessionValid,
17
+ loginToComputeApi: () => loginToComputeApi,
18
+ logoutFromComputeApi: () => logoutFromComputeApi
19
+ });
20
+ function stripHexPrefix2(hex) {
21
+ return hex.startsWith("0x") ? hex.slice(2) : hex;
22
+ }
23
+ async function parseErrorResponse(response) {
24
+ try {
25
+ const data = await response.json();
26
+ return data.error || response.statusText;
27
+ } catch {
28
+ return response.statusText;
29
+ }
30
+ }
31
+ async function loginToComputeApi(config, request) {
32
+ let response;
33
+ try {
34
+ response = await fetch(`${config.baseUrl}/auth/siwe/login`, {
35
+ method: "POST",
36
+ credentials: "include",
37
+ // Include cookies for session management
38
+ headers: {
39
+ "Content-Type": "application/json"
40
+ },
41
+ body: JSON.stringify({
42
+ message: request.message,
43
+ signature: stripHexPrefix2(request.signature)
44
+ })
45
+ });
46
+ } catch (error) {
47
+ throw new SessionError(
48
+ `Network error connecting to ${config.baseUrl}: ${error instanceof Error ? error.message : String(error)}`,
49
+ "NETWORK_ERROR"
50
+ );
51
+ }
52
+ if (!response.ok) {
53
+ const errorMessage = await parseErrorResponse(response);
54
+ const status = response.status;
55
+ if (status === 400) {
56
+ if (errorMessage.toLowerCase().includes("siwe")) {
57
+ throw new SessionError(`Invalid SIWE message: ${errorMessage}`, "INVALID_MESSAGE", status);
58
+ }
59
+ throw new SessionError(`Bad request: ${errorMessage}`, "INVALID_MESSAGE", status);
60
+ }
61
+ if (status === 401) {
62
+ throw new SessionError(`Invalid signature: ${errorMessage}`, "INVALID_SIGNATURE", status);
63
+ }
64
+ throw new SessionError(`Login failed: ${errorMessage}`, "UNKNOWN", status);
65
+ }
66
+ const data = await response.json();
67
+ return {
68
+ success: data.success,
69
+ address: data.address
70
+ };
71
+ }
72
+ async function getComputeApiSession(config) {
73
+ let response;
74
+ try {
75
+ response = await fetch(`${config.baseUrl}/auth/session`, {
76
+ method: "GET",
77
+ credentials: "include",
78
+ // Include cookies for session management
79
+ headers: {
80
+ "Content-Type": "application/json"
81
+ }
82
+ });
83
+ } catch {
84
+ return {
85
+ authenticated: false
86
+ };
87
+ }
88
+ if (response.status === 401) {
89
+ return {
90
+ authenticated: false
91
+ };
92
+ }
93
+ if (!response.ok) {
94
+ const errorMessage = await parseErrorResponse(response);
95
+ throw new SessionError(`Failed to get session: ${errorMessage}`, "UNKNOWN", response.status);
96
+ }
97
+ const data = await response.json();
98
+ return {
99
+ authenticated: data.authenticated,
100
+ address: data.address,
101
+ chainId: data.chain_id
102
+ };
103
+ }
104
+ async function logoutFromComputeApi(config) {
105
+ let response;
106
+ try {
107
+ response = await fetch(`${config.baseUrl}/auth/logout`, {
108
+ method: "POST",
109
+ credentials: "include",
110
+ // Include cookies for session management
111
+ headers: {
112
+ "Content-Type": "application/json"
113
+ }
114
+ });
115
+ } catch (error) {
116
+ throw new SessionError(
117
+ `Network error connecting to ${config.baseUrl}: ${error instanceof Error ? error.message : String(error)}`,
118
+ "NETWORK_ERROR"
119
+ );
120
+ }
121
+ if (response.status === 401) {
122
+ return;
123
+ }
124
+ if (!response.ok) {
125
+ const errorMessage = await parseErrorResponse(response);
126
+ throw new SessionError(`Logout failed: ${errorMessage}`, "UNKNOWN", response.status);
127
+ }
128
+ }
129
+ async function isSessionValid(config) {
130
+ const session = await getComputeApiSession(config);
131
+ return session.authenticated;
132
+ }
133
+ var SessionError;
134
+ var init_session = __esm({
135
+ "src/client/common/auth/session.ts"() {
136
+ "use strict";
137
+ SessionError = class extends Error {
138
+ constructor(message, code, statusCode) {
139
+ super(message);
140
+ this.code = code;
141
+ this.statusCode = statusCode;
142
+ this.name = "SessionError";
143
+ }
144
+ };
145
+ }
146
+ });
147
+
1
148
  // src/client/common/types/index.ts
2
149
  var noopLogger = {
3
150
  debug: () => {
@@ -402,130 +549,8 @@ async function calculateBillingAuthSignature(options) {
402
549
  return { signature, expiry };
403
550
  }
404
551
 
405
- // src/client/common/auth/session.ts
406
- var SessionError = class extends Error {
407
- constructor(message, code, statusCode) {
408
- super(message);
409
- this.code = code;
410
- this.statusCode = statusCode;
411
- this.name = "SessionError";
412
- }
413
- };
414
- function stripHexPrefix2(hex) {
415
- return hex.startsWith("0x") ? hex.slice(2) : hex;
416
- }
417
- async function parseErrorResponse(response) {
418
- try {
419
- const data = await response.json();
420
- return data.error || response.statusText;
421
- } catch {
422
- return response.statusText;
423
- }
424
- }
425
- async function loginToComputeApi(config, request) {
426
- let response;
427
- try {
428
- response = await fetch(`${config.baseUrl}/auth/siwe/login`, {
429
- method: "POST",
430
- credentials: "include",
431
- // Include cookies for session management
432
- headers: {
433
- "Content-Type": "application/json"
434
- },
435
- body: JSON.stringify({
436
- message: request.message,
437
- signature: stripHexPrefix2(request.signature)
438
- })
439
- });
440
- } catch (error) {
441
- throw new SessionError(
442
- `Network error connecting to ${config.baseUrl}: ${error instanceof Error ? error.message : String(error)}`,
443
- "NETWORK_ERROR"
444
- );
445
- }
446
- if (!response.ok) {
447
- const errorMessage = await parseErrorResponse(response);
448
- const status = response.status;
449
- if (status === 400) {
450
- if (errorMessage.toLowerCase().includes("siwe")) {
451
- throw new SessionError(`Invalid SIWE message: ${errorMessage}`, "INVALID_MESSAGE", status);
452
- }
453
- throw new SessionError(`Bad request: ${errorMessage}`, "INVALID_MESSAGE", status);
454
- }
455
- if (status === 401) {
456
- throw new SessionError(`Invalid signature: ${errorMessage}`, "INVALID_SIGNATURE", status);
457
- }
458
- throw new SessionError(`Login failed: ${errorMessage}`, "UNKNOWN", status);
459
- }
460
- const data = await response.json();
461
- return {
462
- success: data.success,
463
- address: data.address
464
- };
465
- }
466
- async function getComputeApiSession(config) {
467
- let response;
468
- try {
469
- response = await fetch(`${config.baseUrl}/auth/session`, {
470
- method: "GET",
471
- credentials: "include",
472
- // Include cookies for session management
473
- headers: {
474
- "Content-Type": "application/json"
475
- }
476
- });
477
- } catch {
478
- return {
479
- authenticated: false
480
- };
481
- }
482
- if (response.status === 401) {
483
- return {
484
- authenticated: false
485
- };
486
- }
487
- if (!response.ok) {
488
- const errorMessage = await parseErrorResponse(response);
489
- throw new SessionError(`Failed to get session: ${errorMessage}`, "UNKNOWN", response.status);
490
- }
491
- const data = await response.json();
492
- return {
493
- authenticated: data.authenticated,
494
- address: data.address,
495
- chainId: data.chain_id
496
- };
497
- }
498
- async function logoutFromComputeApi(config) {
499
- let response;
500
- try {
501
- response = await fetch(`${config.baseUrl}/auth/logout`, {
502
- method: "POST",
503
- credentials: "include",
504
- // Include cookies for session management
505
- headers: {
506
- "Content-Type": "application/json"
507
- }
508
- });
509
- } catch (error) {
510
- throw new SessionError(
511
- `Network error connecting to ${config.baseUrl}: ${error instanceof Error ? error.message : String(error)}`,
512
- "NETWORK_ERROR"
513
- );
514
- }
515
- if (response.status === 401) {
516
- return;
517
- }
518
- if (!response.ok) {
519
- const errorMessage = await parseErrorResponse(response);
520
- throw new SessionError(`Logout failed: ${errorMessage}`, "UNKNOWN", response.status);
521
- }
522
- }
523
- async function isSessionValid(config) {
524
- const session = await getComputeApiSession(config);
525
- return session.authenticated;
526
- }
527
-
528
552
  // src/client/common/utils/userapi.ts
553
+ init_session();
529
554
  function isJsonObject(value) {
530
555
  return typeof value === "object" && value !== null && !Array.isArray(value);
531
556
  }
@@ -542,7 +567,7 @@ var CanViewAppLogsPermission = "0x2fd3f2fe";
542
567
  var CanViewSensitiveAppInfoPermission = "0x0e67b22f";
543
568
  var CanUpdateAppProfilePermission = "0x036fef61";
544
569
  function getDefaultClientId() {
545
- const version = true ? "0.2.2-dev" : "0.0.0";
570
+ const version = true ? "0.3.0-dev" : "0.0.0";
546
571
  return `ecloud-sdk/v${version}`;
547
572
  }
548
573
  var UserApiClient = class {
@@ -880,21 +905,233 @@ function transformAppRelease(raw) {
880
905
 
881
906
  // src/client/common/utils/billingapi.ts
882
907
  import axios2 from "axios";
908
+
909
+ // src/client/common/auth/billingSession.ts
910
+ var BillingSessionError = class extends Error {
911
+ constructor(message, code, statusCode) {
912
+ super(message);
913
+ this.code = code;
914
+ this.statusCode = statusCode;
915
+ this.name = "BillingSessionError";
916
+ }
917
+ };
918
+ function stripHexPrefix3(hex) {
919
+ return hex.startsWith("0x") ? hex.slice(2) : hex;
920
+ }
921
+ async function parseErrorResponse2(response) {
922
+ try {
923
+ const data = await response.json();
924
+ return data.error || response.statusText;
925
+ } catch {
926
+ return response.statusText;
927
+ }
928
+ }
929
+ async function loginToBillingApi(config, request) {
930
+ let response;
931
+ try {
932
+ response = await fetch(`${config.baseUrl}/auth/siwe/login`, {
933
+ method: "POST",
934
+ credentials: "include",
935
+ // Include cookies for session management
936
+ headers: {
937
+ "Content-Type": "application/json"
938
+ },
939
+ body: JSON.stringify({
940
+ message: request.message,
941
+ signature: stripHexPrefix3(request.signature)
942
+ })
943
+ });
944
+ } catch (error) {
945
+ throw new BillingSessionError(
946
+ `Network error connecting to ${config.baseUrl}: ${error instanceof Error ? error.message : String(error)}`,
947
+ "NETWORK_ERROR"
948
+ );
949
+ }
950
+ if (!response.ok) {
951
+ const errorMessage = await parseErrorResponse2(response);
952
+ const status = response.status;
953
+ if (status === 400) {
954
+ if (errorMessage.toLowerCase().includes("siwe")) {
955
+ throw new BillingSessionError(`Invalid SIWE message: ${errorMessage}`, "INVALID_MESSAGE", status);
956
+ }
957
+ throw new BillingSessionError(`Bad request: ${errorMessage}`, "INVALID_MESSAGE", status);
958
+ }
959
+ if (status === 401) {
960
+ throw new BillingSessionError(`Invalid signature: ${errorMessage}`, "INVALID_SIGNATURE", status);
961
+ }
962
+ throw new BillingSessionError(`Login failed: ${errorMessage}`, "UNKNOWN", status);
963
+ }
964
+ const data = await response.json();
965
+ return {
966
+ success: data.success,
967
+ address: data.address
968
+ };
969
+ }
970
+ async function getBillingApiSession(config) {
971
+ let response;
972
+ try {
973
+ response = await fetch(`${config.baseUrl}/auth/session`, {
974
+ method: "GET",
975
+ credentials: "include",
976
+ // Include cookies for session management
977
+ headers: {
978
+ "Content-Type": "application/json"
979
+ }
980
+ });
981
+ } catch {
982
+ return {
983
+ authenticated: false
984
+ };
985
+ }
986
+ if (response.status === 401) {
987
+ return {
988
+ authenticated: false
989
+ };
990
+ }
991
+ if (!response.ok) {
992
+ const errorMessage = await parseErrorResponse2(response);
993
+ throw new BillingSessionError(`Failed to get session: ${errorMessage}`, "UNKNOWN", response.status);
994
+ }
995
+ const data = await response.json();
996
+ return {
997
+ authenticated: data.authenticated,
998
+ address: data.address,
999
+ chainId: data.chainId,
1000
+ authenticatedAt: data.authenticatedAt
1001
+ };
1002
+ }
1003
+ async function logoutFromBillingApi(config) {
1004
+ let response;
1005
+ try {
1006
+ response = await fetch(`${config.baseUrl}/auth/logout`, {
1007
+ method: "POST",
1008
+ credentials: "include",
1009
+ // Include cookies for session management
1010
+ headers: {
1011
+ "Content-Type": "application/json"
1012
+ }
1013
+ });
1014
+ } catch (error) {
1015
+ throw new BillingSessionError(
1016
+ `Network error connecting to ${config.baseUrl}: ${error instanceof Error ? error.message : String(error)}`,
1017
+ "NETWORK_ERROR"
1018
+ );
1019
+ }
1020
+ if (response.status === 401) {
1021
+ return;
1022
+ }
1023
+ if (!response.ok) {
1024
+ const errorMessage = await parseErrorResponse2(response);
1025
+ throw new BillingSessionError(`Logout failed: ${errorMessage}`, "UNKNOWN", response.status);
1026
+ }
1027
+ }
1028
+ async function isBillingSessionValid(config) {
1029
+ const session = await getBillingApiSession(config);
1030
+ return session.authenticated;
1031
+ }
1032
+ async function loginToBothApis(computeConfig, billingConfig, request) {
1033
+ const { loginToComputeApi: loginToComputeApi2 } = await Promise.resolve().then(() => (init_session(), session_exports));
1034
+ const [compute, billing] = await Promise.all([
1035
+ loginToComputeApi2(computeConfig, request),
1036
+ loginToBillingApi(billingConfig, request)
1037
+ ]);
1038
+ return { compute, billing };
1039
+ }
1040
+ async function logoutFromBothApis(computeConfig, billingConfig) {
1041
+ const { logoutFromComputeApi: logoutFromComputeApi2 } = await Promise.resolve().then(() => (init_session(), session_exports));
1042
+ await Promise.all([
1043
+ logoutFromComputeApi2(computeConfig),
1044
+ logoutFromBillingApi(billingConfig)
1045
+ ]);
1046
+ }
1047
+
1048
+ // src/client/common/utils/billingapi.ts
883
1049
  var BillingApiClient = class {
884
- constructor(config, walletClient) {
1050
+ constructor(config, walletClient, options = {}) {
885
1051
  this.config = config;
886
1052
  this.walletClient = walletClient;
1053
+ this.options = options;
1054
+ this.useSession = options.useSession ?? false;
1055
+ if (!this.useSession && !walletClient) {
1056
+ throw new Error("WalletClient is required when not using session authentication");
1057
+ }
887
1058
  }
888
1059
  /**
889
1060
  * Get the address of the connected wallet
1061
+ * Returns undefined if using session auth without a wallet client
890
1062
  */
891
1063
  get address() {
892
- const account = this.walletClient.account;
1064
+ const account = this.walletClient?.account;
893
1065
  if (!account) {
894
- throw new Error("WalletClient must have an account attached");
1066
+ if (!this.useSession) {
1067
+ throw new Error("WalletClient must have an account attached");
1068
+ }
1069
+ return void 0;
895
1070
  }
896
1071
  return account.address;
897
1072
  }
1073
+ /**
1074
+ * Get the base URL of the billing API
1075
+ */
1076
+ get baseUrl() {
1077
+ return this.config.billingApiServerURL;
1078
+ }
1079
+ // ==========================================================================
1080
+ // SIWE Session Methods
1081
+ // ==========================================================================
1082
+ /**
1083
+ * Login to the billing API using SIWE
1084
+ *
1085
+ * This establishes a session with the billing API by verifying the SIWE message
1086
+ * and signature. On success, a session cookie is set in the browser.
1087
+ *
1088
+ * @param request - Login request containing SIWE message and signature
1089
+ * @returns Login result with the authenticated address
1090
+ *
1091
+ * @example
1092
+ * ```typescript
1093
+ * const { message } = createSiweMessage({
1094
+ * address: userAddress,
1095
+ * chainId: 11155111,
1096
+ * domain: window.location.host,
1097
+ * uri: window.location.origin,
1098
+ * });
1099
+ *
1100
+ * const signature = await signMessageAsync({ message });
1101
+ * const result = await billingClient.siweLogin({ message, signature });
1102
+ * ```
1103
+ */
1104
+ async siweLogin(request) {
1105
+ return loginToBillingApi({ baseUrl: this.baseUrl }, request);
1106
+ }
1107
+ /**
1108
+ * Logout from the billing API
1109
+ *
1110
+ * This destroys the current session and clears the session cookie.
1111
+ */
1112
+ async siweLogout() {
1113
+ return logoutFromBillingApi({ baseUrl: this.baseUrl });
1114
+ }
1115
+ /**
1116
+ * Get the current session status from the billing API
1117
+ *
1118
+ * @returns Session information including authentication status and address
1119
+ */
1120
+ async getSession() {
1121
+ return getBillingApiSession({ baseUrl: this.baseUrl });
1122
+ }
1123
+ /**
1124
+ * Check if there is a valid session
1125
+ *
1126
+ * @returns True if session is authenticated, false otherwise
1127
+ */
1128
+ async isSessionValid() {
1129
+ const session = await this.getSession();
1130
+ return session.authenticated;
1131
+ }
1132
+ // ==========================================================================
1133
+ // Subscription Methods
1134
+ // ==========================================================================
898
1135
  async createSubscription(productId = "compute", options) {
899
1136
  const endpoint = `${this.config.billingApiServerURL}/products/${productId}/subscription`;
900
1137
  const body = options ? {
@@ -913,10 +1150,72 @@ var BillingApiClient = class {
913
1150
  const endpoint = `${this.config.billingApiServerURL}/products/${productId}/subscription`;
914
1151
  await this.makeAuthenticatedRequest(endpoint, "DELETE", productId);
915
1152
  }
1153
+ // ==========================================================================
1154
+ // Internal Methods
1155
+ // ==========================================================================
916
1156
  /**
917
1157
  * Make an authenticated request to the billing API
1158
+ *
1159
+ * Uses session auth if useSession is true, otherwise uses EIP-712 signature auth.
918
1160
  */
919
1161
  async makeAuthenticatedRequest(url, method, productId, body) {
1162
+ if (this.useSession) {
1163
+ return this.makeSessionAuthenticatedRequest(url, method, body);
1164
+ }
1165
+ return this.makeSignatureAuthenticatedRequest(url, method, productId, body);
1166
+ }
1167
+ /**
1168
+ * Make a request using session-based authentication (cookies)
1169
+ */
1170
+ async makeSessionAuthenticatedRequest(url, method, body) {
1171
+ const headers = {};
1172
+ if (body) {
1173
+ headers["Content-Type"] = "application/json";
1174
+ }
1175
+ try {
1176
+ const response = await fetch(url, {
1177
+ method,
1178
+ credentials: "include",
1179
+ // Include cookies for session management
1180
+ headers,
1181
+ body: body ? JSON.stringify(body) : void 0
1182
+ });
1183
+ const status = response.status;
1184
+ const statusText = status >= 200 && status < 300 ? "OK" : "Error";
1185
+ if (status < 200 || status >= 300) {
1186
+ let errorBody;
1187
+ try {
1188
+ errorBody = await response.text();
1189
+ } catch {
1190
+ errorBody = statusText;
1191
+ }
1192
+ throw new Error(`BillingAPI request failed: ${status} ${statusText} - ${errorBody}`);
1193
+ }
1194
+ const responseData = await response.json();
1195
+ return {
1196
+ json: async () => responseData,
1197
+ text: async () => JSON.stringify(responseData)
1198
+ };
1199
+ } catch (error) {
1200
+ if (error.name === "TypeError" || error.message?.includes("fetch")) {
1201
+ throw new Error(
1202
+ `Failed to connect to BillingAPI at ${url}: ${error.message}
1203
+ Please check:
1204
+ 1. Your internet connection
1205
+ 2. The API server is accessible: ${this.config.billingApiServerURL}
1206
+ 3. Firewall/proxy settings`
1207
+ );
1208
+ }
1209
+ throw error;
1210
+ }
1211
+ }
1212
+ /**
1213
+ * Make a request using EIP-712 signature authentication
1214
+ */
1215
+ async makeSignatureAuthenticatedRequest(url, method, productId, body) {
1216
+ if (!this.walletClient) {
1217
+ throw new Error("WalletClient is required for signature authentication");
1218
+ }
920
1219
  const expiry = BigInt(Math.floor(Date.now() / 1e3) + 5 * 60);
921
1220
  const { signature } = await calculateBillingAuthSignature({
922
1221
  walletClient: this.walletClient,
@@ -1003,9 +1302,22 @@ async function requestWithRetry(config) {
1003
1302
  }
1004
1303
  var BuildApiClient = class {
1005
1304
  constructor(options) {
1006
- this.baseUrl = options.baseUrl.replace(/\/+$/, "");
1305
+ let url = options.baseUrl;
1306
+ while (url.endsWith("/")) {
1307
+ url = url.slice(0, -1);
1308
+ }
1309
+ this.baseUrl = url;
1007
1310
  this.clientId = options.clientId;
1008
1311
  this.walletClient = options.walletClient;
1312
+ this.useSession = options.useSession ?? false;
1313
+ this.billingSessionId = options.billingSessionId;
1314
+ }
1315
+ /**
1316
+ * Update the billing session ID.
1317
+ * Call this after logging into the billing API to enable session-based auth for builds.
1318
+ */
1319
+ setBillingSessionId(sessionId) {
1320
+ this.billingSessionId = sessionId;
1009
1321
  }
1010
1322
  /**
1011
1323
  * Get the address of the connected wallet
@@ -1017,8 +1329,17 @@ var BuildApiClient = class {
1017
1329
  }
1018
1330
  return account.address;
1019
1331
  }
1332
+ /**
1333
+ * Submit a new build request.
1334
+ * Supports two auth modes (session auth is tried first when billingSessionId is available):
1335
+ * 1. Session-based auth: X-Billing-Session header (forwarded billing_session cookie)
1336
+ * 2. Signature-based auth: Authorization + X-Account + X-eigenx-expiry headers (requires walletClient)
1337
+ */
1020
1338
  async submitBuild(payload) {
1021
- return this.authenticatedJsonRequest("/builds", "POST", payload);
1339
+ if (this.useSession && this.billingSessionId) {
1340
+ return this.billingSessionAuthJsonRequest("/builds", "POST", payload);
1341
+ }
1342
+ return this.signatureAuthJsonRequest("/builds", "POST", payload);
1022
1343
  }
1023
1344
  async getBuild(buildId) {
1024
1345
  return this.publicJsonRequest(`/builds/${encodeURIComponent(buildId)}`);
@@ -1029,8 +1350,11 @@ var BuildApiClient = class {
1029
1350
  async verify(identifier) {
1030
1351
  return this.publicJsonRequest(`/builds/verify/${encodeURIComponent(identifier)}`);
1031
1352
  }
1353
+ /**
1354
+ * Get build logs. Supports session auth (identity verification only, no billing check).
1355
+ */
1032
1356
  async getLogs(buildId) {
1033
- return this.authenticatedTextRequest(`/builds/${encodeURIComponent(buildId)}/logs`);
1357
+ return this.sessionOrSignatureTextRequest(`/builds/${encodeURIComponent(buildId)}/logs`);
1034
1358
  }
1035
1359
  async listBuilds(params) {
1036
1360
  const res = await requestWithRetry({
@@ -1038,7 +1362,9 @@ var BuildApiClient = class {
1038
1362
  method: "GET",
1039
1363
  params,
1040
1364
  headers: this.clientId ? { "x-client-id": this.clientId } : void 0,
1041
- timeout: 6e4
1365
+ timeout: 6e4,
1366
+ validateStatus: () => true,
1367
+ withCredentials: this.useSession
1042
1368
  });
1043
1369
  if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
1044
1370
  return res.data;
@@ -1048,12 +1374,18 @@ var BuildApiClient = class {
1048
1374
  url: `${this.baseUrl}${path}`,
1049
1375
  method: "GET",
1050
1376
  headers: this.clientId ? { "x-client-id": this.clientId } : void 0,
1051
- timeout: 6e4
1377
+ timeout: 6e4,
1378
+ validateStatus: () => true,
1379
+ withCredentials: this.useSession
1052
1380
  });
1053
1381
  if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
1054
1382
  return res.data;
1055
1383
  }
1056
- async authenticatedJsonRequest(path, method, body) {
1384
+ /**
1385
+ * Make a request that ALWAYS requires signature auth (for billing verification).
1386
+ * Used for endpoints like POST /builds that need to verify subscription status.
1387
+ */
1388
+ async signatureAuthJsonRequest(path, method, body) {
1057
1389
  if (!this.walletClient?.account) {
1058
1390
  throw new Error("WalletClient with account required for authenticated requests");
1059
1391
  }
@@ -1075,32 +1407,69 @@ var BuildApiClient = class {
1075
1407
  method,
1076
1408
  headers,
1077
1409
  data: body,
1078
- timeout: 6e4
1410
+ timeout: 6e4,
1411
+ validateStatus: () => true,
1412
+ withCredentials: this.useSession
1079
1413
  });
1080
1414
  if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
1081
1415
  return res.data;
1082
1416
  }
1083
- async authenticatedTextRequest(path) {
1084
- if (!this.walletClient?.account) {
1085
- throw new Error("WalletClient with account required for authenticated requests");
1417
+ /**
1418
+ * Make a request using billing session auth (for billing verification without wallet signature).
1419
+ * Forwards the billing_session cookie value via X-Billing-Session header.
1420
+ * Used for endpoints that need to verify subscription status when using session-based auth.
1421
+ */
1422
+ async billingSessionAuthJsonRequest(path, method, body) {
1423
+ if (!this.billingSessionId) {
1424
+ throw new Error("billingSessionId required for session-based billing auth");
1086
1425
  }
1087
- const headers = {};
1426
+ const headers = {
1427
+ "Content-Type": "application/json",
1428
+ "X-Billing-Session": this.billingSessionId
1429
+ };
1088
1430
  if (this.clientId) headers["x-client-id"] = this.clientId;
1089
- const expiry = BigInt(Math.floor(Date.now() / 1e3) + 60);
1090
- const { signature } = await calculateBillingAuthSignature({
1091
- walletClient: this.walletClient,
1092
- product: "compute",
1093
- expiry
1431
+ const res = await requestWithRetry({
1432
+ url: `${this.baseUrl}${path}`,
1433
+ method,
1434
+ headers,
1435
+ data: body,
1436
+ timeout: 6e4,
1437
+ validateStatus: () => true,
1438
+ withCredentials: this.useSession
1094
1439
  });
1095
- headers.Authorization = `Bearer ${signature}`;
1096
- headers["X-eigenx-expiry"] = expiry.toString();
1097
- headers["X-Account"] = this.address;
1440
+ if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
1441
+ return res.data;
1442
+ }
1443
+ /**
1444
+ * Make an authenticated request that can use session OR signature auth.
1445
+ * When useSession is true, relies on cookies for identity verification.
1446
+ * Used for endpoints that only need identity verification (not billing).
1447
+ */
1448
+ async sessionOrSignatureTextRequest(path) {
1449
+ const headers = {};
1450
+ if (this.clientId) headers["x-client-id"] = this.clientId;
1451
+ if (!this.useSession) {
1452
+ if (!this.walletClient?.account) {
1453
+ throw new Error("WalletClient with account required for authenticated requests");
1454
+ }
1455
+ const expiry = BigInt(Math.floor(Date.now() / 1e3) + 60);
1456
+ const { signature } = await calculateBillingAuthSignature({
1457
+ walletClient: this.walletClient,
1458
+ product: "compute",
1459
+ expiry
1460
+ });
1461
+ headers.Authorization = `Bearer ${signature}`;
1462
+ headers["X-eigenx-expiry"] = expiry.toString();
1463
+ headers["X-Account"] = this.address;
1464
+ }
1098
1465
  const res = await requestWithRetry({
1099
1466
  url: `${this.baseUrl}${path}`,
1100
1467
  method: "GET",
1101
1468
  headers,
1102
1469
  timeout: 6e4,
1103
- responseType: "text"
1470
+ responseType: "text",
1471
+ validateStatus: () => true,
1472
+ withCredentials: this.useSession
1104
1473
  });
1105
1474
  if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
1106
1475
  return typeof res.data === "string" ? res.data : JSON.stringify(res.data);
@@ -4589,7 +4958,11 @@ function isSiweMessageNotYetValid(params) {
4589
4958
  return /* @__PURE__ */ new Date() < params.notBefore;
4590
4959
  }
4591
4960
 
4961
+ // src/browser.ts
4962
+ init_session();
4963
+
4592
4964
  // src/client/common/hooks/useComputeSession.ts
4965
+ init_session();
4593
4966
  import { useCallback, useEffect, useRef, useState } from "react";
4594
4967
  function useComputeSession(config) {
4595
4968
  const {
@@ -4847,6 +5220,7 @@ function getKMSKeysForEnvironment(environment, build = "prod") {
4847
5220
  }
4848
5221
  export {
4849
5222
  BillingApiClient,
5223
+ BillingSessionError,
4850
5224
  BuildApiClient,
4851
5225
  SessionError,
4852
5226
  UserApiClient,
@@ -4878,6 +5252,7 @@ export {
4878
5252
  getAppsByCreator,
4879
5253
  getAppsByDeveloper,
4880
5254
  getAvailableEnvironments,
5255
+ getBillingApiSession,
4881
5256
  getBillingEnvironmentConfig,
4882
5257
  getBuildType,
4883
5258
  getChainFromID,
@@ -4885,6 +5260,7 @@ export {
4885
5260
  getEnvironmentConfig,
4886
5261
  getKMSKeysForEnvironment,
4887
5262
  getMaxActiveAppsPerUser,
5263
+ isBillingSessionValid,
4888
5264
  isDelegated,
4889
5265
  isEnvironmentAvailable,
4890
5266
  isMainnet,
@@ -4892,7 +5268,11 @@ export {
4892
5268
  isSiweMessageExpired,
4893
5269
  isSiweMessageNotYetValid,
4894
5270
  isSubscriptionActive,
5271
+ loginToBillingApi,
5272
+ loginToBothApis,
4895
5273
  loginToComputeApi,
5274
+ logoutFromBillingApi,
5275
+ logoutFromBothApis,
4896
5276
  logoutFromComputeApi,
4897
5277
  noopLogger,
4898
5278
  parseSiweMessage,