@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.js
CHANGED
|
@@ -1,3 +1,137 @@
|
|
|
1
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
2
|
+
var __esm = (fn, res) => function __init() {
|
|
3
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
// src/client/common/auth/session.ts
|
|
7
|
+
function stripHexPrefix2(hex) {
|
|
8
|
+
return hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
9
|
+
}
|
|
10
|
+
async function parseErrorResponse(response) {
|
|
11
|
+
try {
|
|
12
|
+
const data = await response.json();
|
|
13
|
+
return data.error || response.statusText;
|
|
14
|
+
} catch {
|
|
15
|
+
return response.statusText;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
async function loginToComputeApi(config, request) {
|
|
19
|
+
let response;
|
|
20
|
+
try {
|
|
21
|
+
response = await fetch(`${config.baseUrl}/auth/siwe/login`, {
|
|
22
|
+
method: "POST",
|
|
23
|
+
credentials: "include",
|
|
24
|
+
// Include cookies for session management
|
|
25
|
+
headers: {
|
|
26
|
+
"Content-Type": "application/json"
|
|
27
|
+
},
|
|
28
|
+
body: JSON.stringify({
|
|
29
|
+
message: request.message,
|
|
30
|
+
signature: stripHexPrefix2(request.signature)
|
|
31
|
+
})
|
|
32
|
+
});
|
|
33
|
+
} catch (error) {
|
|
34
|
+
throw new SessionError(
|
|
35
|
+
`Network error connecting to ${config.baseUrl}: ${error instanceof Error ? error.message : String(error)}`,
|
|
36
|
+
"NETWORK_ERROR"
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
if (!response.ok) {
|
|
40
|
+
const errorMessage = await parseErrorResponse(response);
|
|
41
|
+
const status = response.status;
|
|
42
|
+
if (status === 400) {
|
|
43
|
+
if (errorMessage.toLowerCase().includes("siwe")) {
|
|
44
|
+
throw new SessionError(`Invalid SIWE message: ${errorMessage}`, "INVALID_MESSAGE", status);
|
|
45
|
+
}
|
|
46
|
+
throw new SessionError(`Bad request: ${errorMessage}`, "INVALID_MESSAGE", status);
|
|
47
|
+
}
|
|
48
|
+
if (status === 401) {
|
|
49
|
+
throw new SessionError(`Invalid signature: ${errorMessage}`, "INVALID_SIGNATURE", status);
|
|
50
|
+
}
|
|
51
|
+
throw new SessionError(`Login failed: ${errorMessage}`, "UNKNOWN", status);
|
|
52
|
+
}
|
|
53
|
+
const data = await response.json();
|
|
54
|
+
return {
|
|
55
|
+
success: data.success,
|
|
56
|
+
address: data.address
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
async function getComputeApiSession(config) {
|
|
60
|
+
let response;
|
|
61
|
+
try {
|
|
62
|
+
response = await fetch(`${config.baseUrl}/auth/session`, {
|
|
63
|
+
method: "GET",
|
|
64
|
+
credentials: "include",
|
|
65
|
+
// Include cookies for session management
|
|
66
|
+
headers: {
|
|
67
|
+
"Content-Type": "application/json"
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
} catch {
|
|
71
|
+
return {
|
|
72
|
+
authenticated: false
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
if (response.status === 401) {
|
|
76
|
+
return {
|
|
77
|
+
authenticated: false
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
if (!response.ok) {
|
|
81
|
+
const errorMessage = await parseErrorResponse(response);
|
|
82
|
+
throw new SessionError(`Failed to get session: ${errorMessage}`, "UNKNOWN", response.status);
|
|
83
|
+
}
|
|
84
|
+
const data = await response.json();
|
|
85
|
+
return {
|
|
86
|
+
authenticated: data.authenticated,
|
|
87
|
+
address: data.address,
|
|
88
|
+
chainId: data.chain_id
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
async function logoutFromComputeApi(config) {
|
|
92
|
+
let response;
|
|
93
|
+
try {
|
|
94
|
+
response = await fetch(`${config.baseUrl}/auth/logout`, {
|
|
95
|
+
method: "POST",
|
|
96
|
+
credentials: "include",
|
|
97
|
+
// Include cookies for session management
|
|
98
|
+
headers: {
|
|
99
|
+
"Content-Type": "application/json"
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
} catch (error) {
|
|
103
|
+
throw new SessionError(
|
|
104
|
+
`Network error connecting to ${config.baseUrl}: ${error instanceof Error ? error.message : String(error)}`,
|
|
105
|
+
"NETWORK_ERROR"
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
if (response.status === 401) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (!response.ok) {
|
|
112
|
+
const errorMessage = await parseErrorResponse(response);
|
|
113
|
+
throw new SessionError(`Logout failed: ${errorMessage}`, "UNKNOWN", response.status);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
async function isSessionValid(config) {
|
|
117
|
+
const session = await getComputeApiSession(config);
|
|
118
|
+
return session.authenticated;
|
|
119
|
+
}
|
|
120
|
+
var SessionError;
|
|
121
|
+
var init_session = __esm({
|
|
122
|
+
"src/client/common/auth/session.ts"() {
|
|
123
|
+
"use strict";
|
|
124
|
+
SessionError = class extends Error {
|
|
125
|
+
constructor(message, code, statusCode) {
|
|
126
|
+
super(message);
|
|
127
|
+
this.code = code;
|
|
128
|
+
this.statusCode = statusCode;
|
|
129
|
+
this.name = "SessionError";
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
|
|
1
135
|
// src/client/modules/compute/app/index.ts
|
|
2
136
|
import { parseAbi as parseAbi2, encodeFunctionData as encodeFunctionData3 } from "viem";
|
|
3
137
|
|
|
@@ -1101,6 +1235,18 @@ function extractRegistryNameNoDocker(imageRef) {
|
|
|
1101
1235
|
// src/client/common/contract/eip7702.ts
|
|
1102
1236
|
import { encodeFunctionData, encodeAbiParameters, decodeErrorResult } from "viem";
|
|
1103
1237
|
|
|
1238
|
+
// src/client/common/types/index.ts
|
|
1239
|
+
var noopLogger = {
|
|
1240
|
+
debug: () => {
|
|
1241
|
+
},
|
|
1242
|
+
info: () => {
|
|
1243
|
+
},
|
|
1244
|
+
warn: () => {
|
|
1245
|
+
},
|
|
1246
|
+
error: () => {
|
|
1247
|
+
}
|
|
1248
|
+
};
|
|
1249
|
+
|
|
1104
1250
|
// src/client/common/abis/ERC7702Delegator.json
|
|
1105
1251
|
var ERC7702Delegator_default = [
|
|
1106
1252
|
{
|
|
@@ -2186,7 +2332,7 @@ async function checkERC7702Delegation(publicClient, account, delegatorAddress) {
|
|
|
2186
2332
|
const expectedCode = `0xef0100${delegatorAddress.slice(2)}`;
|
|
2187
2333
|
return code.toLowerCase() === expectedCode.toLowerCase();
|
|
2188
2334
|
}
|
|
2189
|
-
async function executeBatch(options, logger) {
|
|
2335
|
+
async function executeBatch(options, logger = noopLogger) {
|
|
2190
2336
|
const { walletClient, publicClient, environmentConfig, executions, pendingMessage, gas } = options;
|
|
2191
2337
|
const account = walletClient.account;
|
|
2192
2338
|
if (!account) {
|
|
@@ -2270,11 +2416,7 @@ async function executeBatch(options, logger) {
|
|
|
2270
2416
|
}
|
|
2271
2417
|
|
|
2272
2418
|
// src/client/common/contract/caller.ts
|
|
2273
|
-
import {
|
|
2274
|
-
encodeFunctionData as encodeFunctionData2,
|
|
2275
|
-
decodeErrorResult as decodeErrorResult2,
|
|
2276
|
-
bytesToHex
|
|
2277
|
-
} from "viem";
|
|
2419
|
+
import { encodeFunctionData as encodeFunctionData2, decodeErrorResult as decodeErrorResult2, bytesToHex } from "viem";
|
|
2278
2420
|
|
|
2279
2421
|
// src/client/common/utils/helpers.ts
|
|
2280
2422
|
import { extractChain, createPublicClient, createWalletClient, http } from "viem";
|
|
@@ -3895,7 +4037,7 @@ async function calculateAppID(options) {
|
|
|
3895
4037
|
});
|
|
3896
4038
|
return appID;
|
|
3897
4039
|
}
|
|
3898
|
-
async function prepareDeployBatch(options, logger) {
|
|
4040
|
+
async function prepareDeployBatch(options, logger = noopLogger) {
|
|
3899
4041
|
const { walletClient, publicClient, environmentConfig, salt, release, publicLogs } = options;
|
|
3900
4042
|
const account = walletClient.account;
|
|
3901
4043
|
if (!account) {
|
|
@@ -3975,7 +4117,7 @@ async function prepareDeployBatch(options, logger) {
|
|
|
3975
4117
|
environmentConfig
|
|
3976
4118
|
};
|
|
3977
4119
|
}
|
|
3978
|
-
async function executeDeployBatch(data, context, gas, logger) {
|
|
4120
|
+
async function executeDeployBatch(data, context, gas, logger = noopLogger) {
|
|
3979
4121
|
const pendingMessage = "Deploying new app...";
|
|
3980
4122
|
const txHash = await executeBatch(
|
|
3981
4123
|
{
|
|
@@ -3990,7 +4132,7 @@ async function executeDeployBatch(data, context, gas, logger) {
|
|
|
3990
4132
|
);
|
|
3991
4133
|
return { appId: data.appId, txHash };
|
|
3992
4134
|
}
|
|
3993
|
-
async function deployApp(options, logger) {
|
|
4135
|
+
async function deployApp(options, logger = noopLogger) {
|
|
3994
4136
|
const prepared = await prepareDeployBatch(options, logger);
|
|
3995
4137
|
const data = {
|
|
3996
4138
|
appId: prepared.appId,
|
|
@@ -4005,7 +4147,15 @@ async function deployApp(options, logger) {
|
|
|
4005
4147
|
return executeDeployBatch(data, context, options.gas, logger);
|
|
4006
4148
|
}
|
|
4007
4149
|
async function prepareUpgradeBatch(options) {
|
|
4008
|
-
const {
|
|
4150
|
+
const {
|
|
4151
|
+
walletClient,
|
|
4152
|
+
publicClient,
|
|
4153
|
+
environmentConfig,
|
|
4154
|
+
appID,
|
|
4155
|
+
release,
|
|
4156
|
+
publicLogs,
|
|
4157
|
+
needsPermissionChange
|
|
4158
|
+
} = options;
|
|
4009
4159
|
const releaseForViem = {
|
|
4010
4160
|
rmsRelease: {
|
|
4011
4161
|
artifacts: release.rmsRelease.artifacts.map((artifact) => ({
|
|
@@ -4078,7 +4228,7 @@ async function prepareUpgradeBatch(options) {
|
|
|
4078
4228
|
environmentConfig
|
|
4079
4229
|
};
|
|
4080
4230
|
}
|
|
4081
|
-
async function executeUpgradeBatch(data, context, gas, logger) {
|
|
4231
|
+
async function executeUpgradeBatch(data, context, gas, logger = noopLogger) {
|
|
4082
4232
|
const pendingMessage = `Upgrading app ${data.appId}...`;
|
|
4083
4233
|
const txHash = await executeBatch(
|
|
4084
4234
|
{
|
|
@@ -4093,7 +4243,7 @@ async function executeUpgradeBatch(data, context, gas, logger) {
|
|
|
4093
4243
|
);
|
|
4094
4244
|
return txHash;
|
|
4095
4245
|
}
|
|
4096
|
-
async function upgradeApp(options, logger) {
|
|
4246
|
+
async function upgradeApp(options, logger = noopLogger) {
|
|
4097
4247
|
const prepared = await prepareUpgradeBatch(options);
|
|
4098
4248
|
const data = {
|
|
4099
4249
|
appId: prepared.appId,
|
|
@@ -4106,8 +4256,18 @@ async function upgradeApp(options, logger) {
|
|
|
4106
4256
|
};
|
|
4107
4257
|
return executeUpgradeBatch(data, context, options.gas, logger);
|
|
4108
4258
|
}
|
|
4109
|
-
async function sendAndWaitForTransaction(options, logger) {
|
|
4110
|
-
const {
|
|
4259
|
+
async function sendAndWaitForTransaction(options, logger = noopLogger) {
|
|
4260
|
+
const {
|
|
4261
|
+
walletClient,
|
|
4262
|
+
publicClient,
|
|
4263
|
+
environmentConfig,
|
|
4264
|
+
to,
|
|
4265
|
+
data,
|
|
4266
|
+
value = 0n,
|
|
4267
|
+
pendingMessage,
|
|
4268
|
+
txDescription,
|
|
4269
|
+
gas
|
|
4270
|
+
} = options;
|
|
4111
4271
|
const account = walletClient.account;
|
|
4112
4272
|
if (!account) {
|
|
4113
4273
|
throw new Error("WalletClient must have an account attached");
|
|
@@ -4227,7 +4387,13 @@ async function getAllAppsByDeveloper(publicClient, env, developer, pageSize = 10
|
|
|
4227
4387
|
const allApps = [];
|
|
4228
4388
|
const allConfigs = [];
|
|
4229
4389
|
while (true) {
|
|
4230
|
-
const { apps, appConfigs } = await getAppsByDeveloper(
|
|
4390
|
+
const { apps, appConfigs } = await getAppsByDeveloper(
|
|
4391
|
+
publicClient,
|
|
4392
|
+
env,
|
|
4393
|
+
developer,
|
|
4394
|
+
offset,
|
|
4395
|
+
pageSize
|
|
4396
|
+
);
|
|
4231
4397
|
if (apps.length === 0) break;
|
|
4232
4398
|
allApps.push(...apps);
|
|
4233
4399
|
allConfigs.push(...appConfigs);
|
|
@@ -4283,7 +4449,7 @@ async function isDelegated(options) {
|
|
|
4283
4449
|
environmentConfig.erc7702DelegatorAddress
|
|
4284
4450
|
);
|
|
4285
4451
|
}
|
|
4286
|
-
async function undelegate(options, logger) {
|
|
4452
|
+
async function undelegate(options, logger = noopLogger) {
|
|
4287
4453
|
const { walletClient, publicClient, environmentConfig } = options;
|
|
4288
4454
|
const account = walletClient.account;
|
|
4289
4455
|
if (!account) {
|
|
@@ -4382,6 +4548,7 @@ async function calculateBillingAuthSignature(options) {
|
|
|
4382
4548
|
}
|
|
4383
4549
|
|
|
4384
4550
|
// src/client/common/utils/userapi.ts
|
|
4551
|
+
init_session();
|
|
4385
4552
|
function isJsonObject(value) {
|
|
4386
4553
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4387
4554
|
}
|
|
@@ -4398,15 +4565,16 @@ var CanViewAppLogsPermission = "0x2fd3f2fe";
|
|
|
4398
4565
|
var CanViewSensitiveAppInfoPermission = "0x0e67b22f";
|
|
4399
4566
|
var CanUpdateAppProfilePermission = "0x036fef61";
|
|
4400
4567
|
function getDefaultClientId() {
|
|
4401
|
-
const version = true ? "0.
|
|
4568
|
+
const version = true ? "0.3.0-dev" : "0.0.0";
|
|
4402
4569
|
return `ecloud-sdk/v${version}`;
|
|
4403
4570
|
}
|
|
4404
4571
|
var UserApiClient = class {
|
|
4405
|
-
constructor(config, walletClient, publicClient,
|
|
4572
|
+
constructor(config, walletClient, publicClient, options) {
|
|
4406
4573
|
this.config = config;
|
|
4407
4574
|
this.walletClient = walletClient;
|
|
4408
4575
|
this.publicClient = publicClient;
|
|
4409
|
-
this.clientId = clientId || getDefaultClientId();
|
|
4576
|
+
this.clientId = options?.clientId || getDefaultClientId();
|
|
4577
|
+
this.useSession = options?.useSession ?? false;
|
|
4410
4578
|
}
|
|
4411
4579
|
/**
|
|
4412
4580
|
* Get the address of the connected wallet
|
|
@@ -4494,7 +4662,7 @@ var UserApiClient = class {
|
|
|
4494
4662
|
const apps = result.apps || result.Apps || [];
|
|
4495
4663
|
return apps.map((app, i) => ({
|
|
4496
4664
|
address: app.address || appIDs[i],
|
|
4497
|
-
status: app.
|
|
4665
|
+
status: app.app_status || app.App_Status || ""
|
|
4498
4666
|
}));
|
|
4499
4667
|
}
|
|
4500
4668
|
/**
|
|
@@ -4526,9 +4694,11 @@ var UserApiClient = class {
|
|
|
4526
4694
|
const headers = {
|
|
4527
4695
|
"x-client-id": this.clientId
|
|
4528
4696
|
};
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
|
|
4697
|
+
if (!this.useSession) {
|
|
4698
|
+
const expiry = BigInt(Math.floor(Date.now() / 1e3) + 5 * 60);
|
|
4699
|
+
const authHeaders = await this.generateAuthHeaders(CanUpdateAppProfilePermission, expiry);
|
|
4700
|
+
Object.assign(headers, authHeaders);
|
|
4701
|
+
}
|
|
4532
4702
|
try {
|
|
4533
4703
|
const response = await axios.post(endpoint, formData, {
|
|
4534
4704
|
headers,
|
|
@@ -4537,8 +4707,10 @@ var UserApiClient = class {
|
|
|
4537
4707
|
// Don't throw on any status
|
|
4538
4708
|
maxContentLength: Infinity,
|
|
4539
4709
|
// Allow large file uploads
|
|
4540
|
-
maxBodyLength: Infinity
|
|
4710
|
+
maxBodyLength: Infinity,
|
|
4541
4711
|
// Allow large file uploads
|
|
4712
|
+
withCredentials: true
|
|
4713
|
+
// Include cookies for session auth
|
|
4542
4714
|
});
|
|
4543
4715
|
const status = response.status;
|
|
4544
4716
|
if (status !== 200 && status !== 201) {
|
|
@@ -4572,7 +4744,7 @@ Please check:
|
|
|
4572
4744
|
const headers = {
|
|
4573
4745
|
"x-client-id": this.clientId
|
|
4574
4746
|
};
|
|
4575
|
-
if (permission) {
|
|
4747
|
+
if (permission && !this.useSession) {
|
|
4576
4748
|
const expiry = BigInt(Math.floor(Date.now() / 1e3) + 5 * 60);
|
|
4577
4749
|
const authHeaders = await this.generateAuthHeaders(permission, expiry);
|
|
4578
4750
|
Object.assign(headers, authHeaders);
|
|
@@ -4581,8 +4753,10 @@ Please check:
|
|
|
4581
4753
|
const response = await axios.get(url, {
|
|
4582
4754
|
headers,
|
|
4583
4755
|
maxRedirects: 0,
|
|
4584
|
-
validateStatus: () => true
|
|
4756
|
+
validateStatus: () => true,
|
|
4585
4757
|
// Don't throw on any status
|
|
4758
|
+
withCredentials: true
|
|
4759
|
+
// Include cookies for session auth
|
|
4586
4760
|
});
|
|
4587
4761
|
const status = response.status;
|
|
4588
4762
|
const statusText = status >= 200 && status < 300 ? "OK" : "Error";
|
|
@@ -4624,6 +4798,65 @@ Please check:
|
|
|
4624
4798
|
"X-eigenx-expiry": expiry.toString()
|
|
4625
4799
|
};
|
|
4626
4800
|
}
|
|
4801
|
+
// ==========================================================================
|
|
4802
|
+
// SIWE Session Management
|
|
4803
|
+
// ==========================================================================
|
|
4804
|
+
/**
|
|
4805
|
+
* Login to the compute API using SIWE (Sign-In with Ethereum)
|
|
4806
|
+
*
|
|
4807
|
+
* This establishes a session with the compute API by verifying the SIWE message
|
|
4808
|
+
* and signature. On success, a session cookie is set in the browser.
|
|
4809
|
+
*
|
|
4810
|
+
* @param request - Login request containing SIWE message and signature
|
|
4811
|
+
* @returns Login result with the authenticated address
|
|
4812
|
+
*
|
|
4813
|
+
* @example
|
|
4814
|
+
* ```typescript
|
|
4815
|
+
* import { createSiweMessage } from "@layr-labs/ecloud-sdk/browser";
|
|
4816
|
+
*
|
|
4817
|
+
* const { message } = createSiweMessage({
|
|
4818
|
+
* address: userAddress,
|
|
4819
|
+
* chainId: 11155111,
|
|
4820
|
+
* domain: window.location.host,
|
|
4821
|
+
* uri: window.location.origin,
|
|
4822
|
+
* });
|
|
4823
|
+
*
|
|
4824
|
+
* const signature = await signMessageAsync({ message });
|
|
4825
|
+
* const result = await client.siweLogin({ message, signature });
|
|
4826
|
+
* ```
|
|
4827
|
+
*/
|
|
4828
|
+
async siweLogin(request) {
|
|
4829
|
+
return loginToComputeApi({ baseUrl: this.config.userApiServerURL }, request);
|
|
4830
|
+
}
|
|
4831
|
+
/**
|
|
4832
|
+
* Logout from the compute API
|
|
4833
|
+
*
|
|
4834
|
+
* This destroys the current session and clears the session cookie.
|
|
4835
|
+
*
|
|
4836
|
+
* @example
|
|
4837
|
+
* ```typescript
|
|
4838
|
+
* await client.siweLogout();
|
|
4839
|
+
* ```
|
|
4840
|
+
*/
|
|
4841
|
+
async siweLogout() {
|
|
4842
|
+
return logoutFromComputeApi({ baseUrl: this.config.userApiServerURL });
|
|
4843
|
+
}
|
|
4844
|
+
/**
|
|
4845
|
+
* Get the current SIWE session status from the compute API
|
|
4846
|
+
*
|
|
4847
|
+
* @returns Session information including authentication status and address
|
|
4848
|
+
*
|
|
4849
|
+
* @example
|
|
4850
|
+
* ```typescript
|
|
4851
|
+
* const session = await client.getSiweSession();
|
|
4852
|
+
* if (session.authenticated) {
|
|
4853
|
+
* console.log(`Logged in as ${session.address}`);
|
|
4854
|
+
* }
|
|
4855
|
+
* ```
|
|
4856
|
+
*/
|
|
4857
|
+
async getSiweSession() {
|
|
4858
|
+
return getComputeApiSession({ baseUrl: this.config.userApiServerURL });
|
|
4859
|
+
}
|
|
4627
4860
|
};
|
|
4628
4861
|
function transformAppReleaseBuild(raw) {
|
|
4629
4862
|
if (!isJsonObject(raw)) return void 0;
|
|
@@ -5240,24 +5473,221 @@ function isSubscriptionActive(status) {
|
|
|
5240
5473
|
|
|
5241
5474
|
// src/client/common/utils/billingapi.ts
|
|
5242
5475
|
import axios2 from "axios";
|
|
5476
|
+
|
|
5477
|
+
// src/client/common/auth/billingSession.ts
|
|
5478
|
+
var BillingSessionError = class extends Error {
|
|
5479
|
+
constructor(message, code, statusCode) {
|
|
5480
|
+
super(message);
|
|
5481
|
+
this.code = code;
|
|
5482
|
+
this.statusCode = statusCode;
|
|
5483
|
+
this.name = "BillingSessionError";
|
|
5484
|
+
}
|
|
5485
|
+
};
|
|
5486
|
+
function stripHexPrefix3(hex) {
|
|
5487
|
+
return hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
5488
|
+
}
|
|
5489
|
+
async function parseErrorResponse2(response) {
|
|
5490
|
+
try {
|
|
5491
|
+
const data = await response.json();
|
|
5492
|
+
return data.error || response.statusText;
|
|
5493
|
+
} catch {
|
|
5494
|
+
return response.statusText;
|
|
5495
|
+
}
|
|
5496
|
+
}
|
|
5497
|
+
async function loginToBillingApi(config, request) {
|
|
5498
|
+
let response;
|
|
5499
|
+
try {
|
|
5500
|
+
response = await fetch(`${config.baseUrl}/auth/siwe/login`, {
|
|
5501
|
+
method: "POST",
|
|
5502
|
+
credentials: "include",
|
|
5503
|
+
// Include cookies for session management
|
|
5504
|
+
headers: {
|
|
5505
|
+
"Content-Type": "application/json"
|
|
5506
|
+
},
|
|
5507
|
+
body: JSON.stringify({
|
|
5508
|
+
message: request.message,
|
|
5509
|
+
signature: stripHexPrefix3(request.signature)
|
|
5510
|
+
})
|
|
5511
|
+
});
|
|
5512
|
+
} catch (error) {
|
|
5513
|
+
throw new BillingSessionError(
|
|
5514
|
+
`Network error connecting to ${config.baseUrl}: ${error instanceof Error ? error.message : String(error)}`,
|
|
5515
|
+
"NETWORK_ERROR"
|
|
5516
|
+
);
|
|
5517
|
+
}
|
|
5518
|
+
if (!response.ok) {
|
|
5519
|
+
const errorMessage = await parseErrorResponse2(response);
|
|
5520
|
+
const status = response.status;
|
|
5521
|
+
if (status === 400) {
|
|
5522
|
+
if (errorMessage.toLowerCase().includes("siwe")) {
|
|
5523
|
+
throw new BillingSessionError(`Invalid SIWE message: ${errorMessage}`, "INVALID_MESSAGE", status);
|
|
5524
|
+
}
|
|
5525
|
+
throw new BillingSessionError(`Bad request: ${errorMessage}`, "INVALID_MESSAGE", status);
|
|
5526
|
+
}
|
|
5527
|
+
if (status === 401) {
|
|
5528
|
+
throw new BillingSessionError(`Invalid signature: ${errorMessage}`, "INVALID_SIGNATURE", status);
|
|
5529
|
+
}
|
|
5530
|
+
throw new BillingSessionError(`Login failed: ${errorMessage}`, "UNKNOWN", status);
|
|
5531
|
+
}
|
|
5532
|
+
const data = await response.json();
|
|
5533
|
+
return {
|
|
5534
|
+
success: data.success,
|
|
5535
|
+
address: data.address
|
|
5536
|
+
};
|
|
5537
|
+
}
|
|
5538
|
+
async function getBillingApiSession(config) {
|
|
5539
|
+
let response;
|
|
5540
|
+
try {
|
|
5541
|
+
response = await fetch(`${config.baseUrl}/auth/session`, {
|
|
5542
|
+
method: "GET",
|
|
5543
|
+
credentials: "include",
|
|
5544
|
+
// Include cookies for session management
|
|
5545
|
+
headers: {
|
|
5546
|
+
"Content-Type": "application/json"
|
|
5547
|
+
}
|
|
5548
|
+
});
|
|
5549
|
+
} catch {
|
|
5550
|
+
return {
|
|
5551
|
+
authenticated: false
|
|
5552
|
+
};
|
|
5553
|
+
}
|
|
5554
|
+
if (response.status === 401) {
|
|
5555
|
+
return {
|
|
5556
|
+
authenticated: false
|
|
5557
|
+
};
|
|
5558
|
+
}
|
|
5559
|
+
if (!response.ok) {
|
|
5560
|
+
const errorMessage = await parseErrorResponse2(response);
|
|
5561
|
+
throw new BillingSessionError(`Failed to get session: ${errorMessage}`, "UNKNOWN", response.status);
|
|
5562
|
+
}
|
|
5563
|
+
const data = await response.json();
|
|
5564
|
+
return {
|
|
5565
|
+
authenticated: data.authenticated,
|
|
5566
|
+
address: data.address,
|
|
5567
|
+
chainId: data.chainId,
|
|
5568
|
+
authenticatedAt: data.authenticatedAt
|
|
5569
|
+
};
|
|
5570
|
+
}
|
|
5571
|
+
async function logoutFromBillingApi(config) {
|
|
5572
|
+
let response;
|
|
5573
|
+
try {
|
|
5574
|
+
response = await fetch(`${config.baseUrl}/auth/logout`, {
|
|
5575
|
+
method: "POST",
|
|
5576
|
+
credentials: "include",
|
|
5577
|
+
// Include cookies for session management
|
|
5578
|
+
headers: {
|
|
5579
|
+
"Content-Type": "application/json"
|
|
5580
|
+
}
|
|
5581
|
+
});
|
|
5582
|
+
} catch (error) {
|
|
5583
|
+
throw new BillingSessionError(
|
|
5584
|
+
`Network error connecting to ${config.baseUrl}: ${error instanceof Error ? error.message : String(error)}`,
|
|
5585
|
+
"NETWORK_ERROR"
|
|
5586
|
+
);
|
|
5587
|
+
}
|
|
5588
|
+
if (response.status === 401) {
|
|
5589
|
+
return;
|
|
5590
|
+
}
|
|
5591
|
+
if (!response.ok) {
|
|
5592
|
+
const errorMessage = await parseErrorResponse2(response);
|
|
5593
|
+
throw new BillingSessionError(`Logout failed: ${errorMessage}`, "UNKNOWN", response.status);
|
|
5594
|
+
}
|
|
5595
|
+
}
|
|
5596
|
+
|
|
5597
|
+
// src/client/common/utils/billingapi.ts
|
|
5243
5598
|
var BillingApiClient = class {
|
|
5244
|
-
constructor(config, walletClient) {
|
|
5599
|
+
constructor(config, walletClient, options = {}) {
|
|
5245
5600
|
this.config = config;
|
|
5246
5601
|
this.walletClient = walletClient;
|
|
5602
|
+
this.options = options;
|
|
5603
|
+
this.useSession = options.useSession ?? false;
|
|
5604
|
+
if (!this.useSession && !walletClient) {
|
|
5605
|
+
throw new Error("WalletClient is required when not using session authentication");
|
|
5606
|
+
}
|
|
5247
5607
|
}
|
|
5248
5608
|
/**
|
|
5249
5609
|
* Get the address of the connected wallet
|
|
5610
|
+
* Returns undefined if using session auth without a wallet client
|
|
5250
5611
|
*/
|
|
5251
5612
|
get address() {
|
|
5252
|
-
const account = this.walletClient
|
|
5613
|
+
const account = this.walletClient?.account;
|
|
5253
5614
|
if (!account) {
|
|
5254
|
-
|
|
5615
|
+
if (!this.useSession) {
|
|
5616
|
+
throw new Error("WalletClient must have an account attached");
|
|
5617
|
+
}
|
|
5618
|
+
return void 0;
|
|
5255
5619
|
}
|
|
5256
5620
|
return account.address;
|
|
5257
5621
|
}
|
|
5258
|
-
|
|
5622
|
+
/**
|
|
5623
|
+
* Get the base URL of the billing API
|
|
5624
|
+
*/
|
|
5625
|
+
get baseUrl() {
|
|
5626
|
+
return this.config.billingApiServerURL;
|
|
5627
|
+
}
|
|
5628
|
+
// ==========================================================================
|
|
5629
|
+
// SIWE Session Methods
|
|
5630
|
+
// ==========================================================================
|
|
5631
|
+
/**
|
|
5632
|
+
* Login to the billing API using SIWE
|
|
5633
|
+
*
|
|
5634
|
+
* This establishes a session with the billing API by verifying the SIWE message
|
|
5635
|
+
* and signature. On success, a session cookie is set in the browser.
|
|
5636
|
+
*
|
|
5637
|
+
* @param request - Login request containing SIWE message and signature
|
|
5638
|
+
* @returns Login result with the authenticated address
|
|
5639
|
+
*
|
|
5640
|
+
* @example
|
|
5641
|
+
* ```typescript
|
|
5642
|
+
* const { message } = createSiweMessage({
|
|
5643
|
+
* address: userAddress,
|
|
5644
|
+
* chainId: 11155111,
|
|
5645
|
+
* domain: window.location.host,
|
|
5646
|
+
* uri: window.location.origin,
|
|
5647
|
+
* });
|
|
5648
|
+
*
|
|
5649
|
+
* const signature = await signMessageAsync({ message });
|
|
5650
|
+
* const result = await billingClient.siweLogin({ message, signature });
|
|
5651
|
+
* ```
|
|
5652
|
+
*/
|
|
5653
|
+
async siweLogin(request) {
|
|
5654
|
+
return loginToBillingApi({ baseUrl: this.baseUrl }, request);
|
|
5655
|
+
}
|
|
5656
|
+
/**
|
|
5657
|
+
* Logout from the billing API
|
|
5658
|
+
*
|
|
5659
|
+
* This destroys the current session and clears the session cookie.
|
|
5660
|
+
*/
|
|
5661
|
+
async siweLogout() {
|
|
5662
|
+
return logoutFromBillingApi({ baseUrl: this.baseUrl });
|
|
5663
|
+
}
|
|
5664
|
+
/**
|
|
5665
|
+
* Get the current session status from the billing API
|
|
5666
|
+
*
|
|
5667
|
+
* @returns Session information including authentication status and address
|
|
5668
|
+
*/
|
|
5669
|
+
async getSession() {
|
|
5670
|
+
return getBillingApiSession({ baseUrl: this.baseUrl });
|
|
5671
|
+
}
|
|
5672
|
+
/**
|
|
5673
|
+
* Check if there is a valid session
|
|
5674
|
+
*
|
|
5675
|
+
* @returns True if session is authenticated, false otherwise
|
|
5676
|
+
*/
|
|
5677
|
+
async isSessionValid() {
|
|
5678
|
+
const session = await this.getSession();
|
|
5679
|
+
return session.authenticated;
|
|
5680
|
+
}
|
|
5681
|
+
// ==========================================================================
|
|
5682
|
+
// Subscription Methods
|
|
5683
|
+
// ==========================================================================
|
|
5684
|
+
async createSubscription(productId = "compute", options) {
|
|
5259
5685
|
const endpoint = `${this.config.billingApiServerURL}/products/${productId}/subscription`;
|
|
5260
|
-
const
|
|
5686
|
+
const body = options ? {
|
|
5687
|
+
success_url: options.successUrl,
|
|
5688
|
+
cancel_url: options.cancelUrl
|
|
5689
|
+
} : void 0;
|
|
5690
|
+
const resp = await this.makeAuthenticatedRequest(endpoint, "POST", productId, body);
|
|
5261
5691
|
return resp.json();
|
|
5262
5692
|
}
|
|
5263
5693
|
async getSubscription(productId = "compute") {
|
|
@@ -5269,10 +5699,72 @@ var BillingApiClient = class {
|
|
|
5269
5699
|
const endpoint = `${this.config.billingApiServerURL}/products/${productId}/subscription`;
|
|
5270
5700
|
await this.makeAuthenticatedRequest(endpoint, "DELETE", productId);
|
|
5271
5701
|
}
|
|
5702
|
+
// ==========================================================================
|
|
5703
|
+
// Internal Methods
|
|
5704
|
+
// ==========================================================================
|
|
5272
5705
|
/**
|
|
5273
5706
|
* Make an authenticated request to the billing API
|
|
5707
|
+
*
|
|
5708
|
+
* Uses session auth if useSession is true, otherwise uses EIP-712 signature auth.
|
|
5709
|
+
*/
|
|
5710
|
+
async makeAuthenticatedRequest(url, method, productId, body) {
|
|
5711
|
+
if (this.useSession) {
|
|
5712
|
+
return this.makeSessionAuthenticatedRequest(url, method, body);
|
|
5713
|
+
}
|
|
5714
|
+
return this.makeSignatureAuthenticatedRequest(url, method, productId, body);
|
|
5715
|
+
}
|
|
5716
|
+
/**
|
|
5717
|
+
* Make a request using session-based authentication (cookies)
|
|
5274
5718
|
*/
|
|
5275
|
-
async
|
|
5719
|
+
async makeSessionAuthenticatedRequest(url, method, body) {
|
|
5720
|
+
const headers = {};
|
|
5721
|
+
if (body) {
|
|
5722
|
+
headers["Content-Type"] = "application/json";
|
|
5723
|
+
}
|
|
5724
|
+
try {
|
|
5725
|
+
const response = await fetch(url, {
|
|
5726
|
+
method,
|
|
5727
|
+
credentials: "include",
|
|
5728
|
+
// Include cookies for session management
|
|
5729
|
+
headers,
|
|
5730
|
+
body: body ? JSON.stringify(body) : void 0
|
|
5731
|
+
});
|
|
5732
|
+
const status = response.status;
|
|
5733
|
+
const statusText = status >= 200 && status < 300 ? "OK" : "Error";
|
|
5734
|
+
if (status < 200 || status >= 300) {
|
|
5735
|
+
let errorBody;
|
|
5736
|
+
try {
|
|
5737
|
+
errorBody = await response.text();
|
|
5738
|
+
} catch {
|
|
5739
|
+
errorBody = statusText;
|
|
5740
|
+
}
|
|
5741
|
+
throw new Error(`BillingAPI request failed: ${status} ${statusText} - ${errorBody}`);
|
|
5742
|
+
}
|
|
5743
|
+
const responseData = await response.json();
|
|
5744
|
+
return {
|
|
5745
|
+
json: async () => responseData,
|
|
5746
|
+
text: async () => JSON.stringify(responseData)
|
|
5747
|
+
};
|
|
5748
|
+
} catch (error) {
|
|
5749
|
+
if (error.name === "TypeError" || error.message?.includes("fetch")) {
|
|
5750
|
+
throw new Error(
|
|
5751
|
+
`Failed to connect to BillingAPI at ${url}: ${error.message}
|
|
5752
|
+
Please check:
|
|
5753
|
+
1. Your internet connection
|
|
5754
|
+
2. The API server is accessible: ${this.config.billingApiServerURL}
|
|
5755
|
+
3. Firewall/proxy settings`
|
|
5756
|
+
);
|
|
5757
|
+
}
|
|
5758
|
+
throw error;
|
|
5759
|
+
}
|
|
5760
|
+
}
|
|
5761
|
+
/**
|
|
5762
|
+
* Make a request using EIP-712 signature authentication
|
|
5763
|
+
*/
|
|
5764
|
+
async makeSignatureAuthenticatedRequest(url, method, productId, body) {
|
|
5765
|
+
if (!this.walletClient) {
|
|
5766
|
+
throw new Error("WalletClient is required for signature authentication");
|
|
5767
|
+
}
|
|
5276
5768
|
const expiry = BigInt(Math.floor(Date.now() / 1e3) + 5 * 60);
|
|
5277
5769
|
const { signature } = await calculateBillingAuthSignature({
|
|
5278
5770
|
walletClient: this.walletClient,
|
|
@@ -5284,11 +5776,15 @@ var BillingApiClient = class {
|
|
|
5284
5776
|
"X-Account": this.address,
|
|
5285
5777
|
"X-Expiry": expiry.toString()
|
|
5286
5778
|
};
|
|
5779
|
+
if (body) {
|
|
5780
|
+
headers["Content-Type"] = "application/json";
|
|
5781
|
+
}
|
|
5287
5782
|
try {
|
|
5288
5783
|
const response = await axios2({
|
|
5289
5784
|
method,
|
|
5290
5785
|
url,
|
|
5291
5786
|
headers,
|
|
5787
|
+
data: body,
|
|
5292
5788
|
timeout: 3e4,
|
|
5293
5789
|
maxRedirects: 0,
|
|
5294
5790
|
validateStatus: () => true
|
|
@@ -5297,8 +5793,8 @@ var BillingApiClient = class {
|
|
|
5297
5793
|
const status = response.status;
|
|
5298
5794
|
const statusText = status >= 200 && status < 300 ? "OK" : "Error";
|
|
5299
5795
|
if (status < 200 || status >= 300) {
|
|
5300
|
-
const
|
|
5301
|
-
throw new Error(`BillingAPI request failed: ${status} ${statusText} - ${
|
|
5796
|
+
const body2 = typeof response.data === "string" ? response.data : JSON.stringify(response.data);
|
|
5797
|
+
throw new Error(`BillingAPI request failed: ${status} ${statusText} - ${body2}`);
|
|
5302
5798
|
}
|
|
5303
5799
|
return {
|
|
5304
5800
|
json: async () => response.data,
|
|
@@ -6784,7 +7280,7 @@ async function logs(options, walletClient, publicClient, environmentConfig, logg
|
|
|
6784
7280
|
environmentConfig,
|
|
6785
7281
|
walletClient,
|
|
6786
7282
|
publicClient,
|
|
6787
|
-
options.clientId
|
|
7283
|
+
options.clientId ? { clientId: options.clientId } : void 0
|
|
6788
7284
|
);
|
|
6789
7285
|
let logsText;
|
|
6790
7286
|
let logsError = null;
|
|
@@ -7083,7 +7579,7 @@ function createAppModule(ctx) {
|
|
|
7083
7579
|
environment,
|
|
7084
7580
|
walletClient,
|
|
7085
7581
|
publicClient,
|
|
7086
|
-
ctx.clientId
|
|
7582
|
+
ctx.clientId ? { clientId: ctx.clientId } : void 0
|
|
7087
7583
|
);
|
|
7088
7584
|
return userApiClient.uploadAppProfile(appId, profile.name, {
|
|
7089
7585
|
website: profile.website,
|
|
@@ -7283,7 +7779,10 @@ function createBillingModule(config) {
|
|
|
7283
7779
|
};
|
|
7284
7780
|
}
|
|
7285
7781
|
logger.debug(`Creating subscription for ${productId}...`);
|
|
7286
|
-
const result = await billingApi.createSubscription(productId
|
|
7782
|
+
const result = await billingApi.createSubscription(productId, {
|
|
7783
|
+
successUrl: opts?.successUrl,
|
|
7784
|
+
cancelUrl: opts?.cancelUrl
|
|
7785
|
+
});
|
|
7287
7786
|
logger.debug(`Checkout URL: ${result.checkoutUrl}`);
|
|
7288
7787
|
return {
|
|
7289
7788
|
type: "checkout_created",
|
|
@@ -7342,11 +7841,55 @@ function createBillingModule(config) {
|
|
|
7342
7841
|
|
|
7343
7842
|
// src/client/common/utils/buildapi.ts
|
|
7344
7843
|
import axios3 from "axios";
|
|
7844
|
+
var MAX_RETRIES = 5;
|
|
7845
|
+
var INITIAL_BACKOFF_MS = 1e3;
|
|
7846
|
+
var MAX_BACKOFF_MS = 3e4;
|
|
7847
|
+
async function sleep2(ms) {
|
|
7848
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
7849
|
+
}
|
|
7850
|
+
function getRetryDelay(res, attempt) {
|
|
7851
|
+
const retryAfter = res.headers["retry-after"];
|
|
7852
|
+
if (retryAfter) {
|
|
7853
|
+
const seconds = parseInt(retryAfter, 10);
|
|
7854
|
+
if (!isNaN(seconds)) {
|
|
7855
|
+
return Math.min(seconds * 1e3, MAX_BACKOFF_MS);
|
|
7856
|
+
}
|
|
7857
|
+
}
|
|
7858
|
+
return Math.min(INITIAL_BACKOFF_MS * Math.pow(2, attempt), MAX_BACKOFF_MS);
|
|
7859
|
+
}
|
|
7860
|
+
async function requestWithRetry(config) {
|
|
7861
|
+
let lastResponse;
|
|
7862
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
7863
|
+
const res = await axios3({ ...config, validateStatus: () => true });
|
|
7864
|
+
lastResponse = res;
|
|
7865
|
+
if (res.status !== 429) {
|
|
7866
|
+
return res;
|
|
7867
|
+
}
|
|
7868
|
+
if (attempt < MAX_RETRIES) {
|
|
7869
|
+
const delay = getRetryDelay(res, attempt);
|
|
7870
|
+
await sleep2(delay);
|
|
7871
|
+
}
|
|
7872
|
+
}
|
|
7873
|
+
return lastResponse;
|
|
7874
|
+
}
|
|
7345
7875
|
var BuildApiClient = class {
|
|
7346
7876
|
constructor(options) {
|
|
7347
|
-
|
|
7877
|
+
let url = options.baseUrl;
|
|
7878
|
+
while (url.endsWith("/")) {
|
|
7879
|
+
url = url.slice(0, -1);
|
|
7880
|
+
}
|
|
7881
|
+
this.baseUrl = url;
|
|
7348
7882
|
this.clientId = options.clientId;
|
|
7349
7883
|
this.walletClient = options.walletClient;
|
|
7884
|
+
this.useSession = options.useSession ?? false;
|
|
7885
|
+
this.billingSessionId = options.billingSessionId;
|
|
7886
|
+
}
|
|
7887
|
+
/**
|
|
7888
|
+
* Update the billing session ID.
|
|
7889
|
+
* Call this after logging into the billing API to enable session-based auth for builds.
|
|
7890
|
+
*/
|
|
7891
|
+
setBillingSessionId(sessionId) {
|
|
7892
|
+
this.billingSessionId = sessionId;
|
|
7350
7893
|
}
|
|
7351
7894
|
/**
|
|
7352
7895
|
* Get the address of the connected wallet
|
|
@@ -7358,8 +7901,17 @@ var BuildApiClient = class {
|
|
|
7358
7901
|
}
|
|
7359
7902
|
return account.address;
|
|
7360
7903
|
}
|
|
7904
|
+
/**
|
|
7905
|
+
* Submit a new build request.
|
|
7906
|
+
* Supports two auth modes (session auth is tried first when billingSessionId is available):
|
|
7907
|
+
* 1. Session-based auth: X-Billing-Session header (forwarded billing_session cookie)
|
|
7908
|
+
* 2. Signature-based auth: Authorization + X-Account + X-eigenx-expiry headers (requires walletClient)
|
|
7909
|
+
*/
|
|
7361
7910
|
async submitBuild(payload) {
|
|
7362
|
-
|
|
7911
|
+
if (this.useSession && this.billingSessionId) {
|
|
7912
|
+
return this.billingSessionAuthJsonRequest("/builds", "POST", payload);
|
|
7913
|
+
}
|
|
7914
|
+
return this.signatureAuthJsonRequest("/builds", "POST", payload);
|
|
7363
7915
|
}
|
|
7364
7916
|
async getBuild(buildId) {
|
|
7365
7917
|
return this.publicJsonRequest(`/builds/${encodeURIComponent(buildId)}`);
|
|
@@ -7370,33 +7922,42 @@ var BuildApiClient = class {
|
|
|
7370
7922
|
async verify(identifier) {
|
|
7371
7923
|
return this.publicJsonRequest(`/builds/verify/${encodeURIComponent(identifier)}`);
|
|
7372
7924
|
}
|
|
7925
|
+
/**
|
|
7926
|
+
* Get build logs. Supports session auth (identity verification only, no billing check).
|
|
7927
|
+
*/
|
|
7373
7928
|
async getLogs(buildId) {
|
|
7374
|
-
return this.
|
|
7929
|
+
return this.sessionOrSignatureTextRequest(`/builds/${encodeURIComponent(buildId)}/logs`);
|
|
7375
7930
|
}
|
|
7376
7931
|
async listBuilds(params) {
|
|
7377
|
-
const res = await
|
|
7932
|
+
const res = await requestWithRetry({
|
|
7378
7933
|
url: `${this.baseUrl}/builds`,
|
|
7379
7934
|
method: "GET",
|
|
7380
7935
|
params,
|
|
7381
7936
|
headers: this.clientId ? { "x-client-id": this.clientId } : void 0,
|
|
7382
7937
|
timeout: 6e4,
|
|
7383
|
-
validateStatus: () => true
|
|
7938
|
+
validateStatus: () => true,
|
|
7939
|
+
withCredentials: this.useSession
|
|
7384
7940
|
});
|
|
7385
7941
|
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
7386
7942
|
return res.data;
|
|
7387
7943
|
}
|
|
7388
7944
|
async publicJsonRequest(path8) {
|
|
7389
|
-
const res = await
|
|
7945
|
+
const res = await requestWithRetry({
|
|
7390
7946
|
url: `${this.baseUrl}${path8}`,
|
|
7391
7947
|
method: "GET",
|
|
7392
7948
|
headers: this.clientId ? { "x-client-id": this.clientId } : void 0,
|
|
7393
7949
|
timeout: 6e4,
|
|
7394
|
-
validateStatus: () => true
|
|
7950
|
+
validateStatus: () => true,
|
|
7951
|
+
withCredentials: this.useSession
|
|
7395
7952
|
});
|
|
7396
7953
|
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
7397
7954
|
return res.data;
|
|
7398
7955
|
}
|
|
7399
|
-
|
|
7956
|
+
/**
|
|
7957
|
+
* Make a request that ALWAYS requires signature auth (for billing verification).
|
|
7958
|
+
* Used for endpoints like POST /builds that need to verify subscription status.
|
|
7959
|
+
*/
|
|
7960
|
+
async signatureAuthJsonRequest(path8, method, body) {
|
|
7400
7961
|
if (!this.walletClient?.account) {
|
|
7401
7962
|
throw new Error("WalletClient with account required for authenticated requests");
|
|
7402
7963
|
}
|
|
@@ -7413,39 +7974,74 @@ var BuildApiClient = class {
|
|
|
7413
7974
|
headers.Authorization = `Bearer ${signature}`;
|
|
7414
7975
|
headers["X-eigenx-expiry"] = expiry.toString();
|
|
7415
7976
|
headers["X-Account"] = this.address;
|
|
7416
|
-
const res = await
|
|
7977
|
+
const res = await requestWithRetry({
|
|
7417
7978
|
url: `${this.baseUrl}${path8}`,
|
|
7418
7979
|
method,
|
|
7419
7980
|
headers,
|
|
7420
7981
|
data: body,
|
|
7421
7982
|
timeout: 6e4,
|
|
7422
|
-
validateStatus: () => true
|
|
7983
|
+
validateStatus: () => true,
|
|
7984
|
+
withCredentials: this.useSession
|
|
7423
7985
|
});
|
|
7424
7986
|
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
7425
7987
|
return res.data;
|
|
7426
7988
|
}
|
|
7427
|
-
|
|
7428
|
-
|
|
7429
|
-
|
|
7989
|
+
/**
|
|
7990
|
+
* Make a request using billing session auth (for billing verification without wallet signature).
|
|
7991
|
+
* Forwards the billing_session cookie value via X-Billing-Session header.
|
|
7992
|
+
* Used for endpoints that need to verify subscription status when using session-based auth.
|
|
7993
|
+
*/
|
|
7994
|
+
async billingSessionAuthJsonRequest(path8, method, body) {
|
|
7995
|
+
if (!this.billingSessionId) {
|
|
7996
|
+
throw new Error("billingSessionId required for session-based billing auth");
|
|
7430
7997
|
}
|
|
7431
|
-
const headers = {
|
|
7998
|
+
const headers = {
|
|
7999
|
+
"Content-Type": "application/json",
|
|
8000
|
+
"X-Billing-Session": this.billingSessionId
|
|
8001
|
+
};
|
|
7432
8002
|
if (this.clientId) headers["x-client-id"] = this.clientId;
|
|
7433
|
-
const
|
|
7434
|
-
|
|
7435
|
-
|
|
7436
|
-
|
|
7437
|
-
|
|
8003
|
+
const res = await requestWithRetry({
|
|
8004
|
+
url: `${this.baseUrl}${path8}`,
|
|
8005
|
+
method,
|
|
8006
|
+
headers,
|
|
8007
|
+
data: body,
|
|
8008
|
+
timeout: 6e4,
|
|
8009
|
+
validateStatus: () => true,
|
|
8010
|
+
withCredentials: this.useSession
|
|
7438
8011
|
});
|
|
7439
|
-
|
|
7440
|
-
|
|
7441
|
-
|
|
7442
|
-
|
|
8012
|
+
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
8013
|
+
return res.data;
|
|
8014
|
+
}
|
|
8015
|
+
/**
|
|
8016
|
+
* Make an authenticated request that can use session OR signature auth.
|
|
8017
|
+
* When useSession is true, relies on cookies for identity verification.
|
|
8018
|
+
* Used for endpoints that only need identity verification (not billing).
|
|
8019
|
+
*/
|
|
8020
|
+
async sessionOrSignatureTextRequest(path8) {
|
|
8021
|
+
const headers = {};
|
|
8022
|
+
if (this.clientId) headers["x-client-id"] = this.clientId;
|
|
8023
|
+
if (!this.useSession) {
|
|
8024
|
+
if (!this.walletClient?.account) {
|
|
8025
|
+
throw new Error("WalletClient with account required for authenticated requests");
|
|
8026
|
+
}
|
|
8027
|
+
const expiry = BigInt(Math.floor(Date.now() / 1e3) + 60);
|
|
8028
|
+
const { signature } = await calculateBillingAuthSignature({
|
|
8029
|
+
walletClient: this.walletClient,
|
|
8030
|
+
product: "compute",
|
|
8031
|
+
expiry
|
|
8032
|
+
});
|
|
8033
|
+
headers.Authorization = `Bearer ${signature}`;
|
|
8034
|
+
headers["X-eigenx-expiry"] = expiry.toString();
|
|
8035
|
+
headers["X-Account"] = this.address;
|
|
8036
|
+
}
|
|
8037
|
+
const res = await requestWithRetry({
|
|
7443
8038
|
url: `${this.baseUrl}${path8}`,
|
|
7444
8039
|
method: "GET",
|
|
7445
8040
|
headers,
|
|
7446
8041
|
timeout: 6e4,
|
|
7447
8042
|
responseType: "text",
|
|
7448
|
-
validateStatus: () => true
|
|
8043
|
+
validateStatus: () => true,
|
|
8044
|
+
withCredentials: this.useSession
|
|
7449
8045
|
});
|
|
7450
8046
|
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
7451
8047
|
return typeof res.data === "string" ? res.data : JSON.stringify(res.data);
|
|
@@ -7634,7 +8230,7 @@ function createBuildModule(config) {
|
|
|
7634
8230
|
if (build.status === BUILD_STATUS.FAILED) {
|
|
7635
8231
|
throw new BuildFailedError(build.errorMessage ?? "Build failed", buildId);
|
|
7636
8232
|
}
|
|
7637
|
-
await
|
|
8233
|
+
await sleep3(pollIntervalMs);
|
|
7638
8234
|
}
|
|
7639
8235
|
},
|
|
7640
8236
|
async *streamLogs(buildId, pollIntervalMs = DEFAULT_POLL_INTERVAL) {
|
|
@@ -7656,12 +8252,12 @@ function createBuildModule(config) {
|
|
|
7656
8252
|
lastLength = logs2.length;
|
|
7657
8253
|
}
|
|
7658
8254
|
if (build.status !== BUILD_STATUS.BUILDING) break;
|
|
7659
|
-
await
|
|
8255
|
+
await sleep3(pollIntervalMs);
|
|
7660
8256
|
}
|
|
7661
8257
|
}
|
|
7662
8258
|
};
|
|
7663
8259
|
}
|
|
7664
|
-
function
|
|
8260
|
+
function sleep3(ms) {
|
|
7665
8261
|
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
7666
8262
|
}
|
|
7667
8263
|
function transformBuild(raw) {
|
|
@@ -7944,6 +8540,77 @@ function generateNewPrivateKey() {
|
|
|
7944
8540
|
};
|
|
7945
8541
|
}
|
|
7946
8542
|
|
|
8543
|
+
// src/client/common/auth/siwe.ts
|
|
8544
|
+
import { SiweMessage, generateNonce as siweGenerateNonce } from "siwe";
|
|
8545
|
+
var generateNonce = siweGenerateNonce;
|
|
8546
|
+
function createSiweMessage(params) {
|
|
8547
|
+
const now = /* @__PURE__ */ new Date();
|
|
8548
|
+
const nonce = params.nonce || generateNonce();
|
|
8549
|
+
const issuedAt = params.issuedAt || now;
|
|
8550
|
+
const expirationTime = params.expirationTime || new Date(now.getTime() + 24 * 60 * 60 * 1e3);
|
|
8551
|
+
const siweMessage = new SiweMessage({
|
|
8552
|
+
domain: params.domain,
|
|
8553
|
+
address: params.address,
|
|
8554
|
+
statement: params.statement,
|
|
8555
|
+
uri: params.uri,
|
|
8556
|
+
version: "1",
|
|
8557
|
+
chainId: params.chainId,
|
|
8558
|
+
nonce,
|
|
8559
|
+
issuedAt: issuedAt.toISOString(),
|
|
8560
|
+
expirationTime: expirationTime.toISOString(),
|
|
8561
|
+
notBefore: params.notBefore?.toISOString(),
|
|
8562
|
+
requestId: params.requestId,
|
|
8563
|
+
resources: params.resources
|
|
8564
|
+
});
|
|
8565
|
+
return {
|
|
8566
|
+
message: siweMessage.prepareMessage(),
|
|
8567
|
+
params: {
|
|
8568
|
+
address: params.address,
|
|
8569
|
+
chainId: params.chainId,
|
|
8570
|
+
domain: params.domain,
|
|
8571
|
+
uri: params.uri,
|
|
8572
|
+
nonce,
|
|
8573
|
+
issuedAt,
|
|
8574
|
+
statement: params.statement,
|
|
8575
|
+
expirationTime,
|
|
8576
|
+
notBefore: params.notBefore,
|
|
8577
|
+
requestId: params.requestId,
|
|
8578
|
+
resources: params.resources
|
|
8579
|
+
}
|
|
8580
|
+
};
|
|
8581
|
+
}
|
|
8582
|
+
function parseSiweMessage(message) {
|
|
8583
|
+
try {
|
|
8584
|
+
const siweMessage = new SiweMessage(message);
|
|
8585
|
+
return {
|
|
8586
|
+
address: siweMessage.address,
|
|
8587
|
+
chainId: siweMessage.chainId,
|
|
8588
|
+
domain: siweMessage.domain,
|
|
8589
|
+
uri: siweMessage.uri,
|
|
8590
|
+
nonce: siweMessage.nonce,
|
|
8591
|
+
statement: siweMessage.statement,
|
|
8592
|
+
issuedAt: siweMessage.issuedAt ? new Date(siweMessage.issuedAt) : void 0,
|
|
8593
|
+
expirationTime: siweMessage.expirationTime ? new Date(siweMessage.expirationTime) : void 0,
|
|
8594
|
+
notBefore: siweMessage.notBefore ? new Date(siweMessage.notBefore) : void 0,
|
|
8595
|
+
requestId: siweMessage.requestId,
|
|
8596
|
+
resources: siweMessage.resources
|
|
8597
|
+
};
|
|
8598
|
+
} catch {
|
|
8599
|
+
return null;
|
|
8600
|
+
}
|
|
8601
|
+
}
|
|
8602
|
+
function isSiweMessageExpired(params) {
|
|
8603
|
+
if (!params.expirationTime) return false;
|
|
8604
|
+
return /* @__PURE__ */ new Date() > params.expirationTime;
|
|
8605
|
+
}
|
|
8606
|
+
function isSiweMessageNotYetValid(params) {
|
|
8607
|
+
if (!params.notBefore) return false;
|
|
8608
|
+
return /* @__PURE__ */ new Date() < params.notBefore;
|
|
8609
|
+
}
|
|
8610
|
+
|
|
8611
|
+
// src/client/common/auth/index.ts
|
|
8612
|
+
init_session();
|
|
8613
|
+
|
|
7947
8614
|
// src/client/common/utils/instance.ts
|
|
7948
8615
|
async function getCurrentInstanceType(preflightCtx, appID, logger, clientId) {
|
|
7949
8616
|
try {
|
|
@@ -7951,7 +8618,7 @@ async function getCurrentInstanceType(preflightCtx, appID, logger, clientId) {
|
|
|
7951
8618
|
preflightCtx.environmentConfig,
|
|
7952
8619
|
preflightCtx.walletClient,
|
|
7953
8620
|
preflightCtx.publicClient,
|
|
7954
|
-
clientId
|
|
8621
|
+
clientId ? { clientId } : void 0
|
|
7955
8622
|
);
|
|
7956
8623
|
const infos = await userApiClient.getInfos([appID], 1);
|
|
7957
8624
|
if (infos.length === 0) {
|
|
@@ -8014,6 +8681,7 @@ export {
|
|
|
8014
8681
|
NotFoundError,
|
|
8015
8682
|
PRIMARY_LANGUAGES,
|
|
8016
8683
|
PostHogClient,
|
|
8684
|
+
SessionError,
|
|
8017
8685
|
TimeoutError,
|
|
8018
8686
|
UserApiClient,
|
|
8019
8687
|
addHexPrefix,
|
|
@@ -8030,6 +8698,7 @@ export {
|
|
|
8030
8698
|
createComputeModule,
|
|
8031
8699
|
createECloudClient,
|
|
8032
8700
|
createMetricsContext,
|
|
8701
|
+
createSiweMessage,
|
|
8033
8702
|
createTelemetryClient,
|
|
8034
8703
|
createClients as createViemClients,
|
|
8035
8704
|
deleteLegacyPrivateKey,
|
|
@@ -8046,6 +8715,7 @@ export {
|
|
|
8046
8715
|
fetchTemplateCatalog,
|
|
8047
8716
|
formatETH,
|
|
8048
8717
|
generateNewPrivateKey,
|
|
8718
|
+
generateNonce,
|
|
8049
8719
|
getAddressFromPrivateKey,
|
|
8050
8720
|
getAllAppsByDeveloper,
|
|
8051
8721
|
getAppLatestReleaseBlockNumbers,
|
|
@@ -8056,6 +8726,7 @@ export {
|
|
|
8056
8726
|
getBuildType,
|
|
8057
8727
|
getCategoryDescriptions,
|
|
8058
8728
|
getChainFromID,
|
|
8729
|
+
getComputeApiSession,
|
|
8059
8730
|
getCurrentInstanceType,
|
|
8060
8731
|
getEnvironmentConfig,
|
|
8061
8732
|
getLegacyKeys,
|
|
@@ -8068,10 +8739,17 @@ export {
|
|
|
8068
8739
|
isEnvironmentAvailable,
|
|
8069
8740
|
isMainnet,
|
|
8070
8741
|
isNoopClient,
|
|
8742
|
+
isSessionValid,
|
|
8743
|
+
isSiweMessageExpired,
|
|
8744
|
+
isSiweMessageNotYetValid,
|
|
8071
8745
|
isSubscriptionActive,
|
|
8072
8746
|
keyExists,
|
|
8073
8747
|
listStoredKeys,
|
|
8748
|
+
loginToComputeApi,
|
|
8749
|
+
logoutFromComputeApi,
|
|
8074
8750
|
logs,
|
|
8751
|
+
noopLogger,
|
|
8752
|
+
parseSiweMessage,
|
|
8075
8753
|
prepareDeploy,
|
|
8076
8754
|
prepareDeployFromVerifiableBuild,
|
|
8077
8755
|
prepareUpgrade,
|