@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.
Files changed (40) hide show
  1. package/VERSION +2 -2
  2. package/dist/billing.cjs +48 -43
  3. package/dist/billing.cjs.map +1 -1
  4. package/dist/billing.d.cts +6 -3
  5. package/dist/billing.d.ts +6 -3
  6. package/dist/billing.js +519 -4
  7. package/dist/billing.js.map +1 -1
  8. package/dist/browser.cjs +5034 -0
  9. package/dist/browser.cjs.map +1 -0
  10. package/dist/browser.d.cts +239 -0
  11. package/dist/browser.d.ts +239 -0
  12. package/dist/browser.js +4924 -0
  13. package/dist/browser.js.map +1 -0
  14. package/dist/{compute-CF2HOXed.d.ts → compute-BYhSs8en.d.ts} +15 -96
  15. package/dist/{compute-CbmjA8kJ.d.cts → compute-Bpjb3hYD.d.cts} +15 -96
  16. package/dist/compute.cjs +875 -846
  17. package/dist/compute.cjs.map +1 -1
  18. package/dist/compute.d.cts +2 -2
  19. package/dist/compute.d.ts +2 -2
  20. package/dist/compute.js +7009 -8
  21. package/dist/compute.js.map +1 -1
  22. package/dist/helpers-CEvhJz7f.d.cts +742 -0
  23. package/dist/helpers-CQuBwQnu.d.ts +742 -0
  24. package/dist/index-DeQzn_yM.d.cts +739 -0
  25. package/dist/index-DeQzn_yM.d.ts +739 -0
  26. package/dist/index.cjs +1958 -1758
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.d.cts +69 -414
  29. package/dist/index.d.ts +69 -414
  30. package/dist/index.js +7977 -134
  31. package/dist/index.js.map +1 -1
  32. package/package.json +17 -2
  33. package/dist/chunk-CA5Y4OVI.js +0 -744
  34. package/dist/chunk-CA5Y4OVI.js.map +0 -1
  35. package/dist/chunk-ZDXN2WKP.js +0 -434
  36. package/dist/chunk-ZDXN2WKP.js.map +0 -1
  37. package/dist/chunk-ZTLKZMSW.js +0 -6719
  38. package/dist/chunk-ZTLKZMSW.js.map +0 -1
  39. package/dist/index-D2QufVB9.d.cts +0 -342
  40. 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 import_viem9 = require("viem");
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: Number(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 import_viem5 = require("viem");
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 import_viem3 = require("viem");
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, import_viem3.extractChain)({ chains: SUPPORTED_CHAINS, id }) || fallback;
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(privateKey, rpcUrl, environmentConfig, salt) {
4314
- const privateKeyHex = addHexPrefix(privateKey);
4315
- const account = (0, import_accounts2.privateKeyToAccount)(privateKeyHex);
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: [accountAddress, saltHex]
3906
+ args: [ownerAddress, saltHex]
4330
3907
  });
4331
3908
  return appID;
4332
3909
  }
4333
- async function prepareDeployBatch(options, logger) {
4334
- const { privateKey, rpcUrl, environmentConfig, salt, release, publicLogs } = options;
4335
- const privateKeyHex = addHexPrefix(privateKey);
4336
- const account = (0, import_accounts2.privateKeyToAccount)(privateKeyHex);
4337
- const chain = getChainFromID(environmentConfig.chainID);
4338
- const publicClient = (0, import_viem5.createPublicClient)({
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(privateKeyHex, rpcUrl, environmentConfig, salt);
4349
- logger.info(`App ID: ${appId}`);
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 = Buffer.from(salt).toString("hex");
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${Buffer.from(artifact.digest).toString("hex").padStart(64, "0")}`,
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: `0x${Buffer.from(release.publicEnv).toString("hex")}`,
4364
- encryptedEnv: `0x${Buffer.from(release.encryptedEnv).toString("hex")}`
3936
+ publicEnv: (0, import_viem3.bytesToHex)(release.publicEnv),
3937
+ encryptedEnv: (0, import_viem3.bytesToHex)(release.encryptedEnv)
4365
3938
  };
4366
- const createData = (0, import_viem5.encodeFunctionData)({
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, import_viem5.encodeFunctionData)({
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, import_viem5.encodeFunctionData)({
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
- privateKey,
4459
- rpcUrl,
4021
+ walletClient,
4022
+ publicClient,
4460
4023
  environmentConfig,
4461
- appId,
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${Buffer.from(artifact.digest).toString("hex").padStart(64, "0")}`,
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: `0x${Buffer.from(release.publicEnv).toString("hex")}`,
4487
- encryptedEnv: `0x${Buffer.from(release.encryptedEnv).toString("hex")}`
4037
+ publicEnv: (0, import_viem3.bytesToHex)(release.publicEnv),
4038
+ encryptedEnv: (0, import_viem3.bytesToHex)(release.encryptedEnv)
4488
4039
  };
4489
- const upgradeData = (0, import_viem5.encodeFunctionData)({
4040
+ const upgradeData = (0, import_viem3.encodeFunctionData)({
4490
4041
  abi: AppController_default,
4491
4042
  functionName: "upgradeApp",
4492
- args: [appId, releaseForViem]
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, import_viem5.encodeFunctionData)({
4054
+ const addLogsData = (0, import_viem3.encodeFunctionData)({
4504
4055
  abi: PermissionController_default,
4505
4056
  functionName: "setAppointee",
4506
4057
  args: [
4507
- appId,
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, import_viem5.encodeFunctionData)({
4073
+ const removeLogsData = (0, import_viem3.encodeFunctionData)({
4523
4074
  abi: PermissionController_default,
4524
4075
  functionName: "removeAppointee",
4525
4076
  args: [
4526
- appId,
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
- privateKey,
4589
- rpcUrl,
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 privateKeyHex = addHexPrefix(privateKey);
4599
- const account = (0, import_accounts2.privateKeyToAccount)(privateKeyHex);
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 && { maxPriorityFeePerGas: 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, import_viem5.decodeErrorResult)({
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(rpcUrl, environmentConfig, user) {
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(rpcUrl, environmentConfig, user) {
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 { privateKey, rpcUrl, environmentConfig } = options;
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
- account.address,
4247
+ address,
4726
4248
  environmentConfig.erc7702DelegatorAddress
4727
4249
  );
4728
4250
  }
4729
- async function undelegate(options, logger) {
4730
- const { privateKey, rpcUrl, environmentConfig } = options;
4731
- const privateKeyHex = addHexPrefix(privateKey);
4732
- const account = (0, import_accounts2.privateKeyToAccount)(privateKeyHex);
4733
- const chain = getChainFromID(environmentConfig.chainID);
4734
- const publicClient = (0, import_viem5.createPublicClient)({
4735
- chain,
4736
- transport: (0, import_viem5.http)(rpcUrl)
4737
- });
4738
- const walletClient = (0, import_viem5.createWalletClient)({
4739
- account,
4740
- chain,
4741
- transport: (0, import_viem5.http)(rpcUrl)
4742
- });
4743
- const transactionNonce = await publicClient.getTransactionCount({
4744
- address: account.address,
4745
- blockTag: "pending"
4746
- });
4747
- const chainId = await publicClient.getChainId();
4748
- const authorizationNonce = BigInt(transactionNonce) + 1n;
4749
- const authorization = {
4750
- chainId: Number(chainId),
4751
- address: "0x0000000000000000000000000000000000000000",
4752
- // Empty address = undelegate
4753
- nonce: authorizationNonce
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 { environmentConfig, appId, privateKey, rpcUrl, clientId } = options;
4800
- const userApiClient = new UserApiClient(environmentConfig, privateKey, rpcUrl, clientId);
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 { environmentConfig, appId, privateKey, rpcUrl, clientId } = options;
4850
- const userApiClient = new UserApiClient(environmentConfig, privateKey, rpcUrl, clientId);
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 import_viem6 = require("viem");
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, import_viem6.isAddress)(normalized)) {
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
- logger.debug("Checking authentication...");
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
- let rpcUrl = options.rpcUrl;
5005
- if (!rpcUrl) {
5006
- rpcUrl = process.env.RPC_URL ?? environmentConfig.defaultRPCURL;
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("Testing network connectivity...");
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(`Cannot connect to ${environmentConfig.name} RPC at ${rpcUrl}: ${err.message}`);
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
- privateKey: privateKeyHex,
5030
- rpcUrl,
5105
+ walletClient,
5106
+ publicClient,
5031
5107
  environmentConfig,
5032
- account,
5033
- selfAddress
5108
+ selfAddress: account.address
5034
5109
  };
5035
5110
  }
5036
- async function getPrivateKeyOrFail(privateKey) {
5037
- if (privateKey) {
5038
- validatePrivateKey(privateKey);
5039
- return privateKey;
5040
- }
5041
- if (process.env.PRIVATE_KEY) {
5042
- validatePrivateKey(process.env.PRIVATE_KEY);
5043
- return process.env.PRIVATE_KEY;
5044
- }
5045
- throw new Error(
5046
- `private key required. Please provide it via:
5047
- \u2022 Option: privateKey in deploy options
5048
- \u2022 Environment: export PRIVATE_KEY=YOUR_KEY
5049
- \u2022 Keyring: (not yet implemented)`
5050
- );
5051
- }
5052
- function validatePrivateKey(key) {
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.privateKey) throw new Error("privateKey is required for deployment");
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
- privateKey: options.privateKey,
5282
- rpcUrl: options.rpcUrl,
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.privateKey,
5294
- options.rpcUrl || preflightCtx.rpcUrl,
5295
- preflightCtx.environmentConfig,
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
- privateKey: preflightCtx.privateKey,
5316
- rpcUrl: options.rpcUrl || preflightCtx.rpcUrl,
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.privateKey) {
5348
- throw new Error("privateKey is required for deployment");
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
- privateKey: options.privateKey,
5388
- rpcUrl: options.rpcUrl,
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.privateKey,
5407
- options.rpcUrl || preflightCtx.rpcUrl,
5408
- preflightCtx.environmentConfig,
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
- privateKey: preflightCtx.privateKey,
5432
- rpcUrl: options.rpcUrl || preflightCtx.rpcUrl,
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
- privateKey: preflightCtx.privateKey,
5446
- rpcUrl: options.rpcUrl || preflightCtx.rpcUrl,
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 rpcUrl = preflightCtx.rpcUrl;
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(rpcUrl, environmentConfig, userAddress);
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(rpcUrl, environmentConfig, userAddress);
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
- privateKey: options.privateKey,
5511
- rpcUrl: options.rpcUrl,
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.privateKey,
5530
- options.rpcUrl || preflightCtx.rpcUrl,
5531
- preflightCtx.environmentConfig,
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
- privateKey: preflightCtx.privateKey,
5555
- rpcUrl: options.rpcUrl || preflightCtx.rpcUrl,
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, privateKey, rpcUrl, environment, logger = defaultLogger, clientId, skipTelemetry) {
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
- privateKey,
5619
- rpcUrl,
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
- privateKey: options.privateKey,
5670
- rpcUrl: options.rpcUrl,
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
- privateKey: preflightCtx.privateKey,
5703
- rpcUrl: options.rpcUrl || preflightCtx.rpcUrl,
5766
+ walletClient: preflightCtx.walletClient,
5767
+ publicClient: preflightCtx.publicClient,
5704
5768
  environmentConfig: preflightCtx.environmentConfig,
5705
- appId: appID,
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.privateKey) {
5733
- throw new Error("privateKey is required for upgrade");
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
- privateKey: options.privateKey,
5771
- rpcUrl: options.rpcUrl,
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
- privateKey: preflightCtx.privateKey,
5806
- rpcUrl: options.rpcUrl || preflightCtx.rpcUrl,
5870
+ walletClient: preflightCtx.walletClient,
5871
+ publicClient: preflightCtx.publicClient,
5807
5872
  environmentConfig: preflightCtx.environmentConfig,
5808
- appId: appID,
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
- privateKey: preflightCtx.privateKey,
5821
- rpcUrl: options.rpcUrl || preflightCtx.rpcUrl,
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
- privateKey: options.privateKey,
5849
- rpcUrl: options.rpcUrl,
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
- privateKey: preflightCtx.privateKey,
5883
- rpcUrl: options.rpcUrl || preflightCtx.rpcUrl,
5947
+ walletClient: preflightCtx.walletClient,
5948
+ publicClient: preflightCtx.publicClient,
5884
5949
  environmentConfig: preflightCtx.environmentConfig,
5885
- appId: appID,
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, privateKey, rpcUrl, environment, logger = defaultLogger, clientId, skipTelemetry) {
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
- privateKey,
5944
- rpcUrl,
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: skipTelemetryFlag,
6517
- properties: { environment: options.environment || "sepolia" }
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
- options.privateKey,
6535
- rpcUrl,
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, import_viem9.parseAbi)([
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, import_viem9.encodeFunctionData)({
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, import_viem9.encodeFunctionData)({
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, import_viem9.encodeFunctionData)({
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 privateKey = addHexPrefix(ctx.privateKey);
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
- privateKey,
6652
- rpcUrl: ctx.rpcUrl,
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
- privateKey,
6677
- rpcUrl: ctx.rpcUrl,
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
- privateKey,
6699
- rpcUrl: ctx.rpcUrl,
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
- privateKey,
6717
- rpcUrl: ctx.rpcUrl,
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
- privateKey,
6765
- ctx.rpcUrl,
6766
- ctx.environment,
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
- privateKey,
6778
- rpcUrl: ctx.rpcUrl,
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
- privateKey,
6796
- rpcUrl: ctx.rpcUrl,
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
- privateKey,
6861
- ctx.rpcUrl,
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, import_viem9.encodeFunctionData)({
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
- privateKey,
6907
- rpcUrl: ctx.rpcUrl,
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, import_viem9.encodeFunctionData)({
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
- privateKey,
6939
- rpcUrl: ctx.rpcUrl,
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, import_viem9.encodeFunctionData)({
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
- privateKey,
6971
- rpcUrl: ctx.rpcUrl,
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
- privateKey,
6988
- rpcUrl: ctx.rpcUrl,
6989
- environmentConfig: environment
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
- privateKey,
7004
- rpcUrl: ctx.rpcUrl,
7032
+ walletClient,
7033
+ publicClient,
7005
7034
  environmentConfig: environment
7006
7035
  },
7007
7036
  logger