@layr-labs/ecloud-sdk 0.3.1-dev → 0.3.1-dev.0
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 +273 -4
- 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 +276 -5
- package/dist/billing.js.map +1 -1
- package/dist/browser.cjs +571 -175
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +53 -12
- package/dist/browser.d.ts +53 -12
- package/dist/browser.js +572 -176
- package/dist/browser.js.map +1 -1
- package/dist/{compute-BYhSs8en.d.ts → compute-BcJuIxc1.d.ts} +1 -1
- package/dist/{compute-Bpjb3hYD.d.cts → compute-oD9uqLtr.d.cts} +1 -1
- package/dist/compute.cjs +242 -156
- 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 +245 -157
- package/dist/compute.js.map +1 -1
- package/dist/{helpers-CEvhJz7f.d.cts → helpers-Cq7IBfHE.d.ts} +250 -6
- package/dist/{helpers-CQuBwQnu.d.ts → helpers-PknfbMQG.d.cts} +250 -6
- package/dist/{index-DeQzn_yM.d.cts → index-5y9NG_Id.d.cts} +9 -1
- package/dist/{index-DeQzn_yM.d.ts → index-5y9NG_Id.d.ts} +9 -1
- package/dist/index.cjs +636 -218
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -7
- package/dist/index.d.ts +7 -7
- package/dist/index.js +639 -219
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
|
|
@@ -2167,7 +2301,7 @@ function encodeExecuteBatchData(executions) {
|
|
|
2167
2301
|
});
|
|
2168
2302
|
}
|
|
2169
2303
|
async function estimateBatchGas(options) {
|
|
2170
|
-
const { publicClient, account, executions } = options;
|
|
2304
|
+
const { publicClient, account, executions, authorizationList } = options;
|
|
2171
2305
|
const executeBatchData = encodeExecuteBatchData(executions);
|
|
2172
2306
|
const [gasTipCap, block, estimatedGas] = await Promise.all([
|
|
2173
2307
|
publicClient.estimateMaxPriorityFeePerGas(),
|
|
@@ -2175,7 +2309,8 @@ async function estimateBatchGas(options) {
|
|
|
2175
2309
|
publicClient.estimateGas({
|
|
2176
2310
|
account,
|
|
2177
2311
|
to: account,
|
|
2178
|
-
data: executeBatchData
|
|
2312
|
+
data: executeBatchData,
|
|
2313
|
+
authorizationList
|
|
2179
2314
|
})
|
|
2180
2315
|
]);
|
|
2181
2316
|
const baseFee = block.baseFeePerGas ?? 0n;
|
|
@@ -2198,8 +2333,44 @@ async function checkERC7702Delegation(publicClient, account, delegatorAddress) {
|
|
|
2198
2333
|
const expectedCode = `0xef0100${delegatorAddress.slice(2)}`;
|
|
2199
2334
|
return code.toLowerCase() === expectedCode.toLowerCase();
|
|
2200
2335
|
}
|
|
2336
|
+
async function createAuthorizationList(options) {
|
|
2337
|
+
const { walletClient, publicClient, environmentConfig } = options;
|
|
2338
|
+
const account = walletClient.account;
|
|
2339
|
+
if (!account) {
|
|
2340
|
+
throw new Error("Wallet client must have an account");
|
|
2341
|
+
}
|
|
2342
|
+
const isDelegated2 = await checkERC7702Delegation(
|
|
2343
|
+
publicClient,
|
|
2344
|
+
account.address,
|
|
2345
|
+
environmentConfig.erc7702DelegatorAddress
|
|
2346
|
+
);
|
|
2347
|
+
if (isDelegated2) {
|
|
2348
|
+
return void 0;
|
|
2349
|
+
}
|
|
2350
|
+
const transactionNonce = await publicClient.getTransactionCount({
|
|
2351
|
+
address: account.address,
|
|
2352
|
+
blockTag: "pending"
|
|
2353
|
+
});
|
|
2354
|
+
const chainId = await publicClient.getChainId();
|
|
2355
|
+
const authorizationNonce = transactionNonce + 1;
|
|
2356
|
+
const signedAuthorization = await walletClient.signAuthorization({
|
|
2357
|
+
account,
|
|
2358
|
+
contractAddress: environmentConfig.erc7702DelegatorAddress,
|
|
2359
|
+
chainId,
|
|
2360
|
+
nonce: Number(authorizationNonce)
|
|
2361
|
+
});
|
|
2362
|
+
return [signedAuthorization];
|
|
2363
|
+
}
|
|
2201
2364
|
async function executeBatch(options, logger = noopLogger) {
|
|
2202
|
-
const {
|
|
2365
|
+
const {
|
|
2366
|
+
walletClient,
|
|
2367
|
+
publicClient,
|
|
2368
|
+
environmentConfig,
|
|
2369
|
+
executions,
|
|
2370
|
+
pendingMessage,
|
|
2371
|
+
gas,
|
|
2372
|
+
authorizationList: providedAuthList
|
|
2373
|
+
} = options;
|
|
2203
2374
|
const account = walletClient.account;
|
|
2204
2375
|
if (!account) {
|
|
2205
2376
|
throw new Error("Wallet client must have an account");
|
|
@@ -2209,27 +2380,29 @@ async function executeBatch(options, logger = noopLogger) {
|
|
|
2209
2380
|
throw new Error("Wallet client must have a chain");
|
|
2210
2381
|
}
|
|
2211
2382
|
const executeBatchData = encodeExecuteBatchData(executions);
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2383
|
+
let authorizationList = providedAuthList || [];
|
|
2384
|
+
if (authorizationList.length === 0) {
|
|
2385
|
+
const isDelegated2 = await checkERC7702Delegation(
|
|
2386
|
+
publicClient,
|
|
2387
|
+
account.address,
|
|
2388
|
+
environmentConfig.erc7702DelegatorAddress
|
|
2389
|
+
);
|
|
2390
|
+
if (!isDelegated2) {
|
|
2391
|
+
const transactionNonce = await publicClient.getTransactionCount({
|
|
2392
|
+
address: account.address,
|
|
2393
|
+
blockTag: "pending"
|
|
2394
|
+
});
|
|
2395
|
+
const chainId = await publicClient.getChainId();
|
|
2396
|
+
const authorizationNonce = transactionNonce + 1;
|
|
2397
|
+
logger.debug("Using wallet client signing for EIP-7702 authorization");
|
|
2398
|
+
const signedAuthorization = await walletClient.signAuthorization({
|
|
2399
|
+
account,
|
|
2400
|
+
contractAddress: environmentConfig.erc7702DelegatorAddress,
|
|
2401
|
+
chainId,
|
|
2402
|
+
nonce: Number(authorizationNonce)
|
|
2403
|
+
});
|
|
2404
|
+
authorizationList = [signedAuthorization];
|
|
2405
|
+
}
|
|
2233
2406
|
}
|
|
2234
2407
|
if (pendingMessage) {
|
|
2235
2408
|
logger.info(pendingMessage);
|
|
@@ -2244,6 +2417,9 @@ async function executeBatch(options, logger = noopLogger) {
|
|
|
2244
2417
|
if (authorizationList.length > 0) {
|
|
2245
2418
|
txRequest.authorizationList = authorizationList;
|
|
2246
2419
|
}
|
|
2420
|
+
if (gas?.gasLimit) {
|
|
2421
|
+
txRequest.gas = gas.gasLimit;
|
|
2422
|
+
}
|
|
2247
2423
|
if (gas?.maxFeePerGas) {
|
|
2248
2424
|
txRequest.maxFeePerGas = gas.maxFeePerGas;
|
|
2249
2425
|
}
|
|
@@ -2285,26 +2461,27 @@ async function executeBatch(options, logger = noopLogger) {
|
|
|
2285
2461
|
import { encodeFunctionData as encodeFunctionData2, decodeErrorResult as decodeErrorResult2, bytesToHex } from "viem";
|
|
2286
2462
|
|
|
2287
2463
|
// src/client/common/utils/helpers.ts
|
|
2288
|
-
import { extractChain, createPublicClient, createWalletClient, http } from "viem";
|
|
2464
|
+
import { extractChain, createPublicClient, createWalletClient, http, fallback } from "viem";
|
|
2289
2465
|
import { sepolia as sepolia2 } from "viem/chains";
|
|
2290
2466
|
import { privateKeyToAccount } from "viem/accounts";
|
|
2291
|
-
function getChainFromID(chainID,
|
|
2467
|
+
function getChainFromID(chainID, fallback2 = sepolia2) {
|
|
2292
2468
|
const id = Number(chainID);
|
|
2293
|
-
return extractChain({ chains: SUPPORTED_CHAINS, id }) ||
|
|
2469
|
+
return extractChain({ chains: SUPPORTED_CHAINS, id }) || fallback2;
|
|
2294
2470
|
}
|
|
2295
2471
|
function createClients(options) {
|
|
2296
2472
|
const { privateKey, rpcUrl, chainId } = options;
|
|
2297
2473
|
const privateKeyHex = addHexPrefix(privateKey);
|
|
2298
2474
|
const account = privateKeyToAccount(privateKeyHex);
|
|
2299
2475
|
const chain = getChainFromID(chainId);
|
|
2476
|
+
const transport = typeof rpcUrl === "string" ? http(rpcUrl) : fallback(rpcUrl.map((url) => http(url)));
|
|
2300
2477
|
const publicClient = createPublicClient({
|
|
2301
2478
|
chain,
|
|
2302
|
-
transport
|
|
2479
|
+
transport
|
|
2303
2480
|
});
|
|
2304
2481
|
const walletClient = createWalletClient({
|
|
2305
2482
|
account,
|
|
2306
2483
|
chain,
|
|
2307
|
-
transport
|
|
2484
|
+
transport
|
|
2308
2485
|
});
|
|
2309
2486
|
return { walletClient, publicClient };
|
|
2310
2487
|
}
|
|
@@ -3992,7 +4169,8 @@ async function executeDeployBatch(data, context, gas, logger = noopLogger) {
|
|
|
3992
4169
|
environmentConfig: context.environmentConfig,
|
|
3993
4170
|
executions: data.executions,
|
|
3994
4171
|
pendingMessage,
|
|
3995
|
-
gas
|
|
4172
|
+
gas,
|
|
4173
|
+
authorizationList: data.authorizationList
|
|
3996
4174
|
},
|
|
3997
4175
|
logger
|
|
3998
4176
|
);
|
|
@@ -4103,7 +4281,8 @@ async function executeUpgradeBatch(data, context, gas, logger = noopLogger) {
|
|
|
4103
4281
|
environmentConfig: context.environmentConfig,
|
|
4104
4282
|
executions: data.executions,
|
|
4105
4283
|
pendingMessage,
|
|
4106
|
-
gas
|
|
4284
|
+
gas,
|
|
4285
|
+
authorizationList: data.authorizationList
|
|
4107
4286
|
},
|
|
4108
4287
|
logger
|
|
4109
4288
|
);
|
|
@@ -4413,166 +4592,44 @@ async function calculateBillingAuthSignature(options) {
|
|
|
4413
4592
|
return { signature, expiry };
|
|
4414
4593
|
}
|
|
4415
4594
|
|
|
4416
|
-
// src/client/common/
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
this.code = code;
|
|
4421
|
-
this.statusCode = statusCode;
|
|
4422
|
-
this.name = "SessionError";
|
|
4423
|
-
}
|
|
4424
|
-
};
|
|
4425
|
-
function stripHexPrefix2(hex) {
|
|
4426
|
-
return hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
4595
|
+
// src/client/common/utils/userapi.ts
|
|
4596
|
+
init_session();
|
|
4597
|
+
function isJsonObject(value) {
|
|
4598
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4427
4599
|
}
|
|
4428
|
-
|
|
4429
|
-
|
|
4430
|
-
|
|
4431
|
-
return data.error || response.statusText;
|
|
4432
|
-
} catch {
|
|
4433
|
-
return response.statusText;
|
|
4434
|
-
}
|
|
4600
|
+
function readString(obj, key) {
|
|
4601
|
+
const v = obj[key];
|
|
4602
|
+
return typeof v === "string" ? v : void 0;
|
|
4435
4603
|
}
|
|
4436
|
-
|
|
4437
|
-
|
|
4438
|
-
|
|
4439
|
-
|
|
4440
|
-
|
|
4441
|
-
|
|
4442
|
-
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
|
|
4454
|
-
|
|
4455
|
-
);
|
|
4604
|
+
function readNumber(obj, key) {
|
|
4605
|
+
const v = obj[key];
|
|
4606
|
+
return typeof v === "number" && Number.isFinite(v) ? v : void 0;
|
|
4607
|
+
}
|
|
4608
|
+
var MAX_ADDRESS_COUNT = 5;
|
|
4609
|
+
var CanViewAppLogsPermission = "0x2fd3f2fe";
|
|
4610
|
+
var CanViewSensitiveAppInfoPermission = "0x0e67b22f";
|
|
4611
|
+
var CanUpdateAppProfilePermission = "0x036fef61";
|
|
4612
|
+
function getDefaultClientId() {
|
|
4613
|
+
const version = true ? "0.3.1-dev.0" : "0.0.0";
|
|
4614
|
+
return `ecloud-sdk/v${version}`;
|
|
4615
|
+
}
|
|
4616
|
+
var UserApiClient = class {
|
|
4617
|
+
constructor(config, walletClient, publicClient, options) {
|
|
4618
|
+
this.config = config;
|
|
4619
|
+
this.walletClient = walletClient;
|
|
4620
|
+
this.publicClient = publicClient;
|
|
4621
|
+
this.clientId = options?.clientId || getDefaultClientId();
|
|
4622
|
+
this.useSession = options?.useSession ?? false;
|
|
4456
4623
|
}
|
|
4457
|
-
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
|
|
4464
|
-
throw new SessionError(`Bad request: ${errorMessage}`, "INVALID_MESSAGE", status);
|
|
4465
|
-
}
|
|
4466
|
-
if (status === 401) {
|
|
4467
|
-
throw new SessionError(`Invalid signature: ${errorMessage}`, "INVALID_SIGNATURE", status);
|
|
4624
|
+
/**
|
|
4625
|
+
* Get the address of the connected wallet
|
|
4626
|
+
*/
|
|
4627
|
+
get address() {
|
|
4628
|
+
const account = this.walletClient.account;
|
|
4629
|
+
if (!account) {
|
|
4630
|
+
throw new Error("WalletClient must have an account attached");
|
|
4468
4631
|
}
|
|
4469
|
-
|
|
4470
|
-
}
|
|
4471
|
-
const data = await response.json();
|
|
4472
|
-
return {
|
|
4473
|
-
success: data.success,
|
|
4474
|
-
address: data.address
|
|
4475
|
-
};
|
|
4476
|
-
}
|
|
4477
|
-
async function getComputeApiSession(config) {
|
|
4478
|
-
let response;
|
|
4479
|
-
try {
|
|
4480
|
-
response = await fetch(`${config.baseUrl}/auth/session`, {
|
|
4481
|
-
method: "GET",
|
|
4482
|
-
credentials: "include",
|
|
4483
|
-
// Include cookies for session management
|
|
4484
|
-
headers: {
|
|
4485
|
-
"Content-Type": "application/json"
|
|
4486
|
-
}
|
|
4487
|
-
});
|
|
4488
|
-
} catch {
|
|
4489
|
-
return {
|
|
4490
|
-
authenticated: false
|
|
4491
|
-
};
|
|
4492
|
-
}
|
|
4493
|
-
if (response.status === 401) {
|
|
4494
|
-
return {
|
|
4495
|
-
authenticated: false
|
|
4496
|
-
};
|
|
4497
|
-
}
|
|
4498
|
-
if (!response.ok) {
|
|
4499
|
-
const errorMessage = await parseErrorResponse(response);
|
|
4500
|
-
throw new SessionError(`Failed to get session: ${errorMessage}`, "UNKNOWN", response.status);
|
|
4501
|
-
}
|
|
4502
|
-
const data = await response.json();
|
|
4503
|
-
return {
|
|
4504
|
-
authenticated: data.authenticated,
|
|
4505
|
-
address: data.address,
|
|
4506
|
-
chainId: data.chain_id
|
|
4507
|
-
};
|
|
4508
|
-
}
|
|
4509
|
-
async function logoutFromComputeApi(config) {
|
|
4510
|
-
let response;
|
|
4511
|
-
try {
|
|
4512
|
-
response = await fetch(`${config.baseUrl}/auth/logout`, {
|
|
4513
|
-
method: "POST",
|
|
4514
|
-
credentials: "include",
|
|
4515
|
-
// Include cookies for session management
|
|
4516
|
-
headers: {
|
|
4517
|
-
"Content-Type": "application/json"
|
|
4518
|
-
}
|
|
4519
|
-
});
|
|
4520
|
-
} catch (error) {
|
|
4521
|
-
throw new SessionError(
|
|
4522
|
-
`Network error connecting to ${config.baseUrl}: ${error instanceof Error ? error.message : String(error)}`,
|
|
4523
|
-
"NETWORK_ERROR"
|
|
4524
|
-
);
|
|
4525
|
-
}
|
|
4526
|
-
if (response.status === 401) {
|
|
4527
|
-
return;
|
|
4528
|
-
}
|
|
4529
|
-
if (!response.ok) {
|
|
4530
|
-
const errorMessage = await parseErrorResponse(response);
|
|
4531
|
-
throw new SessionError(`Logout failed: ${errorMessage}`, "UNKNOWN", response.status);
|
|
4532
|
-
}
|
|
4533
|
-
}
|
|
4534
|
-
async function isSessionValid(config) {
|
|
4535
|
-
const session = await getComputeApiSession(config);
|
|
4536
|
-
return session.authenticated;
|
|
4537
|
-
}
|
|
4538
|
-
|
|
4539
|
-
// src/client/common/utils/userapi.ts
|
|
4540
|
-
function isJsonObject(value) {
|
|
4541
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4542
|
-
}
|
|
4543
|
-
function readString(obj, key) {
|
|
4544
|
-
const v = obj[key];
|
|
4545
|
-
return typeof v === "string" ? v : void 0;
|
|
4546
|
-
}
|
|
4547
|
-
function readNumber(obj, key) {
|
|
4548
|
-
const v = obj[key];
|
|
4549
|
-
return typeof v === "number" && Number.isFinite(v) ? v : void 0;
|
|
4550
|
-
}
|
|
4551
|
-
var MAX_ADDRESS_COUNT = 5;
|
|
4552
|
-
var CanViewAppLogsPermission = "0x2fd3f2fe";
|
|
4553
|
-
var CanViewSensitiveAppInfoPermission = "0x0e67b22f";
|
|
4554
|
-
var CanUpdateAppProfilePermission = "0x036fef61";
|
|
4555
|
-
function getDefaultClientId() {
|
|
4556
|
-
const version = true ? "0.3.1-dev" : "0.0.0";
|
|
4557
|
-
return `ecloud-sdk/v${version}`;
|
|
4558
|
-
}
|
|
4559
|
-
var UserApiClient = class {
|
|
4560
|
-
constructor(config, walletClient, publicClient, options) {
|
|
4561
|
-
this.config = config;
|
|
4562
|
-
this.walletClient = walletClient;
|
|
4563
|
-
this.publicClient = publicClient;
|
|
4564
|
-
this.clientId = options?.clientId || getDefaultClientId();
|
|
4565
|
-
this.useSession = options?.useSession ?? false;
|
|
4566
|
-
}
|
|
4567
|
-
/**
|
|
4568
|
-
* Get the address of the connected wallet
|
|
4569
|
-
*/
|
|
4570
|
-
get address() {
|
|
4571
|
-
const account = this.walletClient.account;
|
|
4572
|
-
if (!account) {
|
|
4573
|
-
throw new Error("WalletClient must have an account attached");
|
|
4574
|
-
}
|
|
4575
|
-
return account.address;
|
|
4632
|
+
return account.address;
|
|
4576
4633
|
}
|
|
4577
4634
|
async getInfos(appIDs, addressCount = 1) {
|
|
4578
4635
|
const count = Math.min(addressCount, MAX_ADDRESS_COUNT);
|
|
@@ -5461,21 +5518,214 @@ function isSubscriptionActive(status) {
|
|
|
5461
5518
|
|
|
5462
5519
|
// src/client/common/utils/billingapi.ts
|
|
5463
5520
|
import axios2 from "axios";
|
|
5521
|
+
|
|
5522
|
+
// src/client/common/auth/billingSession.ts
|
|
5523
|
+
var BillingSessionError = class extends Error {
|
|
5524
|
+
constructor(message, code, statusCode) {
|
|
5525
|
+
super(message);
|
|
5526
|
+
this.code = code;
|
|
5527
|
+
this.statusCode = statusCode;
|
|
5528
|
+
this.name = "BillingSessionError";
|
|
5529
|
+
}
|
|
5530
|
+
};
|
|
5531
|
+
function stripHexPrefix3(hex) {
|
|
5532
|
+
return hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
5533
|
+
}
|
|
5534
|
+
async function parseErrorResponse2(response) {
|
|
5535
|
+
try {
|
|
5536
|
+
const data = await response.json();
|
|
5537
|
+
return data.error || response.statusText;
|
|
5538
|
+
} catch {
|
|
5539
|
+
return response.statusText;
|
|
5540
|
+
}
|
|
5541
|
+
}
|
|
5542
|
+
async function loginToBillingApi(config, request) {
|
|
5543
|
+
let response;
|
|
5544
|
+
try {
|
|
5545
|
+
response = await fetch(`${config.baseUrl}/auth/siwe/login`, {
|
|
5546
|
+
method: "POST",
|
|
5547
|
+
credentials: "include",
|
|
5548
|
+
// Include cookies for session management
|
|
5549
|
+
headers: {
|
|
5550
|
+
"Content-Type": "application/json"
|
|
5551
|
+
},
|
|
5552
|
+
body: JSON.stringify({
|
|
5553
|
+
message: request.message,
|
|
5554
|
+
signature: stripHexPrefix3(request.signature)
|
|
5555
|
+
})
|
|
5556
|
+
});
|
|
5557
|
+
} catch (error) {
|
|
5558
|
+
throw new BillingSessionError(
|
|
5559
|
+
`Network error connecting to ${config.baseUrl}: ${error instanceof Error ? error.message : String(error)}`,
|
|
5560
|
+
"NETWORK_ERROR"
|
|
5561
|
+
);
|
|
5562
|
+
}
|
|
5563
|
+
if (!response.ok) {
|
|
5564
|
+
const errorMessage = await parseErrorResponse2(response);
|
|
5565
|
+
const status = response.status;
|
|
5566
|
+
if (status === 400) {
|
|
5567
|
+
if (errorMessage.toLowerCase().includes("siwe")) {
|
|
5568
|
+
throw new BillingSessionError(`Invalid SIWE message: ${errorMessage}`, "INVALID_MESSAGE", status);
|
|
5569
|
+
}
|
|
5570
|
+
throw new BillingSessionError(`Bad request: ${errorMessage}`, "INVALID_MESSAGE", status);
|
|
5571
|
+
}
|
|
5572
|
+
if (status === 401) {
|
|
5573
|
+
throw new BillingSessionError(`Invalid signature: ${errorMessage}`, "INVALID_SIGNATURE", status);
|
|
5574
|
+
}
|
|
5575
|
+
throw new BillingSessionError(`Login failed: ${errorMessage}`, "UNKNOWN", status);
|
|
5576
|
+
}
|
|
5577
|
+
const data = await response.json();
|
|
5578
|
+
return {
|
|
5579
|
+
success: data.success,
|
|
5580
|
+
address: data.address
|
|
5581
|
+
};
|
|
5582
|
+
}
|
|
5583
|
+
async function getBillingApiSession(config) {
|
|
5584
|
+
let response;
|
|
5585
|
+
try {
|
|
5586
|
+
response = await fetch(`${config.baseUrl}/auth/session`, {
|
|
5587
|
+
method: "GET",
|
|
5588
|
+
credentials: "include",
|
|
5589
|
+
// Include cookies for session management
|
|
5590
|
+
headers: {
|
|
5591
|
+
"Content-Type": "application/json"
|
|
5592
|
+
}
|
|
5593
|
+
});
|
|
5594
|
+
} catch {
|
|
5595
|
+
return {
|
|
5596
|
+
authenticated: false
|
|
5597
|
+
};
|
|
5598
|
+
}
|
|
5599
|
+
if (response.status === 401) {
|
|
5600
|
+
return {
|
|
5601
|
+
authenticated: false
|
|
5602
|
+
};
|
|
5603
|
+
}
|
|
5604
|
+
if (!response.ok) {
|
|
5605
|
+
const errorMessage = await parseErrorResponse2(response);
|
|
5606
|
+
throw new BillingSessionError(`Failed to get session: ${errorMessage}`, "UNKNOWN", response.status);
|
|
5607
|
+
}
|
|
5608
|
+
const data = await response.json();
|
|
5609
|
+
return {
|
|
5610
|
+
authenticated: data.authenticated,
|
|
5611
|
+
address: data.address,
|
|
5612
|
+
chainId: data.chainId,
|
|
5613
|
+
authenticatedAt: data.authenticatedAt
|
|
5614
|
+
};
|
|
5615
|
+
}
|
|
5616
|
+
async function logoutFromBillingApi(config) {
|
|
5617
|
+
let response;
|
|
5618
|
+
try {
|
|
5619
|
+
response = await fetch(`${config.baseUrl}/auth/logout`, {
|
|
5620
|
+
method: "POST",
|
|
5621
|
+
credentials: "include",
|
|
5622
|
+
// Include cookies for session management
|
|
5623
|
+
headers: {
|
|
5624
|
+
"Content-Type": "application/json"
|
|
5625
|
+
}
|
|
5626
|
+
});
|
|
5627
|
+
} catch (error) {
|
|
5628
|
+
throw new BillingSessionError(
|
|
5629
|
+
`Network error connecting to ${config.baseUrl}: ${error instanceof Error ? error.message : String(error)}`,
|
|
5630
|
+
"NETWORK_ERROR"
|
|
5631
|
+
);
|
|
5632
|
+
}
|
|
5633
|
+
if (response.status === 401) {
|
|
5634
|
+
return;
|
|
5635
|
+
}
|
|
5636
|
+
if (!response.ok) {
|
|
5637
|
+
const errorMessage = await parseErrorResponse2(response);
|
|
5638
|
+
throw new BillingSessionError(`Logout failed: ${errorMessage}`, "UNKNOWN", response.status);
|
|
5639
|
+
}
|
|
5640
|
+
}
|
|
5641
|
+
|
|
5642
|
+
// src/client/common/utils/billingapi.ts
|
|
5464
5643
|
var BillingApiClient = class {
|
|
5465
|
-
constructor(config, walletClient) {
|
|
5644
|
+
constructor(config, walletClient, options = {}) {
|
|
5466
5645
|
this.config = config;
|
|
5467
5646
|
this.walletClient = walletClient;
|
|
5647
|
+
this.options = options;
|
|
5648
|
+
this.useSession = options.useSession ?? false;
|
|
5649
|
+
if (!this.useSession && !walletClient) {
|
|
5650
|
+
throw new Error("WalletClient is required when not using session authentication");
|
|
5651
|
+
}
|
|
5468
5652
|
}
|
|
5469
5653
|
/**
|
|
5470
5654
|
* Get the address of the connected wallet
|
|
5655
|
+
* Returns undefined if using session auth without a wallet client
|
|
5471
5656
|
*/
|
|
5472
5657
|
get address() {
|
|
5473
|
-
const account = this.walletClient
|
|
5658
|
+
const account = this.walletClient?.account;
|
|
5474
5659
|
if (!account) {
|
|
5475
|
-
|
|
5660
|
+
if (!this.useSession) {
|
|
5661
|
+
throw new Error("WalletClient must have an account attached");
|
|
5662
|
+
}
|
|
5663
|
+
return void 0;
|
|
5476
5664
|
}
|
|
5477
5665
|
return account.address;
|
|
5478
5666
|
}
|
|
5667
|
+
/**
|
|
5668
|
+
* Get the base URL of the billing API
|
|
5669
|
+
*/
|
|
5670
|
+
get baseUrl() {
|
|
5671
|
+
return this.config.billingApiServerURL;
|
|
5672
|
+
}
|
|
5673
|
+
// ==========================================================================
|
|
5674
|
+
// SIWE Session Methods
|
|
5675
|
+
// ==========================================================================
|
|
5676
|
+
/**
|
|
5677
|
+
* Login to the billing API using SIWE
|
|
5678
|
+
*
|
|
5679
|
+
* This establishes a session with the billing API by verifying the SIWE message
|
|
5680
|
+
* and signature. On success, a session cookie is set in the browser.
|
|
5681
|
+
*
|
|
5682
|
+
* @param request - Login request containing SIWE message and signature
|
|
5683
|
+
* @returns Login result with the authenticated address
|
|
5684
|
+
*
|
|
5685
|
+
* @example
|
|
5686
|
+
* ```typescript
|
|
5687
|
+
* const { message } = createSiweMessage({
|
|
5688
|
+
* address: userAddress,
|
|
5689
|
+
* chainId: 11155111,
|
|
5690
|
+
* domain: window.location.host,
|
|
5691
|
+
* uri: window.location.origin,
|
|
5692
|
+
* });
|
|
5693
|
+
*
|
|
5694
|
+
* const signature = await signMessageAsync({ message });
|
|
5695
|
+
* const result = await billingClient.siweLogin({ message, signature });
|
|
5696
|
+
* ```
|
|
5697
|
+
*/
|
|
5698
|
+
async siweLogin(request) {
|
|
5699
|
+
return loginToBillingApi({ baseUrl: this.baseUrl }, request);
|
|
5700
|
+
}
|
|
5701
|
+
/**
|
|
5702
|
+
* Logout from the billing API
|
|
5703
|
+
*
|
|
5704
|
+
* This destroys the current session and clears the session cookie.
|
|
5705
|
+
*/
|
|
5706
|
+
async siweLogout() {
|
|
5707
|
+
return logoutFromBillingApi({ baseUrl: this.baseUrl });
|
|
5708
|
+
}
|
|
5709
|
+
/**
|
|
5710
|
+
* Get the current session status from the billing API
|
|
5711
|
+
*
|
|
5712
|
+
* @returns Session information including authentication status and address
|
|
5713
|
+
*/
|
|
5714
|
+
async getSession() {
|
|
5715
|
+
return getBillingApiSession({ baseUrl: this.baseUrl });
|
|
5716
|
+
}
|
|
5717
|
+
/**
|
|
5718
|
+
* Check if there is a valid session
|
|
5719
|
+
*
|
|
5720
|
+
* @returns True if session is authenticated, false otherwise
|
|
5721
|
+
*/
|
|
5722
|
+
async isSessionValid() {
|
|
5723
|
+
const session = await this.getSession();
|
|
5724
|
+
return session.authenticated;
|
|
5725
|
+
}
|
|
5726
|
+
// ==========================================================================
|
|
5727
|
+
// Subscription Methods
|
|
5728
|
+
// ==========================================================================
|
|
5479
5729
|
async createSubscription(productId = "compute", options) {
|
|
5480
5730
|
const endpoint = `${this.config.billingApiServerURL}/products/${productId}/subscription`;
|
|
5481
5731
|
const body = options ? {
|
|
@@ -5494,10 +5744,72 @@ var BillingApiClient = class {
|
|
|
5494
5744
|
const endpoint = `${this.config.billingApiServerURL}/products/${productId}/subscription`;
|
|
5495
5745
|
await this.makeAuthenticatedRequest(endpoint, "DELETE", productId);
|
|
5496
5746
|
}
|
|
5747
|
+
// ==========================================================================
|
|
5748
|
+
// Internal Methods
|
|
5749
|
+
// ==========================================================================
|
|
5497
5750
|
/**
|
|
5498
5751
|
* Make an authenticated request to the billing API
|
|
5752
|
+
*
|
|
5753
|
+
* Uses session auth if useSession is true, otherwise uses EIP-712 signature auth.
|
|
5499
5754
|
*/
|
|
5500
5755
|
async makeAuthenticatedRequest(url, method, productId, body) {
|
|
5756
|
+
if (this.useSession) {
|
|
5757
|
+
return this.makeSessionAuthenticatedRequest(url, method, body);
|
|
5758
|
+
}
|
|
5759
|
+
return this.makeSignatureAuthenticatedRequest(url, method, productId, body);
|
|
5760
|
+
}
|
|
5761
|
+
/**
|
|
5762
|
+
* Make a request using session-based authentication (cookies)
|
|
5763
|
+
*/
|
|
5764
|
+
async makeSessionAuthenticatedRequest(url, method, body) {
|
|
5765
|
+
const headers = {};
|
|
5766
|
+
if (body) {
|
|
5767
|
+
headers["Content-Type"] = "application/json";
|
|
5768
|
+
}
|
|
5769
|
+
try {
|
|
5770
|
+
const response = await fetch(url, {
|
|
5771
|
+
method,
|
|
5772
|
+
credentials: "include",
|
|
5773
|
+
// Include cookies for session management
|
|
5774
|
+
headers,
|
|
5775
|
+
body: body ? JSON.stringify(body) : void 0
|
|
5776
|
+
});
|
|
5777
|
+
const status = response.status;
|
|
5778
|
+
const statusText = status >= 200 && status < 300 ? "OK" : "Error";
|
|
5779
|
+
if (status < 200 || status >= 300) {
|
|
5780
|
+
let errorBody;
|
|
5781
|
+
try {
|
|
5782
|
+
errorBody = await response.text();
|
|
5783
|
+
} catch {
|
|
5784
|
+
errorBody = statusText;
|
|
5785
|
+
}
|
|
5786
|
+
throw new Error(`BillingAPI request failed: ${status} ${statusText} - ${errorBody}`);
|
|
5787
|
+
}
|
|
5788
|
+
const responseData = await response.json();
|
|
5789
|
+
return {
|
|
5790
|
+
json: async () => responseData,
|
|
5791
|
+
text: async () => JSON.stringify(responseData)
|
|
5792
|
+
};
|
|
5793
|
+
} catch (error) {
|
|
5794
|
+
if (error.name === "TypeError" || error.message?.includes("fetch")) {
|
|
5795
|
+
throw new Error(
|
|
5796
|
+
`Failed to connect to BillingAPI at ${url}: ${error.message}
|
|
5797
|
+
Please check:
|
|
5798
|
+
1. Your internet connection
|
|
5799
|
+
2. The API server is accessible: ${this.config.billingApiServerURL}
|
|
5800
|
+
3. Firewall/proxy settings`
|
|
5801
|
+
);
|
|
5802
|
+
}
|
|
5803
|
+
throw error;
|
|
5804
|
+
}
|
|
5805
|
+
}
|
|
5806
|
+
/**
|
|
5807
|
+
* Make a request using EIP-712 signature authentication
|
|
5808
|
+
*/
|
|
5809
|
+
async makeSignatureAuthenticatedRequest(url, method, productId, body) {
|
|
5810
|
+
if (!this.walletClient) {
|
|
5811
|
+
throw new Error("WalletClient is required for signature authentication");
|
|
5812
|
+
}
|
|
5501
5813
|
const expiry = BigInt(Math.floor(Date.now() / 1e3) + 5 * 60);
|
|
5502
5814
|
const { signature } = await calculateBillingAuthSignature({
|
|
5503
5815
|
walletClient: this.walletClient,
|
|
@@ -5817,16 +6129,24 @@ async function prepareDeployFromVerifiableBuild(options, logger = defaultLogger)
|
|
|
5817
6129
|
},
|
|
5818
6130
|
logger
|
|
5819
6131
|
);
|
|
6132
|
+
logger.debug("Checking delegation status...");
|
|
6133
|
+
const authorizationList = await createAuthorizationList({
|
|
6134
|
+
walletClient: batch.walletClient,
|
|
6135
|
+
publicClient: batch.publicClient,
|
|
6136
|
+
environmentConfig: batch.environmentConfig
|
|
6137
|
+
});
|
|
5820
6138
|
logger.debug("Estimating gas...");
|
|
5821
6139
|
const gasEstimate = await estimateBatchGas({
|
|
5822
6140
|
publicClient: batch.publicClient,
|
|
5823
6141
|
account: batch.walletClient.account.address,
|
|
5824
|
-
executions: batch.executions
|
|
6142
|
+
executions: batch.executions,
|
|
6143
|
+
authorizationList
|
|
5825
6144
|
});
|
|
5826
6145
|
const data = {
|
|
5827
6146
|
appId: batch.appId,
|
|
5828
6147
|
salt: batch.salt,
|
|
5829
|
-
executions: batch.executions
|
|
6148
|
+
executions: batch.executions,
|
|
6149
|
+
authorizationList
|
|
5830
6150
|
};
|
|
5831
6151
|
return {
|
|
5832
6152
|
prepared: {
|
|
@@ -6055,16 +6375,24 @@ async function prepareDeploy(options, logger = defaultLogger) {
|
|
|
6055
6375
|
},
|
|
6056
6376
|
logger
|
|
6057
6377
|
);
|
|
6378
|
+
logger.debug("Checking delegation status...");
|
|
6379
|
+
const authorizationList = await createAuthorizationList({
|
|
6380
|
+
walletClient: batch.walletClient,
|
|
6381
|
+
publicClient: batch.publicClient,
|
|
6382
|
+
environmentConfig: batch.environmentConfig
|
|
6383
|
+
});
|
|
6058
6384
|
logger.debug("Estimating gas...");
|
|
6059
6385
|
const gasEstimate = await estimateBatchGas({
|
|
6060
6386
|
publicClient: batch.publicClient,
|
|
6061
6387
|
account: batch.walletClient.account.address,
|
|
6062
|
-
executions: batch.executions
|
|
6388
|
+
executions: batch.executions,
|
|
6389
|
+
authorizationList
|
|
6063
6390
|
});
|
|
6064
6391
|
const data = {
|
|
6065
6392
|
appId: batch.appId,
|
|
6066
6393
|
salt: batch.salt,
|
|
6067
|
-
executions: batch.executions
|
|
6394
|
+
executions: batch.executions,
|
|
6395
|
+
authorizationList
|
|
6068
6396
|
};
|
|
6069
6397
|
return {
|
|
6070
6398
|
prepared: {
|
|
@@ -6195,15 +6523,23 @@ async function prepareUpgradeFromVerifiableBuild(options, logger = defaultLogger
|
|
|
6195
6523
|
needsPermissionChange,
|
|
6196
6524
|
imageRef: options.imageRef
|
|
6197
6525
|
});
|
|
6526
|
+
logger.debug("Checking delegation status...");
|
|
6527
|
+
const authorizationList = await createAuthorizationList({
|
|
6528
|
+
walletClient: batch.walletClient,
|
|
6529
|
+
publicClient: batch.publicClient,
|
|
6530
|
+
environmentConfig: batch.environmentConfig
|
|
6531
|
+
});
|
|
6198
6532
|
logger.debug("Estimating gas...");
|
|
6199
6533
|
const gasEstimate = await estimateBatchGas({
|
|
6200
6534
|
publicClient: batch.publicClient,
|
|
6201
6535
|
account: batch.walletClient.account.address,
|
|
6202
|
-
executions: batch.executions
|
|
6536
|
+
executions: batch.executions,
|
|
6537
|
+
authorizationList
|
|
6203
6538
|
});
|
|
6204
6539
|
const data = {
|
|
6205
6540
|
appId: batch.appId,
|
|
6206
|
-
executions: batch.executions
|
|
6541
|
+
executions: batch.executions,
|
|
6542
|
+
authorizationList
|
|
6207
6543
|
};
|
|
6208
6544
|
return {
|
|
6209
6545
|
prepared: {
|
|
@@ -6376,15 +6712,23 @@ async function prepareUpgrade(options, logger = defaultLogger) {
|
|
|
6376
6712
|
needsPermissionChange,
|
|
6377
6713
|
imageRef: finalImageRef
|
|
6378
6714
|
});
|
|
6715
|
+
logger.debug("Checking delegation status...");
|
|
6716
|
+
const authorizationList = await createAuthorizationList({
|
|
6717
|
+
walletClient: batch.walletClient,
|
|
6718
|
+
publicClient: batch.publicClient,
|
|
6719
|
+
environmentConfig: batch.environmentConfig
|
|
6720
|
+
});
|
|
6379
6721
|
logger.debug("Estimating gas...");
|
|
6380
6722
|
const gasEstimate = await estimateBatchGas({
|
|
6381
6723
|
publicClient: batch.publicClient,
|
|
6382
6724
|
account: batch.walletClient.account.address,
|
|
6383
|
-
executions: batch.executions
|
|
6725
|
+
executions: batch.executions,
|
|
6726
|
+
authorizationList
|
|
6384
6727
|
});
|
|
6385
6728
|
const data = {
|
|
6386
6729
|
appId: batch.appId,
|
|
6387
|
-
executions: batch.executions
|
|
6730
|
+
executions: batch.executions,
|
|
6731
|
+
authorizationList
|
|
6388
6732
|
};
|
|
6389
6733
|
return {
|
|
6390
6734
|
prepared: {
|
|
@@ -7512,7 +7856,10 @@ function createBillingModule(config) {
|
|
|
7512
7856
|
};
|
|
7513
7857
|
}
|
|
7514
7858
|
logger.debug(`Creating subscription for ${productId}...`);
|
|
7515
|
-
const result = await billingApi.createSubscription(productId
|
|
7859
|
+
const result = await billingApi.createSubscription(productId, {
|
|
7860
|
+
successUrl: opts?.successUrl,
|
|
7861
|
+
cancelUrl: opts?.cancelUrl
|
|
7862
|
+
});
|
|
7516
7863
|
logger.debug(`Checkout URL: ${result.checkoutUrl}`);
|
|
7517
7864
|
return {
|
|
7518
7865
|
type: "checkout_created",
|
|
@@ -7604,9 +7951,22 @@ async function requestWithRetry(config) {
|
|
|
7604
7951
|
}
|
|
7605
7952
|
var BuildApiClient = class {
|
|
7606
7953
|
constructor(options) {
|
|
7607
|
-
|
|
7954
|
+
let url = options.baseUrl;
|
|
7955
|
+
while (url.endsWith("/")) {
|
|
7956
|
+
url = url.slice(0, -1);
|
|
7957
|
+
}
|
|
7958
|
+
this.baseUrl = url;
|
|
7608
7959
|
this.clientId = options.clientId;
|
|
7609
7960
|
this.walletClient = options.walletClient;
|
|
7961
|
+
this.useSession = options.useSession ?? false;
|
|
7962
|
+
this.billingSessionId = options.billingSessionId;
|
|
7963
|
+
}
|
|
7964
|
+
/**
|
|
7965
|
+
* Update the billing session ID.
|
|
7966
|
+
* Call this after logging into the billing API to enable session-based auth for builds.
|
|
7967
|
+
*/
|
|
7968
|
+
setBillingSessionId(sessionId) {
|
|
7969
|
+
this.billingSessionId = sessionId;
|
|
7610
7970
|
}
|
|
7611
7971
|
/**
|
|
7612
7972
|
* Get the address of the connected wallet
|
|
@@ -7618,8 +7978,17 @@ var BuildApiClient = class {
|
|
|
7618
7978
|
}
|
|
7619
7979
|
return account.address;
|
|
7620
7980
|
}
|
|
7981
|
+
/**
|
|
7982
|
+
* Submit a new build request.
|
|
7983
|
+
* Supports two auth modes (session auth is tried first when billingSessionId is available):
|
|
7984
|
+
* 1. Session-based auth: X-Billing-Session header (forwarded billing_session cookie)
|
|
7985
|
+
* 2. Signature-based auth: Authorization + X-Account + X-eigenx-expiry headers (requires walletClient)
|
|
7986
|
+
*/
|
|
7621
7987
|
async submitBuild(payload) {
|
|
7622
|
-
|
|
7988
|
+
if (this.useSession && this.billingSessionId) {
|
|
7989
|
+
return this.billingSessionAuthJsonRequest("/builds", "POST", payload);
|
|
7990
|
+
}
|
|
7991
|
+
return this.signatureAuthJsonRequest("/builds", "POST", payload);
|
|
7623
7992
|
}
|
|
7624
7993
|
async getBuild(buildId) {
|
|
7625
7994
|
return this.publicJsonRequest(`/builds/${encodeURIComponent(buildId)}`);
|
|
@@ -7630,8 +7999,11 @@ var BuildApiClient = class {
|
|
|
7630
7999
|
async verify(identifier) {
|
|
7631
8000
|
return this.publicJsonRequest(`/builds/verify/${encodeURIComponent(identifier)}`);
|
|
7632
8001
|
}
|
|
8002
|
+
/**
|
|
8003
|
+
* Get build logs. Supports session auth (identity verification only, no billing check).
|
|
8004
|
+
*/
|
|
7633
8005
|
async getLogs(buildId) {
|
|
7634
|
-
return this.
|
|
8006
|
+
return this.sessionOrSignatureTextRequest(`/builds/${encodeURIComponent(buildId)}/logs`);
|
|
7635
8007
|
}
|
|
7636
8008
|
async listBuilds(params) {
|
|
7637
8009
|
const res = await requestWithRetry({
|
|
@@ -7639,7 +8011,9 @@ var BuildApiClient = class {
|
|
|
7639
8011
|
method: "GET",
|
|
7640
8012
|
params,
|
|
7641
8013
|
headers: this.clientId ? { "x-client-id": this.clientId } : void 0,
|
|
7642
|
-
timeout: 6e4
|
|
8014
|
+
timeout: 6e4,
|
|
8015
|
+
validateStatus: () => true,
|
|
8016
|
+
withCredentials: this.useSession
|
|
7643
8017
|
});
|
|
7644
8018
|
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
7645
8019
|
return res.data;
|
|
@@ -7649,12 +8023,18 @@ var BuildApiClient = class {
|
|
|
7649
8023
|
url: `${this.baseUrl}${path8}`,
|
|
7650
8024
|
method: "GET",
|
|
7651
8025
|
headers: this.clientId ? { "x-client-id": this.clientId } : void 0,
|
|
7652
|
-
timeout: 6e4
|
|
8026
|
+
timeout: 6e4,
|
|
8027
|
+
validateStatus: () => true,
|
|
8028
|
+
withCredentials: this.useSession
|
|
7653
8029
|
});
|
|
7654
8030
|
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
7655
8031
|
return res.data;
|
|
7656
8032
|
}
|
|
7657
|
-
|
|
8033
|
+
/**
|
|
8034
|
+
* Make a request that ALWAYS requires signature auth (for billing verification).
|
|
8035
|
+
* Used for endpoints like POST /builds that need to verify subscription status.
|
|
8036
|
+
*/
|
|
8037
|
+
async signatureAuthJsonRequest(path8, method, body) {
|
|
7658
8038
|
if (!this.walletClient?.account) {
|
|
7659
8039
|
throw new Error("WalletClient with account required for authenticated requests");
|
|
7660
8040
|
}
|
|
@@ -7676,32 +8056,69 @@ var BuildApiClient = class {
|
|
|
7676
8056
|
method,
|
|
7677
8057
|
headers,
|
|
7678
8058
|
data: body,
|
|
7679
|
-
timeout: 6e4
|
|
8059
|
+
timeout: 6e4,
|
|
8060
|
+
validateStatus: () => true,
|
|
8061
|
+
withCredentials: this.useSession
|
|
7680
8062
|
});
|
|
7681
8063
|
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
7682
8064
|
return res.data;
|
|
7683
8065
|
}
|
|
7684
|
-
|
|
7685
|
-
|
|
7686
|
-
|
|
8066
|
+
/**
|
|
8067
|
+
* Make a request using billing session auth (for billing verification without wallet signature).
|
|
8068
|
+
* Forwards the billing_session cookie value via X-Billing-Session header.
|
|
8069
|
+
* Used for endpoints that need to verify subscription status when using session-based auth.
|
|
8070
|
+
*/
|
|
8071
|
+
async billingSessionAuthJsonRequest(path8, method, body) {
|
|
8072
|
+
if (!this.billingSessionId) {
|
|
8073
|
+
throw new Error("billingSessionId required for session-based billing auth");
|
|
7687
8074
|
}
|
|
7688
|
-
const headers = {
|
|
8075
|
+
const headers = {
|
|
8076
|
+
"Content-Type": "application/json",
|
|
8077
|
+
"X-Billing-Session": this.billingSessionId
|
|
8078
|
+
};
|
|
7689
8079
|
if (this.clientId) headers["x-client-id"] = this.clientId;
|
|
7690
|
-
const
|
|
7691
|
-
|
|
7692
|
-
|
|
7693
|
-
|
|
7694
|
-
|
|
8080
|
+
const res = await requestWithRetry({
|
|
8081
|
+
url: `${this.baseUrl}${path8}`,
|
|
8082
|
+
method,
|
|
8083
|
+
headers,
|
|
8084
|
+
data: body,
|
|
8085
|
+
timeout: 6e4,
|
|
8086
|
+
validateStatus: () => true,
|
|
8087
|
+
withCredentials: this.useSession
|
|
7695
8088
|
});
|
|
7696
|
-
|
|
7697
|
-
|
|
7698
|
-
|
|
8089
|
+
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
8090
|
+
return res.data;
|
|
8091
|
+
}
|
|
8092
|
+
/**
|
|
8093
|
+
* Make an authenticated request that can use session OR signature auth.
|
|
8094
|
+
* When useSession is true, relies on cookies for identity verification.
|
|
8095
|
+
* Used for endpoints that only need identity verification (not billing).
|
|
8096
|
+
*/
|
|
8097
|
+
async sessionOrSignatureTextRequest(path8) {
|
|
8098
|
+
const headers = {};
|
|
8099
|
+
if (this.clientId) headers["x-client-id"] = this.clientId;
|
|
8100
|
+
if (!this.useSession) {
|
|
8101
|
+
if (!this.walletClient?.account) {
|
|
8102
|
+
throw new Error("WalletClient with account required for authenticated requests");
|
|
8103
|
+
}
|
|
8104
|
+
const expiry = BigInt(Math.floor(Date.now() / 1e3) + 60);
|
|
8105
|
+
const { signature } = await calculateBillingAuthSignature({
|
|
8106
|
+
walletClient: this.walletClient,
|
|
8107
|
+
product: "compute",
|
|
8108
|
+
expiry
|
|
8109
|
+
});
|
|
8110
|
+
headers.Authorization = `Bearer ${signature}`;
|
|
8111
|
+
headers["X-eigenx-expiry"] = expiry.toString();
|
|
8112
|
+
headers["X-Account"] = this.address;
|
|
8113
|
+
}
|
|
7699
8114
|
const res = await requestWithRetry({
|
|
7700
8115
|
url: `${this.baseUrl}${path8}`,
|
|
7701
8116
|
method: "GET",
|
|
7702
8117
|
headers,
|
|
7703
8118
|
timeout: 6e4,
|
|
7704
|
-
responseType: "text"
|
|
8119
|
+
responseType: "text",
|
|
8120
|
+
validateStatus: () => true,
|
|
8121
|
+
withCredentials: this.useSession
|
|
7705
8122
|
});
|
|
7706
8123
|
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
7707
8124
|
return typeof res.data === "string" ? res.data : JSON.stringify(res.data);
|
|
@@ -8268,6 +8685,9 @@ function isSiweMessageNotYetValid(params) {
|
|
|
8268
8685
|
return /* @__PURE__ */ new Date() < params.notBefore;
|
|
8269
8686
|
}
|
|
8270
8687
|
|
|
8688
|
+
// src/client/common/auth/index.ts
|
|
8689
|
+
init_session();
|
|
8690
|
+
|
|
8271
8691
|
// src/client/common/utils/instance.ts
|
|
8272
8692
|
async function getCurrentInstanceType(preflightCtx, appID, logger, clientId) {
|
|
8273
8693
|
try {
|