@hsuite/smart-engines-sdk 3.4.1 → 3.6.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
@@ -5674,7 +5674,7 @@ var CreateAccountRequestSchema = zod.z.object({
5674
5674
  * Smart node security mode for the account key structure.
5675
5675
  * - 'partial': threshold(2, [appOwnerKey, tssKeyList]) — co-control
5676
5676
  * - 'full': TSS KeyList only — full validator network control
5677
- * Default: 'full' (Arc 5 §7.5.2: 'none' removed).
5677
+ * @defaultValue 'full'
5678
5678
  */
5679
5679
  securityMode: zod.z.enum(["partial", "full"]).default("full"),
5680
5680
  /**
@@ -6008,7 +6008,8 @@ __export(discovery_exports, {
6008
6008
  MirrorNodeClient: () => MirrorNodeClient,
6009
6009
  MirrorNodeError: () => MirrorNodeError,
6010
6010
  PlatformImagesClient: () => PlatformImagesClient,
6011
- ValidatorDiscoveryClient: () => ValidatorDiscoveryClient
6011
+ ValidatorDiscoveryClient: () => ValidatorDiscoveryClient,
6012
+ resolveClusterEndpoint: () => resolveClusterEndpoint
6012
6013
  });
6013
6014
 
6014
6015
  // src/discovery/mirror-node.ts
@@ -6556,6 +6557,198 @@ var ClusterDiscoveryClient = class {
6556
6557
  }
6557
6558
  };
6558
6559
 
6560
+ // src/http/index.ts
6561
+ var SdkHttpError = class extends Error {
6562
+ constructor(message, statusCode, details) {
6563
+ super(message);
6564
+ this.statusCode = statusCode;
6565
+ this.details = details;
6566
+ this.name = "SdkHttpError";
6567
+ }
6568
+ statusCode;
6569
+ details;
6570
+ };
6571
+ function createHttpClient(config) {
6572
+ const timeout = config.timeout ?? 3e4;
6573
+ function getHeaders(contentType) {
6574
+ const headers = {};
6575
+ if (contentType) {
6576
+ headers["Content-Type"] = contentType;
6577
+ }
6578
+ if (config.authToken) {
6579
+ headers["Authorization"] = `Bearer ${config.authToken}`;
6580
+ }
6581
+ if (config.apiKey) {
6582
+ headers["X-API-Key"] = config.apiKey;
6583
+ }
6584
+ return headers;
6585
+ }
6586
+ function setAuthToken(token) {
6587
+ config.authToken = token;
6588
+ }
6589
+ function getAuthToken() {
6590
+ return config.authToken;
6591
+ }
6592
+ async function request(method, path, body) {
6593
+ const url = `${config.baseUrl}${path}`;
6594
+ const controller = new AbortController();
6595
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
6596
+ try {
6597
+ const init = {
6598
+ method,
6599
+ headers: getHeaders("application/json"),
6600
+ signal: controller.signal
6601
+ };
6602
+ if (body !== void 0) {
6603
+ init.body = JSON.stringify(body);
6604
+ }
6605
+ const response = await fetch(url, init);
6606
+ clearTimeout(timeoutId);
6607
+ if (!response.ok) {
6608
+ const errorData = await response.json().catch(() => ({}));
6609
+ throw new SdkHttpError(
6610
+ errorData.message || `API error: ${response.status} ${response.statusText}`,
6611
+ response.status,
6612
+ errorData
6613
+ );
6614
+ }
6615
+ const text = await response.text();
6616
+ if (!text) return void 0;
6617
+ return JSON.parse(text);
6618
+ } catch (error) {
6619
+ clearTimeout(timeoutId);
6620
+ if (error instanceof SdkHttpError) throw error;
6621
+ const err = error;
6622
+ if (err.name === "AbortError") {
6623
+ throw new SdkHttpError("Request timeout", 408);
6624
+ }
6625
+ throw new SdkHttpError(`Network error: ${err.message}`, 0, error);
6626
+ }
6627
+ }
6628
+ async function getText(path) {
6629
+ const url = `${config.baseUrl}${path}`;
6630
+ const controller = new AbortController();
6631
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
6632
+ try {
6633
+ const response = await fetch(url, {
6634
+ method: "GET",
6635
+ headers: getHeaders(),
6636
+ signal: controller.signal
6637
+ });
6638
+ clearTimeout(timeoutId);
6639
+ if (!response.ok) {
6640
+ const errBody = await response.json().catch(() => ({}));
6641
+ throw new SdkHttpError(
6642
+ errBody.message || `API error: ${response.status} ${response.statusText}`,
6643
+ response.status,
6644
+ errBody
6645
+ );
6646
+ }
6647
+ return await response.text();
6648
+ } catch (error) {
6649
+ clearTimeout(timeoutId);
6650
+ if (error instanceof SdkHttpError) throw error;
6651
+ const err = error;
6652
+ if (err.name === "AbortError") {
6653
+ throw new SdkHttpError("Request timeout", 408);
6654
+ }
6655
+ throw new SdkHttpError(`Network error: ${err.message}`, 0, error);
6656
+ }
6657
+ }
6658
+ async function upload(path, file, filename, metadata, fieldName = "file") {
6659
+ const url = `${config.baseUrl}${path}`;
6660
+ const controller = new AbortController();
6661
+ const timeoutId = setTimeout(() => controller.abort(), timeout * 2);
6662
+ try {
6663
+ const formData = new FormData();
6664
+ const blob = file instanceof Blob ? file : new Blob([new Uint8Array(file)]);
6665
+ formData.append(fieldName, blob, filename);
6666
+ if (metadata) {
6667
+ for (const [key, value] of Object.entries(metadata)) {
6668
+ formData.append(key, value);
6669
+ }
6670
+ }
6671
+ const headers = {};
6672
+ if (config.authToken) {
6673
+ headers["Authorization"] = `Bearer ${config.authToken}`;
6674
+ }
6675
+ if (config.apiKey) {
6676
+ headers["X-API-Key"] = config.apiKey;
6677
+ }
6678
+ const response = await fetch(url, {
6679
+ method: "POST",
6680
+ headers,
6681
+ body: formData,
6682
+ signal: controller.signal
6683
+ });
6684
+ clearTimeout(timeoutId);
6685
+ if (!response.ok) {
6686
+ const errorData = await response.json().catch(() => ({}));
6687
+ throw new SdkHttpError(
6688
+ errorData.message || `Upload error: ${response.status} ${response.statusText}`,
6689
+ response.status,
6690
+ errorData
6691
+ );
6692
+ }
6693
+ return response.json();
6694
+ } catch (error) {
6695
+ clearTimeout(timeoutId);
6696
+ if (error instanceof SdkHttpError) throw error;
6697
+ const err = error;
6698
+ if (err.name === "AbortError") {
6699
+ throw new SdkHttpError("Upload timeout", 408);
6700
+ }
6701
+ throw new SdkHttpError(`Upload error: ${err.message}`, 0, error);
6702
+ }
6703
+ }
6704
+ let reauthInFlight = null;
6705
+ async function withAuthRetry(path, op) {
6706
+ try {
6707
+ return await op();
6708
+ } catch (error) {
6709
+ const refreshable = !!config.onUnauthorized && !path.startsWith("/api/auth/") && error instanceof SdkHttpError && error.statusCode === 401;
6710
+ if (!refreshable) throw error;
6711
+ if (!reauthInFlight) {
6712
+ reauthInFlight = Promise.resolve(config.onUnauthorized()).finally(() => {
6713
+ reauthInFlight = null;
6714
+ });
6715
+ }
6716
+ try {
6717
+ await reauthInFlight;
6718
+ } catch {
6719
+ throw error;
6720
+ }
6721
+ return await op();
6722
+ }
6723
+ }
6724
+ const client = {
6725
+ post: (path, body) => withAuthRetry(path, () => request("POST", path, body)),
6726
+ get: (path) => withAuthRetry(path, () => request("GET", path)),
6727
+ put: (path, body) => withAuthRetry(path, () => request("PUT", path, body)),
6728
+ patch: (path, body) => withAuthRetry(path, () => request("PATCH", path, body)),
6729
+ delete: (path) => withAuthRetry(path, () => request("DELETE", path)),
6730
+ getText: (path) => withAuthRetry(path, () => getText(path)),
6731
+ upload: ((path, file, filename, metadata, fieldName) => withAuthRetry(path, () => upload(path, file, filename, metadata, fieldName))),
6732
+ setAuthToken,
6733
+ getAuthToken
6734
+ };
6735
+ return client;
6736
+ }
6737
+ function encodePathParam(param) {
6738
+ return encodeURIComponent(param).replace(/%2F/gi, "");
6739
+ }
6740
+ function isRuleRejected(err) {
6741
+ if (!(err instanceof SdkHttpError)) return false;
6742
+ if (err.statusCode !== 403) return false;
6743
+ const d = err.details;
6744
+ if (d === null || typeof d !== "object") return false;
6745
+ const obj = d;
6746
+ if (obj.error !== "rule_rejected") return false;
6747
+ if (typeof obj.reason !== "string") return false;
6748
+ if (!Array.isArray(obj.ruleAtoms)) return false;
6749
+ return obj.ruleAtoms.every((a) => typeof a === "string");
6750
+ }
6751
+
6559
6752
  // src/discovery/discovery-client.ts
6560
6753
  var DiscoveryClient = class {
6561
6754
  constructor(http) {
@@ -6589,7 +6782,7 @@ var DiscoveryClient = class {
6589
6782
  * try/catch.
6590
6783
  */
6591
6784
  async getClusterByNode(nodeId) {
6592
- return this.http.get(`/discovery/clusters/${encodeURIComponent(nodeId)}`);
6785
+ return this.http.get(`/discovery/clusters/${encodePathParam(nodeId)}`);
6593
6786
  }
6594
6787
  };
6595
6788
  var PlatformImagesClient = class {
@@ -6619,7 +6812,7 @@ var PlatformImagesClient = class {
6619
6812
  * authorized?" queries.
6620
6813
  */
6621
6814
  async get(imageName) {
6622
- return this.http.get(`/discovery/platform-images/${encodeURIComponent(imageName)}`);
6815
+ return this.http.get(`/discovery/platform-images/${encodePathParam(imageName)}`);
6623
6816
  }
6624
6817
  /**
6625
6818
  * `GET /api/v3/discovery/platform-images/:imageName/:version` —
@@ -6628,7 +6821,7 @@ var PlatformImagesClient = class {
6628
6821
  */
6629
6822
  async getVersion(imageName, version) {
6630
6823
  return this.http.get(
6631
- `/discovery/platform-images/${encodeURIComponent(imageName)}/${encodeURIComponent(version)}`
6824
+ `/discovery/platform-images/${encodePathParam(imageName)}/${encodePathParam(version)}`
6632
6825
  );
6633
6826
  }
6634
6827
  /**
@@ -6642,13 +6835,66 @@ var PlatformImagesClient = class {
6642
6835
  */
6643
6836
  async verify(imageName, version, digest) {
6644
6837
  return this.http.get(
6645
- `/discovery/platform-images/${encodeURIComponent(imageName)}/${encodeURIComponent(
6838
+ `/discovery/platform-images/${encodePathParam(imageName)}/${encodePathParam(
6646
6839
  version
6647
6840
  )}/verify?digest=${encodeURIComponent(digest)}`
6648
6841
  );
6649
6842
  }
6650
6843
  };
6651
6844
 
6845
+ // src/network-presets.ts
6846
+ var KNOWN_NETWORKS = {
6847
+ testnet: {
6848
+ bootstrap: ["https://gateway.testnet.hsuite.network"]
6849
+ },
6850
+ mainnet: {
6851
+ // Mainnet entrypoint reserved. The SDK still resolves the name so
6852
+ // upgrade-by-flipping-NETWORK works; the bootstrap URL is the
6853
+ // pre-allocated DNS we own. If mainnet isn't deployed yet, the discovery
6854
+ // fetch will fail at runtime with the same "no seed reachable" error
6855
+ // any unreachable URL produces — the caller learns the network is not
6856
+ // live, rather than getting a baffling "unknown network" TypeScript
6857
+ // error at compile time.
6858
+ bootstrap: ["https://gateway.hsuite.network"]
6859
+ }
6860
+ };
6861
+ function resolveNetwork(name) {
6862
+ const preset = KNOWN_NETWORKS[name];
6863
+ if (!preset) {
6864
+ throw new Error(
6865
+ `Unknown network: "${name}". Known networks: ${Object.keys(KNOWN_NETWORKS).join(", ")}`
6866
+ );
6867
+ }
6868
+ return preset;
6869
+ }
6870
+ function isKnownNetwork(name) {
6871
+ return Object.prototype.hasOwnProperty.call(KNOWN_NETWORKS, name);
6872
+ }
6873
+
6874
+ // src/discovery/resolve-cluster.ts
6875
+ async function resolveClusterEndpoint(config) {
6876
+ const allowInsecure = config.allowInsecure ?? false;
6877
+ const bootstrap = config.bootstrap ? [...config.bootstrap] : config.network ? [...resolveNetwork(config.network).bootstrap] : [];
6878
+ if (bootstrap.length === 0) {
6879
+ return { ok: false, reason: "no-seeds" };
6880
+ }
6881
+ const discovery = new ClusterDiscoveryClient({
6882
+ bootstrap,
6883
+ allowInsecure,
6884
+ trustAnchor: config.trustAnchor ? {
6885
+ network: config.trustAnchor.network,
6886
+ registryTopicId: config.trustAnchor.registryTopicId,
6887
+ mirrorNodeUrl: config.trustAnchor.mirrorNodeUrl,
6888
+ allowInsecure
6889
+ } : void 0
6890
+ });
6891
+ const cluster = await discovery.getRandomCluster();
6892
+ if (!cluster) {
6893
+ return { ok: false, reason: "no-clusters" };
6894
+ }
6895
+ return { ok: true, cluster };
6896
+ }
6897
+
6652
6898
  // src/auth/index.ts
6653
6899
  var auth_exports = {};
6654
6900
  __export(auth_exports, {
@@ -6665,6 +6911,10 @@ var SUPPORTED_AUTH_CHAINS = [
6665
6911
  "stellar",
6666
6912
  "solana"
6667
6913
  ];
6914
+ function toBytes(value) {
6915
+ if (value instanceof Uint8Array) return value;
6916
+ return value.toBytes();
6917
+ }
6668
6918
  function validateValidatorUrl(url, allowInsecure = false) {
6669
6919
  try {
6670
6920
  const parsed = new URL(url);
@@ -6863,276 +7113,91 @@ var ValidatorAuthClient = class {
6863
7113
  throw new ValidatorAuthError(`Session request failed: ${err.message}`, 0);
6864
7114
  }
6865
7115
  }
6866
- /**
6867
- * Sign challenge with Hedera private key
6868
- *
6869
- * @param challenge - Challenge string from validator
6870
- * @param privateKey - Hedera PrivateKey instance from @hashgraph/sdk
6871
- * @returns Hex-encoded signature
6872
- */
6873
- signChallengeHedera(challenge, privateKey) {
6874
- const messageBytes = Buffer.from(challenge, "utf-8");
6875
- const signature = privateKey.sign(messageBytes);
6876
- return Buffer.from(signature).toString("hex");
6877
- }
6878
- /**
6879
- * Sign challenge with XRPL wallet
6880
- *
6881
- * @param challenge - Challenge string from validator
6882
- * @param wallet - XRPL Wallet instance from xrpl library
6883
- * @returns Hex-encoded signature
6884
- */
6885
- signChallengeXRPL(challenge, wallet) {
6886
- const signature = wallet.sign(challenge);
6887
- if (typeof signature === "string" && /^[0-9A-Fa-f]+$/.test(signature)) {
6888
- return signature;
6889
- }
6890
- return Buffer.from(signature).toString("hex");
6891
- }
6892
- /**
6893
- * Complete authentication flow in one call
6894
- *
6895
- * @param validatorUrl - Validator API base URL
6896
- * @param chain - Blockchain type
6897
- * @param address - Wallet address
6898
- * @param publicKey - Public key (hex)
6899
- * @param signFn - Function to sign the challenge
6900
- * @param metadata - Optional metadata
6901
- * @returns Session token and info
6902
- */
6903
- async authenticateWithSigner(validatorUrl, chain, address, publicKey, signFn, metadata) {
6904
- const challengeResponse = await this.requestChallenge(validatorUrl, chain, address);
6905
- const signature = await signFn(challengeResponse.challenge);
6906
- return this.authenticate(validatorUrl, {
6907
- chain,
6908
- address,
6909
- publicKey,
6910
- signature,
6911
- challenge: challengeResponse.challenge,
6912
- metadata
6913
- });
6914
- }
6915
- };
6916
- var ValidatorAuthError = class extends Error {
6917
- constructor(message, statusCode, details) {
6918
- super(message);
6919
- this.statusCode = statusCode;
6920
- this.details = details;
6921
- this.name = "ValidatorAuthError";
6922
- }
6923
- statusCode;
6924
- details;
6925
- };
6926
- var { sign: rippleSign } = require_dist2();
6927
- function createXrplWeb3Signer(seed) {
6928
- const wallet = xrpl.Wallet.fromSeed(seed);
6929
- return {
6930
- chain: "xrpl",
6931
- address: wallet.classicAddress,
6932
- publicKey: wallet.publicKey,
6933
- signFn: (challenge) => {
6934
- const messageHex = Buffer.from(challenge, "utf-8").toString("hex").toUpperCase();
6935
- return rippleSign(messageHex, wallet.privateKey);
6936
- },
6937
- wallet
6938
- };
6939
- }
6940
-
6941
- // src/http/index.ts
6942
- var SdkHttpError = class extends Error {
6943
- constructor(message, statusCode, details) {
6944
- super(message);
6945
- this.statusCode = statusCode;
6946
- this.details = details;
6947
- this.name = "SdkHttpError";
6948
- }
6949
- statusCode;
6950
- details;
6951
- };
6952
- function createHttpClient(config) {
6953
- const timeout = config.timeout ?? 3e4;
6954
- function getHeaders(contentType) {
6955
- const headers = {};
6956
- if (contentType) {
6957
- headers["Content-Type"] = contentType;
6958
- }
6959
- if (config.authToken) {
6960
- headers["Authorization"] = `Bearer ${config.authToken}`;
6961
- }
6962
- if (config.apiKey) {
6963
- headers["X-API-Key"] = config.apiKey;
6964
- }
6965
- return headers;
6966
- }
6967
- function setAuthToken(token) {
6968
- config.authToken = token;
6969
- }
6970
- async function request(method, path, body) {
6971
- const url = `${config.baseUrl}${path}`;
6972
- const controller = new AbortController();
6973
- const timeoutId = setTimeout(() => controller.abort(), timeout);
6974
- try {
6975
- const init = {
6976
- method,
6977
- headers: getHeaders("application/json"),
6978
- signal: controller.signal
6979
- };
6980
- if (body !== void 0) {
6981
- init.body = JSON.stringify(body);
6982
- }
6983
- const response = await fetch(url, init);
6984
- clearTimeout(timeoutId);
6985
- if (!response.ok) {
6986
- const errorData = await response.json().catch(() => ({}));
6987
- throw new SdkHttpError(
6988
- errorData.message || `API error: ${response.status} ${response.statusText}`,
6989
- response.status,
6990
- errorData
6991
- );
6992
- }
6993
- const text = await response.text();
6994
- if (!text) return void 0;
6995
- return JSON.parse(text);
6996
- } catch (error) {
6997
- clearTimeout(timeoutId);
6998
- if (error instanceof SdkHttpError) throw error;
6999
- const err = error;
7000
- if (err.name === "AbortError") {
7001
- throw new SdkHttpError("Request timeout", 408);
7002
- }
7003
- throw new SdkHttpError(`Network error: ${err.message}`, 0, error);
7004
- }
7005
- }
7006
- async function getText(path) {
7007
- const url = `${config.baseUrl}${path}`;
7008
- const controller = new AbortController();
7009
- const timeoutId = setTimeout(() => controller.abort(), timeout);
7010
- try {
7011
- const response = await fetch(url, {
7012
- method: "GET",
7013
- headers: getHeaders(),
7014
- signal: controller.signal
7015
- });
7016
- clearTimeout(timeoutId);
7017
- if (!response.ok) {
7018
- const errBody = await response.json().catch(() => ({}));
7019
- throw new SdkHttpError(
7020
- errBody.message || `API error: ${response.status} ${response.statusText}`,
7021
- response.status,
7022
- errBody
7023
- );
7024
- }
7025
- return await response.text();
7026
- } catch (error) {
7027
- clearTimeout(timeoutId);
7028
- if (error instanceof SdkHttpError) throw error;
7029
- const err = error;
7030
- if (err.name === "AbortError") {
7031
- throw new SdkHttpError("Request timeout", 408);
7032
- }
7033
- throw new SdkHttpError(`Network error: ${err.message}`, 0, error);
7034
- }
7035
- }
7036
- async function upload(path, file, filename, metadata, fieldName = "file") {
7037
- const url = `${config.baseUrl}${path}`;
7038
- const controller = new AbortController();
7039
- const timeoutId = setTimeout(() => controller.abort(), timeout * 2);
7040
- try {
7041
- const formData = new FormData();
7042
- const blob = file instanceof Blob ? file : new Blob([new Uint8Array(file)]);
7043
- formData.append(fieldName, blob, filename);
7044
- if (metadata) {
7045
- for (const [key, value] of Object.entries(metadata)) {
7046
- formData.append(key, value);
7047
- }
7048
- }
7049
- const headers = {};
7050
- if (config.authToken) {
7051
- headers["Authorization"] = `Bearer ${config.authToken}`;
7052
- }
7053
- if (config.apiKey) {
7054
- headers["X-API-Key"] = config.apiKey;
7055
- }
7056
- const response = await fetch(url, {
7057
- method: "POST",
7058
- headers,
7059
- body: formData,
7060
- signal: controller.signal
7061
- });
7062
- clearTimeout(timeoutId);
7063
- if (!response.ok) {
7064
- const errorData = await response.json().catch(() => ({}));
7065
- throw new SdkHttpError(
7066
- errorData.message || `Upload error: ${response.status} ${response.statusText}`,
7067
- response.status,
7068
- errorData
7069
- );
7070
- }
7071
- return response.json();
7072
- } catch (error) {
7073
- clearTimeout(timeoutId);
7074
- if (error instanceof SdkHttpError) throw error;
7075
- const err = error;
7076
- if (err.name === "AbortError") {
7077
- throw new SdkHttpError("Upload timeout", 408);
7078
- }
7079
- throw new SdkHttpError(`Upload error: ${err.message}`, 0, error);
7116
+ /**
7117
+ * Sign challenge with Hedera private key.
7118
+ *
7119
+ * Structurally typed against the surface of `@hashgraph/sdk`'s
7120
+ * `PrivateKey`. We don't `import` the SDK directly — pulling it into
7121
+ * the smart-engine SDK's runtime would bloat browser bundles and bring
7122
+ * peer-dep churn — but any object with a compatible `sign(...)` method
7123
+ * works.
7124
+ *
7125
+ * @param challenge - Challenge string from validator
7126
+ * @param privateKey - Hedera PrivateKey instance (or compatible signer)
7127
+ * @returns Hex-encoded signature
7128
+ */
7129
+ signChallengeHedera(challenge, privateKey) {
7130
+ const messageBytes = new Uint8Array(Buffer.from(challenge, "utf-8"));
7131
+ const signature = privateKey.sign(messageBytes);
7132
+ return Buffer.from(toBytes(signature)).toString("hex");
7133
+ }
7134
+ /**
7135
+ * Sign challenge with XRPL wallet.
7136
+ *
7137
+ * Structurally typed against the surface of xrpl's `Wallet` — see the
7138
+ * comment on {@link HederaSigner} for the "no direct import" rationale.
7139
+ * Accepts both the `{ signedTransaction }` envelope and the bare-string
7140
+ * return shapes that xrpl signer libraries expose.
7141
+ *
7142
+ * @param challenge - Challenge string from validator
7143
+ * @param wallet - XRPL Wallet instance (or compatible signer)
7144
+ * @returns Hex-encoded signature
7145
+ */
7146
+ signChallengeXRPL(challenge, wallet) {
7147
+ const signature = wallet.sign(challenge);
7148
+ if (typeof signature === "string") {
7149
+ if (/^[0-9A-Fa-f]+$/.test(signature)) return signature;
7150
+ return Buffer.from(signature).toString("hex");
7080
7151
  }
7152
+ return signature.signedTransaction;
7081
7153
  }
7082
- const client = {
7083
- post: (path, body) => request("POST", path, body),
7084
- get: (path) => request("GET", path),
7085
- put: (path, body) => request("PUT", path, body),
7086
- patch: (path, body) => request("PATCH", path, body),
7087
- delete: (path) => request("DELETE", path),
7088
- getText,
7089
- upload: ((path, file, filename, metadata, fieldName) => upload(path, file, filename, metadata, fieldName)),
7090
- setAuthToken
7091
- };
7092
- return client;
7093
- }
7094
- function encodePathParam(param) {
7095
- return encodeURIComponent(param).replace(/%2F/gi, "");
7096
- }
7097
- function isRuleRejected(err) {
7098
- if (!(err instanceof SdkHttpError)) return false;
7099
- if (err.statusCode !== 403) return false;
7100
- const d = err.details;
7101
- if (d === null || typeof d !== "object") return false;
7102
- const obj = d;
7103
- if (obj.error !== "rule_rejected") return false;
7104
- if (typeof obj.reason !== "string") return false;
7105
- if (!Array.isArray(obj.ruleAtoms)) return false;
7106
- return obj.ruleAtoms.every((a) => typeof a === "string");
7107
- }
7108
-
7109
- // src/network-presets.ts
7110
- var KNOWN_NETWORKS = {
7111
- testnet: {
7112
- bootstrap: ["https://gateway.testnet.hsuite.network"]
7113
- },
7114
- mainnet: {
7115
- // Mainnet entrypoint reserved. The SDK still resolves the name so
7116
- // upgrade-by-flipping-NETWORK works; the bootstrap URL is the
7117
- // pre-allocated DNS we own. If mainnet isn't deployed yet, the discovery
7118
- // fetch will fail at runtime with the same "no seed reachable" error
7119
- // any unreachable URL produces — the caller learns the network is not
7120
- // live, rather than getting a baffling "unknown network" TypeScript
7121
- // error at compile time.
7122
- bootstrap: ["https://gateway.hsuite.network"]
7154
+ /**
7155
+ * Complete authentication flow in one call
7156
+ *
7157
+ * @param validatorUrl - Validator API base URL
7158
+ * @param chain - Blockchain type
7159
+ * @param address - Wallet address
7160
+ * @param publicKey - Public key (hex)
7161
+ * @param signFn - Function to sign the challenge
7162
+ * @param metadata - Optional metadata
7163
+ * @returns Session token and info
7164
+ */
7165
+ async authenticateWithSigner(validatorUrl, chain, address, publicKey, signFn, metadata) {
7166
+ const challengeResponse = await this.requestChallenge(validatorUrl, chain, address);
7167
+ const signature = await signFn(challengeResponse.challenge);
7168
+ return this.authenticate(validatorUrl, {
7169
+ chain,
7170
+ address,
7171
+ publicKey,
7172
+ signature,
7173
+ challenge: challengeResponse.challenge,
7174
+ metadata
7175
+ });
7123
7176
  }
7124
7177
  };
7125
- function resolveNetwork(name) {
7126
- const preset = KNOWN_NETWORKS[name];
7127
- if (!preset) {
7128
- throw new Error(
7129
- `Unknown network: "${name}". Known networks: ${Object.keys(KNOWN_NETWORKS).join(", ")}`
7130
- );
7178
+ var ValidatorAuthError = class extends Error {
7179
+ constructor(message, statusCode, details) {
7180
+ super(message);
7181
+ this.statusCode = statusCode;
7182
+ this.details = details;
7183
+ this.name = "ValidatorAuthError";
7131
7184
  }
7132
- return preset;
7133
- }
7134
- function isKnownNetwork(name) {
7135
- return Object.prototype.hasOwnProperty.call(KNOWN_NETWORKS, name);
7185
+ statusCode;
7186
+ details;
7187
+ };
7188
+ var { sign: rippleSign } = require_dist2();
7189
+ function createXrplWeb3Signer(seed) {
7190
+ const wallet = xrpl.Wallet.fromSeed(seed);
7191
+ return {
7192
+ chain: "xrpl",
7193
+ address: wallet.classicAddress,
7194
+ publicKey: wallet.publicKey,
7195
+ signFn: (challenge) => {
7196
+ const messageHex = Buffer.from(challenge, "utf-8").toString("hex").toUpperCase();
7197
+ return rippleSign(messageHex, wallet.privateKey);
7198
+ },
7199
+ wallet
7200
+ };
7136
7201
  }
7137
7202
 
7138
7203
  // src/subscription/index.ts
@@ -7156,13 +7221,13 @@ var SubscriptionClient = class {
7156
7221
  * Get subscription status by app ID
7157
7222
  */
7158
7223
  async getStatus(appId) {
7159
- return this.http.get(`/subscription/status/${encodeURIComponent(appId)}`);
7224
+ return this.http.get(`/subscription/status/${encodePathParam(appId)}`);
7160
7225
  }
7161
7226
  /**
7162
7227
  * Mint subscription NFT after deposit is confirmed
7163
7228
  */
7164
7229
  async mintNft(appId) {
7165
- return this.http.post(`/subscription/mint/${encodeURIComponent(appId)}`, {});
7230
+ return this.http.post(`/subscription/mint/${encodePathParam(appId)}`, {});
7166
7231
  }
7167
7232
  /**
7168
7233
  * Renew subscription by extending period
@@ -7231,13 +7296,13 @@ var SubscriptionClient = class {
7231
7296
  * List subscriptions by status
7232
7297
  */
7233
7298
  async listByStatus(status) {
7234
- return this.http.get(`/subscription/list/status/${encodeURIComponent(status)}`);
7299
+ return this.http.get(`/subscription/list/status/${encodePathParam(status)}`);
7235
7300
  }
7236
7301
  /**
7237
7302
  * Get subscription balance
7238
7303
  */
7239
7304
  async getBalance(appId) {
7240
- return this.http.get(`/subscription/balance/${encodeURIComponent(appId)}`);
7305
+ return this.http.get(`/subscription/balance/${encodePathParam(appId)}`);
7241
7306
  }
7242
7307
  // ─── Tier-Change Endpoints ────────────────────────────────────────────────
7243
7308
  /**
@@ -7269,19 +7334,19 @@ var SubscriptionClient = class {
7269
7334
  */
7270
7335
  async getActiveFor(walletAddress) {
7271
7336
  return this.http.get(
7272
- `/subscription/active-for/${encodeURIComponent(walletAddress)}`
7337
+ `/subscription/active-for/${encodePathParam(walletAddress)}`
7273
7338
  );
7274
7339
  }
7275
7340
  /** Today's consumption breakdown by category for an app. Owner-only. */
7276
7341
  async getUsage(appId) {
7277
- return this.http.get(`/subscription/usage/${encodeURIComponent(appId)}`);
7342
+ return this.http.get(`/subscription/usage/${encodePathParam(appId)}`);
7278
7343
  }
7279
7344
  /**
7280
7345
  * Current usage with overage info: usage percent, grace status,
7281
7346
  * upgrade suggestion, projected days until limit. Owner-only.
7282
7347
  */
7283
7348
  async getUsageStatus(appId) {
7284
- return this.http.get(`/subscription/usage/status/${encodeURIComponent(appId)}`);
7349
+ return this.http.get(`/subscription/usage/status/${encodePathParam(appId)}`);
7285
7350
  }
7286
7351
  /**
7287
7352
  * Subscription balance deduction history. Pagination + ISO-8601 range
@@ -7295,7 +7360,7 @@ var SubscriptionClient = class {
7295
7360
  if (options?.to) params.append("to", options.to);
7296
7361
  const qs = params.toString();
7297
7362
  return this.http.get(
7298
- `/subscription/billing/${encodeURIComponent(appId)}${qs ? `?${qs}` : ""}`
7363
+ `/subscription/billing/${encodePathParam(appId)}${qs ? `?${qs}` : ""}`
7299
7364
  );
7300
7365
  }
7301
7366
  /**
@@ -7315,6 +7380,44 @@ var SubscriptionClient = class {
7315
7380
  }
7316
7381
  };
7317
7382
 
7383
+ // src/faucet/index.ts
7384
+ var faucet_exports = {};
7385
+ __export(faucet_exports, {
7386
+ FaucetClient: () => FaucetClient
7387
+ });
7388
+ var FaucetClient = class {
7389
+ constructor(http) {
7390
+ this.http = http;
7391
+ }
7392
+ http;
7393
+ /**
7394
+ * Request a signing challenge for a recipient address. The returned
7395
+ * `message` must be signed by the key controlling `recipientAddress`.
7396
+ */
7397
+ async requestChallenge(chain, recipientAddress) {
7398
+ return this.http.post("/faucet/hsuite/challenge", { chain, recipientAddress });
7399
+ }
7400
+ /**
7401
+ * Submit a signed challenge to dispense HST. The result is a discriminated
7402
+ * union on `status` — branch on `'dispensed' | 'trustline_required' |
7403
+ * 'rate_limited'`. On `'trustline_required'`, set the returned trust line on
7404
+ * the recipient and re-dispense with a fresh challenge.
7405
+ */
7406
+ async dispense(req) {
7407
+ return this.http.post("/faucet/hsuite", req);
7408
+ }
7409
+ /**
7410
+ * Get today's dispense status for a recipient (e.g. amount already
7411
+ * dispensed today).
7412
+ */
7413
+ async getStatus(chain, recipientAddress) {
7414
+ const params = new URLSearchParams();
7415
+ params.append("chain", chain);
7416
+ params.append("recipientAddress", recipientAddress);
7417
+ return this.http.get(`/faucet/hsuite/status?${params.toString()}`);
7418
+ }
7419
+ };
7420
+
7318
7421
  // src/tss/index.ts
7319
7422
  var TSSClient = class {
7320
7423
  constructor(http) {
@@ -7322,80 +7425,105 @@ var TSSClient = class {
7322
7425
  }
7323
7426
  http;
7324
7427
  /**
7325
- * Create a multi-sig entity with TSS
7428
+ * Create a multi-sig entity via a synchronous DKG ceremony.
7429
+ *
7430
+ * @param options Entity-creation parameters (chain, threshold, participants).
7431
+ * @returns The created entity's identity (ids + group public keys).
7326
7432
  */
7327
7433
  async createEntity(options) {
7328
7434
  return this.http.post("/tss/entity/create", options);
7329
7435
  }
7330
7436
  /**
7331
- * Reshare keys when cluster membership changes.
7332
- * Redistributes secret shares WITHOUT changing public keys.
7437
+ * Reshare keys when cluster membership changes. Redistributes secret shares
7438
+ * WITHOUT changing public keys.
7439
+ *
7440
+ * @param request The new membership / threshold to reshare to.
7441
+ * @returns The reshare outcome.
7333
7442
  */
7334
7443
  async reshareCluster(request) {
7335
7444
  return this.http.post("/tss/cluster/reshare", request);
7336
7445
  }
7337
7446
  /**
7338
- * Get entity details by ID
7447
+ * Get entity details by id.
7448
+ *
7449
+ * @param entityId The entity id to look up.
7450
+ * @returns The entity's details.
7339
7451
  */
7340
7452
  async getEntity(entityId) {
7341
- return this.http.get(`/tss/entity/${encodeURIComponent(entityId)}`);
7453
+ return this.http.get(`/tss/entity/${encodePathParam(entityId)}`);
7342
7454
  }
7343
7455
  /**
7344
7456
  * Sign a transaction using MPC.
7345
7457
  *
7346
7458
  * Routes to `POST /api/v3/tss/hedera/sign-mpc`. Only `'hedera'` is wired
7347
- * server-side today (see
7348
- * `apps/smart-validator/src/tss/tss.controller.ts:279`); other chain
7349
- * signing paths run via their own controllers (XRPL multisig, Polkadot
7350
- * MPC) and are not exposed through this sub-client. The `chain` field is
7351
- * carried into the request body so the validator can log + route, but
7352
- * any non-`'hedera'` value will 404.
7459
+ * server-side; other chain signing paths run via their own controllers (XRPL
7460
+ * multisig, Polkadot MPC) and are not exposed through this sub-client. The
7461
+ * `chain` field is carried into the request body so the validator can log +
7462
+ * route, but any non-`'hedera'` value will 404.
7463
+ *
7464
+ * @param request The MPC signing request; `chain` is forced to `'hedera'`.
7465
+ * @returns The MPC signing result.
7353
7466
  */
7354
7467
  async signMPC(request) {
7355
7468
  const chain = "hedera";
7356
7469
  return this.http.post(`/tss/${chain}/sign-mpc`, { ...request, chain });
7357
7470
  }
7358
7471
  /**
7359
- * Get known validators and their public keys
7472
+ * Get known validators and their public keys.
7473
+ *
7474
+ * @returns The validator list with public keys.
7360
7475
  */
7361
7476
  async getValidators() {
7362
7477
  return this.http.get("/tss/validators");
7363
7478
  }
7364
7479
  /**
7365
- * Force announcement of this node's public key
7480
+ * Force announcement of this node's public key.
7481
+ *
7482
+ * @returns Whether the announcement was accepted, plus a status message.
7366
7483
  */
7367
7484
  async announceKey() {
7368
7485
  return this.http.post("/tss/announce", {});
7369
7486
  }
7370
7487
  /**
7371
- * Get TSS statistics
7488
+ * Get TSS statistics.
7489
+ *
7490
+ * @returns Aggregate TSS statistics.
7372
7491
  */
7373
7492
  async getStats() {
7374
7493
  return this.http.get("/tss/stats");
7375
7494
  }
7376
7495
  /**
7377
- * List all TSS entities
7496
+ * List all TSS entities.
7497
+ *
7498
+ * @returns The full entity list.
7378
7499
  */
7379
7500
  async listEntities() {
7380
7501
  return this.http.get("/tss/entities");
7381
7502
  }
7382
7503
  /**
7383
- * TSS health check
7504
+ * TSS health check.
7505
+ *
7506
+ * @returns The TSS subsystem health report.
7384
7507
  */
7385
7508
  async getHealth() {
7386
7509
  return this.http.get("/tss/health");
7387
7510
  }
7388
7511
  /**
7389
- * List DKG ceremonies and their statistics
7512
+ * List DKG ceremonies and their statistics.
7513
+ *
7514
+ * @returns The ceremony list.
7390
7515
  */
7391
7516
  async listCeremonies() {
7392
7517
  return this.http.get("/tss/multisig/ceremonies");
7393
7518
  }
7394
7519
  /**
7395
- * Get multi-sig transaction status by transaction ID
7520
+ * Get multi-sig transaction status by transaction id.
7521
+ *
7522
+ * @param txId The multi-sig transaction id.
7523
+ * @returns The current status of that transaction.
7396
7524
  */
7397
7525
  async getMultiSigStatus(txId) {
7398
- return this.http.get(`/tss/multisig/transactions/${encodeURIComponent(txId)}`);
7526
+ return this.http.get(`/tss/multisig/transactions/${encodePathParam(txId)}`);
7399
7527
  }
7400
7528
  /**
7401
7529
  * Async-job variant of {@link createEntity}.
@@ -7403,6 +7531,9 @@ var TSSClient = class {
7403
7531
  * Server returns 202 + `{ jobId, statusUrl, status: 'pending' }` immediately;
7404
7532
  * the DKG ceremony runs in the background. Poll {@link getJob} until the
7405
7533
  * status reaches `'success'` or `'failed'`.
7534
+ *
7535
+ * @param options Entity-creation parameters.
7536
+ * @returns A job descriptor (`jobId`, `statusUrl`, initial status).
7406
7537
  */
7407
7538
  async createEntityAsync(options) {
7408
7539
  return this.http.post("/tss/entity/create/async", options);
@@ -7410,6 +7541,9 @@ var TSSClient = class {
7410
7541
  /**
7411
7542
  * Async-job variant of {@link reshareCluster}. Returns 202 + a polling
7412
7543
  * descriptor; resharing runs in the background.
7544
+ *
7545
+ * @param request The new membership / threshold to reshare to.
7546
+ * @returns A job descriptor to poll via {@link getJob}.
7413
7547
  */
7414
7548
  async reshareClusterAsync(request) {
7415
7549
  return this.http.post("/tss/cluster/reshare/async", request);
@@ -7417,9 +7551,12 @@ var TSSClient = class {
7417
7551
  /**
7418
7552
  * Poll the status of an async TSS-ceremony job kicked off via
7419
7553
  * {@link createEntityAsync} or {@link reshareClusterAsync}.
7554
+ *
7555
+ * @param jobId The job id returned by the async kickoff call.
7556
+ * @returns The job's current status (and result once terminal).
7420
7557
  */
7421
7558
  async getJob(jobId) {
7422
- return this.http.get(`/tss/jobs/${encodeURIComponent(jobId)}`);
7559
+ return this.http.get(`/tss/jobs/${encodePathParam(jobId)}`);
7423
7560
  }
7424
7561
  /**
7425
7562
  * Sign a hex payload as smart-app entity `appId` via the cluster's TSS
@@ -7429,9 +7566,13 @@ var TSSClient = class {
7429
7566
  * Payload constraints (enforced server-side):
7430
7567
  * - even-length lowercase hex
7431
7568
  * - ≥32 bytes, ≤8KB
7569
+ *
7570
+ * @param appId The smart-app entity id to sign as.
7571
+ * @param request The hex payload to sign.
7572
+ * @returns The aggregate signature over the payload.
7432
7573
  */
7433
7574
  async signForApp(appId, request) {
7434
- return this.http.post(`/tss/entity/${encodeURIComponent(appId)}/sign`, request);
7575
+ return this.http.post(`/tss/entity/${encodePathParam(appId)}/sign`, request);
7435
7576
  }
7436
7577
  };
7437
7578
 
@@ -7456,31 +7597,31 @@ var IPFSClient = class {
7456
7597
  * Pin content by CID to ensure it persists
7457
7598
  */
7458
7599
  async pin(cid) {
7459
- return this.http.post(`/ipfs/pin/${encodeURIComponent(cid)}`, {});
7600
+ return this.http.post(`/ipfs/pin/${encodePathParam(cid)}`, {});
7460
7601
  }
7461
7602
  /**
7462
7603
  * Unpin content by CID
7463
7604
  */
7464
7605
  async unpin(cid) {
7465
- return this.http.delete(`/ipfs/unpin/${encodeURIComponent(cid)}`);
7606
+ return this.http.delete(`/ipfs/unpin/${encodePathParam(cid)}`);
7466
7607
  }
7467
7608
  /**
7468
7609
  * Get a file by CID
7469
7610
  */
7470
7611
  async getFile(cid) {
7471
- return this.http.get(`/ipfs/file/${encodeURIComponent(cid)}`);
7612
+ return this.http.get(`/ipfs/file/${encodePathParam(cid)}`);
7472
7613
  }
7473
7614
  /**
7474
7615
  * Get raw content by CID
7475
7616
  */
7476
7617
  async getContent(cid) {
7477
- return this.http.get(`/ipfs/${encodeURIComponent(cid)}`);
7618
+ return this.http.get(`/ipfs/${encodePathParam(cid)}`);
7478
7619
  }
7479
7620
  /**
7480
7621
  * Get file metadata by CID
7481
7622
  */
7482
7623
  async getMetadata(cid) {
7483
- return this.http.get(`/ipfs/metadata/${encodeURIComponent(cid)}`);
7624
+ return this.http.get(`/ipfs/metadata/${encodePathParam(cid)}`);
7484
7625
  }
7485
7626
  /**
7486
7627
  * List all pinned content
@@ -7538,7 +7679,7 @@ var HederaTssClient = class {
7538
7679
  var HederaTransactionsClient = class {
7539
7680
  constructor(http, tssHttp) {
7540
7681
  this.http = http;
7541
- this.tss = new HederaTssClient(tssHttp ?? http);
7682
+ this.tss = new HederaTssClient(tssHttp);
7542
7683
  }
7543
7684
  http;
7544
7685
  /**
@@ -7549,10 +7690,10 @@ var HederaTransactionsClient = class {
7549
7690
  * - `client.hedera.tss.createTopic(...)` makes the cluster sign+submit in one call.
7550
7691
  *
7551
7692
  * `tssHttp` is the validator's `/api/v3`-rooted HTTP client (different from
7552
- * the `/api/transactions` one this class uses for prepare paths). When the
7553
- * legacy single-arg constructor is used (no tssHttp passed), `tss` falls
7554
- * back to the same `http` instance for backwards compatibility — callers
7555
- * outside `SmartEngineClient` rarely use the TSS surface.
7693
+ * the `/api/transactions` one this class uses for prepare paths). Both
7694
+ * clients are required the previous single-arg fallback to `http` was
7695
+ * unreachable through `SmartEngineClient` (the only call site always
7696
+ * passes both).
7556
7697
  */
7557
7698
  tss;
7558
7699
  /** Prepare an HCS topic creation transaction. */
@@ -7733,7 +7874,7 @@ var SnapshotsClient = class {
7733
7874
  */
7734
7875
  async generate(tokenId, options) {
7735
7876
  return this.http.post(
7736
- `/snapshots/generate/${encodeURIComponent(tokenId)}`,
7877
+ `/snapshots/generate/${encodePathParam(tokenId)}`,
7737
7878
  options || {}
7738
7879
  );
7739
7880
  }
@@ -7741,7 +7882,7 @@ var SnapshotsClient = class {
7741
7882
  * Get snapshot details by ID
7742
7883
  */
7743
7884
  async get(snapshotId) {
7744
- return this.http.get(`/snapshots/${encodeURIComponent(snapshotId)}`);
7885
+ return this.http.get(`/snapshots/${encodePathParam(snapshotId)}`);
7745
7886
  }
7746
7887
  /**
7747
7888
  * List snapshots for a token
@@ -7752,7 +7893,7 @@ var SnapshotsClient = class {
7752
7893
  if (pagination?.limit !== void 0) params.set("limit", String(pagination.limit));
7753
7894
  const qs = params.toString();
7754
7895
  return this.http.get(
7755
- `/snapshots/token/${encodeURIComponent(tokenId)}${qs ? `?${qs}` : ""}`
7896
+ `/snapshots/token/${encodePathParam(tokenId)}${qs ? `?${qs}` : ""}`
7756
7897
  );
7757
7898
  }
7758
7899
  /**
@@ -7764,7 +7905,7 @@ var SnapshotsClient = class {
7764
7905
  async download(snapshotId, format) {
7765
7906
  const params = format ? `?format=${encodeURIComponent(format)}` : "";
7766
7907
  return this.http.get(
7767
- `/snapshots/${encodeURIComponent(snapshotId)}/download${params}`
7908
+ `/snapshots/${encodePathParam(snapshotId)}/download${params}`
7768
7909
  );
7769
7910
  }
7770
7911
  };
@@ -7951,20 +8092,20 @@ var SettlementClient = class {
7951
8092
  * Get the current status of a settlement by ID.
7952
8093
  */
7953
8094
  async getStatus(settlementId) {
7954
- return this.http.get(`/settlement/${encodeURIComponent(settlementId)}/status`);
8095
+ return this.http.get(`/settlement/${encodePathParam(settlementId)}/status`);
7955
8096
  }
7956
8097
  /**
7957
8098
  * Confirm that XRP has landed on the destination address.
7958
8099
  * Advances the settlement to the next processing step.
7959
8100
  */
7960
8101
  async confirmXrpLanded(settlementId) {
7961
- return this.http.post(`/settlement/${encodeURIComponent(settlementId)}/confirm-xrp`, {});
8102
+ return this.http.post(`/settlement/${encodePathParam(settlementId)}/confirm-xrp`, {});
7962
8103
  }
7963
8104
  /**
7964
8105
  * Get settlement history for a given entity.
7965
8106
  */
7966
8107
  async getHistory(entityId) {
7967
- return this.http.get(`/settlement/history/${encodeURIComponent(entityId)}`);
8108
+ return this.http.get(`/settlement/history/${encodePathParam(entityId)}`);
7968
8109
  }
7969
8110
  };
7970
8111
 
@@ -8020,39 +8161,39 @@ var DaoDashboardClient = class {
8020
8161
  /** Aggregated dashboard counters for a user's governance home screen. */
8021
8162
  async getStats(userAddress) {
8022
8163
  return this.http.get(
8023
- `/dao/dashboard/stats/${encodeURIComponent(userAddress)}`
8164
+ `/dao/dashboard/stats/${encodePathParam(userAddress)}`
8024
8165
  );
8025
8166
  }
8026
8167
  /** Active proposals across every DAO the user belongs to, with vote state. */
8027
8168
  async getActiveProposals(userAddress) {
8028
8169
  return this.http.get(
8029
- `/dao/dashboard/active-proposals/${encodeURIComponent(userAddress)}`
8170
+ `/dao/dashboard/active-proposals/${encodePathParam(userAddress)}`
8030
8171
  );
8031
8172
  }
8032
8173
  /** Paginated vote history across DAOs. */
8033
8174
  async getVoteHistory(userAddress, opts = {}) {
8034
8175
  const qs = buildQuery({ limit: opts.limit, offset: opts.offset });
8035
8176
  return this.http.get(
8036
- `/dao/dashboard/vote-history/${encodeURIComponent(userAddress)}${qs}`
8177
+ `/dao/dashboard/vote-history/${encodePathParam(userAddress)}${qs}`
8037
8178
  );
8038
8179
  }
8039
8180
  /** Activity feed (proposal-created/vote-cast/etc.) across user's DAOs. */
8040
8181
  async getActivity(userAddress, opts = {}) {
8041
8182
  const qs = buildQuery({ limit: opts.limit, daoId: opts.daoId });
8042
8183
  return this.http.get(
8043
- `/dao/dashboard/activity/${encodeURIComponent(userAddress)}${qs}`
8184
+ `/dao/dashboard/activity/${encodePathParam(userAddress)}${qs}`
8044
8185
  );
8045
8186
  }
8046
8187
  /** Items the user must act on (sign prepared messages, claim NFTs, …). */
8047
8188
  async getPendingActions(userAddress) {
8048
8189
  return this.http.get(
8049
- `/dao/dashboard/pending-actions/${encodeURIComponent(userAddress)}`
8190
+ `/dao/dashboard/pending-actions/${encodePathParam(userAddress)}`
8050
8191
  );
8051
8192
  }
8052
8193
  /** Governance impact metrics — weight delivered, success rate, streak. */
8053
8194
  async getImpact(userAddress) {
8054
8195
  return this.http.get(
8055
- `/dao/dashboard/impact/${encodeURIComponent(userAddress)}`
8196
+ `/dao/dashboard/impact/${encodePathParam(userAddress)}`
8056
8197
  );
8057
8198
  }
8058
8199
  };
@@ -8068,13 +8209,13 @@ function buildQuery2(params) {
8068
8209
  return qs ? `?${qs}` : "";
8069
8210
  }
8070
8211
  function encodeDaoId(daoId) {
8071
- return encodeURIComponent(daoId);
8212
+ return encodePathParam(daoId);
8072
8213
  }
8073
8214
  function encodeProposalId(proposalId) {
8074
- return encodeURIComponent(proposalId);
8215
+ return encodePathParam(proposalId);
8075
8216
  }
8076
8217
  function encodeAddress(address) {
8077
- return encodeURIComponent(address);
8218
+ return encodePathParam(address);
8078
8219
  }
8079
8220
  var DaoClient = class {
8080
8221
  constructor(http) {
@@ -8355,7 +8496,7 @@ var AgentsClient = class {
8355
8496
  }
8356
8497
  /** Get agent details */
8357
8498
  async get(agentId) {
8358
- return this.http.get(`/api/agents/${encodeURIComponent(agentId)}`);
8499
+ return this.http.get(`/api/agents/${encodePathParam(agentId)}`);
8359
8500
  }
8360
8501
  /** List all agents */
8361
8502
  async list() {
@@ -8367,33 +8508,33 @@ var AgentsClient = class {
8367
8508
  * the caller is expected to sign and submit the prepared bytes.
8368
8509
  */
8369
8510
  async fund(agentId, request) {
8370
- return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/fund`, request);
8511
+ return this.http.post(`/api/agents/${encodePathParam(agentId)}/fund`, request);
8371
8512
  }
8372
8513
  /**
8373
8514
  * Execute a trade (agent-wallet OR owner). Returns a
8374
8515
  * `PreparedTransactionResponse` wrapped in a `success: true` envelope.
8375
8516
  */
8376
8517
  async trade(agentId, request) {
8377
- return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/trade`, request);
8518
+ return this.http.post(`/api/agents/${encodePathParam(agentId)}/trade`, request);
8378
8519
  }
8379
8520
  /**
8380
8521
  * Withdraw from agent treasury (owner-only). Returns a
8381
8522
  * `PreparedTransactionResponse` wrapped in a `success: true` envelope.
8382
8523
  */
8383
8524
  async withdraw(agentId, request) {
8384
- return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/withdraw`, request);
8525
+ return this.http.post(`/api/agents/${encodePathParam(agentId)}/withdraw`, request);
8385
8526
  }
8386
8527
  /** Pause an agent */
8387
8528
  async pause(agentId) {
8388
- return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/pause`, {});
8529
+ return this.http.post(`/api/agents/${encodePathParam(agentId)}/pause`, {});
8389
8530
  }
8390
8531
  /** Resume a paused agent */
8391
8532
  async resume(agentId) {
8392
- return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/resume`, {});
8533
+ return this.http.post(`/api/agents/${encodePathParam(agentId)}/resume`, {});
8393
8534
  }
8394
8535
  /** Revoke an agent (permanent) */
8395
8536
  async revoke(agentId) {
8396
- return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/revoke`, {});
8537
+ return this.http.post(`/api/agents/${encodePathParam(agentId)}/revoke`, {});
8397
8538
  }
8398
8539
  /**
8399
8540
  * Update agent rules.
@@ -8404,23 +8545,23 @@ var AgentsClient = class {
8404
8545
  * the verb mismatch.
8405
8546
  */
8406
8547
  async updateRules(agentId, rules) {
8407
- return this.http.patch(`/api/agents/${encodeURIComponent(agentId)}/rules`, rules);
8548
+ return this.http.patch(`/api/agents/${encodePathParam(agentId)}/rules`, rules);
8408
8549
  }
8409
8550
  /** Get agent events */
8410
8551
  async getEvents(agentId) {
8411
- return this.http.get(`/api/agents/${encodeURIComponent(agentId)}/events`);
8552
+ return this.http.get(`/api/agents/${encodePathParam(agentId)}/events`);
8412
8553
  }
8413
8554
  /** Get agent balances across chains */
8414
8555
  async getBalances(agentId) {
8415
- return this.http.get(`/api/agents/${encodeURIComponent(agentId)}/balances`);
8556
+ return this.http.get(`/api/agents/${encodePathParam(agentId)}/balances`);
8416
8557
  }
8417
8558
  /** Approve a pending agent operation */
8418
8559
  async approve(agentId, operationId) {
8419
- return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/approve/${encodeURIComponent(operationId)}`, {});
8560
+ return this.http.post(`/api/agents/${encodePathParam(agentId)}/approve/${encodePathParam(operationId)}`, {});
8420
8561
  }
8421
8562
  /** Reject a pending agent operation */
8422
8563
  async reject(agentId, operationId) {
8423
- return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/reject/${encodeURIComponent(operationId)}`, {});
8564
+ return this.http.post(`/api/agents/${encodePathParam(agentId)}/reject/${encodePathParam(operationId)}`, {});
8424
8565
  }
8425
8566
  };
8426
8567
 
@@ -8459,7 +8600,7 @@ var DeploymentClient = class {
8459
8600
  */
8460
8601
  async uploadFrontend(appId, bundle, filename = "bundle.tar.gz") {
8461
8602
  return this.http.upload(
8462
- `/api/deployment/apps/${encodeURIComponent(appId)}/frontend`,
8603
+ `/api/deployment/apps/${encodePathParam(appId)}/frontend`,
8463
8604
  bundle,
8464
8605
  filename,
8465
8606
  void 0,
@@ -8473,20 +8614,20 @@ var DeploymentClient = class {
8473
8614
  * until `runtime.runtimeState === 'RUNNING'` for the URL to be live.
8474
8615
  */
8475
8616
  async deploy(appId, request) {
8476
- return this.http.post(`/api/deployment/apps/${encodeURIComponent(appId)}/deploy`, request);
8617
+ return this.http.post(`/api/deployment/apps/${encodePathParam(appId)}/deploy`, request);
8477
8618
  }
8478
8619
  /**
8479
8620
  * Roll back to a previously-deployed image tag (must exist in
8480
8621
  * `runtime.deploymentHistory[]`).
8481
8622
  */
8482
8623
  async rollback(appId, request) {
8483
- return this.http.post(`/api/deployment/apps/${encodeURIComponent(appId)}/rollback`, request);
8624
+ return this.http.post(`/api/deployment/apps/${encodePathParam(appId)}/rollback`, request);
8484
8625
  }
8485
8626
  /**
8486
8627
  * Live combined lifecycle + runtime status of an app.
8487
8628
  */
8488
8629
  async status(appId) {
8489
- return this.http.get(`/api/deployment/apps/${encodeURIComponent(appId)}/status`);
8630
+ return this.http.get(`/api/deployment/apps/${encodePathParam(appId)}/status`);
8490
8631
  }
8491
8632
  /**
8492
8633
  * List all deployed apps for the authenticated developer.
@@ -8498,31 +8639,35 @@ var DeploymentClient = class {
8498
8639
  * Get app details.
8499
8640
  */
8500
8641
  async get(appId) {
8501
- return this.http.get(`/api/deployment/apps/${encodeURIComponent(appId)}`);
8642
+ return this.http.get(`/api/deployment/apps/${encodePathParam(appId)}`);
8502
8643
  }
8503
8644
  /**
8504
- * Update app configuration. Runtime effect lands in PR-H.
8645
+ * Update app configuration.
8646
+ *
8647
+ * @param appId - The app to update.
8648
+ * @param updates - Partial deploy-request fields to apply.
8649
+ * @returns The updated app info.
8505
8650
  */
8506
8651
  async update(appId, updates) {
8507
- return this.http.put(`/api/deployment/apps/${encodeURIComponent(appId)}`, updates);
8652
+ return this.http.put(`/api/deployment/apps/${encodePathParam(appId)}`, updates);
8508
8653
  }
8509
8654
  /**
8510
- * Delete an app. Runtime effect (namespace teardown) lands in PR-H.
8655
+ * Delete an app (runtime effect: namespace teardown).
8511
8656
  */
8512
8657
  async delete(appId) {
8513
- return this.http.delete(`/api/deployment/apps/${encodeURIComponent(appId)}`);
8658
+ return this.http.delete(`/api/deployment/apps/${encodePathParam(appId)}`);
8514
8659
  }
8515
8660
  /**
8516
- * Suspend an app. Runtime effect (scale to zero) lands in PR-H.
8661
+ * Suspend an app (runtime effect: scale to zero).
8517
8662
  */
8518
8663
  async suspend(appId) {
8519
- return this.http.post(`/api/deployment/apps/${encodeURIComponent(appId)}/suspend`, {});
8664
+ return this.http.post(`/api/deployment/apps/${encodePathParam(appId)}/suspend`, {});
8520
8665
  }
8521
8666
  /**
8522
- * Resume a suspended app. Runtime effect (scale back up) lands in PR-H.
8667
+ * Resume a suspended app (runtime effect: scale back up).
8523
8668
  */
8524
8669
  async resume(appId) {
8525
- return this.http.post(`/api/deployment/apps/${encodeURIComponent(appId)}/resume`, {});
8670
+ return this.http.post(`/api/deployment/apps/${encodePathParam(appId)}/resume`, {});
8526
8671
  }
8527
8672
  /**
8528
8673
  * Get deployment statistics.
@@ -8549,7 +8694,7 @@ var DeploymentClient = class {
8549
8694
  * CGNAT / cloud metadata destinations (SSRF guard).
8550
8695
  */
8551
8696
  async setWebhook(appId, webhookUrl) {
8552
- return this.http.put(`/api/deployment/apps/${encodeURIComponent(appId)}/webhook`, {
8697
+ return this.http.put(`/api/deployment/apps/${encodePathParam(appId)}/webhook`, {
8553
8698
  webhookUrl
8554
8699
  });
8555
8700
  }
@@ -8565,10 +8710,10 @@ var DeploymentClient = class {
8565
8710
  * exposition format.
8566
8711
  */
8567
8712
  async getMetrics(appId) {
8568
- return this.http.getText(`/api/deployment/apps/${encodeURIComponent(appId)}/metrics`);
8713
+ return this.http.getText(`/api/deployment/apps/${encodePathParam(appId)}/metrics`);
8569
8714
  }
8570
8715
  /**
8571
- * Rotate the smart-app's tenant-secret KEK (ADR-011 Phase 6).
8716
+ * Rotate the smart-app's tenant-secret KEK.
8572
8717
  *
8573
8718
  * Re-encrypts every `runtime.env` envelope at the new KEK version
8574
8719
  * transparently. Previous versions remain valid until explicitly
@@ -8576,12 +8721,12 @@ var DeploymentClient = class {
8576
8721
  */
8577
8722
  async rotateKek(appId) {
8578
8723
  return this.http.post(
8579
- `/api/deployment/apps/${encodeURIComponent(appId)}/credentials/rotate-kek`,
8724
+ `/api/deployment/apps/${encodePathParam(appId)}/credentials/rotate-kek`,
8580
8725
  {}
8581
8726
  );
8582
8727
  }
8583
8728
  /**
8584
- * Revoke a tenant-secret KEK version (ADR-011 Phase 6 emergency burn).
8729
+ * Revoke a tenant-secret KEK version (emergency burn).
8585
8730
  *
8586
8731
  * Envelopes at the revoked version become operationally dead —
8587
8732
  * decryption inside the smart-app pod fails. Owner-only and
@@ -8590,7 +8735,7 @@ var DeploymentClient = class {
8590
8735
  */
8591
8736
  async revokeKek(appId, version) {
8592
8737
  return this.http.post(
8593
- `/api/deployment/apps/${encodeURIComponent(appId)}/credentials/revoke-kek`,
8738
+ `/api/deployment/apps/${encodePathParam(appId)}/credentials/revoke-kek`,
8594
8739
  { version }
8595
8740
  );
8596
8741
  }
@@ -8794,16 +8939,6 @@ var TokensClient = class {
8794
8939
  async getMigrationsForToken(tokenId) {
8795
8940
  return this.http.get(`/tokens/${encodePathParam(tokenId)}/migrations`);
8796
8941
  }
8797
- /**
8798
- * Get token details. NOTE: collides with `client.getTokenInfo(...)` —
8799
- * see the class JSDoc above for the route-order details. Prefer
8800
- * `client.getTokenInfo(...)` unless you have a reason to call this one.
8801
- */
8802
- async getDetails(chain, tokenId) {
8803
- return this.http.get(
8804
- `/tokens/${encodePathParam(chain)}/${encodePathParam(tokenId)}`
8805
- );
8806
- }
8807
8942
  };
8808
8943
 
8809
8944
  // src/operator/index.ts
@@ -8844,6 +8979,8 @@ var SmartEngineClient = class _SmartEngineClient {
8844
8979
  // ========== Sub-Clients ==========
8845
8980
  /** Application subscription management */
8846
8981
  subscription;
8982
+ /** Testnet HST faucet (challenge -> sign -> dispense) */
8983
+ faucet;
8847
8984
  /** Threshold Signature Scheme — chain-agnostic MPC operations */
8848
8985
  tss;
8849
8986
  /** IPFS decentralized file storage */
@@ -8902,6 +9039,7 @@ var SmartEngineClient = class _SmartEngineClient {
8902
9039
  timeout: config.timeout
8903
9040
  });
8904
9041
  this.subscription = new SubscriptionClient(this.http);
9042
+ this.faucet = new FaucetClient(this.http);
8905
9043
  this.tss = new TSSClient(this.http);
8906
9044
  this.ipfs = new IPFSClient(this.http);
8907
9045
  this.transactions = new TransactionsClient(this.txHttp);
@@ -8957,13 +9095,17 @@ var SmartEngineClient = class _SmartEngineClient {
8957
9095
  });
8958
9096
  }
8959
9097
  /**
8960
- * Connect to the smart-engines network with auto-discovery and authentication
9098
+ * Connect to the smart-engines network with auto-discovery and authentication.
8961
9099
  *
8962
- * This method:
8963
- * 1. Discovers validators via HCS registry topic
8964
- * 2. Selects a random validator with API endpoint
8965
- * 3. Authenticates with Web3-style challenge-response
8966
- * 4. Returns a configured client ready to use
9100
+ * Steps:
9101
+ * 1. Discovers validators via the HCS registry topic.
9102
+ * 2. Selects a random validator with an API endpoint.
9103
+ * 3. Authenticates with Web3-style challenge-response.
9104
+ * 4. Returns a configured client ready to use.
9105
+ *
9106
+ * @param config - Network, registry topic, and auth signer config.
9107
+ * @returns The configured client, the chosen validator, and the auth session.
9108
+ * @throws SmartEngineError 503 if no validator with an API endpoint is found.
8967
9109
  */
8968
9110
  static async connectToNetwork(config) {
8969
9111
  const allowInsecure = config.allowInsecure ?? false;
@@ -9000,18 +9142,22 @@ var SmartEngineClient = class _SmartEngineClient {
9000
9142
  return { client, validator, session };
9001
9143
  }
9002
9144
  /**
9003
- * Connect to the smart-engines network via the **service-registry**
9004
- * (PR-1 of the cluster-discovery arc). Preferred over
9005
- * {@link connectToNetwork} once the validator pods in the target network
9006
- * have published their cluster endpoints the SDK auto-balances across
9007
- * the active cluster set and rides permissionless cluster join/leave
9008
- * without code edits.
9145
+ * Connect to the smart-engines network via the **service-registry**.
9146
+ * Preferred over {@link connectToNetwork} once the validator pods in the
9147
+ * target network have published their cluster endpoints the SDK
9148
+ * auto-balances across the active cluster set and rides permissionless
9149
+ * cluster join/leave without code edits.
9009
9150
  *
9010
- * Fallback ladder (per `docs/ops/HANDOFF-service-registry-distribution-layer.md` §6):
9151
+ * Resolution ladder:
9011
9152
  * 1. HTTP fetch `/api/v3/discovery/clusters` from each bootstrap seed.
9012
9153
  * 2. (Optional) HCS trust-anchor membership cross-check.
9013
9154
  * 3. Random-pick over the verified set.
9014
9155
  *
9156
+ * @param config - Seed + auth config. See {@link ClusterConnectionConfig}.
9157
+ * @returns The configured client, the selected cluster, and the auth session.
9158
+ * @throws SmartEngineError 400 if neither `bootstrap` nor `network` is given.
9159
+ * @throws SmartEngineError 503 if no active cluster can be reached.
9160
+ *
9015
9161
  * @example Zero-config (recommended for smart-app callers)
9016
9162
  * ```ts
9017
9163
  * const { client, cluster, session } = await SmartEngineClient.connectToCluster({
@@ -9036,30 +9182,25 @@ var SmartEngineClient = class _SmartEngineClient {
9036
9182
  */
9037
9183
  static async connectToCluster(config) {
9038
9184
  const allowInsecure = config.allowInsecure ?? false;
9039
- const bootstrap = config.bootstrap ? [...config.bootstrap] : [...resolveNetwork(config.network).bootstrap];
9040
- if (bootstrap.length === 0) {
9041
- throw new SmartEngineError2(
9042
- "connectToCluster requires either a non-empty `bootstrap` list or a known `network` name.",
9043
- 400
9044
- );
9045
- }
9046
- const discovery = new ClusterDiscoveryClient({
9047
- bootstrap,
9185
+ const resolved = await resolveClusterEndpoint({
9186
+ bootstrap: config.bootstrap,
9187
+ network: config.network,
9048
9188
  allowInsecure,
9049
- trustAnchor: config.trustAnchor ? {
9050
- network: config.trustAnchor.network,
9051
- registryTopicId: config.trustAnchor.registryTopicId,
9052
- mirrorNodeUrl: config.trustAnchor.mirrorNodeUrl,
9053
- allowInsecure
9054
- } : void 0
9189
+ trustAnchor: config.trustAnchor
9055
9190
  });
9056
- const cluster = await discovery.getRandomCluster();
9057
- if (!cluster) {
9191
+ if (!resolved.ok) {
9192
+ if (resolved.reason === "no-seeds") {
9193
+ throw new SmartEngineError2(
9194
+ "connectToCluster requires either a non-empty `bootstrap` list or a known `network` name.",
9195
+ 400
9196
+ );
9197
+ }
9058
9198
  throw new SmartEngineError2(
9059
9199
  "No active clusters available via bootstrap seeds. Check bootstrap URLs and network reachability.",
9060
9200
  503
9061
9201
  );
9062
9202
  }
9203
+ const cluster = resolved.cluster;
9063
9204
  const gatewayUrl = cluster.endpoints.gatewayUrl;
9064
9205
  validateClientUrl(gatewayUrl, allowInsecure);
9065
9206
  const auth = new ValidatorAuthClient({ security: { allowInsecure } });
@@ -9084,7 +9225,7 @@ var SmartEngineClient = class _SmartEngineClient {
9084
9225
  }
9085
9226
  /** Check if client has an auth token */
9086
9227
  isAuthenticated() {
9087
- return !!this.http.authToken;
9228
+ return this.http.getAuthToken() !== void 0;
9088
9229
  }
9089
9230
  /**
9090
9231
  * Get HTTP resilience health information
@@ -9145,17 +9286,11 @@ var SmartEngineClient = class _SmartEngineClient {
9145
9286
  return this.http.post("/tokens/mint", validated);
9146
9287
  }
9147
9288
  /**
9148
- * Get token information.
9289
+ * Get token information for a token on the given chain.
9149
9290
  *
9150
- * Route `GET /api/v3/tokens/:chain/:tokenId` is registered twice on the
9151
- * validator: by `ValidatorController` at
9152
- * `apps/smart-validator/src/validator.controller.ts:497` and by
9153
- * `TokenMigrationController` at
9154
- * `apps/smart-validator/src/token-migration/token-migration.controller.ts:173`.
9155
- * Nest resolves routes in `controllers: [...]` order — `ValidatorController`
9156
- * is registered first (`apps/smart-validator/src/smart-validator.module.ts:1222`),
9157
- * so `multiChain.getTokenInfo(chain, tokenId)` wins and the
9158
- * token-migration handler is unreachable via this path.
9291
+ * @param chain - Chain identifier (e.g. `'hedera'`, `'xrpl'`).
9292
+ * @param tokenId - Chain-native token identifier.
9293
+ * @returns Token metadata and supply information.
9159
9294
  */
9160
9295
  async getTokenInfo(chain, tokenId) {
9161
9296
  return this.http.get(`/tokens/${encodePathParam(chain)}/${encodePathParam(tokenId)}`);
@@ -9315,7 +9450,7 @@ var RoutingClient = class {
9315
9450
  }
9316
9451
  /** Unregister a host. */
9317
9452
  async unregisterHost(hostId) {
9318
- return this.http.delete(`/routing/hosts/${encodeURIComponent(hostId)}`);
9453
+ return this.http.delete(`/routing/hosts/${encodePathParam(hostId)}`);
9319
9454
  }
9320
9455
  /** Get all registered hosts. */
9321
9456
  async getAllHosts() {
@@ -9327,19 +9462,19 @@ var RoutingClient = class {
9327
9462
  }
9328
9463
  /** Get a specific host by ID. */
9329
9464
  async getHost(hostId) {
9330
- return this.http.get(`/routing/hosts/${encodeURIComponent(hostId)}`);
9465
+ return this.http.get(`/routing/hosts/${encodePathParam(hostId)}`);
9331
9466
  }
9332
9467
  /** Trigger host re-verification. */
9333
9468
  async verifyHost(hostId) {
9334
- return this.http.post(`/routing/hosts/${encodeURIComponent(hostId)}/verify`, {});
9469
+ return this.http.post(`/routing/hosts/${encodePathParam(hostId)}/verify`, {});
9335
9470
  }
9336
9471
  /** Set routing configuration for an app. */
9337
9472
  async setRoutingConfig(appId, config) {
9338
- return this.http.put(`/routing/config/${encodeURIComponent(appId)}`, config);
9473
+ return this.http.put(`/routing/config/${encodePathParam(appId)}`, config);
9339
9474
  }
9340
9475
  /** Get routing configuration for an app. */
9341
9476
  async getRoutingConfig(appId) {
9342
- return this.http.get(`/routing/config/${encodeURIComponent(appId)}`);
9477
+ return this.http.get(`/routing/config/${encodePathParam(appId)}`);
9343
9478
  }
9344
9479
  /** Proxy a request through the gateway. */
9345
9480
  async proxyRequest(request) {
@@ -9355,7 +9490,7 @@ var RoutingClient = class {
9355
9490
  * field; treat `appId` as the success signal.
9356
9491
  */
9357
9492
  async mapDomainToApp(domain, appId) {
9358
- return this.http.post(`/routing/domains/${encodeURIComponent(domain)}/map`, { appId });
9493
+ return this.http.post(`/routing/domains/${encodePathParam(domain)}/map`, { appId });
9359
9494
  }
9360
9495
  };
9361
9496
 
@@ -9371,11 +9506,11 @@ var DomainsClient = class {
9371
9506
  }
9372
9507
  /** Check domain availability */
9373
9508
  async checkAvailability(domain) {
9374
- return this.http.get(`/domains/check/${encodeURIComponent(domain)}`);
9509
+ return this.http.get(`/domains/check/${encodePathParam(domain)}`);
9375
9510
  }
9376
9511
  /** Get domain information */
9377
9512
  async getInfo(domain) {
9378
- return this.http.get(`/domains/${encodeURIComponent(domain)}`);
9513
+ return this.http.get(`/domains/${encodePathParam(domain)}`);
9379
9514
  }
9380
9515
  /** List domains, optionally filtered by owner */
9381
9516
  async list(owner) {
@@ -9384,51 +9519,50 @@ var DomainsClient = class {
9384
9519
  }
9385
9520
  /**
9386
9521
  * Generate a verification token. Server accepts one of `dns-txt`,
9387
- * `dns-cname`, `http-file`, `email` (see controller Swagger enum at
9388
- * `apps/smart-gateway/src/domains/domains.controller.ts:226-234`).
9522
+ * `dns-cname`, `http-file`, `email`.
9389
9523
  */
9390
9524
  async generateVerificationToken(domain, method) {
9391
- return this.http.post(`/domains/${encodeURIComponent(domain)}/verification`, { method });
9525
+ return this.http.post(`/domains/${encodePathParam(domain)}/verification`, { method });
9392
9526
  }
9393
9527
  /** Verify domain ownership */
9394
9528
  async verifyOwnership(domain, token) {
9395
- return this.http.post(`/domains/${encodeURIComponent(domain)}/verify`, { token });
9529
+ return this.http.post(`/domains/${encodePathParam(domain)}/verify`, { token });
9396
9530
  }
9397
9531
  /** Configure DNS records for a domain */
9398
9532
  async configureDns(domain, records) {
9399
- return this.http.post(`/domains/${encodeURIComponent(domain)}/dns`, { records });
9533
+ return this.http.post(`/domains/${encodePathParam(domain)}/dns`, { records });
9400
9534
  }
9401
9535
  /** Enable DNSSEC for a domain */
9402
9536
  async enableDnssec(domain) {
9403
- return this.http.post(`/domains/${encodeURIComponent(domain)}/dnssec/enable`, {});
9537
+ return this.http.post(`/domains/${encodePathParam(domain)}/dnssec/enable`, {});
9404
9538
  }
9405
9539
  /** Disable DNSSEC for a domain */
9406
9540
  async disableDnssec(domain) {
9407
- return this.http.post(`/domains/${encodeURIComponent(domain)}/dnssec/disable`, {});
9541
+ return this.http.post(`/domains/${encodePathParam(domain)}/dnssec/disable`, {});
9408
9542
  }
9409
9543
  /** Renew a domain */
9410
9544
  async renew(domain, years) {
9411
- return this.http.post(`/domains/${encodeURIComponent(domain)}/renew`, { years: years ?? 1 });
9545
+ return this.http.post(`/domains/${encodePathParam(domain)}/renew`, { years: years ?? 1 });
9412
9546
  }
9413
9547
  /** Initiate a domain transfer */
9414
9548
  async transfer(domain, request) {
9415
- return this.http.post(`/domains/${encodeURIComponent(domain)}/transfer`, request);
9549
+ return this.http.post(`/domains/${encodePathParam(domain)}/transfer`, request);
9416
9550
  }
9417
9551
  /** Approve a pending domain transfer */
9418
9552
  async approveTransfer(domain) {
9419
- return this.http.post(`/domains/${encodeURIComponent(domain)}/transfer/approve`, {});
9553
+ return this.http.post(`/domains/${encodePathParam(domain)}/transfer/approve`, {});
9420
9554
  }
9421
9555
  /** Reject a pending domain transfer */
9422
9556
  async rejectTransfer(domain) {
9423
- return this.http.post(`/domains/${encodeURIComponent(domain)}/transfer/reject`, {});
9557
+ return this.http.post(`/domains/${encodePathParam(domain)}/transfer/reject`, {});
9424
9558
  }
9425
9559
  /** Suspend a domain */
9426
9560
  async suspend(domain, reason) {
9427
- return this.http.post(`/domains/${encodeURIComponent(domain)}/suspend`, { reason });
9561
+ return this.http.post(`/domains/${encodePathParam(domain)}/suspend`, { reason });
9428
9562
  }
9429
9563
  /** Unsuspend a domain */
9430
9564
  async unsuspend(domain) {
9431
- return this.http.post(`/domains/${encodeURIComponent(domain)}/unsuspend`, {});
9565
+ return this.http.post(`/domains/${encodePathParam(domain)}/unsuspend`, {});
9432
9566
  }
9433
9567
  };
9434
9568
 
@@ -9455,7 +9589,7 @@ var DnsClient = class {
9455
9589
  }
9456
9590
  /** Get a specific zone */
9457
9591
  async getZone(zoneName) {
9458
- return this.http.get(`/dns/zones/${encodeURIComponent(zoneName)}`);
9592
+ return this.http.get(`/dns/zones/${encodePathParam(zoneName)}`);
9459
9593
  }
9460
9594
  /** Create a new DNS zone */
9461
9595
  async createZone(request) {
@@ -9463,38 +9597,38 @@ var DnsClient = class {
9463
9597
  }
9464
9598
  /** Delete a DNS zone */
9465
9599
  async deleteZone(zoneName) {
9466
- return this.http.delete(`/dns/zones/${encodeURIComponent(zoneName)}`);
9600
+ return this.http.delete(`/dns/zones/${encodePathParam(zoneName)}`);
9467
9601
  }
9468
9602
  /** Add a record to a zone */
9469
9603
  async addRecord(zoneName, record) {
9470
- return this.http.post(`/dns/zones/${encodeURIComponent(zoneName)}/records`, record);
9604
+ return this.http.post(`/dns/zones/${encodePathParam(zoneName)}/records`, record);
9471
9605
  }
9472
9606
  /** Update a record in a zone */
9473
9607
  async updateRecord(zoneName, recordId, updates) {
9474
9608
  return this.http.put(
9475
- `/dns/zones/${encodeURIComponent(zoneName)}/records/${encodeURIComponent(recordId)}`,
9609
+ `/dns/zones/${encodePathParam(zoneName)}/records/${encodePathParam(recordId)}`,
9476
9610
  updates
9477
9611
  );
9478
9612
  }
9479
9613
  /** Delete a record from a zone */
9480
9614
  async deleteRecord(zoneName, recordId) {
9481
9615
  return this.http.delete(
9482
- `/dns/zones/${encodeURIComponent(zoneName)}/records/${encodeURIComponent(recordId)}`
9616
+ `/dns/zones/${encodePathParam(zoneName)}/records/${encodePathParam(recordId)}`
9483
9617
  );
9484
9618
  }
9485
9619
  /** Generate DNSSEC keys for a zone */
9486
9620
  async generateDnssecKeys(zoneName, algorithm) {
9487
- return this.http.post(`/dns/zones/${encodeURIComponent(zoneName)}/dnssec/keys`, {
9621
+ return this.http.post(`/dns/zones/${encodePathParam(zoneName)}/dnssec/keys`, {
9488
9622
  algorithm
9489
9623
  });
9490
9624
  }
9491
9625
  /** Get DNSSEC keys for a zone */
9492
9626
  async getDnssecKeys(zoneName) {
9493
- return this.http.get(`/dns/zones/${encodeURIComponent(zoneName)}/dnssec/keys`);
9627
+ return this.http.get(`/dns/zones/${encodePathParam(zoneName)}/dnssec/keys`);
9494
9628
  }
9495
9629
  /** Get DS record for a zone (for registrar configuration) */
9496
9630
  async getDsRecord(zoneName) {
9497
- return this.http.get(`/dns/zones/${encodeURIComponent(zoneName)}/dnssec/ds`);
9631
+ return this.http.get(`/dns/zones/${encodePathParam(zoneName)}/dnssec/ds`);
9498
9632
  }
9499
9633
  /** Clear DNS cache */
9500
9634
  async clearCache() {
@@ -9509,10 +9643,8 @@ var HealthClient = class {
9509
9643
  }
9510
9644
  http;
9511
9645
  /**
9512
- * Per-cluster aggregate health probe. Wraps
9513
- * `GET /api/v3/cluster/health` see
9514
- * `apps/smart-gateway/src/health/health.controller.ts:213-263`. Returns
9515
- * local validator + host + genesis state in a single payload.
9646
+ * Per-cluster aggregate health probe. Wraps `GET /api/v3/cluster/health`.
9647
+ * Returns local validator + host + genesis state in a single payload.
9516
9648
  */
9517
9649
  async getCluster() {
9518
9650
  return this.http.get("/cluster/health");
@@ -10107,7 +10239,7 @@ var DatabaseClient = class {
10107
10239
  async insert(collection, document) {
10108
10240
  const appId = this.getAppId();
10109
10241
  return this.http.post(
10110
- `/api/db/${encodeURIComponent(appId)}/${encodeURIComponent(collection)}`,
10242
+ `/api/db/${encodePathParam(appId)}/${encodePathParam(collection)}`,
10111
10243
  document
10112
10244
  );
10113
10245
  }
@@ -10125,7 +10257,7 @@ var DatabaseClient = class {
10125
10257
  if (options?.sort) params.set("sort", options.sort);
10126
10258
  const qs = params.toString();
10127
10259
  return this.http.get(
10128
- `/api/db/${encodeURIComponent(appId)}/${encodeURIComponent(collection)}${qs ? `?${qs}` : ""}`
10260
+ `/api/db/${encodePathParam(appId)}/${encodePathParam(collection)}${qs ? `?${qs}` : ""}`
10129
10261
  );
10130
10262
  }
10131
10263
  /**
@@ -10134,7 +10266,7 @@ var DatabaseClient = class {
10134
10266
  async update(collection, documentId, updates) {
10135
10267
  const appId = this.getAppId();
10136
10268
  return this.http.put(
10137
- `/api/db/${encodeURIComponent(appId)}/${encodeURIComponent(collection)}/${encodeURIComponent(documentId)}`,
10269
+ `/api/db/${encodePathParam(appId)}/${encodePathParam(collection)}/${encodePathParam(documentId)}`,
10138
10270
  updates
10139
10271
  );
10140
10272
  }
@@ -10144,7 +10276,7 @@ var DatabaseClient = class {
10144
10276
  async delete(collection, documentId) {
10145
10277
  const appId = this.getAppId();
10146
10278
  return this.http.delete(
10147
- `/api/db/${encodeURIComponent(appId)}/${encodeURIComponent(collection)}/${encodeURIComponent(documentId)}`
10279
+ `/api/db/${encodePathParam(appId)}/${encodePathParam(collection)}/${encodePathParam(documentId)}`
10148
10280
  );
10149
10281
  }
10150
10282
  /**
@@ -10156,7 +10288,7 @@ var DatabaseClient = class {
10156
10288
  */
10157
10289
  async listCollections() {
10158
10290
  const appId = this.getAppId();
10159
- return this.http.get(`/api/db/${encodeURIComponent(appId)}/collections`);
10291
+ return this.http.get(`/api/db/${encodePathParam(appId)}/collections`);
10160
10292
  }
10161
10293
  /**
10162
10294
  * Create a new collection in the database.
@@ -10166,7 +10298,7 @@ var DatabaseClient = class {
10166
10298
  */
10167
10299
  async createCollection(name) {
10168
10300
  const appId = this.getAppId();
10169
- return this.http.post(`/api/db/${encodeURIComponent(appId)}/collections`, { name });
10301
+ return this.http.post(`/api/db/${encodePathParam(appId)}/collections`, { name });
10170
10302
  }
10171
10303
  /**
10172
10304
  * Drop a collection and all its documents.
@@ -10177,7 +10309,7 @@ var DatabaseClient = class {
10177
10309
  async dropCollection(name) {
10178
10310
  const appId = this.getAppId();
10179
10311
  return this.http.delete(
10180
- `/api/db/${encodeURIComponent(appId)}/collections/${encodeURIComponent(name)}`
10312
+ `/api/db/${encodePathParam(appId)}/collections/${encodePathParam(name)}`
10181
10313
  );
10182
10314
  }
10183
10315
  // ========== State Proofs ==========
@@ -10186,7 +10318,7 @@ var DatabaseClient = class {
10186
10318
  */
10187
10319
  async getStateRoot() {
10188
10320
  const appId = this.getAppId();
10189
- return this.http.get(`/api/db/${encodeURIComponent(appId)}/state/root`);
10321
+ return this.http.get(`/api/db/${encodePathParam(appId)}/state/root`);
10190
10322
  }
10191
10323
  /**
10192
10324
  * Get a Merkle proof for a specific document
@@ -10194,7 +10326,7 @@ var DatabaseClient = class {
10194
10326
  async getDocumentProof(documentId) {
10195
10327
  const appId = this.getAppId();
10196
10328
  return this.http.get(
10197
- `/api/db/${encodeURIComponent(appId)}/${encodeURIComponent(documentId)}/proof`
10329
+ `/api/db/${encodePathParam(appId)}/${encodePathParam(documentId)}/proof`
10198
10330
  );
10199
10331
  }
10200
10332
  /**
@@ -10208,7 +10340,7 @@ var DatabaseClient = class {
10208
10340
  if (options?.limit !== void 0) params.set("limit", String(options.limit));
10209
10341
  const qs = params.toString();
10210
10342
  return this.http.get(
10211
- `/api/db/${encodeURIComponent(appId)}/state/transitions${qs ? `?${qs}` : ""}`
10343
+ `/api/db/${encodePathParam(appId)}/state/transitions${qs ? `?${qs}` : ""}`
10212
10344
  );
10213
10345
  }
10214
10346
  /**
@@ -10216,7 +10348,7 @@ var DatabaseClient = class {
10216
10348
  */
10217
10349
  async getDbStats() {
10218
10350
  const appId = this.getAppId();
10219
- return this.http.get(`/api/db/${encodeURIComponent(appId)}/stats`);
10351
+ return this.http.get(`/api/db/${encodePathParam(appId)}/stats`);
10220
10352
  }
10221
10353
  };
10222
10354
 
@@ -10233,47 +10365,35 @@ var StorageClient = class {
10233
10365
  */
10234
10366
  async upload(file, filename, metadata) {
10235
10367
  const appId = this.getAppId();
10236
- return this.http.upload(`/api/storage/${encodeURIComponent(appId)}/upload`, file, filename, metadata);
10368
+ return this.http.upload(`/api/storage/${encodePathParam(appId)}/upload`, file, filename, metadata);
10237
10369
  }
10238
10370
  /**
10239
10371
  * Download a file by CID
10240
10372
  */
10241
10373
  async download(cid) {
10242
10374
  const appId = this.getAppId();
10243
- return this.http.get(`/api/storage/${encodeURIComponent(appId)}/download/${encodeURIComponent(cid)}`);
10375
+ return this.http.get(`/api/storage/${encodePathParam(appId)}/download/${encodePathParam(cid)}`);
10244
10376
  }
10245
10377
  /**
10246
10378
  * Get file metadata
10247
10379
  */
10248
10380
  async getMetadata(cid) {
10249
10381
  const appId = this.getAppId();
10250
- return this.http.get(`/api/storage/${encodeURIComponent(appId)}/metadata/${encodeURIComponent(cid)}`);
10382
+ return this.http.get(`/api/storage/${encodePathParam(appId)}/metadata/${encodePathParam(cid)}`);
10251
10383
  }
10252
10384
  /**
10253
10385
  * Delete a file
10254
10386
  */
10255
10387
  async delete(cid) {
10256
10388
  const appId = this.getAppId();
10257
- return this.http.delete(`/api/storage/${encodeURIComponent(appId)}/${encodeURIComponent(cid)}`);
10389
+ return this.http.delete(`/api/storage/${encodePathParam(appId)}/${encodePathParam(cid)}`);
10258
10390
  }
10259
10391
  /**
10260
- * Get file info.
10392
+ * List all files for the app.
10261
10393
  *
10262
- * @deprecated The smart-host storage controller does not expose a
10263
- * bare-CID metadata route — every metadata lookup must go through
10264
- * `getMetadata(cid)` (`/api/storage/:appId/metadata/:cid`) or the
10265
- * stream body via `download(cid)`. This alias forwards to `download`
10266
- * for back-compat; remove in the next major SDK release.
10267
- */
10268
- async getFile(cid) {
10269
- return this.download(cid);
10270
- }
10271
- /**
10272
- * List all files for the app
10273
- *
10274
- * @param pagination.offset Server reads `offset`; the legacy `skip`
10275
- * option was a client-only synonym that the server silently ignored.
10276
- * Use `offset` going forward.
10394
+ * @param pagination - Optional `limit` and `offset` (the server reads
10395
+ * `offset` for pagination).
10396
+ * @returns The file list and total count.
10277
10397
  */
10278
10398
  async listFiles(pagination) {
10279
10399
  const appId = this.getAppId();
@@ -10281,21 +10401,21 @@ var StorageClient = class {
10281
10401
  if (pagination?.limit !== void 0) params.set("limit", String(pagination.limit));
10282
10402
  if (pagination?.offset !== void 0) params.set("offset", String(pagination.offset));
10283
10403
  const qs = params.toString();
10284
- return this.http.get(`/api/storage/${encodeURIComponent(appId)}/files${qs ? `?${qs}` : ""}`);
10404
+ return this.http.get(`/api/storage/${encodePathParam(appId)}/files${qs ? `?${qs}` : ""}`);
10285
10405
  }
10286
10406
  /**
10287
10407
  * Get storage usage for the current app
10288
10408
  */
10289
10409
  async getUsage() {
10290
10410
  const appId = this.getAppId();
10291
- return this.http.get(`/api/storage/${encodeURIComponent(appId)}/usage`);
10411
+ return this.http.get(`/api/storage/${encodePathParam(appId)}/usage`);
10292
10412
  }
10293
10413
  /**
10294
10414
  * Check if a file exists
10295
10415
  */
10296
10416
  async exists(cid) {
10297
10417
  const appId = this.getAppId();
10298
- return this.http.get(`/api/storage/${encodeURIComponent(appId)}/exists/${encodeURIComponent(cid)}`);
10418
+ return this.http.get(`/api/storage/${encodePathParam(appId)}/exists/${encodePathParam(cid)}`);
10299
10419
  }
10300
10420
  };
10301
10421
 
@@ -10312,7 +10432,7 @@ var FunctionsClient = class {
10312
10432
  */
10313
10433
  async deploy(request) {
10314
10434
  const appId = this.getAppId();
10315
- return this.http.post(`/api/functions/${encodeURIComponent(appId)}`, request);
10435
+ return this.http.post(`/api/functions/${encodePathParam(appId)}`, request);
10316
10436
  }
10317
10437
  /**
10318
10438
  * Invoke a function
@@ -10320,7 +10440,7 @@ var FunctionsClient = class {
10320
10440
  async invoke(functionId, payload) {
10321
10441
  const appId = this.getAppId();
10322
10442
  return this.http.post(
10323
- `/api/functions/${encodeURIComponent(appId)}/${encodeURIComponent(functionId)}/invoke`,
10443
+ `/api/functions/${encodePathParam(appId)}/${encodePathParam(functionId)}/invoke`,
10324
10444
  payload ?? {}
10325
10445
  );
10326
10446
  }
@@ -10329,7 +10449,7 @@ var FunctionsClient = class {
10329
10449
  */
10330
10450
  async list() {
10331
10451
  const appId = this.getAppId();
10332
- return this.http.get(`/api/functions/${encodeURIComponent(appId)}`);
10452
+ return this.http.get(`/api/functions/${encodePathParam(appId)}`);
10333
10453
  }
10334
10454
  /**
10335
10455
  * Get function details
@@ -10337,7 +10457,7 @@ var FunctionsClient = class {
10337
10457
  async get(functionId) {
10338
10458
  const appId = this.getAppId();
10339
10459
  return this.http.get(
10340
- `/api/functions/${encodeURIComponent(appId)}/${encodeURIComponent(functionId)}`
10460
+ `/api/functions/${encodePathParam(appId)}/${encodePathParam(functionId)}`
10341
10461
  );
10342
10462
  }
10343
10463
  /**
@@ -10346,7 +10466,7 @@ var FunctionsClient = class {
10346
10466
  async update(functionId, updates) {
10347
10467
  const appId = this.getAppId();
10348
10468
  return this.http.put(
10349
- `/api/functions/${encodeURIComponent(appId)}/${encodeURIComponent(functionId)}`,
10469
+ `/api/functions/${encodePathParam(appId)}/${encodePathParam(functionId)}`,
10350
10470
  updates
10351
10471
  );
10352
10472
  }
@@ -10356,7 +10476,7 @@ var FunctionsClient = class {
10356
10476
  async delete(functionId) {
10357
10477
  const appId = this.getAppId();
10358
10478
  return this.http.delete(
10359
- `/api/functions/${encodeURIComponent(appId)}/${encodeURIComponent(functionId)}`
10479
+ `/api/functions/${encodePathParam(appId)}/${encodePathParam(functionId)}`
10360
10480
  );
10361
10481
  }
10362
10482
  /**
@@ -10370,7 +10490,7 @@ var FunctionsClient = class {
10370
10490
  if (options?.level) params.set("level", options.level);
10371
10491
  const qs = params.toString();
10372
10492
  return this.http.get(
10373
- `/api/functions/${encodeURIComponent(appId)}/${encodeURIComponent(functionId)}/logs${qs ? `?${qs}` : ""}`
10493
+ `/api/functions/${encodePathParam(appId)}/${encodePathParam(functionId)}/logs${qs ? `?${qs}` : ""}`
10374
10494
  );
10375
10495
  }
10376
10496
  /**
@@ -10378,7 +10498,7 @@ var FunctionsClient = class {
10378
10498
  */
10379
10499
  async getStats() {
10380
10500
  const appId = this.getAppId();
10381
- return this.http.get(`/api/functions/${encodeURIComponent(appId)}/stats`);
10501
+ return this.http.get(`/api/functions/${encodePathParam(appId)}/stats`);
10382
10502
  }
10383
10503
  };
10384
10504
 
@@ -10395,28 +10515,28 @@ var MessagingClient = class {
10395
10515
  */
10396
10516
  async createChannel(config) {
10397
10517
  const appId = this.getAppId();
10398
- return this.http.post(`/api/messaging/${encodeURIComponent(appId)}/channels`, config);
10518
+ return this.http.post(`/api/messaging/${encodePathParam(appId)}/channels`, config);
10399
10519
  }
10400
10520
  /**
10401
10521
  * Delete a channel
10402
10522
  */
10403
10523
  async deleteChannel(channelId) {
10404
10524
  const appId = this.getAppId();
10405
- return this.http.delete(`/api/messaging/${encodeURIComponent(appId)}/channels/${encodeURIComponent(channelId)}`);
10525
+ return this.http.delete(`/api/messaging/${encodePathParam(appId)}/channels/${encodePathParam(channelId)}`);
10406
10526
  }
10407
10527
  /**
10408
10528
  * Get a channel by ID
10409
10529
  */
10410
10530
  async getChannel(channelId) {
10411
10531
  const appId = this.getAppId();
10412
- return this.http.get(`/api/messaging/${encodeURIComponent(appId)}/channels/${encodeURIComponent(channelId)}`);
10532
+ return this.http.get(`/api/messaging/${encodePathParam(appId)}/channels/${encodePathParam(channelId)}`);
10413
10533
  }
10414
10534
  /**
10415
10535
  * List all channels for the app
10416
10536
  */
10417
10537
  async listChannels() {
10418
10538
  const appId = this.getAppId();
10419
- return this.http.get(`/api/messaging/${encodeURIComponent(appId)}/channels`);
10539
+ return this.http.get(`/api/messaging/${encodePathParam(appId)}/channels`);
10420
10540
  }
10421
10541
  /**
10422
10542
  * Publish a message to a channel
@@ -10424,7 +10544,7 @@ var MessagingClient = class {
10424
10544
  async publish(channel, message, metadata) {
10425
10545
  const appId = this.getAppId();
10426
10546
  return this.http.post(
10427
- `/api/messaging/${encodeURIComponent(appId)}/channels/${encodeURIComponent(channel)}/publish`,
10547
+ `/api/messaging/${encodePathParam(appId)}/channels/${encodePathParam(channel)}/publish`,
10428
10548
  { data: message, metadata }
10429
10549
  );
10430
10550
  }
@@ -10439,7 +10559,7 @@ var MessagingClient = class {
10439
10559
  if (options?.after) params.set("after", options.after);
10440
10560
  const qs = params.toString();
10441
10561
  return this.http.get(
10442
- `/api/messaging/${encodeURIComponent(appId)}/channels/${encodeURIComponent(channel)}/history${qs ? `?${qs}` : ""}`
10562
+ `/api/messaging/${encodePathParam(appId)}/channels/${encodePathParam(channel)}/history${qs ? `?${qs}` : ""}`
10443
10563
  );
10444
10564
  }
10445
10565
  /**
@@ -10453,7 +10573,7 @@ var MessagingClient = class {
10453
10573
  async setPresence(channel, member) {
10454
10574
  const appId = this.getAppId();
10455
10575
  return this.http.post(
10456
- `/api/messaging/${encodeURIComponent(appId)}/channels/${encodeURIComponent(channel)}/presence`,
10576
+ `/api/messaging/${encodePathParam(appId)}/channels/${encodePathParam(channel)}/presence`,
10457
10577
  member
10458
10578
  );
10459
10579
  }
@@ -10469,7 +10589,7 @@ var MessagingClient = class {
10469
10589
  async removePresence(channel, clientId) {
10470
10590
  const appId = this.getAppId();
10471
10591
  return this.http.delete(
10472
- `/api/messaging/${encodeURIComponent(appId)}/channels/${encodeURIComponent(channel)}/presence/${encodeURIComponent(clientId)}`
10592
+ `/api/messaging/${encodePathParam(appId)}/channels/${encodePathParam(channel)}/presence/${encodePathParam(clientId)}`
10473
10593
  );
10474
10594
  }
10475
10595
  /**
@@ -10478,7 +10598,7 @@ var MessagingClient = class {
10478
10598
  async getPresence(channel) {
10479
10599
  const appId = this.getAppId();
10480
10600
  return this.http.get(
10481
- `/api/messaging/${encodeURIComponent(appId)}/channels/${encodeURIComponent(channel)}/presence`
10601
+ `/api/messaging/${encodePathParam(appId)}/channels/${encodePathParam(channel)}/presence`
10482
10602
  );
10483
10603
  }
10484
10604
  /**
@@ -10486,7 +10606,7 @@ var MessagingClient = class {
10486
10606
  */
10487
10607
  async getStats() {
10488
10608
  const appId = this.getAppId();
10489
- return this.http.get(`/api/messaging/${encodeURIComponent(appId)}/stats`);
10609
+ return this.http.get(`/api/messaging/${encodePathParam(appId)}/stats`);
10490
10610
  }
10491
10611
  };
10492
10612
 
@@ -10574,7 +10694,7 @@ var RulesClient = class {
10574
10694
  }
10575
10695
  /** Fetch a published rule by its HCS consensus timestamp. */
10576
10696
  async get(consensusTimestamp) {
10577
- return this.http.get(`/api/rules/${encodeURIComponent(consensusTimestamp)}`);
10697
+ return this.http.get(`/api/rules/${encodePathParam(consensusTimestamp)}`);
10578
10698
  }
10579
10699
  /** List rules owned by the authenticated entity, optionally filtered by type. */
10580
10700
  async listByOwner(filter) {
@@ -10591,13 +10711,13 @@ var RulesClient = class {
10591
10711
  /** Walk the version history of a published rule. */
10592
10712
  async getVersionHistory(consensusTimestamp) {
10593
10713
  return this.http.get(
10594
- `/api/rules/${encodeURIComponent(consensusTimestamp)}/versions`
10714
+ `/api/rules/${encodePathParam(consensusTimestamp)}/versions`
10595
10715
  );
10596
10716
  }
10597
10717
  /** Deprecate a published rule (owner-only). */
10598
10718
  async deprecate(consensusTimestamp) {
10599
10719
  return this.http.post(
10600
- `/api/rules/${encodeURIComponent(consensusTimestamp)}/deprecate`,
10720
+ `/api/rules/${encodePathParam(consensusTimestamp)}/deprecate`,
10601
10721
  {}
10602
10722
  );
10603
10723
  }
@@ -10635,7 +10755,7 @@ var EntitiesClient = class {
10635
10755
  }
10636
10756
  /** Fetch an entity by its canonical `entityId`. */
10637
10757
  async get(entityId) {
10638
- return this.http.get(`/api/entities/${encodeURIComponent(entityId)}`);
10758
+ return this.http.get(`/api/entities/${encodePathParam(entityId)}`);
10639
10759
  }
10640
10760
  /** List entities owned by the authenticated wallet, optionally filtered by type. */
10641
10761
  async listByOwner(filter) {
@@ -10651,10 +10771,16 @@ var BaasClient = class _BaasClient {
10651
10771
  appId;
10652
10772
  timeout;
10653
10773
  allowInsecure;
10654
- authToken = null;
10655
10774
  http;
10656
10775
  /** Last HTTP error (for getHttpHealth) */
10657
10776
  lastHttpError;
10777
+ /**
10778
+ * Auth options from the last {@link authenticate} call, retained so the
10779
+ * client can transparently re-authenticate when the session token expires
10780
+ * (the http client invokes {@link reauthenticate} on a 401). Undefined until
10781
+ * the first successful authenticate.
10782
+ */
10783
+ authContext;
10658
10784
  // ========== Sub-Clients ==========
10659
10785
  /** Trustless database with state proofs and Merkle verification */
10660
10786
  db;
@@ -10684,7 +10810,11 @@ var BaasClient = class _BaasClient {
10684
10810
  const baseUrlWithPrefix = this.pathPrefix ? this.hostUrl.replace(/\/$/, "") + this.pathPrefix : this.hostUrl;
10685
10811
  this.http = createHttpClient({
10686
10812
  baseUrl: baseUrlWithPrefix,
10687
- timeout: this.timeout
10813
+ timeout: this.timeout,
10814
+ // Transparent session refresh: on a 401, re-run the challenge-response
10815
+ // with the retained signer and retry once. No-op until authenticate() has
10816
+ // been called (authContext set). Excludes /api/auth/* (see http client).
10817
+ onUnauthorized: () => this.reauthenticate()
10688
10818
  });
10689
10819
  const getAppId = () => this.requireAppId();
10690
10820
  this.db = new DatabaseClient(this.http, getAppId);
@@ -10738,30 +10868,25 @@ var BaasClient = class _BaasClient {
10738
10868
  */
10739
10869
  static async connectToCluster(config) {
10740
10870
  const allowInsecure = config.allowInsecure ?? false;
10741
- const bootstrap = config.bootstrap ? [...config.bootstrap] : [...resolveNetwork(config.network).bootstrap];
10742
- if (bootstrap.length === 0) {
10743
- throw new BaasError(
10744
- "connectToCluster requires either a non-empty `bootstrap` list or a known `network` name.",
10745
- 400
10746
- );
10747
- }
10748
- const discovery = new ClusterDiscoveryClient({
10749
- bootstrap,
10871
+ const resolved = await resolveClusterEndpoint({
10872
+ bootstrap: config.bootstrap,
10873
+ network: config.network,
10750
10874
  allowInsecure,
10751
- trustAnchor: config.trustAnchor ? {
10752
- network: config.trustAnchor.network,
10753
- registryTopicId: config.trustAnchor.registryTopicId,
10754
- mirrorNodeUrl: config.trustAnchor.mirrorNodeUrl,
10755
- allowInsecure
10756
- } : void 0
10875
+ trustAnchor: config.trustAnchor
10757
10876
  });
10758
- const cluster = await discovery.getRandomCluster();
10759
- if (!cluster) {
10877
+ if (!resolved.ok) {
10878
+ if (resolved.reason === "no-seeds") {
10879
+ throw new BaasError(
10880
+ "connectToCluster requires either a non-empty `bootstrap` list or a known `network` name.",
10881
+ 400
10882
+ );
10883
+ }
10760
10884
  throw new BaasError(
10761
10885
  "No active clusters available via bootstrap seeds. Check network reachability or bootstrap URLs.",
10762
10886
  503
10763
10887
  );
10764
10888
  }
10889
+ const cluster = resolved.cluster;
10765
10890
  return new _BaasClient({
10766
10891
  hostUrl: cluster.endpoints.gatewayUrl,
10767
10892
  appId: config.appId,
@@ -10779,7 +10904,7 @@ var BaasClient = class _BaasClient {
10779
10904
  }
10780
10905
  /** Check if the client is authenticated */
10781
10906
  isAuthenticated() {
10782
- return this.authToken !== null;
10907
+ return this.http.getAuthToken() !== void 0;
10783
10908
  }
10784
10909
  /** Get the current app ID */
10785
10910
  getAppId() {
@@ -10825,93 +10950,80 @@ var BaasClient = class _BaasClient {
10825
10950
  */
10826
10951
  async authenticate(options) {
10827
10952
  const { chain, walletAddress, publicKey, signFn } = options;
10828
- const challenge = await this.post("/api/auth/challenge", {
10829
- chain,
10830
- walletAddress,
10953
+ this.authContext = options;
10954
+ let challenge;
10955
+ try {
10956
+ challenge = await this.http.post("/api/auth/challenge", {
10957
+ chain,
10958
+ walletAddress,
10959
+ appId: this.appId
10960
+ });
10961
+ } catch (err) {
10962
+ throw asBaasError(err);
10963
+ }
10964
+ const signature = await signFn(challenge.message);
10965
+ let result;
10966
+ try {
10967
+ result = await this.http.post("/api/auth/verify", {
10968
+ challengeId: challenge.challengeId,
10969
+ signature,
10970
+ publicKey
10971
+ });
10972
+ } catch (err) {
10973
+ throw asBaasError(err);
10974
+ }
10975
+ this.http.setAuthToken(result.token);
10976
+ return result;
10977
+ }
10978
+ /**
10979
+ * Re-run the challenge-response with the retained signer to mint a fresh
10980
+ * session token. Invoked by the http client's `onUnauthorized` hook when a
10981
+ * request 401s because the token expired — so long-lived clients keep working
10982
+ * without the caller re-implementing refresh. No-op if {@link authenticate}
10983
+ * was never called. The `/api/auth/*` calls below are excluded from the http
10984
+ * client's 401-retry path, so this can never recurse.
10985
+ */
10986
+ async reauthenticate() {
10987
+ const ctx = this.authContext;
10988
+ if (!ctx) return;
10989
+ const challenge = await this.http.post("/api/auth/challenge", {
10990
+ chain: ctx.chain,
10991
+ walletAddress: ctx.walletAddress,
10831
10992
  appId: this.appId
10832
10993
  });
10833
- const signature = await signFn(challenge.message);
10834
- const result = await this.post("/api/auth/verify", {
10994
+ const signature = await ctx.signFn(challenge.message);
10995
+ const result = await this.http.post("/api/auth/verify", {
10835
10996
  challengeId: challenge.challengeId,
10836
10997
  signature,
10837
- publicKey
10998
+ publicKey: ctx.publicKey
10838
10999
  });
10839
- this.authToken = result.token;
10840
- this.http.setAuthToken?.(result.token);
10841
- return result;
11000
+ this.http.setAuthToken(result.token);
10842
11001
  }
10843
11002
  /** Validate the current session */
10844
11003
  async validateSession() {
10845
11004
  this.requireAuth();
10846
- return this.get("/api/auth/session");
11005
+ try {
11006
+ return await this.http.get("/api/auth/session");
11007
+ } catch (err) {
11008
+ throw asBaasError(err);
11009
+ }
10847
11010
  }
10848
11011
  /** Destroy the current session on server and clear local token */
10849
11012
  async logout() {
10850
- if (this.authToken) {
11013
+ if (this.http.getAuthToken()) {
10851
11014
  try {
10852
- await this.post("/api/auth/logout", {});
11015
+ await this.http.post("/api/auth/logout", {});
10853
11016
  } catch {
10854
11017
  }
10855
11018
  }
10856
- this.authToken = null;
11019
+ this.http.setAuthToken(void 0);
10857
11020
  }
10858
11021
  // ========== HTTP Helpers ==========
10859
11022
  requireAuth() {
10860
- if (!this.authToken) {
11023
+ if (!this.http.getAuthToken()) {
10861
11024
  throw new BaasError("Authentication required. Call authenticate() first.", 401);
10862
11025
  }
10863
11026
  }
10864
- getHeaders() {
10865
- const headers = {
10866
- "Content-Type": "application/json"
10867
- };
10868
- if (this.authToken) {
10869
- headers["Authorization"] = `Bearer ${this.authToken}`;
10870
- }
10871
- return headers;
10872
- }
10873
- async post(path, body) {
10874
- return this.request("POST", path, body);
10875
- }
10876
- async get(path) {
10877
- return this.request("GET", path);
10878
- }
10879
- async request(method, path, body) {
10880
- const url = `${this.hostUrl}${this.pathPrefix}${path}`;
10881
- const controller = new AbortController();
10882
- const timeoutId = setTimeout(() => controller.abort(), this.timeout);
10883
- try {
10884
- const options = {
10885
- method,
10886
- headers: this.getHeaders(),
10887
- signal: controller.signal
10888
- };
10889
- if (body !== void 0) {
10890
- options.body = JSON.stringify(body);
10891
- }
10892
- const response = await fetch(url, options);
10893
- clearTimeout(timeoutId);
10894
- if (!response.ok) {
10895
- const errorData = await response.json().catch(() => ({}));
10896
- throw new BaasError(
10897
- errorData.message || `API error: ${response.status} ${response.statusText}`,
10898
- response.status,
10899
- errorData
10900
- );
10901
- }
10902
- const text = await response.text();
10903
- if (!text) return void 0;
10904
- return JSON.parse(text);
10905
- } catch (error) {
10906
- clearTimeout(timeoutId);
10907
- if (error instanceof BaasError) throw error;
10908
- const err = error;
10909
- if (err.name === "AbortError") {
10910
- throw new BaasError("Request timeout", 408);
10911
- }
10912
- throw new BaasError(`Network error: ${err.message}`, 0, { originalError: err.message });
10913
- }
10914
- }
10915
11027
  };
10916
11028
  var BaasError = class extends Error {
10917
11029
  constructor(message, statusCode, details) {
@@ -10923,6 +11035,17 @@ var BaasError = class extends Error {
10923
11035
  statusCode;
10924
11036
  details;
10925
11037
  };
11038
+ function asBaasError(err) {
11039
+ if (err instanceof BaasError) return err;
11040
+ if (err instanceof SdkHttpError) {
11041
+ const details = err.details ?? void 0;
11042
+ return new BaasError(err.message, err.statusCode, details);
11043
+ }
11044
+ const e = err;
11045
+ return new BaasError(`Network error: ${e?.message ?? String(err)}`, 0, {
11046
+ originalError: e?.message ?? String(err)
11047
+ });
11048
+ }
10926
11049
  function validateUrl2(url, allowInsecure = false) {
10927
11050
  try {
10928
11051
  const parsed = new URL(url);
@@ -11152,9 +11275,6 @@ function validateEnvelopeSchema(envelope) {
11152
11275
  if (version === "kyber-aes-v1") {
11153
11276
  return validateKyberAesV1(envelope);
11154
11277
  }
11155
- if (version === "aes-v0") {
11156
- return validateAesV0(envelope);
11157
- }
11158
11278
  return {
11159
11279
  ok: false,
11160
11280
  reason: `unknown envelope version: ${JSON.stringify(version)}`
@@ -11248,38 +11368,6 @@ function validateKyberAesV1(env) {
11248
11368
  }
11249
11369
  return { ok: true, version: "kyber-aes-v1" };
11250
11370
  }
11251
- function validateAesV0(env) {
11252
- if (!isNonEmptyString(env.aesIv)) {
11253
- return { ok: false, reason: "aesIv must be a non-empty base64 string" };
11254
- }
11255
- const ivBytes = tryDecodeBase64(env.aesIv);
11256
- if (!ivBytes) return { ok: false, reason: "aesIv is not valid base64" };
11257
- if (ivBytes.length !== AES_IV_LEN) {
11258
- return {
11259
- ok: false,
11260
- reason: `aesIv length ${ivBytes.length} != expected ${AES_IV_LEN} (AES-GCM 96-bit nonce)`
11261
- };
11262
- }
11263
- if (typeof env.aesCiphertext !== "string") {
11264
- return { ok: false, reason: "aesCiphertext must be a base64 string" };
11265
- }
11266
- if (env.aesCiphertext.length > 0) {
11267
- const ctBytes = tryDecodeBase64(env.aesCiphertext);
11268
- if (!ctBytes) return { ok: false, reason: "aesCiphertext is not valid base64" };
11269
- }
11270
- if (!isNonEmptyString(env.aesAuthTag)) {
11271
- return { ok: false, reason: "aesAuthTag must be a non-empty base64 string" };
11272
- }
11273
- const tagBytes = tryDecodeBase64(env.aesAuthTag);
11274
- if (!tagBytes) return { ok: false, reason: "aesAuthTag is not valid base64" };
11275
- if (tagBytes.length !== AES_TAG_LEN) {
11276
- return {
11277
- ok: false,
11278
- reason: `aesAuthTag length ${tagBytes.length} != expected ${AES_TAG_LEN} (AES-GCM 128-bit tag)`
11279
- };
11280
- }
11281
- return { ok: true, version: "aes-v0" };
11282
- }
11283
11371
 
11284
11372
  // src/pqc-verify-envelope/verify-pqc-envelope.ts
11285
11373
  var KYBER_MIN_TIMESTAMP_MS = 17040672e5;
@@ -11298,10 +11386,10 @@ async function verifyPqcEnvelope(envelope, options = {}) {
11298
11386
  version,
11299
11387
  schemaValid: true,
11300
11388
  base64Valid: true,
11301
- // computed below for kyber-aes-v1; legacy has no encryptedAt so treat as plausible.
11389
+ // Set to false below if the timestamp plausibility check fails.
11302
11390
  timestampPlausible: true
11303
11391
  };
11304
- if (version === "kyber-aes-v1") {
11392
+ {
11305
11393
  details.kemAlgorithm = env.kemAlgorithm;
11306
11394
  details.recipientPkFingerprint = env.recipientPkFingerprint;
11307
11395
  details.kdfLabel = env.kdfLabel;
@@ -12163,17 +12251,13 @@ var AgentRulesBuilder = class extends BaseRuleBuilder {
12163
12251
  return this;
12164
12252
  }
12165
12253
  // ────────────────────────────────────────────────────────────────────────
12166
- // PR F — Phase-6.6 AI atom shortcuts
12254
+ // AI atom shortcuts
12167
12255
  //
12168
12256
  // `MaxTradesPerWindow` and `RequireStructuredOutput` are optional atoms
12169
12257
  // (NOT registered as builtin organism modules) wired in the AI-inference
12170
12258
  // path of the smart-app's BaaS function. Attached here as canonical
12171
12259
  // `ModuleEntry`s so they ship inside the published rule and the cluster's
12172
12260
  // canonical evaluator can dispatch them.
12173
- //
12174
- // Atom sources:
12175
- // libs/rules-engine/src/atoms/max-trades-per-window.atom.ts
12176
- // libs/rules-engine/src/atoms/require-structured-output.atom.ts
12177
12261
  // ────────────────────────────────────────────────────────────────────────
12178
12262
  /**
12179
12263
  * Cap the agent at `maxTradesPerWindow` trades within a rolling `windowMs`
@@ -12285,7 +12369,7 @@ var module_ = {
12285
12369
  version: "1.0.0",
12286
12370
  config: withDexDefaults(config)
12287
12371
  })
12288
- // PR F — `agent` retired per Arc 6 Phase 6.5. Use `Rules.forAgent()` instead.
12372
+ // No `agent` module use `Rules.forAgent()` instead.
12289
12373
  };
12290
12374
 
12291
12375
  // src/rules/templates/index.ts
@@ -12773,6 +12857,7 @@ exports.DomainsClient = DomainsClient;
12773
12857
  exports.EntitiesClient = EntitiesClient;
12774
12858
  exports.EnvelopeClient = EnvelopeClient;
12775
12859
  exports.ErrorCode = ErrorCode;
12860
+ exports.FaucetClient = FaucetClient;
12776
12861
  exports.FeeConditionsSchema = FeeConditionsSchema;
12777
12862
  exports.FixedFeeConditionSchema = FixedFeeConditionSchema;
12778
12863
  exports.FractionalFeeConditionSchema = FractionalFeeConditionSchema;
@@ -12865,6 +12950,7 @@ exports.discovery = discovery_exports;
12865
12950
  exports.encodePathParam = encodePathParam;
12866
12951
  exports.envelope = envelope_exports;
12867
12952
  exports.fairLaunch = fairLaunch;
12953
+ exports.faucet = faucet_exports;
12868
12954
  exports.fetchRegistrySnapshot = fetchRegistrySnapshot;
12869
12955
  exports.forAccount = forAccount;
12870
12956
  exports.forAgent = forAgent;