@hsuite/smart-engines-sdk 3.0.3 → 3.1.0

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.js CHANGED
@@ -1014,6 +1014,7 @@ zod.z.object({
1014
1014
  // src/discovery/index.ts
1015
1015
  var discovery_exports = {};
1016
1016
  __export(discovery_exports, {
1017
+ ClusterDiscoveryClient: () => ClusterDiscoveryClient,
1017
1018
  MIRROR_NODE_URLS: () => MIRROR_NODE_URLS,
1018
1019
  MirrorNodeClient: () => MirrorNodeClient,
1019
1020
  MirrorNodeError: () => MirrorNodeError,
@@ -1386,6 +1387,185 @@ function normalizeRegistryEntry(raw) {
1386
1387
  return null;
1387
1388
  }
1388
1389
 
1390
+ // src/discovery/cluster-discovery.ts
1391
+ var ClusterDiscoveryClient = class {
1392
+ bootstrap;
1393
+ cacheTtlMs;
1394
+ fetchTimeoutMs;
1395
+ allowInsecure;
1396
+ trustAnchorClient;
1397
+ cache = null;
1398
+ constructor(config) {
1399
+ if (!config.bootstrap || config.bootstrap.length === 0) {
1400
+ throw new Error("ClusterDiscoveryClient: bootstrap must list at least one seed URL");
1401
+ }
1402
+ if (!config.allowInsecure) {
1403
+ for (const seed of config.bootstrap) {
1404
+ if (!seed.startsWith("https://")) {
1405
+ throw new Error(
1406
+ `ClusterDiscoveryClient: bootstrap seed "${seed}" is not HTTPS. Set allowInsecure=true for local development only.`
1407
+ );
1408
+ }
1409
+ }
1410
+ }
1411
+ this.bootstrap = config.bootstrap;
1412
+ this.cacheTtlMs = config.cacheTtlMs ?? 6e4;
1413
+ this.fetchTimeoutMs = config.fetchTimeoutMs ?? 5e3;
1414
+ this.allowInsecure = config.allowInsecure ?? false;
1415
+ this.trustAnchorClient = config.trustAnchor ? new ValidatorDiscoveryClient(config.trustAnchor) : null;
1416
+ }
1417
+ /**
1418
+ * Fetch the active-cluster set, with caching.
1419
+ *
1420
+ * Tries each bootstrap seed in order until one returns HTTP 200 with a
1421
+ * parseable cluster list. If all seeds fail, throws — callers can
1422
+ * handle by falling back to a previously-cached value if they want,
1423
+ * or by initializing with multiple seeds.
1424
+ */
1425
+ async getClusters(forceRefresh = false) {
1426
+ if (!forceRefresh && this.cache && this.isCacheValid()) {
1427
+ return this.cache.clusters;
1428
+ }
1429
+ const fetched = await this.fetchFromFirstAvailableSeed();
1430
+ const verified = this.trustAnchorClient ? await this.verifyAgainstTrustAnchor(fetched) : fetched;
1431
+ this.cache = { clusters: verified, lastUpdated: Date.now() };
1432
+ return verified;
1433
+ }
1434
+ /**
1435
+ * Random pick over the active-cluster set. Returns `null` when no
1436
+ * cluster passes verification (empty registry / all-rejected anchor).
1437
+ *
1438
+ * Uses `crypto.getRandomValues` when available (browsers, Deno, modern
1439
+ * Node) for cryptographic-strength randomness; `Math.random` is a
1440
+ * fallback for older runtimes where `globalThis.crypto` is undefined.
1441
+ * Discovery isn't cryptographically sensitive — load distribution is
1442
+ * the goal here.
1443
+ */
1444
+ async getRandomCluster(forceRefresh = false) {
1445
+ const clusters = await this.getClusters(forceRefresh);
1446
+ if (clusters.length === 0) return null;
1447
+ return clusters[this.pickRandomIndex(clusters.length)];
1448
+ }
1449
+ /**
1450
+ * Convenience wrapper returning just the gateway URL of a random
1451
+ * active cluster. The single most-used SDK entry point — most
1452
+ * downstream callers want `new SmartEngineClient({ baseUrl: ... })`
1453
+ * and don't care about the rest of the metadata.
1454
+ */
1455
+ async getRandomGatewayUrl(forceRefresh = false) {
1456
+ const cluster = await this.getRandomCluster(forceRefresh);
1457
+ return cluster?.endpoints.gatewayUrl ?? null;
1458
+ }
1459
+ /** Per-clusterId lookup, useful for "stick the SDK to cluster X" flows. */
1460
+ async getClusterById(clusterId, forceRefresh = false) {
1461
+ const clusters = await this.getClusters(forceRefresh);
1462
+ return clusters.find((c) => c.clusterId === clusterId) ?? null;
1463
+ }
1464
+ clearCache() {
1465
+ this.cache = null;
1466
+ }
1467
+ isCacheValid() {
1468
+ if (!this.cache) return false;
1469
+ return Date.now() - this.cache.lastUpdated < this.cacheTtlMs;
1470
+ }
1471
+ async fetchFromFirstAvailableSeed() {
1472
+ const errors = [];
1473
+ for (const seed of this.bootstrap) {
1474
+ try {
1475
+ return await this.fetchClustersFromSeed(seed);
1476
+ } catch (err) {
1477
+ errors.push(`${seed}: ${err.message}`);
1478
+ }
1479
+ }
1480
+ throw new Error(
1481
+ `ClusterDiscoveryClient: no bootstrap seed reachable. Attempts:
1482
+ ${errors.join("\n ")}`
1483
+ );
1484
+ }
1485
+ async fetchClustersFromSeed(seed) {
1486
+ const url = `${seed.replace(/\/$/, "")}/api/v3/discovery/clusters`;
1487
+ const ctrl = new AbortController();
1488
+ const timer = setTimeout(() => ctrl.abort(), this.fetchTimeoutMs);
1489
+ try {
1490
+ const res = await fetch(url, { signal: ctrl.signal });
1491
+ if (!res.ok) {
1492
+ throw new Error(`HTTP ${res.status}`);
1493
+ }
1494
+ const body = await res.json();
1495
+ if (!Array.isArray(body.clusters)) {
1496
+ throw new Error("response missing clusters[]");
1497
+ }
1498
+ return body.clusters.map((c) => this.normalizeClusterEntry(c)).filter((c) => c !== null);
1499
+ } finally {
1500
+ clearTimeout(timer);
1501
+ }
1502
+ }
1503
+ normalizeClusterEntry(raw) {
1504
+ if (typeof raw.clusterId !== "string" || !raw.clusterId) return null;
1505
+ if (!raw.endpoints || typeof raw.endpoints !== "object") return null;
1506
+ const ep = raw.endpoints;
1507
+ if (typeof ep.gatewayUrl !== "string" || !ep.gatewayUrl) return null;
1508
+ if (!this.allowInsecure && !ep.gatewayUrl.startsWith("https://")) {
1509
+ return null;
1510
+ }
1511
+ const nodeIds = Array.isArray(raw.nodeIds) ? raw.nodeIds.filter((n) => typeof n === "string") : [];
1512
+ return {
1513
+ clusterId: raw.clusterId,
1514
+ endpoints: {
1515
+ clusterId: raw.clusterId,
1516
+ gatewayUrl: ep.gatewayUrl,
1517
+ harborUrl: typeof ep.harborUrl === "string" ? ep.harborUrl : void 0,
1518
+ natsUrl: typeof ep.natsUrl === "string" ? ep.natsUrl : void 0,
1519
+ publicIp: typeof ep.publicIp === "string" ? ep.publicIp : void 0,
1520
+ region: typeof ep.region === "string" ? ep.region : void 0
1521
+ },
1522
+ nodeIds
1523
+ };
1524
+ }
1525
+ /**
1526
+ * Cross-check the HTTP-fetched cluster set against the HCS validator
1527
+ * registry. Clusters whose nodeIds are not on-chain are dropped.
1528
+ *
1529
+ * Two failure modes are deliberately silent here:
1530
+ * - the HCS read itself throws → original list is returned
1531
+ * un-verified. Trust-anchor is advisory; a network partition
1532
+ * between SDK and Hedera mirror shouldn't strand the SDK.
1533
+ * - the HCS read returns empty (mirror node lag, wrong topicId)
1534
+ * → original list is returned. Better to keep working off
1535
+ * possibly-stale-but-real data than reject every cluster.
1536
+ *
1537
+ * Both behaviors are why this is called "trust *anchor*", not
1538
+ * "trust gate". Crypto-strong gating is a follow-up.
1539
+ */
1540
+ async verifyAgainstTrustAnchor(clusters) {
1541
+ if (!this.trustAnchorClient || clusters.length === 0) return clusters;
1542
+ let onChainNodeIds;
1543
+ try {
1544
+ const validators = await this.trustAnchorClient.getValidators();
1545
+ if (validators.length === 0) return clusters;
1546
+ onChainNodeIds = new Set(validators.map((v) => v.nodeId));
1547
+ } catch {
1548
+ return clusters;
1549
+ }
1550
+ return clusters.filter((c) => {
1551
+ if (c.nodeIds.length === 0) {
1552
+ return false;
1553
+ }
1554
+ return c.nodeIds.some((id) => onChainNodeIds.has(id));
1555
+ });
1556
+ }
1557
+ pickRandomIndex(n) {
1558
+ if (n <= 1) return 0;
1559
+ const g = globalThis.crypto;
1560
+ if (g?.getRandomValues) {
1561
+ const buf = new Uint32Array(1);
1562
+ g.getRandomValues(buf);
1563
+ return buf[0] % n;
1564
+ }
1565
+ return Math.floor(Math.random() * n);
1566
+ }
1567
+ };
1568
+
1389
1569
  // src/auth/index.ts
1390
1570
  var auth_exports = {};
1391
1571
  __export(auth_exports, {
@@ -1784,6 +1964,17 @@ function createHttpClient(config) {
1784
1964
  function encodePathParam(param) {
1785
1965
  return encodeURIComponent(param).replace(/%2F/gi, "");
1786
1966
  }
1967
+ function isRuleRejected(err) {
1968
+ if (!(err instanceof SdkHttpError)) return false;
1969
+ if (err.statusCode !== 403) return false;
1970
+ const d = err.details;
1971
+ if (d === null || typeof d !== "object") return false;
1972
+ const obj = d;
1973
+ if (obj.error !== "rule_rejected") return false;
1974
+ if (typeof obj.reason !== "string") return false;
1975
+ if (!Array.isArray(obj.ruleAtoms)) return false;
1976
+ return obj.ruleAtoms.every((a) => typeof a === "string");
1977
+ }
1787
1978
 
1788
1979
  // src/subscription/index.ts
1789
1980
  var subscription_exports = {};
@@ -2207,6 +2398,167 @@ var SnapshotsClient = class {
2207
2398
  }
2208
2399
  };
2209
2400
 
2401
+ // src/historical-balance/historical-balance-client.ts
2402
+ var DEFAULT_TIMEOUT_MS = 3e4;
2403
+ var ENDPOINT_PATH = "/api/v3/historical-balance/query";
2404
+ var HistoricalBalanceClientError = class extends Error {
2405
+ constructor(message, statusCode, details) {
2406
+ super(message);
2407
+ this.statusCode = statusCode;
2408
+ this.details = details;
2409
+ this.name = "HistoricalBalanceClientError";
2410
+ }
2411
+ statusCode;
2412
+ details;
2413
+ };
2414
+ var HistoricalBalanceClient = class _HistoricalBalanceClient {
2415
+ // Standalone-mode fields (set when the client builds its own fetch).
2416
+ baseUrl;
2417
+ authToken;
2418
+ apiKey;
2419
+ timeoutMs;
2420
+ fetchImpl;
2421
+ // Sub-client-mode field (set when wired via SmartEngineClient).
2422
+ http;
2423
+ constructor(config) {
2424
+ if ("http" in config) {
2425
+ this.http = config.http;
2426
+ this.timeoutMs = DEFAULT_TIMEOUT_MS;
2427
+ return;
2428
+ }
2429
+ if (!config.baseUrl) {
2430
+ throw new HistoricalBalanceClientError(
2431
+ "HistoricalBalanceClient: baseUrl is required for standalone construction",
2432
+ 400
2433
+ );
2434
+ }
2435
+ this.baseUrl = config.baseUrl.replace(/\/+$/, "");
2436
+ this.authToken = config.authToken;
2437
+ this.apiKey = config.apiKey;
2438
+ this.timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;
2439
+ this.fetchImpl = config.fetchImpl;
2440
+ }
2441
+ /**
2442
+ * Factory used by `SmartEngineClient` to wire this sub-client onto the
2443
+ * parent's shared `HttpClient` (which already carries auth + baseUrl + a
2444
+ * `/api/v3` prefix). Routes through `/historical-balance/query` since the
2445
+ * parent's HttpClient is rooted at `/api/v3`.
2446
+ */
2447
+ static fromHttp(http) {
2448
+ return new _HistoricalBalanceClient({ http });
2449
+ }
2450
+ /**
2451
+ * Query a point-in-time balance.
2452
+ *
2453
+ * The validator returns the on-chain bigint as a base-10 decimal string.
2454
+ * Callers needing arithmetic precision should wrap the result:
2455
+ *
2456
+ * ```ts
2457
+ * const { balance } = await client.historicalBalance.getBalance({ ... });
2458
+ * const value = BigInt(balance);
2459
+ * ```
2460
+ */
2461
+ async getBalance(params) {
2462
+ this.validateParams(params);
2463
+ if (this.http) {
2464
+ return this.http.post("/historical-balance/query", params);
2465
+ }
2466
+ return this.standaloneFetch(params);
2467
+ }
2468
+ validateParams(params) {
2469
+ if (!params || typeof params !== "object") {
2470
+ throw new HistoricalBalanceClientError(
2471
+ "HistoricalBalanceClient.getBalance: params object is required",
2472
+ 400
2473
+ );
2474
+ }
2475
+ const { chain, entityId, account, atTimestamp } = params;
2476
+ if (chain !== "hedera" && chain !== "xrpl" && chain !== "polkadot") {
2477
+ throw new HistoricalBalanceClientError(
2478
+ `HistoricalBalanceClient.getBalance: unsupported chain "${String(chain)}" (expected hedera | xrpl | polkadot)`,
2479
+ 400
2480
+ );
2481
+ }
2482
+ if (typeof entityId !== "string" || entityId.length === 0) {
2483
+ throw new HistoricalBalanceClientError(
2484
+ "HistoricalBalanceClient.getBalance: entityId must be a non-empty string",
2485
+ 400
2486
+ );
2487
+ }
2488
+ if (typeof account !== "string" || account.length === 0) {
2489
+ throw new HistoricalBalanceClientError(
2490
+ "HistoricalBalanceClient.getBalance: account must be a non-empty string",
2491
+ 400
2492
+ );
2493
+ }
2494
+ if (typeof atTimestamp !== "number" || !Number.isInteger(atTimestamp) || atTimestamp <= 0) {
2495
+ throw new HistoricalBalanceClientError(
2496
+ "HistoricalBalanceClient.getBalance: atTimestamp must be a positive integer (unix seconds)",
2497
+ 400
2498
+ );
2499
+ }
2500
+ }
2501
+ async standaloneFetch(params) {
2502
+ const url = `${this.baseUrl}${ENDPOINT_PATH}`;
2503
+ const headers = {
2504
+ "Content-Type": "application/json",
2505
+ Accept: "application/json"
2506
+ };
2507
+ if (this.authToken) headers.Authorization = `Bearer ${this.authToken}`;
2508
+ if (this.apiKey) headers["X-API-Key"] = this.apiKey;
2509
+ const fetchFn = this.fetchImpl ?? (typeof fetch !== "undefined" ? fetch : void 0);
2510
+ if (!fetchFn) {
2511
+ throw new HistoricalBalanceClientError(
2512
+ "HistoricalBalanceClient: no fetch implementation available (provide fetchImpl)",
2513
+ 500
2514
+ );
2515
+ }
2516
+ const controller = new AbortController();
2517
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
2518
+ let response;
2519
+ try {
2520
+ response = await fetchFn(url, {
2521
+ method: "POST",
2522
+ headers,
2523
+ body: JSON.stringify(params),
2524
+ signal: controller.signal
2525
+ });
2526
+ } catch (err) {
2527
+ clearTimeout(timer);
2528
+ const message = err instanceof Error ? err.message : String(err);
2529
+ throw new HistoricalBalanceClientError(
2530
+ `HistoricalBalanceClient: transport error: ${message}`,
2531
+ 0,
2532
+ err
2533
+ );
2534
+ }
2535
+ clearTimeout(timer);
2536
+ let body;
2537
+ const text = await response.text();
2538
+ if (text.length > 0) {
2539
+ try {
2540
+ body = JSON.parse(text);
2541
+ } catch (err) {
2542
+ const message = err instanceof Error ? err.message : String(err);
2543
+ throw new HistoricalBalanceClientError(
2544
+ `HistoricalBalanceClient: non-JSON response (status=${response.status}): ${message}`,
2545
+ response.status,
2546
+ { raw: text }
2547
+ );
2548
+ }
2549
+ }
2550
+ if (!response.ok) {
2551
+ const detail = body && typeof body === "object" && "message" in body ? String(body.message) : `HTTP ${response.status}`;
2552
+ throw new HistoricalBalanceClientError(
2553
+ `HistoricalBalanceClient: ${detail}`,
2554
+ response.status,
2555
+ body
2556
+ );
2557
+ }
2558
+ return body;
2559
+ }
2560
+ };
2561
+
2210
2562
  // src/settlement/index.ts
2211
2563
  var settlement_exports = {};
2212
2564
  __export(settlement_exports, {
@@ -2245,6 +2597,75 @@ var SettlementClient = class {
2245
2597
  }
2246
2598
  };
2247
2599
 
2600
+ // src/governance/index.ts
2601
+ var governance_exports = {};
2602
+ __export(governance_exports, {
2603
+ GovernanceClient: () => GovernanceClient
2604
+ });
2605
+
2606
+ // src/governance/governance-client.ts
2607
+ var GovernanceClient = class {
2608
+ constructor(http) {
2609
+ this.http = http;
2610
+ }
2611
+ http;
2612
+ /**
2613
+ * Dry-run a governance proposal/vote/etc. against `GovernanceMolecule.validate(...)`.
2614
+ *
2615
+ * Returns whatever `ValidationResult` the molecule produced. A `false`
2616
+ * `isValid` is **not** an error — it is a successful "this proposal is
2617
+ * invalid" outcome and is surfaced via the normal return value.
2618
+ *
2619
+ * HTTP errors (400 malformed body, 500 unexpected) bubble up as
2620
+ * `SdkHttpError` via the shared `HttpClient` layer.
2621
+ */
2622
+ async simulate(params) {
2623
+ return this.http.post("/governance/simulate", params);
2624
+ }
2625
+ };
2626
+
2627
+ // src/personhood/index.ts
2628
+ var personhood_exports = {};
2629
+ __export(personhood_exports, {
2630
+ PERSONHOOD_VERIFIER_NOT_CONFIGURED: () => PERSONHOOD_VERIFIER_NOT_CONFIGURED,
2631
+ PersonhoodClient: () => PersonhoodClient,
2632
+ isPersonhoodVerifierNotConfigured: () => isPersonhoodVerifierNotConfigured
2633
+ });
2634
+
2635
+ // src/personhood/personhood-client.ts
2636
+ var PERSONHOOD_VERIFIER_NOT_CONFIGURED = "personhood_verifier_not_configured";
2637
+ var PersonhoodClient = class {
2638
+ constructor(http) {
2639
+ this.http = http;
2640
+ }
2641
+ http;
2642
+ /**
2643
+ * Verify a personhood proof for `candidate`.
2644
+ *
2645
+ * Returns the issued cert on accept, `null` on clean rejection. All
2646
+ * other failure modes (validation, transport, 5xx) propagate as
2647
+ * `SdkHttpError`.
2648
+ */
2649
+ async verify(params) {
2650
+ const result = await this.http.post(
2651
+ "/personhood/verify",
2652
+ {
2653
+ candidate: params.candidate,
2654
+ proof: params.proof
2655
+ }
2656
+ );
2657
+ if (result === void 0) return null;
2658
+ return result;
2659
+ }
2660
+ };
2661
+ function isPersonhoodVerifierNotConfigured(err) {
2662
+ if (!(err instanceof SdkHttpError)) return false;
2663
+ if (err.statusCode !== 503) return false;
2664
+ const d = err.details;
2665
+ if (d === null || typeof d !== "object") return false;
2666
+ return d.error === PERSONHOOD_VERIFIER_NOT_CONFIGURED;
2667
+ }
2668
+
2248
2669
  // src/client.ts
2249
2670
  var SmartEngineClient = class _SmartEngineClient {
2250
2671
  baseUrl;
@@ -2265,8 +2686,14 @@ var SmartEngineClient = class _SmartEngineClient {
2265
2686
  transactions;
2266
2687
  /** Token holder snapshot generation and retrieval */
2267
2688
  snapshots;
2689
+ /** Historical balance archive reads (chain-native bigint, returned as decimal string) */
2690
+ historicalBalance;
2268
2691
  /** Cross-chain settlement operations */
2269
2692
  settlement;
2693
+ /** Governance proposal dry-run (simulate-only) */
2694
+ governance;
2695
+ /** Personhood verification (HPP one-human-one-member) */
2696
+ personhood;
2270
2697
  constructor(config) {
2271
2698
  this.allowInsecure = config.allowInsecure ?? false;
2272
2699
  this.baseUrl = validateClientUrl(config.baseUrl, this.allowInsecure);
@@ -2287,7 +2714,10 @@ var SmartEngineClient = class _SmartEngineClient {
2287
2714
  this.ipfs = new IPFSClient(this.http);
2288
2715
  this.transactions = new TransactionsClient(this.txHttp);
2289
2716
  this.snapshots = new SnapshotsClient(this.http);
2717
+ this.historicalBalance = HistoricalBalanceClient.fromHttp(this.http);
2290
2718
  this.settlement = new SettlementClient(this.http);
2719
+ this.governance = new GovernanceClient(this.http);
2720
+ this.personhood = new PersonhoodClient(this.http);
2291
2721
  }
2292
2722
  /**
2293
2723
  * Connect to the smart-engines network with auto-discovery and authentication
@@ -2332,6 +2762,67 @@ var SmartEngineClient = class _SmartEngineClient {
2332
2762
  });
2333
2763
  return { client, validator, session };
2334
2764
  }
2765
+ /**
2766
+ * Connect to the smart-engines network via the **service-registry**
2767
+ * (PR-1 of the cluster-discovery arc). Preferred over
2768
+ * {@link connectToNetwork} once the validator pods in the target network
2769
+ * have published their cluster endpoints — the SDK auto-balances across
2770
+ * the active cluster set and rides permissionless cluster join/leave
2771
+ * without code edits.
2772
+ *
2773
+ * Fallback ladder (per `docs/ops/HANDOFF-service-registry-distribution-layer.md` §6):
2774
+ * 1. HTTP fetch `/api/v3/discovery/clusters` from each bootstrap seed.
2775
+ * 2. (Optional) HCS trust-anchor membership cross-check.
2776
+ * 3. Random-pick over the verified set.
2777
+ *
2778
+ * @example
2779
+ * ```ts
2780
+ * const { client, cluster, session } = await SmartEngineClient.connectToCluster({
2781
+ * bootstrap: ['https://sn1.testnet.hsuite.network', 'https://sn2.testnet.hsuite.network'],
2782
+ * chain: 'xrpl',
2783
+ * address: '...',
2784
+ * publicKey: '...',
2785
+ * signFn: async (challenge) => sign(challenge),
2786
+ * });
2787
+ * ```
2788
+ */
2789
+ static async connectToCluster(config) {
2790
+ const allowInsecure = config.allowInsecure ?? false;
2791
+ const discovery = new ClusterDiscoveryClient({
2792
+ bootstrap: config.bootstrap,
2793
+ allowInsecure,
2794
+ trustAnchor: config.trustAnchor ? {
2795
+ network: config.trustAnchor.network,
2796
+ registryTopicId: config.trustAnchor.registryTopicId,
2797
+ mirrorNodeUrl: config.trustAnchor.mirrorNodeUrl,
2798
+ allowInsecure
2799
+ } : void 0
2800
+ });
2801
+ const cluster = await discovery.getRandomCluster();
2802
+ if (!cluster) {
2803
+ throw new SmartEngineError2(
2804
+ "No active clusters available via bootstrap seeds. Check bootstrap URLs and network reachability.",
2805
+ 503
2806
+ );
2807
+ }
2808
+ const gatewayUrl = cluster.endpoints.gatewayUrl;
2809
+ validateClientUrl(gatewayUrl, allowInsecure);
2810
+ const auth = new ValidatorAuthClient({ security: { allowInsecure } });
2811
+ const session = await auth.authenticateWithSigner(
2812
+ gatewayUrl,
2813
+ config.chain,
2814
+ config.address,
2815
+ config.publicKey,
2816
+ config.signFn,
2817
+ config.metadata
2818
+ );
2819
+ const client = new _SmartEngineClient({
2820
+ baseUrl: gatewayUrl,
2821
+ authToken: session.token,
2822
+ allowInsecure
2823
+ });
2824
+ return { client, cluster, session };
2825
+ }
2335
2826
  /** Get the current validator URL */
2336
2827
  getBaseUrl() {
2337
2828
  return this.baseUrl;
@@ -4137,11 +4628,16 @@ exports.DnsClient = DnsClient;
4137
4628
  exports.DomainsClient = DomainsClient;
4138
4629
  exports.ErrorCode = ErrorCode;
4139
4630
  exports.FunctionsClient = FunctionsClient;
4631
+ exports.GovernanceClient = GovernanceClient;
4632
+ exports.HistoricalBalanceClient = HistoricalBalanceClient;
4633
+ exports.HistoricalBalanceClientError = HistoricalBalanceClientError;
4140
4634
  exports.IPFSClient = IPFSClient;
4141
4635
  exports.MIRROR_NODE_URLS = MIRROR_NODE_URLS;
4142
4636
  exports.MessagingClient = MessagingClient;
4143
4637
  exports.MirrorNodeClient = MirrorNodeClient;
4144
4638
  exports.MirrorNodeError = MirrorNodeError;
4639
+ exports.PERSONHOOD_VERIFIER_NOT_CONFIGURED = PERSONHOOD_VERIFIER_NOT_CONFIGURED;
4640
+ exports.PersonhoodClient = PersonhoodClient;
4145
4641
  exports.RateLimiter = RateLimiter;
4146
4642
  exports.RoutingClient = RoutingClient;
4147
4643
  exports.SdkHttpError = SdkHttpError;
@@ -4165,6 +4661,10 @@ exports.createHttpClient = createHttpClient;
4165
4661
  exports.createResilientFetchWithBreaker = createResilientFetchWithBreaker;
4166
4662
  exports.discovery = discovery_exports;
4167
4663
  exports.encodePathParam = encodePathParam;
4664
+ exports.governance = governance_exports;
4665
+ exports.isPersonhoodVerifierNotConfigured = isPersonhoodVerifierNotConfigured;
4666
+ exports.isRuleRejected = isRuleRejected;
4667
+ exports.personhood = personhood_exports;
4168
4668
  exports.resilientFetch = resilientFetch;
4169
4669
  exports.settlement = settlement_exports;
4170
4670
  exports.subscription = subscription_exports;