@layr-labs/ecloud-sdk 0.2.1-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/VERSION +2 -2
- package/dist/billing.cjs +286 -9
- package/dist/billing.cjs.map +1 -1
- package/dist/billing.d.cts +1 -1
- package/dist/billing.d.ts +1 -1
- package/dist/billing.js +288 -9
- package/dist/billing.js.map +1 -1
- package/dist/browser.cjs +2551 -127
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +243 -5
- package/dist/browser.d.ts +243 -5
- package/dist/browser.js +2514 -132
- package/dist/browser.js.map +1 -1
- package/dist/{compute-B85ikS78.d.ts → compute-CdZxISln.d.ts} +1 -1
- package/dist/{compute-CC0R7HEu.d.cts → compute-Dstl0CA0.d.cts} +1 -1
- package/dist/compute.cjs +247 -22
- package/dist/compute.cjs.map +1 -1
- package/dist/compute.d.cts +2 -2
- package/dist/compute.d.ts +2 -2
- package/dist/compute.js +250 -27
- package/dist/compute.js.map +1 -1
- package/dist/helpers-4w0Iojmm.d.ts +983 -0
- package/dist/helpers-Dk0zwgms.d.cts +983 -0
- package/dist/{index-D5oW73Dx.d.cts → index-C0w92tCs.d.cts} +313 -2
- package/dist/{index-D5oW73Dx.d.ts → index-C0w92tCs.d.ts} +313 -2
- package/dist/index.cjs +751 -60
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -88
- package/dist/index.d.ts +8 -88
- package/dist/index.js +743 -65
- package/dist/index.js.map +1 -1
- package/package.json +12 -2
- package/dist/eip7702-CXCYfOnk.d.ts +0 -400
- package/dist/eip7702-DeqoCP5b.d.cts +0 -400
package/dist/index.cjs
CHANGED
|
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __esm = (fn, res) => function __init() {
|
|
9
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
10
|
+
};
|
|
8
11
|
var __export = (target, all) => {
|
|
9
12
|
for (var name in all)
|
|
10
13
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -27,6 +30,135 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
27
30
|
));
|
|
28
31
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
32
|
|
|
33
|
+
// src/client/common/auth/session.ts
|
|
34
|
+
function stripHexPrefix2(hex) {
|
|
35
|
+
return hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
36
|
+
}
|
|
37
|
+
async function parseErrorResponse(response) {
|
|
38
|
+
try {
|
|
39
|
+
const data = await response.json();
|
|
40
|
+
return data.error || response.statusText;
|
|
41
|
+
} catch {
|
|
42
|
+
return response.statusText;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
async function loginToComputeApi(config, request) {
|
|
46
|
+
let response;
|
|
47
|
+
try {
|
|
48
|
+
response = await fetch(`${config.baseUrl}/auth/siwe/login`, {
|
|
49
|
+
method: "POST",
|
|
50
|
+
credentials: "include",
|
|
51
|
+
// Include cookies for session management
|
|
52
|
+
headers: {
|
|
53
|
+
"Content-Type": "application/json"
|
|
54
|
+
},
|
|
55
|
+
body: JSON.stringify({
|
|
56
|
+
message: request.message,
|
|
57
|
+
signature: stripHexPrefix2(request.signature)
|
|
58
|
+
})
|
|
59
|
+
});
|
|
60
|
+
} catch (error) {
|
|
61
|
+
throw new SessionError(
|
|
62
|
+
`Network error connecting to ${config.baseUrl}: ${error instanceof Error ? error.message : String(error)}`,
|
|
63
|
+
"NETWORK_ERROR"
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
if (!response.ok) {
|
|
67
|
+
const errorMessage = await parseErrorResponse(response);
|
|
68
|
+
const status = response.status;
|
|
69
|
+
if (status === 400) {
|
|
70
|
+
if (errorMessage.toLowerCase().includes("siwe")) {
|
|
71
|
+
throw new SessionError(`Invalid SIWE message: ${errorMessage}`, "INVALID_MESSAGE", status);
|
|
72
|
+
}
|
|
73
|
+
throw new SessionError(`Bad request: ${errorMessage}`, "INVALID_MESSAGE", status);
|
|
74
|
+
}
|
|
75
|
+
if (status === 401) {
|
|
76
|
+
throw new SessionError(`Invalid signature: ${errorMessage}`, "INVALID_SIGNATURE", status);
|
|
77
|
+
}
|
|
78
|
+
throw new SessionError(`Login failed: ${errorMessage}`, "UNKNOWN", status);
|
|
79
|
+
}
|
|
80
|
+
const data = await response.json();
|
|
81
|
+
return {
|
|
82
|
+
success: data.success,
|
|
83
|
+
address: data.address
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
async function getComputeApiSession(config) {
|
|
87
|
+
let response;
|
|
88
|
+
try {
|
|
89
|
+
response = await fetch(`${config.baseUrl}/auth/session`, {
|
|
90
|
+
method: "GET",
|
|
91
|
+
credentials: "include",
|
|
92
|
+
// Include cookies for session management
|
|
93
|
+
headers: {
|
|
94
|
+
"Content-Type": "application/json"
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
} catch {
|
|
98
|
+
return {
|
|
99
|
+
authenticated: false
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
if (response.status === 401) {
|
|
103
|
+
return {
|
|
104
|
+
authenticated: false
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
if (!response.ok) {
|
|
108
|
+
const errorMessage = await parseErrorResponse(response);
|
|
109
|
+
throw new SessionError(`Failed to get session: ${errorMessage}`, "UNKNOWN", response.status);
|
|
110
|
+
}
|
|
111
|
+
const data = await response.json();
|
|
112
|
+
return {
|
|
113
|
+
authenticated: data.authenticated,
|
|
114
|
+
address: data.address,
|
|
115
|
+
chainId: data.chain_id
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
async function logoutFromComputeApi(config) {
|
|
119
|
+
let response;
|
|
120
|
+
try {
|
|
121
|
+
response = await fetch(`${config.baseUrl}/auth/logout`, {
|
|
122
|
+
method: "POST",
|
|
123
|
+
credentials: "include",
|
|
124
|
+
// Include cookies for session management
|
|
125
|
+
headers: {
|
|
126
|
+
"Content-Type": "application/json"
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
} catch (error) {
|
|
130
|
+
throw new SessionError(
|
|
131
|
+
`Network error connecting to ${config.baseUrl}: ${error instanceof Error ? error.message : String(error)}`,
|
|
132
|
+
"NETWORK_ERROR"
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
if (response.status === 401) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
if (!response.ok) {
|
|
139
|
+
const errorMessage = await parseErrorResponse(response);
|
|
140
|
+
throw new SessionError(`Logout failed: ${errorMessage}`, "UNKNOWN", response.status);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
async function isSessionValid(config) {
|
|
144
|
+
const session = await getComputeApiSession(config);
|
|
145
|
+
return session.authenticated;
|
|
146
|
+
}
|
|
147
|
+
var SessionError;
|
|
148
|
+
var init_session = __esm({
|
|
149
|
+
"src/client/common/auth/session.ts"() {
|
|
150
|
+
"use strict";
|
|
151
|
+
SessionError = class extends Error {
|
|
152
|
+
constructor(message, code, statusCode) {
|
|
153
|
+
super(message);
|
|
154
|
+
this.code = code;
|
|
155
|
+
this.statusCode = statusCode;
|
|
156
|
+
this.name = "SessionError";
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
|
|
30
162
|
// src/index.ts
|
|
31
163
|
var index_exports = {};
|
|
32
164
|
__export(index_exports, {
|
|
@@ -42,6 +174,7 @@ __export(index_exports, {
|
|
|
42
174
|
NotFoundError: () => NotFoundError,
|
|
43
175
|
PRIMARY_LANGUAGES: () => PRIMARY_LANGUAGES,
|
|
44
176
|
PostHogClient: () => PostHogClient,
|
|
177
|
+
SessionError: () => SessionError,
|
|
45
178
|
TimeoutError: () => TimeoutError,
|
|
46
179
|
UserApiClient: () => UserApiClient,
|
|
47
180
|
addHexPrefix: () => addHexPrefix,
|
|
@@ -58,6 +191,7 @@ __export(index_exports, {
|
|
|
58
191
|
createComputeModule: () => createComputeModule,
|
|
59
192
|
createECloudClient: () => createECloudClient,
|
|
60
193
|
createMetricsContext: () => createMetricsContext,
|
|
194
|
+
createSiweMessage: () => createSiweMessage,
|
|
61
195
|
createTelemetryClient: () => createTelemetryClient,
|
|
62
196
|
createViemClients: () => createClients,
|
|
63
197
|
deleteLegacyPrivateKey: () => deleteLegacyPrivateKey,
|
|
@@ -74,6 +208,7 @@ __export(index_exports, {
|
|
|
74
208
|
fetchTemplateCatalog: () => fetchTemplateCatalog,
|
|
75
209
|
formatETH: () => formatETH,
|
|
76
210
|
generateNewPrivateKey: () => generateNewPrivateKey,
|
|
211
|
+
generateNonce: () => generateNonce,
|
|
77
212
|
getAddressFromPrivateKey: () => getAddressFromPrivateKey,
|
|
78
213
|
getAllAppsByDeveloper: () => getAllAppsByDeveloper,
|
|
79
214
|
getAppLatestReleaseBlockNumbers: () => getAppLatestReleaseBlockNumbers,
|
|
@@ -84,6 +219,7 @@ __export(index_exports, {
|
|
|
84
219
|
getBuildType: () => getBuildType,
|
|
85
220
|
getCategoryDescriptions: () => getCategoryDescriptions,
|
|
86
221
|
getChainFromID: () => getChainFromID,
|
|
222
|
+
getComputeApiSession: () => getComputeApiSession,
|
|
87
223
|
getCurrentInstanceType: () => getCurrentInstanceType,
|
|
88
224
|
getEnvironmentConfig: () => getEnvironmentConfig,
|
|
89
225
|
getLegacyKeys: () => getLegacyKeys,
|
|
@@ -96,10 +232,17 @@ __export(index_exports, {
|
|
|
96
232
|
isEnvironmentAvailable: () => isEnvironmentAvailable,
|
|
97
233
|
isMainnet: () => isMainnet,
|
|
98
234
|
isNoopClient: () => isNoopClient,
|
|
235
|
+
isSessionValid: () => isSessionValid,
|
|
236
|
+
isSiweMessageExpired: () => isSiweMessageExpired,
|
|
237
|
+
isSiweMessageNotYetValid: () => isSiweMessageNotYetValid,
|
|
99
238
|
isSubscriptionActive: () => isSubscriptionActive,
|
|
100
239
|
keyExists: () => keyExists,
|
|
101
240
|
listStoredKeys: () => listStoredKeys,
|
|
241
|
+
loginToComputeApi: () => loginToComputeApi,
|
|
242
|
+
logoutFromComputeApi: () => logoutFromComputeApi,
|
|
102
243
|
logs: () => logs,
|
|
244
|
+
noopLogger: () => noopLogger,
|
|
245
|
+
parseSiweMessage: () => parseSiweMessage,
|
|
103
246
|
prepareDeploy: () => prepareDeploy,
|
|
104
247
|
prepareDeployFromVerifiableBuild: () => prepareDeployFromVerifiableBuild,
|
|
105
248
|
prepareUpgrade: () => prepareUpgrade,
|
|
@@ -1237,6 +1380,18 @@ function extractRegistryNameNoDocker(imageRef) {
|
|
|
1237
1380
|
// src/client/common/contract/eip7702.ts
|
|
1238
1381
|
var import_viem = require("viem");
|
|
1239
1382
|
|
|
1383
|
+
// src/client/common/types/index.ts
|
|
1384
|
+
var noopLogger = {
|
|
1385
|
+
debug: () => {
|
|
1386
|
+
},
|
|
1387
|
+
info: () => {
|
|
1388
|
+
},
|
|
1389
|
+
warn: () => {
|
|
1390
|
+
},
|
|
1391
|
+
error: () => {
|
|
1392
|
+
}
|
|
1393
|
+
};
|
|
1394
|
+
|
|
1240
1395
|
// src/client/common/abis/ERC7702Delegator.json
|
|
1241
1396
|
var ERC7702Delegator_default = [
|
|
1242
1397
|
{
|
|
@@ -2322,7 +2477,7 @@ async function checkERC7702Delegation(publicClient, account, delegatorAddress) {
|
|
|
2322
2477
|
const expectedCode = `0xef0100${delegatorAddress.slice(2)}`;
|
|
2323
2478
|
return code.toLowerCase() === expectedCode.toLowerCase();
|
|
2324
2479
|
}
|
|
2325
|
-
async function executeBatch(options, logger) {
|
|
2480
|
+
async function executeBatch(options, logger = noopLogger) {
|
|
2326
2481
|
const { walletClient, publicClient, environmentConfig, executions, pendingMessage, gas } = options;
|
|
2327
2482
|
const account = walletClient.account;
|
|
2328
2483
|
if (!account) {
|
|
@@ -4027,7 +4182,7 @@ async function calculateAppID(options) {
|
|
|
4027
4182
|
});
|
|
4028
4183
|
return appID;
|
|
4029
4184
|
}
|
|
4030
|
-
async function prepareDeployBatch(options, logger) {
|
|
4185
|
+
async function prepareDeployBatch(options, logger = noopLogger) {
|
|
4031
4186
|
const { walletClient, publicClient, environmentConfig, salt, release, publicLogs } = options;
|
|
4032
4187
|
const account = walletClient.account;
|
|
4033
4188
|
if (!account) {
|
|
@@ -4107,7 +4262,7 @@ async function prepareDeployBatch(options, logger) {
|
|
|
4107
4262
|
environmentConfig
|
|
4108
4263
|
};
|
|
4109
4264
|
}
|
|
4110
|
-
async function executeDeployBatch(data, context, gas, logger) {
|
|
4265
|
+
async function executeDeployBatch(data, context, gas, logger = noopLogger) {
|
|
4111
4266
|
const pendingMessage = "Deploying new app...";
|
|
4112
4267
|
const txHash = await executeBatch(
|
|
4113
4268
|
{
|
|
@@ -4122,7 +4277,7 @@ async function executeDeployBatch(data, context, gas, logger) {
|
|
|
4122
4277
|
);
|
|
4123
4278
|
return { appId: data.appId, txHash };
|
|
4124
4279
|
}
|
|
4125
|
-
async function deployApp(options, logger) {
|
|
4280
|
+
async function deployApp(options, logger = noopLogger) {
|
|
4126
4281
|
const prepared = await prepareDeployBatch(options, logger);
|
|
4127
4282
|
const data = {
|
|
4128
4283
|
appId: prepared.appId,
|
|
@@ -4137,7 +4292,15 @@ async function deployApp(options, logger) {
|
|
|
4137
4292
|
return executeDeployBatch(data, context, options.gas, logger);
|
|
4138
4293
|
}
|
|
4139
4294
|
async function prepareUpgradeBatch(options) {
|
|
4140
|
-
const {
|
|
4295
|
+
const {
|
|
4296
|
+
walletClient,
|
|
4297
|
+
publicClient,
|
|
4298
|
+
environmentConfig,
|
|
4299
|
+
appID,
|
|
4300
|
+
release,
|
|
4301
|
+
publicLogs,
|
|
4302
|
+
needsPermissionChange
|
|
4303
|
+
} = options;
|
|
4141
4304
|
const releaseForViem = {
|
|
4142
4305
|
rmsRelease: {
|
|
4143
4306
|
artifacts: release.rmsRelease.artifacts.map((artifact) => ({
|
|
@@ -4210,7 +4373,7 @@ async function prepareUpgradeBatch(options) {
|
|
|
4210
4373
|
environmentConfig
|
|
4211
4374
|
};
|
|
4212
4375
|
}
|
|
4213
|
-
async function executeUpgradeBatch(data, context, gas, logger) {
|
|
4376
|
+
async function executeUpgradeBatch(data, context, gas, logger = noopLogger) {
|
|
4214
4377
|
const pendingMessage = `Upgrading app ${data.appId}...`;
|
|
4215
4378
|
const txHash = await executeBatch(
|
|
4216
4379
|
{
|
|
@@ -4225,7 +4388,7 @@ async function executeUpgradeBatch(data, context, gas, logger) {
|
|
|
4225
4388
|
);
|
|
4226
4389
|
return txHash;
|
|
4227
4390
|
}
|
|
4228
|
-
async function upgradeApp(options, logger) {
|
|
4391
|
+
async function upgradeApp(options, logger = noopLogger) {
|
|
4229
4392
|
const prepared = await prepareUpgradeBatch(options);
|
|
4230
4393
|
const data = {
|
|
4231
4394
|
appId: prepared.appId,
|
|
@@ -4238,8 +4401,18 @@ async function upgradeApp(options, logger) {
|
|
|
4238
4401
|
};
|
|
4239
4402
|
return executeUpgradeBatch(data, context, options.gas, logger);
|
|
4240
4403
|
}
|
|
4241
|
-
async function sendAndWaitForTransaction(options, logger) {
|
|
4242
|
-
const {
|
|
4404
|
+
async function sendAndWaitForTransaction(options, logger = noopLogger) {
|
|
4405
|
+
const {
|
|
4406
|
+
walletClient,
|
|
4407
|
+
publicClient,
|
|
4408
|
+
environmentConfig,
|
|
4409
|
+
to,
|
|
4410
|
+
data,
|
|
4411
|
+
value = 0n,
|
|
4412
|
+
pendingMessage,
|
|
4413
|
+
txDescription,
|
|
4414
|
+
gas
|
|
4415
|
+
} = options;
|
|
4243
4416
|
const account = walletClient.account;
|
|
4244
4417
|
if (!account) {
|
|
4245
4418
|
throw new Error("WalletClient must have an account attached");
|
|
@@ -4359,7 +4532,13 @@ async function getAllAppsByDeveloper(publicClient, env, developer, pageSize = 10
|
|
|
4359
4532
|
const allApps = [];
|
|
4360
4533
|
const allConfigs = [];
|
|
4361
4534
|
while (true) {
|
|
4362
|
-
const { apps, appConfigs } = await getAppsByDeveloper(
|
|
4535
|
+
const { apps, appConfigs } = await getAppsByDeveloper(
|
|
4536
|
+
publicClient,
|
|
4537
|
+
env,
|
|
4538
|
+
developer,
|
|
4539
|
+
offset,
|
|
4540
|
+
pageSize
|
|
4541
|
+
);
|
|
4363
4542
|
if (apps.length === 0) break;
|
|
4364
4543
|
allApps.push(...apps);
|
|
4365
4544
|
allConfigs.push(...appConfigs);
|
|
@@ -4415,7 +4594,7 @@ async function isDelegated(options) {
|
|
|
4415
4594
|
environmentConfig.erc7702DelegatorAddress
|
|
4416
4595
|
);
|
|
4417
4596
|
}
|
|
4418
|
-
async function undelegate(options, logger) {
|
|
4597
|
+
async function undelegate(options, logger = noopLogger) {
|
|
4419
4598
|
const { walletClient, publicClient, environmentConfig } = options;
|
|
4420
4599
|
const account = walletClient.account;
|
|
4421
4600
|
if (!account) {
|
|
@@ -4514,6 +4693,7 @@ async function calculateBillingAuthSignature(options) {
|
|
|
4514
4693
|
}
|
|
4515
4694
|
|
|
4516
4695
|
// src/client/common/utils/userapi.ts
|
|
4696
|
+
init_session();
|
|
4517
4697
|
function isJsonObject(value) {
|
|
4518
4698
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4519
4699
|
}
|
|
@@ -4530,15 +4710,16 @@ var CanViewAppLogsPermission = "0x2fd3f2fe";
|
|
|
4530
4710
|
var CanViewSensitiveAppInfoPermission = "0x0e67b22f";
|
|
4531
4711
|
var CanUpdateAppProfilePermission = "0x036fef61";
|
|
4532
4712
|
function getDefaultClientId() {
|
|
4533
|
-
const version = true ? "0.
|
|
4713
|
+
const version = true ? "0.3.0-dev" : "0.0.0";
|
|
4534
4714
|
return `ecloud-sdk/v${version}`;
|
|
4535
4715
|
}
|
|
4536
4716
|
var UserApiClient = class {
|
|
4537
|
-
constructor(config, walletClient, publicClient,
|
|
4717
|
+
constructor(config, walletClient, publicClient, options) {
|
|
4538
4718
|
this.config = config;
|
|
4539
4719
|
this.walletClient = walletClient;
|
|
4540
4720
|
this.publicClient = publicClient;
|
|
4541
|
-
this.clientId = clientId || getDefaultClientId();
|
|
4721
|
+
this.clientId = options?.clientId || getDefaultClientId();
|
|
4722
|
+
this.useSession = options?.useSession ?? false;
|
|
4542
4723
|
}
|
|
4543
4724
|
/**
|
|
4544
4725
|
* Get the address of the connected wallet
|
|
@@ -4626,7 +4807,7 @@ var UserApiClient = class {
|
|
|
4626
4807
|
const apps = result.apps || result.Apps || [];
|
|
4627
4808
|
return apps.map((app, i) => ({
|
|
4628
4809
|
address: app.address || appIDs[i],
|
|
4629
|
-
status: app.
|
|
4810
|
+
status: app.app_status || app.App_Status || ""
|
|
4630
4811
|
}));
|
|
4631
4812
|
}
|
|
4632
4813
|
/**
|
|
@@ -4658,9 +4839,11 @@ var UserApiClient = class {
|
|
|
4658
4839
|
const headers = {
|
|
4659
4840
|
"x-client-id": this.clientId
|
|
4660
4841
|
};
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
|
|
4842
|
+
if (!this.useSession) {
|
|
4843
|
+
const expiry = BigInt(Math.floor(Date.now() / 1e3) + 5 * 60);
|
|
4844
|
+
const authHeaders = await this.generateAuthHeaders(CanUpdateAppProfilePermission, expiry);
|
|
4845
|
+
Object.assign(headers, authHeaders);
|
|
4846
|
+
}
|
|
4664
4847
|
try {
|
|
4665
4848
|
const response = await import_axios.default.post(endpoint, formData, {
|
|
4666
4849
|
headers,
|
|
@@ -4669,8 +4852,10 @@ var UserApiClient = class {
|
|
|
4669
4852
|
// Don't throw on any status
|
|
4670
4853
|
maxContentLength: Infinity,
|
|
4671
4854
|
// Allow large file uploads
|
|
4672
|
-
maxBodyLength: Infinity
|
|
4855
|
+
maxBodyLength: Infinity,
|
|
4673
4856
|
// Allow large file uploads
|
|
4857
|
+
withCredentials: true
|
|
4858
|
+
// Include cookies for session auth
|
|
4674
4859
|
});
|
|
4675
4860
|
const status = response.status;
|
|
4676
4861
|
if (status !== 200 && status !== 201) {
|
|
@@ -4704,7 +4889,7 @@ Please check:
|
|
|
4704
4889
|
const headers = {
|
|
4705
4890
|
"x-client-id": this.clientId
|
|
4706
4891
|
};
|
|
4707
|
-
if (permission) {
|
|
4892
|
+
if (permission && !this.useSession) {
|
|
4708
4893
|
const expiry = BigInt(Math.floor(Date.now() / 1e3) + 5 * 60);
|
|
4709
4894
|
const authHeaders = await this.generateAuthHeaders(permission, expiry);
|
|
4710
4895
|
Object.assign(headers, authHeaders);
|
|
@@ -4713,8 +4898,10 @@ Please check:
|
|
|
4713
4898
|
const response = await import_axios.default.get(url, {
|
|
4714
4899
|
headers,
|
|
4715
4900
|
maxRedirects: 0,
|
|
4716
|
-
validateStatus: () => true
|
|
4901
|
+
validateStatus: () => true,
|
|
4717
4902
|
// Don't throw on any status
|
|
4903
|
+
withCredentials: true
|
|
4904
|
+
// Include cookies for session auth
|
|
4718
4905
|
});
|
|
4719
4906
|
const status = response.status;
|
|
4720
4907
|
const statusText = status >= 200 && status < 300 ? "OK" : "Error";
|
|
@@ -4756,6 +4943,65 @@ Please check:
|
|
|
4756
4943
|
"X-eigenx-expiry": expiry.toString()
|
|
4757
4944
|
};
|
|
4758
4945
|
}
|
|
4946
|
+
// ==========================================================================
|
|
4947
|
+
// SIWE Session Management
|
|
4948
|
+
// ==========================================================================
|
|
4949
|
+
/**
|
|
4950
|
+
* Login to the compute API using SIWE (Sign-In with Ethereum)
|
|
4951
|
+
*
|
|
4952
|
+
* This establishes a session with the compute API by verifying the SIWE message
|
|
4953
|
+
* and signature. On success, a session cookie is set in the browser.
|
|
4954
|
+
*
|
|
4955
|
+
* @param request - Login request containing SIWE message and signature
|
|
4956
|
+
* @returns Login result with the authenticated address
|
|
4957
|
+
*
|
|
4958
|
+
* @example
|
|
4959
|
+
* ```typescript
|
|
4960
|
+
* import { createSiweMessage } from "@layr-labs/ecloud-sdk/browser";
|
|
4961
|
+
*
|
|
4962
|
+
* const { message } = createSiweMessage({
|
|
4963
|
+
* address: userAddress,
|
|
4964
|
+
* chainId: 11155111,
|
|
4965
|
+
* domain: window.location.host,
|
|
4966
|
+
* uri: window.location.origin,
|
|
4967
|
+
* });
|
|
4968
|
+
*
|
|
4969
|
+
* const signature = await signMessageAsync({ message });
|
|
4970
|
+
* const result = await client.siweLogin({ message, signature });
|
|
4971
|
+
* ```
|
|
4972
|
+
*/
|
|
4973
|
+
async siweLogin(request) {
|
|
4974
|
+
return loginToComputeApi({ baseUrl: this.config.userApiServerURL }, request);
|
|
4975
|
+
}
|
|
4976
|
+
/**
|
|
4977
|
+
* Logout from the compute API
|
|
4978
|
+
*
|
|
4979
|
+
* This destroys the current session and clears the session cookie.
|
|
4980
|
+
*
|
|
4981
|
+
* @example
|
|
4982
|
+
* ```typescript
|
|
4983
|
+
* await client.siweLogout();
|
|
4984
|
+
* ```
|
|
4985
|
+
*/
|
|
4986
|
+
async siweLogout() {
|
|
4987
|
+
return logoutFromComputeApi({ baseUrl: this.config.userApiServerURL });
|
|
4988
|
+
}
|
|
4989
|
+
/**
|
|
4990
|
+
* Get the current SIWE session status from the compute API
|
|
4991
|
+
*
|
|
4992
|
+
* @returns Session information including authentication status and address
|
|
4993
|
+
*
|
|
4994
|
+
* @example
|
|
4995
|
+
* ```typescript
|
|
4996
|
+
* const session = await client.getSiweSession();
|
|
4997
|
+
* if (session.authenticated) {
|
|
4998
|
+
* console.log(`Logged in as ${session.address}`);
|
|
4999
|
+
* }
|
|
5000
|
+
* ```
|
|
5001
|
+
*/
|
|
5002
|
+
async getSiweSession() {
|
|
5003
|
+
return getComputeApiSession({ baseUrl: this.config.userApiServerURL });
|
|
5004
|
+
}
|
|
4759
5005
|
};
|
|
4760
5006
|
function transformAppReleaseBuild(raw) {
|
|
4761
5007
|
if (!isJsonObject(raw)) return void 0;
|
|
@@ -5372,24 +5618,221 @@ function isSubscriptionActive(status) {
|
|
|
5372
5618
|
|
|
5373
5619
|
// src/client/common/utils/billingapi.ts
|
|
5374
5620
|
var import_axios2 = __toESM(require("axios"), 1);
|
|
5621
|
+
|
|
5622
|
+
// src/client/common/auth/billingSession.ts
|
|
5623
|
+
var BillingSessionError = class extends Error {
|
|
5624
|
+
constructor(message, code, statusCode) {
|
|
5625
|
+
super(message);
|
|
5626
|
+
this.code = code;
|
|
5627
|
+
this.statusCode = statusCode;
|
|
5628
|
+
this.name = "BillingSessionError";
|
|
5629
|
+
}
|
|
5630
|
+
};
|
|
5631
|
+
function stripHexPrefix3(hex) {
|
|
5632
|
+
return hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
5633
|
+
}
|
|
5634
|
+
async function parseErrorResponse2(response) {
|
|
5635
|
+
try {
|
|
5636
|
+
const data = await response.json();
|
|
5637
|
+
return data.error || response.statusText;
|
|
5638
|
+
} catch {
|
|
5639
|
+
return response.statusText;
|
|
5640
|
+
}
|
|
5641
|
+
}
|
|
5642
|
+
async function loginToBillingApi(config, request) {
|
|
5643
|
+
let response;
|
|
5644
|
+
try {
|
|
5645
|
+
response = await fetch(`${config.baseUrl}/auth/siwe/login`, {
|
|
5646
|
+
method: "POST",
|
|
5647
|
+
credentials: "include",
|
|
5648
|
+
// Include cookies for session management
|
|
5649
|
+
headers: {
|
|
5650
|
+
"Content-Type": "application/json"
|
|
5651
|
+
},
|
|
5652
|
+
body: JSON.stringify({
|
|
5653
|
+
message: request.message,
|
|
5654
|
+
signature: stripHexPrefix3(request.signature)
|
|
5655
|
+
})
|
|
5656
|
+
});
|
|
5657
|
+
} catch (error) {
|
|
5658
|
+
throw new BillingSessionError(
|
|
5659
|
+
`Network error connecting to ${config.baseUrl}: ${error instanceof Error ? error.message : String(error)}`,
|
|
5660
|
+
"NETWORK_ERROR"
|
|
5661
|
+
);
|
|
5662
|
+
}
|
|
5663
|
+
if (!response.ok) {
|
|
5664
|
+
const errorMessage = await parseErrorResponse2(response);
|
|
5665
|
+
const status = response.status;
|
|
5666
|
+
if (status === 400) {
|
|
5667
|
+
if (errorMessage.toLowerCase().includes("siwe")) {
|
|
5668
|
+
throw new BillingSessionError(`Invalid SIWE message: ${errorMessage}`, "INVALID_MESSAGE", status);
|
|
5669
|
+
}
|
|
5670
|
+
throw new BillingSessionError(`Bad request: ${errorMessage}`, "INVALID_MESSAGE", status);
|
|
5671
|
+
}
|
|
5672
|
+
if (status === 401) {
|
|
5673
|
+
throw new BillingSessionError(`Invalid signature: ${errorMessage}`, "INVALID_SIGNATURE", status);
|
|
5674
|
+
}
|
|
5675
|
+
throw new BillingSessionError(`Login failed: ${errorMessage}`, "UNKNOWN", status);
|
|
5676
|
+
}
|
|
5677
|
+
const data = await response.json();
|
|
5678
|
+
return {
|
|
5679
|
+
success: data.success,
|
|
5680
|
+
address: data.address
|
|
5681
|
+
};
|
|
5682
|
+
}
|
|
5683
|
+
async function getBillingApiSession(config) {
|
|
5684
|
+
let response;
|
|
5685
|
+
try {
|
|
5686
|
+
response = await fetch(`${config.baseUrl}/auth/session`, {
|
|
5687
|
+
method: "GET",
|
|
5688
|
+
credentials: "include",
|
|
5689
|
+
// Include cookies for session management
|
|
5690
|
+
headers: {
|
|
5691
|
+
"Content-Type": "application/json"
|
|
5692
|
+
}
|
|
5693
|
+
});
|
|
5694
|
+
} catch {
|
|
5695
|
+
return {
|
|
5696
|
+
authenticated: false
|
|
5697
|
+
};
|
|
5698
|
+
}
|
|
5699
|
+
if (response.status === 401) {
|
|
5700
|
+
return {
|
|
5701
|
+
authenticated: false
|
|
5702
|
+
};
|
|
5703
|
+
}
|
|
5704
|
+
if (!response.ok) {
|
|
5705
|
+
const errorMessage = await parseErrorResponse2(response);
|
|
5706
|
+
throw new BillingSessionError(`Failed to get session: ${errorMessage}`, "UNKNOWN", response.status);
|
|
5707
|
+
}
|
|
5708
|
+
const data = await response.json();
|
|
5709
|
+
return {
|
|
5710
|
+
authenticated: data.authenticated,
|
|
5711
|
+
address: data.address,
|
|
5712
|
+
chainId: data.chainId,
|
|
5713
|
+
authenticatedAt: data.authenticatedAt
|
|
5714
|
+
};
|
|
5715
|
+
}
|
|
5716
|
+
async function logoutFromBillingApi(config) {
|
|
5717
|
+
let response;
|
|
5718
|
+
try {
|
|
5719
|
+
response = await fetch(`${config.baseUrl}/auth/logout`, {
|
|
5720
|
+
method: "POST",
|
|
5721
|
+
credentials: "include",
|
|
5722
|
+
// Include cookies for session management
|
|
5723
|
+
headers: {
|
|
5724
|
+
"Content-Type": "application/json"
|
|
5725
|
+
}
|
|
5726
|
+
});
|
|
5727
|
+
} catch (error) {
|
|
5728
|
+
throw new BillingSessionError(
|
|
5729
|
+
`Network error connecting to ${config.baseUrl}: ${error instanceof Error ? error.message : String(error)}`,
|
|
5730
|
+
"NETWORK_ERROR"
|
|
5731
|
+
);
|
|
5732
|
+
}
|
|
5733
|
+
if (response.status === 401) {
|
|
5734
|
+
return;
|
|
5735
|
+
}
|
|
5736
|
+
if (!response.ok) {
|
|
5737
|
+
const errorMessage = await parseErrorResponse2(response);
|
|
5738
|
+
throw new BillingSessionError(`Logout failed: ${errorMessage}`, "UNKNOWN", response.status);
|
|
5739
|
+
}
|
|
5740
|
+
}
|
|
5741
|
+
|
|
5742
|
+
// src/client/common/utils/billingapi.ts
|
|
5375
5743
|
var BillingApiClient = class {
|
|
5376
|
-
constructor(config, walletClient) {
|
|
5744
|
+
constructor(config, walletClient, options = {}) {
|
|
5377
5745
|
this.config = config;
|
|
5378
5746
|
this.walletClient = walletClient;
|
|
5747
|
+
this.options = options;
|
|
5748
|
+
this.useSession = options.useSession ?? false;
|
|
5749
|
+
if (!this.useSession && !walletClient) {
|
|
5750
|
+
throw new Error("WalletClient is required when not using session authentication");
|
|
5751
|
+
}
|
|
5379
5752
|
}
|
|
5380
5753
|
/**
|
|
5381
5754
|
* Get the address of the connected wallet
|
|
5755
|
+
* Returns undefined if using session auth without a wallet client
|
|
5382
5756
|
*/
|
|
5383
5757
|
get address() {
|
|
5384
|
-
const account = this.walletClient
|
|
5758
|
+
const account = this.walletClient?.account;
|
|
5385
5759
|
if (!account) {
|
|
5386
|
-
|
|
5760
|
+
if (!this.useSession) {
|
|
5761
|
+
throw new Error("WalletClient must have an account attached");
|
|
5762
|
+
}
|
|
5763
|
+
return void 0;
|
|
5387
5764
|
}
|
|
5388
5765
|
return account.address;
|
|
5389
5766
|
}
|
|
5390
|
-
|
|
5767
|
+
/**
|
|
5768
|
+
* Get the base URL of the billing API
|
|
5769
|
+
*/
|
|
5770
|
+
get baseUrl() {
|
|
5771
|
+
return this.config.billingApiServerURL;
|
|
5772
|
+
}
|
|
5773
|
+
// ==========================================================================
|
|
5774
|
+
// SIWE Session Methods
|
|
5775
|
+
// ==========================================================================
|
|
5776
|
+
/**
|
|
5777
|
+
* Login to the billing API using SIWE
|
|
5778
|
+
*
|
|
5779
|
+
* This establishes a session with the billing API by verifying the SIWE message
|
|
5780
|
+
* and signature. On success, a session cookie is set in the browser.
|
|
5781
|
+
*
|
|
5782
|
+
* @param request - Login request containing SIWE message and signature
|
|
5783
|
+
* @returns Login result with the authenticated address
|
|
5784
|
+
*
|
|
5785
|
+
* @example
|
|
5786
|
+
* ```typescript
|
|
5787
|
+
* const { message } = createSiweMessage({
|
|
5788
|
+
* address: userAddress,
|
|
5789
|
+
* chainId: 11155111,
|
|
5790
|
+
* domain: window.location.host,
|
|
5791
|
+
* uri: window.location.origin,
|
|
5792
|
+
* });
|
|
5793
|
+
*
|
|
5794
|
+
* const signature = await signMessageAsync({ message });
|
|
5795
|
+
* const result = await billingClient.siweLogin({ message, signature });
|
|
5796
|
+
* ```
|
|
5797
|
+
*/
|
|
5798
|
+
async siweLogin(request) {
|
|
5799
|
+
return loginToBillingApi({ baseUrl: this.baseUrl }, request);
|
|
5800
|
+
}
|
|
5801
|
+
/**
|
|
5802
|
+
* Logout from the billing API
|
|
5803
|
+
*
|
|
5804
|
+
* This destroys the current session and clears the session cookie.
|
|
5805
|
+
*/
|
|
5806
|
+
async siweLogout() {
|
|
5807
|
+
return logoutFromBillingApi({ baseUrl: this.baseUrl });
|
|
5808
|
+
}
|
|
5809
|
+
/**
|
|
5810
|
+
* Get the current session status from the billing API
|
|
5811
|
+
*
|
|
5812
|
+
* @returns Session information including authentication status and address
|
|
5813
|
+
*/
|
|
5814
|
+
async getSession() {
|
|
5815
|
+
return getBillingApiSession({ baseUrl: this.baseUrl });
|
|
5816
|
+
}
|
|
5817
|
+
/**
|
|
5818
|
+
* Check if there is a valid session
|
|
5819
|
+
*
|
|
5820
|
+
* @returns True if session is authenticated, false otherwise
|
|
5821
|
+
*/
|
|
5822
|
+
async isSessionValid() {
|
|
5823
|
+
const session = await this.getSession();
|
|
5824
|
+
return session.authenticated;
|
|
5825
|
+
}
|
|
5826
|
+
// ==========================================================================
|
|
5827
|
+
// Subscription Methods
|
|
5828
|
+
// ==========================================================================
|
|
5829
|
+
async createSubscription(productId = "compute", options) {
|
|
5391
5830
|
const endpoint = `${this.config.billingApiServerURL}/products/${productId}/subscription`;
|
|
5392
|
-
const
|
|
5831
|
+
const body = options ? {
|
|
5832
|
+
success_url: options.successUrl,
|
|
5833
|
+
cancel_url: options.cancelUrl
|
|
5834
|
+
} : void 0;
|
|
5835
|
+
const resp = await this.makeAuthenticatedRequest(endpoint, "POST", productId, body);
|
|
5393
5836
|
return resp.json();
|
|
5394
5837
|
}
|
|
5395
5838
|
async getSubscription(productId = "compute") {
|
|
@@ -5401,10 +5844,72 @@ var BillingApiClient = class {
|
|
|
5401
5844
|
const endpoint = `${this.config.billingApiServerURL}/products/${productId}/subscription`;
|
|
5402
5845
|
await this.makeAuthenticatedRequest(endpoint, "DELETE", productId);
|
|
5403
5846
|
}
|
|
5847
|
+
// ==========================================================================
|
|
5848
|
+
// Internal Methods
|
|
5849
|
+
// ==========================================================================
|
|
5404
5850
|
/**
|
|
5405
5851
|
* Make an authenticated request to the billing API
|
|
5852
|
+
*
|
|
5853
|
+
* Uses session auth if useSession is true, otherwise uses EIP-712 signature auth.
|
|
5854
|
+
*/
|
|
5855
|
+
async makeAuthenticatedRequest(url, method, productId, body) {
|
|
5856
|
+
if (this.useSession) {
|
|
5857
|
+
return this.makeSessionAuthenticatedRequest(url, method, body);
|
|
5858
|
+
}
|
|
5859
|
+
return this.makeSignatureAuthenticatedRequest(url, method, productId, body);
|
|
5860
|
+
}
|
|
5861
|
+
/**
|
|
5862
|
+
* Make a request using session-based authentication (cookies)
|
|
5406
5863
|
*/
|
|
5407
|
-
async
|
|
5864
|
+
async makeSessionAuthenticatedRequest(url, method, body) {
|
|
5865
|
+
const headers = {};
|
|
5866
|
+
if (body) {
|
|
5867
|
+
headers["Content-Type"] = "application/json";
|
|
5868
|
+
}
|
|
5869
|
+
try {
|
|
5870
|
+
const response = await fetch(url, {
|
|
5871
|
+
method,
|
|
5872
|
+
credentials: "include",
|
|
5873
|
+
// Include cookies for session management
|
|
5874
|
+
headers,
|
|
5875
|
+
body: body ? JSON.stringify(body) : void 0
|
|
5876
|
+
});
|
|
5877
|
+
const status = response.status;
|
|
5878
|
+
const statusText = status >= 200 && status < 300 ? "OK" : "Error";
|
|
5879
|
+
if (status < 200 || status >= 300) {
|
|
5880
|
+
let errorBody;
|
|
5881
|
+
try {
|
|
5882
|
+
errorBody = await response.text();
|
|
5883
|
+
} catch {
|
|
5884
|
+
errorBody = statusText;
|
|
5885
|
+
}
|
|
5886
|
+
throw new Error(`BillingAPI request failed: ${status} ${statusText} - ${errorBody}`);
|
|
5887
|
+
}
|
|
5888
|
+
const responseData = await response.json();
|
|
5889
|
+
return {
|
|
5890
|
+
json: async () => responseData,
|
|
5891
|
+
text: async () => JSON.stringify(responseData)
|
|
5892
|
+
};
|
|
5893
|
+
} catch (error) {
|
|
5894
|
+
if (error.name === "TypeError" || error.message?.includes("fetch")) {
|
|
5895
|
+
throw new Error(
|
|
5896
|
+
`Failed to connect to BillingAPI at ${url}: ${error.message}
|
|
5897
|
+
Please check:
|
|
5898
|
+
1. Your internet connection
|
|
5899
|
+
2. The API server is accessible: ${this.config.billingApiServerURL}
|
|
5900
|
+
3. Firewall/proxy settings`
|
|
5901
|
+
);
|
|
5902
|
+
}
|
|
5903
|
+
throw error;
|
|
5904
|
+
}
|
|
5905
|
+
}
|
|
5906
|
+
/**
|
|
5907
|
+
* Make a request using EIP-712 signature authentication
|
|
5908
|
+
*/
|
|
5909
|
+
async makeSignatureAuthenticatedRequest(url, method, productId, body) {
|
|
5910
|
+
if (!this.walletClient) {
|
|
5911
|
+
throw new Error("WalletClient is required for signature authentication");
|
|
5912
|
+
}
|
|
5408
5913
|
const expiry = BigInt(Math.floor(Date.now() / 1e3) + 5 * 60);
|
|
5409
5914
|
const { signature } = await calculateBillingAuthSignature({
|
|
5410
5915
|
walletClient: this.walletClient,
|
|
@@ -5416,11 +5921,15 @@ var BillingApiClient = class {
|
|
|
5416
5921
|
"X-Account": this.address,
|
|
5417
5922
|
"X-Expiry": expiry.toString()
|
|
5418
5923
|
};
|
|
5924
|
+
if (body) {
|
|
5925
|
+
headers["Content-Type"] = "application/json";
|
|
5926
|
+
}
|
|
5419
5927
|
try {
|
|
5420
5928
|
const response = await (0, import_axios2.default)({
|
|
5421
5929
|
method,
|
|
5422
5930
|
url,
|
|
5423
5931
|
headers,
|
|
5932
|
+
data: body,
|
|
5424
5933
|
timeout: 3e4,
|
|
5425
5934
|
maxRedirects: 0,
|
|
5426
5935
|
validateStatus: () => true
|
|
@@ -5429,8 +5938,8 @@ var BillingApiClient = class {
|
|
|
5429
5938
|
const status = response.status;
|
|
5430
5939
|
const statusText = status >= 200 && status < 300 ? "OK" : "Error";
|
|
5431
5940
|
if (status < 200 || status >= 300) {
|
|
5432
|
-
const
|
|
5433
|
-
throw new Error(`BillingAPI request failed: ${status} ${statusText} - ${
|
|
5941
|
+
const body2 = typeof response.data === "string" ? response.data : JSON.stringify(response.data);
|
|
5942
|
+
throw new Error(`BillingAPI request failed: ${status} ${statusText} - ${body2}`);
|
|
5434
5943
|
}
|
|
5435
5944
|
return {
|
|
5436
5945
|
json: async () => response.data,
|
|
@@ -6916,7 +7425,7 @@ async function logs(options, walletClient, publicClient, environmentConfig, logg
|
|
|
6916
7425
|
environmentConfig,
|
|
6917
7426
|
walletClient,
|
|
6918
7427
|
publicClient,
|
|
6919
|
-
options.clientId
|
|
7428
|
+
options.clientId ? { clientId: options.clientId } : void 0
|
|
6920
7429
|
);
|
|
6921
7430
|
let logsText;
|
|
6922
7431
|
let logsError = null;
|
|
@@ -7215,7 +7724,7 @@ function createAppModule(ctx) {
|
|
|
7215
7724
|
environment,
|
|
7216
7725
|
walletClient,
|
|
7217
7726
|
publicClient,
|
|
7218
|
-
ctx.clientId
|
|
7727
|
+
ctx.clientId ? { clientId: ctx.clientId } : void 0
|
|
7219
7728
|
);
|
|
7220
7729
|
return userApiClient.uploadAppProfile(appId, profile.name, {
|
|
7221
7730
|
website: profile.website,
|
|
@@ -7415,7 +7924,10 @@ function createBillingModule(config) {
|
|
|
7415
7924
|
};
|
|
7416
7925
|
}
|
|
7417
7926
|
logger.debug(`Creating subscription for ${productId}...`);
|
|
7418
|
-
const result = await billingApi.createSubscription(productId
|
|
7927
|
+
const result = await billingApi.createSubscription(productId, {
|
|
7928
|
+
successUrl: opts?.successUrl,
|
|
7929
|
+
cancelUrl: opts?.cancelUrl
|
|
7930
|
+
});
|
|
7419
7931
|
logger.debug(`Checkout URL: ${result.checkoutUrl}`);
|
|
7420
7932
|
return {
|
|
7421
7933
|
type: "checkout_created",
|
|
@@ -7474,11 +7986,55 @@ function createBillingModule(config) {
|
|
|
7474
7986
|
|
|
7475
7987
|
// src/client/common/utils/buildapi.ts
|
|
7476
7988
|
var import_axios3 = __toESM(require("axios"), 1);
|
|
7989
|
+
var MAX_RETRIES = 5;
|
|
7990
|
+
var INITIAL_BACKOFF_MS = 1e3;
|
|
7991
|
+
var MAX_BACKOFF_MS = 3e4;
|
|
7992
|
+
async function sleep2(ms) {
|
|
7993
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
7994
|
+
}
|
|
7995
|
+
function getRetryDelay(res, attempt) {
|
|
7996
|
+
const retryAfter = res.headers["retry-after"];
|
|
7997
|
+
if (retryAfter) {
|
|
7998
|
+
const seconds = parseInt(retryAfter, 10);
|
|
7999
|
+
if (!isNaN(seconds)) {
|
|
8000
|
+
return Math.min(seconds * 1e3, MAX_BACKOFF_MS);
|
|
8001
|
+
}
|
|
8002
|
+
}
|
|
8003
|
+
return Math.min(INITIAL_BACKOFF_MS * Math.pow(2, attempt), MAX_BACKOFF_MS);
|
|
8004
|
+
}
|
|
8005
|
+
async function requestWithRetry(config) {
|
|
8006
|
+
let lastResponse;
|
|
8007
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
8008
|
+
const res = await (0, import_axios3.default)({ ...config, validateStatus: () => true });
|
|
8009
|
+
lastResponse = res;
|
|
8010
|
+
if (res.status !== 429) {
|
|
8011
|
+
return res;
|
|
8012
|
+
}
|
|
8013
|
+
if (attempt < MAX_RETRIES) {
|
|
8014
|
+
const delay = getRetryDelay(res, attempt);
|
|
8015
|
+
await sleep2(delay);
|
|
8016
|
+
}
|
|
8017
|
+
}
|
|
8018
|
+
return lastResponse;
|
|
8019
|
+
}
|
|
7477
8020
|
var BuildApiClient = class {
|
|
7478
8021
|
constructor(options) {
|
|
7479
|
-
|
|
8022
|
+
let url = options.baseUrl;
|
|
8023
|
+
while (url.endsWith("/")) {
|
|
8024
|
+
url = url.slice(0, -1);
|
|
8025
|
+
}
|
|
8026
|
+
this.baseUrl = url;
|
|
7480
8027
|
this.clientId = options.clientId;
|
|
7481
8028
|
this.walletClient = options.walletClient;
|
|
8029
|
+
this.useSession = options.useSession ?? false;
|
|
8030
|
+
this.billingSessionId = options.billingSessionId;
|
|
8031
|
+
}
|
|
8032
|
+
/**
|
|
8033
|
+
* Update the billing session ID.
|
|
8034
|
+
* Call this after logging into the billing API to enable session-based auth for builds.
|
|
8035
|
+
*/
|
|
8036
|
+
setBillingSessionId(sessionId) {
|
|
8037
|
+
this.billingSessionId = sessionId;
|
|
7482
8038
|
}
|
|
7483
8039
|
/**
|
|
7484
8040
|
* Get the address of the connected wallet
|
|
@@ -7490,8 +8046,17 @@ var BuildApiClient = class {
|
|
|
7490
8046
|
}
|
|
7491
8047
|
return account.address;
|
|
7492
8048
|
}
|
|
8049
|
+
/**
|
|
8050
|
+
* Submit a new build request.
|
|
8051
|
+
* Supports two auth modes (session auth is tried first when billingSessionId is available):
|
|
8052
|
+
* 1. Session-based auth: X-Billing-Session header (forwarded billing_session cookie)
|
|
8053
|
+
* 2. Signature-based auth: Authorization + X-Account + X-eigenx-expiry headers (requires walletClient)
|
|
8054
|
+
*/
|
|
7493
8055
|
async submitBuild(payload) {
|
|
7494
|
-
|
|
8056
|
+
if (this.useSession && this.billingSessionId) {
|
|
8057
|
+
return this.billingSessionAuthJsonRequest("/builds", "POST", payload);
|
|
8058
|
+
}
|
|
8059
|
+
return this.signatureAuthJsonRequest("/builds", "POST", payload);
|
|
7495
8060
|
}
|
|
7496
8061
|
async getBuild(buildId) {
|
|
7497
8062
|
return this.publicJsonRequest(`/builds/${encodeURIComponent(buildId)}`);
|
|
@@ -7502,33 +8067,42 @@ var BuildApiClient = class {
|
|
|
7502
8067
|
async verify(identifier) {
|
|
7503
8068
|
return this.publicJsonRequest(`/builds/verify/${encodeURIComponent(identifier)}`);
|
|
7504
8069
|
}
|
|
8070
|
+
/**
|
|
8071
|
+
* Get build logs. Supports session auth (identity verification only, no billing check).
|
|
8072
|
+
*/
|
|
7505
8073
|
async getLogs(buildId) {
|
|
7506
|
-
return this.
|
|
8074
|
+
return this.sessionOrSignatureTextRequest(`/builds/${encodeURIComponent(buildId)}/logs`);
|
|
7507
8075
|
}
|
|
7508
8076
|
async listBuilds(params) {
|
|
7509
|
-
const res = await (
|
|
8077
|
+
const res = await requestWithRetry({
|
|
7510
8078
|
url: `${this.baseUrl}/builds`,
|
|
7511
8079
|
method: "GET",
|
|
7512
8080
|
params,
|
|
7513
8081
|
headers: this.clientId ? { "x-client-id": this.clientId } : void 0,
|
|
7514
8082
|
timeout: 6e4,
|
|
7515
|
-
validateStatus: () => true
|
|
8083
|
+
validateStatus: () => true,
|
|
8084
|
+
withCredentials: this.useSession
|
|
7516
8085
|
});
|
|
7517
8086
|
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
7518
8087
|
return res.data;
|
|
7519
8088
|
}
|
|
7520
8089
|
async publicJsonRequest(path8) {
|
|
7521
|
-
const res = await (
|
|
8090
|
+
const res = await requestWithRetry({
|
|
7522
8091
|
url: `${this.baseUrl}${path8}`,
|
|
7523
8092
|
method: "GET",
|
|
7524
8093
|
headers: this.clientId ? { "x-client-id": this.clientId } : void 0,
|
|
7525
8094
|
timeout: 6e4,
|
|
7526
|
-
validateStatus: () => true
|
|
8095
|
+
validateStatus: () => true,
|
|
8096
|
+
withCredentials: this.useSession
|
|
7527
8097
|
});
|
|
7528
8098
|
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
7529
8099
|
return res.data;
|
|
7530
8100
|
}
|
|
7531
|
-
|
|
8101
|
+
/**
|
|
8102
|
+
* Make a request that ALWAYS requires signature auth (for billing verification).
|
|
8103
|
+
* Used for endpoints like POST /builds that need to verify subscription status.
|
|
8104
|
+
*/
|
|
8105
|
+
async signatureAuthJsonRequest(path8, method, body) {
|
|
7532
8106
|
if (!this.walletClient?.account) {
|
|
7533
8107
|
throw new Error("WalletClient with account required for authenticated requests");
|
|
7534
8108
|
}
|
|
@@ -7545,39 +8119,74 @@ var BuildApiClient = class {
|
|
|
7545
8119
|
headers.Authorization = `Bearer ${signature}`;
|
|
7546
8120
|
headers["X-eigenx-expiry"] = expiry.toString();
|
|
7547
8121
|
headers["X-Account"] = this.address;
|
|
7548
|
-
const res = await (
|
|
8122
|
+
const res = await requestWithRetry({
|
|
7549
8123
|
url: `${this.baseUrl}${path8}`,
|
|
7550
8124
|
method,
|
|
7551
8125
|
headers,
|
|
7552
8126
|
data: body,
|
|
7553
8127
|
timeout: 6e4,
|
|
7554
|
-
validateStatus: () => true
|
|
8128
|
+
validateStatus: () => true,
|
|
8129
|
+
withCredentials: this.useSession
|
|
7555
8130
|
});
|
|
7556
8131
|
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
7557
8132
|
return res.data;
|
|
7558
8133
|
}
|
|
7559
|
-
|
|
7560
|
-
|
|
7561
|
-
|
|
8134
|
+
/**
|
|
8135
|
+
* Make a request using billing session auth (for billing verification without wallet signature).
|
|
8136
|
+
* Forwards the billing_session cookie value via X-Billing-Session header.
|
|
8137
|
+
* Used for endpoints that need to verify subscription status when using session-based auth.
|
|
8138
|
+
*/
|
|
8139
|
+
async billingSessionAuthJsonRequest(path8, method, body) {
|
|
8140
|
+
if (!this.billingSessionId) {
|
|
8141
|
+
throw new Error("billingSessionId required for session-based billing auth");
|
|
7562
8142
|
}
|
|
7563
|
-
const headers = {
|
|
8143
|
+
const headers = {
|
|
8144
|
+
"Content-Type": "application/json",
|
|
8145
|
+
"X-Billing-Session": this.billingSessionId
|
|
8146
|
+
};
|
|
7564
8147
|
if (this.clientId) headers["x-client-id"] = this.clientId;
|
|
7565
|
-
const
|
|
7566
|
-
|
|
7567
|
-
|
|
7568
|
-
|
|
7569
|
-
|
|
8148
|
+
const res = await requestWithRetry({
|
|
8149
|
+
url: `${this.baseUrl}${path8}`,
|
|
8150
|
+
method,
|
|
8151
|
+
headers,
|
|
8152
|
+
data: body,
|
|
8153
|
+
timeout: 6e4,
|
|
8154
|
+
validateStatus: () => true,
|
|
8155
|
+
withCredentials: this.useSession
|
|
7570
8156
|
});
|
|
7571
|
-
|
|
7572
|
-
|
|
7573
|
-
|
|
7574
|
-
|
|
8157
|
+
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
8158
|
+
return res.data;
|
|
8159
|
+
}
|
|
8160
|
+
/**
|
|
8161
|
+
* Make an authenticated request that can use session OR signature auth.
|
|
8162
|
+
* When useSession is true, relies on cookies for identity verification.
|
|
8163
|
+
* Used for endpoints that only need identity verification (not billing).
|
|
8164
|
+
*/
|
|
8165
|
+
async sessionOrSignatureTextRequest(path8) {
|
|
8166
|
+
const headers = {};
|
|
8167
|
+
if (this.clientId) headers["x-client-id"] = this.clientId;
|
|
8168
|
+
if (!this.useSession) {
|
|
8169
|
+
if (!this.walletClient?.account) {
|
|
8170
|
+
throw new Error("WalletClient with account required for authenticated requests");
|
|
8171
|
+
}
|
|
8172
|
+
const expiry = BigInt(Math.floor(Date.now() / 1e3) + 60);
|
|
8173
|
+
const { signature } = await calculateBillingAuthSignature({
|
|
8174
|
+
walletClient: this.walletClient,
|
|
8175
|
+
product: "compute",
|
|
8176
|
+
expiry
|
|
8177
|
+
});
|
|
8178
|
+
headers.Authorization = `Bearer ${signature}`;
|
|
8179
|
+
headers["X-eigenx-expiry"] = expiry.toString();
|
|
8180
|
+
headers["X-Account"] = this.address;
|
|
8181
|
+
}
|
|
8182
|
+
const res = await requestWithRetry({
|
|
7575
8183
|
url: `${this.baseUrl}${path8}`,
|
|
7576
8184
|
method: "GET",
|
|
7577
8185
|
headers,
|
|
7578
8186
|
timeout: 6e4,
|
|
7579
8187
|
responseType: "text",
|
|
7580
|
-
validateStatus: () => true
|
|
8188
|
+
validateStatus: () => true,
|
|
8189
|
+
withCredentials: this.useSession
|
|
7581
8190
|
});
|
|
7582
8191
|
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
7583
8192
|
return typeof res.data === "string" ? res.data : JSON.stringify(res.data);
|
|
@@ -7766,7 +8375,7 @@ function createBuildModule(config) {
|
|
|
7766
8375
|
if (build.status === BUILD_STATUS.FAILED) {
|
|
7767
8376
|
throw new BuildFailedError(build.errorMessage ?? "Build failed", buildId);
|
|
7768
8377
|
}
|
|
7769
|
-
await
|
|
8378
|
+
await sleep3(pollIntervalMs);
|
|
7770
8379
|
}
|
|
7771
8380
|
},
|
|
7772
8381
|
async *streamLogs(buildId, pollIntervalMs = DEFAULT_POLL_INTERVAL) {
|
|
@@ -7788,12 +8397,12 @@ function createBuildModule(config) {
|
|
|
7788
8397
|
lastLength = logs2.length;
|
|
7789
8398
|
}
|
|
7790
8399
|
if (build.status !== BUILD_STATUS.BUILDING) break;
|
|
7791
|
-
await
|
|
8400
|
+
await sleep3(pollIntervalMs);
|
|
7792
8401
|
}
|
|
7793
8402
|
}
|
|
7794
8403
|
};
|
|
7795
8404
|
}
|
|
7796
|
-
function
|
|
8405
|
+
function sleep3(ms) {
|
|
7797
8406
|
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
7798
8407
|
}
|
|
7799
8408
|
function transformBuild(raw) {
|
|
@@ -8076,6 +8685,77 @@ function generateNewPrivateKey() {
|
|
|
8076
8685
|
};
|
|
8077
8686
|
}
|
|
8078
8687
|
|
|
8688
|
+
// src/client/common/auth/siwe.ts
|
|
8689
|
+
var import_siwe = require("siwe");
|
|
8690
|
+
var generateNonce = import_siwe.generateNonce;
|
|
8691
|
+
function createSiweMessage(params) {
|
|
8692
|
+
const now = /* @__PURE__ */ new Date();
|
|
8693
|
+
const nonce = params.nonce || generateNonce();
|
|
8694
|
+
const issuedAt = params.issuedAt || now;
|
|
8695
|
+
const expirationTime = params.expirationTime || new Date(now.getTime() + 24 * 60 * 60 * 1e3);
|
|
8696
|
+
const siweMessage = new import_siwe.SiweMessage({
|
|
8697
|
+
domain: params.domain,
|
|
8698
|
+
address: params.address,
|
|
8699
|
+
statement: params.statement,
|
|
8700
|
+
uri: params.uri,
|
|
8701
|
+
version: "1",
|
|
8702
|
+
chainId: params.chainId,
|
|
8703
|
+
nonce,
|
|
8704
|
+
issuedAt: issuedAt.toISOString(),
|
|
8705
|
+
expirationTime: expirationTime.toISOString(),
|
|
8706
|
+
notBefore: params.notBefore?.toISOString(),
|
|
8707
|
+
requestId: params.requestId,
|
|
8708
|
+
resources: params.resources
|
|
8709
|
+
});
|
|
8710
|
+
return {
|
|
8711
|
+
message: siweMessage.prepareMessage(),
|
|
8712
|
+
params: {
|
|
8713
|
+
address: params.address,
|
|
8714
|
+
chainId: params.chainId,
|
|
8715
|
+
domain: params.domain,
|
|
8716
|
+
uri: params.uri,
|
|
8717
|
+
nonce,
|
|
8718
|
+
issuedAt,
|
|
8719
|
+
statement: params.statement,
|
|
8720
|
+
expirationTime,
|
|
8721
|
+
notBefore: params.notBefore,
|
|
8722
|
+
requestId: params.requestId,
|
|
8723
|
+
resources: params.resources
|
|
8724
|
+
}
|
|
8725
|
+
};
|
|
8726
|
+
}
|
|
8727
|
+
function parseSiweMessage(message) {
|
|
8728
|
+
try {
|
|
8729
|
+
const siweMessage = new import_siwe.SiweMessage(message);
|
|
8730
|
+
return {
|
|
8731
|
+
address: siweMessage.address,
|
|
8732
|
+
chainId: siweMessage.chainId,
|
|
8733
|
+
domain: siweMessage.domain,
|
|
8734
|
+
uri: siweMessage.uri,
|
|
8735
|
+
nonce: siweMessage.nonce,
|
|
8736
|
+
statement: siweMessage.statement,
|
|
8737
|
+
issuedAt: siweMessage.issuedAt ? new Date(siweMessage.issuedAt) : void 0,
|
|
8738
|
+
expirationTime: siweMessage.expirationTime ? new Date(siweMessage.expirationTime) : void 0,
|
|
8739
|
+
notBefore: siweMessage.notBefore ? new Date(siweMessage.notBefore) : void 0,
|
|
8740
|
+
requestId: siweMessage.requestId,
|
|
8741
|
+
resources: siweMessage.resources
|
|
8742
|
+
};
|
|
8743
|
+
} catch {
|
|
8744
|
+
return null;
|
|
8745
|
+
}
|
|
8746
|
+
}
|
|
8747
|
+
function isSiweMessageExpired(params) {
|
|
8748
|
+
if (!params.expirationTime) return false;
|
|
8749
|
+
return /* @__PURE__ */ new Date() > params.expirationTime;
|
|
8750
|
+
}
|
|
8751
|
+
function isSiweMessageNotYetValid(params) {
|
|
8752
|
+
if (!params.notBefore) return false;
|
|
8753
|
+
return /* @__PURE__ */ new Date() < params.notBefore;
|
|
8754
|
+
}
|
|
8755
|
+
|
|
8756
|
+
// src/client/common/auth/index.ts
|
|
8757
|
+
init_session();
|
|
8758
|
+
|
|
8079
8759
|
// src/client/common/utils/instance.ts
|
|
8080
8760
|
async function getCurrentInstanceType(preflightCtx, appID, logger, clientId) {
|
|
8081
8761
|
try {
|
|
@@ -8083,7 +8763,7 @@ async function getCurrentInstanceType(preflightCtx, appID, logger, clientId) {
|
|
|
8083
8763
|
preflightCtx.environmentConfig,
|
|
8084
8764
|
preflightCtx.walletClient,
|
|
8085
8765
|
preflightCtx.publicClient,
|
|
8086
|
-
clientId
|
|
8766
|
+
clientId ? { clientId } : void 0
|
|
8087
8767
|
);
|
|
8088
8768
|
const infos = await userApiClient.getInfos([appID], 1);
|
|
8089
8769
|
if (infos.length === 0) {
|
|
@@ -8147,6 +8827,7 @@ function createECloudClient(cfg) {
|
|
|
8147
8827
|
NotFoundError,
|
|
8148
8828
|
PRIMARY_LANGUAGES,
|
|
8149
8829
|
PostHogClient,
|
|
8830
|
+
SessionError,
|
|
8150
8831
|
TimeoutError,
|
|
8151
8832
|
UserApiClient,
|
|
8152
8833
|
addHexPrefix,
|
|
@@ -8163,6 +8844,7 @@ function createECloudClient(cfg) {
|
|
|
8163
8844
|
createComputeModule,
|
|
8164
8845
|
createECloudClient,
|
|
8165
8846
|
createMetricsContext,
|
|
8847
|
+
createSiweMessage,
|
|
8166
8848
|
createTelemetryClient,
|
|
8167
8849
|
createViemClients,
|
|
8168
8850
|
deleteLegacyPrivateKey,
|
|
@@ -8179,6 +8861,7 @@ function createECloudClient(cfg) {
|
|
|
8179
8861
|
fetchTemplateCatalog,
|
|
8180
8862
|
formatETH,
|
|
8181
8863
|
generateNewPrivateKey,
|
|
8864
|
+
generateNonce,
|
|
8182
8865
|
getAddressFromPrivateKey,
|
|
8183
8866
|
getAllAppsByDeveloper,
|
|
8184
8867
|
getAppLatestReleaseBlockNumbers,
|
|
@@ -8189,6 +8872,7 @@ function createECloudClient(cfg) {
|
|
|
8189
8872
|
getBuildType,
|
|
8190
8873
|
getCategoryDescriptions,
|
|
8191
8874
|
getChainFromID,
|
|
8875
|
+
getComputeApiSession,
|
|
8192
8876
|
getCurrentInstanceType,
|
|
8193
8877
|
getEnvironmentConfig,
|
|
8194
8878
|
getLegacyKeys,
|
|
@@ -8201,10 +8885,17 @@ function createECloudClient(cfg) {
|
|
|
8201
8885
|
isEnvironmentAvailable,
|
|
8202
8886
|
isMainnet,
|
|
8203
8887
|
isNoopClient,
|
|
8888
|
+
isSessionValid,
|
|
8889
|
+
isSiweMessageExpired,
|
|
8890
|
+
isSiweMessageNotYetValid,
|
|
8204
8891
|
isSubscriptionActive,
|
|
8205
8892
|
keyExists,
|
|
8206
8893
|
listStoredKeys,
|
|
8894
|
+
loginToComputeApi,
|
|
8895
|
+
logoutFromComputeApi,
|
|
8207
8896
|
logs,
|
|
8897
|
+
noopLogger,
|
|
8898
|
+
parseSiweMessage,
|
|
8208
8899
|
prepareDeploy,
|
|
8209
8900
|
prepareDeployFromVerifiableBuild,
|
|
8210
8901
|
prepareUpgrade,
|