@layr-labs/ecloud-sdk 0.2.0 → 0.2.2-dev
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/VERSION +2 -2
- package/dist/billing.cjs +48 -43
- package/dist/billing.cjs.map +1 -1
- package/dist/billing.d.cts +6 -3
- package/dist/billing.d.ts +6 -3
- package/dist/billing.js +519 -4
- package/dist/billing.js.map +1 -1
- package/dist/browser.cjs +5034 -0
- package/dist/browser.cjs.map +1 -0
- package/dist/browser.d.cts +239 -0
- package/dist/browser.d.ts +239 -0
- package/dist/browser.js +4924 -0
- package/dist/browser.js.map +1 -0
- package/dist/{compute-CF2HOXed.d.ts → compute-BYhSs8en.d.ts} +15 -96
- package/dist/{compute-CbmjA8kJ.d.cts → compute-Bpjb3hYD.d.cts} +15 -96
- package/dist/compute.cjs +875 -846
- 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 +7009 -8
- package/dist/compute.js.map +1 -1
- package/dist/helpers-CEvhJz7f.d.cts +742 -0
- package/dist/helpers-CQuBwQnu.d.ts +742 -0
- package/dist/index-DeQzn_yM.d.cts +739 -0
- package/dist/index-DeQzn_yM.d.ts +739 -0
- package/dist/index.cjs +1958 -1758
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +69 -414
- package/dist/index.d.ts +69 -414
- package/dist/index.js +7977 -134
- package/dist/index.js.map +1 -1
- package/package.json +17 -2
- package/dist/chunk-CA5Y4OVI.js +0 -744
- package/dist/chunk-CA5Y4OVI.js.map +0 -1
- package/dist/chunk-ZDXN2WKP.js +0 -434
- package/dist/chunk-ZDXN2WKP.js.map +0 -1
- package/dist/chunk-ZTLKZMSW.js +0 -6719
- package/dist/chunk-ZTLKZMSW.js.map +0 -1
- package/dist/index-D2QufVB9.d.cts +0 -342
- package/dist/index-D2QufVB9.d.ts +0 -342
package/dist/compute.cjs
CHANGED
|
@@ -39,100 +39,7 @@ __export(compute_exports, {
|
|
|
39
39
|
module.exports = __toCommonJS(compute_exports);
|
|
40
40
|
|
|
41
41
|
// src/client/modules/compute/app/index.ts
|
|
42
|
-
var
|
|
43
|
-
var import_accounts5 = require("viem/accounts");
|
|
44
|
-
|
|
45
|
-
// src/client/common/config/environment.ts
|
|
46
|
-
var SEPOLIA_CHAIN_ID = 11155111;
|
|
47
|
-
var MAINNET_CHAIN_ID = 1;
|
|
48
|
-
var CommonAddresses = {
|
|
49
|
-
ERC7702Delegator: "0x63c0c19a282a1b52b07dd5a65b58948a07dae32b"
|
|
50
|
-
};
|
|
51
|
-
var ChainAddresses = {
|
|
52
|
-
[MAINNET_CHAIN_ID]: {
|
|
53
|
-
PermissionController: "0x25E5F8B1E7aDf44518d35D5B2271f114e081f0E5"
|
|
54
|
-
},
|
|
55
|
-
[SEPOLIA_CHAIN_ID]: {
|
|
56
|
-
PermissionController: "0x44632dfBdCb6D3E21EF613B0ca8A6A0c618F5a37"
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
var ENVIRONMENTS = {
|
|
60
|
-
"sepolia-dev": {
|
|
61
|
-
name: "sepolia",
|
|
62
|
-
build: "dev",
|
|
63
|
-
appControllerAddress: "0xa86DC1C47cb2518327fB4f9A1627F51966c83B92",
|
|
64
|
-
permissionControllerAddress: ChainAddresses[SEPOLIA_CHAIN_ID].PermissionController,
|
|
65
|
-
erc7702DelegatorAddress: CommonAddresses.ERC7702Delegator,
|
|
66
|
-
kmsServerURL: "http://10.128.0.57:8080",
|
|
67
|
-
userApiServerURL: "https://userapi-compute-sepolia-dev.eigencloud.xyz",
|
|
68
|
-
defaultRPCURL: "https://ethereum-sepolia-rpc.publicnode.com"
|
|
69
|
-
},
|
|
70
|
-
sepolia: {
|
|
71
|
-
name: "sepolia",
|
|
72
|
-
build: "prod",
|
|
73
|
-
appControllerAddress: "0x0dd810a6ffba6a9820a10d97b659f07d8d23d4E2",
|
|
74
|
-
permissionControllerAddress: ChainAddresses[SEPOLIA_CHAIN_ID].PermissionController,
|
|
75
|
-
erc7702DelegatorAddress: CommonAddresses.ERC7702Delegator,
|
|
76
|
-
kmsServerURL: "http://10.128.15.203:8080",
|
|
77
|
-
userApiServerURL: "https://userapi-compute-sepolia-prod.eigencloud.xyz",
|
|
78
|
-
defaultRPCURL: "https://ethereum-sepolia-rpc.publicnode.com"
|
|
79
|
-
},
|
|
80
|
-
"mainnet-alpha": {
|
|
81
|
-
name: "mainnet-alpha",
|
|
82
|
-
build: "prod",
|
|
83
|
-
appControllerAddress: "0xc38d35Fc995e75342A21CBd6D770305b142Fbe67",
|
|
84
|
-
permissionControllerAddress: ChainAddresses[MAINNET_CHAIN_ID].PermissionController,
|
|
85
|
-
erc7702DelegatorAddress: CommonAddresses.ERC7702Delegator,
|
|
86
|
-
kmsServerURL: "http://10.128.0.2:8080",
|
|
87
|
-
userApiServerURL: "https://userapi-compute.eigencloud.xyz",
|
|
88
|
-
defaultRPCURL: "https://ethereum-rpc.publicnode.com"
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
var CHAIN_ID_TO_ENVIRONMENT = {
|
|
92
|
-
[SEPOLIA_CHAIN_ID.toString()]: "sepolia",
|
|
93
|
-
[MAINNET_CHAIN_ID.toString()]: "mainnet-alpha"
|
|
94
|
-
};
|
|
95
|
-
function getEnvironmentConfig(environment, chainID) {
|
|
96
|
-
const env = ENVIRONMENTS[environment];
|
|
97
|
-
if (!env) {
|
|
98
|
-
throw new Error(`Unknown environment: ${environment}`);
|
|
99
|
-
}
|
|
100
|
-
if (!isEnvironmentAvailable(environment)) {
|
|
101
|
-
throw new Error(
|
|
102
|
-
`Environment ${environment} is not available in this build type. Available environments: ${getAvailableEnvironments().join(", ")}`
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
if (chainID) {
|
|
106
|
-
const expectedEnv = CHAIN_ID_TO_ENVIRONMENT[chainID.toString()];
|
|
107
|
-
if (expectedEnv && expectedEnv !== environment) {
|
|
108
|
-
throw new Error(`Environment ${environment} does not match chain ID ${chainID}`);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
const resolvedChainID = chainID || (environment === "sepolia" || environment === "sepolia-dev" ? SEPOLIA_CHAIN_ID : MAINNET_CHAIN_ID);
|
|
112
|
-
return {
|
|
113
|
-
...env,
|
|
114
|
-
chainID: BigInt(resolvedChainID)
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
function getBuildType() {
|
|
118
|
-
const buildTimeType = true ? "prod"?.toLowerCase() : void 0;
|
|
119
|
-
const runtimeType = process.env.BUILD_TYPE?.toLowerCase();
|
|
120
|
-
const buildType = buildTimeType || runtimeType;
|
|
121
|
-
if (buildType === "dev") {
|
|
122
|
-
return "dev";
|
|
123
|
-
}
|
|
124
|
-
return "prod";
|
|
125
|
-
}
|
|
126
|
-
function getAvailableEnvironments() {
|
|
127
|
-
const buildType = getBuildType();
|
|
128
|
-
if (buildType === "dev") {
|
|
129
|
-
return ["sepolia-dev"];
|
|
130
|
-
}
|
|
131
|
-
return ["sepolia", "mainnet-alpha"];
|
|
132
|
-
}
|
|
133
|
-
function isEnvironmentAvailable(environment) {
|
|
134
|
-
return getAvailableEnvironments().includes(environment);
|
|
135
|
-
}
|
|
42
|
+
var import_viem6 = require("viem");
|
|
136
43
|
|
|
137
44
|
// src/client/common/docker/build.ts
|
|
138
45
|
var child_process = __toESM(require("child_process"), 1);
|
|
@@ -1232,12 +1139,21 @@ function extractRegistryNameNoDocker(imageRef) {
|
|
|
1232
1139
|
return name;
|
|
1233
1140
|
}
|
|
1234
1141
|
|
|
1235
|
-
// src/client/common/contract/caller.ts
|
|
1236
|
-
var import_accounts2 = require("viem/accounts");
|
|
1237
|
-
|
|
1238
1142
|
// src/client/common/contract/eip7702.ts
|
|
1239
1143
|
var import_viem = require("viem");
|
|
1240
1144
|
|
|
1145
|
+
// src/client/common/types/index.ts
|
|
1146
|
+
var noopLogger = {
|
|
1147
|
+
debug: () => {
|
|
1148
|
+
},
|
|
1149
|
+
info: () => {
|
|
1150
|
+
},
|
|
1151
|
+
warn: () => {
|
|
1152
|
+
},
|
|
1153
|
+
error: () => {
|
|
1154
|
+
}
|
|
1155
|
+
};
|
|
1156
|
+
|
|
1241
1157
|
// src/client/common/abis/ERC7702Delegator.json
|
|
1242
1158
|
var ERC7702Delegator_default = [
|
|
1243
1159
|
{
|
|
@@ -2323,7 +2239,7 @@ async function checkERC7702Delegation(publicClient, account, delegatorAddress) {
|
|
|
2323
2239
|
const expectedCode = `0xef0100${delegatorAddress.slice(2)}`;
|
|
2324
2240
|
return code.toLowerCase() === expectedCode.toLowerCase();
|
|
2325
2241
|
}
|
|
2326
|
-
async function executeBatch(options, logger) {
|
|
2242
|
+
async function executeBatch(options, logger = noopLogger) {
|
|
2327
2243
|
const { walletClient, publicClient, environmentConfig, executions, pendingMessage, gas } = options;
|
|
2328
2244
|
const account = walletClient.account;
|
|
2329
2245
|
if (!account) {
|
|
@@ -2347,11 +2263,12 @@ async function executeBatch(options, logger) {
|
|
|
2347
2263
|
});
|
|
2348
2264
|
const chainId = await publicClient.getChainId();
|
|
2349
2265
|
const authorizationNonce = transactionNonce + 1;
|
|
2266
|
+
logger.debug("Using wallet client signing for EIP-7702 authorization");
|
|
2350
2267
|
const signedAuthorization = await walletClient.signAuthorization({
|
|
2351
|
-
account,
|
|
2268
|
+
account: account.address,
|
|
2352
2269
|
contractAddress: environmentConfig.erc7702DelegatorAddress,
|
|
2353
|
-
chainId
|
|
2354
|
-
nonce: authorizationNonce
|
|
2270
|
+
chainId,
|
|
2271
|
+
nonce: Number(authorizationNonce)
|
|
2355
2272
|
});
|
|
2356
2273
|
authorizationList = [signedAuthorization];
|
|
2357
2274
|
}
|
|
@@ -2406,57 +2323,15 @@ async function executeBatch(options, logger) {
|
|
|
2406
2323
|
}
|
|
2407
2324
|
|
|
2408
2325
|
// src/client/common/contract/caller.ts
|
|
2409
|
-
var
|
|
2410
|
-
var import_utils = require("viem/utils");
|
|
2411
|
-
var import_accounts3 = require("viem/accounts");
|
|
2412
|
-
|
|
2413
|
-
// src/client/common/utils/logger.ts
|
|
2414
|
-
var defaultLogger = {
|
|
2415
|
-
info: (...args) => console.info(...args),
|
|
2416
|
-
warn: (...args) => console.warn(...args),
|
|
2417
|
-
error: (...args) => console.error(...args),
|
|
2418
|
-
debug: (...args) => console.debug(...args)
|
|
2419
|
-
};
|
|
2420
|
-
var getLogger = (verbose) => ({
|
|
2421
|
-
info: (...args) => console.info(...args),
|
|
2422
|
-
warn: (...args) => console.warn(...args),
|
|
2423
|
-
error: (...args) => console.error(...args),
|
|
2424
|
-
debug: (...args) => verbose && console.debug(...args)
|
|
2425
|
-
});
|
|
2426
|
-
|
|
2427
|
-
// src/client/common/utils/userapi.ts
|
|
2428
|
-
var import_axios = __toESM(require("axios"), 1);
|
|
2429
|
-
var import_form_data = __toESM(require("form-data"), 1);
|
|
2430
|
-
var import_viem4 = require("viem");
|
|
2431
|
-
|
|
2432
|
-
// src/client/common/utils/auth.ts
|
|
2433
|
-
var import_viem2 = require("viem");
|
|
2434
|
-
var APP_CONTROLLER_ABI = (0, import_viem2.parseAbi)([
|
|
2435
|
-
"function calculateApiPermissionDigestHash(bytes4 permission, uint256 expiry) view returns (bytes32)"
|
|
2436
|
-
]);
|
|
2437
|
-
async function calculatePermissionSignature(options) {
|
|
2438
|
-
const { permission, expiry, appControllerAddress, publicClient, account } = options;
|
|
2439
|
-
const digest = await publicClient.readContract({
|
|
2440
|
-
address: appControllerAddress,
|
|
2441
|
-
abi: APP_CONTROLLER_ABI,
|
|
2442
|
-
functionName: "calculateApiPermissionDigestHash",
|
|
2443
|
-
args: [permission, expiry]
|
|
2444
|
-
});
|
|
2445
|
-
const signature = await account.signMessage({
|
|
2446
|
-
message: { raw: digest }
|
|
2447
|
-
});
|
|
2448
|
-
return { signature, digest };
|
|
2449
|
-
}
|
|
2450
|
-
|
|
2451
|
-
// src/client/common/utils/userapi.ts
|
|
2452
|
-
var import_accounts = require("viem/accounts");
|
|
2326
|
+
var import_viem3 = require("viem");
|
|
2453
2327
|
|
|
2454
2328
|
// src/client/common/utils/helpers.ts
|
|
2455
|
-
var
|
|
2329
|
+
var import_viem2 = require("viem");
|
|
2456
2330
|
var import_chains2 = require("viem/chains");
|
|
2331
|
+
var import_accounts = require("viem/accounts");
|
|
2457
2332
|
function getChainFromID(chainID, fallback = import_chains2.sepolia) {
|
|
2458
2333
|
const id = Number(chainID);
|
|
2459
|
-
return (0,
|
|
2334
|
+
return (0, import_viem2.extractChain)({ chains: SUPPORTED_CHAINS, id }) || fallback;
|
|
2460
2335
|
}
|
|
2461
2336
|
function addHexPrefix(value) {
|
|
2462
2337
|
return value.startsWith("0x") ? value : `0x${value}`;
|
|
@@ -2465,297 +2340,6 @@ function stripHexPrefix(value) {
|
|
|
2465
2340
|
return value.startsWith("0x") ? value.slice(2) : value;
|
|
2466
2341
|
}
|
|
2467
2342
|
|
|
2468
|
-
// src/client/common/utils/userapi.ts
|
|
2469
|
-
function isJsonObject(value) {
|
|
2470
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2471
|
-
}
|
|
2472
|
-
function readString(obj, key) {
|
|
2473
|
-
const v = obj[key];
|
|
2474
|
-
return typeof v === "string" ? v : void 0;
|
|
2475
|
-
}
|
|
2476
|
-
function readNumber(obj, key) {
|
|
2477
|
-
const v = obj[key];
|
|
2478
|
-
return typeof v === "number" && Number.isFinite(v) ? v : void 0;
|
|
2479
|
-
}
|
|
2480
|
-
var MAX_ADDRESS_COUNT = 5;
|
|
2481
|
-
var CanViewAppLogsPermission = "0x2fd3f2fe";
|
|
2482
|
-
var CanViewSensitiveAppInfoPermission = "0x0e67b22f";
|
|
2483
|
-
var CanUpdateAppProfilePermission = "0x036fef61";
|
|
2484
|
-
function getDefaultClientId() {
|
|
2485
|
-
const version = true ? "0.2.0" : "0.0.0";
|
|
2486
|
-
return `ecloud-sdk/v${version}`;
|
|
2487
|
-
}
|
|
2488
|
-
var UserApiClient = class {
|
|
2489
|
-
constructor(config, privateKey, rpcUrl, clientId) {
|
|
2490
|
-
this.config = config;
|
|
2491
|
-
if (privateKey) {
|
|
2492
|
-
const privateKeyHex = addHexPrefix(privateKey);
|
|
2493
|
-
this.account = (0, import_accounts.privateKeyToAccount)(privateKeyHex);
|
|
2494
|
-
}
|
|
2495
|
-
this.rpcUrl = rpcUrl;
|
|
2496
|
-
this.clientId = clientId || getDefaultClientId();
|
|
2497
|
-
}
|
|
2498
|
-
async getInfos(appIDs, addressCount = 1) {
|
|
2499
|
-
const count = Math.min(addressCount, MAX_ADDRESS_COUNT);
|
|
2500
|
-
const endpoint = `${this.config.userApiServerURL}/info`;
|
|
2501
|
-
const url = `${endpoint}?${new URLSearchParams({ apps: appIDs.join(",") })}`;
|
|
2502
|
-
const res = await this.makeAuthenticatedRequest(url, CanViewSensitiveAppInfoPermission);
|
|
2503
|
-
const result = await res.json();
|
|
2504
|
-
return result.apps.map((app, i) => {
|
|
2505
|
-
const evmAddresses = app.addresses?.data?.evmAddresses?.slice(0, count) || [];
|
|
2506
|
-
const solanaAddresses = app.addresses?.data?.solanaAddresses?.slice(0, count) || [];
|
|
2507
|
-
return {
|
|
2508
|
-
address: appIDs[i],
|
|
2509
|
-
status: app.app_status,
|
|
2510
|
-
ip: app.ip,
|
|
2511
|
-
machineType: app.machine_type,
|
|
2512
|
-
profile: app.profile,
|
|
2513
|
-
metrics: app.metrics,
|
|
2514
|
-
evmAddresses,
|
|
2515
|
-
solanaAddresses
|
|
2516
|
-
};
|
|
2517
|
-
});
|
|
2518
|
-
}
|
|
2519
|
-
/**
|
|
2520
|
-
* Get app details from UserAPI (includes releases and build/provenance info when available).
|
|
2521
|
-
*
|
|
2522
|
-
* Endpoint: GET /apps/:appAddress
|
|
2523
|
-
*/
|
|
2524
|
-
async getApp(appAddress) {
|
|
2525
|
-
const endpoint = `${this.config.userApiServerURL}/apps/${appAddress}`;
|
|
2526
|
-
const res = await this.makeAuthenticatedRequest(endpoint);
|
|
2527
|
-
const raw = await res.json();
|
|
2528
|
-
if (!isJsonObject(raw)) {
|
|
2529
|
-
throw new Error("Unexpected /apps/:id response: expected object");
|
|
2530
|
-
}
|
|
2531
|
-
const id = readString(raw, "id");
|
|
2532
|
-
if (!id) {
|
|
2533
|
-
throw new Error("Unexpected /apps/:id response: missing 'id'");
|
|
2534
|
-
}
|
|
2535
|
-
const releasesRaw = raw.releases;
|
|
2536
|
-
const releases = Array.isArray(releasesRaw) ? releasesRaw.map((r) => transformAppRelease(r)).filter((r) => !!r) : [];
|
|
2537
|
-
return {
|
|
2538
|
-
id,
|
|
2539
|
-
creator: readString(raw, "creator"),
|
|
2540
|
-
contractStatus: readString(raw, "contract_status") ?? readString(raw, "contractStatus"),
|
|
2541
|
-
releases
|
|
2542
|
-
};
|
|
2543
|
-
}
|
|
2544
|
-
/**
|
|
2545
|
-
* Get available SKUs (instance types) from UserAPI
|
|
2546
|
-
*/
|
|
2547
|
-
async getSKUs() {
|
|
2548
|
-
const endpoint = `${this.config.userApiServerURL}/skus`;
|
|
2549
|
-
const response = await this.makeAuthenticatedRequest(endpoint);
|
|
2550
|
-
const result = await response.json();
|
|
2551
|
-
return {
|
|
2552
|
-
skus: result.skus || result.SKUs || []
|
|
2553
|
-
};
|
|
2554
|
-
}
|
|
2555
|
-
/**
|
|
2556
|
-
* Get logs for an app
|
|
2557
|
-
*/
|
|
2558
|
-
async getLogs(appID) {
|
|
2559
|
-
const endpoint = `${this.config.userApiServerURL}/logs/${appID}`;
|
|
2560
|
-
const response = await this.makeAuthenticatedRequest(endpoint, CanViewAppLogsPermission);
|
|
2561
|
-
return await response.text();
|
|
2562
|
-
}
|
|
2563
|
-
/**
|
|
2564
|
-
* Get statuses for apps
|
|
2565
|
-
*/
|
|
2566
|
-
async getStatuses(appIDs) {
|
|
2567
|
-
const endpoint = `${this.config.userApiServerURL}/status`;
|
|
2568
|
-
const url = `${endpoint}?${new URLSearchParams({ apps: appIDs.join(",") })}`;
|
|
2569
|
-
const response = await this.makeAuthenticatedRequest(url);
|
|
2570
|
-
const result = await response.json();
|
|
2571
|
-
const apps = result.apps || result.Apps || [];
|
|
2572
|
-
return apps.map((app, i) => ({
|
|
2573
|
-
address: app.address || appIDs[i],
|
|
2574
|
-
status: app.status || app.Status || ""
|
|
2575
|
-
}));
|
|
2576
|
-
}
|
|
2577
|
-
/**
|
|
2578
|
-
* Upload app profile information with optional image
|
|
2579
|
-
*/
|
|
2580
|
-
async uploadAppProfile(appAddress, name, website, description, xURL, imagePath) {
|
|
2581
|
-
const endpoint = `${this.config.userApiServerURL}/apps/${appAddress}/profile`;
|
|
2582
|
-
const formData = new import_form_data.default();
|
|
2583
|
-
formData.append("name", name);
|
|
2584
|
-
if (website) {
|
|
2585
|
-
formData.append("website", website);
|
|
2586
|
-
}
|
|
2587
|
-
if (description) {
|
|
2588
|
-
formData.append("description", description);
|
|
2589
|
-
}
|
|
2590
|
-
if (xURL) {
|
|
2591
|
-
formData.append("xURL", xURL);
|
|
2592
|
-
}
|
|
2593
|
-
if (imagePath) {
|
|
2594
|
-
const fs8 = await import("fs");
|
|
2595
|
-
const path7 = await import("path");
|
|
2596
|
-
const fileName = path7.basename(imagePath);
|
|
2597
|
-
const fileBuffer = fs8.readFileSync(imagePath);
|
|
2598
|
-
formData.append("image", fileBuffer, fileName);
|
|
2599
|
-
}
|
|
2600
|
-
const headers = {
|
|
2601
|
-
"x-client-id": this.clientId,
|
|
2602
|
-
...formData.getHeaders()
|
|
2603
|
-
};
|
|
2604
|
-
if (this.account) {
|
|
2605
|
-
const expiry = BigInt(Math.floor(Date.now() / 1e3) + 5 * 60);
|
|
2606
|
-
const authHeaders = await this.generateAuthHeaders(CanUpdateAppProfilePermission, expiry);
|
|
2607
|
-
Object.assign(headers, authHeaders);
|
|
2608
|
-
}
|
|
2609
|
-
try {
|
|
2610
|
-
const response = await import_axios.default.post(endpoint, formData, {
|
|
2611
|
-
headers,
|
|
2612
|
-
maxRedirects: 0,
|
|
2613
|
-
validateStatus: () => true,
|
|
2614
|
-
// Don't throw on any status
|
|
2615
|
-
maxContentLength: Infinity,
|
|
2616
|
-
// Allow large file uploads
|
|
2617
|
-
maxBodyLength: Infinity
|
|
2618
|
-
// Allow large file uploads
|
|
2619
|
-
});
|
|
2620
|
-
const status = response.status;
|
|
2621
|
-
if (status !== 200 && status !== 201) {
|
|
2622
|
-
const body = typeof response.data === "string" ? response.data : JSON.stringify(response.data);
|
|
2623
|
-
if (status === 403 && body.includes("Cloudflare") && body.includes("challenge-platform")) {
|
|
2624
|
-
throw new Error(
|
|
2625
|
-
`Cloudflare protection is blocking the request. This is likely due to bot detection.
|
|
2626
|
-
Status: ${status}`
|
|
2627
|
-
);
|
|
2628
|
-
}
|
|
2629
|
-
throw new Error(
|
|
2630
|
-
`UserAPI request failed: ${status} ${status >= 200 && status < 300 ? "OK" : "Error"} - ${body.substring(0, 500)}${body.length > 500 ? "..." : ""}`
|
|
2631
|
-
);
|
|
2632
|
-
}
|
|
2633
|
-
return response.data;
|
|
2634
|
-
} catch (error) {
|
|
2635
|
-
if (error.message?.includes("fetch failed") || error.message?.includes("ECONNREFUSED") || error.message?.includes("ENOTFOUND") || error.cause) {
|
|
2636
|
-
const cause = error.cause?.message || error.cause || error.message;
|
|
2637
|
-
throw new Error(
|
|
2638
|
-
`Failed to connect to UserAPI at ${endpoint}: ${cause}
|
|
2639
|
-
Please check:
|
|
2640
|
-
1. Your internet connection
|
|
2641
|
-
2. The API server is accessible: ${this.config.userApiServerURL}
|
|
2642
|
-
3. Firewall/proxy settings`
|
|
2643
|
-
);
|
|
2644
|
-
}
|
|
2645
|
-
throw error;
|
|
2646
|
-
}
|
|
2647
|
-
}
|
|
2648
|
-
async makeAuthenticatedRequest(url, permission) {
|
|
2649
|
-
const headers = {
|
|
2650
|
-
"x-client-id": this.clientId
|
|
2651
|
-
};
|
|
2652
|
-
if (permission && this.account) {
|
|
2653
|
-
const expiry = BigInt(Math.floor(Date.now() / 1e3) + 5 * 60);
|
|
2654
|
-
const authHeaders = await this.generateAuthHeaders(permission, expiry);
|
|
2655
|
-
Object.assign(headers, authHeaders);
|
|
2656
|
-
}
|
|
2657
|
-
try {
|
|
2658
|
-
const response = await import_axios.default.get(url, {
|
|
2659
|
-
headers,
|
|
2660
|
-
maxRedirects: 0,
|
|
2661
|
-
validateStatus: () => true
|
|
2662
|
-
// Don't throw on any status
|
|
2663
|
-
});
|
|
2664
|
-
const status = response.status;
|
|
2665
|
-
const statusText = status >= 200 && status < 300 ? "OK" : "Error";
|
|
2666
|
-
if (status < 200 || status >= 300) {
|
|
2667
|
-
const body = typeof response.data === "string" ? response.data : JSON.stringify(response.data);
|
|
2668
|
-
throw new Error(`UserAPI request failed: ${status} ${statusText} - ${body}`);
|
|
2669
|
-
}
|
|
2670
|
-
return {
|
|
2671
|
-
json: async () => response.data,
|
|
2672
|
-
text: async () => typeof response.data === "string" ? response.data : JSON.stringify(response.data)
|
|
2673
|
-
};
|
|
2674
|
-
} catch (error) {
|
|
2675
|
-
if (error.message?.includes("fetch failed") || error.message?.includes("ECONNREFUSED") || error.message?.includes("ENOTFOUND") || error.cause) {
|
|
2676
|
-
const cause = error.cause?.message || error.cause || error.message;
|
|
2677
|
-
throw new Error(
|
|
2678
|
-
`Failed to connect to UserAPI at ${url}: ${cause}
|
|
2679
|
-
Please check:
|
|
2680
|
-
1. Your internet connection
|
|
2681
|
-
2. The API server is accessible: ${this.config.userApiServerURL}
|
|
2682
|
-
3. Firewall/proxy settings`
|
|
2683
|
-
);
|
|
2684
|
-
}
|
|
2685
|
-
throw error;
|
|
2686
|
-
}
|
|
2687
|
-
}
|
|
2688
|
-
/**
|
|
2689
|
-
* Generate authentication headers for UserAPI requests
|
|
2690
|
-
*/
|
|
2691
|
-
async generateAuthHeaders(permission, expiry) {
|
|
2692
|
-
if (!this.account) {
|
|
2693
|
-
throw new Error("Private key required for authenticated requests");
|
|
2694
|
-
}
|
|
2695
|
-
if (!this.rpcUrl) {
|
|
2696
|
-
throw new Error("RPC URL required for authenticated requests");
|
|
2697
|
-
}
|
|
2698
|
-
const chain = getChainFromID(this.config.chainID);
|
|
2699
|
-
const publicClient = (0, import_viem4.createPublicClient)({
|
|
2700
|
-
chain,
|
|
2701
|
-
transport: (0, import_viem4.http)(this.rpcUrl)
|
|
2702
|
-
});
|
|
2703
|
-
const { signature } = await calculatePermissionSignature({
|
|
2704
|
-
permission,
|
|
2705
|
-
expiry,
|
|
2706
|
-
appControllerAddress: this.config.appControllerAddress,
|
|
2707
|
-
publicClient,
|
|
2708
|
-
account: this.account
|
|
2709
|
-
});
|
|
2710
|
-
return {
|
|
2711
|
-
Authorization: `Bearer ${stripHexPrefix(signature)}`,
|
|
2712
|
-
"X-eigenx-expiry": expiry.toString()
|
|
2713
|
-
};
|
|
2714
|
-
}
|
|
2715
|
-
};
|
|
2716
|
-
function transformAppReleaseBuild(raw) {
|
|
2717
|
-
if (!isJsonObject(raw)) return void 0;
|
|
2718
|
-
const depsRaw = raw.dependencies;
|
|
2719
|
-
const deps = isJsonObject(depsRaw) ? Object.fromEntries(
|
|
2720
|
-
Object.entries(depsRaw).flatMap(([digest, depRaw]) => {
|
|
2721
|
-
const parsed = transformAppReleaseBuild(depRaw);
|
|
2722
|
-
return parsed ? [[digest, parsed]] : [];
|
|
2723
|
-
})
|
|
2724
|
-
) : void 0;
|
|
2725
|
-
return {
|
|
2726
|
-
buildId: readString(raw, "build_id") ?? readString(raw, "buildId"),
|
|
2727
|
-
billingAddress: readString(raw, "billing_address") ?? readString(raw, "billingAddress"),
|
|
2728
|
-
repoUrl: readString(raw, "repo_url") ?? readString(raw, "repoUrl"),
|
|
2729
|
-
gitRef: readString(raw, "git_ref") ?? readString(raw, "gitRef"),
|
|
2730
|
-
status: readString(raw, "status"),
|
|
2731
|
-
buildType: readString(raw, "build_type") ?? readString(raw, "buildType"),
|
|
2732
|
-
imageName: readString(raw, "image_name") ?? readString(raw, "imageName"),
|
|
2733
|
-
imageDigest: readString(raw, "image_digest") ?? readString(raw, "imageDigest"),
|
|
2734
|
-
imageUrl: readString(raw, "image_url") ?? readString(raw, "imageUrl"),
|
|
2735
|
-
provenanceJson: raw.provenance_json ?? raw.provenanceJson,
|
|
2736
|
-
provenanceSignature: readString(raw, "provenance_signature") ?? readString(raw, "provenanceSignature"),
|
|
2737
|
-
createdAt: readString(raw, "created_at") ?? readString(raw, "createdAt"),
|
|
2738
|
-
updatedAt: readString(raw, "updated_at") ?? readString(raw, "updatedAt"),
|
|
2739
|
-
errorMessage: readString(raw, "error_message") ?? readString(raw, "errorMessage"),
|
|
2740
|
-
dependencies: deps
|
|
2741
|
-
};
|
|
2742
|
-
}
|
|
2743
|
-
function transformAppRelease(raw) {
|
|
2744
|
-
if (!isJsonObject(raw)) return void 0;
|
|
2745
|
-
return {
|
|
2746
|
-
appId: readString(raw, "appId") ?? readString(raw, "app_id"),
|
|
2747
|
-
rmsReleaseId: readString(raw, "rmsReleaseId") ?? readString(raw, "rms_release_id"),
|
|
2748
|
-
imageDigest: readString(raw, "imageDigest") ?? readString(raw, "image_digest"),
|
|
2749
|
-
registryUrl: readString(raw, "registryUrl") ?? readString(raw, "registry_url"),
|
|
2750
|
-
publicEnv: readString(raw, "publicEnv") ?? readString(raw, "public_env"),
|
|
2751
|
-
encryptedEnv: readString(raw, "encryptedEnv") ?? readString(raw, "encrypted_env"),
|
|
2752
|
-
upgradeByTime: readNumber(raw, "upgradeByTime") ?? readNumber(raw, "upgrade_by_time"),
|
|
2753
|
-
createdAt: readString(raw, "createdAt") ?? readString(raw, "created_at"),
|
|
2754
|
-
createdAtBlock: readString(raw, "createdAtBlock") ?? readString(raw, "created_at_block"),
|
|
2755
|
-
build: raw.build ? transformAppReleaseBuild(raw.build) : void 0
|
|
2756
|
-
};
|
|
2757
|
-
}
|
|
2758
|
-
|
|
2759
2343
|
// src/client/common/abis/AppController.json
|
|
2760
2344
|
var AppController_default = [
|
|
2761
2345
|
{
|
|
@@ -4310,65 +3894,54 @@ function formatETH(wei) {
|
|
|
4310
3894
|
}
|
|
4311
3895
|
return trimmed;
|
|
4312
3896
|
}
|
|
4313
|
-
async function calculateAppID(
|
|
4314
|
-
const
|
|
4315
|
-
const
|
|
4316
|
-
const chain = getChainFromID(environmentConfig.chainID);
|
|
4317
|
-
const publicClient = (0, import_viem5.createPublicClient)({
|
|
4318
|
-
chain,
|
|
4319
|
-
transport: (0, import_viem5.http)(rpcUrl)
|
|
4320
|
-
});
|
|
4321
|
-
const saltHexString = Buffer.from(salt).toString("hex");
|
|
3897
|
+
async function calculateAppID(options) {
|
|
3898
|
+
const { publicClient, environmentConfig, ownerAddress, salt } = options;
|
|
3899
|
+
const saltHexString = (0, import_viem3.bytesToHex)(salt).slice(2);
|
|
4322
3900
|
const paddedSaltHex = saltHexString.padStart(64, "0");
|
|
4323
3901
|
const saltHex = `0x${paddedSaltHex}`;
|
|
4324
|
-
const accountAddress = typeof account.address === "string" ? account.address : account.address.toString();
|
|
4325
3902
|
const appID = await publicClient.readContract({
|
|
4326
3903
|
address: environmentConfig.appControllerAddress,
|
|
4327
3904
|
abi: AppController_default,
|
|
4328
3905
|
functionName: "calculateAppId",
|
|
4329
|
-
args: [
|
|
3906
|
+
args: [ownerAddress, saltHex]
|
|
4330
3907
|
});
|
|
4331
3908
|
return appID;
|
|
4332
3909
|
}
|
|
4333
|
-
async function prepareDeployBatch(options, logger) {
|
|
4334
|
-
const {
|
|
4335
|
-
const
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
chain,
|
|
4340
|
-
transport: (0, import_viem5.http)(rpcUrl)
|
|
4341
|
-
});
|
|
4342
|
-
const walletClient = (0, import_viem5.createWalletClient)({
|
|
4343
|
-
account,
|
|
4344
|
-
chain,
|
|
4345
|
-
transport: (0, import_viem5.http)(rpcUrl)
|
|
4346
|
-
});
|
|
3910
|
+
async function prepareDeployBatch(options, logger = noopLogger) {
|
|
3911
|
+
const { walletClient, publicClient, environmentConfig, salt, release, publicLogs } = options;
|
|
3912
|
+
const account = walletClient.account;
|
|
3913
|
+
if (!account) {
|
|
3914
|
+
throw new Error("WalletClient must have an account attached");
|
|
3915
|
+
}
|
|
4347
3916
|
logger.info("Calculating app ID...");
|
|
4348
|
-
const appId = await calculateAppID(
|
|
4349
|
-
|
|
3917
|
+
const appId = await calculateAppID({
|
|
3918
|
+
publicClient,
|
|
3919
|
+
environmentConfig,
|
|
3920
|
+
ownerAddress: account.address,
|
|
3921
|
+
salt
|
|
3922
|
+
});
|
|
4350
3923
|
logger.debug(`App ID calculated: ${appId}`);
|
|
4351
3924
|
logger.debug(`This address will be used for acceptAdmin call`);
|
|
4352
|
-
const saltHexString =
|
|
3925
|
+
const saltHexString = (0, import_viem3.bytesToHex)(salt).slice(2);
|
|
4353
3926
|
const paddedSaltHex = saltHexString.padStart(64, "0");
|
|
4354
3927
|
const saltHex = `0x${paddedSaltHex}`;
|
|
4355
3928
|
const releaseForViem = {
|
|
4356
3929
|
rmsRelease: {
|
|
4357
3930
|
artifacts: release.rmsRelease.artifacts.map((artifact) => ({
|
|
4358
|
-
digest: `0x${
|
|
3931
|
+
digest: `0x${(0, import_viem3.bytesToHex)(artifact.digest).slice(2).padStart(64, "0")}`,
|
|
4359
3932
|
registry: artifact.registry
|
|
4360
3933
|
})),
|
|
4361
3934
|
upgradeByTime: release.rmsRelease.upgradeByTime
|
|
4362
3935
|
},
|
|
4363
|
-
publicEnv:
|
|
4364
|
-
encryptedEnv:
|
|
3936
|
+
publicEnv: (0, import_viem3.bytesToHex)(release.publicEnv),
|
|
3937
|
+
encryptedEnv: (0, import_viem3.bytesToHex)(release.encryptedEnv)
|
|
4365
3938
|
};
|
|
4366
|
-
const createData = (0,
|
|
3939
|
+
const createData = (0, import_viem3.encodeFunctionData)({
|
|
4367
3940
|
abi: AppController_default,
|
|
4368
3941
|
functionName: "createApp",
|
|
4369
3942
|
args: [saltHex, releaseForViem]
|
|
4370
3943
|
});
|
|
4371
|
-
const acceptAdminData = (0,
|
|
3944
|
+
const acceptAdminData = (0, import_viem3.encodeFunctionData)({
|
|
4372
3945
|
abi: PermissionController_default,
|
|
4373
3946
|
functionName: "acceptAdmin",
|
|
4374
3947
|
args: [appId]
|
|
@@ -4386,7 +3959,7 @@ async function prepareDeployBatch(options, logger) {
|
|
|
4386
3959
|
}
|
|
4387
3960
|
];
|
|
4388
3961
|
if (publicLogs) {
|
|
4389
|
-
const anyoneCanViewLogsData = (0,
|
|
3962
|
+
const anyoneCanViewLogsData = (0, import_viem3.encodeFunctionData)({
|
|
4390
3963
|
abi: PermissionController_default,
|
|
4391
3964
|
functionName: "setAppointee",
|
|
4392
3965
|
args: [
|
|
@@ -4414,7 +3987,7 @@ async function prepareDeployBatch(options, logger) {
|
|
|
4414
3987
|
environmentConfig
|
|
4415
3988
|
};
|
|
4416
3989
|
}
|
|
4417
|
-
async function executeDeployBatch(data, context, gas, logger) {
|
|
3990
|
+
async function executeDeployBatch(data, context, gas, logger = noopLogger) {
|
|
4418
3991
|
const pendingMessage = "Deploying new app...";
|
|
4419
3992
|
const txHash = await executeBatch(
|
|
4420
3993
|
{
|
|
@@ -4429,18 +4002,8 @@ async function executeDeployBatch(data, context, gas, logger) {
|
|
|
4429
4002
|
);
|
|
4430
4003
|
return { appId: data.appId, txHash };
|
|
4431
4004
|
}
|
|
4432
|
-
async function deployApp(options, logger) {
|
|
4433
|
-
const prepared = await prepareDeployBatch(
|
|
4434
|
-
{
|
|
4435
|
-
privateKey: options.privateKey,
|
|
4436
|
-
rpcUrl: options.rpcUrl,
|
|
4437
|
-
environmentConfig: options.environmentConfig,
|
|
4438
|
-
salt: options.salt,
|
|
4439
|
-
release: options.release,
|
|
4440
|
-
publicLogs: options.publicLogs
|
|
4441
|
-
},
|
|
4442
|
-
logger
|
|
4443
|
-
);
|
|
4005
|
+
async function deployApp(options, logger = noopLogger) {
|
|
4006
|
+
const prepared = await prepareDeployBatch(options, logger);
|
|
4444
4007
|
const data = {
|
|
4445
4008
|
appId: prepared.appId,
|
|
4446
4009
|
salt: prepared.salt,
|
|
@@ -4455,41 +4018,29 @@ async function deployApp(options, logger) {
|
|
|
4455
4018
|
}
|
|
4456
4019
|
async function prepareUpgradeBatch(options) {
|
|
4457
4020
|
const {
|
|
4458
|
-
|
|
4459
|
-
|
|
4021
|
+
walletClient,
|
|
4022
|
+
publicClient,
|
|
4460
4023
|
environmentConfig,
|
|
4461
|
-
|
|
4024
|
+
appID,
|
|
4462
4025
|
release,
|
|
4463
4026
|
publicLogs,
|
|
4464
4027
|
needsPermissionChange
|
|
4465
4028
|
} = options;
|
|
4466
|
-
const privateKeyHex = addHexPrefix(privateKey);
|
|
4467
|
-
const account = (0, import_accounts2.privateKeyToAccount)(privateKeyHex);
|
|
4468
|
-
const chain = getChainFromID(environmentConfig.chainID);
|
|
4469
|
-
const publicClient = (0, import_viem5.createPublicClient)({
|
|
4470
|
-
chain,
|
|
4471
|
-
transport: (0, import_viem5.http)(rpcUrl)
|
|
4472
|
-
});
|
|
4473
|
-
const walletClient = (0, import_viem5.createWalletClient)({
|
|
4474
|
-
account,
|
|
4475
|
-
chain,
|
|
4476
|
-
transport: (0, import_viem5.http)(rpcUrl)
|
|
4477
|
-
});
|
|
4478
4029
|
const releaseForViem = {
|
|
4479
4030
|
rmsRelease: {
|
|
4480
4031
|
artifacts: release.rmsRelease.artifacts.map((artifact) => ({
|
|
4481
|
-
digest: `0x${
|
|
4032
|
+
digest: `0x${(0, import_viem3.bytesToHex)(artifact.digest).slice(2).padStart(64, "0")}`,
|
|
4482
4033
|
registry: artifact.registry
|
|
4483
4034
|
})),
|
|
4484
4035
|
upgradeByTime: release.rmsRelease.upgradeByTime
|
|
4485
4036
|
},
|
|
4486
|
-
publicEnv:
|
|
4487
|
-
encryptedEnv:
|
|
4037
|
+
publicEnv: (0, import_viem3.bytesToHex)(release.publicEnv),
|
|
4038
|
+
encryptedEnv: (0, import_viem3.bytesToHex)(release.encryptedEnv)
|
|
4488
4039
|
};
|
|
4489
|
-
const upgradeData = (0,
|
|
4040
|
+
const upgradeData = (0, import_viem3.encodeFunctionData)({
|
|
4490
4041
|
abi: AppController_default,
|
|
4491
4042
|
functionName: "upgradeApp",
|
|
4492
|
-
args: [
|
|
4043
|
+
args: [appID, releaseForViem]
|
|
4493
4044
|
});
|
|
4494
4045
|
const executions = [
|
|
4495
4046
|
{
|
|
@@ -4500,11 +4051,11 @@ async function prepareUpgradeBatch(options) {
|
|
|
4500
4051
|
];
|
|
4501
4052
|
if (needsPermissionChange) {
|
|
4502
4053
|
if (publicLogs) {
|
|
4503
|
-
const addLogsData = (0,
|
|
4054
|
+
const addLogsData = (0, import_viem3.encodeFunctionData)({
|
|
4504
4055
|
abi: PermissionController_default,
|
|
4505
4056
|
functionName: "setAppointee",
|
|
4506
4057
|
args: [
|
|
4507
|
-
|
|
4058
|
+
appID,
|
|
4508
4059
|
"0x493219d9949348178af1f58740655951a8cd110c",
|
|
4509
4060
|
// AnyoneCanCallAddress
|
|
4510
4061
|
"0x57ee1fb74c1087e26446abc4fb87fd8f07c43d8d",
|
|
@@ -4519,11 +4070,11 @@ async function prepareUpgradeBatch(options) {
|
|
|
4519
4070
|
callData: addLogsData
|
|
4520
4071
|
});
|
|
4521
4072
|
} else {
|
|
4522
|
-
const removeLogsData = (0,
|
|
4073
|
+
const removeLogsData = (0, import_viem3.encodeFunctionData)({
|
|
4523
4074
|
abi: PermissionController_default,
|
|
4524
4075
|
functionName: "removeAppointee",
|
|
4525
4076
|
args: [
|
|
4526
|
-
|
|
4077
|
+
appID,
|
|
4527
4078
|
"0x493219d9949348178af1f58740655951a8cd110c",
|
|
4528
4079
|
// AnyoneCanCallAddress
|
|
4529
4080
|
"0x57ee1fb74c1087e26446abc4fb87fd8f07c43d8d",
|
|
@@ -4540,14 +4091,14 @@ async function prepareUpgradeBatch(options) {
|
|
|
4540
4091
|
}
|
|
4541
4092
|
}
|
|
4542
4093
|
return {
|
|
4543
|
-
appId,
|
|
4094
|
+
appId: appID,
|
|
4544
4095
|
executions,
|
|
4545
4096
|
walletClient,
|
|
4546
4097
|
publicClient,
|
|
4547
4098
|
environmentConfig
|
|
4548
4099
|
};
|
|
4549
4100
|
}
|
|
4550
|
-
async function executeUpgradeBatch(data, context, gas, logger) {
|
|
4101
|
+
async function executeUpgradeBatch(data, context, gas, logger = noopLogger) {
|
|
4551
4102
|
const pendingMessage = `Upgrading app ${data.appId}...`;
|
|
4552
4103
|
const txHash = await executeBatch(
|
|
4553
4104
|
{
|
|
@@ -4562,16 +4113,8 @@ async function executeUpgradeBatch(data, context, gas, logger) {
|
|
|
4562
4113
|
);
|
|
4563
4114
|
return txHash;
|
|
4564
4115
|
}
|
|
4565
|
-
async function upgradeApp(options, logger) {
|
|
4566
|
-
const prepared = await prepareUpgradeBatch(
|
|
4567
|
-
privateKey: options.privateKey,
|
|
4568
|
-
rpcUrl: options.rpcUrl,
|
|
4569
|
-
environmentConfig: options.environmentConfig,
|
|
4570
|
-
appId: options.appId,
|
|
4571
|
-
release: options.release,
|
|
4572
|
-
publicLogs: options.publicLogs,
|
|
4573
|
-
needsPermissionChange: options.needsPermissionChange
|
|
4574
|
-
});
|
|
4116
|
+
async function upgradeApp(options, logger = noopLogger) {
|
|
4117
|
+
const prepared = await prepareUpgradeBatch(options);
|
|
4575
4118
|
const data = {
|
|
4576
4119
|
appId: prepared.appId,
|
|
4577
4120
|
executions: prepared.executions
|
|
@@ -4583,10 +4126,10 @@ async function upgradeApp(options, logger) {
|
|
|
4583
4126
|
};
|
|
4584
4127
|
return executeUpgradeBatch(data, context, options.gas, logger);
|
|
4585
4128
|
}
|
|
4586
|
-
async function sendAndWaitForTransaction(options, logger) {
|
|
4129
|
+
async function sendAndWaitForTransaction(options, logger = noopLogger) {
|
|
4587
4130
|
const {
|
|
4588
|
-
|
|
4589
|
-
|
|
4131
|
+
walletClient,
|
|
4132
|
+
publicClient,
|
|
4590
4133
|
environmentConfig,
|
|
4591
4134
|
to,
|
|
4592
4135
|
data,
|
|
@@ -4595,18 +4138,11 @@ async function sendAndWaitForTransaction(options, logger) {
|
|
|
4595
4138
|
txDescription,
|
|
4596
4139
|
gas
|
|
4597
4140
|
} = options;
|
|
4598
|
-
const
|
|
4599
|
-
|
|
4141
|
+
const account = walletClient.account;
|
|
4142
|
+
if (!account) {
|
|
4143
|
+
throw new Error("WalletClient must have an account attached");
|
|
4144
|
+
}
|
|
4600
4145
|
const chain = getChainFromID(environmentConfig.chainID);
|
|
4601
|
-
const publicClient = (0, import_viem5.createPublicClient)({
|
|
4602
|
-
chain,
|
|
4603
|
-
transport: (0, import_viem5.http)(rpcUrl)
|
|
4604
|
-
});
|
|
4605
|
-
const walletClient = (0, import_viem5.createWalletClient)({
|
|
4606
|
-
account,
|
|
4607
|
-
chain,
|
|
4608
|
-
transport: (0, import_viem5.http)(rpcUrl)
|
|
4609
|
-
});
|
|
4610
4146
|
if (pendingMessage) {
|
|
4611
4147
|
logger.info(`
|
|
4612
4148
|
${pendingMessage}`);
|
|
@@ -4617,7 +4153,10 @@ ${pendingMessage}`);
|
|
|
4617
4153
|
data,
|
|
4618
4154
|
value,
|
|
4619
4155
|
...gas?.maxFeePerGas && { maxFeePerGas: gas.maxFeePerGas },
|
|
4620
|
-
...gas?.maxPriorityFeePerGas && {
|
|
4156
|
+
...gas?.maxPriorityFeePerGas && {
|
|
4157
|
+
maxPriorityFeePerGas: gas.maxPriorityFeePerGas
|
|
4158
|
+
},
|
|
4159
|
+
chain
|
|
4621
4160
|
});
|
|
4622
4161
|
logger.info(`Transaction sent: ${hash}`);
|
|
4623
4162
|
const receipt = await publicClient.waitForTransactionReceipt({ hash });
|
|
@@ -4632,7 +4171,7 @@ ${pendingMessage}`);
|
|
|
4632
4171
|
} catch (callError) {
|
|
4633
4172
|
if (callError.data) {
|
|
4634
4173
|
try {
|
|
4635
|
-
const decoded = (0,
|
|
4174
|
+
const decoded = (0, import_viem3.decodeErrorResult)({
|
|
4636
4175
|
abi: AppController_default,
|
|
4637
4176
|
data: callError.data
|
|
4638
4177
|
});
|
|
@@ -4683,12 +4222,7 @@ function formatAppControllerError(decoded) {
|
|
|
4683
4222
|
return new Error(`contract error: ${errorName}`);
|
|
4684
4223
|
}
|
|
4685
4224
|
}
|
|
4686
|
-
async function getActiveAppCount(
|
|
4687
|
-
const chain = getChainFromID(environmentConfig.chainID);
|
|
4688
|
-
const publicClient = (0, import_viem5.createPublicClient)({
|
|
4689
|
-
chain,
|
|
4690
|
-
transport: (0, import_viem5.http)(rpcUrl)
|
|
4691
|
-
});
|
|
4225
|
+
async function getActiveAppCount(publicClient, environmentConfig, user) {
|
|
4692
4226
|
const count = await publicClient.readContract({
|
|
4693
4227
|
address: environmentConfig.appControllerAddress,
|
|
4694
4228
|
abi: AppController_default,
|
|
@@ -4697,12 +4231,7 @@ async function getActiveAppCount(rpcUrl, environmentConfig, user) {
|
|
|
4697
4231
|
});
|
|
4698
4232
|
return Number(count);
|
|
4699
4233
|
}
|
|
4700
|
-
async function getMaxActiveAppsPerUser(
|
|
4701
|
-
const chain = getChainFromID(environmentConfig.chainID);
|
|
4702
|
-
const publicClient = (0, import_viem5.createPublicClient)({
|
|
4703
|
-
chain,
|
|
4704
|
-
transport: (0, import_viem5.http)(rpcUrl)
|
|
4705
|
-
});
|
|
4234
|
+
async function getMaxActiveAppsPerUser(publicClient, environmentConfig, user) {
|
|
4706
4235
|
const quota = await publicClient.readContract({
|
|
4707
4236
|
address: environmentConfig.appControllerAddress,
|
|
4708
4237
|
abi: AppController_default,
|
|
@@ -4712,83 +4241,550 @@ async function getMaxActiveAppsPerUser(rpcUrl, environmentConfig, user) {
|
|
|
4712
4241
|
return Number(quota);
|
|
4713
4242
|
}
|
|
4714
4243
|
async function isDelegated(options) {
|
|
4715
|
-
const {
|
|
4716
|
-
const privateKeyHex = addHexPrefix(privateKey);
|
|
4717
|
-
const account = (0, import_accounts2.privateKeyToAccount)(privateKeyHex);
|
|
4718
|
-
const chain = getChainFromID(environmentConfig.chainID);
|
|
4719
|
-
const publicClient = (0, import_viem5.createPublicClient)({
|
|
4720
|
-
chain,
|
|
4721
|
-
transport: (0, import_viem5.http)(rpcUrl)
|
|
4722
|
-
});
|
|
4244
|
+
const { publicClient, environmentConfig, address } = options;
|
|
4723
4245
|
return checkERC7702Delegation(
|
|
4724
4246
|
publicClient,
|
|
4725
|
-
|
|
4247
|
+
address,
|
|
4726
4248
|
environmentConfig.erc7702DelegatorAddress
|
|
4727
4249
|
);
|
|
4728
4250
|
}
|
|
4729
|
-
async function undelegate(options, logger) {
|
|
4730
|
-
const {
|
|
4731
|
-
const
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
|
|
4737
|
-
|
|
4738
|
-
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
|
|
4743
|
-
const
|
|
4744
|
-
|
|
4745
|
-
|
|
4746
|
-
|
|
4747
|
-
|
|
4748
|
-
|
|
4749
|
-
const
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
|
|
4753
|
-
|
|
4251
|
+
async function undelegate(options, logger = noopLogger) {
|
|
4252
|
+
const { walletClient, publicClient, environmentConfig } = options;
|
|
4253
|
+
const account = walletClient.account;
|
|
4254
|
+
if (!account) {
|
|
4255
|
+
throw new Error("WalletClient must have an account attached");
|
|
4256
|
+
}
|
|
4257
|
+
const chain = getChainFromID(environmentConfig.chainID);
|
|
4258
|
+
const transactionNonce = await publicClient.getTransactionCount({
|
|
4259
|
+
address: account.address,
|
|
4260
|
+
blockTag: "pending"
|
|
4261
|
+
});
|
|
4262
|
+
const chainId = await publicClient.getChainId();
|
|
4263
|
+
const authorizationNonce = BigInt(transactionNonce) + 1n;
|
|
4264
|
+
logger.debug("Signing undelegate authorization");
|
|
4265
|
+
const signedAuthorization = await walletClient.signAuthorization({
|
|
4266
|
+
contractAddress: "0x0000000000000000000000000000000000000000",
|
|
4267
|
+
chainId,
|
|
4268
|
+
nonce: Number(authorizationNonce),
|
|
4269
|
+
account
|
|
4270
|
+
});
|
|
4271
|
+
const authorizationList = [signedAuthorization];
|
|
4272
|
+
const hash = await walletClient.sendTransaction({
|
|
4273
|
+
account,
|
|
4274
|
+
to: account.address,
|
|
4275
|
+
// Send to self
|
|
4276
|
+
data: "0x",
|
|
4277
|
+
// Empty data
|
|
4278
|
+
value: 0n,
|
|
4279
|
+
authorizationList,
|
|
4280
|
+
chain
|
|
4281
|
+
});
|
|
4282
|
+
logger.info(`Transaction sent: ${hash}`);
|
|
4283
|
+
const receipt = await publicClient.waitForTransactionReceipt({ hash });
|
|
4284
|
+
if (receipt.status === "reverted") {
|
|
4285
|
+
logger.error(`Undelegate transaction (hash: ${hash}) reverted`);
|
|
4286
|
+
throw new Error(`Undelegate transaction (hash: ${hash}) reverted`);
|
|
4287
|
+
}
|
|
4288
|
+
return hash;
|
|
4289
|
+
}
|
|
4290
|
+
|
|
4291
|
+
// src/client/common/utils/userapi.ts
|
|
4292
|
+
var import_axios = __toESM(require("axios"), 1);
|
|
4293
|
+
|
|
4294
|
+
// src/client/common/utils/auth.ts
|
|
4295
|
+
var import_viem4 = require("viem");
|
|
4296
|
+
var APP_CONTROLLER_ABI = (0, import_viem4.parseAbi)([
|
|
4297
|
+
"function calculateApiPermissionDigestHash(bytes4 permission, uint256 expiry) view returns (bytes32)"
|
|
4298
|
+
]);
|
|
4299
|
+
async function calculatePermissionSignature(options) {
|
|
4300
|
+
const { permission, expiry, appControllerAddress, publicClient, walletClient } = options;
|
|
4301
|
+
const digest = await publicClient.readContract({
|
|
4302
|
+
address: appControllerAddress,
|
|
4303
|
+
abi: APP_CONTROLLER_ABI,
|
|
4304
|
+
functionName: "calculateApiPermissionDigestHash",
|
|
4305
|
+
args: [permission, expiry]
|
|
4306
|
+
});
|
|
4307
|
+
const account = walletClient.account;
|
|
4308
|
+
if (!account) {
|
|
4309
|
+
throw new Error("WalletClient must have an account attached");
|
|
4310
|
+
}
|
|
4311
|
+
const signature = await walletClient.signMessage({
|
|
4312
|
+
account,
|
|
4313
|
+
message: { raw: digest }
|
|
4314
|
+
});
|
|
4315
|
+
return { signature, digest };
|
|
4316
|
+
}
|
|
4317
|
+
|
|
4318
|
+
// src/client/common/auth/session.ts
|
|
4319
|
+
var SessionError = class extends Error {
|
|
4320
|
+
constructor(message, code, statusCode) {
|
|
4321
|
+
super(message);
|
|
4322
|
+
this.code = code;
|
|
4323
|
+
this.statusCode = statusCode;
|
|
4324
|
+
this.name = "SessionError";
|
|
4325
|
+
}
|
|
4326
|
+
};
|
|
4327
|
+
function stripHexPrefix2(hex) {
|
|
4328
|
+
return hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
4329
|
+
}
|
|
4330
|
+
async function parseErrorResponse(response) {
|
|
4331
|
+
try {
|
|
4332
|
+
const data = await response.json();
|
|
4333
|
+
return data.error || response.statusText;
|
|
4334
|
+
} catch {
|
|
4335
|
+
return response.statusText;
|
|
4336
|
+
}
|
|
4337
|
+
}
|
|
4338
|
+
async function loginToComputeApi(config, request) {
|
|
4339
|
+
let response;
|
|
4340
|
+
try {
|
|
4341
|
+
response = await fetch(`${config.baseUrl}/auth/siwe/login`, {
|
|
4342
|
+
method: "POST",
|
|
4343
|
+
credentials: "include",
|
|
4344
|
+
// Include cookies for session management
|
|
4345
|
+
headers: {
|
|
4346
|
+
"Content-Type": "application/json"
|
|
4347
|
+
},
|
|
4348
|
+
body: JSON.stringify({
|
|
4349
|
+
message: request.message,
|
|
4350
|
+
signature: stripHexPrefix2(request.signature)
|
|
4351
|
+
})
|
|
4352
|
+
});
|
|
4353
|
+
} catch (error) {
|
|
4354
|
+
throw new SessionError(
|
|
4355
|
+
`Network error connecting to ${config.baseUrl}: ${error instanceof Error ? error.message : String(error)}`,
|
|
4356
|
+
"NETWORK_ERROR"
|
|
4357
|
+
);
|
|
4358
|
+
}
|
|
4359
|
+
if (!response.ok) {
|
|
4360
|
+
const errorMessage = await parseErrorResponse(response);
|
|
4361
|
+
const status = response.status;
|
|
4362
|
+
if (status === 400) {
|
|
4363
|
+
if (errorMessage.toLowerCase().includes("siwe")) {
|
|
4364
|
+
throw new SessionError(`Invalid SIWE message: ${errorMessage}`, "INVALID_MESSAGE", status);
|
|
4365
|
+
}
|
|
4366
|
+
throw new SessionError(`Bad request: ${errorMessage}`, "INVALID_MESSAGE", status);
|
|
4367
|
+
}
|
|
4368
|
+
if (status === 401) {
|
|
4369
|
+
throw new SessionError(`Invalid signature: ${errorMessage}`, "INVALID_SIGNATURE", status);
|
|
4370
|
+
}
|
|
4371
|
+
throw new SessionError(`Login failed: ${errorMessage}`, "UNKNOWN", status);
|
|
4372
|
+
}
|
|
4373
|
+
const data = await response.json();
|
|
4374
|
+
return {
|
|
4375
|
+
success: data.success,
|
|
4376
|
+
address: data.address
|
|
4377
|
+
};
|
|
4378
|
+
}
|
|
4379
|
+
async function getComputeApiSession(config) {
|
|
4380
|
+
let response;
|
|
4381
|
+
try {
|
|
4382
|
+
response = await fetch(`${config.baseUrl}/auth/session`, {
|
|
4383
|
+
method: "GET",
|
|
4384
|
+
credentials: "include",
|
|
4385
|
+
// Include cookies for session management
|
|
4386
|
+
headers: {
|
|
4387
|
+
"Content-Type": "application/json"
|
|
4388
|
+
}
|
|
4389
|
+
});
|
|
4390
|
+
} catch {
|
|
4391
|
+
return {
|
|
4392
|
+
authenticated: false
|
|
4393
|
+
};
|
|
4394
|
+
}
|
|
4395
|
+
if (response.status === 401) {
|
|
4396
|
+
return {
|
|
4397
|
+
authenticated: false
|
|
4398
|
+
};
|
|
4399
|
+
}
|
|
4400
|
+
if (!response.ok) {
|
|
4401
|
+
const errorMessage = await parseErrorResponse(response);
|
|
4402
|
+
throw new SessionError(`Failed to get session: ${errorMessage}`, "UNKNOWN", response.status);
|
|
4403
|
+
}
|
|
4404
|
+
const data = await response.json();
|
|
4405
|
+
return {
|
|
4406
|
+
authenticated: data.authenticated,
|
|
4407
|
+
address: data.address,
|
|
4408
|
+
chainId: data.chain_id
|
|
4409
|
+
};
|
|
4410
|
+
}
|
|
4411
|
+
async function logoutFromComputeApi(config) {
|
|
4412
|
+
let response;
|
|
4413
|
+
try {
|
|
4414
|
+
response = await fetch(`${config.baseUrl}/auth/logout`, {
|
|
4415
|
+
method: "POST",
|
|
4416
|
+
credentials: "include",
|
|
4417
|
+
// Include cookies for session management
|
|
4418
|
+
headers: {
|
|
4419
|
+
"Content-Type": "application/json"
|
|
4420
|
+
}
|
|
4421
|
+
});
|
|
4422
|
+
} catch (error) {
|
|
4423
|
+
throw new SessionError(
|
|
4424
|
+
`Network error connecting to ${config.baseUrl}: ${error instanceof Error ? error.message : String(error)}`,
|
|
4425
|
+
"NETWORK_ERROR"
|
|
4426
|
+
);
|
|
4427
|
+
}
|
|
4428
|
+
if (response.status === 401) {
|
|
4429
|
+
return;
|
|
4430
|
+
}
|
|
4431
|
+
if (!response.ok) {
|
|
4432
|
+
const errorMessage = await parseErrorResponse(response);
|
|
4433
|
+
throw new SessionError(`Logout failed: ${errorMessage}`, "UNKNOWN", response.status);
|
|
4434
|
+
}
|
|
4435
|
+
}
|
|
4436
|
+
|
|
4437
|
+
// src/client/common/utils/userapi.ts
|
|
4438
|
+
function isJsonObject(value) {
|
|
4439
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4440
|
+
}
|
|
4441
|
+
function readString(obj, key) {
|
|
4442
|
+
const v = obj[key];
|
|
4443
|
+
return typeof v === "string" ? v : void 0;
|
|
4444
|
+
}
|
|
4445
|
+
function readNumber(obj, key) {
|
|
4446
|
+
const v = obj[key];
|
|
4447
|
+
return typeof v === "number" && Number.isFinite(v) ? v : void 0;
|
|
4448
|
+
}
|
|
4449
|
+
var MAX_ADDRESS_COUNT = 5;
|
|
4450
|
+
var CanViewAppLogsPermission = "0x2fd3f2fe";
|
|
4451
|
+
var CanViewSensitiveAppInfoPermission = "0x0e67b22f";
|
|
4452
|
+
var CanUpdateAppProfilePermission = "0x036fef61";
|
|
4453
|
+
function getDefaultClientId() {
|
|
4454
|
+
const version = true ? "0.2.2-dev" : "0.0.0";
|
|
4455
|
+
return `ecloud-sdk/v${version}`;
|
|
4456
|
+
}
|
|
4457
|
+
var UserApiClient = class {
|
|
4458
|
+
constructor(config, walletClient, publicClient, options) {
|
|
4459
|
+
this.config = config;
|
|
4460
|
+
this.walletClient = walletClient;
|
|
4461
|
+
this.publicClient = publicClient;
|
|
4462
|
+
this.clientId = options?.clientId || getDefaultClientId();
|
|
4463
|
+
this.useSession = options?.useSession ?? false;
|
|
4464
|
+
}
|
|
4465
|
+
/**
|
|
4466
|
+
* Get the address of the connected wallet
|
|
4467
|
+
*/
|
|
4468
|
+
get address() {
|
|
4469
|
+
const account = this.walletClient.account;
|
|
4470
|
+
if (!account) {
|
|
4471
|
+
throw new Error("WalletClient must have an account attached");
|
|
4472
|
+
}
|
|
4473
|
+
return account.address;
|
|
4474
|
+
}
|
|
4475
|
+
async getInfos(appIDs, addressCount = 1) {
|
|
4476
|
+
const count = Math.min(addressCount, MAX_ADDRESS_COUNT);
|
|
4477
|
+
const endpoint = `${this.config.userApiServerURL}/info`;
|
|
4478
|
+
const url = `${endpoint}?${new URLSearchParams({ apps: appIDs.join(",") })}`;
|
|
4479
|
+
const res = await this.makeAuthenticatedRequest(url, CanViewSensitiveAppInfoPermission);
|
|
4480
|
+
const result = await res.json();
|
|
4481
|
+
return result.apps.map((app, i) => {
|
|
4482
|
+
const evmAddresses = app.addresses?.data?.evmAddresses?.slice(0, count) || [];
|
|
4483
|
+
const solanaAddresses = app.addresses?.data?.solanaAddresses?.slice(0, count) || [];
|
|
4484
|
+
return {
|
|
4485
|
+
address: appIDs[i],
|
|
4486
|
+
status: app.app_status,
|
|
4487
|
+
ip: app.ip,
|
|
4488
|
+
machineType: app.machine_type,
|
|
4489
|
+
profile: app.profile,
|
|
4490
|
+
metrics: app.metrics,
|
|
4491
|
+
evmAddresses,
|
|
4492
|
+
solanaAddresses
|
|
4493
|
+
};
|
|
4494
|
+
});
|
|
4495
|
+
}
|
|
4496
|
+
/**
|
|
4497
|
+
* Get app details from UserAPI (includes releases and build/provenance info when available).
|
|
4498
|
+
*
|
|
4499
|
+
* Endpoint: GET /apps/:appAddress
|
|
4500
|
+
*/
|
|
4501
|
+
async getApp(appAddress) {
|
|
4502
|
+
const endpoint = `${this.config.userApiServerURL}/apps/${appAddress}`;
|
|
4503
|
+
const res = await this.makeAuthenticatedRequest(endpoint);
|
|
4504
|
+
const raw = await res.json();
|
|
4505
|
+
if (!isJsonObject(raw)) {
|
|
4506
|
+
throw new Error("Unexpected /apps/:id response: expected object");
|
|
4507
|
+
}
|
|
4508
|
+
const id = readString(raw, "id");
|
|
4509
|
+
if (!id) {
|
|
4510
|
+
throw new Error("Unexpected /apps/:id response: missing 'id'");
|
|
4511
|
+
}
|
|
4512
|
+
const releasesRaw = raw.releases;
|
|
4513
|
+
const releases = Array.isArray(releasesRaw) ? releasesRaw.map((r) => transformAppRelease(r)).filter((r) => !!r) : [];
|
|
4514
|
+
return {
|
|
4515
|
+
id,
|
|
4516
|
+
creator: readString(raw, "creator"),
|
|
4517
|
+
contractStatus: readString(raw, "contract_status") ?? readString(raw, "contractStatus"),
|
|
4518
|
+
releases
|
|
4519
|
+
};
|
|
4520
|
+
}
|
|
4521
|
+
/**
|
|
4522
|
+
* Get available SKUs (instance types) from UserAPI
|
|
4523
|
+
*/
|
|
4524
|
+
async getSKUs() {
|
|
4525
|
+
const endpoint = `${this.config.userApiServerURL}/skus`;
|
|
4526
|
+
const response = await this.makeAuthenticatedRequest(endpoint);
|
|
4527
|
+
const result = await response.json();
|
|
4528
|
+
return {
|
|
4529
|
+
skus: result.skus || result.SKUs || []
|
|
4530
|
+
};
|
|
4531
|
+
}
|
|
4532
|
+
/**
|
|
4533
|
+
* Get logs for an app
|
|
4534
|
+
*/
|
|
4535
|
+
async getLogs(appID) {
|
|
4536
|
+
const endpoint = `${this.config.userApiServerURL}/logs/${appID}`;
|
|
4537
|
+
const response = await this.makeAuthenticatedRequest(endpoint, CanViewAppLogsPermission);
|
|
4538
|
+
return await response.text();
|
|
4539
|
+
}
|
|
4540
|
+
/**
|
|
4541
|
+
* Get statuses for apps
|
|
4542
|
+
*/
|
|
4543
|
+
async getStatuses(appIDs) {
|
|
4544
|
+
const endpoint = `${this.config.userApiServerURL}/status`;
|
|
4545
|
+
const url = `${endpoint}?${new URLSearchParams({ apps: appIDs.join(",") })}`;
|
|
4546
|
+
const response = await this.makeAuthenticatedRequest(url);
|
|
4547
|
+
const result = await response.json();
|
|
4548
|
+
const apps = result.apps || result.Apps || [];
|
|
4549
|
+
return apps.map((app, i) => ({
|
|
4550
|
+
address: app.address || appIDs[i],
|
|
4551
|
+
status: app.app_status || app.App_Status || ""
|
|
4552
|
+
}));
|
|
4553
|
+
}
|
|
4554
|
+
/**
|
|
4555
|
+
* Upload app profile information with optional image
|
|
4556
|
+
*
|
|
4557
|
+
* @param appAddress - The app's contract address
|
|
4558
|
+
* @param name - Display name for the app
|
|
4559
|
+
* @param options - Optional fields including website, description, xURL, and image
|
|
4560
|
+
* @param options.image - Image file as Blob or File (browser: from input element, Node.js: new Blob([buffer]))
|
|
4561
|
+
* @param options.imageName - Filename for the image (required if image is provided)
|
|
4562
|
+
*/
|
|
4563
|
+
async uploadAppProfile(appAddress, name, options) {
|
|
4564
|
+
const endpoint = `${this.config.userApiServerURL}/apps/${appAddress}/profile`;
|
|
4565
|
+
const formData = new FormData();
|
|
4566
|
+
formData.append("name", name);
|
|
4567
|
+
if (options?.website) {
|
|
4568
|
+
formData.append("website", options.website);
|
|
4569
|
+
}
|
|
4570
|
+
if (options?.description) {
|
|
4571
|
+
formData.append("description", options.description);
|
|
4572
|
+
}
|
|
4573
|
+
if (options?.xURL) {
|
|
4574
|
+
formData.append("xURL", options.xURL);
|
|
4575
|
+
}
|
|
4576
|
+
if (options?.image) {
|
|
4577
|
+
const fileName = options.image instanceof File ? options.image.name : options.imageName || "image";
|
|
4578
|
+
formData.append("image", options.image, fileName);
|
|
4579
|
+
}
|
|
4580
|
+
const headers = {
|
|
4581
|
+
"x-client-id": this.clientId
|
|
4582
|
+
};
|
|
4583
|
+
if (!this.useSession) {
|
|
4584
|
+
const expiry = BigInt(Math.floor(Date.now() / 1e3) + 5 * 60);
|
|
4585
|
+
const authHeaders = await this.generateAuthHeaders(CanUpdateAppProfilePermission, expiry);
|
|
4586
|
+
Object.assign(headers, authHeaders);
|
|
4587
|
+
}
|
|
4588
|
+
try {
|
|
4589
|
+
const response = await import_axios.default.post(endpoint, formData, {
|
|
4590
|
+
headers,
|
|
4591
|
+
maxRedirects: 0,
|
|
4592
|
+
validateStatus: () => true,
|
|
4593
|
+
// Don't throw on any status
|
|
4594
|
+
maxContentLength: Infinity,
|
|
4595
|
+
// Allow large file uploads
|
|
4596
|
+
maxBodyLength: Infinity,
|
|
4597
|
+
// Allow large file uploads
|
|
4598
|
+
withCredentials: true
|
|
4599
|
+
// Include cookies for session auth
|
|
4600
|
+
});
|
|
4601
|
+
const status = response.status;
|
|
4602
|
+
if (status !== 200 && status !== 201) {
|
|
4603
|
+
const body = typeof response.data === "string" ? response.data : JSON.stringify(response.data);
|
|
4604
|
+
if (status === 403 && body.includes("Cloudflare") && body.includes("challenge-platform")) {
|
|
4605
|
+
throw new Error(
|
|
4606
|
+
`Cloudflare protection is blocking the request. This is likely due to bot detection.
|
|
4607
|
+
Status: ${status}`
|
|
4608
|
+
);
|
|
4609
|
+
}
|
|
4610
|
+
throw new Error(
|
|
4611
|
+
`UserAPI request failed: ${status} ${status >= 200 && status < 300 ? "OK" : "Error"} - ${body.substring(0, 500)}${body.length > 500 ? "..." : ""}`
|
|
4612
|
+
);
|
|
4613
|
+
}
|
|
4614
|
+
return response.data;
|
|
4615
|
+
} catch (error) {
|
|
4616
|
+
if (error.message?.includes("fetch failed") || error.message?.includes("ECONNREFUSED") || error.message?.includes("ENOTFOUND") || error.cause) {
|
|
4617
|
+
const cause = error.cause?.message || error.cause || error.message;
|
|
4618
|
+
throw new Error(
|
|
4619
|
+
`Failed to connect to UserAPI at ${endpoint}: ${cause}
|
|
4620
|
+
Please check:
|
|
4621
|
+
1. Your internet connection
|
|
4622
|
+
2. The API server is accessible: ${this.config.userApiServerURL}
|
|
4623
|
+
3. Firewall/proxy settings`
|
|
4624
|
+
);
|
|
4625
|
+
}
|
|
4626
|
+
throw error;
|
|
4627
|
+
}
|
|
4628
|
+
}
|
|
4629
|
+
async makeAuthenticatedRequest(url, permission) {
|
|
4630
|
+
const headers = {
|
|
4631
|
+
"x-client-id": this.clientId
|
|
4632
|
+
};
|
|
4633
|
+
if (permission && !this.useSession) {
|
|
4634
|
+
const expiry = BigInt(Math.floor(Date.now() / 1e3) + 5 * 60);
|
|
4635
|
+
const authHeaders = await this.generateAuthHeaders(permission, expiry);
|
|
4636
|
+
Object.assign(headers, authHeaders);
|
|
4637
|
+
}
|
|
4638
|
+
try {
|
|
4639
|
+
const response = await import_axios.default.get(url, {
|
|
4640
|
+
headers,
|
|
4641
|
+
maxRedirects: 0,
|
|
4642
|
+
validateStatus: () => true,
|
|
4643
|
+
// Don't throw on any status
|
|
4644
|
+
withCredentials: true
|
|
4645
|
+
// Include cookies for session auth
|
|
4646
|
+
});
|
|
4647
|
+
const status = response.status;
|
|
4648
|
+
const statusText = status >= 200 && status < 300 ? "OK" : "Error";
|
|
4649
|
+
if (status < 200 || status >= 300) {
|
|
4650
|
+
const body = typeof response.data === "string" ? response.data : JSON.stringify(response.data);
|
|
4651
|
+
throw new Error(`UserAPI request failed: ${status} ${statusText} - ${body}`);
|
|
4652
|
+
}
|
|
4653
|
+
return {
|
|
4654
|
+
json: async () => response.data,
|
|
4655
|
+
text: async () => typeof response.data === "string" ? response.data : JSON.stringify(response.data)
|
|
4656
|
+
};
|
|
4657
|
+
} catch (error) {
|
|
4658
|
+
if (error.message?.includes("fetch failed") || error.message?.includes("ECONNREFUSED") || error.message?.includes("ENOTFOUND") || error.cause) {
|
|
4659
|
+
const cause = error.cause?.message || error.cause || error.message;
|
|
4660
|
+
throw new Error(
|
|
4661
|
+
`Failed to connect to UserAPI at ${url}: ${cause}
|
|
4662
|
+
Please check:
|
|
4663
|
+
1. Your internet connection
|
|
4664
|
+
2. The API server is accessible: ${this.config.userApiServerURL}
|
|
4665
|
+
3. Firewall/proxy settings`
|
|
4666
|
+
);
|
|
4667
|
+
}
|
|
4668
|
+
throw error;
|
|
4669
|
+
}
|
|
4670
|
+
}
|
|
4671
|
+
/**
|
|
4672
|
+
* Generate authentication headers for UserAPI requests
|
|
4673
|
+
*/
|
|
4674
|
+
async generateAuthHeaders(permission, expiry) {
|
|
4675
|
+
const { signature } = await calculatePermissionSignature({
|
|
4676
|
+
permission,
|
|
4677
|
+
expiry,
|
|
4678
|
+
appControllerAddress: this.config.appControllerAddress,
|
|
4679
|
+
publicClient: this.publicClient,
|
|
4680
|
+
walletClient: this.walletClient
|
|
4681
|
+
});
|
|
4682
|
+
return {
|
|
4683
|
+
Authorization: `Bearer ${stripHexPrefix(signature)}`,
|
|
4684
|
+
"X-eigenx-expiry": expiry.toString()
|
|
4685
|
+
};
|
|
4686
|
+
}
|
|
4687
|
+
// ==========================================================================
|
|
4688
|
+
// SIWE Session Management
|
|
4689
|
+
// ==========================================================================
|
|
4690
|
+
/**
|
|
4691
|
+
* Login to the compute API using SIWE (Sign-In with Ethereum)
|
|
4692
|
+
*
|
|
4693
|
+
* This establishes a session with the compute API by verifying the SIWE message
|
|
4694
|
+
* and signature. On success, a session cookie is set in the browser.
|
|
4695
|
+
*
|
|
4696
|
+
* @param request - Login request containing SIWE message and signature
|
|
4697
|
+
* @returns Login result with the authenticated address
|
|
4698
|
+
*
|
|
4699
|
+
* @example
|
|
4700
|
+
* ```typescript
|
|
4701
|
+
* import { createSiweMessage } from "@layr-labs/ecloud-sdk/browser";
|
|
4702
|
+
*
|
|
4703
|
+
* const { message } = createSiweMessage({
|
|
4704
|
+
* address: userAddress,
|
|
4705
|
+
* chainId: 11155111,
|
|
4706
|
+
* domain: window.location.host,
|
|
4707
|
+
* uri: window.location.origin,
|
|
4708
|
+
* });
|
|
4709
|
+
*
|
|
4710
|
+
* const signature = await signMessageAsync({ message });
|
|
4711
|
+
* const result = await client.siweLogin({ message, signature });
|
|
4712
|
+
* ```
|
|
4713
|
+
*/
|
|
4714
|
+
async siweLogin(request) {
|
|
4715
|
+
return loginToComputeApi({ baseUrl: this.config.userApiServerURL }, request);
|
|
4716
|
+
}
|
|
4717
|
+
/**
|
|
4718
|
+
* Logout from the compute API
|
|
4719
|
+
*
|
|
4720
|
+
* This destroys the current session and clears the session cookie.
|
|
4721
|
+
*
|
|
4722
|
+
* @example
|
|
4723
|
+
* ```typescript
|
|
4724
|
+
* await client.siweLogout();
|
|
4725
|
+
* ```
|
|
4726
|
+
*/
|
|
4727
|
+
async siweLogout() {
|
|
4728
|
+
return logoutFromComputeApi({ baseUrl: this.config.userApiServerURL });
|
|
4729
|
+
}
|
|
4730
|
+
/**
|
|
4731
|
+
* Get the current SIWE session status from the compute API
|
|
4732
|
+
*
|
|
4733
|
+
* @returns Session information including authentication status and address
|
|
4734
|
+
*
|
|
4735
|
+
* @example
|
|
4736
|
+
* ```typescript
|
|
4737
|
+
* const session = await client.getSiweSession();
|
|
4738
|
+
* if (session.authenticated) {
|
|
4739
|
+
* console.log(`Logged in as ${session.address}`);
|
|
4740
|
+
* }
|
|
4741
|
+
* ```
|
|
4742
|
+
*/
|
|
4743
|
+
async getSiweSession() {
|
|
4744
|
+
return getComputeApiSession({ baseUrl: this.config.userApiServerURL });
|
|
4745
|
+
}
|
|
4746
|
+
};
|
|
4747
|
+
function transformAppReleaseBuild(raw) {
|
|
4748
|
+
if (!isJsonObject(raw)) return void 0;
|
|
4749
|
+
const depsRaw = raw.dependencies;
|
|
4750
|
+
const deps = isJsonObject(depsRaw) ? Object.fromEntries(
|
|
4751
|
+
Object.entries(depsRaw).flatMap(([digest, depRaw]) => {
|
|
4752
|
+
const parsed = transformAppReleaseBuild(depRaw);
|
|
4753
|
+
return parsed ? [[digest, parsed]] : [];
|
|
4754
|
+
})
|
|
4755
|
+
) : void 0;
|
|
4756
|
+
return {
|
|
4757
|
+
buildId: readString(raw, "build_id") ?? readString(raw, "buildId"),
|
|
4758
|
+
billingAddress: readString(raw, "billing_address") ?? readString(raw, "billingAddress"),
|
|
4759
|
+
repoUrl: readString(raw, "repo_url") ?? readString(raw, "repoUrl"),
|
|
4760
|
+
gitRef: readString(raw, "git_ref") ?? readString(raw, "gitRef"),
|
|
4761
|
+
status: readString(raw, "status"),
|
|
4762
|
+
buildType: readString(raw, "build_type") ?? readString(raw, "buildType"),
|
|
4763
|
+
imageName: readString(raw, "image_name") ?? readString(raw, "imageName"),
|
|
4764
|
+
imageDigest: readString(raw, "image_digest") ?? readString(raw, "imageDigest"),
|
|
4765
|
+
imageUrl: readString(raw, "image_url") ?? readString(raw, "imageUrl"),
|
|
4766
|
+
provenanceJson: raw.provenance_json ?? raw.provenanceJson,
|
|
4767
|
+
provenanceSignature: readString(raw, "provenance_signature") ?? readString(raw, "provenanceSignature"),
|
|
4768
|
+
createdAt: readString(raw, "created_at") ?? readString(raw, "createdAt"),
|
|
4769
|
+
updatedAt: readString(raw, "updated_at") ?? readString(raw, "updatedAt"),
|
|
4770
|
+
errorMessage: readString(raw, "error_message") ?? readString(raw, "errorMessage"),
|
|
4771
|
+
dependencies: deps
|
|
4772
|
+
};
|
|
4773
|
+
}
|
|
4774
|
+
function transformAppRelease(raw) {
|
|
4775
|
+
if (!isJsonObject(raw)) return void 0;
|
|
4776
|
+
return {
|
|
4777
|
+
appId: readString(raw, "appId") ?? readString(raw, "app_id"),
|
|
4778
|
+
rmsReleaseId: readString(raw, "rmsReleaseId") ?? readString(raw, "rms_release_id"),
|
|
4779
|
+
imageDigest: readString(raw, "imageDigest") ?? readString(raw, "image_digest"),
|
|
4780
|
+
registryUrl: readString(raw, "registryUrl") ?? readString(raw, "registry_url"),
|
|
4781
|
+
publicEnv: readString(raw, "publicEnv") ?? readString(raw, "public_env"),
|
|
4782
|
+
encryptedEnv: readString(raw, "encryptedEnv") ?? readString(raw, "encrypted_env"),
|
|
4783
|
+
upgradeByTime: readNumber(raw, "upgradeByTime") ?? readNumber(raw, "upgrade_by_time"),
|
|
4784
|
+
createdAt: readString(raw, "createdAt") ?? readString(raw, "created_at"),
|
|
4785
|
+
createdAtBlock: readString(raw, "createdAtBlock") ?? readString(raw, "created_at_block"),
|
|
4786
|
+
build: raw.build ? transformAppReleaseBuild(raw.build) : void 0
|
|
4754
4787
|
};
|
|
4755
|
-
const sighash = (0, import_utils.hashAuthorization)({
|
|
4756
|
-
chainId: authorization.chainId,
|
|
4757
|
-
contractAddress: authorization.address,
|
|
4758
|
-
nonce: Number(authorization.nonce)
|
|
4759
|
-
});
|
|
4760
|
-
const sig = await (0, import_accounts3.sign)({
|
|
4761
|
-
hash: sighash,
|
|
4762
|
-
privateKey: privateKeyHex
|
|
4763
|
-
});
|
|
4764
|
-
const v = Number(sig.v);
|
|
4765
|
-
const yParity = v === 27 ? 0 : 1;
|
|
4766
|
-
const authorizationList = [
|
|
4767
|
-
{
|
|
4768
|
-
chainId: authorization.chainId,
|
|
4769
|
-
address: authorization.address,
|
|
4770
|
-
nonce: Number(authorization.nonce),
|
|
4771
|
-
r: sig.r,
|
|
4772
|
-
s: sig.s,
|
|
4773
|
-
yParity
|
|
4774
|
-
}
|
|
4775
|
-
];
|
|
4776
|
-
const hash = await walletClient.sendTransaction({
|
|
4777
|
-
account,
|
|
4778
|
-
to: account.address,
|
|
4779
|
-
// Send to self
|
|
4780
|
-
data: "0x",
|
|
4781
|
-
// Empty data
|
|
4782
|
-
value: 0n,
|
|
4783
|
-
authorizationList
|
|
4784
|
-
});
|
|
4785
|
-
logger.info(`Transaction sent: ${hash}`);
|
|
4786
|
-
const receipt = await publicClient.waitForTransactionReceipt({ hash });
|
|
4787
|
-
if (receipt.status === "reverted") {
|
|
4788
|
-
logger.error(`Undelegate transaction (hash: ${hash}) reverted`);
|
|
4789
|
-
throw new Error(`Undelegate transaction (hash: ${hash}) reverted`);
|
|
4790
|
-
}
|
|
4791
|
-
return hash;
|
|
4792
4788
|
}
|
|
4793
4789
|
|
|
4794
4790
|
// src/client/common/contract/watcher.ts
|
|
@@ -4796,8 +4792,8 @@ var WATCH_POLL_INTERVAL_SECONDS = 5;
|
|
|
4796
4792
|
var APP_STATUS_RUNNING = "Running";
|
|
4797
4793
|
var APP_STATUS_FAILED = "Failed";
|
|
4798
4794
|
async function watchUntilRunning(options, logger) {
|
|
4799
|
-
const {
|
|
4800
|
-
const userApiClient = new UserApiClient(environmentConfig,
|
|
4795
|
+
const { walletClient, publicClient, environmentConfig, appId } = options;
|
|
4796
|
+
const userApiClient = new UserApiClient(environmentConfig, walletClient, publicClient);
|
|
4801
4797
|
let initialStatus;
|
|
4802
4798
|
let initialIP;
|
|
4803
4799
|
let hasChanged = false;
|
|
@@ -4846,8 +4842,8 @@ async function watchUntilRunning(options, logger) {
|
|
|
4846
4842
|
}
|
|
4847
4843
|
var APP_STATUS_STOPPED = "Stopped";
|
|
4848
4844
|
async function watchUntilUpgradeComplete(options, logger) {
|
|
4849
|
-
const {
|
|
4850
|
-
const userApiClient = new UserApiClient(environmentConfig,
|
|
4845
|
+
const { walletClient, publicClient, environmentConfig, appId } = options;
|
|
4846
|
+
const userApiClient = new UserApiClient(environmentConfig, walletClient, publicClient);
|
|
4851
4847
|
let initialStatus;
|
|
4852
4848
|
let initialIP;
|
|
4853
4849
|
let hasChanged = false;
|
|
@@ -4910,7 +4906,7 @@ function sleep(ms) {
|
|
|
4910
4906
|
|
|
4911
4907
|
// src/client/common/utils/validation.ts
|
|
4912
4908
|
var import_fs = __toESM(require("fs"), 1);
|
|
4913
|
-
var
|
|
4909
|
+
var import_viem5 = require("viem");
|
|
4914
4910
|
function validateAppName(name) {
|
|
4915
4911
|
if (!name) {
|
|
4916
4912
|
throw new Error("App name cannot be empty");
|
|
@@ -4958,7 +4954,7 @@ function validateAppID(appID) {
|
|
|
4958
4954
|
throw new Error("App ID is required");
|
|
4959
4955
|
}
|
|
4960
4956
|
const normalized = typeof appID === "string" ? addHexPrefix(appID) : appID;
|
|
4961
|
-
if ((0,
|
|
4957
|
+
if ((0, import_viem5.isAddress)(normalized)) {
|
|
4962
4958
|
return normalized;
|
|
4963
4959
|
}
|
|
4964
4960
|
throw new Error(`Invalid app ID: '${appID}' is not a valid address`);
|
|
@@ -4993,68 +4989,142 @@ function validateResourceUsageMonitoring(resourceUsageMonitoring) {
|
|
|
4993
4989
|
}
|
|
4994
4990
|
}
|
|
4995
4991
|
|
|
4992
|
+
// src/client/common/config/environment.ts
|
|
4993
|
+
var SEPOLIA_CHAIN_ID = 11155111;
|
|
4994
|
+
var MAINNET_CHAIN_ID = 1;
|
|
4995
|
+
var CommonAddresses = {
|
|
4996
|
+
ERC7702Delegator: "0x63c0c19a282a1b52b07dd5a65b58948a07dae32b"
|
|
4997
|
+
};
|
|
4998
|
+
var ChainAddresses = {
|
|
4999
|
+
[MAINNET_CHAIN_ID]: {
|
|
5000
|
+
PermissionController: "0x25E5F8B1E7aDf44518d35D5B2271f114e081f0E5"
|
|
5001
|
+
},
|
|
5002
|
+
[SEPOLIA_CHAIN_ID]: {
|
|
5003
|
+
PermissionController: "0x44632dfBdCb6D3E21EF613B0ca8A6A0c618F5a37"
|
|
5004
|
+
}
|
|
5005
|
+
};
|
|
5006
|
+
var ENVIRONMENTS = {
|
|
5007
|
+
"sepolia-dev": {
|
|
5008
|
+
name: "sepolia",
|
|
5009
|
+
build: "dev",
|
|
5010
|
+
appControllerAddress: "0xa86DC1C47cb2518327fB4f9A1627F51966c83B92",
|
|
5011
|
+
permissionControllerAddress: ChainAddresses[SEPOLIA_CHAIN_ID].PermissionController,
|
|
5012
|
+
erc7702DelegatorAddress: CommonAddresses.ERC7702Delegator,
|
|
5013
|
+
kmsServerURL: "http://10.128.0.57:8080",
|
|
5014
|
+
userApiServerURL: "https://userapi-compute-sepolia-dev.eigencloud.xyz",
|
|
5015
|
+
defaultRPCURL: "https://ethereum-sepolia-rpc.publicnode.com"
|
|
5016
|
+
},
|
|
5017
|
+
sepolia: {
|
|
5018
|
+
name: "sepolia",
|
|
5019
|
+
build: "prod",
|
|
5020
|
+
appControllerAddress: "0x0dd810a6ffba6a9820a10d97b659f07d8d23d4E2",
|
|
5021
|
+
permissionControllerAddress: ChainAddresses[SEPOLIA_CHAIN_ID].PermissionController,
|
|
5022
|
+
erc7702DelegatorAddress: CommonAddresses.ERC7702Delegator,
|
|
5023
|
+
kmsServerURL: "http://10.128.15.203:8080",
|
|
5024
|
+
userApiServerURL: "https://userapi-compute-sepolia-prod.eigencloud.xyz",
|
|
5025
|
+
defaultRPCURL: "https://ethereum-sepolia-rpc.publicnode.com"
|
|
5026
|
+
},
|
|
5027
|
+
"mainnet-alpha": {
|
|
5028
|
+
name: "mainnet-alpha",
|
|
5029
|
+
build: "prod",
|
|
5030
|
+
appControllerAddress: "0xc38d35Fc995e75342A21CBd6D770305b142Fbe67",
|
|
5031
|
+
permissionControllerAddress: ChainAddresses[MAINNET_CHAIN_ID].PermissionController,
|
|
5032
|
+
erc7702DelegatorAddress: CommonAddresses.ERC7702Delegator,
|
|
5033
|
+
kmsServerURL: "http://10.128.0.2:8080",
|
|
5034
|
+
userApiServerURL: "https://userapi-compute.eigencloud.xyz",
|
|
5035
|
+
defaultRPCURL: "https://ethereum-rpc.publicnode.com"
|
|
5036
|
+
}
|
|
5037
|
+
};
|
|
5038
|
+
var CHAIN_ID_TO_ENVIRONMENT = {
|
|
5039
|
+
[SEPOLIA_CHAIN_ID.toString()]: "sepolia",
|
|
5040
|
+
[MAINNET_CHAIN_ID.toString()]: "mainnet-alpha"
|
|
5041
|
+
};
|
|
5042
|
+
function getEnvironmentConfig(environment, chainID) {
|
|
5043
|
+
const env = ENVIRONMENTS[environment];
|
|
5044
|
+
if (!env) {
|
|
5045
|
+
throw new Error(`Unknown environment: ${environment}`);
|
|
5046
|
+
}
|
|
5047
|
+
if (!isEnvironmentAvailable(environment)) {
|
|
5048
|
+
throw new Error(
|
|
5049
|
+
`Environment ${environment} is not available in this build type. Available environments: ${getAvailableEnvironments().join(", ")}`
|
|
5050
|
+
);
|
|
5051
|
+
}
|
|
5052
|
+
if (chainID) {
|
|
5053
|
+
const expectedEnv = CHAIN_ID_TO_ENVIRONMENT[chainID.toString()];
|
|
5054
|
+
if (expectedEnv && expectedEnv !== environment) {
|
|
5055
|
+
throw new Error(`Environment ${environment} does not match chain ID ${chainID}`);
|
|
5056
|
+
}
|
|
5057
|
+
}
|
|
5058
|
+
const resolvedChainID = chainID || (environment === "sepolia" || environment === "sepolia-dev" ? SEPOLIA_CHAIN_ID : MAINNET_CHAIN_ID);
|
|
5059
|
+
return {
|
|
5060
|
+
...env,
|
|
5061
|
+
chainID: BigInt(resolvedChainID)
|
|
5062
|
+
};
|
|
5063
|
+
}
|
|
5064
|
+
function getBuildType() {
|
|
5065
|
+
const buildTimeType = true ? "dev"?.toLowerCase() : void 0;
|
|
5066
|
+
const runtimeType = process.env.BUILD_TYPE?.toLowerCase();
|
|
5067
|
+
const buildType = buildTimeType || runtimeType;
|
|
5068
|
+
if (buildType === "dev") {
|
|
5069
|
+
return "dev";
|
|
5070
|
+
}
|
|
5071
|
+
return "prod";
|
|
5072
|
+
}
|
|
5073
|
+
function getAvailableEnvironments() {
|
|
5074
|
+
const buildType = getBuildType();
|
|
5075
|
+
if (buildType === "dev") {
|
|
5076
|
+
return ["sepolia-dev"];
|
|
5077
|
+
}
|
|
5078
|
+
return ["sepolia", "mainnet-alpha"];
|
|
5079
|
+
}
|
|
5080
|
+
function isEnvironmentAvailable(environment) {
|
|
5081
|
+
return getAvailableEnvironments().includes(environment);
|
|
5082
|
+
}
|
|
5083
|
+
|
|
4996
5084
|
// src/client/common/utils/preflight.ts
|
|
4997
|
-
var import_viem7 = require("viem");
|
|
4998
|
-
var import_accounts4 = require("viem/accounts");
|
|
4999
5085
|
async function doPreflightChecks(options, logger) {
|
|
5000
|
-
|
|
5001
|
-
const privateKey = await getPrivateKeyOrFail(options.privateKey);
|
|
5086
|
+
const { walletClient, publicClient } = options;
|
|
5002
5087
|
logger.debug("Determining environment...");
|
|
5003
5088
|
const environmentConfig = getEnvironmentConfig(options.environment || "sepolia");
|
|
5004
|
-
|
|
5005
|
-
if (!
|
|
5006
|
-
|
|
5007
|
-
}
|
|
5008
|
-
if (!rpcUrl) {
|
|
5009
|
-
throw new Error(
|
|
5010
|
-
`RPC URL is required. Provide via options.rpcUrl, RPC_URL env var, or ensure environment has default RPC URL`
|
|
5011
|
-
);
|
|
5089
|
+
const account = walletClient.account;
|
|
5090
|
+
if (!account) {
|
|
5091
|
+
throw new Error("WalletClient must have an account attached");
|
|
5012
5092
|
}
|
|
5013
|
-
logger.debug("
|
|
5014
|
-
const publicClient = (0, import_viem7.createPublicClient)({
|
|
5015
|
-
transport: (0, import_viem7.http)(rpcUrl)
|
|
5016
|
-
});
|
|
5093
|
+
logger.debug("Validating chain ID...");
|
|
5017
5094
|
try {
|
|
5018
5095
|
const chainID = await publicClient.getChainId();
|
|
5019
5096
|
if (BigInt(chainID) !== environmentConfig.chainID) {
|
|
5020
5097
|
throw new Error(`Chain ID mismatch: expected ${environmentConfig.chainID}, got ${chainID}`);
|
|
5021
5098
|
}
|
|
5022
5099
|
} catch (err) {
|
|
5023
|
-
throw new Error(
|
|
5100
|
+
throw new Error(
|
|
5101
|
+
`Cannot connect to ${environmentConfig.name} RPC at ${publicClient.transport.url}: ${err.message}`
|
|
5102
|
+
);
|
|
5024
5103
|
}
|
|
5025
|
-
const privateKeyHex = addHexPrefix(privateKey);
|
|
5026
|
-
const account = (0, import_accounts4.privateKeyToAccount)(privateKeyHex);
|
|
5027
|
-
const selfAddress = account.address;
|
|
5028
5104
|
return {
|
|
5029
|
-
|
|
5030
|
-
|
|
5105
|
+
walletClient,
|
|
5106
|
+
publicClient,
|
|
5031
5107
|
environmentConfig,
|
|
5032
|
-
account
|
|
5033
|
-
selfAddress
|
|
5108
|
+
selfAddress: account.address
|
|
5034
5109
|
};
|
|
5035
5110
|
}
|
|
5036
|
-
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
5043
|
-
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
|
|
5052
|
-
|
|
5053
|
-
const cleaned = stripHexPrefix(key);
|
|
5054
|
-
if (!/^[0-9a-fA-F]{64}$/.test(cleaned)) {
|
|
5055
|
-
throw new Error("Invalid private key format (must be 64 hex characters)");
|
|
5056
|
-
}
|
|
5057
|
-
}
|
|
5111
|
+
|
|
5112
|
+
// src/client/common/utils/logger.ts
|
|
5113
|
+
var defaultLogger = {
|
|
5114
|
+
info: (...args) => console.info(...args),
|
|
5115
|
+
warn: (...args) => console.warn(...args),
|
|
5116
|
+
error: (...args) => console.error(...args),
|
|
5117
|
+
debug: (...args) => console.debug(...args)
|
|
5118
|
+
};
|
|
5119
|
+
var getLogger = (verbose) => ({
|
|
5120
|
+
info: (...args) => console.info(...args),
|
|
5121
|
+
warn: (...args) => console.warn(...args),
|
|
5122
|
+
error: (...args) => console.error(...args),
|
|
5123
|
+
debug: (...args) => verbose && console.debug(...args)
|
|
5124
|
+
});
|
|
5125
|
+
|
|
5126
|
+
// src/client/common/utils/billingapi.ts
|
|
5127
|
+
var import_axios2 = __toESM(require("axios"), 1);
|
|
5058
5128
|
|
|
5059
5129
|
// src/client/common/telemetry/noop.ts
|
|
5060
5130
|
var NoopClient = class {
|
|
@@ -5262,7 +5332,9 @@ async function prepareDeployFromVerifiableBuild(options, logger = defaultLogger)
|
|
|
5262
5332
|
}
|
|
5263
5333
|
},
|
|
5264
5334
|
async () => {
|
|
5265
|
-
if (!options.
|
|
5335
|
+
if (!options.walletClient.account) {
|
|
5336
|
+
throw new Error("WalletClient must have an account attached");
|
|
5337
|
+
}
|
|
5266
5338
|
if (!options.imageRef) throw new Error("imageRef is required for deployment");
|
|
5267
5339
|
if (!options.imageDigest) throw new Error("imageDigest is required for deployment");
|
|
5268
5340
|
assertValidImageReference(options.imageRef);
|
|
@@ -5278,8 +5350,8 @@ async function prepareDeployFromVerifiableBuild(options, logger = defaultLogger)
|
|
|
5278
5350
|
logger.debug("Performing preflight checks...");
|
|
5279
5351
|
const preflightCtx = await doPreflightChecks(
|
|
5280
5352
|
{
|
|
5281
|
-
|
|
5282
|
-
|
|
5353
|
+
walletClient: options.walletClient,
|
|
5354
|
+
publicClient: options.publicClient,
|
|
5283
5355
|
environment: options.environment
|
|
5284
5356
|
},
|
|
5285
5357
|
logger
|
|
@@ -5289,12 +5361,12 @@ async function prepareDeployFromVerifiableBuild(options, logger = defaultLogger)
|
|
|
5289
5361
|
const salt = generateRandomSalt();
|
|
5290
5362
|
logger.debug(`Generated salt: ${Buffer.from(salt).toString("hex")}`);
|
|
5291
5363
|
logger.debug("Calculating app ID...");
|
|
5292
|
-
const appIDToBeDeployed = await calculateAppID(
|
|
5293
|
-
preflightCtx.
|
|
5294
|
-
|
|
5295
|
-
preflightCtx.
|
|
5364
|
+
const appIDToBeDeployed = await calculateAppID({
|
|
5365
|
+
publicClient: preflightCtx.publicClient,
|
|
5366
|
+
environmentConfig: preflightCtx.environmentConfig,
|
|
5367
|
+
ownerAddress: preflightCtx.selfAddress,
|
|
5296
5368
|
salt
|
|
5297
|
-
);
|
|
5369
|
+
});
|
|
5298
5370
|
logger.info(``);
|
|
5299
5371
|
logger.info(`App ID: ${appIDToBeDeployed}`);
|
|
5300
5372
|
logger.info(``);
|
|
@@ -5312,12 +5384,13 @@ async function prepareDeployFromVerifiableBuild(options, logger = defaultLogger)
|
|
|
5312
5384
|
logger.debug("Preparing deploy batch...");
|
|
5313
5385
|
const batch = await prepareDeployBatch(
|
|
5314
5386
|
{
|
|
5315
|
-
|
|
5316
|
-
|
|
5387
|
+
walletClient: preflightCtx.walletClient,
|
|
5388
|
+
publicClient: preflightCtx.publicClient,
|
|
5317
5389
|
environmentConfig: preflightCtx.environmentConfig,
|
|
5318
5390
|
salt,
|
|
5319
5391
|
release,
|
|
5320
|
-
publicLogs
|
|
5392
|
+
publicLogs,
|
|
5393
|
+
imageRef: options.imageRef
|
|
5321
5394
|
},
|
|
5322
5395
|
logger
|
|
5323
5396
|
);
|
|
@@ -5344,8 +5417,8 @@ async function prepareDeployFromVerifiableBuild(options, logger = defaultLogger)
|
|
|
5344
5417
|
);
|
|
5345
5418
|
}
|
|
5346
5419
|
function validateDeployOptions(options) {
|
|
5347
|
-
if (!options.
|
|
5348
|
-
throw new Error("
|
|
5420
|
+
if (!options.walletClient.account) {
|
|
5421
|
+
throw new Error("WalletClient must have an account attached");
|
|
5349
5422
|
}
|
|
5350
5423
|
if (!options.dockerfilePath && !options.imageRef) {
|
|
5351
5424
|
throw new Error("Either dockerfilePath or imageRef is required for deployment");
|
|
@@ -5384,8 +5457,8 @@ async function deploy(options, logger = defaultLogger) {
|
|
|
5384
5457
|
logger.debug("Performing preflight checks...");
|
|
5385
5458
|
const preflightCtx = await doPreflightChecks(
|
|
5386
5459
|
{
|
|
5387
|
-
|
|
5388
|
-
|
|
5460
|
+
walletClient: options.walletClient,
|
|
5461
|
+
publicClient: options.publicClient,
|
|
5389
5462
|
environment: options.environment
|
|
5390
5463
|
},
|
|
5391
5464
|
logger
|
|
@@ -5402,12 +5475,12 @@ async function deploy(options, logger = defaultLogger) {
|
|
|
5402
5475
|
const salt = generateRandomSalt();
|
|
5403
5476
|
logger.debug(`Generated salt: ${Buffer.from(salt).toString("hex")}`);
|
|
5404
5477
|
logger.debug("Calculating app ID...");
|
|
5405
|
-
const appIDToBeDeployed = await calculateAppID(
|
|
5406
|
-
preflightCtx.
|
|
5407
|
-
|
|
5408
|
-
preflightCtx.
|
|
5478
|
+
const appIDToBeDeployed = await calculateAppID({
|
|
5479
|
+
publicClient: preflightCtx.publicClient,
|
|
5480
|
+
environmentConfig: preflightCtx.environmentConfig,
|
|
5481
|
+
ownerAddress: preflightCtx.selfAddress,
|
|
5409
5482
|
salt
|
|
5410
|
-
);
|
|
5483
|
+
});
|
|
5411
5484
|
logger.info(``);
|
|
5412
5485
|
logger.info(`App ID: ${appIDToBeDeployed}`);
|
|
5413
5486
|
logger.info(``);
|
|
@@ -5428,8 +5501,8 @@ async function deploy(options, logger = defaultLogger) {
|
|
|
5428
5501
|
logger.info("Deploying on-chain...");
|
|
5429
5502
|
const deployResult = await deployApp(
|
|
5430
5503
|
{
|
|
5431
|
-
|
|
5432
|
-
|
|
5504
|
+
walletClient: preflightCtx.walletClient,
|
|
5505
|
+
publicClient: preflightCtx.publicClient,
|
|
5433
5506
|
environmentConfig: preflightCtx.environmentConfig,
|
|
5434
5507
|
salt,
|
|
5435
5508
|
release,
|
|
@@ -5442,8 +5515,8 @@ async function deploy(options, logger = defaultLogger) {
|
|
|
5442
5515
|
logger.info("Waiting for app to start...");
|
|
5443
5516
|
const ipAddress = await watchUntilRunning(
|
|
5444
5517
|
{
|
|
5445
|
-
|
|
5446
|
-
|
|
5518
|
+
walletClient: preflightCtx.walletClient,
|
|
5519
|
+
publicClient: preflightCtx.publicClient,
|
|
5447
5520
|
environmentConfig: preflightCtx.environmentConfig,
|
|
5448
5521
|
appId: deployResult.appId
|
|
5449
5522
|
},
|
|
@@ -5460,12 +5533,10 @@ async function deploy(options, logger = defaultLogger) {
|
|
|
5460
5533
|
);
|
|
5461
5534
|
}
|
|
5462
5535
|
async function checkQuotaAvailable(preflightCtx) {
|
|
5463
|
-
const
|
|
5464
|
-
const environmentConfig = preflightCtx.environmentConfig;
|
|
5465
|
-
const userAddress = preflightCtx.selfAddress;
|
|
5536
|
+
const { publicClient, environmentConfig, selfAddress: userAddress } = preflightCtx;
|
|
5466
5537
|
let maxQuota;
|
|
5467
5538
|
try {
|
|
5468
|
-
maxQuota = await getMaxActiveAppsPerUser(
|
|
5539
|
+
maxQuota = await getMaxActiveAppsPerUser(publicClient, environmentConfig, userAddress);
|
|
5469
5540
|
} catch (err) {
|
|
5470
5541
|
throw new Error(`failed to get quota limit: ${err.message}`);
|
|
5471
5542
|
}
|
|
@@ -5476,7 +5547,7 @@ async function checkQuotaAvailable(preflightCtx) {
|
|
|
5476
5547
|
}
|
|
5477
5548
|
let activeCount;
|
|
5478
5549
|
try {
|
|
5479
|
-
activeCount = await getActiveAppCount(
|
|
5550
|
+
activeCount = await getActiveAppCount(publicClient, environmentConfig, userAddress);
|
|
5480
5551
|
} catch (err) {
|
|
5481
5552
|
throw new Error(`failed to get active app count: ${err.message}`);
|
|
5482
5553
|
}
|
|
@@ -5507,8 +5578,8 @@ async function prepareDeploy(options, logger = defaultLogger) {
|
|
|
5507
5578
|
logger.debug("Performing preflight checks...");
|
|
5508
5579
|
const preflightCtx = await doPreflightChecks(
|
|
5509
5580
|
{
|
|
5510
|
-
|
|
5511
|
-
|
|
5581
|
+
walletClient: options.walletClient,
|
|
5582
|
+
publicClient: options.publicClient,
|
|
5512
5583
|
environment: options.environment
|
|
5513
5584
|
},
|
|
5514
5585
|
logger
|
|
@@ -5525,12 +5596,12 @@ async function prepareDeploy(options, logger = defaultLogger) {
|
|
|
5525
5596
|
const salt = generateRandomSalt();
|
|
5526
5597
|
logger.debug(`Generated salt: ${Buffer.from(salt).toString("hex")}`);
|
|
5527
5598
|
logger.debug("Calculating app ID...");
|
|
5528
|
-
const appIDToBeDeployed = await calculateAppID(
|
|
5529
|
-
preflightCtx.
|
|
5530
|
-
|
|
5531
|
-
preflightCtx.
|
|
5599
|
+
const appIDToBeDeployed = await calculateAppID({
|
|
5600
|
+
publicClient: preflightCtx.publicClient,
|
|
5601
|
+
environmentConfig: preflightCtx.environmentConfig,
|
|
5602
|
+
ownerAddress: preflightCtx.selfAddress,
|
|
5532
5603
|
salt
|
|
5533
|
-
);
|
|
5604
|
+
});
|
|
5534
5605
|
logger.info(``);
|
|
5535
5606
|
logger.info(`App ID: ${appIDToBeDeployed}`);
|
|
5536
5607
|
logger.info(``);
|
|
@@ -5551,12 +5622,13 @@ async function prepareDeploy(options, logger = defaultLogger) {
|
|
|
5551
5622
|
logger.debug("Preparing deploy batch...");
|
|
5552
5623
|
const batch = await prepareDeployBatch(
|
|
5553
5624
|
{
|
|
5554
|
-
|
|
5555
|
-
|
|
5625
|
+
walletClient: preflightCtx.walletClient,
|
|
5626
|
+
publicClient: preflightCtx.publicClient,
|
|
5556
5627
|
environmentConfig: preflightCtx.environmentConfig,
|
|
5557
5628
|
salt,
|
|
5558
5629
|
release,
|
|
5559
|
-
publicLogs
|
|
5630
|
+
publicLogs,
|
|
5631
|
+
imageRef: finalImageRef
|
|
5560
5632
|
},
|
|
5561
5633
|
logger
|
|
5562
5634
|
);
|
|
@@ -5601,25 +5673,23 @@ async function executeDeploy(options) {
|
|
|
5601
5673
|
}
|
|
5602
5674
|
);
|
|
5603
5675
|
}
|
|
5604
|
-
async function watchDeployment(appId,
|
|
5676
|
+
async function watchDeployment(appId, walletClient, publicClient, environmentConfig, logger = defaultLogger, skipTelemetry) {
|
|
5605
5677
|
return withSDKTelemetry(
|
|
5606
5678
|
{
|
|
5607
5679
|
functionName: "watchDeployment",
|
|
5608
5680
|
skipTelemetry,
|
|
5609
5681
|
properties: {
|
|
5610
|
-
environment
|
|
5682
|
+
environment: environmentConfig.name
|
|
5611
5683
|
}
|
|
5612
5684
|
},
|
|
5613
5685
|
async () => {
|
|
5614
|
-
const environmentConfig = getEnvironmentConfig(environment);
|
|
5615
5686
|
logger.info("Waiting for app to start...");
|
|
5616
5687
|
return watchUntilRunning(
|
|
5617
5688
|
{
|
|
5618
|
-
|
|
5619
|
-
|
|
5689
|
+
walletClient,
|
|
5690
|
+
publicClient,
|
|
5620
5691
|
environmentConfig,
|
|
5621
|
-
appId
|
|
5622
|
-
clientId
|
|
5692
|
+
appId
|
|
5623
5693
|
},
|
|
5624
5694
|
logger
|
|
5625
5695
|
);
|
|
@@ -5628,18 +5698,12 @@ async function watchDeployment(appId, privateKey, rpcUrl, environment, logger =
|
|
|
5628
5698
|
}
|
|
5629
5699
|
|
|
5630
5700
|
// src/client/common/utils/permissions.ts
|
|
5631
|
-
var import_viem8 = require("viem");
|
|
5632
5701
|
var AnyoneCanCallAddress = "0x493219d9949348178af1f58740655951a8cd110c";
|
|
5633
5702
|
var ApiPermissionsTarget = "0x57ee1fb74c1087e26446abc4fb87fd8f07c43d8d";
|
|
5634
5703
|
var CanViewAppLogsPermission2 = "0x2fd3f2fe";
|
|
5635
5704
|
async function checkAppLogPermission(preflightCtx, appAddress, logger) {
|
|
5636
|
-
const chain = getChainFromID(preflightCtx.environmentConfig.chainID);
|
|
5637
|
-
const publicClient = (0, import_viem8.createPublicClient)({
|
|
5638
|
-
chain,
|
|
5639
|
-
transport: (0, import_viem8.http)(preflightCtx.rpcUrl)
|
|
5640
|
-
});
|
|
5641
5705
|
try {
|
|
5642
|
-
const canCall = await publicClient.readContract({
|
|
5706
|
+
const canCall = await preflightCtx.publicClient.readContract({
|
|
5643
5707
|
address: preflightCtx.environmentConfig.permissionControllerAddress,
|
|
5644
5708
|
abi: PermissionController_default,
|
|
5645
5709
|
functionName: "canCall",
|
|
@@ -5666,8 +5730,8 @@ async function prepareUpgradeFromVerifiableBuild(options, logger = defaultLogger
|
|
|
5666
5730
|
logger.debug("Performing preflight checks...");
|
|
5667
5731
|
const preflightCtx = await doPreflightChecks(
|
|
5668
5732
|
{
|
|
5669
|
-
|
|
5670
|
-
|
|
5733
|
+
walletClient: options.walletClient,
|
|
5734
|
+
publicClient: options.publicClient,
|
|
5671
5735
|
environment: options.environment
|
|
5672
5736
|
},
|
|
5673
5737
|
logger
|
|
@@ -5699,13 +5763,14 @@ async function prepareUpgradeFromVerifiableBuild(options, logger = defaultLogger
|
|
|
5699
5763
|
const needsPermissionChange = currentlyPublic !== publicLogs;
|
|
5700
5764
|
logger.debug("Preparing upgrade batch...");
|
|
5701
5765
|
const batch = await prepareUpgradeBatch({
|
|
5702
|
-
|
|
5703
|
-
|
|
5766
|
+
walletClient: preflightCtx.walletClient,
|
|
5767
|
+
publicClient: preflightCtx.publicClient,
|
|
5704
5768
|
environmentConfig: preflightCtx.environmentConfig,
|
|
5705
|
-
|
|
5769
|
+
appID,
|
|
5706
5770
|
release,
|
|
5707
5771
|
publicLogs,
|
|
5708
|
-
needsPermissionChange
|
|
5772
|
+
needsPermissionChange,
|
|
5773
|
+
imageRef: options.imageRef
|
|
5709
5774
|
});
|
|
5710
5775
|
logger.debug("Estimating gas...");
|
|
5711
5776
|
const gasEstimate = await estimateBatchGas({
|
|
@@ -5729,8 +5794,8 @@ async function prepareUpgradeFromVerifiableBuild(options, logger = defaultLogger
|
|
|
5729
5794
|
);
|
|
5730
5795
|
}
|
|
5731
5796
|
function validateUpgradeOptions(options) {
|
|
5732
|
-
if (!options.
|
|
5733
|
-
throw new Error("
|
|
5797
|
+
if (!options.walletClient?.account) {
|
|
5798
|
+
throw new Error("walletClient with account is required for upgrade");
|
|
5734
5799
|
}
|
|
5735
5800
|
if (!options.appId) {
|
|
5736
5801
|
throw new Error("appId is required for upgrade");
|
|
@@ -5767,8 +5832,8 @@ async function upgrade(options, logger = defaultLogger) {
|
|
|
5767
5832
|
logger.debug("Performing preflight checks...");
|
|
5768
5833
|
const preflightCtx = await doPreflightChecks(
|
|
5769
5834
|
{
|
|
5770
|
-
|
|
5771
|
-
|
|
5835
|
+
walletClient: options.walletClient,
|
|
5836
|
+
publicClient: options.publicClient,
|
|
5772
5837
|
environment: options.environment
|
|
5773
5838
|
},
|
|
5774
5839
|
logger
|
|
@@ -5802,10 +5867,10 @@ async function upgrade(options, logger = defaultLogger) {
|
|
|
5802
5867
|
logger.info("Upgrading on-chain...");
|
|
5803
5868
|
const txHash = await upgradeApp(
|
|
5804
5869
|
{
|
|
5805
|
-
|
|
5806
|
-
|
|
5870
|
+
walletClient: preflightCtx.walletClient,
|
|
5871
|
+
publicClient: preflightCtx.publicClient,
|
|
5807
5872
|
environmentConfig: preflightCtx.environmentConfig,
|
|
5808
|
-
|
|
5873
|
+
appID,
|
|
5809
5874
|
release,
|
|
5810
5875
|
publicLogs,
|
|
5811
5876
|
needsPermissionChange,
|
|
@@ -5817,8 +5882,8 @@ async function upgrade(options, logger = defaultLogger) {
|
|
|
5817
5882
|
logger.info("Waiting for upgrade to complete...");
|
|
5818
5883
|
await watchUntilUpgradeComplete(
|
|
5819
5884
|
{
|
|
5820
|
-
|
|
5821
|
-
|
|
5885
|
+
walletClient: preflightCtx.walletClient,
|
|
5886
|
+
publicClient: preflightCtx.publicClient,
|
|
5822
5887
|
environmentConfig: preflightCtx.environmentConfig,
|
|
5823
5888
|
appId: appID
|
|
5824
5889
|
},
|
|
@@ -5845,8 +5910,8 @@ async function prepareUpgrade(options, logger = defaultLogger) {
|
|
|
5845
5910
|
logger.debug("Performing preflight checks...");
|
|
5846
5911
|
const preflightCtx = await doPreflightChecks(
|
|
5847
5912
|
{
|
|
5848
|
-
|
|
5849
|
-
|
|
5913
|
+
walletClient: options.walletClient,
|
|
5914
|
+
publicClient: options.publicClient,
|
|
5850
5915
|
environment: options.environment
|
|
5851
5916
|
},
|
|
5852
5917
|
logger
|
|
@@ -5879,13 +5944,14 @@ async function prepareUpgrade(options, logger = defaultLogger) {
|
|
|
5879
5944
|
const needsPermissionChange = currentlyPublic !== publicLogs;
|
|
5880
5945
|
logger.debug("Preparing upgrade batch...");
|
|
5881
5946
|
const batch = await prepareUpgradeBatch({
|
|
5882
|
-
|
|
5883
|
-
|
|
5947
|
+
walletClient: preflightCtx.walletClient,
|
|
5948
|
+
publicClient: preflightCtx.publicClient,
|
|
5884
5949
|
environmentConfig: preflightCtx.environmentConfig,
|
|
5885
|
-
|
|
5950
|
+
appID,
|
|
5886
5951
|
release,
|
|
5887
5952
|
publicLogs,
|
|
5888
|
-
needsPermissionChange
|
|
5953
|
+
needsPermissionChange,
|
|
5954
|
+
imageRef: finalImageRef
|
|
5889
5955
|
});
|
|
5890
5956
|
logger.debug("Estimating gas...");
|
|
5891
5957
|
const gasEstimate = await estimateBatchGas({
|
|
@@ -5926,25 +5992,23 @@ async function executeUpgrade(options) {
|
|
|
5926
5992
|
}
|
|
5927
5993
|
);
|
|
5928
5994
|
}
|
|
5929
|
-
async function watchUpgrade(appId,
|
|
5995
|
+
async function watchUpgrade(appId, walletClient, publicClient, environmentConfig, logger = defaultLogger, skipTelemetry) {
|
|
5930
5996
|
return withSDKTelemetry(
|
|
5931
5997
|
{
|
|
5932
5998
|
functionName: "watchUpgrade",
|
|
5933
5999
|
skipTelemetry,
|
|
5934
6000
|
properties: {
|
|
5935
|
-
environment
|
|
6001
|
+
environment: environmentConfig.name
|
|
5936
6002
|
}
|
|
5937
6003
|
},
|
|
5938
6004
|
async () => {
|
|
5939
|
-
const environmentConfig = getEnvironmentConfig(environment);
|
|
5940
6005
|
logger.info("Waiting for upgrade to complete...");
|
|
5941
6006
|
await watchUntilUpgradeComplete(
|
|
5942
6007
|
{
|
|
5943
|
-
|
|
5944
|
-
|
|
6008
|
+
walletClient,
|
|
6009
|
+
publicClient,
|
|
5945
6010
|
environmentConfig,
|
|
5946
|
-
appId
|
|
5947
|
-
clientId
|
|
6011
|
+
appId
|
|
5948
6012
|
},
|
|
5949
6013
|
logger
|
|
5950
6014
|
);
|
|
@@ -6508,32 +6572,25 @@ async function watchLogs(appID, userApiClient, initialLogs) {
|
|
|
6508
6572
|
}
|
|
6509
6573
|
console.log("\nStopped watching");
|
|
6510
6574
|
}
|
|
6511
|
-
async function logs(options, logger = defaultLogger, skipTelemetry = false) {
|
|
6512
|
-
const skipTelemetryFlag = skipTelemetry || options.skipTelemetry || false;
|
|
6575
|
+
async function logs(options, walletClient, publicClient, environmentConfig, logger = defaultLogger, skipTelemetry = false) {
|
|
6513
6576
|
return withSDKTelemetry(
|
|
6514
6577
|
{
|
|
6515
6578
|
functionName: "logs",
|
|
6516
|
-
skipTelemetry
|
|
6517
|
-
properties: { environment:
|
|
6579
|
+
skipTelemetry,
|
|
6580
|
+
properties: { environment: environmentConfig.name }
|
|
6518
6581
|
},
|
|
6519
6582
|
async () => {
|
|
6520
6583
|
console.log();
|
|
6521
6584
|
if (!options.appID) {
|
|
6522
6585
|
throw new Error("appID is required for viewing logs");
|
|
6523
6586
|
}
|
|
6524
|
-
const environment = options.environment || "sepolia";
|
|
6525
|
-
const environmentConfig = getEnvironmentConfig(environment);
|
|
6526
|
-
const rpcUrl = options.rpcUrl || environmentConfig.defaultRPCURL;
|
|
6527
|
-
if (!rpcUrl) {
|
|
6528
|
-
throw new Error("RPC URL is required for authenticated requests");
|
|
6529
|
-
}
|
|
6530
6587
|
const appID = validateAppID(options.appID);
|
|
6531
6588
|
const formattedApp = formatAppDisplay(environmentConfig.name, appID, "");
|
|
6532
6589
|
const userApiClient = new UserApiClient(
|
|
6533
6590
|
environmentConfig,
|
|
6534
|
-
|
|
6535
|
-
|
|
6536
|
-
options.clientId
|
|
6591
|
+
walletClient,
|
|
6592
|
+
publicClient,
|
|
6593
|
+
options.clientId ? { clientId: options.clientId } : void 0
|
|
6537
6594
|
);
|
|
6538
6595
|
let logsText;
|
|
6539
6596
|
let logsError = null;
|
|
@@ -6609,35 +6666,39 @@ async function logs(options, logger = defaultLogger, skipTelemetry = false) {
|
|
|
6609
6666
|
}
|
|
6610
6667
|
|
|
6611
6668
|
// src/client/modules/compute/app/index.ts
|
|
6612
|
-
var CONTROLLER_ABI = (0,
|
|
6669
|
+
var CONTROLLER_ABI = (0, import_viem6.parseAbi)([
|
|
6613
6670
|
"function startApp(address appId)",
|
|
6614
6671
|
"function stopApp(address appId)",
|
|
6615
6672
|
"function terminateApp(address appId)"
|
|
6616
6673
|
]);
|
|
6617
6674
|
function encodeStartAppData(appId) {
|
|
6618
|
-
return (0,
|
|
6675
|
+
return (0, import_viem6.encodeFunctionData)({
|
|
6619
6676
|
abi: CONTROLLER_ABI,
|
|
6620
6677
|
functionName: "startApp",
|
|
6621
6678
|
args: [appId]
|
|
6622
6679
|
});
|
|
6623
6680
|
}
|
|
6624
6681
|
function encodeStopAppData(appId) {
|
|
6625
|
-
return (0,
|
|
6682
|
+
return (0, import_viem6.encodeFunctionData)({
|
|
6626
6683
|
abi: CONTROLLER_ABI,
|
|
6627
6684
|
functionName: "stopApp",
|
|
6628
6685
|
args: [appId]
|
|
6629
6686
|
});
|
|
6630
6687
|
}
|
|
6631
6688
|
function encodeTerminateAppData(appId) {
|
|
6632
|
-
return (0,
|
|
6689
|
+
return (0, import_viem6.encodeFunctionData)({
|
|
6633
6690
|
abi: CONTROLLER_ABI,
|
|
6634
6691
|
functionName: "terminateApp",
|
|
6635
6692
|
args: [appId]
|
|
6636
6693
|
});
|
|
6637
6694
|
}
|
|
6638
6695
|
function createAppModule(ctx) {
|
|
6639
|
-
const
|
|
6696
|
+
const { walletClient, publicClient } = ctx;
|
|
6640
6697
|
const skipTelemetry = ctx.skipTelemetry || false;
|
|
6698
|
+
if (!walletClient.account) {
|
|
6699
|
+
throw new Error("WalletClient must have an account attached");
|
|
6700
|
+
}
|
|
6701
|
+
const account = walletClient.account;
|
|
6641
6702
|
const environment = getEnvironmentConfig(ctx.environment);
|
|
6642
6703
|
const logger = getLogger(ctx.verbose);
|
|
6643
6704
|
return {
|
|
@@ -6648,8 +6709,8 @@ function createAppModule(ctx) {
|
|
|
6648
6709
|
async deploy(opts) {
|
|
6649
6710
|
const result = await deploy(
|
|
6650
6711
|
{
|
|
6651
|
-
|
|
6652
|
-
|
|
6712
|
+
walletClient,
|
|
6713
|
+
publicClient,
|
|
6653
6714
|
environment: ctx.environment,
|
|
6654
6715
|
appName: opts.name,
|
|
6655
6716
|
instanceType: opts.instanceType,
|
|
@@ -6673,8 +6734,8 @@ function createAppModule(ctx) {
|
|
|
6673
6734
|
const result = await upgrade(
|
|
6674
6735
|
{
|
|
6675
6736
|
appId,
|
|
6676
|
-
|
|
6677
|
-
|
|
6737
|
+
walletClient,
|
|
6738
|
+
publicClient,
|
|
6678
6739
|
environment: ctx.environment,
|
|
6679
6740
|
instanceType: opts.instanceType,
|
|
6680
6741
|
dockerfilePath: opts.dockerfile,
|
|
@@ -6695,8 +6756,8 @@ function createAppModule(ctx) {
|
|
|
6695
6756
|
async prepareDeploy(opts) {
|
|
6696
6757
|
return prepareDeploy(
|
|
6697
6758
|
{
|
|
6698
|
-
|
|
6699
|
-
|
|
6759
|
+
walletClient,
|
|
6760
|
+
publicClient,
|
|
6700
6761
|
environment: ctx.environment,
|
|
6701
6762
|
appName: opts.name,
|
|
6702
6763
|
instanceType: opts.instanceType,
|
|
@@ -6713,8 +6774,8 @@ function createAppModule(ctx) {
|
|
|
6713
6774
|
async prepareDeployFromVerifiableBuild(opts) {
|
|
6714
6775
|
return prepareDeployFromVerifiableBuild(
|
|
6715
6776
|
{
|
|
6716
|
-
|
|
6717
|
-
|
|
6777
|
+
walletClient,
|
|
6778
|
+
publicClient,
|
|
6718
6779
|
environment: ctx.environment,
|
|
6719
6780
|
appName: opts.name,
|
|
6720
6781
|
instanceType: opts.instanceType,
|
|
@@ -6729,17 +6790,6 @@ function createAppModule(ctx) {
|
|
|
6729
6790
|
);
|
|
6730
6791
|
},
|
|
6731
6792
|
async executeDeploy(prepared, gas) {
|
|
6732
|
-
const account = (0, import_accounts5.privateKeyToAccount)(privateKey);
|
|
6733
|
-
const chain = getChainFromID(environment.chainID);
|
|
6734
|
-
const publicClient = (0, import_viem9.createPublicClient)({
|
|
6735
|
-
chain,
|
|
6736
|
-
transport: (0, import_viem9.http)(ctx.rpcUrl)
|
|
6737
|
-
});
|
|
6738
|
-
const walletClient = (0, import_viem9.createWalletClient)({
|
|
6739
|
-
account,
|
|
6740
|
-
chain,
|
|
6741
|
-
transport: (0, import_viem9.http)(ctx.rpcUrl)
|
|
6742
|
-
});
|
|
6743
6793
|
const result = await executeDeploy({
|
|
6744
6794
|
prepared,
|
|
6745
6795
|
context: {
|
|
@@ -6761,11 +6811,10 @@ function createAppModule(ctx) {
|
|
|
6761
6811
|
async watchDeployment(appId) {
|
|
6762
6812
|
return watchDeployment(
|
|
6763
6813
|
appId,
|
|
6764
|
-
|
|
6765
|
-
|
|
6766
|
-
|
|
6814
|
+
walletClient,
|
|
6815
|
+
publicClient,
|
|
6816
|
+
environment,
|
|
6767
6817
|
logger,
|
|
6768
|
-
ctx.clientId,
|
|
6769
6818
|
skipTelemetry
|
|
6770
6819
|
);
|
|
6771
6820
|
},
|
|
@@ -6774,8 +6823,8 @@ function createAppModule(ctx) {
|
|
|
6774
6823
|
return prepareUpgrade(
|
|
6775
6824
|
{
|
|
6776
6825
|
appId,
|
|
6777
|
-
|
|
6778
|
-
|
|
6826
|
+
walletClient,
|
|
6827
|
+
publicClient,
|
|
6779
6828
|
environment: ctx.environment,
|
|
6780
6829
|
instanceType: opts.instanceType,
|
|
6781
6830
|
dockerfilePath: opts.dockerfile,
|
|
@@ -6792,8 +6841,8 @@ function createAppModule(ctx) {
|
|
|
6792
6841
|
return prepareUpgradeFromVerifiableBuild(
|
|
6793
6842
|
{
|
|
6794
6843
|
appId,
|
|
6795
|
-
|
|
6796
|
-
|
|
6844
|
+
walletClient,
|
|
6845
|
+
publicClient,
|
|
6797
6846
|
environment: ctx.environment,
|
|
6798
6847
|
instanceType: opts.instanceType,
|
|
6799
6848
|
envFilePath: opts.envFile,
|
|
@@ -6807,17 +6856,6 @@ function createAppModule(ctx) {
|
|
|
6807
6856
|
);
|
|
6808
6857
|
},
|
|
6809
6858
|
async executeUpgrade(prepared, gas) {
|
|
6810
|
-
const account = (0, import_accounts5.privateKeyToAccount)(privateKey);
|
|
6811
|
-
const chain = getChainFromID(environment.chainID);
|
|
6812
|
-
const publicClient = (0, import_viem9.createPublicClient)({
|
|
6813
|
-
chain,
|
|
6814
|
-
transport: (0, import_viem9.http)(ctx.rpcUrl)
|
|
6815
|
-
});
|
|
6816
|
-
const walletClient = (0, import_viem9.createWalletClient)({
|
|
6817
|
-
account,
|
|
6818
|
-
chain,
|
|
6819
|
-
transport: (0, import_viem9.http)(ctx.rpcUrl)
|
|
6820
|
-
});
|
|
6821
6859
|
const result = await executeUpgrade({
|
|
6822
6860
|
prepared,
|
|
6823
6861
|
context: {
|
|
@@ -6836,15 +6874,7 @@ function createAppModule(ctx) {
|
|
|
6836
6874
|
};
|
|
6837
6875
|
},
|
|
6838
6876
|
async watchUpgrade(appId) {
|
|
6839
|
-
return watchUpgrade(
|
|
6840
|
-
appId,
|
|
6841
|
-
privateKey,
|
|
6842
|
-
ctx.rpcUrl,
|
|
6843
|
-
ctx.environment,
|
|
6844
|
-
logger,
|
|
6845
|
-
ctx.clientId,
|
|
6846
|
-
skipTelemetry
|
|
6847
|
-
);
|
|
6877
|
+
return watchUpgrade(appId, walletClient, publicClient, environment, logger, skipTelemetry);
|
|
6848
6878
|
},
|
|
6849
6879
|
// Profile management
|
|
6850
6880
|
async setProfile(appId, profile) {
|
|
@@ -6857,33 +6887,32 @@ function createAppModule(ctx) {
|
|
|
6857
6887
|
async () => {
|
|
6858
6888
|
const userApiClient = new UserApiClient(
|
|
6859
6889
|
environment,
|
|
6860
|
-
|
|
6861
|
-
|
|
6862
|
-
ctx.clientId
|
|
6863
|
-
);
|
|
6864
|
-
return userApiClient.uploadAppProfile(
|
|
6865
|
-
appId,
|
|
6866
|
-
profile.name,
|
|
6867
|
-
profile.website,
|
|
6868
|
-
profile.description,
|
|
6869
|
-
profile.xURL,
|
|
6870
|
-
profile.imagePath
|
|
6890
|
+
walletClient,
|
|
6891
|
+
publicClient,
|
|
6892
|
+
ctx.clientId ? { clientId: ctx.clientId } : void 0
|
|
6871
6893
|
);
|
|
6894
|
+
return userApiClient.uploadAppProfile(appId, profile.name, {
|
|
6895
|
+
website: profile.website,
|
|
6896
|
+
description: profile.description,
|
|
6897
|
+
xURL: profile.xURL,
|
|
6898
|
+
image: profile.image,
|
|
6899
|
+
imageName: profile.imageName
|
|
6900
|
+
});
|
|
6872
6901
|
}
|
|
6873
6902
|
);
|
|
6874
6903
|
},
|
|
6875
6904
|
async logs(opts) {
|
|
6876
6905
|
return logs(
|
|
6877
6906
|
{
|
|
6878
|
-
privateKey,
|
|
6879
6907
|
appID: opts.appID,
|
|
6880
6908
|
watch: opts.watch,
|
|
6881
|
-
environment: ctx.environment,
|
|
6882
6909
|
clientId: ctx.clientId
|
|
6883
6910
|
},
|
|
6911
|
+
walletClient,
|
|
6912
|
+
publicClient,
|
|
6913
|
+
environment,
|
|
6884
6914
|
logger,
|
|
6885
6915
|
skipTelemetry
|
|
6886
|
-
// Skip if called from CLI
|
|
6887
6916
|
);
|
|
6888
6917
|
},
|
|
6889
6918
|
async start(appId, opts) {
|
|
@@ -6896,15 +6925,15 @@ function createAppModule(ctx) {
|
|
|
6896
6925
|
},
|
|
6897
6926
|
async () => {
|
|
6898
6927
|
const pendingMessage = `Starting app ${appId}...`;
|
|
6899
|
-
const data = (0,
|
|
6928
|
+
const data = (0, import_viem6.encodeFunctionData)({
|
|
6900
6929
|
abi: CONTROLLER_ABI,
|
|
6901
6930
|
functionName: "startApp",
|
|
6902
6931
|
args: [appId]
|
|
6903
6932
|
});
|
|
6904
6933
|
const tx = await sendAndWaitForTransaction(
|
|
6905
6934
|
{
|
|
6906
|
-
|
|
6907
|
-
|
|
6935
|
+
walletClient,
|
|
6936
|
+
publicClient,
|
|
6908
6937
|
environmentConfig: environment,
|
|
6909
6938
|
to: environment.appControllerAddress,
|
|
6910
6939
|
data,
|
|
@@ -6928,15 +6957,15 @@ function createAppModule(ctx) {
|
|
|
6928
6957
|
},
|
|
6929
6958
|
async () => {
|
|
6930
6959
|
const pendingMessage = `Stopping app ${appId}...`;
|
|
6931
|
-
const data = (0,
|
|
6960
|
+
const data = (0, import_viem6.encodeFunctionData)({
|
|
6932
6961
|
abi: CONTROLLER_ABI,
|
|
6933
6962
|
functionName: "stopApp",
|
|
6934
6963
|
args: [appId]
|
|
6935
6964
|
});
|
|
6936
6965
|
const tx = await sendAndWaitForTransaction(
|
|
6937
6966
|
{
|
|
6938
|
-
|
|
6939
|
-
|
|
6967
|
+
walletClient,
|
|
6968
|
+
publicClient,
|
|
6940
6969
|
environmentConfig: environment,
|
|
6941
6970
|
to: environment.appControllerAddress,
|
|
6942
6971
|
data,
|
|
@@ -6960,15 +6989,15 @@ function createAppModule(ctx) {
|
|
|
6960
6989
|
},
|
|
6961
6990
|
async () => {
|
|
6962
6991
|
const pendingMessage = `Terminating app ${appId}...`;
|
|
6963
|
-
const data = (0,
|
|
6992
|
+
const data = (0, import_viem6.encodeFunctionData)({
|
|
6964
6993
|
abi: CONTROLLER_ABI,
|
|
6965
6994
|
functionName: "terminateApp",
|
|
6966
6995
|
args: [appId]
|
|
6967
6996
|
});
|
|
6968
6997
|
const tx = await sendAndWaitForTransaction(
|
|
6969
6998
|
{
|
|
6970
|
-
|
|
6971
|
-
|
|
6999
|
+
walletClient,
|
|
7000
|
+
publicClient,
|
|
6972
7001
|
environmentConfig: environment,
|
|
6973
7002
|
to: environment.appControllerAddress,
|
|
6974
7003
|
data,
|
|
@@ -6984,9 +7013,9 @@ function createAppModule(ctx) {
|
|
|
6984
7013
|
},
|
|
6985
7014
|
async isDelegated() {
|
|
6986
7015
|
return isDelegated({
|
|
6987
|
-
|
|
6988
|
-
|
|
6989
|
-
|
|
7016
|
+
publicClient,
|
|
7017
|
+
environmentConfig: environment,
|
|
7018
|
+
address: account.address
|
|
6990
7019
|
});
|
|
6991
7020
|
},
|
|
6992
7021
|
async undelegate() {
|
|
@@ -7000,8 +7029,8 @@ function createAppModule(ctx) {
|
|
|
7000
7029
|
async () => {
|
|
7001
7030
|
const tx = await undelegate(
|
|
7002
7031
|
{
|
|
7003
|
-
|
|
7004
|
-
|
|
7032
|
+
walletClient,
|
|
7033
|
+
publicClient,
|
|
7005
7034
|
environmentConfig: environment
|
|
7006
7035
|
},
|
|
7007
7036
|
logger
|