@layr-labs/ecloud-sdk 0.2.0-dev.3 → 0.2.1-dev

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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 ? "dev"?.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,9 +1139,6 @@ 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
 
@@ -2347,11 +2251,12 @@ async function executeBatch(options, logger) {
2347
2251
  });
2348
2252
  const chainId = await publicClient.getChainId();
2349
2253
  const authorizationNonce = transactionNonce + 1;
2254
+ logger.debug("Using wallet client signing for EIP-7702 authorization");
2350
2255
  const signedAuthorization = await walletClient.signAuthorization({
2351
- account,
2256
+ account: account.address,
2352
2257
  contractAddress: environmentConfig.erc7702DelegatorAddress,
2353
- chainId: Number(chainId),
2354
- nonce: authorizationNonce
2258
+ chainId,
2259
+ nonce: Number(authorizationNonce)
2355
2260
  });
2356
2261
  authorizationList = [signedAuthorization];
2357
2262
  }
@@ -2406,57 +2311,15 @@ async function executeBatch(options, logger) {
2406
2311
  }
2407
2312
 
2408
2313
  // 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");
2314
+ var import_viem3 = require("viem");
2453
2315
 
2454
2316
  // src/client/common/utils/helpers.ts
2455
- var import_viem3 = require("viem");
2317
+ var import_viem2 = require("viem");
2456
2318
  var import_chains2 = require("viem/chains");
2319
+ var import_accounts = require("viem/accounts");
2457
2320
  function getChainFromID(chainID, fallback = import_chains2.sepolia) {
2458
2321
  const id = Number(chainID);
2459
- return (0, import_viem3.extractChain)({ chains: SUPPORTED_CHAINS, id }) || fallback;
2322
+ return (0, import_viem2.extractChain)({ chains: SUPPORTED_CHAINS, id }) || fallback;
2460
2323
  }
2461
2324
  function addHexPrefix(value) {
2462
2325
  return value.startsWith("0x") ? value : `0x${value}`;
@@ -2465,297 +2328,6 @@ function stripHexPrefix(value) {
2465
2328
  return value.startsWith("0x") ? value.slice(2) : value;
2466
2329
  }
2467
2330
 
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-dev.3" : "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
2331
  // src/client/common/abis/AppController.json
2760
2332
  var AppController_default = [
2761
2333
  {
@@ -4310,65 +3882,54 @@ function formatETH(wei) {
4310
3882
  }
4311
3883
  return trimmed;
4312
3884
  }
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");
3885
+ async function calculateAppID(options) {
3886
+ const { publicClient, environmentConfig, ownerAddress, salt } = options;
3887
+ const saltHexString = (0, import_viem3.bytesToHex)(salt).slice(2);
4322
3888
  const paddedSaltHex = saltHexString.padStart(64, "0");
4323
3889
  const saltHex = `0x${paddedSaltHex}`;
4324
- const accountAddress = typeof account.address === "string" ? account.address : account.address.toString();
4325
3890
  const appID = await publicClient.readContract({
4326
3891
  address: environmentConfig.appControllerAddress,
4327
3892
  abi: AppController_default,
4328
3893
  functionName: "calculateAppId",
4329
- args: [accountAddress, saltHex]
3894
+ args: [ownerAddress, saltHex]
4330
3895
  });
4331
3896
  return appID;
4332
3897
  }
4333
3898
  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
- });
3899
+ const { walletClient, publicClient, environmentConfig, salt, release, publicLogs } = options;
3900
+ const account = walletClient.account;
3901
+ if (!account) {
3902
+ throw new Error("WalletClient must have an account attached");
3903
+ }
4347
3904
  logger.info("Calculating app ID...");
4348
- const appId = await calculateAppID(privateKeyHex, rpcUrl, environmentConfig, salt);
4349
- logger.info(`App ID: ${appId}`);
3905
+ const appId = await calculateAppID({
3906
+ publicClient,
3907
+ environmentConfig,
3908
+ ownerAddress: account.address,
3909
+ salt
3910
+ });
4350
3911
  logger.debug(`App ID calculated: ${appId}`);
4351
3912
  logger.debug(`This address will be used for acceptAdmin call`);
4352
- const saltHexString = Buffer.from(salt).toString("hex");
3913
+ const saltHexString = (0, import_viem3.bytesToHex)(salt).slice(2);
4353
3914
  const paddedSaltHex = saltHexString.padStart(64, "0");
4354
3915
  const saltHex = `0x${paddedSaltHex}`;
4355
3916
  const releaseForViem = {
4356
3917
  rmsRelease: {
4357
3918
  artifacts: release.rmsRelease.artifacts.map((artifact) => ({
4358
- digest: `0x${Buffer.from(artifact.digest).toString("hex").padStart(64, "0")}`,
3919
+ digest: `0x${(0, import_viem3.bytesToHex)(artifact.digest).slice(2).padStart(64, "0")}`,
4359
3920
  registry: artifact.registry
4360
3921
  })),
4361
3922
  upgradeByTime: release.rmsRelease.upgradeByTime
4362
3923
  },
4363
- publicEnv: `0x${Buffer.from(release.publicEnv).toString("hex")}`,
4364
- encryptedEnv: `0x${Buffer.from(release.encryptedEnv).toString("hex")}`
3924
+ publicEnv: (0, import_viem3.bytesToHex)(release.publicEnv),
3925
+ encryptedEnv: (0, import_viem3.bytesToHex)(release.encryptedEnv)
4365
3926
  };
4366
- const createData = (0, import_viem5.encodeFunctionData)({
3927
+ const createData = (0, import_viem3.encodeFunctionData)({
4367
3928
  abi: AppController_default,
4368
3929
  functionName: "createApp",
4369
3930
  args: [saltHex, releaseForViem]
4370
3931
  });
4371
- const acceptAdminData = (0, import_viem5.encodeFunctionData)({
3932
+ const acceptAdminData = (0, import_viem3.encodeFunctionData)({
4372
3933
  abi: PermissionController_default,
4373
3934
  functionName: "acceptAdmin",
4374
3935
  args: [appId]
@@ -4386,7 +3947,7 @@ async function prepareDeployBatch(options, logger) {
4386
3947
  }
4387
3948
  ];
4388
3949
  if (publicLogs) {
4389
- const anyoneCanViewLogsData = (0, import_viem5.encodeFunctionData)({
3950
+ const anyoneCanViewLogsData = (0, import_viem3.encodeFunctionData)({
4390
3951
  abi: PermissionController_default,
4391
3952
  functionName: "setAppointee",
4392
3953
  args: [
@@ -4430,17 +3991,7 @@ async function executeDeployBatch(data, context, gas, logger) {
4430
3991
  return { appId: data.appId, txHash };
4431
3992
  }
4432
3993
  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
- );
3994
+ const prepared = await prepareDeployBatch(options, logger);
4444
3995
  const data = {
4445
3996
  appId: prepared.appId,
4446
3997
  salt: prepared.salt,
@@ -4454,42 +4005,22 @@ async function deployApp(options, logger) {
4454
4005
  return executeDeployBatch(data, context, options.gas, logger);
4455
4006
  }
4456
4007
  async function prepareUpgradeBatch(options) {
4457
- const {
4458
- privateKey,
4459
- rpcUrl,
4460
- environmentConfig,
4461
- appId,
4462
- release,
4463
- publicLogs,
4464
- needsPermissionChange
4465
- } = 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
- });
4008
+ const { walletClient, publicClient, environmentConfig, appID, release, publicLogs, needsPermissionChange } = options;
4478
4009
  const releaseForViem = {
4479
4010
  rmsRelease: {
4480
4011
  artifacts: release.rmsRelease.artifacts.map((artifact) => ({
4481
- digest: `0x${Buffer.from(artifact.digest).toString("hex").padStart(64, "0")}`,
4012
+ digest: `0x${(0, import_viem3.bytesToHex)(artifact.digest).slice(2).padStart(64, "0")}`,
4482
4013
  registry: artifact.registry
4483
4014
  })),
4484
4015
  upgradeByTime: release.rmsRelease.upgradeByTime
4485
4016
  },
4486
- publicEnv: `0x${Buffer.from(release.publicEnv).toString("hex")}`,
4487
- encryptedEnv: `0x${Buffer.from(release.encryptedEnv).toString("hex")}`
4017
+ publicEnv: (0, import_viem3.bytesToHex)(release.publicEnv),
4018
+ encryptedEnv: (0, import_viem3.bytesToHex)(release.encryptedEnv)
4488
4019
  };
4489
- const upgradeData = (0, import_viem5.encodeFunctionData)({
4020
+ const upgradeData = (0, import_viem3.encodeFunctionData)({
4490
4021
  abi: AppController_default,
4491
4022
  functionName: "upgradeApp",
4492
- args: [appId, releaseForViem]
4023
+ args: [appID, releaseForViem]
4493
4024
  });
4494
4025
  const executions = [
4495
4026
  {
@@ -4500,11 +4031,11 @@ async function prepareUpgradeBatch(options) {
4500
4031
  ];
4501
4032
  if (needsPermissionChange) {
4502
4033
  if (publicLogs) {
4503
- const addLogsData = (0, import_viem5.encodeFunctionData)({
4034
+ const addLogsData = (0, import_viem3.encodeFunctionData)({
4504
4035
  abi: PermissionController_default,
4505
4036
  functionName: "setAppointee",
4506
4037
  args: [
4507
- appId,
4038
+ appID,
4508
4039
  "0x493219d9949348178af1f58740655951a8cd110c",
4509
4040
  // AnyoneCanCallAddress
4510
4041
  "0x57ee1fb74c1087e26446abc4fb87fd8f07c43d8d",
@@ -4519,11 +4050,11 @@ async function prepareUpgradeBatch(options) {
4519
4050
  callData: addLogsData
4520
4051
  });
4521
4052
  } else {
4522
- const removeLogsData = (0, import_viem5.encodeFunctionData)({
4053
+ const removeLogsData = (0, import_viem3.encodeFunctionData)({
4523
4054
  abi: PermissionController_default,
4524
4055
  functionName: "removeAppointee",
4525
4056
  args: [
4526
- appId,
4057
+ appID,
4527
4058
  "0x493219d9949348178af1f58740655951a8cd110c",
4528
4059
  // AnyoneCanCallAddress
4529
4060
  "0x57ee1fb74c1087e26446abc4fb87fd8f07c43d8d",
@@ -4540,7 +4071,7 @@ async function prepareUpgradeBatch(options) {
4540
4071
  }
4541
4072
  }
4542
4073
  return {
4543
- appId,
4074
+ appId: appID,
4544
4075
  executions,
4545
4076
  walletClient,
4546
4077
  publicClient,
@@ -4563,15 +4094,7 @@ async function executeUpgradeBatch(data, context, gas, logger) {
4563
4094
  return txHash;
4564
4095
  }
4565
4096
  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
- });
4097
+ const prepared = await prepareUpgradeBatch(options);
4575
4098
  const data = {
4576
4099
  appId: prepared.appId,
4577
4100
  executions: prepared.executions
@@ -4584,29 +4107,12 @@ async function upgradeApp(options, logger) {
4584
4107
  return executeUpgradeBatch(data, context, options.gas, logger);
4585
4108
  }
4586
4109
  async function sendAndWaitForTransaction(options, logger) {
4587
- const {
4588
- privateKey,
4589
- rpcUrl,
4590
- environmentConfig,
4591
- to,
4592
- data,
4593
- value = 0n,
4594
- pendingMessage,
4595
- txDescription,
4596
- gas
4597
- } = options;
4598
- const privateKeyHex = addHexPrefix(privateKey);
4599
- const account = (0, import_accounts2.privateKeyToAccount)(privateKeyHex);
4110
+ const { walletClient, publicClient, environmentConfig, to, data, value = 0n, pendingMessage, txDescription, gas } = options;
4111
+ const account = walletClient.account;
4112
+ if (!account) {
4113
+ throw new Error("WalletClient must have an account attached");
4114
+ }
4600
4115
  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
4116
  if (pendingMessage) {
4611
4117
  logger.info(`
4612
4118
  ${pendingMessage}`);
@@ -4617,7 +4123,10 @@ ${pendingMessage}`);
4617
4123
  data,
4618
4124
  value,
4619
4125
  ...gas?.maxFeePerGas && { maxFeePerGas: gas.maxFeePerGas },
4620
- ...gas?.maxPriorityFeePerGas && { maxPriorityFeePerGas: gas.maxPriorityFeePerGas }
4126
+ ...gas?.maxPriorityFeePerGas && {
4127
+ maxPriorityFeePerGas: gas.maxPriorityFeePerGas
4128
+ },
4129
+ chain
4621
4130
  });
4622
4131
  logger.info(`Transaction sent: ${hash}`);
4623
4132
  const receipt = await publicClient.waitForTransactionReceipt({ hash });
@@ -4632,7 +4141,7 @@ ${pendingMessage}`);
4632
4141
  } catch (callError) {
4633
4142
  if (callError.data) {
4634
4143
  try {
4635
- const decoded = (0, import_viem5.decodeErrorResult)({
4144
+ const decoded = (0, import_viem3.decodeErrorResult)({
4636
4145
  abi: AppController_default,
4637
4146
  data: callError.data
4638
4147
  });
@@ -4683,12 +4192,7 @@ function formatAppControllerError(decoded) {
4683
4192
  return new Error(`contract error: ${errorName}`);
4684
4193
  }
4685
4194
  }
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
- });
4195
+ async function getActiveAppCount(publicClient, environmentConfig, user) {
4692
4196
  const count = await publicClient.readContract({
4693
4197
  address: environmentConfig.appControllerAddress,
4694
4198
  abi: AppController_default,
@@ -4697,12 +4201,7 @@ async function getActiveAppCount(rpcUrl, environmentConfig, user) {
4697
4201
  });
4698
4202
  return Number(count);
4699
4203
  }
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
- });
4204
+ async function getMaxActiveAppsPerUser(publicClient, environmentConfig, user) {
4706
4205
  const quota = await publicClient.readContract({
4707
4206
  address: environmentConfig.appControllerAddress,
4708
4207
  abi: AppController_default,
@@ -4712,83 +4211,365 @@ async function getMaxActiveAppsPerUser(rpcUrl, environmentConfig, user) {
4712
4211
  return Number(quota);
4713
4212
  }
4714
4213
  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
- });
4214
+ const { publicClient, environmentConfig, address } = options;
4723
4215
  return checkERC7702Delegation(
4724
4216
  publicClient,
4725
- account.address,
4217
+ address,
4726
4218
  environmentConfig.erc7702DelegatorAddress
4727
4219
  );
4728
4220
  }
4729
4221
  async function undelegate(options, logger) {
4730
- const { privateKey, rpcUrl, environmentConfig } = options;
4731
- const privateKeyHex = addHexPrefix(privateKey);
4732
- const account = (0, import_accounts2.privateKeyToAccount)(privateKeyHex);
4222
+ const { walletClient, publicClient, environmentConfig } = options;
4223
+ const account = walletClient.account;
4224
+ if (!account) {
4225
+ throw new Error("WalletClient must have an account attached");
4226
+ }
4733
4227
  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
4228
  const transactionNonce = await publicClient.getTransactionCount({
4744
4229
  address: account.address,
4745
4230
  blockTag: "pending"
4746
4231
  });
4747
4232
  const chainId = await publicClient.getChainId();
4748
4233
  const authorizationNonce = BigInt(transactionNonce) + 1n;
4749
- const authorization = {
4750
- chainId: Number(chainId),
4751
- address: "0x0000000000000000000000000000000000000000",
4752
- // Empty address = undelegate
4753
- nonce: authorizationNonce
4754
- };
4755
- const sighash = (0, import_utils.hashAuthorization)({
4756
- chainId: authorization.chainId,
4757
- contractAddress: authorization.address,
4758
- nonce: Number(authorization.nonce)
4234
+ logger.debug("Signing undelegate authorization");
4235
+ const signedAuthorization = await walletClient.signAuthorization({
4236
+ contractAddress: "0x0000000000000000000000000000000000000000",
4237
+ chainId,
4238
+ nonce: Number(authorizationNonce),
4239
+ account
4759
4240
  });
4760
- const sig = await (0, import_accounts3.sign)({
4761
- hash: sighash,
4762
- privateKey: privateKeyHex
4241
+ const authorizationList = [signedAuthorization];
4242
+ const hash = await walletClient.sendTransaction({
4243
+ account,
4244
+ to: account.address,
4245
+ // Send to self
4246
+ data: "0x",
4247
+ // Empty data
4248
+ value: 0n,
4249
+ authorizationList,
4250
+ chain
4763
4251
  });
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
4252
+ logger.info(`Transaction sent: ${hash}`);
4253
+ const receipt = await publicClient.waitForTransactionReceipt({ hash });
4254
+ if (receipt.status === "reverted") {
4255
+ logger.error(`Undelegate transaction (hash: ${hash}) reverted`);
4256
+ throw new Error(`Undelegate transaction (hash: ${hash}) reverted`);
4257
+ }
4258
+ return hash;
4259
+ }
4260
+
4261
+ // src/client/common/utils/userapi.ts
4262
+ var import_axios = __toESM(require("axios"), 1);
4263
+
4264
+ // src/client/common/utils/auth.ts
4265
+ var import_viem4 = require("viem");
4266
+ var APP_CONTROLLER_ABI = (0, import_viem4.parseAbi)([
4267
+ "function calculateApiPermissionDigestHash(bytes4 permission, uint256 expiry) view returns (bytes32)"
4268
+ ]);
4269
+ async function calculatePermissionSignature(options) {
4270
+ const { permission, expiry, appControllerAddress, publicClient, walletClient } = options;
4271
+ const digest = await publicClient.readContract({
4272
+ address: appControllerAddress,
4273
+ abi: APP_CONTROLLER_ABI,
4274
+ functionName: "calculateApiPermissionDigestHash",
4275
+ args: [permission, expiry]
4276
+ });
4277
+ const account = walletClient.account;
4278
+ if (!account) {
4279
+ throw new Error("WalletClient must have an account attached");
4280
+ }
4281
+ const signature = await walletClient.signMessage({
4282
+ account,
4283
+ message: { raw: digest }
4284
+ });
4285
+ return { signature, digest };
4286
+ }
4287
+
4288
+ // src/client/common/utils/userapi.ts
4289
+ function isJsonObject(value) {
4290
+ return typeof value === "object" && value !== null && !Array.isArray(value);
4291
+ }
4292
+ function readString(obj, key) {
4293
+ const v = obj[key];
4294
+ return typeof v === "string" ? v : void 0;
4295
+ }
4296
+ function readNumber(obj, key) {
4297
+ const v = obj[key];
4298
+ return typeof v === "number" && Number.isFinite(v) ? v : void 0;
4299
+ }
4300
+ var MAX_ADDRESS_COUNT = 5;
4301
+ var CanViewAppLogsPermission = "0x2fd3f2fe";
4302
+ var CanViewSensitiveAppInfoPermission = "0x0e67b22f";
4303
+ var CanUpdateAppProfilePermission = "0x036fef61";
4304
+ function getDefaultClientId() {
4305
+ const version = true ? "0.2.1-dev" : "0.0.0";
4306
+ return `ecloud-sdk/v${version}`;
4307
+ }
4308
+ var UserApiClient = class {
4309
+ constructor(config, walletClient, publicClient, clientId) {
4310
+ this.config = config;
4311
+ this.walletClient = walletClient;
4312
+ this.publicClient = publicClient;
4313
+ this.clientId = clientId || getDefaultClientId();
4314
+ }
4315
+ /**
4316
+ * Get the address of the connected wallet
4317
+ */
4318
+ get address() {
4319
+ const account = this.walletClient.account;
4320
+ if (!account) {
4321
+ throw new Error("WalletClient must have an account attached");
4322
+ }
4323
+ return account.address;
4324
+ }
4325
+ async getInfos(appIDs, addressCount = 1) {
4326
+ const count = Math.min(addressCount, MAX_ADDRESS_COUNT);
4327
+ const endpoint = `${this.config.userApiServerURL}/info`;
4328
+ const url = `${endpoint}?${new URLSearchParams({ apps: appIDs.join(",") })}`;
4329
+ const res = await this.makeAuthenticatedRequest(url, CanViewSensitiveAppInfoPermission);
4330
+ const result = await res.json();
4331
+ return result.apps.map((app, i) => {
4332
+ const evmAddresses = app.addresses?.data?.evmAddresses?.slice(0, count) || [];
4333
+ const solanaAddresses = app.addresses?.data?.solanaAddresses?.slice(0, count) || [];
4334
+ return {
4335
+ address: appIDs[i],
4336
+ status: app.app_status,
4337
+ ip: app.ip,
4338
+ machineType: app.machine_type,
4339
+ profile: app.profile,
4340
+ metrics: app.metrics,
4341
+ evmAddresses,
4342
+ solanaAddresses
4343
+ };
4344
+ });
4345
+ }
4346
+ /**
4347
+ * Get app details from UserAPI (includes releases and build/provenance info when available).
4348
+ *
4349
+ * Endpoint: GET /apps/:appAddress
4350
+ */
4351
+ async getApp(appAddress) {
4352
+ const endpoint = `${this.config.userApiServerURL}/apps/${appAddress}`;
4353
+ const res = await this.makeAuthenticatedRequest(endpoint);
4354
+ const raw = await res.json();
4355
+ if (!isJsonObject(raw)) {
4356
+ throw new Error("Unexpected /apps/:id response: expected object");
4357
+ }
4358
+ const id = readString(raw, "id");
4359
+ if (!id) {
4360
+ throw new Error("Unexpected /apps/:id response: missing 'id'");
4361
+ }
4362
+ const releasesRaw = raw.releases;
4363
+ const releases = Array.isArray(releasesRaw) ? releasesRaw.map((r) => transformAppRelease(r)).filter((r) => !!r) : [];
4364
+ return {
4365
+ id,
4366
+ creator: readString(raw, "creator"),
4367
+ contractStatus: readString(raw, "contract_status") ?? readString(raw, "contractStatus"),
4368
+ releases
4369
+ };
4370
+ }
4371
+ /**
4372
+ * Get available SKUs (instance types) from UserAPI
4373
+ */
4374
+ async getSKUs() {
4375
+ const endpoint = `${this.config.userApiServerURL}/skus`;
4376
+ const response = await this.makeAuthenticatedRequest(endpoint);
4377
+ const result = await response.json();
4378
+ return {
4379
+ skus: result.skus || result.SKUs || []
4380
+ };
4381
+ }
4382
+ /**
4383
+ * Get logs for an app
4384
+ */
4385
+ async getLogs(appID) {
4386
+ const endpoint = `${this.config.userApiServerURL}/logs/${appID}`;
4387
+ const response = await this.makeAuthenticatedRequest(endpoint, CanViewAppLogsPermission);
4388
+ return await response.text();
4389
+ }
4390
+ /**
4391
+ * Get statuses for apps
4392
+ */
4393
+ async getStatuses(appIDs) {
4394
+ const endpoint = `${this.config.userApiServerURL}/status`;
4395
+ const url = `${endpoint}?${new URLSearchParams({ apps: appIDs.join(",") })}`;
4396
+ const response = await this.makeAuthenticatedRequest(url);
4397
+ const result = await response.json();
4398
+ const apps = result.apps || result.Apps || [];
4399
+ return apps.map((app, i) => ({
4400
+ address: app.address || appIDs[i],
4401
+ status: app.status || app.Status || ""
4402
+ }));
4403
+ }
4404
+ /**
4405
+ * Upload app profile information with optional image
4406
+ *
4407
+ * @param appAddress - The app's contract address
4408
+ * @param name - Display name for the app
4409
+ * @param options - Optional fields including website, description, xURL, and image
4410
+ * @param options.image - Image file as Blob or File (browser: from input element, Node.js: new Blob([buffer]))
4411
+ * @param options.imageName - Filename for the image (required if image is provided)
4412
+ */
4413
+ async uploadAppProfile(appAddress, name, options) {
4414
+ const endpoint = `${this.config.userApiServerURL}/apps/${appAddress}/profile`;
4415
+ const formData = new FormData();
4416
+ formData.append("name", name);
4417
+ if (options?.website) {
4418
+ formData.append("website", options.website);
4419
+ }
4420
+ if (options?.description) {
4421
+ formData.append("description", options.description);
4422
+ }
4423
+ if (options?.xURL) {
4424
+ formData.append("xURL", options.xURL);
4425
+ }
4426
+ if (options?.image) {
4427
+ const fileName = options.image instanceof File ? options.image.name : options.imageName || "image";
4428
+ formData.append("image", options.image, fileName);
4429
+ }
4430
+ const headers = {
4431
+ "x-client-id": this.clientId
4432
+ };
4433
+ const expiry = BigInt(Math.floor(Date.now() / 1e3) + 5 * 60);
4434
+ const authHeaders = await this.generateAuthHeaders(CanUpdateAppProfilePermission, expiry);
4435
+ Object.assign(headers, authHeaders);
4436
+ try {
4437
+ const response = await import_axios.default.post(endpoint, formData, {
4438
+ headers,
4439
+ maxRedirects: 0,
4440
+ validateStatus: () => true,
4441
+ // Don't throw on any status
4442
+ maxContentLength: Infinity,
4443
+ // Allow large file uploads
4444
+ maxBodyLength: Infinity
4445
+ // Allow large file uploads
4446
+ });
4447
+ const status = response.status;
4448
+ if (status !== 200 && status !== 201) {
4449
+ const body = typeof response.data === "string" ? response.data : JSON.stringify(response.data);
4450
+ if (status === 403 && body.includes("Cloudflare") && body.includes("challenge-platform")) {
4451
+ throw new Error(
4452
+ `Cloudflare protection is blocking the request. This is likely due to bot detection.
4453
+ Status: ${status}`
4454
+ );
4455
+ }
4456
+ throw new Error(
4457
+ `UserAPI request failed: ${status} ${status >= 200 && status < 300 ? "OK" : "Error"} - ${body.substring(0, 500)}${body.length > 500 ? "..." : ""}`
4458
+ );
4459
+ }
4460
+ return response.data;
4461
+ } catch (error) {
4462
+ if (error.message?.includes("fetch failed") || error.message?.includes("ECONNREFUSED") || error.message?.includes("ENOTFOUND") || error.cause) {
4463
+ const cause = error.cause?.message || error.cause || error.message;
4464
+ throw new Error(
4465
+ `Failed to connect to UserAPI at ${endpoint}: ${cause}
4466
+ Please check:
4467
+ 1. Your internet connection
4468
+ 2. The API server is accessible: ${this.config.userApiServerURL}
4469
+ 3. Firewall/proxy settings`
4470
+ );
4471
+ }
4472
+ throw error;
4473
+ }
4474
+ }
4475
+ async makeAuthenticatedRequest(url, permission) {
4476
+ const headers = {
4477
+ "x-client-id": this.clientId
4478
+ };
4479
+ if (permission) {
4480
+ const expiry = BigInt(Math.floor(Date.now() / 1e3) + 5 * 60);
4481
+ const authHeaders = await this.generateAuthHeaders(permission, expiry);
4482
+ Object.assign(headers, authHeaders);
4483
+ }
4484
+ try {
4485
+ const response = await import_axios.default.get(url, {
4486
+ headers,
4487
+ maxRedirects: 0,
4488
+ validateStatus: () => true
4489
+ // Don't throw on any status
4490
+ });
4491
+ const status = response.status;
4492
+ const statusText = status >= 200 && status < 300 ? "OK" : "Error";
4493
+ if (status < 200 || status >= 300) {
4494
+ const body = typeof response.data === "string" ? response.data : JSON.stringify(response.data);
4495
+ throw new Error(`UserAPI request failed: ${status} ${statusText} - ${body}`);
4496
+ }
4497
+ return {
4498
+ json: async () => response.data,
4499
+ text: async () => typeof response.data === "string" ? response.data : JSON.stringify(response.data)
4500
+ };
4501
+ } catch (error) {
4502
+ if (error.message?.includes("fetch failed") || error.message?.includes("ECONNREFUSED") || error.message?.includes("ENOTFOUND") || error.cause) {
4503
+ const cause = error.cause?.message || error.cause || error.message;
4504
+ throw new Error(
4505
+ `Failed to connect to UserAPI at ${url}: ${cause}
4506
+ Please check:
4507
+ 1. Your internet connection
4508
+ 2. The API server is accessible: ${this.config.userApiServerURL}
4509
+ 3. Firewall/proxy settings`
4510
+ );
4511
+ }
4512
+ throw error;
4774
4513
  }
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
4514
  }
4791
- return hash;
4515
+ /**
4516
+ * Generate authentication headers for UserAPI requests
4517
+ */
4518
+ async generateAuthHeaders(permission, expiry) {
4519
+ const { signature } = await calculatePermissionSignature({
4520
+ permission,
4521
+ expiry,
4522
+ appControllerAddress: this.config.appControllerAddress,
4523
+ publicClient: this.publicClient,
4524
+ walletClient: this.walletClient
4525
+ });
4526
+ return {
4527
+ Authorization: `Bearer ${stripHexPrefix(signature)}`,
4528
+ "X-eigenx-expiry": expiry.toString()
4529
+ };
4530
+ }
4531
+ };
4532
+ function transformAppReleaseBuild(raw) {
4533
+ if (!isJsonObject(raw)) return void 0;
4534
+ const depsRaw = raw.dependencies;
4535
+ const deps = isJsonObject(depsRaw) ? Object.fromEntries(
4536
+ Object.entries(depsRaw).flatMap(([digest, depRaw]) => {
4537
+ const parsed = transformAppReleaseBuild(depRaw);
4538
+ return parsed ? [[digest, parsed]] : [];
4539
+ })
4540
+ ) : void 0;
4541
+ return {
4542
+ buildId: readString(raw, "build_id") ?? readString(raw, "buildId"),
4543
+ billingAddress: readString(raw, "billing_address") ?? readString(raw, "billingAddress"),
4544
+ repoUrl: readString(raw, "repo_url") ?? readString(raw, "repoUrl"),
4545
+ gitRef: readString(raw, "git_ref") ?? readString(raw, "gitRef"),
4546
+ status: readString(raw, "status"),
4547
+ buildType: readString(raw, "build_type") ?? readString(raw, "buildType"),
4548
+ imageName: readString(raw, "image_name") ?? readString(raw, "imageName"),
4549
+ imageDigest: readString(raw, "image_digest") ?? readString(raw, "imageDigest"),
4550
+ imageUrl: readString(raw, "image_url") ?? readString(raw, "imageUrl"),
4551
+ provenanceJson: raw.provenance_json ?? raw.provenanceJson,
4552
+ provenanceSignature: readString(raw, "provenance_signature") ?? readString(raw, "provenanceSignature"),
4553
+ createdAt: readString(raw, "created_at") ?? readString(raw, "createdAt"),
4554
+ updatedAt: readString(raw, "updated_at") ?? readString(raw, "updatedAt"),
4555
+ errorMessage: readString(raw, "error_message") ?? readString(raw, "errorMessage"),
4556
+ dependencies: deps
4557
+ };
4558
+ }
4559
+ function transformAppRelease(raw) {
4560
+ if (!isJsonObject(raw)) return void 0;
4561
+ return {
4562
+ appId: readString(raw, "appId") ?? readString(raw, "app_id"),
4563
+ rmsReleaseId: readString(raw, "rmsReleaseId") ?? readString(raw, "rms_release_id"),
4564
+ imageDigest: readString(raw, "imageDigest") ?? readString(raw, "image_digest"),
4565
+ registryUrl: readString(raw, "registryUrl") ?? readString(raw, "registry_url"),
4566
+ publicEnv: readString(raw, "publicEnv") ?? readString(raw, "public_env"),
4567
+ encryptedEnv: readString(raw, "encryptedEnv") ?? readString(raw, "encrypted_env"),
4568
+ upgradeByTime: readNumber(raw, "upgradeByTime") ?? readNumber(raw, "upgrade_by_time"),
4569
+ createdAt: readString(raw, "createdAt") ?? readString(raw, "created_at"),
4570
+ createdAtBlock: readString(raw, "createdAtBlock") ?? readString(raw, "created_at_block"),
4571
+ build: raw.build ? transformAppReleaseBuild(raw.build) : void 0
4572
+ };
4792
4573
  }
4793
4574
 
4794
4575
  // src/client/common/contract/watcher.ts
@@ -4796,8 +4577,8 @@ var WATCH_POLL_INTERVAL_SECONDS = 5;
4796
4577
  var APP_STATUS_RUNNING = "Running";
4797
4578
  var APP_STATUS_FAILED = "Failed";
4798
4579
  async function watchUntilRunning(options, logger) {
4799
- const { environmentConfig, appId, privateKey, rpcUrl, clientId } = options;
4800
- const userApiClient = new UserApiClient(environmentConfig, privateKey, rpcUrl, clientId);
4580
+ const { walletClient, publicClient, environmentConfig, appId } = options;
4581
+ const userApiClient = new UserApiClient(environmentConfig, walletClient, publicClient);
4801
4582
  let initialStatus;
4802
4583
  let initialIP;
4803
4584
  let hasChanged = false;
@@ -4846,8 +4627,8 @@ async function watchUntilRunning(options, logger) {
4846
4627
  }
4847
4628
  var APP_STATUS_STOPPED = "Stopped";
4848
4629
  async function watchUntilUpgradeComplete(options, logger) {
4849
- const { environmentConfig, appId, privateKey, rpcUrl, clientId } = options;
4850
- const userApiClient = new UserApiClient(environmentConfig, privateKey, rpcUrl, clientId);
4630
+ const { walletClient, publicClient, environmentConfig, appId } = options;
4631
+ const userApiClient = new UserApiClient(environmentConfig, walletClient, publicClient);
4851
4632
  let initialStatus;
4852
4633
  let initialIP;
4853
4634
  let hasChanged = false;
@@ -4910,7 +4691,7 @@ function sleep(ms) {
4910
4691
 
4911
4692
  // src/client/common/utils/validation.ts
4912
4693
  var import_fs = __toESM(require("fs"), 1);
4913
- var import_viem6 = require("viem");
4694
+ var import_viem5 = require("viem");
4914
4695
  function validateAppName(name) {
4915
4696
  if (!name) {
4916
4697
  throw new Error("App name cannot be empty");
@@ -4958,7 +4739,7 @@ function validateAppID(appID) {
4958
4739
  throw new Error("App ID is required");
4959
4740
  }
4960
4741
  const normalized = typeof appID === "string" ? addHexPrefix(appID) : appID;
4961
- if ((0, import_viem6.isAddress)(normalized)) {
4742
+ if ((0, import_viem5.isAddress)(normalized)) {
4962
4743
  return normalized;
4963
4744
  }
4964
4745
  throw new Error(`Invalid app ID: '${appID}' is not a valid address`);
@@ -4993,68 +4774,142 @@ function validateResourceUsageMonitoring(resourceUsageMonitoring) {
4993
4774
  }
4994
4775
  }
4995
4776
 
4777
+ // src/client/common/config/environment.ts
4778
+ var SEPOLIA_CHAIN_ID = 11155111;
4779
+ var MAINNET_CHAIN_ID = 1;
4780
+ var CommonAddresses = {
4781
+ ERC7702Delegator: "0x63c0c19a282a1b52b07dd5a65b58948a07dae32b"
4782
+ };
4783
+ var ChainAddresses = {
4784
+ [MAINNET_CHAIN_ID]: {
4785
+ PermissionController: "0x25E5F8B1E7aDf44518d35D5B2271f114e081f0E5"
4786
+ },
4787
+ [SEPOLIA_CHAIN_ID]: {
4788
+ PermissionController: "0x44632dfBdCb6D3E21EF613B0ca8A6A0c618F5a37"
4789
+ }
4790
+ };
4791
+ var ENVIRONMENTS = {
4792
+ "sepolia-dev": {
4793
+ name: "sepolia",
4794
+ build: "dev",
4795
+ appControllerAddress: "0xa86DC1C47cb2518327fB4f9A1627F51966c83B92",
4796
+ permissionControllerAddress: ChainAddresses[SEPOLIA_CHAIN_ID].PermissionController,
4797
+ erc7702DelegatorAddress: CommonAddresses.ERC7702Delegator,
4798
+ kmsServerURL: "http://10.128.0.57:8080",
4799
+ userApiServerURL: "https://userapi-compute-sepolia-dev.eigencloud.xyz",
4800
+ defaultRPCURL: "https://ethereum-sepolia-rpc.publicnode.com"
4801
+ },
4802
+ sepolia: {
4803
+ name: "sepolia",
4804
+ build: "prod",
4805
+ appControllerAddress: "0x0dd810a6ffba6a9820a10d97b659f07d8d23d4E2",
4806
+ permissionControllerAddress: ChainAddresses[SEPOLIA_CHAIN_ID].PermissionController,
4807
+ erc7702DelegatorAddress: CommonAddresses.ERC7702Delegator,
4808
+ kmsServerURL: "http://10.128.15.203:8080",
4809
+ userApiServerURL: "https://userapi-compute-sepolia-prod.eigencloud.xyz",
4810
+ defaultRPCURL: "https://ethereum-sepolia-rpc.publicnode.com"
4811
+ },
4812
+ "mainnet-alpha": {
4813
+ name: "mainnet-alpha",
4814
+ build: "prod",
4815
+ appControllerAddress: "0xc38d35Fc995e75342A21CBd6D770305b142Fbe67",
4816
+ permissionControllerAddress: ChainAddresses[MAINNET_CHAIN_ID].PermissionController,
4817
+ erc7702DelegatorAddress: CommonAddresses.ERC7702Delegator,
4818
+ kmsServerURL: "http://10.128.0.2:8080",
4819
+ userApiServerURL: "https://userapi-compute.eigencloud.xyz",
4820
+ defaultRPCURL: "https://ethereum-rpc.publicnode.com"
4821
+ }
4822
+ };
4823
+ var CHAIN_ID_TO_ENVIRONMENT = {
4824
+ [SEPOLIA_CHAIN_ID.toString()]: "sepolia",
4825
+ [MAINNET_CHAIN_ID.toString()]: "mainnet-alpha"
4826
+ };
4827
+ function getEnvironmentConfig(environment, chainID) {
4828
+ const env = ENVIRONMENTS[environment];
4829
+ if (!env) {
4830
+ throw new Error(`Unknown environment: ${environment}`);
4831
+ }
4832
+ if (!isEnvironmentAvailable(environment)) {
4833
+ throw new Error(
4834
+ `Environment ${environment} is not available in this build type. Available environments: ${getAvailableEnvironments().join(", ")}`
4835
+ );
4836
+ }
4837
+ if (chainID) {
4838
+ const expectedEnv = CHAIN_ID_TO_ENVIRONMENT[chainID.toString()];
4839
+ if (expectedEnv && expectedEnv !== environment) {
4840
+ throw new Error(`Environment ${environment} does not match chain ID ${chainID}`);
4841
+ }
4842
+ }
4843
+ const resolvedChainID = chainID || (environment === "sepolia" || environment === "sepolia-dev" ? SEPOLIA_CHAIN_ID : MAINNET_CHAIN_ID);
4844
+ return {
4845
+ ...env,
4846
+ chainID: BigInt(resolvedChainID)
4847
+ };
4848
+ }
4849
+ function getBuildType() {
4850
+ const buildTimeType = true ? "dev"?.toLowerCase() : void 0;
4851
+ const runtimeType = process.env.BUILD_TYPE?.toLowerCase();
4852
+ const buildType = buildTimeType || runtimeType;
4853
+ if (buildType === "dev") {
4854
+ return "dev";
4855
+ }
4856
+ return "prod";
4857
+ }
4858
+ function getAvailableEnvironments() {
4859
+ const buildType = getBuildType();
4860
+ if (buildType === "dev") {
4861
+ return ["sepolia-dev"];
4862
+ }
4863
+ return ["sepolia", "mainnet-alpha"];
4864
+ }
4865
+ function isEnvironmentAvailable(environment) {
4866
+ return getAvailableEnvironments().includes(environment);
4867
+ }
4868
+
4996
4869
  // src/client/common/utils/preflight.ts
4997
- var import_viem7 = require("viem");
4998
- var import_accounts4 = require("viem/accounts");
4999
4870
  async function doPreflightChecks(options, logger) {
5000
- logger.debug("Checking authentication...");
5001
- const privateKey = await getPrivateKeyOrFail(options.privateKey);
4871
+ const { walletClient, publicClient } = options;
5002
4872
  logger.debug("Determining environment...");
5003
4873
  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
- );
4874
+ const account = walletClient.account;
4875
+ if (!account) {
4876
+ throw new Error("WalletClient must have an account attached");
5012
4877
  }
5013
- logger.debug("Testing network connectivity...");
5014
- const publicClient = (0, import_viem7.createPublicClient)({
5015
- transport: (0, import_viem7.http)(rpcUrl)
5016
- });
4878
+ logger.debug("Validating chain ID...");
5017
4879
  try {
5018
4880
  const chainID = await publicClient.getChainId();
5019
4881
  if (BigInt(chainID) !== environmentConfig.chainID) {
5020
4882
  throw new Error(`Chain ID mismatch: expected ${environmentConfig.chainID}, got ${chainID}`);
5021
4883
  }
5022
4884
  } catch (err) {
5023
- throw new Error(`Cannot connect to ${environmentConfig.name} RPC at ${rpcUrl}: ${err.message}`);
4885
+ throw new Error(
4886
+ `Cannot connect to ${environmentConfig.name} RPC at ${publicClient.transport.url}: ${err.message}`
4887
+ );
5024
4888
  }
5025
- const privateKeyHex = addHexPrefix(privateKey);
5026
- const account = (0, import_accounts4.privateKeyToAccount)(privateKeyHex);
5027
- const selfAddress = account.address;
5028
4889
  return {
5029
- privateKey: privateKeyHex,
5030
- rpcUrl,
4890
+ walletClient,
4891
+ publicClient,
5031
4892
  environmentConfig,
5032
- account,
5033
- selfAddress
4893
+ selfAddress: account.address
5034
4894
  };
5035
4895
  }
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
- }
4896
+
4897
+ // src/client/common/utils/logger.ts
4898
+ var defaultLogger = {
4899
+ info: (...args) => console.info(...args),
4900
+ warn: (...args) => console.warn(...args),
4901
+ error: (...args) => console.error(...args),
4902
+ debug: (...args) => console.debug(...args)
4903
+ };
4904
+ var getLogger = (verbose) => ({
4905
+ info: (...args) => console.info(...args),
4906
+ warn: (...args) => console.warn(...args),
4907
+ error: (...args) => console.error(...args),
4908
+ debug: (...args) => verbose && console.debug(...args)
4909
+ });
4910
+
4911
+ // src/client/common/utils/billingapi.ts
4912
+ var import_axios2 = __toESM(require("axios"), 1);
5058
4913
 
5059
4914
  // src/client/common/telemetry/noop.ts
5060
4915
  var NoopClient = class {
@@ -5262,7 +5117,9 @@ async function prepareDeployFromVerifiableBuild(options, logger = defaultLogger)
5262
5117
  }
5263
5118
  },
5264
5119
  async () => {
5265
- if (!options.privateKey) throw new Error("privateKey is required for deployment");
5120
+ if (!options.walletClient.account) {
5121
+ throw new Error("WalletClient must have an account attached");
5122
+ }
5266
5123
  if (!options.imageRef) throw new Error("imageRef is required for deployment");
5267
5124
  if (!options.imageDigest) throw new Error("imageDigest is required for deployment");
5268
5125
  assertValidImageReference(options.imageRef);
@@ -5278,8 +5135,8 @@ async function prepareDeployFromVerifiableBuild(options, logger = defaultLogger)
5278
5135
  logger.debug("Performing preflight checks...");
5279
5136
  const preflightCtx = await doPreflightChecks(
5280
5137
  {
5281
- privateKey: options.privateKey,
5282
- rpcUrl: options.rpcUrl,
5138
+ walletClient: options.walletClient,
5139
+ publicClient: options.publicClient,
5283
5140
  environment: options.environment
5284
5141
  },
5285
5142
  logger
@@ -5289,12 +5146,12 @@ async function prepareDeployFromVerifiableBuild(options, logger = defaultLogger)
5289
5146
  const salt = generateRandomSalt();
5290
5147
  logger.debug(`Generated salt: ${Buffer.from(salt).toString("hex")}`);
5291
5148
  logger.debug("Calculating app ID...");
5292
- const appIDToBeDeployed = await calculateAppID(
5293
- preflightCtx.privateKey,
5294
- options.rpcUrl || preflightCtx.rpcUrl,
5295
- preflightCtx.environmentConfig,
5149
+ const appIDToBeDeployed = await calculateAppID({
5150
+ publicClient: preflightCtx.publicClient,
5151
+ environmentConfig: preflightCtx.environmentConfig,
5152
+ ownerAddress: preflightCtx.selfAddress,
5296
5153
  salt
5297
- );
5154
+ });
5298
5155
  logger.info(``);
5299
5156
  logger.info(`App ID: ${appIDToBeDeployed}`);
5300
5157
  logger.info(``);
@@ -5312,12 +5169,13 @@ async function prepareDeployFromVerifiableBuild(options, logger = defaultLogger)
5312
5169
  logger.debug("Preparing deploy batch...");
5313
5170
  const batch = await prepareDeployBatch(
5314
5171
  {
5315
- privateKey: preflightCtx.privateKey,
5316
- rpcUrl: options.rpcUrl || preflightCtx.rpcUrl,
5172
+ walletClient: preflightCtx.walletClient,
5173
+ publicClient: preflightCtx.publicClient,
5317
5174
  environmentConfig: preflightCtx.environmentConfig,
5318
5175
  salt,
5319
5176
  release,
5320
- publicLogs
5177
+ publicLogs,
5178
+ imageRef: options.imageRef
5321
5179
  },
5322
5180
  logger
5323
5181
  );
@@ -5344,8 +5202,8 @@ async function prepareDeployFromVerifiableBuild(options, logger = defaultLogger)
5344
5202
  );
5345
5203
  }
5346
5204
  function validateDeployOptions(options) {
5347
- if (!options.privateKey) {
5348
- throw new Error("privateKey is required for deployment");
5205
+ if (!options.walletClient.account) {
5206
+ throw new Error("WalletClient must have an account attached");
5349
5207
  }
5350
5208
  if (!options.dockerfilePath && !options.imageRef) {
5351
5209
  throw new Error("Either dockerfilePath or imageRef is required for deployment");
@@ -5384,8 +5242,8 @@ async function deploy(options, logger = defaultLogger) {
5384
5242
  logger.debug("Performing preflight checks...");
5385
5243
  const preflightCtx = await doPreflightChecks(
5386
5244
  {
5387
- privateKey: options.privateKey,
5388
- rpcUrl: options.rpcUrl,
5245
+ walletClient: options.walletClient,
5246
+ publicClient: options.publicClient,
5389
5247
  environment: options.environment
5390
5248
  },
5391
5249
  logger
@@ -5402,12 +5260,12 @@ async function deploy(options, logger = defaultLogger) {
5402
5260
  const salt = generateRandomSalt();
5403
5261
  logger.debug(`Generated salt: ${Buffer.from(salt).toString("hex")}`);
5404
5262
  logger.debug("Calculating app ID...");
5405
- const appIDToBeDeployed = await calculateAppID(
5406
- preflightCtx.privateKey,
5407
- options.rpcUrl || preflightCtx.rpcUrl,
5408
- preflightCtx.environmentConfig,
5263
+ const appIDToBeDeployed = await calculateAppID({
5264
+ publicClient: preflightCtx.publicClient,
5265
+ environmentConfig: preflightCtx.environmentConfig,
5266
+ ownerAddress: preflightCtx.selfAddress,
5409
5267
  salt
5410
- );
5268
+ });
5411
5269
  logger.info(``);
5412
5270
  logger.info(`App ID: ${appIDToBeDeployed}`);
5413
5271
  logger.info(``);
@@ -5428,8 +5286,8 @@ async function deploy(options, logger = defaultLogger) {
5428
5286
  logger.info("Deploying on-chain...");
5429
5287
  const deployResult = await deployApp(
5430
5288
  {
5431
- privateKey: preflightCtx.privateKey,
5432
- rpcUrl: options.rpcUrl || preflightCtx.rpcUrl,
5289
+ walletClient: preflightCtx.walletClient,
5290
+ publicClient: preflightCtx.publicClient,
5433
5291
  environmentConfig: preflightCtx.environmentConfig,
5434
5292
  salt,
5435
5293
  release,
@@ -5442,8 +5300,8 @@ async function deploy(options, logger = defaultLogger) {
5442
5300
  logger.info("Waiting for app to start...");
5443
5301
  const ipAddress = await watchUntilRunning(
5444
5302
  {
5445
- privateKey: preflightCtx.privateKey,
5446
- rpcUrl: options.rpcUrl || preflightCtx.rpcUrl,
5303
+ walletClient: preflightCtx.walletClient,
5304
+ publicClient: preflightCtx.publicClient,
5447
5305
  environmentConfig: preflightCtx.environmentConfig,
5448
5306
  appId: deployResult.appId
5449
5307
  },
@@ -5460,12 +5318,10 @@ async function deploy(options, logger = defaultLogger) {
5460
5318
  );
5461
5319
  }
5462
5320
  async function checkQuotaAvailable(preflightCtx) {
5463
- const rpcUrl = preflightCtx.rpcUrl;
5464
- const environmentConfig = preflightCtx.environmentConfig;
5465
- const userAddress = preflightCtx.selfAddress;
5321
+ const { publicClient, environmentConfig, selfAddress: userAddress } = preflightCtx;
5466
5322
  let maxQuota;
5467
5323
  try {
5468
- maxQuota = await getMaxActiveAppsPerUser(rpcUrl, environmentConfig, userAddress);
5324
+ maxQuota = await getMaxActiveAppsPerUser(publicClient, environmentConfig, userAddress);
5469
5325
  } catch (err) {
5470
5326
  throw new Error(`failed to get quota limit: ${err.message}`);
5471
5327
  }
@@ -5476,7 +5332,7 @@ async function checkQuotaAvailable(preflightCtx) {
5476
5332
  }
5477
5333
  let activeCount;
5478
5334
  try {
5479
- activeCount = await getActiveAppCount(rpcUrl, environmentConfig, userAddress);
5335
+ activeCount = await getActiveAppCount(publicClient, environmentConfig, userAddress);
5480
5336
  } catch (err) {
5481
5337
  throw new Error(`failed to get active app count: ${err.message}`);
5482
5338
  }
@@ -5507,8 +5363,8 @@ async function prepareDeploy(options, logger = defaultLogger) {
5507
5363
  logger.debug("Performing preflight checks...");
5508
5364
  const preflightCtx = await doPreflightChecks(
5509
5365
  {
5510
- privateKey: options.privateKey,
5511
- rpcUrl: options.rpcUrl,
5366
+ walletClient: options.walletClient,
5367
+ publicClient: options.publicClient,
5512
5368
  environment: options.environment
5513
5369
  },
5514
5370
  logger
@@ -5525,12 +5381,12 @@ async function prepareDeploy(options, logger = defaultLogger) {
5525
5381
  const salt = generateRandomSalt();
5526
5382
  logger.debug(`Generated salt: ${Buffer.from(salt).toString("hex")}`);
5527
5383
  logger.debug("Calculating app ID...");
5528
- const appIDToBeDeployed = await calculateAppID(
5529
- preflightCtx.privateKey,
5530
- options.rpcUrl || preflightCtx.rpcUrl,
5531
- preflightCtx.environmentConfig,
5384
+ const appIDToBeDeployed = await calculateAppID({
5385
+ publicClient: preflightCtx.publicClient,
5386
+ environmentConfig: preflightCtx.environmentConfig,
5387
+ ownerAddress: preflightCtx.selfAddress,
5532
5388
  salt
5533
- );
5389
+ });
5534
5390
  logger.info(``);
5535
5391
  logger.info(`App ID: ${appIDToBeDeployed}`);
5536
5392
  logger.info(``);
@@ -5551,12 +5407,13 @@ async function prepareDeploy(options, logger = defaultLogger) {
5551
5407
  logger.debug("Preparing deploy batch...");
5552
5408
  const batch = await prepareDeployBatch(
5553
5409
  {
5554
- privateKey: preflightCtx.privateKey,
5555
- rpcUrl: options.rpcUrl || preflightCtx.rpcUrl,
5410
+ walletClient: preflightCtx.walletClient,
5411
+ publicClient: preflightCtx.publicClient,
5556
5412
  environmentConfig: preflightCtx.environmentConfig,
5557
5413
  salt,
5558
5414
  release,
5559
- publicLogs
5415
+ publicLogs,
5416
+ imageRef: finalImageRef
5560
5417
  },
5561
5418
  logger
5562
5419
  );
@@ -5601,25 +5458,23 @@ async function executeDeploy(options) {
5601
5458
  }
5602
5459
  );
5603
5460
  }
5604
- async function watchDeployment(appId, privateKey, rpcUrl, environment, logger = defaultLogger, clientId, skipTelemetry) {
5461
+ async function watchDeployment(appId, walletClient, publicClient, environmentConfig, logger = defaultLogger, skipTelemetry) {
5605
5462
  return withSDKTelemetry(
5606
5463
  {
5607
5464
  functionName: "watchDeployment",
5608
5465
  skipTelemetry,
5609
5466
  properties: {
5610
- environment
5467
+ environment: environmentConfig.name
5611
5468
  }
5612
5469
  },
5613
5470
  async () => {
5614
- const environmentConfig = getEnvironmentConfig(environment);
5615
5471
  logger.info("Waiting for app to start...");
5616
5472
  return watchUntilRunning(
5617
5473
  {
5618
- privateKey,
5619
- rpcUrl,
5474
+ walletClient,
5475
+ publicClient,
5620
5476
  environmentConfig,
5621
- appId,
5622
- clientId
5477
+ appId
5623
5478
  },
5624
5479
  logger
5625
5480
  );
@@ -5628,18 +5483,12 @@ async function watchDeployment(appId, privateKey, rpcUrl, environment, logger =
5628
5483
  }
5629
5484
 
5630
5485
  // src/client/common/utils/permissions.ts
5631
- var import_viem8 = require("viem");
5632
5486
  var AnyoneCanCallAddress = "0x493219d9949348178af1f58740655951a8cd110c";
5633
5487
  var ApiPermissionsTarget = "0x57ee1fb74c1087e26446abc4fb87fd8f07c43d8d";
5634
5488
  var CanViewAppLogsPermission2 = "0x2fd3f2fe";
5635
5489
  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
5490
  try {
5642
- const canCall = await publicClient.readContract({
5491
+ const canCall = await preflightCtx.publicClient.readContract({
5643
5492
  address: preflightCtx.environmentConfig.permissionControllerAddress,
5644
5493
  abi: PermissionController_default,
5645
5494
  functionName: "canCall",
@@ -5666,8 +5515,8 @@ async function prepareUpgradeFromVerifiableBuild(options, logger = defaultLogger
5666
5515
  logger.debug("Performing preflight checks...");
5667
5516
  const preflightCtx = await doPreflightChecks(
5668
5517
  {
5669
- privateKey: options.privateKey,
5670
- rpcUrl: options.rpcUrl,
5518
+ walletClient: options.walletClient,
5519
+ publicClient: options.publicClient,
5671
5520
  environment: options.environment
5672
5521
  },
5673
5522
  logger
@@ -5699,13 +5548,14 @@ async function prepareUpgradeFromVerifiableBuild(options, logger = defaultLogger
5699
5548
  const needsPermissionChange = currentlyPublic !== publicLogs;
5700
5549
  logger.debug("Preparing upgrade batch...");
5701
5550
  const batch = await prepareUpgradeBatch({
5702
- privateKey: preflightCtx.privateKey,
5703
- rpcUrl: options.rpcUrl || preflightCtx.rpcUrl,
5551
+ walletClient: preflightCtx.walletClient,
5552
+ publicClient: preflightCtx.publicClient,
5704
5553
  environmentConfig: preflightCtx.environmentConfig,
5705
- appId: appID,
5554
+ appID,
5706
5555
  release,
5707
5556
  publicLogs,
5708
- needsPermissionChange
5557
+ needsPermissionChange,
5558
+ imageRef: options.imageRef
5709
5559
  });
5710
5560
  logger.debug("Estimating gas...");
5711
5561
  const gasEstimate = await estimateBatchGas({
@@ -5729,8 +5579,8 @@ async function prepareUpgradeFromVerifiableBuild(options, logger = defaultLogger
5729
5579
  );
5730
5580
  }
5731
5581
  function validateUpgradeOptions(options) {
5732
- if (!options.privateKey) {
5733
- throw new Error("privateKey is required for upgrade");
5582
+ if (!options.walletClient?.account) {
5583
+ throw new Error("walletClient with account is required for upgrade");
5734
5584
  }
5735
5585
  if (!options.appId) {
5736
5586
  throw new Error("appId is required for upgrade");
@@ -5767,8 +5617,8 @@ async function upgrade(options, logger = defaultLogger) {
5767
5617
  logger.debug("Performing preflight checks...");
5768
5618
  const preflightCtx = await doPreflightChecks(
5769
5619
  {
5770
- privateKey: options.privateKey,
5771
- rpcUrl: options.rpcUrl,
5620
+ walletClient: options.walletClient,
5621
+ publicClient: options.publicClient,
5772
5622
  environment: options.environment
5773
5623
  },
5774
5624
  logger
@@ -5802,10 +5652,10 @@ async function upgrade(options, logger = defaultLogger) {
5802
5652
  logger.info("Upgrading on-chain...");
5803
5653
  const txHash = await upgradeApp(
5804
5654
  {
5805
- privateKey: preflightCtx.privateKey,
5806
- rpcUrl: options.rpcUrl || preflightCtx.rpcUrl,
5655
+ walletClient: preflightCtx.walletClient,
5656
+ publicClient: preflightCtx.publicClient,
5807
5657
  environmentConfig: preflightCtx.environmentConfig,
5808
- appId: appID,
5658
+ appID,
5809
5659
  release,
5810
5660
  publicLogs,
5811
5661
  needsPermissionChange,
@@ -5817,8 +5667,8 @@ async function upgrade(options, logger = defaultLogger) {
5817
5667
  logger.info("Waiting for upgrade to complete...");
5818
5668
  await watchUntilUpgradeComplete(
5819
5669
  {
5820
- privateKey: preflightCtx.privateKey,
5821
- rpcUrl: options.rpcUrl || preflightCtx.rpcUrl,
5670
+ walletClient: preflightCtx.walletClient,
5671
+ publicClient: preflightCtx.publicClient,
5822
5672
  environmentConfig: preflightCtx.environmentConfig,
5823
5673
  appId: appID
5824
5674
  },
@@ -5845,8 +5695,8 @@ async function prepareUpgrade(options, logger = defaultLogger) {
5845
5695
  logger.debug("Performing preflight checks...");
5846
5696
  const preflightCtx = await doPreflightChecks(
5847
5697
  {
5848
- privateKey: options.privateKey,
5849
- rpcUrl: options.rpcUrl,
5698
+ walletClient: options.walletClient,
5699
+ publicClient: options.publicClient,
5850
5700
  environment: options.environment
5851
5701
  },
5852
5702
  logger
@@ -5879,13 +5729,14 @@ async function prepareUpgrade(options, logger = defaultLogger) {
5879
5729
  const needsPermissionChange = currentlyPublic !== publicLogs;
5880
5730
  logger.debug("Preparing upgrade batch...");
5881
5731
  const batch = await prepareUpgradeBatch({
5882
- privateKey: preflightCtx.privateKey,
5883
- rpcUrl: options.rpcUrl || preflightCtx.rpcUrl,
5732
+ walletClient: preflightCtx.walletClient,
5733
+ publicClient: preflightCtx.publicClient,
5884
5734
  environmentConfig: preflightCtx.environmentConfig,
5885
- appId: appID,
5735
+ appID,
5886
5736
  release,
5887
5737
  publicLogs,
5888
- needsPermissionChange
5738
+ needsPermissionChange,
5739
+ imageRef: finalImageRef
5889
5740
  });
5890
5741
  logger.debug("Estimating gas...");
5891
5742
  const gasEstimate = await estimateBatchGas({
@@ -5926,25 +5777,23 @@ async function executeUpgrade(options) {
5926
5777
  }
5927
5778
  );
5928
5779
  }
5929
- async function watchUpgrade(appId, privateKey, rpcUrl, environment, logger = defaultLogger, clientId, skipTelemetry) {
5780
+ async function watchUpgrade(appId, walletClient, publicClient, environmentConfig, logger = defaultLogger, skipTelemetry) {
5930
5781
  return withSDKTelemetry(
5931
5782
  {
5932
5783
  functionName: "watchUpgrade",
5933
5784
  skipTelemetry,
5934
5785
  properties: {
5935
- environment
5786
+ environment: environmentConfig.name
5936
5787
  }
5937
5788
  },
5938
5789
  async () => {
5939
- const environmentConfig = getEnvironmentConfig(environment);
5940
5790
  logger.info("Waiting for upgrade to complete...");
5941
5791
  await watchUntilUpgradeComplete(
5942
5792
  {
5943
- privateKey,
5944
- rpcUrl,
5793
+ walletClient,
5794
+ publicClient,
5945
5795
  environmentConfig,
5946
- appId,
5947
- clientId
5796
+ appId
5948
5797
  },
5949
5798
  logger
5950
5799
  );
@@ -6508,31 +6357,24 @@ async function watchLogs(appID, userApiClient, initialLogs) {
6508
6357
  }
6509
6358
  console.log("\nStopped watching");
6510
6359
  }
6511
- async function logs(options, logger = defaultLogger, skipTelemetry = false) {
6512
- const skipTelemetryFlag = skipTelemetry || options.skipTelemetry || false;
6360
+ async function logs(options, walletClient, publicClient, environmentConfig, logger = defaultLogger, skipTelemetry = false) {
6513
6361
  return withSDKTelemetry(
6514
6362
  {
6515
6363
  functionName: "logs",
6516
- skipTelemetry: skipTelemetryFlag,
6517
- properties: { environment: options.environment || "sepolia" }
6364
+ skipTelemetry,
6365
+ properties: { environment: environmentConfig.name }
6518
6366
  },
6519
6367
  async () => {
6520
6368
  console.log();
6521
6369
  if (!options.appID) {
6522
6370
  throw new Error("appID is required for viewing logs");
6523
6371
  }
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
6372
  const appID = validateAppID(options.appID);
6531
6373
  const formattedApp = formatAppDisplay(environmentConfig.name, appID, "");
6532
6374
  const userApiClient = new UserApiClient(
6533
6375
  environmentConfig,
6534
- options.privateKey,
6535
- rpcUrl,
6376
+ walletClient,
6377
+ publicClient,
6536
6378
  options.clientId
6537
6379
  );
6538
6380
  let logsText;
@@ -6609,35 +6451,39 @@ async function logs(options, logger = defaultLogger, skipTelemetry = false) {
6609
6451
  }
6610
6452
 
6611
6453
  // src/client/modules/compute/app/index.ts
6612
- var CONTROLLER_ABI = (0, import_viem9.parseAbi)([
6454
+ var CONTROLLER_ABI = (0, import_viem6.parseAbi)([
6613
6455
  "function startApp(address appId)",
6614
6456
  "function stopApp(address appId)",
6615
6457
  "function terminateApp(address appId)"
6616
6458
  ]);
6617
6459
  function encodeStartAppData(appId) {
6618
- return (0, import_viem9.encodeFunctionData)({
6460
+ return (0, import_viem6.encodeFunctionData)({
6619
6461
  abi: CONTROLLER_ABI,
6620
6462
  functionName: "startApp",
6621
6463
  args: [appId]
6622
6464
  });
6623
6465
  }
6624
6466
  function encodeStopAppData(appId) {
6625
- return (0, import_viem9.encodeFunctionData)({
6467
+ return (0, import_viem6.encodeFunctionData)({
6626
6468
  abi: CONTROLLER_ABI,
6627
6469
  functionName: "stopApp",
6628
6470
  args: [appId]
6629
6471
  });
6630
6472
  }
6631
6473
  function encodeTerminateAppData(appId) {
6632
- return (0, import_viem9.encodeFunctionData)({
6474
+ return (0, import_viem6.encodeFunctionData)({
6633
6475
  abi: CONTROLLER_ABI,
6634
6476
  functionName: "terminateApp",
6635
6477
  args: [appId]
6636
6478
  });
6637
6479
  }
6638
6480
  function createAppModule(ctx) {
6639
- const privateKey = addHexPrefix(ctx.privateKey);
6481
+ const { walletClient, publicClient } = ctx;
6640
6482
  const skipTelemetry = ctx.skipTelemetry || false;
6483
+ if (!walletClient.account) {
6484
+ throw new Error("WalletClient must have an account attached");
6485
+ }
6486
+ const account = walletClient.account;
6641
6487
  const environment = getEnvironmentConfig(ctx.environment);
6642
6488
  const logger = getLogger(ctx.verbose);
6643
6489
  return {
@@ -6648,8 +6494,8 @@ function createAppModule(ctx) {
6648
6494
  async deploy(opts) {
6649
6495
  const result = await deploy(
6650
6496
  {
6651
- privateKey,
6652
- rpcUrl: ctx.rpcUrl,
6497
+ walletClient,
6498
+ publicClient,
6653
6499
  environment: ctx.environment,
6654
6500
  appName: opts.name,
6655
6501
  instanceType: opts.instanceType,
@@ -6673,8 +6519,8 @@ function createAppModule(ctx) {
6673
6519
  const result = await upgrade(
6674
6520
  {
6675
6521
  appId,
6676
- privateKey,
6677
- rpcUrl: ctx.rpcUrl,
6522
+ walletClient,
6523
+ publicClient,
6678
6524
  environment: ctx.environment,
6679
6525
  instanceType: opts.instanceType,
6680
6526
  dockerfilePath: opts.dockerfile,
@@ -6695,8 +6541,8 @@ function createAppModule(ctx) {
6695
6541
  async prepareDeploy(opts) {
6696
6542
  return prepareDeploy(
6697
6543
  {
6698
- privateKey,
6699
- rpcUrl: ctx.rpcUrl,
6544
+ walletClient,
6545
+ publicClient,
6700
6546
  environment: ctx.environment,
6701
6547
  appName: opts.name,
6702
6548
  instanceType: opts.instanceType,
@@ -6713,8 +6559,8 @@ function createAppModule(ctx) {
6713
6559
  async prepareDeployFromVerifiableBuild(opts) {
6714
6560
  return prepareDeployFromVerifiableBuild(
6715
6561
  {
6716
- privateKey,
6717
- rpcUrl: ctx.rpcUrl,
6562
+ walletClient,
6563
+ publicClient,
6718
6564
  environment: ctx.environment,
6719
6565
  appName: opts.name,
6720
6566
  instanceType: opts.instanceType,
@@ -6729,17 +6575,6 @@ function createAppModule(ctx) {
6729
6575
  );
6730
6576
  },
6731
6577
  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
6578
  const result = await executeDeploy({
6744
6579
  prepared,
6745
6580
  context: {
@@ -6761,11 +6596,10 @@ function createAppModule(ctx) {
6761
6596
  async watchDeployment(appId) {
6762
6597
  return watchDeployment(
6763
6598
  appId,
6764
- privateKey,
6765
- ctx.rpcUrl,
6766
- ctx.environment,
6599
+ walletClient,
6600
+ publicClient,
6601
+ environment,
6767
6602
  logger,
6768
- ctx.clientId,
6769
6603
  skipTelemetry
6770
6604
  );
6771
6605
  },
@@ -6774,8 +6608,8 @@ function createAppModule(ctx) {
6774
6608
  return prepareUpgrade(
6775
6609
  {
6776
6610
  appId,
6777
- privateKey,
6778
- rpcUrl: ctx.rpcUrl,
6611
+ walletClient,
6612
+ publicClient,
6779
6613
  environment: ctx.environment,
6780
6614
  instanceType: opts.instanceType,
6781
6615
  dockerfilePath: opts.dockerfile,
@@ -6792,8 +6626,8 @@ function createAppModule(ctx) {
6792
6626
  return prepareUpgradeFromVerifiableBuild(
6793
6627
  {
6794
6628
  appId,
6795
- privateKey,
6796
- rpcUrl: ctx.rpcUrl,
6629
+ walletClient,
6630
+ publicClient,
6797
6631
  environment: ctx.environment,
6798
6632
  instanceType: opts.instanceType,
6799
6633
  envFilePath: opts.envFile,
@@ -6807,17 +6641,6 @@ function createAppModule(ctx) {
6807
6641
  );
6808
6642
  },
6809
6643
  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
6644
  const result = await executeUpgrade({
6822
6645
  prepared,
6823
6646
  context: {
@@ -6836,15 +6659,7 @@ function createAppModule(ctx) {
6836
6659
  };
6837
6660
  },
6838
6661
  async watchUpgrade(appId) {
6839
- return watchUpgrade(
6840
- appId,
6841
- privateKey,
6842
- ctx.rpcUrl,
6843
- ctx.environment,
6844
- logger,
6845
- ctx.clientId,
6846
- skipTelemetry
6847
- );
6662
+ return watchUpgrade(appId, walletClient, publicClient, environment, logger, skipTelemetry);
6848
6663
  },
6849
6664
  // Profile management
6850
6665
  async setProfile(appId, profile) {
@@ -6857,33 +6672,32 @@ function createAppModule(ctx) {
6857
6672
  async () => {
6858
6673
  const userApiClient = new UserApiClient(
6859
6674
  environment,
6860
- privateKey,
6861
- ctx.rpcUrl,
6675
+ walletClient,
6676
+ publicClient,
6862
6677
  ctx.clientId
6863
6678
  );
6864
- return userApiClient.uploadAppProfile(
6865
- appId,
6866
- profile.name,
6867
- profile.website,
6868
- profile.description,
6869
- profile.xURL,
6870
- profile.imagePath
6871
- );
6679
+ return userApiClient.uploadAppProfile(appId, profile.name, {
6680
+ website: profile.website,
6681
+ description: profile.description,
6682
+ xURL: profile.xURL,
6683
+ image: profile.image,
6684
+ imageName: profile.imageName
6685
+ });
6872
6686
  }
6873
6687
  );
6874
6688
  },
6875
6689
  async logs(opts) {
6876
6690
  return logs(
6877
6691
  {
6878
- privateKey,
6879
6692
  appID: opts.appID,
6880
6693
  watch: opts.watch,
6881
- environment: ctx.environment,
6882
6694
  clientId: ctx.clientId
6883
6695
  },
6696
+ walletClient,
6697
+ publicClient,
6698
+ environment,
6884
6699
  logger,
6885
6700
  skipTelemetry
6886
- // Skip if called from CLI
6887
6701
  );
6888
6702
  },
6889
6703
  async start(appId, opts) {
@@ -6896,15 +6710,15 @@ function createAppModule(ctx) {
6896
6710
  },
6897
6711
  async () => {
6898
6712
  const pendingMessage = `Starting app ${appId}...`;
6899
- const data = (0, import_viem9.encodeFunctionData)({
6713
+ const data = (0, import_viem6.encodeFunctionData)({
6900
6714
  abi: CONTROLLER_ABI,
6901
6715
  functionName: "startApp",
6902
6716
  args: [appId]
6903
6717
  });
6904
6718
  const tx = await sendAndWaitForTransaction(
6905
6719
  {
6906
- privateKey,
6907
- rpcUrl: ctx.rpcUrl,
6720
+ walletClient,
6721
+ publicClient,
6908
6722
  environmentConfig: environment,
6909
6723
  to: environment.appControllerAddress,
6910
6724
  data,
@@ -6928,15 +6742,15 @@ function createAppModule(ctx) {
6928
6742
  },
6929
6743
  async () => {
6930
6744
  const pendingMessage = `Stopping app ${appId}...`;
6931
- const data = (0, import_viem9.encodeFunctionData)({
6745
+ const data = (0, import_viem6.encodeFunctionData)({
6932
6746
  abi: CONTROLLER_ABI,
6933
6747
  functionName: "stopApp",
6934
6748
  args: [appId]
6935
6749
  });
6936
6750
  const tx = await sendAndWaitForTransaction(
6937
6751
  {
6938
- privateKey,
6939
- rpcUrl: ctx.rpcUrl,
6752
+ walletClient,
6753
+ publicClient,
6940
6754
  environmentConfig: environment,
6941
6755
  to: environment.appControllerAddress,
6942
6756
  data,
@@ -6960,15 +6774,15 @@ function createAppModule(ctx) {
6960
6774
  },
6961
6775
  async () => {
6962
6776
  const pendingMessage = `Terminating app ${appId}...`;
6963
- const data = (0, import_viem9.encodeFunctionData)({
6777
+ const data = (0, import_viem6.encodeFunctionData)({
6964
6778
  abi: CONTROLLER_ABI,
6965
6779
  functionName: "terminateApp",
6966
6780
  args: [appId]
6967
6781
  });
6968
6782
  const tx = await sendAndWaitForTransaction(
6969
6783
  {
6970
- privateKey,
6971
- rpcUrl: ctx.rpcUrl,
6784
+ walletClient,
6785
+ publicClient,
6972
6786
  environmentConfig: environment,
6973
6787
  to: environment.appControllerAddress,
6974
6788
  data,
@@ -6984,9 +6798,9 @@ function createAppModule(ctx) {
6984
6798
  },
6985
6799
  async isDelegated() {
6986
6800
  return isDelegated({
6987
- privateKey,
6988
- rpcUrl: ctx.rpcUrl,
6989
- environmentConfig: environment
6801
+ publicClient,
6802
+ environmentConfig: environment,
6803
+ address: account.address
6990
6804
  });
6991
6805
  },
6992
6806
  async undelegate() {
@@ -7000,8 +6814,8 @@ function createAppModule(ctx) {
7000
6814
  async () => {
7001
6815
  const tx = await undelegate(
7002
6816
  {
7003
- privateKey,
7004
- rpcUrl: ctx.rpcUrl,
6817
+ walletClient,
6818
+ publicClient,
7005
6819
  environmentConfig: environment
7006
6820
  },
7007
6821
  logger