@layr-labs/ecloud-sdk 0.2.0 → 0.2.2-dev

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/VERSION +2 -2
  2. package/dist/billing.cjs +48 -43
  3. package/dist/billing.cjs.map +1 -1
  4. package/dist/billing.d.cts +6 -3
  5. package/dist/billing.d.ts +6 -3
  6. package/dist/billing.js +519 -4
  7. package/dist/billing.js.map +1 -1
  8. package/dist/browser.cjs +5034 -0
  9. package/dist/browser.cjs.map +1 -0
  10. package/dist/browser.d.cts +239 -0
  11. package/dist/browser.d.ts +239 -0
  12. package/dist/browser.js +4924 -0
  13. package/dist/browser.js.map +1 -0
  14. package/dist/{compute-CF2HOXed.d.ts → compute-BYhSs8en.d.ts} +15 -96
  15. package/dist/{compute-CbmjA8kJ.d.cts → compute-Bpjb3hYD.d.cts} +15 -96
  16. package/dist/compute.cjs +875 -846
  17. package/dist/compute.cjs.map +1 -1
  18. package/dist/compute.d.cts +2 -2
  19. package/dist/compute.d.ts +2 -2
  20. package/dist/compute.js +7009 -8
  21. package/dist/compute.js.map +1 -1
  22. package/dist/helpers-CEvhJz7f.d.cts +742 -0
  23. package/dist/helpers-CQuBwQnu.d.ts +742 -0
  24. package/dist/index-DeQzn_yM.d.cts +739 -0
  25. package/dist/index-DeQzn_yM.d.ts +739 -0
  26. package/dist/index.cjs +1958 -1758
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.d.cts +69 -414
  29. package/dist/index.d.ts +69 -414
  30. package/dist/index.js +7977 -134
  31. package/dist/index.js.map +1 -1
  32. package/package.json +17 -2
  33. package/dist/chunk-CA5Y4OVI.js +0 -744
  34. package/dist/chunk-CA5Y4OVI.js.map +0 -1
  35. package/dist/chunk-ZDXN2WKP.js +0 -434
  36. package/dist/chunk-ZDXN2WKP.js.map +0 -1
  37. package/dist/chunk-ZTLKZMSW.js +0 -6719
  38. package/dist/chunk-ZTLKZMSW.js.map +0 -1
  39. package/dist/index-D2QufVB9.d.cts +0 -342
  40. package/dist/index-D2QufVB9.d.ts +0 -342
package/dist/billing.js CHANGED
@@ -1,7 +1,522 @@
1
- import {
2
- createBillingModule
3
- } from "./chunk-ZDXN2WKP.js";
4
- import "./chunk-CA5Y4OVI.js";
1
+ // src/client/common/utils/billingapi.ts
2
+ import axios from "axios";
3
+
4
+ // src/client/common/utils/auth.ts
5
+ import { parseAbi } from "viem";
6
+ var APP_CONTROLLER_ABI = parseAbi([
7
+ "function calculateApiPermissionDigestHash(bytes4 permission, uint256 expiry) view returns (bytes32)"
8
+ ]);
9
+ var generateBillingSigData = (product, expiry) => {
10
+ return {
11
+ domain: {
12
+ name: "EigenCloud Billing API",
13
+ version: "1"
14
+ },
15
+ types: {
16
+ BillingAuth: [
17
+ { name: "product", type: "string" },
18
+ { name: "expiry", type: "uint256" }
19
+ ]
20
+ },
21
+ primaryType: "BillingAuth",
22
+ message: {
23
+ product,
24
+ expiry
25
+ }
26
+ };
27
+ };
28
+ async function calculateBillingAuthSignature(options) {
29
+ const { walletClient, product, expiry } = options;
30
+ const account = walletClient.account;
31
+ if (!account) {
32
+ throw new Error("WalletClient must have an account attached");
33
+ }
34
+ const signature = await walletClient.signTypedData({
35
+ account,
36
+ ...generateBillingSigData(product, expiry)
37
+ });
38
+ return { signature, expiry };
39
+ }
40
+
41
+ // src/client/common/utils/billingapi.ts
42
+ var BillingApiClient = class {
43
+ constructor(config, walletClient) {
44
+ this.config = config;
45
+ this.walletClient = walletClient;
46
+ }
47
+ /**
48
+ * Get the address of the connected wallet
49
+ */
50
+ get address() {
51
+ const account = this.walletClient.account;
52
+ if (!account) {
53
+ throw new Error("WalletClient must have an account attached");
54
+ }
55
+ return account.address;
56
+ }
57
+ async createSubscription(productId = "compute", options) {
58
+ const endpoint = `${this.config.billingApiServerURL}/products/${productId}/subscription`;
59
+ const body = options ? {
60
+ success_url: options.successUrl,
61
+ cancel_url: options.cancelUrl
62
+ } : void 0;
63
+ const resp = await this.makeAuthenticatedRequest(endpoint, "POST", productId, body);
64
+ return resp.json();
65
+ }
66
+ async getSubscription(productId = "compute") {
67
+ const endpoint = `${this.config.billingApiServerURL}/products/${productId}/subscription`;
68
+ const resp = await this.makeAuthenticatedRequest(endpoint, "GET", productId);
69
+ return resp.json();
70
+ }
71
+ async cancelSubscription(productId = "compute") {
72
+ const endpoint = `${this.config.billingApiServerURL}/products/${productId}/subscription`;
73
+ await this.makeAuthenticatedRequest(endpoint, "DELETE", productId);
74
+ }
75
+ /**
76
+ * Make an authenticated request to the billing API
77
+ */
78
+ async makeAuthenticatedRequest(url, method, productId, body) {
79
+ const expiry = BigInt(Math.floor(Date.now() / 1e3) + 5 * 60);
80
+ const { signature } = await calculateBillingAuthSignature({
81
+ walletClient: this.walletClient,
82
+ product: productId,
83
+ expiry
84
+ });
85
+ const headers = {
86
+ Authorization: `Bearer ${signature}`,
87
+ "X-Account": this.address,
88
+ "X-Expiry": expiry.toString()
89
+ };
90
+ if (body) {
91
+ headers["Content-Type"] = "application/json";
92
+ }
93
+ try {
94
+ const response = await axios({
95
+ method,
96
+ url,
97
+ headers,
98
+ data: body,
99
+ timeout: 3e4,
100
+ maxRedirects: 0,
101
+ validateStatus: () => true
102
+ // Don't throw on any status
103
+ });
104
+ const status = response.status;
105
+ const statusText = status >= 200 && status < 300 ? "OK" : "Error";
106
+ if (status < 200 || status >= 300) {
107
+ const body2 = typeof response.data === "string" ? response.data : JSON.stringify(response.data);
108
+ throw new Error(`BillingAPI request failed: ${status} ${statusText} - ${body2}`);
109
+ }
110
+ return {
111
+ json: async () => response.data,
112
+ text: async () => typeof response.data === "string" ? response.data : JSON.stringify(response.data)
113
+ };
114
+ } catch (error) {
115
+ if (error.message?.includes("fetch failed") || error.message?.includes("ECONNREFUSED") || error.message?.includes("ENOTFOUND") || error.cause) {
116
+ const cause = error.cause?.message || error.cause || error.message;
117
+ throw new Error(
118
+ `Failed to connect to BillingAPI at ${url}: ${cause}
119
+ Please check:
120
+ 1. Your internet connection
121
+ 2. The API server is accessible: ${this.config.billingApiServerURL}
122
+ 3. Firewall/proxy settings`
123
+ );
124
+ }
125
+ throw error;
126
+ }
127
+ }
128
+ };
129
+
130
+ // src/client/common/config/environment.ts
131
+ var SEPOLIA_CHAIN_ID = 11155111;
132
+ var MAINNET_CHAIN_ID = 1;
133
+ var CommonAddresses = {
134
+ ERC7702Delegator: "0x63c0c19a282a1b52b07dd5a65b58948a07dae32b"
135
+ };
136
+ var ChainAddresses = {
137
+ [MAINNET_CHAIN_ID]: {
138
+ PermissionController: "0x25E5F8B1E7aDf44518d35D5B2271f114e081f0E5"
139
+ },
140
+ [SEPOLIA_CHAIN_ID]: {
141
+ PermissionController: "0x44632dfBdCb6D3E21EF613B0ca8A6A0c618F5a37"
142
+ }
143
+ };
144
+ var BILLING_ENVIRONMENTS = {
145
+ dev: {
146
+ billingApiServerURL: "https://billingapi-dev.eigencloud.xyz"
147
+ },
148
+ prod: {
149
+ billingApiServerURL: "https://billingapi.eigencloud.xyz"
150
+ }
151
+ };
152
+ var ENVIRONMENTS = {
153
+ "sepolia-dev": {
154
+ name: "sepolia",
155
+ build: "dev",
156
+ appControllerAddress: "0xa86DC1C47cb2518327fB4f9A1627F51966c83B92",
157
+ permissionControllerAddress: ChainAddresses[SEPOLIA_CHAIN_ID].PermissionController,
158
+ erc7702DelegatorAddress: CommonAddresses.ERC7702Delegator,
159
+ kmsServerURL: "http://10.128.0.57:8080",
160
+ userApiServerURL: "https://userapi-compute-sepolia-dev.eigencloud.xyz",
161
+ defaultRPCURL: "https://ethereum-sepolia-rpc.publicnode.com"
162
+ },
163
+ sepolia: {
164
+ name: "sepolia",
165
+ build: "prod",
166
+ appControllerAddress: "0x0dd810a6ffba6a9820a10d97b659f07d8d23d4E2",
167
+ permissionControllerAddress: ChainAddresses[SEPOLIA_CHAIN_ID].PermissionController,
168
+ erc7702DelegatorAddress: CommonAddresses.ERC7702Delegator,
169
+ kmsServerURL: "http://10.128.15.203:8080",
170
+ userApiServerURL: "https://userapi-compute-sepolia-prod.eigencloud.xyz",
171
+ defaultRPCURL: "https://ethereum-sepolia-rpc.publicnode.com"
172
+ },
173
+ "mainnet-alpha": {
174
+ name: "mainnet-alpha",
175
+ build: "prod",
176
+ appControllerAddress: "0xc38d35Fc995e75342A21CBd6D770305b142Fbe67",
177
+ permissionControllerAddress: ChainAddresses[MAINNET_CHAIN_ID].PermissionController,
178
+ erc7702DelegatorAddress: CommonAddresses.ERC7702Delegator,
179
+ kmsServerURL: "http://10.128.0.2:8080",
180
+ userApiServerURL: "https://userapi-compute.eigencloud.xyz",
181
+ defaultRPCURL: "https://ethereum-rpc.publicnode.com"
182
+ }
183
+ };
184
+ var CHAIN_ID_TO_ENVIRONMENT = {
185
+ [SEPOLIA_CHAIN_ID.toString()]: "sepolia",
186
+ [MAINNET_CHAIN_ID.toString()]: "mainnet-alpha"
187
+ };
188
+ function getBillingEnvironmentConfig(build) {
189
+ const config = BILLING_ENVIRONMENTS[build];
190
+ if (!config) {
191
+ throw new Error(`Unknown billing environment: ${build}`);
192
+ }
193
+ return config;
194
+ }
195
+ function getBuildType() {
196
+ const buildTimeType = true ? "dev"?.toLowerCase() : void 0;
197
+ const runtimeType = process.env.BUILD_TYPE?.toLowerCase();
198
+ const buildType = buildTimeType || runtimeType;
199
+ if (buildType === "dev") {
200
+ return "dev";
201
+ }
202
+ return "prod";
203
+ }
204
+
205
+ // src/client/common/utils/logger.ts
206
+ var getLogger = (verbose) => ({
207
+ info: (...args) => console.info(...args),
208
+ warn: (...args) => console.warn(...args),
209
+ error: (...args) => console.error(...args),
210
+ debug: (...args) => verbose && console.debug(...args)
211
+ });
212
+
213
+ // src/client/common/utils/userapi.ts
214
+ import axios2 from "axios";
215
+
216
+ // src/client/common/utils/helpers.ts
217
+ import { extractChain, createPublicClient, createWalletClient, http } from "viem";
218
+ import { sepolia as sepolia2 } from "viem/chains";
219
+ import { privateKeyToAccount } from "viem/accounts";
220
+
221
+ // src/client/common/constants.ts
222
+ import { sepolia, mainnet } from "viem/chains";
223
+
224
+ // src/client/common/utils/billing.ts
225
+ function isSubscriptionActive(status) {
226
+ return status === "active" || status === "trialing";
227
+ }
228
+
229
+ // src/client/common/telemetry/noop.ts
230
+ var NoopClient = class {
231
+ /**
232
+ * AddMetric implements the TelemetryClient interface
233
+ */
234
+ async addMetric(_metric) {
235
+ }
236
+ /**
237
+ * Close implements the TelemetryClient interface
238
+ */
239
+ async close() {
240
+ }
241
+ };
242
+ function isNoopClient(client) {
243
+ return client instanceof NoopClient;
244
+ }
245
+
246
+ // src/client/common/telemetry/posthog.ts
247
+ import { PostHog } from "posthog-node";
248
+ var PostHogClient = class {
249
+ constructor(environment, namespace, apiKey, endpoint) {
250
+ this.namespace = namespace;
251
+ this.appEnvironment = environment;
252
+ const host = endpoint || "https://us.i.posthog.com";
253
+ this.client = new PostHog(apiKey, {
254
+ host,
255
+ flushAt: 1,
256
+ // Flush immediately for CLI/SDK usage
257
+ flushInterval: 0
258
+ // Disable interval flushing
259
+ });
260
+ this.client.identify({
261
+ distinctId: environment.userUUID,
262
+ properties: {
263
+ os: environment.os,
264
+ arch: environment.arch,
265
+ ...environment.cliVersion ? { cliVersion: environment.cliVersion } : {}
266
+ }
267
+ });
268
+ }
269
+ /**
270
+ * AddMetric implements the TelemetryClient interface
271
+ */
272
+ async addMetric(metric) {
273
+ try {
274
+ const props = {
275
+ name: metric.name,
276
+ value: metric.value
277
+ };
278
+ for (const [k, v] of Object.entries(metric.dimensions)) {
279
+ props[k] = v;
280
+ }
281
+ this.client.capture({
282
+ distinctId: this.appEnvironment.userUUID,
283
+ event: this.namespace,
284
+ properties: props
285
+ });
286
+ } catch {
287
+ }
288
+ }
289
+ /**
290
+ * Close implements the TelemetryClient interface
291
+ */
292
+ async close() {
293
+ try {
294
+ this.client.shutdown();
295
+ } catch {
296
+ }
297
+ }
298
+ };
299
+ function getPostHogAPIKey() {
300
+ if (process.env.ECLOUD_POSTHOG_KEY) {
301
+ return process.env.ECLOUD_POSTHOG_KEY;
302
+ }
303
+ return true ? "phc_BiKfywNft5iBI8N7MxmuVCkb4GGZj4mDFXYPmOPUAI8" : void 0;
304
+ }
305
+ function getPostHogEndpoint() {
306
+ return process.env.ECLOUD_POSTHOG_ENDPOINT || "https://us.i.posthog.com";
307
+ }
308
+
309
+ // src/client/common/telemetry/index.ts
310
+ import * as os from "os";
311
+
312
+ // src/client/common/telemetry/metricsContext.ts
313
+ function createMetricsContext() {
314
+ return {
315
+ startTime: /* @__PURE__ */ new Date(),
316
+ metrics: [],
317
+ properties: {}
318
+ };
319
+ }
320
+ function addMetric(context, name, value) {
321
+ addMetricWithDimensions(context, name, value, {});
322
+ }
323
+ function addMetricWithDimensions(context, name, value, dimensions) {
324
+ context.metrics.push({
325
+ name,
326
+ value,
327
+ dimensions
328
+ });
329
+ }
330
+
331
+ // src/client/common/telemetry/index.ts
332
+ function createTelemetryClient(environment, namespace, options) {
333
+ const telemetryEnabled = options?.telemetryEnabled === true;
334
+ if (!telemetryEnabled) {
335
+ return new NoopClient();
336
+ }
337
+ const resolvedApiKey = options?.apiKey || getPostHogAPIKey();
338
+ if (!resolvedApiKey) {
339
+ return new NoopClient();
340
+ }
341
+ const endpoint = options?.endpoint || getPostHogEndpoint();
342
+ try {
343
+ return new PostHogClient(environment, namespace, resolvedApiKey, endpoint);
344
+ } catch {
345
+ return new NoopClient();
346
+ }
347
+ }
348
+ function createAppEnvironment(userUUID, cliVersion, osOverride, archOverride) {
349
+ return {
350
+ userUUID,
351
+ cliVersion,
352
+ os: osOverride || os.platform(),
353
+ arch: archOverride || os.arch()
354
+ };
355
+ }
356
+ async function emitMetrics(client, context) {
357
+ if (isNoopClient(client)) {
358
+ return;
359
+ }
360
+ for (const metric of context.metrics) {
361
+ const dimensions = {
362
+ ...metric.dimensions,
363
+ ...context.properties
364
+ };
365
+ const metricWithProperties = {
366
+ ...metric,
367
+ dimensions
368
+ };
369
+ try {
370
+ await client.addMetric(metricWithProperties);
371
+ } catch {
372
+ }
373
+ }
374
+ }
375
+
376
+ // src/client/common/telemetry/wrapper.ts
377
+ import { randomUUID } from "crypto";
378
+ function generateRandomUUID() {
379
+ return randomUUID();
380
+ }
381
+ async function withSDKTelemetry(options, action) {
382
+ if (options.skipTelemetry) {
383
+ return action();
384
+ }
385
+ const userUUID = options.userUUID || generateRandomUUID();
386
+ const environment = createAppEnvironment(userUUID);
387
+ const client = createTelemetryClient(environment, "ecloud-sdk", {
388
+ telemetryEnabled: options.telemetryEnabled,
389
+ apiKey: options.apiKey,
390
+ endpoint: options.endpoint
391
+ });
392
+ const metrics = createMetricsContext();
393
+ metrics.properties["source"] = "ecloud-sdk";
394
+ metrics.properties["function"] = options.functionName;
395
+ if (options.properties) {
396
+ Object.assign(metrics.properties, options.properties);
397
+ }
398
+ addMetric(metrics, "Count", 1);
399
+ let actionError;
400
+ let result;
401
+ try {
402
+ result = await action();
403
+ return result;
404
+ } catch (err) {
405
+ actionError = err instanceof Error ? err : new Error(String(err));
406
+ throw err;
407
+ } finally {
408
+ const resultValue = actionError ? "Failure" : "Success";
409
+ const dimensions = {};
410
+ if (actionError) {
411
+ dimensions["error"] = actionError.message;
412
+ }
413
+ addMetricWithDimensions(metrics, resultValue, 1, dimensions);
414
+ const duration = Date.now() - metrics.startTime.getTime();
415
+ addMetric(metrics, "DurationMilliseconds", duration);
416
+ try {
417
+ await emitMetrics(client, metrics);
418
+ await client.close();
419
+ } catch {
420
+ }
421
+ }
422
+ }
423
+
424
+ // src/client/modules/billing/index.ts
425
+ function createBillingModule(config) {
426
+ const { verbose = false, skipTelemetry = false, walletClient } = config;
427
+ if (!walletClient.account) {
428
+ throw new Error("WalletClient must have an account attached");
429
+ }
430
+ const address = walletClient.account.address;
431
+ const logger = getLogger(verbose);
432
+ const billingEnvConfig = getBillingEnvironmentConfig(getBuildType());
433
+ const billingApi = new BillingApiClient(billingEnvConfig, walletClient);
434
+ return {
435
+ address,
436
+ async subscribe(opts) {
437
+ return withSDKTelemetry(
438
+ {
439
+ functionName: "subscribe",
440
+ skipTelemetry,
441
+ // Skip if called from CLI
442
+ properties: { productId: opts?.productId || "compute" }
443
+ },
444
+ async () => {
445
+ const productId = opts?.productId || "compute";
446
+ logger.debug(`Checking existing subscription for ${productId}...`);
447
+ const currentStatus = await billingApi.getSubscription(productId);
448
+ if (isSubscriptionActive(currentStatus.subscriptionStatus)) {
449
+ logger.debug(`Subscription already active: ${currentStatus.subscriptionStatus}`);
450
+ return {
451
+ type: "already_active",
452
+ status: currentStatus.subscriptionStatus
453
+ };
454
+ }
455
+ if (currentStatus.subscriptionStatus === "past_due" || currentStatus.subscriptionStatus === "unpaid") {
456
+ logger.debug(`Subscription has payment issue: ${currentStatus.subscriptionStatus}`);
457
+ return {
458
+ type: "payment_issue",
459
+ status: currentStatus.subscriptionStatus,
460
+ portalUrl: currentStatus.portalUrl
461
+ };
462
+ }
463
+ logger.debug(`Creating subscription for ${productId}...`);
464
+ const result = await billingApi.createSubscription(productId);
465
+ logger.debug(`Checkout URL: ${result.checkoutUrl}`);
466
+ return {
467
+ type: "checkout_created",
468
+ checkoutUrl: result.checkoutUrl
469
+ };
470
+ }
471
+ );
472
+ },
473
+ async getStatus(opts) {
474
+ return withSDKTelemetry(
475
+ {
476
+ functionName: "getStatus",
477
+ skipTelemetry,
478
+ // Skip if called from CLI
479
+ properties: { productId: opts?.productId || "compute" }
480
+ },
481
+ async () => {
482
+ const productId = opts?.productId || "compute";
483
+ logger.debug(`Fetching subscription status for ${productId}...`);
484
+ const result = await billingApi.getSubscription(productId);
485
+ logger.debug(`Subscription status: ${result.subscriptionStatus}`);
486
+ return result;
487
+ }
488
+ );
489
+ },
490
+ async cancel(opts) {
491
+ return withSDKTelemetry(
492
+ {
493
+ functionName: "cancel",
494
+ skipTelemetry,
495
+ // Skip if called from CLI
496
+ properties: { productId: opts?.productId || "compute" }
497
+ },
498
+ async () => {
499
+ const productId = opts?.productId || "compute";
500
+ logger.debug(`Checking subscription status for ${productId}...`);
501
+ const currentStatus = await billingApi.getSubscription(productId);
502
+ if (!isSubscriptionActive(currentStatus.subscriptionStatus)) {
503
+ logger.debug(`No active subscription to cancel: ${currentStatus.subscriptionStatus}`);
504
+ return {
505
+ type: "no_active_subscription",
506
+ status: currentStatus.subscriptionStatus
507
+ };
508
+ }
509
+ logger.debug(`Canceling subscription for ${productId}...`);
510
+ await billingApi.cancelSubscription(productId);
511
+ logger.debug(`Subscription canceled successfully`);
512
+ return {
513
+ type: "canceled"
514
+ };
515
+ }
516
+ );
517
+ }
518
+ };
519
+ }
5
520
  export {
6
521
  createBillingModule
7
522
  };