@phala/cloud 0.0.1
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/index.d.mts +2978 -0
- package/dist/index.d.ts +2978 -0
- package/dist/index.js +2433 -0
- package/dist/index.mjs +2349 -0
- package/package.json +50 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,2433 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
AddComposeHashSchema: () => AddComposeHashSchema,
|
|
24
|
+
ApiErrorSchema: () => ApiErrorSchema,
|
|
25
|
+
AvailableNodesSchema: () => AvailableNodesSchema,
|
|
26
|
+
CommitCvmComposeFileUpdateRequestSchema: () => CommitCvmComposeFileUpdateRequestSchema,
|
|
27
|
+
CommitCvmComposeFileUpdateSchema: () => CommitCvmComposeFileUpdateSchema,
|
|
28
|
+
CommitCvmProvisionRequestSchema: () => CommitCvmProvisionRequestSchema,
|
|
29
|
+
CommitCvmProvisionSchema: () => CommitCvmProvisionSchema,
|
|
30
|
+
CurrentUserSchema: () => CurrentUserSchema,
|
|
31
|
+
DeployAppAuthRequestSchema: () => DeployAppAuthRequestSchema,
|
|
32
|
+
DeployAppAuthSchema: () => DeployAppAuthSchema,
|
|
33
|
+
GetAppEnvEncryptPubKeySchema: () => GetAppEnvEncryptPubKeySchema,
|
|
34
|
+
GetCvmComposeFileResultSchema: () => GetCvmComposeFileResultSchema,
|
|
35
|
+
GetCvmInfoSchema: () => GetCvmInfoSchema,
|
|
36
|
+
GetCvmListSchema: () => GetCvmListSchema,
|
|
37
|
+
GetKmsListSchema: () => GetKmsListSchema,
|
|
38
|
+
NetworkError: () => NetworkError,
|
|
39
|
+
ProvisionCvmComposeFileUpdateRequestSchema: () => ProvisionCvmComposeFileUpdateRequestSchema,
|
|
40
|
+
ProvisionCvmComposeFileUpdateResultSchema: () => ProvisionCvmComposeFileUpdateResultSchema,
|
|
41
|
+
ProvisionCvmRequestSchema: () => ProvisionCvmRequestSchema,
|
|
42
|
+
ProvisionCvmSchema: () => ProvisionCvmSchema,
|
|
43
|
+
RequestError: () => RequestError,
|
|
44
|
+
TransactionError: () => TransactionError,
|
|
45
|
+
WalletError: () => WalletError,
|
|
46
|
+
addComposeHash: () => addComposeHash,
|
|
47
|
+
addNetwork: () => addNetwork,
|
|
48
|
+
asHex: () => asHex,
|
|
49
|
+
autoCreateClients: () => autoCreateClients,
|
|
50
|
+
checkBalance: () => checkBalance,
|
|
51
|
+
checkNetworkStatus: () => checkNetworkStatus,
|
|
52
|
+
commitCvmComposeFileUpdate: () => commitCvmComposeFileUpdate,
|
|
53
|
+
commitCvmProvision: () => commitCvmProvision,
|
|
54
|
+
createClient: () => createClient,
|
|
55
|
+
createClientsFromBrowser: () => createClientsFromBrowser,
|
|
56
|
+
createClientsFromPrivateKey: () => createClientsFromPrivateKey,
|
|
57
|
+
createNetworkClients: () => createNetworkClients,
|
|
58
|
+
createTransactionTracker: () => createTransactionTracker,
|
|
59
|
+
deployAppAuth: () => deployAppAuth,
|
|
60
|
+
encryptEnvVars: () => import_encrypt_env_vars2.encryptEnvVars,
|
|
61
|
+
estimateTransactionGas: () => estimateTransactionGas,
|
|
62
|
+
executeBatchTransactions: () => executeBatchTransactions,
|
|
63
|
+
executeTransaction: () => executeTransaction,
|
|
64
|
+
executeTransactionWithRetry: () => executeTransactionWithRetry,
|
|
65
|
+
extractNetworkClients: () => extractNetworkClients,
|
|
66
|
+
getAppEnvEncryptPubKey: () => getAppEnvEncryptPubKey,
|
|
67
|
+
getAvailableNodes: () => getAvailableNodes,
|
|
68
|
+
getComposeHash: () => import_dstack_sdk.getComposeHash,
|
|
69
|
+
getCurrentUser: () => getCurrentUser,
|
|
70
|
+
getCvmComposeFile: () => getCvmComposeFile,
|
|
71
|
+
getCvmInfo: () => getCvmInfo,
|
|
72
|
+
getCvmList: () => getCvmList,
|
|
73
|
+
getErrorMessage: () => getErrorMessage,
|
|
74
|
+
getKmsInfo: () => getKmsInfo,
|
|
75
|
+
getKmsList: () => getKmsList,
|
|
76
|
+
provisionCvm: () => provisionCvm,
|
|
77
|
+
provisionCvmComposeFileUpdate: () => provisionCvmComposeFileUpdate,
|
|
78
|
+
safeAddComposeHash: () => safeAddComposeHash,
|
|
79
|
+
safeCommitCvmComposeFileUpdate: () => safeCommitCvmComposeFileUpdate,
|
|
80
|
+
safeCommitCvmProvision: () => safeCommitCvmProvision,
|
|
81
|
+
safeDeployAppAuth: () => safeDeployAppAuth,
|
|
82
|
+
safeGetAppEnvEncryptPubKey: () => safeGetAppEnvEncryptPubKey,
|
|
83
|
+
safeGetAvailableNodes: () => safeGetAvailableNodes,
|
|
84
|
+
safeGetCurrentUser: () => safeGetCurrentUser,
|
|
85
|
+
safeGetCvmComposeFile: () => safeGetCvmComposeFile,
|
|
86
|
+
safeGetCvmInfo: () => safeGetCvmInfo,
|
|
87
|
+
safeGetCvmList: () => safeGetCvmList,
|
|
88
|
+
safeGetKmsInfo: () => safeGetKmsInfo,
|
|
89
|
+
safeGetKmsList: () => safeGetKmsList,
|
|
90
|
+
safeProvisionCvm: () => safeProvisionCvm,
|
|
91
|
+
safeProvisionCvmComposeFileUpdate: () => safeProvisionCvmComposeFileUpdate,
|
|
92
|
+
safeValidateActionParameters: () => safeValidateActionParameters,
|
|
93
|
+
switchToNetwork: () => switchToNetwork,
|
|
94
|
+
validateActionParameters: () => validateActionParameters,
|
|
95
|
+
validateNetworkPrerequisites: () => validateNetworkPrerequisites,
|
|
96
|
+
verifyEnvEncryptPublicKey: () => import_dstack_sdk2.verifyEnvEncryptPublicKey,
|
|
97
|
+
waitForTransactionReceipt: () => waitForTransactionReceipt
|
|
98
|
+
});
|
|
99
|
+
module.exports = __toCommonJS(index_exports);
|
|
100
|
+
|
|
101
|
+
// src/client.ts
|
|
102
|
+
var import_ofetch = require("ofetch");
|
|
103
|
+
|
|
104
|
+
// src/types/client.ts
|
|
105
|
+
var import_zod = require("zod");
|
|
106
|
+
var ApiErrorSchema = import_zod.z.object({
|
|
107
|
+
detail: import_zod.z.union([
|
|
108
|
+
import_zod.z.string(),
|
|
109
|
+
import_zod.z.array(
|
|
110
|
+
import_zod.z.object({
|
|
111
|
+
msg: import_zod.z.string(),
|
|
112
|
+
type: import_zod.z.string().optional(),
|
|
113
|
+
ctx: import_zod.z.record(import_zod.z.unknown()).optional()
|
|
114
|
+
})
|
|
115
|
+
),
|
|
116
|
+
import_zod.z.record(import_zod.z.unknown())
|
|
117
|
+
]),
|
|
118
|
+
type: import_zod.z.string().optional(),
|
|
119
|
+
code: import_zod.z.string().optional()
|
|
120
|
+
});
|
|
121
|
+
var RequestError = class _RequestError extends Error {
|
|
122
|
+
constructor(message, options) {
|
|
123
|
+
super(message);
|
|
124
|
+
this.name = "RequestError";
|
|
125
|
+
this.isRequestError = true;
|
|
126
|
+
this.status = options?.status;
|
|
127
|
+
this.statusText = options?.statusText;
|
|
128
|
+
this.data = options?.data;
|
|
129
|
+
this.request = options?.request;
|
|
130
|
+
this.response = options?.response;
|
|
131
|
+
this.detail = options?.detail || message;
|
|
132
|
+
this.code = options?.code;
|
|
133
|
+
this.type = options?.type;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Create RequestError from FetchError
|
|
137
|
+
*/
|
|
138
|
+
static fromFetchError(error) {
|
|
139
|
+
const parseResult = ApiErrorSchema.safeParse(error.data);
|
|
140
|
+
if (parseResult.success) {
|
|
141
|
+
return new _RequestError(error.message, {
|
|
142
|
+
status: error.status ?? void 0,
|
|
143
|
+
statusText: error.statusText ?? void 0,
|
|
144
|
+
data: error.data,
|
|
145
|
+
request: error.request ?? void 0,
|
|
146
|
+
response: error.response ?? void 0,
|
|
147
|
+
detail: parseResult.data.detail,
|
|
148
|
+
code: parseResult.data.code ?? void 0,
|
|
149
|
+
type: parseResult.data.type ?? void 0
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
return new _RequestError(error.message, {
|
|
153
|
+
status: error.status ?? void 0,
|
|
154
|
+
statusText: error.statusText ?? void 0,
|
|
155
|
+
data: error.data,
|
|
156
|
+
request: error.request ?? void 0,
|
|
157
|
+
response: error.response ?? void 0,
|
|
158
|
+
detail: error.data?.detail || "Unknown API error",
|
|
159
|
+
code: error.status?.toString() ?? void 0
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Create RequestError from generic Error
|
|
164
|
+
*/
|
|
165
|
+
static fromError(error, request) {
|
|
166
|
+
return new _RequestError(error.message, {
|
|
167
|
+
request: request ?? void 0,
|
|
168
|
+
detail: error.message
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
// src/client.ts
|
|
174
|
+
var Client = class {
|
|
175
|
+
constructor(config = {}) {
|
|
176
|
+
const resolvedConfig = {
|
|
177
|
+
...config,
|
|
178
|
+
apiKey: config.apiKey || process.env.PHALA_CLOUD_API_KEY,
|
|
179
|
+
baseURL: config.baseURL || process.env.PHALA_CLOUD_API_PREFIX || "https://cloud-api.phala.network/api/v1"
|
|
180
|
+
};
|
|
181
|
+
this.config = resolvedConfig;
|
|
182
|
+
if (!resolvedConfig.apiKey) {
|
|
183
|
+
throw new Error(
|
|
184
|
+
"API key is required. Provide it via config.apiKey or set PHALA_CLOUD_API_KEY environment variable."
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
const { apiKey, baseURL, timeout, headers, ...fetchOptions } = resolvedConfig;
|
|
188
|
+
this.fetchInstance = import_ofetch.ofetch.create({
|
|
189
|
+
baseURL,
|
|
190
|
+
timeout: timeout || 3e4,
|
|
191
|
+
headers: {
|
|
192
|
+
"X-API-Key": apiKey,
|
|
193
|
+
"Content-Type": "application/json",
|
|
194
|
+
...headers || {}
|
|
195
|
+
},
|
|
196
|
+
...fetchOptions,
|
|
197
|
+
// Generic handlers for response error (similar to request.ts)
|
|
198
|
+
onResponseError: ({ response }) => {
|
|
199
|
+
console.warn(`HTTP ${response.status}: ${response.url}`);
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Get the underlying ofetch instance for advanced usage
|
|
205
|
+
*/
|
|
206
|
+
get raw() {
|
|
207
|
+
return this.fetchInstance;
|
|
208
|
+
}
|
|
209
|
+
// ===== Direct methods (throw on error) =====
|
|
210
|
+
/**
|
|
211
|
+
* Perform GET request (throws on error)
|
|
212
|
+
*/
|
|
213
|
+
async get(request, options) {
|
|
214
|
+
return this.fetchInstance(request, {
|
|
215
|
+
...options,
|
|
216
|
+
method: "GET"
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Perform POST request (throws on error)
|
|
221
|
+
*/
|
|
222
|
+
async post(request, body, options) {
|
|
223
|
+
return this.fetchInstance(request, {
|
|
224
|
+
...options,
|
|
225
|
+
method: "POST",
|
|
226
|
+
body
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Perform PUT request (throws on error)
|
|
231
|
+
*/
|
|
232
|
+
async put(request, body, options) {
|
|
233
|
+
return this.fetchInstance(request, {
|
|
234
|
+
...options,
|
|
235
|
+
method: "PUT",
|
|
236
|
+
body
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Perform PATCH request (throws on error)
|
|
241
|
+
*/
|
|
242
|
+
async patch(request, body, options) {
|
|
243
|
+
return this.fetchInstance(request, {
|
|
244
|
+
...options,
|
|
245
|
+
method: "PATCH",
|
|
246
|
+
body
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Perform DELETE request (throws on error)
|
|
251
|
+
*/
|
|
252
|
+
async delete(request, options) {
|
|
253
|
+
return this.fetchInstance(request, {
|
|
254
|
+
...options,
|
|
255
|
+
method: "DELETE"
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
// ===== Safe methods (return SafeResult) =====
|
|
259
|
+
/**
|
|
260
|
+
* Safe wrapper for any request method (zod-style result)
|
|
261
|
+
*/
|
|
262
|
+
async safeRequest(fn) {
|
|
263
|
+
try {
|
|
264
|
+
const data = await fn();
|
|
265
|
+
return { success: true, data };
|
|
266
|
+
} catch (error) {
|
|
267
|
+
if (error && typeof error === "object" && "data" in error) {
|
|
268
|
+
const requestError2 = RequestError.fromFetchError(error);
|
|
269
|
+
return { success: false, error: requestError2 };
|
|
270
|
+
}
|
|
271
|
+
if (error instanceof Error) {
|
|
272
|
+
const requestError2 = RequestError.fromError(error);
|
|
273
|
+
return { success: false, error: requestError2 };
|
|
274
|
+
}
|
|
275
|
+
const requestError = new RequestError("Unknown error occurred", {
|
|
276
|
+
detail: "Unknown error occurred"
|
|
277
|
+
});
|
|
278
|
+
return { success: false, error: requestError };
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Safe GET request (returns SafeResult)
|
|
283
|
+
*/
|
|
284
|
+
async safeGet(request, options) {
|
|
285
|
+
return this.safeRequest(() => this.get(request, options));
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Safe POST request (returns SafeResult)
|
|
289
|
+
*/
|
|
290
|
+
async safePost(request, body, options) {
|
|
291
|
+
return this.safeRequest(() => this.post(request, body, options));
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Safe PUT request (returns SafeResult)
|
|
295
|
+
*/
|
|
296
|
+
async safePut(request, body, options) {
|
|
297
|
+
return this.safeRequest(() => this.put(request, body, options));
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Safe PATCH request (returns SafeResult)
|
|
301
|
+
*/
|
|
302
|
+
async safePatch(request, body, options) {
|
|
303
|
+
return this.safeRequest(() => this.patch(request, body, options));
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Safe DELETE request (returns SafeResult)
|
|
307
|
+
*/
|
|
308
|
+
async safeDelete(request, options) {
|
|
309
|
+
return this.safeRequest(() => this.delete(request, options));
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
function createClient(config = {}) {
|
|
313
|
+
return new Client(config);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// src/actions/get_current_user.ts
|
|
317
|
+
var import_zod2 = require("zod");
|
|
318
|
+
|
|
319
|
+
// src/utils/index.ts
|
|
320
|
+
var import_encrypt_env_vars = require("@phala/dstack-sdk/encrypt-env-vars");
|
|
321
|
+
|
|
322
|
+
// src/utils/get_error_message.ts
|
|
323
|
+
function getErrorMessage(error) {
|
|
324
|
+
if (typeof error.detail === "string") {
|
|
325
|
+
return error.detail;
|
|
326
|
+
}
|
|
327
|
+
if (Array.isArray(error.detail)) {
|
|
328
|
+
if (error.detail.length > 0) {
|
|
329
|
+
return error.detail[0]?.msg || "Validation error";
|
|
330
|
+
}
|
|
331
|
+
return "Validation error";
|
|
332
|
+
}
|
|
333
|
+
if (typeof error.detail === "object" && error.detail !== null) {
|
|
334
|
+
return JSON.stringify(error.detail);
|
|
335
|
+
}
|
|
336
|
+
return "Unknown error occurred";
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// src/utils/as-hex.ts
|
|
340
|
+
var import_viem = require("viem");
|
|
341
|
+
function asHex(value) {
|
|
342
|
+
if (typeof value === "string") {
|
|
343
|
+
if (value.startsWith("0x") && (0, import_viem.isHex)(value)) {
|
|
344
|
+
return value;
|
|
345
|
+
} else if ((0, import_viem.isHex)(`0x${value}`)) {
|
|
346
|
+
return `0x${value}`;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
throw new Error(`Invalid hex value: ${value}`);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// src/utils/validate-parameters.ts
|
|
353
|
+
function validateActionParameters(parameters) {
|
|
354
|
+
if (parameters?.schema !== void 0 && parameters?.schema !== false) {
|
|
355
|
+
if (typeof parameters.schema !== "object" || parameters.schema === null || !("parse" in parameters.schema) || typeof parameters.schema.parse !== "function") {
|
|
356
|
+
throw new Error("Invalid schema: must be a Zod schema object, false, or undefined");
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
function safeValidateActionParameters(parameters) {
|
|
361
|
+
if (parameters?.schema !== void 0 && parameters?.schema !== false) {
|
|
362
|
+
if (typeof parameters.schema !== "object" || parameters.schema === null || !("parse" in parameters.schema) || typeof parameters.schema.parse !== "function") {
|
|
363
|
+
return {
|
|
364
|
+
success: false,
|
|
365
|
+
error: {
|
|
366
|
+
name: "ZodError",
|
|
367
|
+
message: "Invalid schema: must be a Zod schema object, false, or undefined",
|
|
368
|
+
issues: [
|
|
369
|
+
{
|
|
370
|
+
code: "invalid_type",
|
|
371
|
+
expected: "object",
|
|
372
|
+
received: typeof parameters.schema,
|
|
373
|
+
path: ["schema"],
|
|
374
|
+
message: "Invalid schema: must be a Zod schema object, false, or undefined"
|
|
375
|
+
}
|
|
376
|
+
]
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
return void 0;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// src/utils/network.ts
|
|
385
|
+
var NetworkError = class extends Error {
|
|
386
|
+
constructor(message, code, details) {
|
|
387
|
+
super(message);
|
|
388
|
+
this.code = code;
|
|
389
|
+
this.details = details;
|
|
390
|
+
this.name = "NetworkError";
|
|
391
|
+
}
|
|
392
|
+
};
|
|
393
|
+
var WalletError = class extends Error {
|
|
394
|
+
constructor(message, code, details) {
|
|
395
|
+
super(message);
|
|
396
|
+
this.code = code;
|
|
397
|
+
this.details = details;
|
|
398
|
+
this.name = "WalletError";
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
var TransactionError = class extends Error {
|
|
402
|
+
constructor(message, hash, details) {
|
|
403
|
+
super(message);
|
|
404
|
+
this.hash = hash;
|
|
405
|
+
this.details = details;
|
|
406
|
+
this.name = "TransactionError";
|
|
407
|
+
}
|
|
408
|
+
};
|
|
409
|
+
function createNetworkClients(publicClient, walletClient, address, chainId) {
|
|
410
|
+
return {
|
|
411
|
+
publicClient,
|
|
412
|
+
walletClient,
|
|
413
|
+
address,
|
|
414
|
+
chainId
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
async function checkNetworkStatus(clients, targetChainId) {
|
|
418
|
+
try {
|
|
419
|
+
const currentChainId = await clients.walletClient.getChainId();
|
|
420
|
+
return {
|
|
421
|
+
isCorrectNetwork: currentChainId === targetChainId,
|
|
422
|
+
currentChainId
|
|
423
|
+
};
|
|
424
|
+
} catch (error) {
|
|
425
|
+
throw new NetworkError(
|
|
426
|
+
`Failed to check network status: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
427
|
+
"NETWORK_CHECK_FAILED",
|
|
428
|
+
error
|
|
429
|
+
);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
async function checkBalance(publicClient, address, minBalance) {
|
|
433
|
+
try {
|
|
434
|
+
const balance = await publicClient.getBalance({ address });
|
|
435
|
+
return {
|
|
436
|
+
address,
|
|
437
|
+
balance,
|
|
438
|
+
sufficient: minBalance ? balance >= minBalance : true,
|
|
439
|
+
required: minBalance
|
|
440
|
+
};
|
|
441
|
+
} catch (error) {
|
|
442
|
+
throw new NetworkError(
|
|
443
|
+
`Failed to check balance: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
444
|
+
"BALANCE_CHECK_FAILED",
|
|
445
|
+
error
|
|
446
|
+
);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
async function waitForTransactionReceipt(publicClient, hash, options = {}) {
|
|
450
|
+
const {
|
|
451
|
+
timeout = 6e4,
|
|
452
|
+
// 60 seconds default
|
|
453
|
+
pollingInterval = 2e3,
|
|
454
|
+
// 2 seconds default
|
|
455
|
+
confirmations = 1
|
|
456
|
+
} = options;
|
|
457
|
+
const startTime = Date.now();
|
|
458
|
+
return new Promise((resolve, reject) => {
|
|
459
|
+
const poll = async () => {
|
|
460
|
+
try {
|
|
461
|
+
const receipt = await publicClient.getTransactionReceipt({ hash });
|
|
462
|
+
if (receipt) {
|
|
463
|
+
if (confirmations > 1) {
|
|
464
|
+
const currentBlock = await publicClient.getBlockNumber();
|
|
465
|
+
const confirmationCount = currentBlock - receipt.blockNumber + 1n;
|
|
466
|
+
if (confirmationCount < BigInt(confirmations)) {
|
|
467
|
+
const elapsed = Date.now() - startTime;
|
|
468
|
+
if (elapsed >= timeout) {
|
|
469
|
+
reject(
|
|
470
|
+
new TransactionError(`Transaction confirmation timeout after ${timeout}ms`, hash)
|
|
471
|
+
);
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
setTimeout(poll, pollingInterval);
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
resolve(receipt);
|
|
479
|
+
} else {
|
|
480
|
+
const elapsed = Date.now() - startTime;
|
|
481
|
+
if (elapsed >= timeout) {
|
|
482
|
+
reject(new TransactionError(`Transaction receipt timeout after ${timeout}ms`, hash));
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
setTimeout(poll, pollingInterval);
|
|
486
|
+
}
|
|
487
|
+
} catch (error) {
|
|
488
|
+
const elapsed = Date.now() - startTime;
|
|
489
|
+
if (elapsed >= timeout) {
|
|
490
|
+
reject(
|
|
491
|
+
new TransactionError(`Transaction receipt timeout after ${timeout}ms`, hash, error)
|
|
492
|
+
);
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
setTimeout(poll, pollingInterval);
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
poll();
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
async function executeTransaction(clients, operation, args, options = {}) {
|
|
502
|
+
const { timeout = 6e4, confirmations = 1, onSubmitted, onConfirmed, onError } = options;
|
|
503
|
+
try {
|
|
504
|
+
const hash = await operation(clients, ...args);
|
|
505
|
+
onSubmitted?.(hash);
|
|
506
|
+
const receipt = await waitForTransactionReceipt(clients.publicClient, hash, {
|
|
507
|
+
timeout,
|
|
508
|
+
confirmations
|
|
509
|
+
});
|
|
510
|
+
const success = receipt.status === "success";
|
|
511
|
+
if (success) {
|
|
512
|
+
onConfirmed?.(receipt);
|
|
513
|
+
} else {
|
|
514
|
+
const error = new TransactionError("Transaction failed on-chain", hash, receipt);
|
|
515
|
+
onError?.(error, hash);
|
|
516
|
+
throw error;
|
|
517
|
+
}
|
|
518
|
+
return {
|
|
519
|
+
hash,
|
|
520
|
+
receipt,
|
|
521
|
+
success
|
|
522
|
+
};
|
|
523
|
+
} catch (error) {
|
|
524
|
+
const txError = error instanceof TransactionError ? error : new TransactionError(
|
|
525
|
+
`Transaction execution failed: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
526
|
+
void 0,
|
|
527
|
+
error
|
|
528
|
+
);
|
|
529
|
+
onError?.(txError, txError.hash);
|
|
530
|
+
throw txError;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
async function extractNetworkClients(publicClient, walletClient) {
|
|
534
|
+
try {
|
|
535
|
+
const address = walletClient.account?.address;
|
|
536
|
+
if (!address) {
|
|
537
|
+
throw new WalletError("WalletClient must have an account", "NO_ACCOUNT");
|
|
538
|
+
}
|
|
539
|
+
const chainId = await walletClient.getChainId();
|
|
540
|
+
return createNetworkClients(publicClient, walletClient, address, chainId);
|
|
541
|
+
} catch (error) {
|
|
542
|
+
throw new WalletError(
|
|
543
|
+
`Failed to extract network clients: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
544
|
+
"EXTRACTION_FAILED",
|
|
545
|
+
error
|
|
546
|
+
);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
async function validateNetworkPrerequisites(clients, requirements) {
|
|
550
|
+
const { targetChainId, minBalance, requiredAddress } = requirements;
|
|
551
|
+
const networkStatus = await checkNetworkStatus(clients, targetChainId);
|
|
552
|
+
const balanceResult = await checkBalance(clients.publicClient, clients.address, minBalance);
|
|
553
|
+
const addressValid = requiredAddress ? clients.address.toLowerCase() === requiredAddress.toLowerCase() : true;
|
|
554
|
+
return {
|
|
555
|
+
networkValid: networkStatus.isCorrectNetwork,
|
|
556
|
+
balanceValid: balanceResult.sufficient,
|
|
557
|
+
addressValid,
|
|
558
|
+
details: {
|
|
559
|
+
currentChainId: networkStatus.currentChainId,
|
|
560
|
+
balance: balanceResult.balance,
|
|
561
|
+
address: clients.address
|
|
562
|
+
}
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
// src/utils/transaction.ts
|
|
567
|
+
function createTransactionTracker() {
|
|
568
|
+
let status = { state: "idle" };
|
|
569
|
+
let timeoutHandle;
|
|
570
|
+
let abortController;
|
|
571
|
+
const updateStatus = (newStatus) => {
|
|
572
|
+
status = { ...status, ...newStatus };
|
|
573
|
+
};
|
|
574
|
+
const reset = () => {
|
|
575
|
+
if (timeoutHandle) {
|
|
576
|
+
clearTimeout(timeoutHandle);
|
|
577
|
+
timeoutHandle = void 0;
|
|
578
|
+
}
|
|
579
|
+
if (abortController) {
|
|
580
|
+
abortController.abort();
|
|
581
|
+
abortController = void 0;
|
|
582
|
+
}
|
|
583
|
+
status = { state: "idle" };
|
|
584
|
+
};
|
|
585
|
+
const abort = () => {
|
|
586
|
+
if (abortController) {
|
|
587
|
+
abortController.abort();
|
|
588
|
+
}
|
|
589
|
+
if (timeoutHandle) {
|
|
590
|
+
clearTimeout(timeoutHandle);
|
|
591
|
+
timeoutHandle = void 0;
|
|
592
|
+
}
|
|
593
|
+
updateStatus({
|
|
594
|
+
state: "error",
|
|
595
|
+
aborted: true,
|
|
596
|
+
error: "Transaction aborted by user"
|
|
597
|
+
});
|
|
598
|
+
};
|
|
599
|
+
const execute = async (operation, clients, args, options = {}) => {
|
|
600
|
+
const {
|
|
601
|
+
timeout = 6e4,
|
|
602
|
+
confirmations = 1,
|
|
603
|
+
onSubmitted,
|
|
604
|
+
onConfirmed,
|
|
605
|
+
onError,
|
|
606
|
+
signal
|
|
607
|
+
} = options;
|
|
608
|
+
try {
|
|
609
|
+
reset();
|
|
610
|
+
abortController = new AbortController();
|
|
611
|
+
if (signal) {
|
|
612
|
+
if (signal.aborted) {
|
|
613
|
+
throw new TransactionError("Operation was aborted before execution");
|
|
614
|
+
}
|
|
615
|
+
signal.addEventListener("abort", () => {
|
|
616
|
+
abort();
|
|
617
|
+
});
|
|
618
|
+
}
|
|
619
|
+
updateStatus({
|
|
620
|
+
state: "submitting",
|
|
621
|
+
startTime: Date.now(),
|
|
622
|
+
error: void 0,
|
|
623
|
+
hash: void 0,
|
|
624
|
+
receipt: void 0,
|
|
625
|
+
aborted: false
|
|
626
|
+
});
|
|
627
|
+
if (abortController.signal.aborted) {
|
|
628
|
+
throw new TransactionError("Transaction aborted");
|
|
629
|
+
}
|
|
630
|
+
const hash = await operation(clients, ...args);
|
|
631
|
+
if (abortController.signal.aborted) {
|
|
632
|
+
throw new TransactionError("Transaction aborted after submission", hash);
|
|
633
|
+
}
|
|
634
|
+
updateStatus({
|
|
635
|
+
state: "pending",
|
|
636
|
+
hash,
|
|
637
|
+
submitTime: Date.now()
|
|
638
|
+
});
|
|
639
|
+
onSubmitted?.(hash);
|
|
640
|
+
if (timeout > 0) {
|
|
641
|
+
timeoutHandle = setTimeout(() => {
|
|
642
|
+
if (status.state === "pending" && !abortController?.signal.aborted) {
|
|
643
|
+
updateStatus({
|
|
644
|
+
state: "timeout",
|
|
645
|
+
error: `Transaction timeout after ${timeout}ms`
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
}, timeout);
|
|
649
|
+
}
|
|
650
|
+
const receipt = await Promise.race([
|
|
651
|
+
waitForTransactionReceipt(clients.publicClient, hash, { timeout, confirmations }),
|
|
652
|
+
new Promise((_, reject) => {
|
|
653
|
+
abortController?.signal.addEventListener("abort", () => {
|
|
654
|
+
reject(new TransactionError("Transaction aborted while waiting for receipt", hash));
|
|
655
|
+
});
|
|
656
|
+
})
|
|
657
|
+
]);
|
|
658
|
+
if (timeoutHandle) {
|
|
659
|
+
clearTimeout(timeoutHandle);
|
|
660
|
+
timeoutHandle = void 0;
|
|
661
|
+
}
|
|
662
|
+
const success = receipt.status === "success";
|
|
663
|
+
updateStatus({
|
|
664
|
+
state: success ? "success" : "error",
|
|
665
|
+
receipt,
|
|
666
|
+
confirmTime: Date.now(),
|
|
667
|
+
error: success ? void 0 : "Transaction failed on-chain"
|
|
668
|
+
});
|
|
669
|
+
if (success) {
|
|
670
|
+
onConfirmed?.(receipt);
|
|
671
|
+
} else {
|
|
672
|
+
const error = new TransactionError("Transaction failed on-chain", hash, receipt);
|
|
673
|
+
onError?.(error, hash);
|
|
674
|
+
throw error;
|
|
675
|
+
}
|
|
676
|
+
return {
|
|
677
|
+
hash,
|
|
678
|
+
receipt,
|
|
679
|
+
success
|
|
680
|
+
};
|
|
681
|
+
} catch (error) {
|
|
682
|
+
const txError = error instanceof TransactionError ? error : new TransactionError(
|
|
683
|
+
`Transaction execution failed: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
684
|
+
status.hash,
|
|
685
|
+
error
|
|
686
|
+
);
|
|
687
|
+
updateStatus({
|
|
688
|
+
state: "error",
|
|
689
|
+
error: txError.message
|
|
690
|
+
});
|
|
691
|
+
onError?.(txError, status.hash);
|
|
692
|
+
throw txError;
|
|
693
|
+
}
|
|
694
|
+
};
|
|
695
|
+
return {
|
|
696
|
+
get status() {
|
|
697
|
+
return { ...status };
|
|
698
|
+
},
|
|
699
|
+
get isIdle() {
|
|
700
|
+
return status.state === "idle";
|
|
701
|
+
},
|
|
702
|
+
get isSubmitting() {
|
|
703
|
+
return status.state === "submitting";
|
|
704
|
+
},
|
|
705
|
+
get isPending() {
|
|
706
|
+
return status.state === "pending";
|
|
707
|
+
},
|
|
708
|
+
get isSuccess() {
|
|
709
|
+
return status.state === "success";
|
|
710
|
+
},
|
|
711
|
+
get isError() {
|
|
712
|
+
return status.state === "error";
|
|
713
|
+
},
|
|
714
|
+
get isTimeout() {
|
|
715
|
+
return status.state === "timeout";
|
|
716
|
+
},
|
|
717
|
+
get isAborted() {
|
|
718
|
+
return status.aborted === true;
|
|
719
|
+
},
|
|
720
|
+
get isComplete() {
|
|
721
|
+
return ["success", "error", "timeout"].includes(status.state);
|
|
722
|
+
},
|
|
723
|
+
abort,
|
|
724
|
+
reset,
|
|
725
|
+
execute
|
|
726
|
+
};
|
|
727
|
+
}
|
|
728
|
+
async function executeBatchTransactions(operations, clients, batchOptions) {
|
|
729
|
+
const { mode, failFast = false, onProgress } = batchOptions;
|
|
730
|
+
const results = [];
|
|
731
|
+
if (mode === "sequential") {
|
|
732
|
+
for (let i = 0; i < operations.length; i++) {
|
|
733
|
+
const op = operations[i];
|
|
734
|
+
if (!op) continue;
|
|
735
|
+
const { operation, args, options } = op;
|
|
736
|
+
try {
|
|
737
|
+
const tracker = createTransactionTracker();
|
|
738
|
+
const result = await tracker.execute(operation, clients, args, options);
|
|
739
|
+
results.push(result);
|
|
740
|
+
onProgress?.(i + 1, operations.length, results);
|
|
741
|
+
} catch (error) {
|
|
742
|
+
const txError = error instanceof Error ? error : new Error(String(error));
|
|
743
|
+
results.push(txError);
|
|
744
|
+
onProgress?.(i + 1, operations.length, results);
|
|
745
|
+
if (failFast) {
|
|
746
|
+
for (let j = i + 1; j < operations.length; j++) {
|
|
747
|
+
results.push(new Error("Cancelled due to previous failure"));
|
|
748
|
+
}
|
|
749
|
+
break;
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
} else {
|
|
754
|
+
const promises = operations.map(async ({ operation, args, options }) => {
|
|
755
|
+
try {
|
|
756
|
+
const tracker = createTransactionTracker();
|
|
757
|
+
return await tracker.execute(operation, clients, args, options);
|
|
758
|
+
} catch (error) {
|
|
759
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
760
|
+
}
|
|
761
|
+
});
|
|
762
|
+
const allResults = await Promise.allSettled(promises);
|
|
763
|
+
results.push(...allResults.map((r) => r.status === "fulfilled" ? r.value : r.reason));
|
|
764
|
+
onProgress?.(operations.length, operations.length, results);
|
|
765
|
+
}
|
|
766
|
+
const successCount = results.filter((r) => !(r instanceof Error)).length;
|
|
767
|
+
const errorCount = results.length - successCount;
|
|
768
|
+
return {
|
|
769
|
+
results,
|
|
770
|
+
successCount,
|
|
771
|
+
errorCount,
|
|
772
|
+
allSuccessful: errorCount === 0
|
|
773
|
+
};
|
|
774
|
+
}
|
|
775
|
+
async function executeTransactionWithRetry(operation, clients, args, options = {}, retryOptions = {}) {
|
|
776
|
+
const {
|
|
777
|
+
maxRetries = 3,
|
|
778
|
+
initialDelay = 1e3,
|
|
779
|
+
maxDelay = 1e4,
|
|
780
|
+
backoffFactor = 2,
|
|
781
|
+
retryCondition = () => true
|
|
782
|
+
} = retryOptions;
|
|
783
|
+
let lastError;
|
|
784
|
+
let delay = initialDelay;
|
|
785
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
786
|
+
try {
|
|
787
|
+
const tracker = createTransactionTracker();
|
|
788
|
+
return await tracker.execute(operation, clients, args, options);
|
|
789
|
+
} catch (error) {
|
|
790
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
791
|
+
if (attempt === maxRetries) {
|
|
792
|
+
break;
|
|
793
|
+
}
|
|
794
|
+
if (!retryCondition(lastError)) {
|
|
795
|
+
break;
|
|
796
|
+
}
|
|
797
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
798
|
+
delay = Math.min(delay * backoffFactor, maxDelay);
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
throw lastError;
|
|
802
|
+
}
|
|
803
|
+
async function estimateTransactionGas(clients, transaction, options = {}) {
|
|
804
|
+
const {
|
|
805
|
+
gasLimitMultiplier = 1.2,
|
|
806
|
+
maxFeePerGasMultiplier = 1.1,
|
|
807
|
+
priorityFeeMultiplier = 1.1
|
|
808
|
+
} = options;
|
|
809
|
+
try {
|
|
810
|
+
const estimatedGas = await clients.publicClient.estimateGas(transaction);
|
|
811
|
+
const gasLimit = BigInt(Math.ceil(Number(estimatedGas) * gasLimitMultiplier));
|
|
812
|
+
let maxFeePerGas;
|
|
813
|
+
let maxPriorityFeePerGas;
|
|
814
|
+
try {
|
|
815
|
+
const feeData = await clients.publicClient.estimateFeesPerGas();
|
|
816
|
+
if (feeData.maxFeePerGas) {
|
|
817
|
+
maxFeePerGas = BigInt(Math.ceil(Number(feeData.maxFeePerGas) * maxFeePerGasMultiplier));
|
|
818
|
+
}
|
|
819
|
+
if (feeData.maxPriorityFeePerGas) {
|
|
820
|
+
maxPriorityFeePerGas = BigInt(
|
|
821
|
+
Math.ceil(Number(feeData.maxPriorityFeePerGas) * priorityFeeMultiplier)
|
|
822
|
+
);
|
|
823
|
+
}
|
|
824
|
+
} catch (error) {
|
|
825
|
+
}
|
|
826
|
+
return {
|
|
827
|
+
gasLimit,
|
|
828
|
+
maxFeePerGas,
|
|
829
|
+
maxPriorityFeePerGas
|
|
830
|
+
};
|
|
831
|
+
} catch (error) {
|
|
832
|
+
throw new TransactionError(
|
|
833
|
+
`Gas estimation failed: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
834
|
+
void 0,
|
|
835
|
+
error
|
|
836
|
+
);
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
// src/utils/client-factories.ts
|
|
841
|
+
var import_viem2 = require("viem");
|
|
842
|
+
var import_accounts = require("viem/accounts");
|
|
843
|
+
function isBrowser() {
|
|
844
|
+
return typeof window !== "undefined" && typeof window.ethereum !== "undefined";
|
|
845
|
+
}
|
|
846
|
+
function getEthereumProvider() {
|
|
847
|
+
if (!isBrowser()) return null;
|
|
848
|
+
const ethereum = window.ethereum;
|
|
849
|
+
return ethereum || null;
|
|
850
|
+
}
|
|
851
|
+
function createClientsFromPrivateKey(chain, privateKey, rpcUrl) {
|
|
852
|
+
try {
|
|
853
|
+
const account = (0, import_accounts.privateKeyToAccount)(privateKey);
|
|
854
|
+
const publicClient = (0, import_viem2.createPublicClient)({
|
|
855
|
+
chain,
|
|
856
|
+
transport: (0, import_viem2.http)(rpcUrl || chain.rpcUrls.default.http[0])
|
|
857
|
+
});
|
|
858
|
+
const walletClient = (0, import_viem2.createWalletClient)({
|
|
859
|
+
account,
|
|
860
|
+
chain,
|
|
861
|
+
transport: (0, import_viem2.http)(rpcUrl || chain.rpcUrls.default.http[0])
|
|
862
|
+
});
|
|
863
|
+
return createNetworkClients(publicClient, walletClient, account.address, chain.id);
|
|
864
|
+
} catch (error) {
|
|
865
|
+
throw new WalletError(
|
|
866
|
+
`Failed to create clients from private key: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
867
|
+
"CLIENT_CREATION_FAILED",
|
|
868
|
+
error
|
|
869
|
+
);
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
async function createClientsFromBrowser(chain, rpcUrl) {
|
|
873
|
+
if (!isBrowser()) {
|
|
874
|
+
throw new WalletError(
|
|
875
|
+
"Browser wallet connection is only available in browser environment",
|
|
876
|
+
"NOT_BROWSER_ENVIRONMENT"
|
|
877
|
+
);
|
|
878
|
+
}
|
|
879
|
+
const provider = getEthereumProvider();
|
|
880
|
+
if (!provider) {
|
|
881
|
+
throw new WalletError(
|
|
882
|
+
"No Ethereum provider found. Please install a wallet like MetaMask.",
|
|
883
|
+
"NO_PROVIDER"
|
|
884
|
+
);
|
|
885
|
+
}
|
|
886
|
+
try {
|
|
887
|
+
const accounts = await provider.request({
|
|
888
|
+
method: "eth_requestAccounts"
|
|
889
|
+
});
|
|
890
|
+
if (!accounts || accounts.length === 0) {
|
|
891
|
+
throw new WalletError("No accounts available", "NO_ACCOUNTS");
|
|
892
|
+
}
|
|
893
|
+
const address = accounts[0];
|
|
894
|
+
const chainId = await provider.request({ method: "eth_chainId" });
|
|
895
|
+
const currentChainId = parseInt(chainId, 16);
|
|
896
|
+
if (currentChainId !== chain.id) {
|
|
897
|
+
await switchToNetwork(provider, chain.id);
|
|
898
|
+
}
|
|
899
|
+
const publicClient = (0, import_viem2.createPublicClient)({
|
|
900
|
+
chain,
|
|
901
|
+
transport: (0, import_viem2.http)(rpcUrl || chain.rpcUrls.default.http[0])
|
|
902
|
+
});
|
|
903
|
+
const walletClient = (0, import_viem2.createWalletClient)({
|
|
904
|
+
account: address,
|
|
905
|
+
chain,
|
|
906
|
+
transport: (0, import_viem2.custom)(provider)
|
|
907
|
+
});
|
|
908
|
+
return createNetworkClients(publicClient, walletClient, address, chain.id);
|
|
909
|
+
} catch (error) {
|
|
910
|
+
if (error instanceof WalletError || error instanceof NetworkError) {
|
|
911
|
+
throw error;
|
|
912
|
+
}
|
|
913
|
+
throw new WalletError(
|
|
914
|
+
`Failed to connect browser wallet: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
915
|
+
"BROWSER_CONNECTION_FAILED",
|
|
916
|
+
error
|
|
917
|
+
);
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
async function switchToNetwork(provider, chainId) {
|
|
921
|
+
try {
|
|
922
|
+
await provider.request({
|
|
923
|
+
method: "wallet_switchEthereumChain",
|
|
924
|
+
params: [{ chainId: `0x${chainId.toString(16)}` }]
|
|
925
|
+
});
|
|
926
|
+
} catch (error) {
|
|
927
|
+
const errorObj = error;
|
|
928
|
+
if (errorObj.code === 4902) {
|
|
929
|
+
throw new NetworkError(
|
|
930
|
+
`Network ${chainId} not found in wallet. Please add it manually.`,
|
|
931
|
+
"NETWORK_NOT_FOUND",
|
|
932
|
+
error
|
|
933
|
+
);
|
|
934
|
+
}
|
|
935
|
+
throw new NetworkError(
|
|
936
|
+
`Failed to switch network: ${errorObj.message || "Unknown error"}`,
|
|
937
|
+
"NETWORK_SWITCH_FAILED",
|
|
938
|
+
error
|
|
939
|
+
);
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
async function addNetwork(provider, config) {
|
|
943
|
+
try {
|
|
944
|
+
await provider.request({
|
|
945
|
+
method: "wallet_addEthereumChain",
|
|
946
|
+
params: [
|
|
947
|
+
{
|
|
948
|
+
chainId: `0x${config.chainId.toString(16)}`,
|
|
949
|
+
chainName: config.name,
|
|
950
|
+
rpcUrls: [config.rpcUrl],
|
|
951
|
+
blockExplorerUrls: config.blockExplorer ? [config.blockExplorer] : void 0,
|
|
952
|
+
nativeCurrency: {
|
|
953
|
+
name: "ETH",
|
|
954
|
+
symbol: "ETH",
|
|
955
|
+
decimals: 18
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
]
|
|
959
|
+
});
|
|
960
|
+
} catch (error) {
|
|
961
|
+
const errorObj = error;
|
|
962
|
+
throw new NetworkError(
|
|
963
|
+
`Failed to add network: ${errorObj.message || "Unknown error"}`,
|
|
964
|
+
"NETWORK_ADD_FAILED",
|
|
965
|
+
error
|
|
966
|
+
);
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
async function autoCreateClients(chain, options = {}) {
|
|
970
|
+
const { privateKey, rpcUrl, preferBrowser = false } = options;
|
|
971
|
+
if (privateKey) {
|
|
972
|
+
return createClientsFromPrivateKey(chain, privateKey, rpcUrl);
|
|
973
|
+
}
|
|
974
|
+
if (isBrowser() && (preferBrowser || !privateKey)) {
|
|
975
|
+
return createClientsFromBrowser(chain, rpcUrl);
|
|
976
|
+
}
|
|
977
|
+
throw new WalletError(
|
|
978
|
+
"No wallet connection method available. Provide a private key for server-side usage or use in browser environment.",
|
|
979
|
+
"NO_CONNECTION_METHOD"
|
|
980
|
+
);
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
// src/actions/get_current_user.ts
|
|
984
|
+
var CurrentUserSchema = import_zod2.z.object({
|
|
985
|
+
username: import_zod2.z.string(),
|
|
986
|
+
email: import_zod2.z.string(),
|
|
987
|
+
credits: import_zod2.z.number(),
|
|
988
|
+
granted_credits: import_zod2.z.number(),
|
|
989
|
+
avatar: import_zod2.z.string(),
|
|
990
|
+
team_name: import_zod2.z.string(),
|
|
991
|
+
team_tier: import_zod2.z.string()
|
|
992
|
+
}).passthrough();
|
|
993
|
+
async function getCurrentUser(client, parameters) {
|
|
994
|
+
validateActionParameters(parameters);
|
|
995
|
+
const response = await client.get("/auth/me");
|
|
996
|
+
if (parameters?.schema === false) {
|
|
997
|
+
return response;
|
|
998
|
+
}
|
|
999
|
+
const schema = parameters?.schema || CurrentUserSchema;
|
|
1000
|
+
return schema.parse(response);
|
|
1001
|
+
}
|
|
1002
|
+
async function safeGetCurrentUser(client, parameters) {
|
|
1003
|
+
const parameterValidationError = safeValidateActionParameters(parameters);
|
|
1004
|
+
if (parameterValidationError) {
|
|
1005
|
+
return parameterValidationError;
|
|
1006
|
+
}
|
|
1007
|
+
const httpResult = await client.safeGet("/auth/me");
|
|
1008
|
+
if (!httpResult.success) {
|
|
1009
|
+
return httpResult;
|
|
1010
|
+
}
|
|
1011
|
+
if (parameters?.schema === false) {
|
|
1012
|
+
return { success: true, data: httpResult.data };
|
|
1013
|
+
}
|
|
1014
|
+
const schema = parameters?.schema || CurrentUserSchema;
|
|
1015
|
+
return schema.safeParse(httpResult.data);
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
// src/actions/get_available_nodes.ts
|
|
1019
|
+
var import_zod4 = require("zod");
|
|
1020
|
+
|
|
1021
|
+
// src/types/kms_info.ts
|
|
1022
|
+
var import_zod3 = require("zod");
|
|
1023
|
+
var KmsInfoSchema = import_zod3.z.object({
|
|
1024
|
+
id: import_zod3.z.string(),
|
|
1025
|
+
slug: import_zod3.z.string().nullable(),
|
|
1026
|
+
url: import_zod3.z.string(),
|
|
1027
|
+
version: import_zod3.z.string(),
|
|
1028
|
+
chain_id: import_zod3.z.number().nullable(),
|
|
1029
|
+
kms_contract_address: import_zod3.z.string().nullable().transform((val) => val),
|
|
1030
|
+
gateway_app_id: import_zod3.z.string().nullable().transform((val) => val)
|
|
1031
|
+
}).passthrough();
|
|
1032
|
+
|
|
1033
|
+
// src/actions/get_available_nodes.ts
|
|
1034
|
+
var AvailableOSImageSchema = import_zod4.z.object({
|
|
1035
|
+
name: import_zod4.z.string(),
|
|
1036
|
+
is_dev: import_zod4.z.boolean(),
|
|
1037
|
+
version: import_zod4.z.tuple([import_zod4.z.number(), import_zod4.z.number(), import_zod4.z.number()]),
|
|
1038
|
+
os_image_hash: import_zod4.z.string().nullable().optional()
|
|
1039
|
+
}).passthrough();
|
|
1040
|
+
var TeepodCapacitySchema = import_zod4.z.object({
|
|
1041
|
+
teepod_id: import_zod4.z.number(),
|
|
1042
|
+
name: import_zod4.z.string(),
|
|
1043
|
+
listed: import_zod4.z.boolean(),
|
|
1044
|
+
resource_score: import_zod4.z.number(),
|
|
1045
|
+
remaining_vcpu: import_zod4.z.number(),
|
|
1046
|
+
remaining_memory: import_zod4.z.number(),
|
|
1047
|
+
remaining_cvm_slots: import_zod4.z.number(),
|
|
1048
|
+
images: import_zod4.z.array(AvailableOSImageSchema),
|
|
1049
|
+
dedicated_for_team_id: import_zod4.z.number().nullable().optional(),
|
|
1050
|
+
support_onchain_kms: import_zod4.z.boolean().optional(),
|
|
1051
|
+
fmspc: import_zod4.z.string().nullable().optional(),
|
|
1052
|
+
device_id: import_zod4.z.string().nullable().optional()
|
|
1053
|
+
}).passthrough();
|
|
1054
|
+
var ResourceThresholdSchema = import_zod4.z.object({
|
|
1055
|
+
max_instances: import_zod4.z.number().nullable().optional(),
|
|
1056
|
+
max_vcpu: import_zod4.z.number().nullable().optional(),
|
|
1057
|
+
max_memory: import_zod4.z.number().nullable().optional(),
|
|
1058
|
+
max_disk: import_zod4.z.number().nullable().optional()
|
|
1059
|
+
}).passthrough();
|
|
1060
|
+
var AvailableNodesSchema = import_zod4.z.object({
|
|
1061
|
+
tier: import_zod4.z.string(),
|
|
1062
|
+
// TeamTier is string enum
|
|
1063
|
+
capacity: ResourceThresholdSchema,
|
|
1064
|
+
nodes: import_zod4.z.array(TeepodCapacitySchema),
|
|
1065
|
+
kms_list: import_zod4.z.array(KmsInfoSchema)
|
|
1066
|
+
}).passthrough();
|
|
1067
|
+
async function getAvailableNodes(client, parameters) {
|
|
1068
|
+
const response = await client.get("/teepods/available");
|
|
1069
|
+
if (parameters?.schema === false) {
|
|
1070
|
+
return response;
|
|
1071
|
+
}
|
|
1072
|
+
const schema = parameters?.schema || AvailableNodesSchema;
|
|
1073
|
+
return schema.parse(response);
|
|
1074
|
+
}
|
|
1075
|
+
async function safeGetAvailableNodes(client, parameters) {
|
|
1076
|
+
const httpResult = await client.safeGet("/teepods/available");
|
|
1077
|
+
if (!httpResult.success) {
|
|
1078
|
+
return httpResult;
|
|
1079
|
+
}
|
|
1080
|
+
if (parameters?.schema === false) {
|
|
1081
|
+
return { success: true, data: httpResult.data };
|
|
1082
|
+
}
|
|
1083
|
+
const schema = parameters?.schema || AvailableNodesSchema;
|
|
1084
|
+
return schema.safeParse(httpResult.data);
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
// src/actions/provision_cvm.ts
|
|
1088
|
+
var import_zod5 = require("zod");
|
|
1089
|
+
var ProvisionCvmSchema = import_zod5.z.object({
|
|
1090
|
+
app_id: import_zod5.z.string().nullable().optional(),
|
|
1091
|
+
app_env_encrypt_pubkey: import_zod5.z.string().nullable().optional(),
|
|
1092
|
+
compose_hash: import_zod5.z.string(),
|
|
1093
|
+
fmspc: import_zod5.z.string().nullable().optional(),
|
|
1094
|
+
device_id: import_zod5.z.string().nullable().optional(),
|
|
1095
|
+
os_image_hash: import_zod5.z.string().nullable().optional(),
|
|
1096
|
+
node_id: import_zod5.z.number().nullable().optional()
|
|
1097
|
+
// Transformed from teepod_id in response
|
|
1098
|
+
}).passthrough();
|
|
1099
|
+
var ProvisionCvmRequestSchema = import_zod5.z.object({
|
|
1100
|
+
node_id: import_zod5.z.number().optional(),
|
|
1101
|
+
// recommended
|
|
1102
|
+
teepod_id: import_zod5.z.number().optional(),
|
|
1103
|
+
// deprecated, for compatibility
|
|
1104
|
+
name: import_zod5.z.string(),
|
|
1105
|
+
image: import_zod5.z.string(),
|
|
1106
|
+
vcpu: import_zod5.z.number(),
|
|
1107
|
+
memory: import_zod5.z.number(),
|
|
1108
|
+
disk_size: import_zod5.z.number(),
|
|
1109
|
+
compose_file: import_zod5.z.object({
|
|
1110
|
+
allowed_envs: import_zod5.z.array(import_zod5.z.string()).optional(),
|
|
1111
|
+
pre_launch_script: import_zod5.z.string().optional(),
|
|
1112
|
+
docker_compose_file: import_zod5.z.string().optional(),
|
|
1113
|
+
name: import_zod5.z.string().optional(),
|
|
1114
|
+
kms_enabled: import_zod5.z.boolean().optional(),
|
|
1115
|
+
public_logs: import_zod5.z.boolean().optional(),
|
|
1116
|
+
public_sysinfo: import_zod5.z.boolean().optional(),
|
|
1117
|
+
gateway_enabled: import_zod5.z.boolean().optional(),
|
|
1118
|
+
// recommended
|
|
1119
|
+
tproxy_enabled: import_zod5.z.boolean().optional()
|
|
1120
|
+
// deprecated, for compatibility
|
|
1121
|
+
}),
|
|
1122
|
+
listed: import_zod5.z.boolean().optional(),
|
|
1123
|
+
instance_type: import_zod5.z.string().nullable().optional(),
|
|
1124
|
+
kms_id: import_zod5.z.string().optional(),
|
|
1125
|
+
env_keys: import_zod5.z.array(import_zod5.z.string()).optional()
|
|
1126
|
+
}).passthrough();
|
|
1127
|
+
function autofillComposeFileName(appCompose) {
|
|
1128
|
+
if (appCompose.compose_file && !appCompose.compose_file.name) {
|
|
1129
|
+
return {
|
|
1130
|
+
...appCompose,
|
|
1131
|
+
compose_file: {
|
|
1132
|
+
...appCompose.compose_file,
|
|
1133
|
+
name: appCompose.name
|
|
1134
|
+
}
|
|
1135
|
+
};
|
|
1136
|
+
}
|
|
1137
|
+
return appCompose;
|
|
1138
|
+
}
|
|
1139
|
+
function handleGatewayCompatibility(appCompose) {
|
|
1140
|
+
if (!appCompose.compose_file) {
|
|
1141
|
+
return appCompose;
|
|
1142
|
+
}
|
|
1143
|
+
const composeFile = { ...appCompose.compose_file };
|
|
1144
|
+
if (typeof composeFile.gateway_enabled === "boolean" && typeof composeFile.tproxy_enabled === "boolean") {
|
|
1145
|
+
delete composeFile.tproxy_enabled;
|
|
1146
|
+
} else if (typeof composeFile.tproxy_enabled === "boolean" && typeof composeFile.gateway_enabled === "undefined") {
|
|
1147
|
+
composeFile.gateway_enabled = composeFile.tproxy_enabled;
|
|
1148
|
+
delete composeFile.tproxy_enabled;
|
|
1149
|
+
if (typeof window !== "undefined" ? window.console : globalThis.console) {
|
|
1150
|
+
console.warn(
|
|
1151
|
+
"[phala/cloud] tproxy_enabled is deprecated, please use gateway_enabled instead. See docs for migration."
|
|
1152
|
+
);
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
return {
|
|
1156
|
+
...appCompose,
|
|
1157
|
+
compose_file: composeFile
|
|
1158
|
+
};
|
|
1159
|
+
}
|
|
1160
|
+
function transformResponse(data, isDefaultSchema) {
|
|
1161
|
+
if (!isDefaultSchema || !data || typeof data !== "object") {
|
|
1162
|
+
return data;
|
|
1163
|
+
}
|
|
1164
|
+
if (data && typeof data === "object" && "teepod_id" in data) {
|
|
1165
|
+
const { teepod_id, ...rest } = data;
|
|
1166
|
+
return { ...rest, node_id: teepod_id };
|
|
1167
|
+
}
|
|
1168
|
+
return data;
|
|
1169
|
+
}
|
|
1170
|
+
async function provisionCvm(client, appCompose, parameters) {
|
|
1171
|
+
validateActionParameters(parameters);
|
|
1172
|
+
const body = handleGatewayCompatibility(autofillComposeFileName(appCompose));
|
|
1173
|
+
let requestBody = { ...body };
|
|
1174
|
+
if (typeof body.node_id === "number") {
|
|
1175
|
+
requestBody = { ...body, teepod_id: body.node_id };
|
|
1176
|
+
delete requestBody.node_id;
|
|
1177
|
+
} else if (typeof body.teepod_id === "number") {
|
|
1178
|
+
console.warn("[phala/cloud] teepod_id is deprecated, please use node_id instead.");
|
|
1179
|
+
}
|
|
1180
|
+
const response = await client.post("/cvms/provision", requestBody);
|
|
1181
|
+
const isDefaultSchema = parameters?.schema === void 0;
|
|
1182
|
+
const transformedData = transformResponse(response, isDefaultSchema);
|
|
1183
|
+
if (parameters?.schema === false) {
|
|
1184
|
+
return transformedData;
|
|
1185
|
+
}
|
|
1186
|
+
const usedSchema = parameters?.schema || ProvisionCvmSchema;
|
|
1187
|
+
return usedSchema.parse(transformedData);
|
|
1188
|
+
}
|
|
1189
|
+
async function safeProvisionCvm(client, appCompose, parameters) {
|
|
1190
|
+
const parameterValidationError = safeValidateActionParameters(parameters);
|
|
1191
|
+
if (parameterValidationError) {
|
|
1192
|
+
return parameterValidationError;
|
|
1193
|
+
}
|
|
1194
|
+
const schema = parameters?.schema;
|
|
1195
|
+
const body = handleGatewayCompatibility(autofillComposeFileName(appCompose));
|
|
1196
|
+
let requestBody = { ...body };
|
|
1197
|
+
if (typeof body.node_id === "number") {
|
|
1198
|
+
requestBody = { ...body, teepod_id: body.node_id };
|
|
1199
|
+
delete requestBody.node_id;
|
|
1200
|
+
} else if (typeof body.teepod_id === "number") {
|
|
1201
|
+
console.warn("[phala/cloud] teepod_id is deprecated, please use node_id instead.");
|
|
1202
|
+
}
|
|
1203
|
+
const httpResult = await client.safePost("/cvms/provision", requestBody);
|
|
1204
|
+
if (!httpResult.success) {
|
|
1205
|
+
return httpResult;
|
|
1206
|
+
}
|
|
1207
|
+
if (schema === false) {
|
|
1208
|
+
return { success: true, data: httpResult.data };
|
|
1209
|
+
}
|
|
1210
|
+
const isDefaultSchema = !schema;
|
|
1211
|
+
const usedSchema = schema || ProvisionCvmSchema;
|
|
1212
|
+
const transformResult = usedSchema.safeParse(transformResponse(httpResult.data, isDefaultSchema));
|
|
1213
|
+
return transformResult;
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
// src/actions/commit_cvm_provision.ts
|
|
1217
|
+
var import_zod6 = require("zod");
|
|
1218
|
+
var CommitCvmProvisionSchema = import_zod6.z.object({
|
|
1219
|
+
id: import_zod6.z.number(),
|
|
1220
|
+
name: import_zod6.z.string(),
|
|
1221
|
+
status: import_zod6.z.string(),
|
|
1222
|
+
teepod_id: import_zod6.z.number(),
|
|
1223
|
+
teepod: import_zod6.z.object({
|
|
1224
|
+
id: import_zod6.z.number(),
|
|
1225
|
+
name: import_zod6.z.string()
|
|
1226
|
+
}).nullable(),
|
|
1227
|
+
user_id: import_zod6.z.number().nullable(),
|
|
1228
|
+
app_id: import_zod6.z.string().nullable(),
|
|
1229
|
+
vm_uuid: import_zod6.z.string().nullable(),
|
|
1230
|
+
instance_id: import_zod6.z.string().nullable(),
|
|
1231
|
+
app_url: import_zod6.z.string().nullable(),
|
|
1232
|
+
base_image: import_zod6.z.string().nullable(),
|
|
1233
|
+
vcpu: import_zod6.z.number(),
|
|
1234
|
+
memory: import_zod6.z.number(),
|
|
1235
|
+
disk_size: import_zod6.z.number(),
|
|
1236
|
+
manifest_version: import_zod6.z.number().nullable(),
|
|
1237
|
+
version: import_zod6.z.string().nullable(),
|
|
1238
|
+
runner: import_zod6.z.string().nullable(),
|
|
1239
|
+
docker_compose_file: import_zod6.z.string().nullable(),
|
|
1240
|
+
features: import_zod6.z.array(import_zod6.z.string()).nullable(),
|
|
1241
|
+
created_at: import_zod6.z.string(),
|
|
1242
|
+
encrypted_env_pubkey: import_zod6.z.string().nullable().optional(),
|
|
1243
|
+
app_auth_contract_address: import_zod6.z.string().nullable().optional(),
|
|
1244
|
+
deployer_address: import_zod6.z.string().nullable().optional()
|
|
1245
|
+
}).passthrough();
|
|
1246
|
+
var CommitCvmProvisionRequestSchema = import_zod6.z.object({
|
|
1247
|
+
encrypted_env: import_zod6.z.string().optional().nullable(),
|
|
1248
|
+
app_id: import_zod6.z.string(),
|
|
1249
|
+
compose_hash: import_zod6.z.string().optional(),
|
|
1250
|
+
kms_id: import_zod6.z.string().optional(),
|
|
1251
|
+
contract_address: import_zod6.z.string().optional(),
|
|
1252
|
+
deployer_address: import_zod6.z.string().optional(),
|
|
1253
|
+
env_keys: import_zod6.z.array(import_zod6.z.string()).optional().nullable()
|
|
1254
|
+
}).passthrough();
|
|
1255
|
+
async function commitCvmProvision(client, payload, parameters) {
|
|
1256
|
+
validateActionParameters(parameters);
|
|
1257
|
+
const response = await client.post("/cvms", payload);
|
|
1258
|
+
if (parameters?.schema === false) {
|
|
1259
|
+
return response;
|
|
1260
|
+
}
|
|
1261
|
+
const schema = parameters?.schema || CommitCvmProvisionSchema;
|
|
1262
|
+
return schema.parse(response);
|
|
1263
|
+
}
|
|
1264
|
+
async function safeCommitCvmProvision(client, payload, parameters) {
|
|
1265
|
+
const parameterValidationError = safeValidateActionParameters(parameters);
|
|
1266
|
+
if (parameterValidationError) {
|
|
1267
|
+
return parameterValidationError;
|
|
1268
|
+
}
|
|
1269
|
+
const httpResult = await client.safePost("/cvms", payload);
|
|
1270
|
+
if (!httpResult.success) {
|
|
1271
|
+
return httpResult;
|
|
1272
|
+
}
|
|
1273
|
+
if (parameters?.schema === false) {
|
|
1274
|
+
return { success: true, data: httpResult.data };
|
|
1275
|
+
}
|
|
1276
|
+
const schema = parameters?.schema || CommitCvmProvisionSchema;
|
|
1277
|
+
const validationResult = schema.safeParse(httpResult.data);
|
|
1278
|
+
return validationResult;
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
// src/actions/deploy_app_auth.ts
|
|
1282
|
+
var import_zod7 = require("zod");
|
|
1283
|
+
var import_viem3 = require("viem");
|
|
1284
|
+
var import_accounts2 = require("viem/accounts");
|
|
1285
|
+
var kmsAuthAbi = [
|
|
1286
|
+
{
|
|
1287
|
+
inputs: [
|
|
1288
|
+
{ name: "deployer", type: "address" },
|
|
1289
|
+
{ name: "disableUpgrades", type: "bool" },
|
|
1290
|
+
{ name: "allowAnyDevice", type: "bool" },
|
|
1291
|
+
{ name: "deviceId", type: "bytes32" },
|
|
1292
|
+
{ name: "composeHash", type: "bytes32" }
|
|
1293
|
+
],
|
|
1294
|
+
name: "deployAndRegisterApp",
|
|
1295
|
+
outputs: [{ name: "", type: "address" }],
|
|
1296
|
+
stateMutability: "nonpayable",
|
|
1297
|
+
type: "function"
|
|
1298
|
+
},
|
|
1299
|
+
{
|
|
1300
|
+
inputs: [
|
|
1301
|
+
{ name: "appId", type: "address", indexed: true },
|
|
1302
|
+
{ name: "deployer", type: "address", indexed: true }
|
|
1303
|
+
],
|
|
1304
|
+
name: "AppDeployedViaFactory",
|
|
1305
|
+
type: "event",
|
|
1306
|
+
anonymous: false
|
|
1307
|
+
},
|
|
1308
|
+
{
|
|
1309
|
+
inputs: [{ name: "appId", type: "address", indexed: false }],
|
|
1310
|
+
name: "AppRegistered",
|
|
1311
|
+
type: "event",
|
|
1312
|
+
anonymous: false
|
|
1313
|
+
}
|
|
1314
|
+
];
|
|
1315
|
+
var DeployAppAuthRequestBaseSchema = import_zod7.z.object({
|
|
1316
|
+
// Chain configuration (conditionally required)
|
|
1317
|
+
chain: import_zod7.z.unknown().optional(),
|
|
1318
|
+
// Contract configuration (required)
|
|
1319
|
+
kmsContractAddress: import_zod7.z.string(),
|
|
1320
|
+
// Authentication mode: either privateKey OR walletClient (required, mutually exclusive)
|
|
1321
|
+
privateKey: import_zod7.z.string().optional(),
|
|
1322
|
+
walletClient: import_zod7.z.unknown().optional(),
|
|
1323
|
+
// Public client (optional, will create default if not provided)
|
|
1324
|
+
publicClient: import_zod7.z.unknown().optional(),
|
|
1325
|
+
// App configuration (optional)
|
|
1326
|
+
allowAnyDevice: import_zod7.z.boolean().optional().default(false),
|
|
1327
|
+
deviceId: import_zod7.z.string().optional().default("0000000000000000000000000000000000000000000000000000000000000000"),
|
|
1328
|
+
composeHash: import_zod7.z.string().optional().default("0000000000000000000000000000000000000000000000000000000000000000"),
|
|
1329
|
+
disableUpgrades: import_zod7.z.boolean().optional().default(false),
|
|
1330
|
+
// Validation configuration (optional)
|
|
1331
|
+
skipPrerequisiteChecks: import_zod7.z.boolean().optional().default(false),
|
|
1332
|
+
minBalance: import_zod7.z.string().optional()
|
|
1333
|
+
// ETH amount as string, e.g., "0.01"
|
|
1334
|
+
}).passthrough();
|
|
1335
|
+
var DeployAppAuthRequestSchema = DeployAppAuthRequestBaseSchema.refine(
|
|
1336
|
+
(data) => {
|
|
1337
|
+
const hasPrivateKey = !!data.privateKey;
|
|
1338
|
+
const hasWalletClient = !!data.walletClient;
|
|
1339
|
+
return hasPrivateKey !== hasWalletClient;
|
|
1340
|
+
},
|
|
1341
|
+
{
|
|
1342
|
+
message: "Either 'privateKey' or 'walletClient' must be provided, but not both",
|
|
1343
|
+
path: ["privateKey", "walletClient"]
|
|
1344
|
+
}
|
|
1345
|
+
).refine(
|
|
1346
|
+
(data) => {
|
|
1347
|
+
const hasPublicClient = !!data.publicClient;
|
|
1348
|
+
const hasWalletClient = !!data.walletClient;
|
|
1349
|
+
const hasChain = !!data.chain;
|
|
1350
|
+
if (hasPublicClient && hasWalletClient) {
|
|
1351
|
+
return true;
|
|
1352
|
+
}
|
|
1353
|
+
return hasChain;
|
|
1354
|
+
},
|
|
1355
|
+
{
|
|
1356
|
+
message: "Chain is required when publicClient or walletClient is not provided",
|
|
1357
|
+
path: ["chain"]
|
|
1358
|
+
}
|
|
1359
|
+
);
|
|
1360
|
+
var DeployAppAuthSchema = import_zod7.z.object({
|
|
1361
|
+
appId: import_zod7.z.string(),
|
|
1362
|
+
appAuthAddress: import_zod7.z.string(),
|
|
1363
|
+
deployer: import_zod7.z.string(),
|
|
1364
|
+
transactionHash: import_zod7.z.string(),
|
|
1365
|
+
blockNumber: import_zod7.z.bigint().optional(),
|
|
1366
|
+
gasUsed: import_zod7.z.bigint().optional()
|
|
1367
|
+
}).passthrough();
|
|
1368
|
+
function parseDeploymentResult(receipt, deployer, kmsContractAddress) {
|
|
1369
|
+
try {
|
|
1370
|
+
const logs = (0, import_viem3.parseEventLogs)({
|
|
1371
|
+
abi: kmsAuthAbi,
|
|
1372
|
+
eventName: "AppDeployedViaFactory",
|
|
1373
|
+
logs: receipt.logs,
|
|
1374
|
+
strict: false
|
|
1375
|
+
});
|
|
1376
|
+
if (logs.length === 0) {
|
|
1377
|
+
if (receipt.status === "reverted") {
|
|
1378
|
+
throw new Error(`Transaction failed: ${receipt.transactionHash}`);
|
|
1379
|
+
}
|
|
1380
|
+
throw new Error(
|
|
1381
|
+
`Transaction ${receipt.transactionHash} has no AppDeployedViaFactory events. The deployment failed. Status: ${receipt.status}. Found ${receipt.logs.length} logs.`
|
|
1382
|
+
);
|
|
1383
|
+
}
|
|
1384
|
+
const deploymentEvent = logs[0];
|
|
1385
|
+
if (!deploymentEvent?.args) {
|
|
1386
|
+
throw new Error("Event has no data");
|
|
1387
|
+
}
|
|
1388
|
+
const { appId, deployer: eventDeployer } = deploymentEvent.args;
|
|
1389
|
+
if (!appId) {
|
|
1390
|
+
throw new Error("Event missing appId");
|
|
1391
|
+
}
|
|
1392
|
+
return {
|
|
1393
|
+
appId,
|
|
1394
|
+
appAuthAddress: appId,
|
|
1395
|
+
deployer,
|
|
1396
|
+
transactionHash: receipt.transactionHash,
|
|
1397
|
+
blockNumber: receipt.blockNumber,
|
|
1398
|
+
gasUsed: receipt.gasUsed
|
|
1399
|
+
};
|
|
1400
|
+
} catch (error) {
|
|
1401
|
+
if (error instanceof Error) {
|
|
1402
|
+
throw error;
|
|
1403
|
+
}
|
|
1404
|
+
throw new Error(`Parse failed: ${error}`);
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
async function deployAppAuth(request, parameters) {
|
|
1408
|
+
const validatedRequest = DeployAppAuthRequestSchema.parse(request);
|
|
1409
|
+
const {
|
|
1410
|
+
chain,
|
|
1411
|
+
kmsContractAddress,
|
|
1412
|
+
privateKey,
|
|
1413
|
+
walletClient: providedWalletClient,
|
|
1414
|
+
publicClient: providedPublicClient,
|
|
1415
|
+
allowAnyDevice: rawAllowAnyDevice = false,
|
|
1416
|
+
deviceId = "0000000000000000000000000000000000000000000000000000000000000000",
|
|
1417
|
+
composeHash = "0000000000000000000000000000000000000000000000000000000000000000",
|
|
1418
|
+
disableUpgrades = false,
|
|
1419
|
+
skipPrerequisiteChecks = false,
|
|
1420
|
+
minBalance,
|
|
1421
|
+
timeout = 12e4,
|
|
1422
|
+
// 2 minutes default
|
|
1423
|
+
retryOptions,
|
|
1424
|
+
signal,
|
|
1425
|
+
onTransactionStateChange,
|
|
1426
|
+
onTransactionSubmitted,
|
|
1427
|
+
onTransactionConfirmed
|
|
1428
|
+
} = validatedRequest;
|
|
1429
|
+
const defaultDeviceId = "0000000000000000000000000000000000000000000000000000000000000000";
|
|
1430
|
+
const hasSpecificDevice = deviceId !== defaultDeviceId && deviceId !== "0x" + defaultDeviceId;
|
|
1431
|
+
const allowAnyDevice = hasSpecificDevice ? false : rawAllowAnyDevice;
|
|
1432
|
+
let publicClient;
|
|
1433
|
+
let walletClient;
|
|
1434
|
+
let deployerAddress;
|
|
1435
|
+
let chainId;
|
|
1436
|
+
if (privateKey) {
|
|
1437
|
+
const account = (0, import_accounts2.privateKeyToAccount)(privateKey);
|
|
1438
|
+
if (providedPublicClient) {
|
|
1439
|
+
if (typeof providedPublicClient !== "object" || !providedPublicClient) {
|
|
1440
|
+
throw new Error("publicClient is invalid");
|
|
1441
|
+
}
|
|
1442
|
+
publicClient = providedPublicClient;
|
|
1443
|
+
} else {
|
|
1444
|
+
if (!chain) {
|
|
1445
|
+
throw new Error("Chain required for publicClient");
|
|
1446
|
+
}
|
|
1447
|
+
publicClient = (0, import_viem3.createPublicClient)({
|
|
1448
|
+
chain,
|
|
1449
|
+
transport: (0, import_viem3.http)()
|
|
1450
|
+
});
|
|
1451
|
+
}
|
|
1452
|
+
if (!chain) {
|
|
1453
|
+
throw new Error("Chain required for walletClient");
|
|
1454
|
+
}
|
|
1455
|
+
walletClient = (0, import_viem3.createWalletClient)({
|
|
1456
|
+
account,
|
|
1457
|
+
chain,
|
|
1458
|
+
transport: (0, import_viem3.http)()
|
|
1459
|
+
});
|
|
1460
|
+
deployerAddress = account.address;
|
|
1461
|
+
chainId = chain.id;
|
|
1462
|
+
} else if (providedWalletClient) {
|
|
1463
|
+
if (typeof providedWalletClient !== "object" || !providedWalletClient) {
|
|
1464
|
+
throw new Error("walletClient is invalid");
|
|
1465
|
+
}
|
|
1466
|
+
walletClient = providedWalletClient;
|
|
1467
|
+
if (providedPublicClient) {
|
|
1468
|
+
if (typeof providedPublicClient !== "object" || !providedPublicClient) {
|
|
1469
|
+
throw new Error("publicClient is invalid");
|
|
1470
|
+
}
|
|
1471
|
+
publicClient = providedPublicClient;
|
|
1472
|
+
} else {
|
|
1473
|
+
if (!chain) {
|
|
1474
|
+
throw new Error("Chain required for publicClient");
|
|
1475
|
+
}
|
|
1476
|
+
publicClient = (0, import_viem3.createPublicClient)({
|
|
1477
|
+
chain,
|
|
1478
|
+
transport: (0, import_viem3.http)()
|
|
1479
|
+
});
|
|
1480
|
+
}
|
|
1481
|
+
if (!walletClient.account?.address) {
|
|
1482
|
+
throw new Error("WalletClient needs an account");
|
|
1483
|
+
}
|
|
1484
|
+
deployerAddress = walletClient.account.address;
|
|
1485
|
+
if (chain) {
|
|
1486
|
+
chainId = chain.id;
|
|
1487
|
+
} else {
|
|
1488
|
+
chainId = await walletClient.getChainId();
|
|
1489
|
+
}
|
|
1490
|
+
} else {
|
|
1491
|
+
throw new Error("Need privateKey or walletClient");
|
|
1492
|
+
}
|
|
1493
|
+
const networkClients = {
|
|
1494
|
+
publicClient,
|
|
1495
|
+
walletClient,
|
|
1496
|
+
address: deployerAddress,
|
|
1497
|
+
chainId
|
|
1498
|
+
};
|
|
1499
|
+
const transactionTracker = createTransactionTracker();
|
|
1500
|
+
if (onTransactionStateChange && typeof onTransactionStateChange === "function") {
|
|
1501
|
+
const pollStatus = () => {
|
|
1502
|
+
onTransactionStateChange(
|
|
1503
|
+
transactionTracker.status
|
|
1504
|
+
);
|
|
1505
|
+
if (!transactionTracker.isComplete) {
|
|
1506
|
+
setTimeout(pollStatus, 100);
|
|
1507
|
+
}
|
|
1508
|
+
};
|
|
1509
|
+
setTimeout(pollStatus, 10);
|
|
1510
|
+
}
|
|
1511
|
+
if (!skipPrerequisiteChecks) {
|
|
1512
|
+
const requirements = {
|
|
1513
|
+
targetChainId: chainId,
|
|
1514
|
+
minBalance: minBalance ? (0, import_viem3.parseEther)(minBalance) : (0, import_viem3.parseEther)("0.001")
|
|
1515
|
+
// Default 0.001 ETH
|
|
1516
|
+
};
|
|
1517
|
+
const validation = await validateNetworkPrerequisites(networkClients, requirements);
|
|
1518
|
+
if (!validation.networkValid) {
|
|
1519
|
+
throw new Error(
|
|
1520
|
+
`Wrong network. Need chain ${requirements.targetChainId}, got ${validation.details.currentChainId}`
|
|
1521
|
+
);
|
|
1522
|
+
}
|
|
1523
|
+
if (!validation.balanceValid) {
|
|
1524
|
+
const requiredEth = Number(requirements.minBalance) / 1e18;
|
|
1525
|
+
const currentEth = Number(validation.details.balance) / 1e18;
|
|
1526
|
+
throw new Error(`Not enough ETH. Need ${requiredEth}, have ${currentEth.toFixed(6)}`);
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
const deviceIdHex = asHex(deviceId);
|
|
1530
|
+
const composeHashHex = asHex(composeHash);
|
|
1531
|
+
const deviceIdBytes = `0x${deviceIdHex.slice(2).padEnd(64, "0")}`;
|
|
1532
|
+
const composeHashBytes = `0x${composeHashHex.slice(2).padEnd(64, "0")}`;
|
|
1533
|
+
const deployOperation = async (clients) => {
|
|
1534
|
+
try {
|
|
1535
|
+
const code = await clients.publicClient.getCode({ address: kmsContractAddress });
|
|
1536
|
+
if (!code || code === "0x") {
|
|
1537
|
+
throw new Error(`No contract at ${kmsContractAddress}`);
|
|
1538
|
+
}
|
|
1539
|
+
} catch (error) {
|
|
1540
|
+
if (error instanceof Error && error.message.includes("No contract at")) {
|
|
1541
|
+
throw error;
|
|
1542
|
+
}
|
|
1543
|
+
}
|
|
1544
|
+
const contractCall = {
|
|
1545
|
+
address: kmsContractAddress,
|
|
1546
|
+
abi: kmsAuthAbi,
|
|
1547
|
+
functionName: "deployAndRegisterApp",
|
|
1548
|
+
args: [
|
|
1549
|
+
clients.address,
|
|
1550
|
+
disableUpgrades,
|
|
1551
|
+
allowAnyDevice,
|
|
1552
|
+
deviceIdBytes,
|
|
1553
|
+
composeHashBytes
|
|
1554
|
+
],
|
|
1555
|
+
account: clients.walletClient.account || clients.address,
|
|
1556
|
+
chain: chain || null
|
|
1557
|
+
};
|
|
1558
|
+
return await clients.walletClient.writeContract(contractCall);
|
|
1559
|
+
};
|
|
1560
|
+
const transactionResult = retryOptions ? await executeTransactionWithRetry(
|
|
1561
|
+
deployOperation,
|
|
1562
|
+
networkClients,
|
|
1563
|
+
[],
|
|
1564
|
+
{
|
|
1565
|
+
timeout,
|
|
1566
|
+
confirmations: 1,
|
|
1567
|
+
onSubmitted: onTransactionSubmitted,
|
|
1568
|
+
onConfirmed: onTransactionConfirmed,
|
|
1569
|
+
signal
|
|
1570
|
+
},
|
|
1571
|
+
retryOptions
|
|
1572
|
+
) : await transactionTracker.execute(deployOperation, networkClients, [], {
|
|
1573
|
+
timeout,
|
|
1574
|
+
confirmations: 1,
|
|
1575
|
+
onSubmitted: onTransactionSubmitted,
|
|
1576
|
+
onConfirmed: onTransactionConfirmed,
|
|
1577
|
+
signal
|
|
1578
|
+
});
|
|
1579
|
+
const result = parseDeploymentResult(
|
|
1580
|
+
transactionResult.receipt,
|
|
1581
|
+
deployerAddress,
|
|
1582
|
+
kmsContractAddress
|
|
1583
|
+
);
|
|
1584
|
+
if (parameters?.schema === false) {
|
|
1585
|
+
return result;
|
|
1586
|
+
}
|
|
1587
|
+
const schema = parameters?.schema || DeployAppAuthSchema;
|
|
1588
|
+
return schema.parse(result);
|
|
1589
|
+
}
|
|
1590
|
+
async function safeDeployAppAuth(request, parameters) {
|
|
1591
|
+
try {
|
|
1592
|
+
const result = await deployAppAuth(request, parameters);
|
|
1593
|
+
return { success: true, data: result };
|
|
1594
|
+
} catch (error) {
|
|
1595
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown deployment error";
|
|
1596
|
+
const requestError = {
|
|
1597
|
+
isRequestError: true,
|
|
1598
|
+
message: errorMessage,
|
|
1599
|
+
status: 500,
|
|
1600
|
+
// Use 500 for blockchain errors since they're not HTTP errors
|
|
1601
|
+
detail: errorMessage
|
|
1602
|
+
};
|
|
1603
|
+
return {
|
|
1604
|
+
success: false,
|
|
1605
|
+
error: requestError
|
|
1606
|
+
};
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1610
|
+
// src/actions/add_compose_hash.ts
|
|
1611
|
+
var import_zod8 = require("zod");
|
|
1612
|
+
var import_viem4 = require("viem");
|
|
1613
|
+
var import_accounts3 = require("viem/accounts");
|
|
1614
|
+
var appAuthAbi = [
|
|
1615
|
+
{
|
|
1616
|
+
inputs: [{ name: "composeHash", type: "bytes32" }],
|
|
1617
|
+
name: "addComposeHash",
|
|
1618
|
+
outputs: [],
|
|
1619
|
+
stateMutability: "nonpayable",
|
|
1620
|
+
type: "function"
|
|
1621
|
+
},
|
|
1622
|
+
{
|
|
1623
|
+
inputs: [{ name: "composeHash", type: "bytes32", indexed: false }],
|
|
1624
|
+
name: "ComposeHashAdded",
|
|
1625
|
+
type: "event",
|
|
1626
|
+
anonymous: false
|
|
1627
|
+
}
|
|
1628
|
+
];
|
|
1629
|
+
var AddComposeHashRequestSchema = import_zod8.z.object({
|
|
1630
|
+
// Chain configuration (conditionally required)
|
|
1631
|
+
chain: import_zod8.z.unknown().optional(),
|
|
1632
|
+
// Contract configuration (required)
|
|
1633
|
+
kmsContractAddress: import_zod8.z.string(),
|
|
1634
|
+
appId: import_zod8.z.string(),
|
|
1635
|
+
composeHash: import_zod8.z.string(),
|
|
1636
|
+
// Authentication mode: either privateKey OR walletClient (required, mutually exclusive)
|
|
1637
|
+
privateKey: import_zod8.z.string().optional(),
|
|
1638
|
+
walletClient: import_zod8.z.unknown().optional(),
|
|
1639
|
+
// Public client (optional, will create default if not provided)
|
|
1640
|
+
publicClient: import_zod8.z.unknown().optional(),
|
|
1641
|
+
// Validation configuration (optional)
|
|
1642
|
+
skipPrerequisiteChecks: import_zod8.z.boolean().optional().default(false),
|
|
1643
|
+
minBalance: import_zod8.z.string().optional(),
|
|
1644
|
+
// ETH amount as string, e.g., "0.01"
|
|
1645
|
+
// Transaction control options
|
|
1646
|
+
timeout: import_zod8.z.number().optional().default(12e4),
|
|
1647
|
+
retryOptions: import_zod8.z.unknown().optional(),
|
|
1648
|
+
signal: import_zod8.z.unknown().optional(),
|
|
1649
|
+
// Progress callbacks
|
|
1650
|
+
onTransactionStateChange: import_zod8.z.function().optional(),
|
|
1651
|
+
onTransactionSubmitted: import_zod8.z.function().optional(),
|
|
1652
|
+
onTransactionConfirmed: import_zod8.z.function().optional()
|
|
1653
|
+
}).passthrough().refine(
|
|
1654
|
+
(data) => {
|
|
1655
|
+
const hasPrivateKey = !!data.privateKey;
|
|
1656
|
+
const hasWalletClient = !!data.walletClient;
|
|
1657
|
+
return hasPrivateKey !== hasWalletClient;
|
|
1658
|
+
},
|
|
1659
|
+
{
|
|
1660
|
+
message: "Either 'privateKey' or 'walletClient' must be provided, but not both",
|
|
1661
|
+
path: ["privateKey", "walletClient"]
|
|
1662
|
+
}
|
|
1663
|
+
).refine(
|
|
1664
|
+
(data) => {
|
|
1665
|
+
const hasPublicClient = !!data.publicClient;
|
|
1666
|
+
const hasWalletClient = !!data.walletClient;
|
|
1667
|
+
const hasChain = !!data.chain;
|
|
1668
|
+
if (hasPublicClient && hasWalletClient) return true;
|
|
1669
|
+
return hasChain;
|
|
1670
|
+
},
|
|
1671
|
+
{
|
|
1672
|
+
message: "Chain is required when publicClient or walletClient is not provided",
|
|
1673
|
+
path: ["chain"]
|
|
1674
|
+
}
|
|
1675
|
+
);
|
|
1676
|
+
var AddComposeHashSchema = import_zod8.z.object({
|
|
1677
|
+
composeHash: import_zod8.z.string(),
|
|
1678
|
+
appId: import_zod8.z.string(),
|
|
1679
|
+
transactionHash: import_zod8.z.string(),
|
|
1680
|
+
blockNumber: import_zod8.z.bigint().optional(),
|
|
1681
|
+
gasUsed: import_zod8.z.bigint().optional()
|
|
1682
|
+
}).passthrough();
|
|
1683
|
+
function parseComposeHashResult(receipt, composeHash, appAuthAddress, appId) {
|
|
1684
|
+
console.log(receipt.logs);
|
|
1685
|
+
try {
|
|
1686
|
+
const logs = (0, import_viem4.parseEventLogs)({
|
|
1687
|
+
abi: appAuthAbi,
|
|
1688
|
+
eventName: "ComposeHashAdded",
|
|
1689
|
+
logs: receipt.logs,
|
|
1690
|
+
strict: false
|
|
1691
|
+
});
|
|
1692
|
+
if (logs.length > 0) {
|
|
1693
|
+
const event = logs[0];
|
|
1694
|
+
if (event?.args?.composeHash !== composeHash) {
|
|
1695
|
+
console.warn(
|
|
1696
|
+
`Event compose hash (${event?.args?.composeHash}) does not match expected (${composeHash})`
|
|
1697
|
+
);
|
|
1698
|
+
}
|
|
1699
|
+
}
|
|
1700
|
+
return {
|
|
1701
|
+
composeHash,
|
|
1702
|
+
appAuthAddress,
|
|
1703
|
+
appId,
|
|
1704
|
+
transactionHash: receipt.transactionHash,
|
|
1705
|
+
blockNumber: receipt.blockNumber,
|
|
1706
|
+
gasUsed: receipt.gasUsed
|
|
1707
|
+
};
|
|
1708
|
+
} catch (parseError) {
|
|
1709
|
+
console.warn("Failed to parse ComposeHashAdded event, returning basic result:", parseError);
|
|
1710
|
+
return {
|
|
1711
|
+
composeHash,
|
|
1712
|
+
appAuthAddress,
|
|
1713
|
+
appId,
|
|
1714
|
+
transactionHash: receipt.transactionHash,
|
|
1715
|
+
blockNumber: receipt.blockNumber,
|
|
1716
|
+
gasUsed: receipt.gasUsed
|
|
1717
|
+
};
|
|
1718
|
+
}
|
|
1719
|
+
}
|
|
1720
|
+
async function addComposeHash(request, parameters) {
|
|
1721
|
+
const validatedRequest = AddComposeHashRequestSchema.parse(request);
|
|
1722
|
+
const {
|
|
1723
|
+
chain,
|
|
1724
|
+
appId,
|
|
1725
|
+
composeHash,
|
|
1726
|
+
privateKey,
|
|
1727
|
+
walletClient: providedWalletClient,
|
|
1728
|
+
publicClient: providedPublicClient,
|
|
1729
|
+
timeout = 12e4,
|
|
1730
|
+
retryOptions,
|
|
1731
|
+
signal,
|
|
1732
|
+
onTransactionStateChange,
|
|
1733
|
+
onTransactionSubmitted,
|
|
1734
|
+
onTransactionConfirmed,
|
|
1735
|
+
skipPrerequisiteChecks = false,
|
|
1736
|
+
minBalance
|
|
1737
|
+
} = validatedRequest;
|
|
1738
|
+
let publicClient;
|
|
1739
|
+
let walletClient;
|
|
1740
|
+
let address;
|
|
1741
|
+
let chainId;
|
|
1742
|
+
const appAuthAddress = appId.startsWith("0x") ? appId : `0x${appId}`;
|
|
1743
|
+
if (privateKey) {
|
|
1744
|
+
const account = (0, import_accounts3.privateKeyToAccount)(privateKey);
|
|
1745
|
+
if (providedPublicClient) {
|
|
1746
|
+
publicClient = providedPublicClient;
|
|
1747
|
+
} else {
|
|
1748
|
+
if (!chain) throw new Error("Chain required when creating publicClient");
|
|
1749
|
+
publicClient = (0, import_viem4.createPublicClient)({ chain, transport: (0, import_viem4.http)() });
|
|
1750
|
+
}
|
|
1751
|
+
if (!chain) throw new Error("Chain required when creating walletClient");
|
|
1752
|
+
walletClient = (0, import_viem4.createWalletClient)({
|
|
1753
|
+
account,
|
|
1754
|
+
chain,
|
|
1755
|
+
transport: (0, import_viem4.http)()
|
|
1756
|
+
});
|
|
1757
|
+
address = account.address;
|
|
1758
|
+
chainId = chain.id;
|
|
1759
|
+
} else if (providedWalletClient) {
|
|
1760
|
+
walletClient = providedWalletClient;
|
|
1761
|
+
if (providedPublicClient) {
|
|
1762
|
+
publicClient = providedPublicClient;
|
|
1763
|
+
} else {
|
|
1764
|
+
if (!chain) throw new Error("Chain required when creating publicClient");
|
|
1765
|
+
publicClient = (0, import_viem4.createPublicClient)({ chain, transport: (0, import_viem4.http)() });
|
|
1766
|
+
}
|
|
1767
|
+
if (!walletClient.account?.address) {
|
|
1768
|
+
throw new Error("WalletClient must have an account with address");
|
|
1769
|
+
}
|
|
1770
|
+
address = walletClient.account.address;
|
|
1771
|
+
chainId = chain ? chain.id : await walletClient.getChainId();
|
|
1772
|
+
} else {
|
|
1773
|
+
throw new Error("Either privateKey or walletClient must be provided");
|
|
1774
|
+
}
|
|
1775
|
+
const networkClients = {
|
|
1776
|
+
publicClient,
|
|
1777
|
+
walletClient,
|
|
1778
|
+
address,
|
|
1779
|
+
chainId
|
|
1780
|
+
};
|
|
1781
|
+
const transactionTracker = createTransactionTracker();
|
|
1782
|
+
if (onTransactionStateChange && typeof onTransactionStateChange === "function") {
|
|
1783
|
+
const pollStatus = () => {
|
|
1784
|
+
onTransactionStateChange(transactionTracker.status);
|
|
1785
|
+
if (!transactionTracker.isComplete) {
|
|
1786
|
+
setTimeout(pollStatus, 100);
|
|
1787
|
+
}
|
|
1788
|
+
};
|
|
1789
|
+
setTimeout(pollStatus, 10);
|
|
1790
|
+
}
|
|
1791
|
+
if (!skipPrerequisiteChecks) {
|
|
1792
|
+
const requirements = {
|
|
1793
|
+
targetChainId: chainId,
|
|
1794
|
+
minBalance: minBalance ? (0, import_viem4.parseEther)(minBalance) : (0, import_viem4.parseEther)("0.001")
|
|
1795
|
+
};
|
|
1796
|
+
const validation = await validateNetworkPrerequisites(networkClients, requirements);
|
|
1797
|
+
if (!validation.networkValid) {
|
|
1798
|
+
throw new Error(
|
|
1799
|
+
`Network mismatch: Expected chain ${requirements.targetChainId}, but wallet is on chain ${validation.details.currentChainId}`
|
|
1800
|
+
);
|
|
1801
|
+
}
|
|
1802
|
+
if (!validation.balanceValid) {
|
|
1803
|
+
const requiredEth = Number(requirements.minBalance) / 1e18;
|
|
1804
|
+
const currentEth = Number(validation.details.balance) / 1e18;
|
|
1805
|
+
throw new Error(
|
|
1806
|
+
`Insufficient balance: Required ${requiredEth} ETH, but account has ${currentEth.toFixed(6)} ETH`
|
|
1807
|
+
);
|
|
1808
|
+
}
|
|
1809
|
+
}
|
|
1810
|
+
const addComposeHashOperation = async (clients) => {
|
|
1811
|
+
const hash = await clients.walletClient.writeContract({
|
|
1812
|
+
address: appAuthAddress,
|
|
1813
|
+
abi: appAuthAbi,
|
|
1814
|
+
functionName: "addComposeHash",
|
|
1815
|
+
args: [asHex(composeHash)],
|
|
1816
|
+
account: clients.walletClient.account || clients.address,
|
|
1817
|
+
chain: chain || null
|
|
1818
|
+
});
|
|
1819
|
+
return hash;
|
|
1820
|
+
};
|
|
1821
|
+
const transactionResult = retryOptions ? await executeTransactionWithRetry(
|
|
1822
|
+
addComposeHashOperation,
|
|
1823
|
+
networkClients,
|
|
1824
|
+
[],
|
|
1825
|
+
{
|
|
1826
|
+
timeout,
|
|
1827
|
+
confirmations: 1,
|
|
1828
|
+
onSubmitted: onTransactionSubmitted,
|
|
1829
|
+
onConfirmed: onTransactionConfirmed,
|
|
1830
|
+
signal
|
|
1831
|
+
},
|
|
1832
|
+
retryOptions
|
|
1833
|
+
) : await transactionTracker.execute(addComposeHashOperation, networkClients, [], {
|
|
1834
|
+
timeout,
|
|
1835
|
+
confirmations: 1,
|
|
1836
|
+
onSubmitted: onTransactionSubmitted,
|
|
1837
|
+
onConfirmed: onTransactionConfirmed,
|
|
1838
|
+
signal
|
|
1839
|
+
});
|
|
1840
|
+
const result = parseComposeHashResult(
|
|
1841
|
+
transactionResult.receipt,
|
|
1842
|
+
asHex(composeHash),
|
|
1843
|
+
appAuthAddress,
|
|
1844
|
+
appId
|
|
1845
|
+
);
|
|
1846
|
+
if (parameters?.schema === false) {
|
|
1847
|
+
return result;
|
|
1848
|
+
}
|
|
1849
|
+
const schema = parameters?.schema || AddComposeHashSchema;
|
|
1850
|
+
return schema.parse(result);
|
|
1851
|
+
}
|
|
1852
|
+
async function safeAddComposeHash(request, parameters) {
|
|
1853
|
+
try {
|
|
1854
|
+
const result = await addComposeHash(request, parameters);
|
|
1855
|
+
return { success: true, data: result };
|
|
1856
|
+
} catch (error) {
|
|
1857
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown blockchain error";
|
|
1858
|
+
return {
|
|
1859
|
+
success: false,
|
|
1860
|
+
error: {
|
|
1861
|
+
isRequestError: true,
|
|
1862
|
+
message: errorMessage,
|
|
1863
|
+
status: 500,
|
|
1864
|
+
// Blockchain errors use 500
|
|
1865
|
+
detail: errorMessage
|
|
1866
|
+
}
|
|
1867
|
+
};
|
|
1868
|
+
}
|
|
1869
|
+
}
|
|
1870
|
+
|
|
1871
|
+
// src/actions/get_cvm_compose_file.ts
|
|
1872
|
+
var import_zod9 = require("zod");
|
|
1873
|
+
var GetCvmComposeFileResultSchema = import_zod9.z.object({
|
|
1874
|
+
allowed_envs: import_zod9.z.array(import_zod9.z.string()).optional(),
|
|
1875
|
+
docker_compose_file: import_zod9.z.string(),
|
|
1876
|
+
features: import_zod9.z.array(import_zod9.z.string()).optional(),
|
|
1877
|
+
name: import_zod9.z.string().optional(),
|
|
1878
|
+
manifest_version: import_zod9.z.number().optional(),
|
|
1879
|
+
kms_enabled: import_zod9.z.boolean().optional(),
|
|
1880
|
+
public_logs: import_zod9.z.boolean().optional(),
|
|
1881
|
+
public_sysinfo: import_zod9.z.boolean().optional(),
|
|
1882
|
+
tproxy_enabled: import_zod9.z.boolean().optional(),
|
|
1883
|
+
pre_launch_script: import_zod9.z.string().optional()
|
|
1884
|
+
}).passthrough();
|
|
1885
|
+
var GetCvmComposeFileRequestSchema = import_zod9.z.object({
|
|
1886
|
+
id: import_zod9.z.string().optional(),
|
|
1887
|
+
uuid: import_zod9.z.string().regex(/^[0-9a-f]{8}[-]?[0-9a-f]{4}[-]?4[0-9a-f]{3}[-]?[89ab][0-9a-f]{3}[-]?[0-9a-f]{12}$/i).optional(),
|
|
1888
|
+
app_id: import_zod9.z.string().refine(
|
|
1889
|
+
(val) => !val.startsWith("app_") && val.length === 40,
|
|
1890
|
+
"app_id should be 40 characters without prefix"
|
|
1891
|
+
).transform((val) => val.startsWith("app_") ? val : `app_${val}`).optional(),
|
|
1892
|
+
instance_id: import_zod9.z.string().refine(
|
|
1893
|
+
(val) => !val.startsWith("instance_") && val.length === 40,
|
|
1894
|
+
"instance_id should be 40 characters without prefix"
|
|
1895
|
+
).transform((val) => val.startsWith("instance_") ? val : `instance_${val}`).optional()
|
|
1896
|
+
}).refine(
|
|
1897
|
+
(data) => !!(data.id || data.uuid || data.app_id || data.instance_id),
|
|
1898
|
+
"One of id, uuid, app_id, or instance_id must be provided"
|
|
1899
|
+
).transform((data) => ({
|
|
1900
|
+
cvmId: data.id || data.uuid || data.app_id || data.instance_id,
|
|
1901
|
+
_raw: data
|
|
1902
|
+
}));
|
|
1903
|
+
async function getCvmComposeFile(client, request, parameters) {
|
|
1904
|
+
const validatedRequest = GetCvmComposeFileRequestSchema.parse(request);
|
|
1905
|
+
const response = await client.get(`/cvms/${validatedRequest.cvmId}/compose_file`);
|
|
1906
|
+
if (parameters?.schema === false) {
|
|
1907
|
+
return response;
|
|
1908
|
+
}
|
|
1909
|
+
const schema = parameters?.schema || GetCvmComposeFileResultSchema;
|
|
1910
|
+
return schema.parse(response);
|
|
1911
|
+
}
|
|
1912
|
+
async function safeGetCvmComposeFile(client, request, parameters) {
|
|
1913
|
+
const requestValidation = GetCvmComposeFileRequestSchema.safeParse(request);
|
|
1914
|
+
if (!requestValidation.success) {
|
|
1915
|
+
return requestValidation;
|
|
1916
|
+
}
|
|
1917
|
+
const httpResult = await client.safeGet(`/cvms/${requestValidation.data.cvmId}/compose_file`);
|
|
1918
|
+
if (!httpResult.success) {
|
|
1919
|
+
return httpResult;
|
|
1920
|
+
}
|
|
1921
|
+
if (parameters?.schema === false) {
|
|
1922
|
+
return { success: true, data: httpResult.data };
|
|
1923
|
+
}
|
|
1924
|
+
const schema = parameters?.schema || GetCvmComposeFileResultSchema;
|
|
1925
|
+
return schema.safeParse(httpResult.data);
|
|
1926
|
+
}
|
|
1927
|
+
|
|
1928
|
+
// src/actions/provision_cvm_compose_file_update.ts
|
|
1929
|
+
var import_zod10 = require("zod");
|
|
1930
|
+
var ProvisionCvmComposeFileUpdateRequestSchema = import_zod10.z.object({
|
|
1931
|
+
id: import_zod10.z.string().optional(),
|
|
1932
|
+
uuid: import_zod10.z.string().regex(/^[0-9a-f]{8}[-]?[0-9a-f]{4}[-]?4[0-9a-f]{3}[-]?[89ab][0-9a-f]{3}[-]?[0-9a-f]{12}$/i).optional(),
|
|
1933
|
+
app_id: import_zod10.z.string().refine(
|
|
1934
|
+
(val) => !val.startsWith("app_") && val.length === 40,
|
|
1935
|
+
"app_id should be 40 characters without prefix"
|
|
1936
|
+
).transform((val) => val.startsWith("app_") ? val : `app_${val}`).optional(),
|
|
1937
|
+
instance_id: import_zod10.z.string().refine(
|
|
1938
|
+
(val) => !val.startsWith("instance_") && val.length === 40,
|
|
1939
|
+
"instance_id should be 40 characters without prefix"
|
|
1940
|
+
).transform((val) => val.startsWith("instance_") ? val : `instance_${val}`).optional(),
|
|
1941
|
+
app_compose: import_zod10.z.object({
|
|
1942
|
+
allowed_envs: import_zod10.z.array(import_zod10.z.string()).optional(),
|
|
1943
|
+
docker_compose_file: import_zod10.z.string().min(1, "Docker compose file is required"),
|
|
1944
|
+
name: import_zod10.z.string(),
|
|
1945
|
+
kms_enabled: import_zod10.z.boolean().optional(),
|
|
1946
|
+
public_logs: import_zod10.z.boolean().optional(),
|
|
1947
|
+
public_sysinfo: import_zod10.z.boolean().optional(),
|
|
1948
|
+
pre_launch_script: import_zod10.z.string().optional()
|
|
1949
|
+
})
|
|
1950
|
+
}).refine(
|
|
1951
|
+
(data) => !!(data.id || data.uuid || data.app_id || data.instance_id),
|
|
1952
|
+
"One of id, uuid, app_id, or instance_id must be provided"
|
|
1953
|
+
).transform((data) => ({
|
|
1954
|
+
cvmId: data.id || data.uuid || data.app_id || data.instance_id,
|
|
1955
|
+
request: data.app_compose,
|
|
1956
|
+
_raw: data
|
|
1957
|
+
}));
|
|
1958
|
+
var ProvisionCvmComposeFileUpdateResultSchema = import_zod10.z.object({
|
|
1959
|
+
app_id: import_zod10.z.string().nullable(),
|
|
1960
|
+
device_id: import_zod10.z.string().nullable(),
|
|
1961
|
+
compose_hash: import_zod10.z.string(),
|
|
1962
|
+
kms_info: KmsInfoSchema.nullable().optional()
|
|
1963
|
+
}).passthrough();
|
|
1964
|
+
async function provisionCvmComposeFileUpdate(client, request, parameters) {
|
|
1965
|
+
const validatedRequest = ProvisionCvmComposeFileUpdateRequestSchema.parse(request);
|
|
1966
|
+
const response = await client.post(
|
|
1967
|
+
`/cvms/${validatedRequest.cvmId}/compose_file/provision`,
|
|
1968
|
+
validatedRequest.request
|
|
1969
|
+
);
|
|
1970
|
+
if (parameters?.schema === false) {
|
|
1971
|
+
return response;
|
|
1972
|
+
}
|
|
1973
|
+
const schema = parameters?.schema || ProvisionCvmComposeFileUpdateResultSchema;
|
|
1974
|
+
return schema.parse(response);
|
|
1975
|
+
}
|
|
1976
|
+
async function safeProvisionCvmComposeFileUpdate(client, request, parameters) {
|
|
1977
|
+
const requestValidation = ProvisionCvmComposeFileUpdateRequestSchema.safeParse(request);
|
|
1978
|
+
if (!requestValidation.success) {
|
|
1979
|
+
return requestValidation;
|
|
1980
|
+
}
|
|
1981
|
+
const httpResult = await client.safePost(
|
|
1982
|
+
`/cvms/${requestValidation.data.cvmId}/compose_file/provision`,
|
|
1983
|
+
requestValidation.data.request
|
|
1984
|
+
);
|
|
1985
|
+
if (!httpResult.success) {
|
|
1986
|
+
return httpResult;
|
|
1987
|
+
}
|
|
1988
|
+
if (parameters?.schema === false) {
|
|
1989
|
+
return { success: true, data: httpResult.data };
|
|
1990
|
+
}
|
|
1991
|
+
const schema = parameters?.schema || ProvisionCvmComposeFileUpdateResultSchema;
|
|
1992
|
+
return schema.safeParse(httpResult.data);
|
|
1993
|
+
}
|
|
1994
|
+
|
|
1995
|
+
// src/actions/commit_cvm_compose_file_update.ts
|
|
1996
|
+
var import_zod11 = require("zod");
|
|
1997
|
+
var CommitCvmComposeFileUpdateRequestSchema = import_zod11.z.object({
|
|
1998
|
+
id: import_zod11.z.string().optional(),
|
|
1999
|
+
uuid: import_zod11.z.string().regex(/^[0-9a-f]{8}[-]?[0-9a-f]{4}[-]?4[0-9a-f]{3}[-]?[89ab][0-9a-f]{3}[-]?[0-9a-f]{12}$/i).optional(),
|
|
2000
|
+
app_id: import_zod11.z.string().refine(
|
|
2001
|
+
(val) => !val.startsWith("app_") && val.length === 40,
|
|
2002
|
+
"app_id should be 40 characters without prefix"
|
|
2003
|
+
).transform((val) => val.startsWith("app_") ? val : `app_${val}`).optional(),
|
|
2004
|
+
instance_id: import_zod11.z.string().refine(
|
|
2005
|
+
(val) => !val.startsWith("instance_") && val.length === 40,
|
|
2006
|
+
"instance_id should be 40 characters without prefix"
|
|
2007
|
+
).transform((val) => val.startsWith("instance_") ? val : `instance_${val}`).optional(),
|
|
2008
|
+
compose_hash: import_zod11.z.string().min(1, "Compose hash is required"),
|
|
2009
|
+
encrypted_env: import_zod11.z.string().optional(),
|
|
2010
|
+
env_keys: import_zod11.z.array(import_zod11.z.string()).optional()
|
|
2011
|
+
}).refine(
|
|
2012
|
+
(data) => !!(data.id || data.uuid || data.app_id || data.instance_id),
|
|
2013
|
+
"One of id, uuid, app_id, or instance_id must be provided"
|
|
2014
|
+
).transform((data) => ({
|
|
2015
|
+
cvmId: data.id || data.uuid || data.app_id || data.instance_id,
|
|
2016
|
+
compose_hash: data.compose_hash,
|
|
2017
|
+
encrypted_env: data.encrypted_env,
|
|
2018
|
+
env_keys: data.env_keys,
|
|
2019
|
+
_raw: data
|
|
2020
|
+
}));
|
|
2021
|
+
var CommitCvmComposeFileUpdateSchema = import_zod11.z.any().transform(() => void 0);
|
|
2022
|
+
async function commitCvmComposeFileUpdate(client, request, parameters) {
|
|
2023
|
+
const validatedRequest = CommitCvmComposeFileUpdateRequestSchema.parse(request);
|
|
2024
|
+
const response = await client.patch(`/cvms/${validatedRequest.cvmId}/compose_file`, {
|
|
2025
|
+
compose_hash: validatedRequest.compose_hash,
|
|
2026
|
+
encrypted_env: validatedRequest.encrypted_env,
|
|
2027
|
+
env_keys: validatedRequest.env_keys
|
|
2028
|
+
});
|
|
2029
|
+
if (parameters?.schema === false) {
|
|
2030
|
+
return response;
|
|
2031
|
+
}
|
|
2032
|
+
const schema = parameters?.schema || CommitCvmComposeFileUpdateSchema;
|
|
2033
|
+
return schema.parse(response);
|
|
2034
|
+
}
|
|
2035
|
+
async function safeCommitCvmComposeFileUpdate(client, request, parameters) {
|
|
2036
|
+
const requestValidation = CommitCvmComposeFileUpdateRequestSchema.safeParse(request);
|
|
2037
|
+
if (!requestValidation.success) {
|
|
2038
|
+
return requestValidation;
|
|
2039
|
+
}
|
|
2040
|
+
const httpResult = await client.safePatch(`/cvms/${requestValidation.data.cvmId}/compose_file`, {
|
|
2041
|
+
compose_hash: requestValidation.data.compose_hash,
|
|
2042
|
+
encrypted_env: requestValidation.data.encrypted_env,
|
|
2043
|
+
env_keys: requestValidation.data.env_keys
|
|
2044
|
+
});
|
|
2045
|
+
if (!httpResult.success) {
|
|
2046
|
+
return httpResult;
|
|
2047
|
+
}
|
|
2048
|
+
if (parameters?.schema === false) {
|
|
2049
|
+
return { success: true, data: httpResult.data };
|
|
2050
|
+
}
|
|
2051
|
+
const schema = parameters?.schema || CommitCvmComposeFileUpdateSchema;
|
|
2052
|
+
return schema.safeParse(httpResult.data);
|
|
2053
|
+
}
|
|
2054
|
+
|
|
2055
|
+
// src/actions/get_app_env_encrypt_pubkey.ts
|
|
2056
|
+
var import_zod12 = require("zod");
|
|
2057
|
+
var GetAppEnvEncryptPubKeyRequestSchema = import_zod12.z.object({
|
|
2058
|
+
kms: import_zod12.z.string().min(1, "KMS ID or slug is required"),
|
|
2059
|
+
app_id: import_zod12.z.string().length(40, "App ID must be exactly 40 characters")
|
|
2060
|
+
}).strict();
|
|
2061
|
+
var GetAppEnvEncryptPubKeySchema = import_zod12.z.object({
|
|
2062
|
+
public_key: import_zod12.z.string(),
|
|
2063
|
+
signature: import_zod12.z.string()
|
|
2064
|
+
}).strict();
|
|
2065
|
+
var getAppEnvEncryptPubKey = async (client, payload, parameters) => {
|
|
2066
|
+
const validatedRequest = GetAppEnvEncryptPubKeyRequestSchema.parse(payload);
|
|
2067
|
+
validateActionParameters(parameters);
|
|
2068
|
+
const response = await client.get(
|
|
2069
|
+
`/kms/${validatedRequest.kms}/pubkey/${validatedRequest.app_id}`
|
|
2070
|
+
);
|
|
2071
|
+
if (parameters?.schema === false) {
|
|
2072
|
+
return response;
|
|
2073
|
+
}
|
|
2074
|
+
const schema = parameters?.schema || GetAppEnvEncryptPubKeySchema;
|
|
2075
|
+
return schema.parse(response);
|
|
2076
|
+
};
|
|
2077
|
+
var safeGetAppEnvEncryptPubKey = async (client, payload, parameters) => {
|
|
2078
|
+
const requestValidation = GetAppEnvEncryptPubKeyRequestSchema.safeParse(payload);
|
|
2079
|
+
if (!requestValidation.success) {
|
|
2080
|
+
return requestValidation;
|
|
2081
|
+
}
|
|
2082
|
+
const parameterValidationError = safeValidateActionParameters(parameters);
|
|
2083
|
+
if (parameterValidationError) {
|
|
2084
|
+
return parameterValidationError;
|
|
2085
|
+
}
|
|
2086
|
+
const httpResult = await client.safeGet(
|
|
2087
|
+
`/kms/${requestValidation.data.kms}/pubkey/${requestValidation.data.app_id}`
|
|
2088
|
+
);
|
|
2089
|
+
if (!httpResult.success) {
|
|
2090
|
+
return httpResult;
|
|
2091
|
+
}
|
|
2092
|
+
if (parameters?.schema === false) {
|
|
2093
|
+
return { success: true, data: httpResult.data };
|
|
2094
|
+
}
|
|
2095
|
+
const schema = parameters?.schema || GetAppEnvEncryptPubKeySchema;
|
|
2096
|
+
return schema.safeParse(httpResult.data);
|
|
2097
|
+
};
|
|
2098
|
+
|
|
2099
|
+
// src/actions/get_cvm_info.ts
|
|
2100
|
+
var import_zod14 = require("zod");
|
|
2101
|
+
|
|
2102
|
+
// src/types/cvm_info.ts
|
|
2103
|
+
var import_zod13 = require("zod");
|
|
2104
|
+
var VmInfoSchema = import_zod13.z.object({
|
|
2105
|
+
id: import_zod13.z.string(),
|
|
2106
|
+
name: import_zod13.z.string(),
|
|
2107
|
+
status: import_zod13.z.string(),
|
|
2108
|
+
uptime: import_zod13.z.string(),
|
|
2109
|
+
app_url: import_zod13.z.string().nullable(),
|
|
2110
|
+
app_id: import_zod13.z.string(),
|
|
2111
|
+
instance_id: import_zod13.z.string().nullable(),
|
|
2112
|
+
configuration: import_zod13.z.any().optional(),
|
|
2113
|
+
// TODO: add VmConfiguration schema if needed
|
|
2114
|
+
exited_at: import_zod13.z.string().nullable(),
|
|
2115
|
+
boot_progress: import_zod13.z.string().nullable(),
|
|
2116
|
+
boot_error: import_zod13.z.string().nullable(),
|
|
2117
|
+
shutdown_progress: import_zod13.z.string().nullable(),
|
|
2118
|
+
image_version: import_zod13.z.string().nullable()
|
|
2119
|
+
});
|
|
2120
|
+
var ManagedUserSchema = import_zod13.z.object({
|
|
2121
|
+
id: import_zod13.z.number(),
|
|
2122
|
+
username: import_zod13.z.string()
|
|
2123
|
+
});
|
|
2124
|
+
var CvmNodeSchema = import_zod13.z.object({
|
|
2125
|
+
id: import_zod13.z.number(),
|
|
2126
|
+
name: import_zod13.z.string(),
|
|
2127
|
+
region_identifier: import_zod13.z.string().optional()
|
|
2128
|
+
});
|
|
2129
|
+
var CvmNetworkUrlsSchema = import_zod13.z.object({
|
|
2130
|
+
app: import_zod13.z.string(),
|
|
2131
|
+
instance: import_zod13.z.string()
|
|
2132
|
+
});
|
|
2133
|
+
var KMSInfoSchema = import_zod13.z.object({
|
|
2134
|
+
id: import_zod13.z.string(),
|
|
2135
|
+
// HashedId is represented as string in JS
|
|
2136
|
+
slug: import_zod13.z.string(),
|
|
2137
|
+
url: import_zod13.z.string(),
|
|
2138
|
+
version: import_zod13.z.string(),
|
|
2139
|
+
chain_id: import_zod13.z.number().optional(),
|
|
2140
|
+
kms_contract_address: import_zod13.z.string().optional(),
|
|
2141
|
+
gateway_app_id: import_zod13.z.string().optional()
|
|
2142
|
+
});
|
|
2143
|
+
var CvmInfoSchema = import_zod13.z.object({
|
|
2144
|
+
hosted: VmInfoSchema,
|
|
2145
|
+
name: import_zod13.z.string(),
|
|
2146
|
+
managed_user: ManagedUserSchema.optional().nullable(),
|
|
2147
|
+
node: CvmNodeSchema.optional().nullable(),
|
|
2148
|
+
listed: import_zod13.z.boolean().default(false),
|
|
2149
|
+
status: import_zod13.z.string(),
|
|
2150
|
+
in_progress: import_zod13.z.boolean().default(false),
|
|
2151
|
+
dapp_dashboard_url: import_zod13.z.string().nullable(),
|
|
2152
|
+
syslog_endpoint: import_zod13.z.string().nullable(),
|
|
2153
|
+
allow_upgrade: import_zod13.z.boolean().default(false),
|
|
2154
|
+
project_id: import_zod13.z.string().nullable(),
|
|
2155
|
+
// HashedId is represented as string in JS
|
|
2156
|
+
project_type: import_zod13.z.string().nullable(),
|
|
2157
|
+
billing_period: import_zod13.z.string().nullable(),
|
|
2158
|
+
kms_info: KMSInfoSchema.nullable(),
|
|
2159
|
+
vcpu: import_zod13.z.number().nullable(),
|
|
2160
|
+
memory: import_zod13.z.number().nullable(),
|
|
2161
|
+
disk_size: import_zod13.z.number().nullable(),
|
|
2162
|
+
gateway_domain: import_zod13.z.string().nullable(),
|
|
2163
|
+
public_urls: import_zod13.z.array(CvmNetworkUrlsSchema)
|
|
2164
|
+
}).partial();
|
|
2165
|
+
|
|
2166
|
+
// src/actions/get_cvm_info.ts
|
|
2167
|
+
var GetCvmInfoSchema = CvmInfoSchema;
|
|
2168
|
+
var GetCvmInfoRequestSchema = import_zod14.z.object({
|
|
2169
|
+
id: import_zod14.z.string().optional(),
|
|
2170
|
+
uuid: import_zod14.z.string().regex(/^[0-9a-f]{8}[-]?[0-9a-f]{4}[-]?4[0-9a-f]{3}[-]?[89ab][0-9a-f]{3}[-]?[0-9a-f]{12}$/i).optional(),
|
|
2171
|
+
app_id: import_zod14.z.string().refine(
|
|
2172
|
+
(val) => !val.startsWith("app_") && val.length === 40,
|
|
2173
|
+
"app_id should be 40 characters without prefix"
|
|
2174
|
+
).transform((val) => val.startsWith("app_") ? val : `app_${val}`).optional(),
|
|
2175
|
+
instance_id: import_zod14.z.string().refine(
|
|
2176
|
+
(val) => !val.startsWith("instance_") && val.length === 40,
|
|
2177
|
+
"instance_id should be 40 characters without prefix"
|
|
2178
|
+
).transform((val) => val.startsWith("instance_") ? val : `instance_${val}`).optional()
|
|
2179
|
+
}).refine(
|
|
2180
|
+
(data) => !!(data.id || data.uuid || data.app_id || data.instance_id),
|
|
2181
|
+
"One of id, uuid, app_id, or instance_id must be provided"
|
|
2182
|
+
).transform((data) => ({
|
|
2183
|
+
cvmId: data.id || data.uuid || data.app_id || data.instance_id,
|
|
2184
|
+
_raw: data
|
|
2185
|
+
}));
|
|
2186
|
+
async function getCvmInfo(client, request, parameters) {
|
|
2187
|
+
const validatedRequest = GetCvmInfoRequestSchema.parse(request);
|
|
2188
|
+
validateActionParameters(parameters);
|
|
2189
|
+
const response = await client.get(`/cvms/${validatedRequest.cvmId}`);
|
|
2190
|
+
if (parameters?.schema === false) {
|
|
2191
|
+
return response;
|
|
2192
|
+
}
|
|
2193
|
+
const schema = parameters?.schema || GetCvmInfoSchema;
|
|
2194
|
+
return schema.parse(response);
|
|
2195
|
+
}
|
|
2196
|
+
async function safeGetCvmInfo(client, request, parameters) {
|
|
2197
|
+
const requestValidation = GetCvmInfoRequestSchema.safeParse(request);
|
|
2198
|
+
if (!requestValidation.success) {
|
|
2199
|
+
return requestValidation;
|
|
2200
|
+
}
|
|
2201
|
+
const parameterValidationError = safeValidateActionParameters(parameters);
|
|
2202
|
+
if (parameterValidationError) {
|
|
2203
|
+
return parameterValidationError;
|
|
2204
|
+
}
|
|
2205
|
+
const httpResult = await client.safeGet(`/cvms/${requestValidation.data.cvmId}`);
|
|
2206
|
+
if (!httpResult.success) {
|
|
2207
|
+
return httpResult;
|
|
2208
|
+
}
|
|
2209
|
+
if (parameters?.schema === false) {
|
|
2210
|
+
return {
|
|
2211
|
+
success: true,
|
|
2212
|
+
data: httpResult.data
|
|
2213
|
+
};
|
|
2214
|
+
}
|
|
2215
|
+
const schema = parameters?.schema || GetCvmInfoSchema;
|
|
2216
|
+
const validationResult = schema.safeParse(httpResult.data);
|
|
2217
|
+
return validationResult;
|
|
2218
|
+
}
|
|
2219
|
+
|
|
2220
|
+
// src/actions/get_cvm_list.ts
|
|
2221
|
+
var import_zod15 = require("zod");
|
|
2222
|
+
var GetCvmListRequestSchema = import_zod15.z.object({
|
|
2223
|
+
page: import_zod15.z.number().int().min(1).optional(),
|
|
2224
|
+
page_size: import_zod15.z.number().int().min(1).optional(),
|
|
2225
|
+
node_id: import_zod15.z.number().int().min(1).optional()
|
|
2226
|
+
}).strict();
|
|
2227
|
+
var GetCvmListSchema = import_zod15.z.object({
|
|
2228
|
+
items: import_zod15.z.array(CvmInfoSchema),
|
|
2229
|
+
total: import_zod15.z.number(),
|
|
2230
|
+
page: import_zod15.z.number(),
|
|
2231
|
+
page_size: import_zod15.z.number(),
|
|
2232
|
+
pages: import_zod15.z.number()
|
|
2233
|
+
}).strict();
|
|
2234
|
+
async function getCvmList(client, request, parameters) {
|
|
2235
|
+
const validatedRequest = GetCvmListRequestSchema.parse(request ?? {});
|
|
2236
|
+
validateActionParameters(parameters);
|
|
2237
|
+
const response = await client.get("/cvms/paginated", { params: validatedRequest });
|
|
2238
|
+
if (parameters?.schema === false) {
|
|
2239
|
+
return response;
|
|
2240
|
+
}
|
|
2241
|
+
const schema = parameters?.schema || GetCvmListSchema;
|
|
2242
|
+
return schema.parse(response);
|
|
2243
|
+
}
|
|
2244
|
+
async function safeGetCvmList(client, request, parameters) {
|
|
2245
|
+
const requestValidation = GetCvmListRequestSchema.safeParse(request ?? {});
|
|
2246
|
+
if (!requestValidation.success) {
|
|
2247
|
+
return requestValidation;
|
|
2248
|
+
}
|
|
2249
|
+
const parameterValidationError = safeValidateActionParameters(parameters);
|
|
2250
|
+
if (parameterValidationError) {
|
|
2251
|
+
return parameterValidationError;
|
|
2252
|
+
}
|
|
2253
|
+
const httpResult = await client.safeGet("/cvms/paginated", { params: requestValidation.data });
|
|
2254
|
+
if (!httpResult.success) {
|
|
2255
|
+
return httpResult;
|
|
2256
|
+
}
|
|
2257
|
+
if (parameters?.schema === false) {
|
|
2258
|
+
return {
|
|
2259
|
+
success: true,
|
|
2260
|
+
data: httpResult.data
|
|
2261
|
+
};
|
|
2262
|
+
}
|
|
2263
|
+
const schema = parameters?.schema || GetCvmListSchema;
|
|
2264
|
+
const validationResult = schema.safeParse(httpResult.data);
|
|
2265
|
+
return validationResult;
|
|
2266
|
+
}
|
|
2267
|
+
|
|
2268
|
+
// src/actions/get_kms_info.ts
|
|
2269
|
+
var import_zod16 = require("zod");
|
|
2270
|
+
var GetKmsInfoRequestSchema = import_zod16.z.object({
|
|
2271
|
+
kms_id: import_zod16.z.string().min(1, "KMS ID is required")
|
|
2272
|
+
});
|
|
2273
|
+
async function getKmsInfo(client, request, parameters) {
|
|
2274
|
+
const validatedRequest = GetKmsInfoRequestSchema.parse(request);
|
|
2275
|
+
validateActionParameters(parameters);
|
|
2276
|
+
const response = await client.get(`/kms/${validatedRequest.kms_id}`);
|
|
2277
|
+
if (parameters?.schema === false) {
|
|
2278
|
+
return response;
|
|
2279
|
+
}
|
|
2280
|
+
const schema = parameters?.schema || KmsInfoSchema;
|
|
2281
|
+
return schema.parse(response);
|
|
2282
|
+
}
|
|
2283
|
+
async function safeGetKmsInfo(client, request, parameters) {
|
|
2284
|
+
const requestValidation = GetKmsInfoRequestSchema.safeParse(request);
|
|
2285
|
+
if (!requestValidation.success) {
|
|
2286
|
+
return requestValidation;
|
|
2287
|
+
}
|
|
2288
|
+
const parameterValidationError = safeValidateActionParameters(parameters);
|
|
2289
|
+
if (parameterValidationError) {
|
|
2290
|
+
return parameterValidationError;
|
|
2291
|
+
}
|
|
2292
|
+
const httpResult = await client.safeGet(`/kms/${requestValidation.data.kms_id}`);
|
|
2293
|
+
if (!httpResult.success) {
|
|
2294
|
+
return httpResult;
|
|
2295
|
+
}
|
|
2296
|
+
if (parameters?.schema === false) {
|
|
2297
|
+
return { success: true, data: httpResult.data };
|
|
2298
|
+
}
|
|
2299
|
+
const schema = parameters?.schema || KmsInfoSchema;
|
|
2300
|
+
const validationResult = schema.safeParse(httpResult.data);
|
|
2301
|
+
return validationResult;
|
|
2302
|
+
}
|
|
2303
|
+
|
|
2304
|
+
// src/actions/get_kms_list.ts
|
|
2305
|
+
var import_zod17 = require("zod");
|
|
2306
|
+
var GetKmsListRequestSchema = import_zod17.z.object({
|
|
2307
|
+
page: import_zod17.z.number().int().min(1).optional(),
|
|
2308
|
+
page_size: import_zod17.z.number().int().min(1).optional(),
|
|
2309
|
+
is_onchain: import_zod17.z.boolean().optional()
|
|
2310
|
+
}).strict();
|
|
2311
|
+
var GetKmsListSchema = import_zod17.z.object({
|
|
2312
|
+
items: import_zod17.z.array(KmsInfoSchema),
|
|
2313
|
+
total: import_zod17.z.number(),
|
|
2314
|
+
page: import_zod17.z.number(),
|
|
2315
|
+
page_size: import_zod17.z.number(),
|
|
2316
|
+
pages: import_zod17.z.number()
|
|
2317
|
+
}).strict();
|
|
2318
|
+
async function getKmsList(client, request, parameters) {
|
|
2319
|
+
const validatedRequest = GetKmsListRequestSchema.parse(request ?? {});
|
|
2320
|
+
validateActionParameters(parameters);
|
|
2321
|
+
const response = await client.get("/kms", { params: validatedRequest });
|
|
2322
|
+
if (parameters?.schema === false) {
|
|
2323
|
+
return response;
|
|
2324
|
+
}
|
|
2325
|
+
const schema = parameters?.schema || GetKmsListSchema;
|
|
2326
|
+
return schema.parse(response);
|
|
2327
|
+
}
|
|
2328
|
+
async function safeGetKmsList(client, request, parameters) {
|
|
2329
|
+
const requestValidation = GetKmsListRequestSchema.safeParse(request ?? {});
|
|
2330
|
+
if (!requestValidation.success) {
|
|
2331
|
+
return requestValidation;
|
|
2332
|
+
}
|
|
2333
|
+
const parameterValidationError = safeValidateActionParameters(parameters);
|
|
2334
|
+
if (parameterValidationError) {
|
|
2335
|
+
return parameterValidationError;
|
|
2336
|
+
}
|
|
2337
|
+
const httpResult = await client.safeGet("/kms", { params: requestValidation.data });
|
|
2338
|
+
if (!httpResult.success) {
|
|
2339
|
+
return httpResult;
|
|
2340
|
+
}
|
|
2341
|
+
if (parameters?.schema === false) {
|
|
2342
|
+
return {
|
|
2343
|
+
success: true,
|
|
2344
|
+
data: httpResult.data
|
|
2345
|
+
};
|
|
2346
|
+
}
|
|
2347
|
+
const schema = parameters?.schema || GetKmsListSchema;
|
|
2348
|
+
const validationResult = schema.safeParse(httpResult.data);
|
|
2349
|
+
return validationResult;
|
|
2350
|
+
}
|
|
2351
|
+
|
|
2352
|
+
// src/index.ts
|
|
2353
|
+
var import_encrypt_env_vars2 = require("@phala/dstack-sdk/encrypt-env-vars");
|
|
2354
|
+
var import_dstack_sdk = require("@phala/dstack-sdk");
|
|
2355
|
+
var import_dstack_sdk2 = require("@phala/dstack-sdk");
|
|
2356
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
2357
|
+
0 && (module.exports = {
|
|
2358
|
+
AddComposeHashSchema,
|
|
2359
|
+
ApiErrorSchema,
|
|
2360
|
+
AvailableNodesSchema,
|
|
2361
|
+
CommitCvmComposeFileUpdateRequestSchema,
|
|
2362
|
+
CommitCvmComposeFileUpdateSchema,
|
|
2363
|
+
CommitCvmProvisionRequestSchema,
|
|
2364
|
+
CommitCvmProvisionSchema,
|
|
2365
|
+
CurrentUserSchema,
|
|
2366
|
+
DeployAppAuthRequestSchema,
|
|
2367
|
+
DeployAppAuthSchema,
|
|
2368
|
+
GetAppEnvEncryptPubKeySchema,
|
|
2369
|
+
GetCvmComposeFileResultSchema,
|
|
2370
|
+
GetCvmInfoSchema,
|
|
2371
|
+
GetCvmListSchema,
|
|
2372
|
+
GetKmsListSchema,
|
|
2373
|
+
NetworkError,
|
|
2374
|
+
ProvisionCvmComposeFileUpdateRequestSchema,
|
|
2375
|
+
ProvisionCvmComposeFileUpdateResultSchema,
|
|
2376
|
+
ProvisionCvmRequestSchema,
|
|
2377
|
+
ProvisionCvmSchema,
|
|
2378
|
+
RequestError,
|
|
2379
|
+
TransactionError,
|
|
2380
|
+
WalletError,
|
|
2381
|
+
addComposeHash,
|
|
2382
|
+
addNetwork,
|
|
2383
|
+
asHex,
|
|
2384
|
+
autoCreateClients,
|
|
2385
|
+
checkBalance,
|
|
2386
|
+
checkNetworkStatus,
|
|
2387
|
+
commitCvmComposeFileUpdate,
|
|
2388
|
+
commitCvmProvision,
|
|
2389
|
+
createClient,
|
|
2390
|
+
createClientsFromBrowser,
|
|
2391
|
+
createClientsFromPrivateKey,
|
|
2392
|
+
createNetworkClients,
|
|
2393
|
+
createTransactionTracker,
|
|
2394
|
+
deployAppAuth,
|
|
2395
|
+
encryptEnvVars,
|
|
2396
|
+
estimateTransactionGas,
|
|
2397
|
+
executeBatchTransactions,
|
|
2398
|
+
executeTransaction,
|
|
2399
|
+
executeTransactionWithRetry,
|
|
2400
|
+
extractNetworkClients,
|
|
2401
|
+
getAppEnvEncryptPubKey,
|
|
2402
|
+
getAvailableNodes,
|
|
2403
|
+
getComposeHash,
|
|
2404
|
+
getCurrentUser,
|
|
2405
|
+
getCvmComposeFile,
|
|
2406
|
+
getCvmInfo,
|
|
2407
|
+
getCvmList,
|
|
2408
|
+
getErrorMessage,
|
|
2409
|
+
getKmsInfo,
|
|
2410
|
+
getKmsList,
|
|
2411
|
+
provisionCvm,
|
|
2412
|
+
provisionCvmComposeFileUpdate,
|
|
2413
|
+
safeAddComposeHash,
|
|
2414
|
+
safeCommitCvmComposeFileUpdate,
|
|
2415
|
+
safeCommitCvmProvision,
|
|
2416
|
+
safeDeployAppAuth,
|
|
2417
|
+
safeGetAppEnvEncryptPubKey,
|
|
2418
|
+
safeGetAvailableNodes,
|
|
2419
|
+
safeGetCurrentUser,
|
|
2420
|
+
safeGetCvmComposeFile,
|
|
2421
|
+
safeGetCvmInfo,
|
|
2422
|
+
safeGetCvmList,
|
|
2423
|
+
safeGetKmsInfo,
|
|
2424
|
+
safeGetKmsList,
|
|
2425
|
+
safeProvisionCvm,
|
|
2426
|
+
safeProvisionCvmComposeFileUpdate,
|
|
2427
|
+
safeValidateActionParameters,
|
|
2428
|
+
switchToNetwork,
|
|
2429
|
+
validateActionParameters,
|
|
2430
|
+
validateNetworkPrerequisites,
|
|
2431
|
+
verifyEnvEncryptPublicKey,
|
|
2432
|
+
waitForTransactionReceipt
|
|
2433
|
+
});
|