@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.cjs
CHANGED
|
@@ -5,6 +5,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
5
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
6
|
var __getProtoOf = Object.getPrototypeOf;
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __esm = (fn, res) => function __init() {
|
|
9
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
10
|
+
};
|
|
8
11
|
var __export = (target, all) => {
|
|
9
12
|
for (var name in all)
|
|
10
13
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -27,6 +30,135 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
27
30
|
));
|
|
28
31
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
32
|
|
|
33
|
+
// src/client/common/auth/session.ts
|
|
34
|
+
function stripHexPrefix2(hex) {
|
|
35
|
+
return hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
36
|
+
}
|
|
37
|
+
async function parseErrorResponse(response) {
|
|
38
|
+
try {
|
|
39
|
+
const data = await response.json();
|
|
40
|
+
return data.error || response.statusText;
|
|
41
|
+
} catch {
|
|
42
|
+
return response.statusText;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
async function loginToComputeApi(config, request) {
|
|
46
|
+
let response;
|
|
47
|
+
try {
|
|
48
|
+
response = await fetch(`${config.baseUrl}/auth/siwe/login`, {
|
|
49
|
+
method: "POST",
|
|
50
|
+
credentials: "include",
|
|
51
|
+
// Include cookies for session management
|
|
52
|
+
headers: {
|
|
53
|
+
"Content-Type": "application/json"
|
|
54
|
+
},
|
|
55
|
+
body: JSON.stringify({
|
|
56
|
+
message: request.message,
|
|
57
|
+
signature: stripHexPrefix2(request.signature)
|
|
58
|
+
})
|
|
59
|
+
});
|
|
60
|
+
} catch (error) {
|
|
61
|
+
throw new SessionError(
|
|
62
|
+
`Network error connecting to ${config.baseUrl}: ${error instanceof Error ? error.message : String(error)}`,
|
|
63
|
+
"NETWORK_ERROR"
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
if (!response.ok) {
|
|
67
|
+
const errorMessage = await parseErrorResponse(response);
|
|
68
|
+
const status = response.status;
|
|
69
|
+
if (status === 400) {
|
|
70
|
+
if (errorMessage.toLowerCase().includes("siwe")) {
|
|
71
|
+
throw new SessionError(`Invalid SIWE message: ${errorMessage}`, "INVALID_MESSAGE", status);
|
|
72
|
+
}
|
|
73
|
+
throw new SessionError(`Bad request: ${errorMessage}`, "INVALID_MESSAGE", status);
|
|
74
|
+
}
|
|
75
|
+
if (status === 401) {
|
|
76
|
+
throw new SessionError(`Invalid signature: ${errorMessage}`, "INVALID_SIGNATURE", status);
|
|
77
|
+
}
|
|
78
|
+
throw new SessionError(`Login failed: ${errorMessage}`, "UNKNOWN", status);
|
|
79
|
+
}
|
|
80
|
+
const data = await response.json();
|
|
81
|
+
return {
|
|
82
|
+
success: data.success,
|
|
83
|
+
address: data.address
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
async function getComputeApiSession(config) {
|
|
87
|
+
let response;
|
|
88
|
+
try {
|
|
89
|
+
response = await fetch(`${config.baseUrl}/auth/session`, {
|
|
90
|
+
method: "GET",
|
|
91
|
+
credentials: "include",
|
|
92
|
+
// Include cookies for session management
|
|
93
|
+
headers: {
|
|
94
|
+
"Content-Type": "application/json"
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
} catch {
|
|
98
|
+
return {
|
|
99
|
+
authenticated: false
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
if (response.status === 401) {
|
|
103
|
+
return {
|
|
104
|
+
authenticated: false
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
if (!response.ok) {
|
|
108
|
+
const errorMessage = await parseErrorResponse(response);
|
|
109
|
+
throw new SessionError(`Failed to get session: ${errorMessage}`, "UNKNOWN", response.status);
|
|
110
|
+
}
|
|
111
|
+
const data = await response.json();
|
|
112
|
+
return {
|
|
113
|
+
authenticated: data.authenticated,
|
|
114
|
+
address: data.address,
|
|
115
|
+
chainId: data.chain_id
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
async function logoutFromComputeApi(config) {
|
|
119
|
+
let response;
|
|
120
|
+
try {
|
|
121
|
+
response = await fetch(`${config.baseUrl}/auth/logout`, {
|
|
122
|
+
method: "POST",
|
|
123
|
+
credentials: "include",
|
|
124
|
+
// Include cookies for session management
|
|
125
|
+
headers: {
|
|
126
|
+
"Content-Type": "application/json"
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
} catch (error) {
|
|
130
|
+
throw new SessionError(
|
|
131
|
+
`Network error connecting to ${config.baseUrl}: ${error instanceof Error ? error.message : String(error)}`,
|
|
132
|
+
"NETWORK_ERROR"
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
if (response.status === 401) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
if (!response.ok) {
|
|
139
|
+
const errorMessage = await parseErrorResponse(response);
|
|
140
|
+
throw new SessionError(`Logout failed: ${errorMessage}`, "UNKNOWN", response.status);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
async function isSessionValid(config) {
|
|
144
|
+
const session = await getComputeApiSession(config);
|
|
145
|
+
return session.authenticated;
|
|
146
|
+
}
|
|
147
|
+
var SessionError;
|
|
148
|
+
var init_session = __esm({
|
|
149
|
+
"src/client/common/auth/session.ts"() {
|
|
150
|
+
"use strict";
|
|
151
|
+
SessionError = class extends Error {
|
|
152
|
+
constructor(message, code, statusCode) {
|
|
153
|
+
super(message);
|
|
154
|
+
this.code = code;
|
|
155
|
+
this.statusCode = statusCode;
|
|
156
|
+
this.name = "SessionError";
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
|
|
30
162
|
// src/index.ts
|
|
31
163
|
var index_exports = {};
|
|
32
164
|
__export(index_exports, {
|
|
@@ -2314,7 +2446,7 @@ function encodeExecuteBatchData(executions) {
|
|
|
2314
2446
|
});
|
|
2315
2447
|
}
|
|
2316
2448
|
async function estimateBatchGas(options) {
|
|
2317
|
-
const { publicClient, account, executions } = options;
|
|
2449
|
+
const { publicClient, account, executions, authorizationList } = options;
|
|
2318
2450
|
const executeBatchData = encodeExecuteBatchData(executions);
|
|
2319
2451
|
const [gasTipCap, block, estimatedGas] = await Promise.all([
|
|
2320
2452
|
publicClient.estimateMaxPriorityFeePerGas(),
|
|
@@ -2322,7 +2454,8 @@ async function estimateBatchGas(options) {
|
|
|
2322
2454
|
publicClient.estimateGas({
|
|
2323
2455
|
account,
|
|
2324
2456
|
to: account,
|
|
2325
|
-
data: executeBatchData
|
|
2457
|
+
data: executeBatchData,
|
|
2458
|
+
authorizationList
|
|
2326
2459
|
})
|
|
2327
2460
|
]);
|
|
2328
2461
|
const baseFee = block.baseFeePerGas ?? 0n;
|
|
@@ -2345,8 +2478,44 @@ async function checkERC7702Delegation(publicClient, account, delegatorAddress) {
|
|
|
2345
2478
|
const expectedCode = `0xef0100${delegatorAddress.slice(2)}`;
|
|
2346
2479
|
return code.toLowerCase() === expectedCode.toLowerCase();
|
|
2347
2480
|
}
|
|
2481
|
+
async function createAuthorizationList(options) {
|
|
2482
|
+
const { walletClient, publicClient, environmentConfig } = options;
|
|
2483
|
+
const account = walletClient.account;
|
|
2484
|
+
if (!account) {
|
|
2485
|
+
throw new Error("Wallet client must have an account");
|
|
2486
|
+
}
|
|
2487
|
+
const isDelegated2 = await checkERC7702Delegation(
|
|
2488
|
+
publicClient,
|
|
2489
|
+
account.address,
|
|
2490
|
+
environmentConfig.erc7702DelegatorAddress
|
|
2491
|
+
);
|
|
2492
|
+
if (isDelegated2) {
|
|
2493
|
+
return void 0;
|
|
2494
|
+
}
|
|
2495
|
+
const transactionNonce = await publicClient.getTransactionCount({
|
|
2496
|
+
address: account.address,
|
|
2497
|
+
blockTag: "pending"
|
|
2498
|
+
});
|
|
2499
|
+
const chainId = await publicClient.getChainId();
|
|
2500
|
+
const authorizationNonce = transactionNonce + 1;
|
|
2501
|
+
const signedAuthorization = await walletClient.signAuthorization({
|
|
2502
|
+
account,
|
|
2503
|
+
contractAddress: environmentConfig.erc7702DelegatorAddress,
|
|
2504
|
+
chainId,
|
|
2505
|
+
nonce: Number(authorizationNonce)
|
|
2506
|
+
});
|
|
2507
|
+
return [signedAuthorization];
|
|
2508
|
+
}
|
|
2348
2509
|
async function executeBatch(options, logger = noopLogger) {
|
|
2349
|
-
const {
|
|
2510
|
+
const {
|
|
2511
|
+
walletClient,
|
|
2512
|
+
publicClient,
|
|
2513
|
+
environmentConfig,
|
|
2514
|
+
executions,
|
|
2515
|
+
pendingMessage,
|
|
2516
|
+
gas,
|
|
2517
|
+
authorizationList: providedAuthList
|
|
2518
|
+
} = options;
|
|
2350
2519
|
const account = walletClient.account;
|
|
2351
2520
|
if (!account) {
|
|
2352
2521
|
throw new Error("Wallet client must have an account");
|
|
@@ -2356,27 +2525,29 @@ async function executeBatch(options, logger = noopLogger) {
|
|
|
2356
2525
|
throw new Error("Wallet client must have a chain");
|
|
2357
2526
|
}
|
|
2358
2527
|
const executeBatchData = encodeExecuteBatchData(executions);
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2528
|
+
let authorizationList = providedAuthList || [];
|
|
2529
|
+
if (authorizationList.length === 0) {
|
|
2530
|
+
const isDelegated2 = await checkERC7702Delegation(
|
|
2531
|
+
publicClient,
|
|
2532
|
+
account.address,
|
|
2533
|
+
environmentConfig.erc7702DelegatorAddress
|
|
2534
|
+
);
|
|
2535
|
+
if (!isDelegated2) {
|
|
2536
|
+
const transactionNonce = await publicClient.getTransactionCount({
|
|
2537
|
+
address: account.address,
|
|
2538
|
+
blockTag: "pending"
|
|
2539
|
+
});
|
|
2540
|
+
const chainId = await publicClient.getChainId();
|
|
2541
|
+
const authorizationNonce = transactionNonce + 1;
|
|
2542
|
+
logger.debug("Using wallet client signing for EIP-7702 authorization");
|
|
2543
|
+
const signedAuthorization = await walletClient.signAuthorization({
|
|
2544
|
+
account,
|
|
2545
|
+
contractAddress: environmentConfig.erc7702DelegatorAddress,
|
|
2546
|
+
chainId,
|
|
2547
|
+
nonce: Number(authorizationNonce)
|
|
2548
|
+
});
|
|
2549
|
+
authorizationList = [signedAuthorization];
|
|
2550
|
+
}
|
|
2380
2551
|
}
|
|
2381
2552
|
if (pendingMessage) {
|
|
2382
2553
|
logger.info(pendingMessage);
|
|
@@ -2391,6 +2562,9 @@ async function executeBatch(options, logger = noopLogger) {
|
|
|
2391
2562
|
if (authorizationList.length > 0) {
|
|
2392
2563
|
txRequest.authorizationList = authorizationList;
|
|
2393
2564
|
}
|
|
2565
|
+
if (gas?.gasLimit) {
|
|
2566
|
+
txRequest.gas = gas.gasLimit;
|
|
2567
|
+
}
|
|
2394
2568
|
if (gas?.maxFeePerGas) {
|
|
2395
2569
|
txRequest.maxFeePerGas = gas.maxFeePerGas;
|
|
2396
2570
|
}
|
|
@@ -2435,23 +2609,24 @@ var import_viem3 = require("viem");
|
|
|
2435
2609
|
var import_viem2 = require("viem");
|
|
2436
2610
|
var import_chains2 = require("viem/chains");
|
|
2437
2611
|
var import_accounts = require("viem/accounts");
|
|
2438
|
-
function getChainFromID(chainID,
|
|
2612
|
+
function getChainFromID(chainID, fallback2 = import_chains2.sepolia) {
|
|
2439
2613
|
const id = Number(chainID);
|
|
2440
|
-
return (0, import_viem2.extractChain)({ chains: SUPPORTED_CHAINS, id }) ||
|
|
2614
|
+
return (0, import_viem2.extractChain)({ chains: SUPPORTED_CHAINS, id }) || fallback2;
|
|
2441
2615
|
}
|
|
2442
2616
|
function createClients(options) {
|
|
2443
2617
|
const { privateKey, rpcUrl, chainId } = options;
|
|
2444
2618
|
const privateKeyHex = addHexPrefix(privateKey);
|
|
2445
2619
|
const account = (0, import_accounts.privateKeyToAccount)(privateKeyHex);
|
|
2446
2620
|
const chain = getChainFromID(chainId);
|
|
2621
|
+
const transport = typeof rpcUrl === "string" ? (0, import_viem2.http)(rpcUrl) : (0, import_viem2.fallback)(rpcUrl.map((url) => (0, import_viem2.http)(url)));
|
|
2447
2622
|
const publicClient = (0, import_viem2.createPublicClient)({
|
|
2448
2623
|
chain,
|
|
2449
|
-
transport
|
|
2624
|
+
transport
|
|
2450
2625
|
});
|
|
2451
2626
|
const walletClient = (0, import_viem2.createWalletClient)({
|
|
2452
2627
|
account,
|
|
2453
2628
|
chain,
|
|
2454
|
-
transport
|
|
2629
|
+
transport
|
|
2455
2630
|
});
|
|
2456
2631
|
return { walletClient, publicClient };
|
|
2457
2632
|
}
|
|
@@ -4139,7 +4314,8 @@ async function executeDeployBatch(data, context, gas, logger = noopLogger) {
|
|
|
4139
4314
|
environmentConfig: context.environmentConfig,
|
|
4140
4315
|
executions: data.executions,
|
|
4141
4316
|
pendingMessage,
|
|
4142
|
-
gas
|
|
4317
|
+
gas,
|
|
4318
|
+
authorizationList: data.authorizationList
|
|
4143
4319
|
},
|
|
4144
4320
|
logger
|
|
4145
4321
|
);
|
|
@@ -4250,7 +4426,8 @@ async function executeUpgradeBatch(data, context, gas, logger = noopLogger) {
|
|
|
4250
4426
|
environmentConfig: context.environmentConfig,
|
|
4251
4427
|
executions: data.executions,
|
|
4252
4428
|
pendingMessage,
|
|
4253
|
-
gas
|
|
4429
|
+
gas,
|
|
4430
|
+
authorizationList: data.authorizationList
|
|
4254
4431
|
},
|
|
4255
4432
|
logger
|
|
4256
4433
|
);
|
|
@@ -4560,166 +4737,44 @@ async function calculateBillingAuthSignature(options) {
|
|
|
4560
4737
|
return { signature, expiry };
|
|
4561
4738
|
}
|
|
4562
4739
|
|
|
4563
|
-
// src/client/common/
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
this.code = code;
|
|
4568
|
-
this.statusCode = statusCode;
|
|
4569
|
-
this.name = "SessionError";
|
|
4570
|
-
}
|
|
4571
|
-
};
|
|
4572
|
-
function stripHexPrefix2(hex) {
|
|
4573
|
-
return hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
4740
|
+
// src/client/common/utils/userapi.ts
|
|
4741
|
+
init_session();
|
|
4742
|
+
function isJsonObject(value) {
|
|
4743
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4574
4744
|
}
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
return data.error || response.statusText;
|
|
4579
|
-
} catch {
|
|
4580
|
-
return response.statusText;
|
|
4581
|
-
}
|
|
4745
|
+
function readString(obj, key) {
|
|
4746
|
+
const v = obj[key];
|
|
4747
|
+
return typeof v === "string" ? v : void 0;
|
|
4582
4748
|
}
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
|
|
4598
|
-
|
|
4599
|
-
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
);
|
|
4749
|
+
function readNumber(obj, key) {
|
|
4750
|
+
const v = obj[key];
|
|
4751
|
+
return typeof v === "number" && Number.isFinite(v) ? v : void 0;
|
|
4752
|
+
}
|
|
4753
|
+
var MAX_ADDRESS_COUNT = 5;
|
|
4754
|
+
var CanViewAppLogsPermission = "0x2fd3f2fe";
|
|
4755
|
+
var CanViewSensitiveAppInfoPermission = "0x0e67b22f";
|
|
4756
|
+
var CanUpdateAppProfilePermission = "0x036fef61";
|
|
4757
|
+
function getDefaultClientId() {
|
|
4758
|
+
const version = true ? "0.3.1-dev.0" : "0.0.0";
|
|
4759
|
+
return `ecloud-sdk/v${version}`;
|
|
4760
|
+
}
|
|
4761
|
+
var UserApiClient = class {
|
|
4762
|
+
constructor(config, walletClient, publicClient, options) {
|
|
4763
|
+
this.config = config;
|
|
4764
|
+
this.walletClient = walletClient;
|
|
4765
|
+
this.publicClient = publicClient;
|
|
4766
|
+
this.clientId = options?.clientId || getDefaultClientId();
|
|
4767
|
+
this.useSession = options?.useSession ?? false;
|
|
4603
4768
|
}
|
|
4604
|
-
|
|
4605
|
-
|
|
4606
|
-
|
|
4607
|
-
|
|
4608
|
-
|
|
4609
|
-
|
|
4610
|
-
|
|
4611
|
-
throw new SessionError(`Bad request: ${errorMessage}`, "INVALID_MESSAGE", status);
|
|
4612
|
-
}
|
|
4613
|
-
if (status === 401) {
|
|
4614
|
-
throw new SessionError(`Invalid signature: ${errorMessage}`, "INVALID_SIGNATURE", status);
|
|
4769
|
+
/**
|
|
4770
|
+
* Get the address of the connected wallet
|
|
4771
|
+
*/
|
|
4772
|
+
get address() {
|
|
4773
|
+
const account = this.walletClient.account;
|
|
4774
|
+
if (!account) {
|
|
4775
|
+
throw new Error("WalletClient must have an account attached");
|
|
4615
4776
|
}
|
|
4616
|
-
|
|
4617
|
-
}
|
|
4618
|
-
const data = await response.json();
|
|
4619
|
-
return {
|
|
4620
|
-
success: data.success,
|
|
4621
|
-
address: data.address
|
|
4622
|
-
};
|
|
4623
|
-
}
|
|
4624
|
-
async function getComputeApiSession(config) {
|
|
4625
|
-
let response;
|
|
4626
|
-
try {
|
|
4627
|
-
response = await fetch(`${config.baseUrl}/auth/session`, {
|
|
4628
|
-
method: "GET",
|
|
4629
|
-
credentials: "include",
|
|
4630
|
-
// Include cookies for session management
|
|
4631
|
-
headers: {
|
|
4632
|
-
"Content-Type": "application/json"
|
|
4633
|
-
}
|
|
4634
|
-
});
|
|
4635
|
-
} catch {
|
|
4636
|
-
return {
|
|
4637
|
-
authenticated: false
|
|
4638
|
-
};
|
|
4639
|
-
}
|
|
4640
|
-
if (response.status === 401) {
|
|
4641
|
-
return {
|
|
4642
|
-
authenticated: false
|
|
4643
|
-
};
|
|
4644
|
-
}
|
|
4645
|
-
if (!response.ok) {
|
|
4646
|
-
const errorMessage = await parseErrorResponse(response);
|
|
4647
|
-
throw new SessionError(`Failed to get session: ${errorMessage}`, "UNKNOWN", response.status);
|
|
4648
|
-
}
|
|
4649
|
-
const data = await response.json();
|
|
4650
|
-
return {
|
|
4651
|
-
authenticated: data.authenticated,
|
|
4652
|
-
address: data.address,
|
|
4653
|
-
chainId: data.chain_id
|
|
4654
|
-
};
|
|
4655
|
-
}
|
|
4656
|
-
async function logoutFromComputeApi(config) {
|
|
4657
|
-
let response;
|
|
4658
|
-
try {
|
|
4659
|
-
response = await fetch(`${config.baseUrl}/auth/logout`, {
|
|
4660
|
-
method: "POST",
|
|
4661
|
-
credentials: "include",
|
|
4662
|
-
// Include cookies for session management
|
|
4663
|
-
headers: {
|
|
4664
|
-
"Content-Type": "application/json"
|
|
4665
|
-
}
|
|
4666
|
-
});
|
|
4667
|
-
} catch (error) {
|
|
4668
|
-
throw new SessionError(
|
|
4669
|
-
`Network error connecting to ${config.baseUrl}: ${error instanceof Error ? error.message : String(error)}`,
|
|
4670
|
-
"NETWORK_ERROR"
|
|
4671
|
-
);
|
|
4672
|
-
}
|
|
4673
|
-
if (response.status === 401) {
|
|
4674
|
-
return;
|
|
4675
|
-
}
|
|
4676
|
-
if (!response.ok) {
|
|
4677
|
-
const errorMessage = await parseErrorResponse(response);
|
|
4678
|
-
throw new SessionError(`Logout failed: ${errorMessage}`, "UNKNOWN", response.status);
|
|
4679
|
-
}
|
|
4680
|
-
}
|
|
4681
|
-
async function isSessionValid(config) {
|
|
4682
|
-
const session = await getComputeApiSession(config);
|
|
4683
|
-
return session.authenticated;
|
|
4684
|
-
}
|
|
4685
|
-
|
|
4686
|
-
// src/client/common/utils/userapi.ts
|
|
4687
|
-
function isJsonObject(value) {
|
|
4688
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4689
|
-
}
|
|
4690
|
-
function readString(obj, key) {
|
|
4691
|
-
const v = obj[key];
|
|
4692
|
-
return typeof v === "string" ? v : void 0;
|
|
4693
|
-
}
|
|
4694
|
-
function readNumber(obj, key) {
|
|
4695
|
-
const v = obj[key];
|
|
4696
|
-
return typeof v === "number" && Number.isFinite(v) ? v : void 0;
|
|
4697
|
-
}
|
|
4698
|
-
var MAX_ADDRESS_COUNT = 5;
|
|
4699
|
-
var CanViewAppLogsPermission = "0x2fd3f2fe";
|
|
4700
|
-
var CanViewSensitiveAppInfoPermission = "0x0e67b22f";
|
|
4701
|
-
var CanUpdateAppProfilePermission = "0x036fef61";
|
|
4702
|
-
function getDefaultClientId() {
|
|
4703
|
-
const version = true ? "0.3.1-dev" : "0.0.0";
|
|
4704
|
-
return `ecloud-sdk/v${version}`;
|
|
4705
|
-
}
|
|
4706
|
-
var UserApiClient = class {
|
|
4707
|
-
constructor(config, walletClient, publicClient, options) {
|
|
4708
|
-
this.config = config;
|
|
4709
|
-
this.walletClient = walletClient;
|
|
4710
|
-
this.publicClient = publicClient;
|
|
4711
|
-
this.clientId = options?.clientId || getDefaultClientId();
|
|
4712
|
-
this.useSession = options?.useSession ?? false;
|
|
4713
|
-
}
|
|
4714
|
-
/**
|
|
4715
|
-
* Get the address of the connected wallet
|
|
4716
|
-
*/
|
|
4717
|
-
get address() {
|
|
4718
|
-
const account = this.walletClient.account;
|
|
4719
|
-
if (!account) {
|
|
4720
|
-
throw new Error("WalletClient must have an account attached");
|
|
4721
|
-
}
|
|
4722
|
-
return account.address;
|
|
4777
|
+
return account.address;
|
|
4723
4778
|
}
|
|
4724
4779
|
async getInfos(appIDs, addressCount = 1) {
|
|
4725
4780
|
const count = Math.min(addressCount, MAX_ADDRESS_COUNT);
|
|
@@ -5608,21 +5663,214 @@ function isSubscriptionActive(status) {
|
|
|
5608
5663
|
|
|
5609
5664
|
// src/client/common/utils/billingapi.ts
|
|
5610
5665
|
var import_axios2 = __toESM(require("axios"), 1);
|
|
5666
|
+
|
|
5667
|
+
// src/client/common/auth/billingSession.ts
|
|
5668
|
+
var BillingSessionError = class extends Error {
|
|
5669
|
+
constructor(message, code, statusCode) {
|
|
5670
|
+
super(message);
|
|
5671
|
+
this.code = code;
|
|
5672
|
+
this.statusCode = statusCode;
|
|
5673
|
+
this.name = "BillingSessionError";
|
|
5674
|
+
}
|
|
5675
|
+
};
|
|
5676
|
+
function stripHexPrefix3(hex) {
|
|
5677
|
+
return hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
5678
|
+
}
|
|
5679
|
+
async function parseErrorResponse2(response) {
|
|
5680
|
+
try {
|
|
5681
|
+
const data = await response.json();
|
|
5682
|
+
return data.error || response.statusText;
|
|
5683
|
+
} catch {
|
|
5684
|
+
return response.statusText;
|
|
5685
|
+
}
|
|
5686
|
+
}
|
|
5687
|
+
async function loginToBillingApi(config, request) {
|
|
5688
|
+
let response;
|
|
5689
|
+
try {
|
|
5690
|
+
response = await fetch(`${config.baseUrl}/auth/siwe/login`, {
|
|
5691
|
+
method: "POST",
|
|
5692
|
+
credentials: "include",
|
|
5693
|
+
// Include cookies for session management
|
|
5694
|
+
headers: {
|
|
5695
|
+
"Content-Type": "application/json"
|
|
5696
|
+
},
|
|
5697
|
+
body: JSON.stringify({
|
|
5698
|
+
message: request.message,
|
|
5699
|
+
signature: stripHexPrefix3(request.signature)
|
|
5700
|
+
})
|
|
5701
|
+
});
|
|
5702
|
+
} catch (error) {
|
|
5703
|
+
throw new BillingSessionError(
|
|
5704
|
+
`Network error connecting to ${config.baseUrl}: ${error instanceof Error ? error.message : String(error)}`,
|
|
5705
|
+
"NETWORK_ERROR"
|
|
5706
|
+
);
|
|
5707
|
+
}
|
|
5708
|
+
if (!response.ok) {
|
|
5709
|
+
const errorMessage = await parseErrorResponse2(response);
|
|
5710
|
+
const status = response.status;
|
|
5711
|
+
if (status === 400) {
|
|
5712
|
+
if (errorMessage.toLowerCase().includes("siwe")) {
|
|
5713
|
+
throw new BillingSessionError(`Invalid SIWE message: ${errorMessage}`, "INVALID_MESSAGE", status);
|
|
5714
|
+
}
|
|
5715
|
+
throw new BillingSessionError(`Bad request: ${errorMessage}`, "INVALID_MESSAGE", status);
|
|
5716
|
+
}
|
|
5717
|
+
if (status === 401) {
|
|
5718
|
+
throw new BillingSessionError(`Invalid signature: ${errorMessage}`, "INVALID_SIGNATURE", status);
|
|
5719
|
+
}
|
|
5720
|
+
throw new BillingSessionError(`Login failed: ${errorMessage}`, "UNKNOWN", status);
|
|
5721
|
+
}
|
|
5722
|
+
const data = await response.json();
|
|
5723
|
+
return {
|
|
5724
|
+
success: data.success,
|
|
5725
|
+
address: data.address
|
|
5726
|
+
};
|
|
5727
|
+
}
|
|
5728
|
+
async function getBillingApiSession(config) {
|
|
5729
|
+
let response;
|
|
5730
|
+
try {
|
|
5731
|
+
response = await fetch(`${config.baseUrl}/auth/session`, {
|
|
5732
|
+
method: "GET",
|
|
5733
|
+
credentials: "include",
|
|
5734
|
+
// Include cookies for session management
|
|
5735
|
+
headers: {
|
|
5736
|
+
"Content-Type": "application/json"
|
|
5737
|
+
}
|
|
5738
|
+
});
|
|
5739
|
+
} catch {
|
|
5740
|
+
return {
|
|
5741
|
+
authenticated: false
|
|
5742
|
+
};
|
|
5743
|
+
}
|
|
5744
|
+
if (response.status === 401) {
|
|
5745
|
+
return {
|
|
5746
|
+
authenticated: false
|
|
5747
|
+
};
|
|
5748
|
+
}
|
|
5749
|
+
if (!response.ok) {
|
|
5750
|
+
const errorMessage = await parseErrorResponse2(response);
|
|
5751
|
+
throw new BillingSessionError(`Failed to get session: ${errorMessage}`, "UNKNOWN", response.status);
|
|
5752
|
+
}
|
|
5753
|
+
const data = await response.json();
|
|
5754
|
+
return {
|
|
5755
|
+
authenticated: data.authenticated,
|
|
5756
|
+
address: data.address,
|
|
5757
|
+
chainId: data.chainId,
|
|
5758
|
+
authenticatedAt: data.authenticatedAt
|
|
5759
|
+
};
|
|
5760
|
+
}
|
|
5761
|
+
async function logoutFromBillingApi(config) {
|
|
5762
|
+
let response;
|
|
5763
|
+
try {
|
|
5764
|
+
response = await fetch(`${config.baseUrl}/auth/logout`, {
|
|
5765
|
+
method: "POST",
|
|
5766
|
+
credentials: "include",
|
|
5767
|
+
// Include cookies for session management
|
|
5768
|
+
headers: {
|
|
5769
|
+
"Content-Type": "application/json"
|
|
5770
|
+
}
|
|
5771
|
+
});
|
|
5772
|
+
} catch (error) {
|
|
5773
|
+
throw new BillingSessionError(
|
|
5774
|
+
`Network error connecting to ${config.baseUrl}: ${error instanceof Error ? error.message : String(error)}`,
|
|
5775
|
+
"NETWORK_ERROR"
|
|
5776
|
+
);
|
|
5777
|
+
}
|
|
5778
|
+
if (response.status === 401) {
|
|
5779
|
+
return;
|
|
5780
|
+
}
|
|
5781
|
+
if (!response.ok) {
|
|
5782
|
+
const errorMessage = await parseErrorResponse2(response);
|
|
5783
|
+
throw new BillingSessionError(`Logout failed: ${errorMessage}`, "UNKNOWN", response.status);
|
|
5784
|
+
}
|
|
5785
|
+
}
|
|
5786
|
+
|
|
5787
|
+
// src/client/common/utils/billingapi.ts
|
|
5611
5788
|
var BillingApiClient = class {
|
|
5612
|
-
constructor(config, walletClient) {
|
|
5789
|
+
constructor(config, walletClient, options = {}) {
|
|
5613
5790
|
this.config = config;
|
|
5614
5791
|
this.walletClient = walletClient;
|
|
5792
|
+
this.options = options;
|
|
5793
|
+
this.useSession = options.useSession ?? false;
|
|
5794
|
+
if (!this.useSession && !walletClient) {
|
|
5795
|
+
throw new Error("WalletClient is required when not using session authentication");
|
|
5796
|
+
}
|
|
5615
5797
|
}
|
|
5616
5798
|
/**
|
|
5617
5799
|
* Get the address of the connected wallet
|
|
5800
|
+
* Returns undefined if using session auth without a wallet client
|
|
5618
5801
|
*/
|
|
5619
5802
|
get address() {
|
|
5620
|
-
const account = this.walletClient
|
|
5803
|
+
const account = this.walletClient?.account;
|
|
5621
5804
|
if (!account) {
|
|
5622
|
-
|
|
5805
|
+
if (!this.useSession) {
|
|
5806
|
+
throw new Error("WalletClient must have an account attached");
|
|
5807
|
+
}
|
|
5808
|
+
return void 0;
|
|
5623
5809
|
}
|
|
5624
5810
|
return account.address;
|
|
5625
5811
|
}
|
|
5812
|
+
/**
|
|
5813
|
+
* Get the base URL of the billing API
|
|
5814
|
+
*/
|
|
5815
|
+
get baseUrl() {
|
|
5816
|
+
return this.config.billingApiServerURL;
|
|
5817
|
+
}
|
|
5818
|
+
// ==========================================================================
|
|
5819
|
+
// SIWE Session Methods
|
|
5820
|
+
// ==========================================================================
|
|
5821
|
+
/**
|
|
5822
|
+
* Login to the billing API using SIWE
|
|
5823
|
+
*
|
|
5824
|
+
* This establishes a session with the billing API by verifying the SIWE message
|
|
5825
|
+
* and signature. On success, a session cookie is set in the browser.
|
|
5826
|
+
*
|
|
5827
|
+
* @param request - Login request containing SIWE message and signature
|
|
5828
|
+
* @returns Login result with the authenticated address
|
|
5829
|
+
*
|
|
5830
|
+
* @example
|
|
5831
|
+
* ```typescript
|
|
5832
|
+
* const { message } = createSiweMessage({
|
|
5833
|
+
* address: userAddress,
|
|
5834
|
+
* chainId: 11155111,
|
|
5835
|
+
* domain: window.location.host,
|
|
5836
|
+
* uri: window.location.origin,
|
|
5837
|
+
* });
|
|
5838
|
+
*
|
|
5839
|
+
* const signature = await signMessageAsync({ message });
|
|
5840
|
+
* const result = await billingClient.siweLogin({ message, signature });
|
|
5841
|
+
* ```
|
|
5842
|
+
*/
|
|
5843
|
+
async siweLogin(request) {
|
|
5844
|
+
return loginToBillingApi({ baseUrl: this.baseUrl }, request);
|
|
5845
|
+
}
|
|
5846
|
+
/**
|
|
5847
|
+
* Logout from the billing API
|
|
5848
|
+
*
|
|
5849
|
+
* This destroys the current session and clears the session cookie.
|
|
5850
|
+
*/
|
|
5851
|
+
async siweLogout() {
|
|
5852
|
+
return logoutFromBillingApi({ baseUrl: this.baseUrl });
|
|
5853
|
+
}
|
|
5854
|
+
/**
|
|
5855
|
+
* Get the current session status from the billing API
|
|
5856
|
+
*
|
|
5857
|
+
* @returns Session information including authentication status and address
|
|
5858
|
+
*/
|
|
5859
|
+
async getSession() {
|
|
5860
|
+
return getBillingApiSession({ baseUrl: this.baseUrl });
|
|
5861
|
+
}
|
|
5862
|
+
/**
|
|
5863
|
+
* Check if there is a valid session
|
|
5864
|
+
*
|
|
5865
|
+
* @returns True if session is authenticated, false otherwise
|
|
5866
|
+
*/
|
|
5867
|
+
async isSessionValid() {
|
|
5868
|
+
const session = await this.getSession();
|
|
5869
|
+
return session.authenticated;
|
|
5870
|
+
}
|
|
5871
|
+
// ==========================================================================
|
|
5872
|
+
// Subscription Methods
|
|
5873
|
+
// ==========================================================================
|
|
5626
5874
|
async createSubscription(productId = "compute", options) {
|
|
5627
5875
|
const endpoint = `${this.config.billingApiServerURL}/products/${productId}/subscription`;
|
|
5628
5876
|
const body = options ? {
|
|
@@ -5641,10 +5889,72 @@ var BillingApiClient = class {
|
|
|
5641
5889
|
const endpoint = `${this.config.billingApiServerURL}/products/${productId}/subscription`;
|
|
5642
5890
|
await this.makeAuthenticatedRequest(endpoint, "DELETE", productId);
|
|
5643
5891
|
}
|
|
5892
|
+
// ==========================================================================
|
|
5893
|
+
// Internal Methods
|
|
5894
|
+
// ==========================================================================
|
|
5644
5895
|
/**
|
|
5645
5896
|
* Make an authenticated request to the billing API
|
|
5897
|
+
*
|
|
5898
|
+
* Uses session auth if useSession is true, otherwise uses EIP-712 signature auth.
|
|
5646
5899
|
*/
|
|
5647
5900
|
async makeAuthenticatedRequest(url, method, productId, body) {
|
|
5901
|
+
if (this.useSession) {
|
|
5902
|
+
return this.makeSessionAuthenticatedRequest(url, method, body);
|
|
5903
|
+
}
|
|
5904
|
+
return this.makeSignatureAuthenticatedRequest(url, method, productId, body);
|
|
5905
|
+
}
|
|
5906
|
+
/**
|
|
5907
|
+
* Make a request using session-based authentication (cookies)
|
|
5908
|
+
*/
|
|
5909
|
+
async makeSessionAuthenticatedRequest(url, method, body) {
|
|
5910
|
+
const headers = {};
|
|
5911
|
+
if (body) {
|
|
5912
|
+
headers["Content-Type"] = "application/json";
|
|
5913
|
+
}
|
|
5914
|
+
try {
|
|
5915
|
+
const response = await fetch(url, {
|
|
5916
|
+
method,
|
|
5917
|
+
credentials: "include",
|
|
5918
|
+
// Include cookies for session management
|
|
5919
|
+
headers,
|
|
5920
|
+
body: body ? JSON.stringify(body) : void 0
|
|
5921
|
+
});
|
|
5922
|
+
const status = response.status;
|
|
5923
|
+
const statusText = status >= 200 && status < 300 ? "OK" : "Error";
|
|
5924
|
+
if (status < 200 || status >= 300) {
|
|
5925
|
+
let errorBody;
|
|
5926
|
+
try {
|
|
5927
|
+
errorBody = await response.text();
|
|
5928
|
+
} catch {
|
|
5929
|
+
errorBody = statusText;
|
|
5930
|
+
}
|
|
5931
|
+
throw new Error(`BillingAPI request failed: ${status} ${statusText} - ${errorBody}`);
|
|
5932
|
+
}
|
|
5933
|
+
const responseData = await response.json();
|
|
5934
|
+
return {
|
|
5935
|
+
json: async () => responseData,
|
|
5936
|
+
text: async () => JSON.stringify(responseData)
|
|
5937
|
+
};
|
|
5938
|
+
} catch (error) {
|
|
5939
|
+
if (error.name === "TypeError" || error.message?.includes("fetch")) {
|
|
5940
|
+
throw new Error(
|
|
5941
|
+
`Failed to connect to BillingAPI at ${url}: ${error.message}
|
|
5942
|
+
Please check:
|
|
5943
|
+
1. Your internet connection
|
|
5944
|
+
2. The API server is accessible: ${this.config.billingApiServerURL}
|
|
5945
|
+
3. Firewall/proxy settings`
|
|
5946
|
+
);
|
|
5947
|
+
}
|
|
5948
|
+
throw error;
|
|
5949
|
+
}
|
|
5950
|
+
}
|
|
5951
|
+
/**
|
|
5952
|
+
* Make a request using EIP-712 signature authentication
|
|
5953
|
+
*/
|
|
5954
|
+
async makeSignatureAuthenticatedRequest(url, method, productId, body) {
|
|
5955
|
+
if (!this.walletClient) {
|
|
5956
|
+
throw new Error("WalletClient is required for signature authentication");
|
|
5957
|
+
}
|
|
5648
5958
|
const expiry = BigInt(Math.floor(Date.now() / 1e3) + 5 * 60);
|
|
5649
5959
|
const { signature } = await calculateBillingAuthSignature({
|
|
5650
5960
|
walletClient: this.walletClient,
|
|
@@ -5964,16 +6274,24 @@ async function prepareDeployFromVerifiableBuild(options, logger = defaultLogger)
|
|
|
5964
6274
|
},
|
|
5965
6275
|
logger
|
|
5966
6276
|
);
|
|
6277
|
+
logger.debug("Checking delegation status...");
|
|
6278
|
+
const authorizationList = await createAuthorizationList({
|
|
6279
|
+
walletClient: batch.walletClient,
|
|
6280
|
+
publicClient: batch.publicClient,
|
|
6281
|
+
environmentConfig: batch.environmentConfig
|
|
6282
|
+
});
|
|
5967
6283
|
logger.debug("Estimating gas...");
|
|
5968
6284
|
const gasEstimate = await estimateBatchGas({
|
|
5969
6285
|
publicClient: batch.publicClient,
|
|
5970
6286
|
account: batch.walletClient.account.address,
|
|
5971
|
-
executions: batch.executions
|
|
6287
|
+
executions: batch.executions,
|
|
6288
|
+
authorizationList
|
|
5972
6289
|
});
|
|
5973
6290
|
const data = {
|
|
5974
6291
|
appId: batch.appId,
|
|
5975
6292
|
salt: batch.salt,
|
|
5976
|
-
executions: batch.executions
|
|
6293
|
+
executions: batch.executions,
|
|
6294
|
+
authorizationList
|
|
5977
6295
|
};
|
|
5978
6296
|
return {
|
|
5979
6297
|
prepared: {
|
|
@@ -6202,16 +6520,24 @@ async function prepareDeploy(options, logger = defaultLogger) {
|
|
|
6202
6520
|
},
|
|
6203
6521
|
logger
|
|
6204
6522
|
);
|
|
6523
|
+
logger.debug("Checking delegation status...");
|
|
6524
|
+
const authorizationList = await createAuthorizationList({
|
|
6525
|
+
walletClient: batch.walletClient,
|
|
6526
|
+
publicClient: batch.publicClient,
|
|
6527
|
+
environmentConfig: batch.environmentConfig
|
|
6528
|
+
});
|
|
6205
6529
|
logger.debug("Estimating gas...");
|
|
6206
6530
|
const gasEstimate = await estimateBatchGas({
|
|
6207
6531
|
publicClient: batch.publicClient,
|
|
6208
6532
|
account: batch.walletClient.account.address,
|
|
6209
|
-
executions: batch.executions
|
|
6533
|
+
executions: batch.executions,
|
|
6534
|
+
authorizationList
|
|
6210
6535
|
});
|
|
6211
6536
|
const data = {
|
|
6212
6537
|
appId: batch.appId,
|
|
6213
6538
|
salt: batch.salt,
|
|
6214
|
-
executions: batch.executions
|
|
6539
|
+
executions: batch.executions,
|
|
6540
|
+
authorizationList
|
|
6215
6541
|
};
|
|
6216
6542
|
return {
|
|
6217
6543
|
prepared: {
|
|
@@ -6342,15 +6668,23 @@ async function prepareUpgradeFromVerifiableBuild(options, logger = defaultLogger
|
|
|
6342
6668
|
needsPermissionChange,
|
|
6343
6669
|
imageRef: options.imageRef
|
|
6344
6670
|
});
|
|
6671
|
+
logger.debug("Checking delegation status...");
|
|
6672
|
+
const authorizationList = await createAuthorizationList({
|
|
6673
|
+
walletClient: batch.walletClient,
|
|
6674
|
+
publicClient: batch.publicClient,
|
|
6675
|
+
environmentConfig: batch.environmentConfig
|
|
6676
|
+
});
|
|
6345
6677
|
logger.debug("Estimating gas...");
|
|
6346
6678
|
const gasEstimate = await estimateBatchGas({
|
|
6347
6679
|
publicClient: batch.publicClient,
|
|
6348
6680
|
account: batch.walletClient.account.address,
|
|
6349
|
-
executions: batch.executions
|
|
6681
|
+
executions: batch.executions,
|
|
6682
|
+
authorizationList
|
|
6350
6683
|
});
|
|
6351
6684
|
const data = {
|
|
6352
6685
|
appId: batch.appId,
|
|
6353
|
-
executions: batch.executions
|
|
6686
|
+
executions: batch.executions,
|
|
6687
|
+
authorizationList
|
|
6354
6688
|
};
|
|
6355
6689
|
return {
|
|
6356
6690
|
prepared: {
|
|
@@ -6523,15 +6857,23 @@ async function prepareUpgrade(options, logger = defaultLogger) {
|
|
|
6523
6857
|
needsPermissionChange,
|
|
6524
6858
|
imageRef: finalImageRef
|
|
6525
6859
|
});
|
|
6860
|
+
logger.debug("Checking delegation status...");
|
|
6861
|
+
const authorizationList = await createAuthorizationList({
|
|
6862
|
+
walletClient: batch.walletClient,
|
|
6863
|
+
publicClient: batch.publicClient,
|
|
6864
|
+
environmentConfig: batch.environmentConfig
|
|
6865
|
+
});
|
|
6526
6866
|
logger.debug("Estimating gas...");
|
|
6527
6867
|
const gasEstimate = await estimateBatchGas({
|
|
6528
6868
|
publicClient: batch.publicClient,
|
|
6529
6869
|
account: batch.walletClient.account.address,
|
|
6530
|
-
executions: batch.executions
|
|
6870
|
+
executions: batch.executions,
|
|
6871
|
+
authorizationList
|
|
6531
6872
|
});
|
|
6532
6873
|
const data = {
|
|
6533
6874
|
appId: batch.appId,
|
|
6534
|
-
executions: batch.executions
|
|
6875
|
+
executions: batch.executions,
|
|
6876
|
+
authorizationList
|
|
6535
6877
|
};
|
|
6536
6878
|
return {
|
|
6537
6879
|
prepared: {
|
|
@@ -7659,7 +8001,10 @@ function createBillingModule(config) {
|
|
|
7659
8001
|
};
|
|
7660
8002
|
}
|
|
7661
8003
|
logger.debug(`Creating subscription for ${productId}...`);
|
|
7662
|
-
const result = await billingApi.createSubscription(productId
|
|
8004
|
+
const result = await billingApi.createSubscription(productId, {
|
|
8005
|
+
successUrl: opts?.successUrl,
|
|
8006
|
+
cancelUrl: opts?.cancelUrl
|
|
8007
|
+
});
|
|
7663
8008
|
logger.debug(`Checkout URL: ${result.checkoutUrl}`);
|
|
7664
8009
|
return {
|
|
7665
8010
|
type: "checkout_created",
|
|
@@ -7751,9 +8096,22 @@ async function requestWithRetry(config) {
|
|
|
7751
8096
|
}
|
|
7752
8097
|
var BuildApiClient = class {
|
|
7753
8098
|
constructor(options) {
|
|
7754
|
-
|
|
8099
|
+
let url = options.baseUrl;
|
|
8100
|
+
while (url.endsWith("/")) {
|
|
8101
|
+
url = url.slice(0, -1);
|
|
8102
|
+
}
|
|
8103
|
+
this.baseUrl = url;
|
|
7755
8104
|
this.clientId = options.clientId;
|
|
7756
8105
|
this.walletClient = options.walletClient;
|
|
8106
|
+
this.useSession = options.useSession ?? false;
|
|
8107
|
+
this.billingSessionId = options.billingSessionId;
|
|
8108
|
+
}
|
|
8109
|
+
/**
|
|
8110
|
+
* Update the billing session ID.
|
|
8111
|
+
* Call this after logging into the billing API to enable session-based auth for builds.
|
|
8112
|
+
*/
|
|
8113
|
+
setBillingSessionId(sessionId) {
|
|
8114
|
+
this.billingSessionId = sessionId;
|
|
7757
8115
|
}
|
|
7758
8116
|
/**
|
|
7759
8117
|
* Get the address of the connected wallet
|
|
@@ -7765,8 +8123,17 @@ var BuildApiClient = class {
|
|
|
7765
8123
|
}
|
|
7766
8124
|
return account.address;
|
|
7767
8125
|
}
|
|
8126
|
+
/**
|
|
8127
|
+
* Submit a new build request.
|
|
8128
|
+
* Supports two auth modes (session auth is tried first when billingSessionId is available):
|
|
8129
|
+
* 1. Session-based auth: X-Billing-Session header (forwarded billing_session cookie)
|
|
8130
|
+
* 2. Signature-based auth: Authorization + X-Account + X-eigenx-expiry headers (requires walletClient)
|
|
8131
|
+
*/
|
|
7768
8132
|
async submitBuild(payload) {
|
|
7769
|
-
|
|
8133
|
+
if (this.useSession && this.billingSessionId) {
|
|
8134
|
+
return this.billingSessionAuthJsonRequest("/builds", "POST", payload);
|
|
8135
|
+
}
|
|
8136
|
+
return this.signatureAuthJsonRequest("/builds", "POST", payload);
|
|
7770
8137
|
}
|
|
7771
8138
|
async getBuild(buildId) {
|
|
7772
8139
|
return this.publicJsonRequest(`/builds/${encodeURIComponent(buildId)}`);
|
|
@@ -7777,8 +8144,11 @@ var BuildApiClient = class {
|
|
|
7777
8144
|
async verify(identifier) {
|
|
7778
8145
|
return this.publicJsonRequest(`/builds/verify/${encodeURIComponent(identifier)}`);
|
|
7779
8146
|
}
|
|
8147
|
+
/**
|
|
8148
|
+
* Get build logs. Supports session auth (identity verification only, no billing check).
|
|
8149
|
+
*/
|
|
7780
8150
|
async getLogs(buildId) {
|
|
7781
|
-
return this.
|
|
8151
|
+
return this.sessionOrSignatureTextRequest(`/builds/${encodeURIComponent(buildId)}/logs`);
|
|
7782
8152
|
}
|
|
7783
8153
|
async listBuilds(params) {
|
|
7784
8154
|
const res = await requestWithRetry({
|
|
@@ -7786,7 +8156,9 @@ var BuildApiClient = class {
|
|
|
7786
8156
|
method: "GET",
|
|
7787
8157
|
params,
|
|
7788
8158
|
headers: this.clientId ? { "x-client-id": this.clientId } : void 0,
|
|
7789
|
-
timeout: 6e4
|
|
8159
|
+
timeout: 6e4,
|
|
8160
|
+
validateStatus: () => true,
|
|
8161
|
+
withCredentials: this.useSession
|
|
7790
8162
|
});
|
|
7791
8163
|
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
7792
8164
|
return res.data;
|
|
@@ -7796,12 +8168,18 @@ var BuildApiClient = class {
|
|
|
7796
8168
|
url: `${this.baseUrl}${path8}`,
|
|
7797
8169
|
method: "GET",
|
|
7798
8170
|
headers: this.clientId ? { "x-client-id": this.clientId } : void 0,
|
|
7799
|
-
timeout: 6e4
|
|
8171
|
+
timeout: 6e4,
|
|
8172
|
+
validateStatus: () => true,
|
|
8173
|
+
withCredentials: this.useSession
|
|
7800
8174
|
});
|
|
7801
8175
|
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
7802
8176
|
return res.data;
|
|
7803
8177
|
}
|
|
7804
|
-
|
|
8178
|
+
/**
|
|
8179
|
+
* Make a request that ALWAYS requires signature auth (for billing verification).
|
|
8180
|
+
* Used for endpoints like POST /builds that need to verify subscription status.
|
|
8181
|
+
*/
|
|
8182
|
+
async signatureAuthJsonRequest(path8, method, body) {
|
|
7805
8183
|
if (!this.walletClient?.account) {
|
|
7806
8184
|
throw new Error("WalletClient with account required for authenticated requests");
|
|
7807
8185
|
}
|
|
@@ -7823,32 +8201,69 @@ var BuildApiClient = class {
|
|
|
7823
8201
|
method,
|
|
7824
8202
|
headers,
|
|
7825
8203
|
data: body,
|
|
7826
|
-
timeout: 6e4
|
|
8204
|
+
timeout: 6e4,
|
|
8205
|
+
validateStatus: () => true,
|
|
8206
|
+
withCredentials: this.useSession
|
|
7827
8207
|
});
|
|
7828
8208
|
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
7829
8209
|
return res.data;
|
|
7830
8210
|
}
|
|
7831
|
-
|
|
7832
|
-
|
|
7833
|
-
|
|
8211
|
+
/**
|
|
8212
|
+
* Make a request using billing session auth (for billing verification without wallet signature).
|
|
8213
|
+
* Forwards the billing_session cookie value via X-Billing-Session header.
|
|
8214
|
+
* Used for endpoints that need to verify subscription status when using session-based auth.
|
|
8215
|
+
*/
|
|
8216
|
+
async billingSessionAuthJsonRequest(path8, method, body) {
|
|
8217
|
+
if (!this.billingSessionId) {
|
|
8218
|
+
throw new Error("billingSessionId required for session-based billing auth");
|
|
7834
8219
|
}
|
|
7835
|
-
const headers = {
|
|
8220
|
+
const headers = {
|
|
8221
|
+
"Content-Type": "application/json",
|
|
8222
|
+
"X-Billing-Session": this.billingSessionId
|
|
8223
|
+
};
|
|
7836
8224
|
if (this.clientId) headers["x-client-id"] = this.clientId;
|
|
7837
|
-
const
|
|
7838
|
-
|
|
7839
|
-
|
|
7840
|
-
|
|
7841
|
-
|
|
8225
|
+
const res = await requestWithRetry({
|
|
8226
|
+
url: `${this.baseUrl}${path8}`,
|
|
8227
|
+
method,
|
|
8228
|
+
headers,
|
|
8229
|
+
data: body,
|
|
8230
|
+
timeout: 6e4,
|
|
8231
|
+
validateStatus: () => true,
|
|
8232
|
+
withCredentials: this.useSession
|
|
7842
8233
|
});
|
|
7843
|
-
|
|
7844
|
-
|
|
7845
|
-
|
|
8234
|
+
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
8235
|
+
return res.data;
|
|
8236
|
+
}
|
|
8237
|
+
/**
|
|
8238
|
+
* Make an authenticated request that can use session OR signature auth.
|
|
8239
|
+
* When useSession is true, relies on cookies for identity verification.
|
|
8240
|
+
* Used for endpoints that only need identity verification (not billing).
|
|
8241
|
+
*/
|
|
8242
|
+
async sessionOrSignatureTextRequest(path8) {
|
|
8243
|
+
const headers = {};
|
|
8244
|
+
if (this.clientId) headers["x-client-id"] = this.clientId;
|
|
8245
|
+
if (!this.useSession) {
|
|
8246
|
+
if (!this.walletClient?.account) {
|
|
8247
|
+
throw new Error("WalletClient with account required for authenticated requests");
|
|
8248
|
+
}
|
|
8249
|
+
const expiry = BigInt(Math.floor(Date.now() / 1e3) + 60);
|
|
8250
|
+
const { signature } = await calculateBillingAuthSignature({
|
|
8251
|
+
walletClient: this.walletClient,
|
|
8252
|
+
product: "compute",
|
|
8253
|
+
expiry
|
|
8254
|
+
});
|
|
8255
|
+
headers.Authorization = `Bearer ${signature}`;
|
|
8256
|
+
headers["X-eigenx-expiry"] = expiry.toString();
|
|
8257
|
+
headers["X-Account"] = this.address;
|
|
8258
|
+
}
|
|
7846
8259
|
const res = await requestWithRetry({
|
|
7847
8260
|
url: `${this.baseUrl}${path8}`,
|
|
7848
8261
|
method: "GET",
|
|
7849
8262
|
headers,
|
|
7850
8263
|
timeout: 6e4,
|
|
7851
|
-
responseType: "text"
|
|
8264
|
+
responseType: "text",
|
|
8265
|
+
validateStatus: () => true,
|
|
8266
|
+
withCredentials: this.useSession
|
|
7852
8267
|
});
|
|
7853
8268
|
if (res.status < 200 || res.status >= 300) throw buildApiHttpError(res);
|
|
7854
8269
|
return typeof res.data === "string" ? res.data : JSON.stringify(res.data);
|
|
@@ -8415,6 +8830,9 @@ function isSiweMessageNotYetValid(params) {
|
|
|
8415
8830
|
return /* @__PURE__ */ new Date() < params.notBefore;
|
|
8416
8831
|
}
|
|
8417
8832
|
|
|
8833
|
+
// src/client/common/auth/index.ts
|
|
8834
|
+
init_session();
|
|
8835
|
+
|
|
8418
8836
|
// src/client/common/utils/instance.ts
|
|
8419
8837
|
async function getCurrentInstanceType(preflightCtx, appID, logger, clientId) {
|
|
8420
8838
|
try {
|