@hsuite/smart-engines-sdk 3.4.1 → 3.5.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.
@@ -1100,6 +1100,167 @@ var ClusterDiscoveryClient = class {
1100
1100
  }
1101
1101
  };
1102
1102
 
1103
+ // src/http/index.ts
1104
+ var SdkHttpError = class extends Error {
1105
+ constructor(message, statusCode, details) {
1106
+ super(message);
1107
+ this.statusCode = statusCode;
1108
+ this.details = details;
1109
+ this.name = "SdkHttpError";
1110
+ }
1111
+ statusCode;
1112
+ details;
1113
+ };
1114
+ function createHttpClient(config) {
1115
+ const timeout = config.timeout ?? 3e4;
1116
+ function getHeaders(contentType) {
1117
+ const headers = {};
1118
+ if (contentType) {
1119
+ headers["Content-Type"] = contentType;
1120
+ }
1121
+ if (config.authToken) {
1122
+ headers["Authorization"] = `Bearer ${config.authToken}`;
1123
+ }
1124
+ if (config.apiKey) {
1125
+ headers["X-API-Key"] = config.apiKey;
1126
+ }
1127
+ return headers;
1128
+ }
1129
+ function setAuthToken(token) {
1130
+ config.authToken = token;
1131
+ }
1132
+ function getAuthToken() {
1133
+ return config.authToken;
1134
+ }
1135
+ async function request(method, path, body) {
1136
+ const url = `${config.baseUrl}${path}`;
1137
+ const controller = new AbortController();
1138
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
1139
+ try {
1140
+ const init = {
1141
+ method,
1142
+ headers: getHeaders("application/json"),
1143
+ signal: controller.signal
1144
+ };
1145
+ if (body !== void 0) {
1146
+ init.body = JSON.stringify(body);
1147
+ }
1148
+ const response = await fetch(url, init);
1149
+ clearTimeout(timeoutId);
1150
+ if (!response.ok) {
1151
+ const errorData = await response.json().catch(() => ({}));
1152
+ throw new SdkHttpError(
1153
+ errorData.message || `API error: ${response.status} ${response.statusText}`,
1154
+ response.status,
1155
+ errorData
1156
+ );
1157
+ }
1158
+ const text = await response.text();
1159
+ if (!text) return void 0;
1160
+ return JSON.parse(text);
1161
+ } catch (error) {
1162
+ clearTimeout(timeoutId);
1163
+ if (error instanceof SdkHttpError) throw error;
1164
+ const err = error;
1165
+ if (err.name === "AbortError") {
1166
+ throw new SdkHttpError("Request timeout", 408);
1167
+ }
1168
+ throw new SdkHttpError(`Network error: ${err.message}`, 0, error);
1169
+ }
1170
+ }
1171
+ async function getText(path) {
1172
+ const url = `${config.baseUrl}${path}`;
1173
+ const controller = new AbortController();
1174
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
1175
+ try {
1176
+ const response = await fetch(url, {
1177
+ method: "GET",
1178
+ headers: getHeaders(),
1179
+ signal: controller.signal
1180
+ });
1181
+ clearTimeout(timeoutId);
1182
+ if (!response.ok) {
1183
+ const errBody = await response.json().catch(() => ({}));
1184
+ throw new SdkHttpError(
1185
+ errBody.message || `API error: ${response.status} ${response.statusText}`,
1186
+ response.status,
1187
+ errBody
1188
+ );
1189
+ }
1190
+ return await response.text();
1191
+ } catch (error) {
1192
+ clearTimeout(timeoutId);
1193
+ if (error instanceof SdkHttpError) throw error;
1194
+ const err = error;
1195
+ if (err.name === "AbortError") {
1196
+ throw new SdkHttpError("Request timeout", 408);
1197
+ }
1198
+ throw new SdkHttpError(`Network error: ${err.message}`, 0, error);
1199
+ }
1200
+ }
1201
+ async function upload(path, file, filename, metadata, fieldName = "file") {
1202
+ const url = `${config.baseUrl}${path}`;
1203
+ const controller = new AbortController();
1204
+ const timeoutId = setTimeout(() => controller.abort(), timeout * 2);
1205
+ try {
1206
+ const formData = new FormData();
1207
+ const blob = file instanceof Blob ? file : new Blob([new Uint8Array(file)]);
1208
+ formData.append(fieldName, blob, filename);
1209
+ if (metadata) {
1210
+ for (const [key, value] of Object.entries(metadata)) {
1211
+ formData.append(key, value);
1212
+ }
1213
+ }
1214
+ const headers = {};
1215
+ if (config.authToken) {
1216
+ headers["Authorization"] = `Bearer ${config.authToken}`;
1217
+ }
1218
+ if (config.apiKey) {
1219
+ headers["X-API-Key"] = config.apiKey;
1220
+ }
1221
+ const response = await fetch(url, {
1222
+ method: "POST",
1223
+ headers,
1224
+ body: formData,
1225
+ signal: controller.signal
1226
+ });
1227
+ clearTimeout(timeoutId);
1228
+ if (!response.ok) {
1229
+ const errorData = await response.json().catch(() => ({}));
1230
+ throw new SdkHttpError(
1231
+ errorData.message || `Upload error: ${response.status} ${response.statusText}`,
1232
+ response.status,
1233
+ errorData
1234
+ );
1235
+ }
1236
+ return response.json();
1237
+ } catch (error) {
1238
+ clearTimeout(timeoutId);
1239
+ if (error instanceof SdkHttpError) throw error;
1240
+ const err = error;
1241
+ if (err.name === "AbortError") {
1242
+ throw new SdkHttpError("Upload timeout", 408);
1243
+ }
1244
+ throw new SdkHttpError(`Upload error: ${err.message}`, 0, error);
1245
+ }
1246
+ }
1247
+ const client = {
1248
+ post: (path, body) => request("POST", path, body),
1249
+ get: (path) => request("GET", path),
1250
+ put: (path, body) => request("PUT", path, body),
1251
+ patch: (path, body) => request("PATCH", path, body),
1252
+ delete: (path) => request("DELETE", path),
1253
+ getText,
1254
+ upload: ((path, file, filename, metadata, fieldName) => upload(path, file, filename, metadata, fieldName)),
1255
+ setAuthToken,
1256
+ getAuthToken
1257
+ };
1258
+ return client;
1259
+ }
1260
+ function encodePathParam(param) {
1261
+ return encodeURIComponent(param).replace(/%2F/gi, "");
1262
+ }
1263
+
1103
1264
  // src/discovery/discovery-client.ts
1104
1265
  var DiscoveryClient = class {
1105
1266
  constructor(http) {
@@ -1133,7 +1294,7 @@ var DiscoveryClient = class {
1133
1294
  * try/catch.
1134
1295
  */
1135
1296
  async getClusterByNode(nodeId) {
1136
- return this.http.get(`/discovery/clusters/${encodeURIComponent(nodeId)}`);
1297
+ return this.http.get(`/discovery/clusters/${encodePathParam(nodeId)}`);
1137
1298
  }
1138
1299
  };
1139
1300
  var PlatformImagesClient = class {
@@ -1163,7 +1324,7 @@ var PlatformImagesClient = class {
1163
1324
  * authorized?" queries.
1164
1325
  */
1165
1326
  async get(imageName) {
1166
- return this.http.get(`/discovery/platform-images/${encodeURIComponent(imageName)}`);
1327
+ return this.http.get(`/discovery/platform-images/${encodePathParam(imageName)}`);
1167
1328
  }
1168
1329
  /**
1169
1330
  * `GET /api/v3/discovery/platform-images/:imageName/:version` —
@@ -1172,7 +1333,7 @@ var PlatformImagesClient = class {
1172
1333
  */
1173
1334
  async getVersion(imageName, version) {
1174
1335
  return this.http.get(
1175
- `/discovery/platform-images/${encodeURIComponent(imageName)}/${encodeURIComponent(version)}`
1336
+ `/discovery/platform-images/${encodePathParam(imageName)}/${encodePathParam(version)}`
1176
1337
  );
1177
1338
  }
1178
1339
  /**
@@ -1186,13 +1347,63 @@ var PlatformImagesClient = class {
1186
1347
  */
1187
1348
  async verify(imageName, version, digest) {
1188
1349
  return this.http.get(
1189
- `/discovery/platform-images/${encodeURIComponent(imageName)}/${encodeURIComponent(
1350
+ `/discovery/platform-images/${encodePathParam(imageName)}/${encodePathParam(
1190
1351
  version
1191
1352
  )}/verify?digest=${encodeURIComponent(digest)}`
1192
1353
  );
1193
1354
  }
1194
1355
  };
1195
1356
 
1357
+ // src/network-presets.ts
1358
+ var KNOWN_NETWORKS = {
1359
+ testnet: {
1360
+ bootstrap: ["https://gateway.testnet.hsuite.network"]
1361
+ },
1362
+ mainnet: {
1363
+ // Mainnet entrypoint reserved. The SDK still resolves the name so
1364
+ // upgrade-by-flipping-NETWORK works; the bootstrap URL is the
1365
+ // pre-allocated DNS we own. If mainnet isn't deployed yet, the discovery
1366
+ // fetch will fail at runtime with the same "no seed reachable" error
1367
+ // any unreachable URL produces — the caller learns the network is not
1368
+ // live, rather than getting a baffling "unknown network" TypeScript
1369
+ // error at compile time.
1370
+ bootstrap: ["https://gateway.hsuite.network"]
1371
+ }
1372
+ };
1373
+ function resolveNetwork(name) {
1374
+ const preset = KNOWN_NETWORKS[name];
1375
+ if (!preset) {
1376
+ throw new Error(
1377
+ `Unknown network: "${name}". Known networks: ${Object.keys(KNOWN_NETWORKS).join(", ")}`
1378
+ );
1379
+ }
1380
+ return preset;
1381
+ }
1382
+
1383
+ // src/discovery/resolve-cluster.ts
1384
+ async function resolveClusterEndpoint(config) {
1385
+ const allowInsecure = config.allowInsecure ?? false;
1386
+ const bootstrap = config.bootstrap ? [...config.bootstrap] : config.network ? [...resolveNetwork(config.network).bootstrap] : [];
1387
+ if (bootstrap.length === 0) {
1388
+ return { ok: false, reason: "no-seeds" };
1389
+ }
1390
+ const discovery = new ClusterDiscoveryClient({
1391
+ bootstrap,
1392
+ allowInsecure,
1393
+ trustAnchor: config.trustAnchor ? {
1394
+ network: config.trustAnchor.network,
1395
+ registryTopicId: config.trustAnchor.registryTopicId,
1396
+ mirrorNodeUrl: config.trustAnchor.mirrorNodeUrl,
1397
+ allowInsecure
1398
+ } : void 0
1399
+ });
1400
+ const cluster = await discovery.getRandomCluster();
1401
+ if (!cluster) {
1402
+ return { ok: false, reason: "no-clusters" };
1403
+ }
1404
+ return { ok: true, cluster };
1405
+ }
1406
+
1196
1407
  // src/auth/validator-auth.ts
1197
1408
  var SUPPORTED_AUTH_CHAINS = [
1198
1409
  "hedera",
@@ -1201,6 +1412,10 @@ var SUPPORTED_AUTH_CHAINS = [
1201
1412
  "stellar",
1202
1413
  "solana"
1203
1414
  ];
1415
+ function toBytes(value) {
1416
+ if (value instanceof Uint8Array) return value;
1417
+ return value.toBytes();
1418
+ }
1204
1419
  function validateValidatorUrl(url, allowInsecure = false) {
1205
1420
  try {
1206
1421
  const parsed = new URL(url);
@@ -1400,30 +1615,42 @@ var ValidatorAuthClient = class {
1400
1615
  }
1401
1616
  }
1402
1617
  /**
1403
- * Sign challenge with Hedera private key
1618
+ * Sign challenge with Hedera private key.
1619
+ *
1620
+ * Structurally typed against the surface of `@hashgraph/sdk`'s
1621
+ * `PrivateKey`. We don't `import` the SDK directly — pulling it into
1622
+ * the smart-engine SDK's runtime would bloat browser bundles and bring
1623
+ * peer-dep churn — but any object with a compatible `sign(...)` method
1624
+ * works.
1404
1625
  *
1405
1626
  * @param challenge - Challenge string from validator
1406
- * @param privateKey - Hedera PrivateKey instance from @hashgraph/sdk
1627
+ * @param privateKey - Hedera PrivateKey instance (or compatible signer)
1407
1628
  * @returns Hex-encoded signature
1408
1629
  */
1409
1630
  signChallengeHedera(challenge, privateKey) {
1410
- const messageBytes = Buffer.from(challenge, "utf-8");
1631
+ const messageBytes = new Uint8Array(Buffer.from(challenge, "utf-8"));
1411
1632
  const signature = privateKey.sign(messageBytes);
1412
- return Buffer.from(signature).toString("hex");
1633
+ return Buffer.from(toBytes(signature)).toString("hex");
1413
1634
  }
1414
1635
  /**
1415
- * Sign challenge with XRPL wallet
1636
+ * Sign challenge with XRPL wallet.
1637
+ *
1638
+ * Structurally typed against the surface of xrpl's `Wallet` — see the
1639
+ * comment on {@link HederaSigner} for the "no direct import" rationale.
1640
+ * Accepts both the modern `{ signedTransaction }` envelope and the
1641
+ * legacy bare-string return shape.
1416
1642
  *
1417
1643
  * @param challenge - Challenge string from validator
1418
- * @param wallet - XRPL Wallet instance from xrpl library
1644
+ * @param wallet - XRPL Wallet instance (or compatible signer)
1419
1645
  * @returns Hex-encoded signature
1420
1646
  */
1421
1647
  signChallengeXRPL(challenge, wallet) {
1422
1648
  const signature = wallet.sign(challenge);
1423
- if (typeof signature === "string" && /^[0-9A-Fa-f]+$/.test(signature)) {
1424
- return signature;
1649
+ if (typeof signature === "string") {
1650
+ if (/^[0-9A-Fa-f]+$/.test(signature)) return signature;
1651
+ return Buffer.from(signature).toString("hex");
1425
1652
  }
1426
- return Buffer.from(signature).toString("hex");
1653
+ return signature.signedTransaction;
1427
1654
  }
1428
1655
  /**
1429
1656
  * Complete authentication flow in one call
@@ -1460,189 +1687,6 @@ var ValidatorAuthError = class extends Error {
1460
1687
  details;
1461
1688
  };
1462
1689
 
1463
- // src/http/index.ts
1464
- var SdkHttpError = class extends Error {
1465
- constructor(message, statusCode, details) {
1466
- super(message);
1467
- this.statusCode = statusCode;
1468
- this.details = details;
1469
- this.name = "SdkHttpError";
1470
- }
1471
- statusCode;
1472
- details;
1473
- };
1474
- function createHttpClient(config) {
1475
- const timeout = config.timeout ?? 3e4;
1476
- function getHeaders(contentType) {
1477
- const headers = {};
1478
- if (contentType) {
1479
- headers["Content-Type"] = contentType;
1480
- }
1481
- if (config.authToken) {
1482
- headers["Authorization"] = `Bearer ${config.authToken}`;
1483
- }
1484
- if (config.apiKey) {
1485
- headers["X-API-Key"] = config.apiKey;
1486
- }
1487
- return headers;
1488
- }
1489
- function setAuthToken(token) {
1490
- config.authToken = token;
1491
- }
1492
- async function request(method, path, body) {
1493
- const url = `${config.baseUrl}${path}`;
1494
- const controller = new AbortController();
1495
- const timeoutId = setTimeout(() => controller.abort(), timeout);
1496
- try {
1497
- const init = {
1498
- method,
1499
- headers: getHeaders("application/json"),
1500
- signal: controller.signal
1501
- };
1502
- if (body !== void 0) {
1503
- init.body = JSON.stringify(body);
1504
- }
1505
- const response = await fetch(url, init);
1506
- clearTimeout(timeoutId);
1507
- if (!response.ok) {
1508
- const errorData = await response.json().catch(() => ({}));
1509
- throw new SdkHttpError(
1510
- errorData.message || `API error: ${response.status} ${response.statusText}`,
1511
- response.status,
1512
- errorData
1513
- );
1514
- }
1515
- const text = await response.text();
1516
- if (!text) return void 0;
1517
- return JSON.parse(text);
1518
- } catch (error) {
1519
- clearTimeout(timeoutId);
1520
- if (error instanceof SdkHttpError) throw error;
1521
- const err = error;
1522
- if (err.name === "AbortError") {
1523
- throw new SdkHttpError("Request timeout", 408);
1524
- }
1525
- throw new SdkHttpError(`Network error: ${err.message}`, 0, error);
1526
- }
1527
- }
1528
- async function getText(path) {
1529
- const url = `${config.baseUrl}${path}`;
1530
- const controller = new AbortController();
1531
- const timeoutId = setTimeout(() => controller.abort(), timeout);
1532
- try {
1533
- const response = await fetch(url, {
1534
- method: "GET",
1535
- headers: getHeaders(),
1536
- signal: controller.signal
1537
- });
1538
- clearTimeout(timeoutId);
1539
- if (!response.ok) {
1540
- const errBody = await response.json().catch(() => ({}));
1541
- throw new SdkHttpError(
1542
- errBody.message || `API error: ${response.status} ${response.statusText}`,
1543
- response.status,
1544
- errBody
1545
- );
1546
- }
1547
- return await response.text();
1548
- } catch (error) {
1549
- clearTimeout(timeoutId);
1550
- if (error instanceof SdkHttpError) throw error;
1551
- const err = error;
1552
- if (err.name === "AbortError") {
1553
- throw new SdkHttpError("Request timeout", 408);
1554
- }
1555
- throw new SdkHttpError(`Network error: ${err.message}`, 0, error);
1556
- }
1557
- }
1558
- async function upload(path, file, filename, metadata, fieldName = "file") {
1559
- const url = `${config.baseUrl}${path}`;
1560
- const controller = new AbortController();
1561
- const timeoutId = setTimeout(() => controller.abort(), timeout * 2);
1562
- try {
1563
- const formData = new FormData();
1564
- const blob = file instanceof Blob ? file : new Blob([new Uint8Array(file)]);
1565
- formData.append(fieldName, blob, filename);
1566
- if (metadata) {
1567
- for (const [key, value] of Object.entries(metadata)) {
1568
- formData.append(key, value);
1569
- }
1570
- }
1571
- const headers = {};
1572
- if (config.authToken) {
1573
- headers["Authorization"] = `Bearer ${config.authToken}`;
1574
- }
1575
- if (config.apiKey) {
1576
- headers["X-API-Key"] = config.apiKey;
1577
- }
1578
- const response = await fetch(url, {
1579
- method: "POST",
1580
- headers,
1581
- body: formData,
1582
- signal: controller.signal
1583
- });
1584
- clearTimeout(timeoutId);
1585
- if (!response.ok) {
1586
- const errorData = await response.json().catch(() => ({}));
1587
- throw new SdkHttpError(
1588
- errorData.message || `Upload error: ${response.status} ${response.statusText}`,
1589
- response.status,
1590
- errorData
1591
- );
1592
- }
1593
- return response.json();
1594
- } catch (error) {
1595
- clearTimeout(timeoutId);
1596
- if (error instanceof SdkHttpError) throw error;
1597
- const err = error;
1598
- if (err.name === "AbortError") {
1599
- throw new SdkHttpError("Upload timeout", 408);
1600
- }
1601
- throw new SdkHttpError(`Upload error: ${err.message}`, 0, error);
1602
- }
1603
- }
1604
- const client = {
1605
- post: (path, body) => request("POST", path, body),
1606
- get: (path) => request("GET", path),
1607
- put: (path, body) => request("PUT", path, body),
1608
- patch: (path, body) => request("PATCH", path, body),
1609
- delete: (path) => request("DELETE", path),
1610
- getText,
1611
- upload: ((path, file, filename, metadata, fieldName) => upload(path, file, filename, metadata, fieldName)),
1612
- setAuthToken
1613
- };
1614
- return client;
1615
- }
1616
- function encodePathParam(param) {
1617
- return encodeURIComponent(param).replace(/%2F/gi, "");
1618
- }
1619
-
1620
- // src/network-presets.ts
1621
- var KNOWN_NETWORKS = {
1622
- testnet: {
1623
- bootstrap: ["https://gateway.testnet.hsuite.network"]
1624
- },
1625
- mainnet: {
1626
- // Mainnet entrypoint reserved. The SDK still resolves the name so
1627
- // upgrade-by-flipping-NETWORK works; the bootstrap URL is the
1628
- // pre-allocated DNS we own. If mainnet isn't deployed yet, the discovery
1629
- // fetch will fail at runtime with the same "no seed reachable" error
1630
- // any unreachable URL produces — the caller learns the network is not
1631
- // live, rather than getting a baffling "unknown network" TypeScript
1632
- // error at compile time.
1633
- bootstrap: ["https://gateway.hsuite.network"]
1634
- }
1635
- };
1636
- function resolveNetwork(name) {
1637
- const preset = KNOWN_NETWORKS[name];
1638
- if (!preset) {
1639
- throw new Error(
1640
- `Unknown network: "${name}". Known networks: ${Object.keys(KNOWN_NETWORKS).join(", ")}`
1641
- );
1642
- }
1643
- return preset;
1644
- }
1645
-
1646
1690
  // src/subscription/index.ts
1647
1691
  var SubscriptionClient = class {
1648
1692
  constructor(http) {
@@ -1660,13 +1704,13 @@ var SubscriptionClient = class {
1660
1704
  * Get subscription status by app ID
1661
1705
  */
1662
1706
  async getStatus(appId) {
1663
- return this.http.get(`/subscription/status/${encodeURIComponent(appId)}`);
1707
+ return this.http.get(`/subscription/status/${encodePathParam(appId)}`);
1664
1708
  }
1665
1709
  /**
1666
1710
  * Mint subscription NFT after deposit is confirmed
1667
1711
  */
1668
1712
  async mintNft(appId) {
1669
- return this.http.post(`/subscription/mint/${encodeURIComponent(appId)}`, {});
1713
+ return this.http.post(`/subscription/mint/${encodePathParam(appId)}`, {});
1670
1714
  }
1671
1715
  /**
1672
1716
  * Renew subscription by extending period
@@ -1735,13 +1779,13 @@ var SubscriptionClient = class {
1735
1779
  * List subscriptions by status
1736
1780
  */
1737
1781
  async listByStatus(status) {
1738
- return this.http.get(`/subscription/list/status/${encodeURIComponent(status)}`);
1782
+ return this.http.get(`/subscription/list/status/${encodePathParam(status)}`);
1739
1783
  }
1740
1784
  /**
1741
1785
  * Get subscription balance
1742
1786
  */
1743
1787
  async getBalance(appId) {
1744
- return this.http.get(`/subscription/balance/${encodeURIComponent(appId)}`);
1788
+ return this.http.get(`/subscription/balance/${encodePathParam(appId)}`);
1745
1789
  }
1746
1790
  // ─── Tier-Change Endpoints ────────────────────────────────────────────────
1747
1791
  /**
@@ -1773,19 +1817,19 @@ var SubscriptionClient = class {
1773
1817
  */
1774
1818
  async getActiveFor(walletAddress) {
1775
1819
  return this.http.get(
1776
- `/subscription/active-for/${encodeURIComponent(walletAddress)}`
1820
+ `/subscription/active-for/${encodePathParam(walletAddress)}`
1777
1821
  );
1778
1822
  }
1779
1823
  /** Today's consumption breakdown by category for an app. Owner-only. */
1780
1824
  async getUsage(appId) {
1781
- return this.http.get(`/subscription/usage/${encodeURIComponent(appId)}`);
1825
+ return this.http.get(`/subscription/usage/${encodePathParam(appId)}`);
1782
1826
  }
1783
1827
  /**
1784
1828
  * Current usage with overage info: usage percent, grace status,
1785
1829
  * upgrade suggestion, projected days until limit. Owner-only.
1786
1830
  */
1787
1831
  async getUsageStatus(appId) {
1788
- return this.http.get(`/subscription/usage/status/${encodeURIComponent(appId)}`);
1832
+ return this.http.get(`/subscription/usage/status/${encodePathParam(appId)}`);
1789
1833
  }
1790
1834
  /**
1791
1835
  * Subscription balance deduction history. Pagination + ISO-8601 range
@@ -1799,7 +1843,7 @@ var SubscriptionClient = class {
1799
1843
  if (options?.to) params.append("to", options.to);
1800
1844
  const qs = params.toString();
1801
1845
  return this.http.get(
1802
- `/subscription/billing/${encodeURIComponent(appId)}${qs ? `?${qs}` : ""}`
1846
+ `/subscription/billing/${encodePathParam(appId)}${qs ? `?${qs}` : ""}`
1803
1847
  );
1804
1848
  }
1805
1849
  /**
@@ -1842,7 +1886,7 @@ var TSSClient = class {
1842
1886
  * Get entity details by ID
1843
1887
  */
1844
1888
  async getEntity(entityId) {
1845
- return this.http.get(`/tss/entity/${encodeURIComponent(entityId)}`);
1889
+ return this.http.get(`/tss/entity/${encodePathParam(entityId)}`);
1846
1890
  }
1847
1891
  /**
1848
1892
  * Sign a transaction using MPC.
@@ -1899,7 +1943,7 @@ var TSSClient = class {
1899
1943
  * Get multi-sig transaction status by transaction ID
1900
1944
  */
1901
1945
  async getMultiSigStatus(txId) {
1902
- return this.http.get(`/tss/multisig/transactions/${encodeURIComponent(txId)}`);
1946
+ return this.http.get(`/tss/multisig/transactions/${encodePathParam(txId)}`);
1903
1947
  }
1904
1948
  /**
1905
1949
  * Async-job variant of {@link createEntity}.
@@ -1923,7 +1967,7 @@ var TSSClient = class {
1923
1967
  * {@link createEntityAsync} or {@link reshareClusterAsync}.
1924
1968
  */
1925
1969
  async getJob(jobId) {
1926
- return this.http.get(`/tss/jobs/${encodeURIComponent(jobId)}`);
1970
+ return this.http.get(`/tss/jobs/${encodePathParam(jobId)}`);
1927
1971
  }
1928
1972
  /**
1929
1973
  * Sign a hex payload as smart-app entity `appId` via the cluster's TSS
@@ -1935,7 +1979,7 @@ var TSSClient = class {
1935
1979
  * - ≥32 bytes, ≤8KB
1936
1980
  */
1937
1981
  async signForApp(appId, request) {
1938
- return this.http.post(`/tss/entity/${encodeURIComponent(appId)}/sign`, request);
1982
+ return this.http.post(`/tss/entity/${encodePathParam(appId)}/sign`, request);
1939
1983
  }
1940
1984
  };
1941
1985
 
@@ -1960,31 +2004,31 @@ var IPFSClient = class {
1960
2004
  * Pin content by CID to ensure it persists
1961
2005
  */
1962
2006
  async pin(cid) {
1963
- return this.http.post(`/ipfs/pin/${encodeURIComponent(cid)}`, {});
2007
+ return this.http.post(`/ipfs/pin/${encodePathParam(cid)}`, {});
1964
2008
  }
1965
2009
  /**
1966
2010
  * Unpin content by CID
1967
2011
  */
1968
2012
  async unpin(cid) {
1969
- return this.http.delete(`/ipfs/unpin/${encodeURIComponent(cid)}`);
2013
+ return this.http.delete(`/ipfs/unpin/${encodePathParam(cid)}`);
1970
2014
  }
1971
2015
  /**
1972
2016
  * Get a file by CID
1973
2017
  */
1974
2018
  async getFile(cid) {
1975
- return this.http.get(`/ipfs/file/${encodeURIComponent(cid)}`);
2019
+ return this.http.get(`/ipfs/file/${encodePathParam(cid)}`);
1976
2020
  }
1977
2021
  /**
1978
2022
  * Get raw content by CID
1979
2023
  */
1980
2024
  async getContent(cid) {
1981
- return this.http.get(`/ipfs/${encodeURIComponent(cid)}`);
2025
+ return this.http.get(`/ipfs/${encodePathParam(cid)}`);
1982
2026
  }
1983
2027
  /**
1984
2028
  * Get file metadata by CID
1985
2029
  */
1986
2030
  async getMetadata(cid) {
1987
- return this.http.get(`/ipfs/metadata/${encodeURIComponent(cid)}`);
2031
+ return this.http.get(`/ipfs/metadata/${encodePathParam(cid)}`);
1988
2032
  }
1989
2033
  /**
1990
2034
  * List all pinned content
@@ -2042,7 +2086,7 @@ var HederaTssClient = class {
2042
2086
  var HederaTransactionsClient = class {
2043
2087
  constructor(http, tssHttp) {
2044
2088
  this.http = http;
2045
- this.tss = new HederaTssClient(tssHttp ?? http);
2089
+ this.tss = new HederaTssClient(tssHttp);
2046
2090
  }
2047
2091
  http;
2048
2092
  /**
@@ -2053,10 +2097,10 @@ var HederaTransactionsClient = class {
2053
2097
  * - `client.hedera.tss.createTopic(...)` makes the cluster sign+submit in one call.
2054
2098
  *
2055
2099
  * `tssHttp` is the validator's `/api/v3`-rooted HTTP client (different from
2056
- * the `/api/transactions` one this class uses for prepare paths). When the
2057
- * legacy single-arg constructor is used (no tssHttp passed), `tss` falls
2058
- * back to the same `http` instance for backwards compatibility — callers
2059
- * outside `SmartEngineClient` rarely use the TSS surface.
2100
+ * the `/api/transactions` one this class uses for prepare paths). Both
2101
+ * clients are required the previous single-arg fallback to `http` was
2102
+ * unreachable through `SmartEngineClient` (the only call site always
2103
+ * passes both).
2060
2104
  */
2061
2105
  tss;
2062
2106
  /** Prepare an HCS topic creation transaction. */
@@ -2237,7 +2281,7 @@ var SnapshotsClient = class {
2237
2281
  */
2238
2282
  async generate(tokenId, options) {
2239
2283
  return this.http.post(
2240
- `/snapshots/generate/${encodeURIComponent(tokenId)}`,
2284
+ `/snapshots/generate/${encodePathParam(tokenId)}`,
2241
2285
  options || {}
2242
2286
  );
2243
2287
  }
@@ -2245,7 +2289,7 @@ var SnapshotsClient = class {
2245
2289
  * Get snapshot details by ID
2246
2290
  */
2247
2291
  async get(snapshotId) {
2248
- return this.http.get(`/snapshots/${encodeURIComponent(snapshotId)}`);
2292
+ return this.http.get(`/snapshots/${encodePathParam(snapshotId)}`);
2249
2293
  }
2250
2294
  /**
2251
2295
  * List snapshots for a token
@@ -2256,7 +2300,7 @@ var SnapshotsClient = class {
2256
2300
  if (pagination?.limit !== void 0) params.set("limit", String(pagination.limit));
2257
2301
  const qs = params.toString();
2258
2302
  return this.http.get(
2259
- `/snapshots/token/${encodeURIComponent(tokenId)}${qs ? `?${qs}` : ""}`
2303
+ `/snapshots/token/${encodePathParam(tokenId)}${qs ? `?${qs}` : ""}`
2260
2304
  );
2261
2305
  }
2262
2306
  /**
@@ -2268,7 +2312,7 @@ var SnapshotsClient = class {
2268
2312
  async download(snapshotId, format) {
2269
2313
  const params = format ? `?format=${encodeURIComponent(format)}` : "";
2270
2314
  return this.http.get(
2271
- `/snapshots/${encodeURIComponent(snapshotId)}/download${params}`
2315
+ `/snapshots/${encodePathParam(snapshotId)}/download${params}`
2272
2316
  );
2273
2317
  }
2274
2318
  };
@@ -2451,20 +2495,20 @@ var SettlementClient = class {
2451
2495
  * Get the current status of a settlement by ID.
2452
2496
  */
2453
2497
  async getStatus(settlementId) {
2454
- return this.http.get(`/settlement/${encodeURIComponent(settlementId)}/status`);
2498
+ return this.http.get(`/settlement/${encodePathParam(settlementId)}/status`);
2455
2499
  }
2456
2500
  /**
2457
2501
  * Confirm that XRP has landed on the destination address.
2458
2502
  * Advances the settlement to the next processing step.
2459
2503
  */
2460
2504
  async confirmXrpLanded(settlementId) {
2461
- return this.http.post(`/settlement/${encodeURIComponent(settlementId)}/confirm-xrp`, {});
2505
+ return this.http.post(`/settlement/${encodePathParam(settlementId)}/confirm-xrp`, {});
2462
2506
  }
2463
2507
  /**
2464
2508
  * Get settlement history for a given entity.
2465
2509
  */
2466
2510
  async getHistory(entityId) {
2467
- return this.http.get(`/settlement/history/${encodeURIComponent(entityId)}`);
2511
+ return this.http.get(`/settlement/history/${encodePathParam(entityId)}`);
2468
2512
  }
2469
2513
  };
2470
2514
 
@@ -2507,39 +2551,39 @@ var DaoDashboardClient = class {
2507
2551
  /** Aggregated dashboard counters for a user's governance home screen. */
2508
2552
  async getStats(userAddress) {
2509
2553
  return this.http.get(
2510
- `/dao/dashboard/stats/${encodeURIComponent(userAddress)}`
2554
+ `/dao/dashboard/stats/${encodePathParam(userAddress)}`
2511
2555
  );
2512
2556
  }
2513
2557
  /** Active proposals across every DAO the user belongs to, with vote state. */
2514
2558
  async getActiveProposals(userAddress) {
2515
2559
  return this.http.get(
2516
- `/dao/dashboard/active-proposals/${encodeURIComponent(userAddress)}`
2560
+ `/dao/dashboard/active-proposals/${encodePathParam(userAddress)}`
2517
2561
  );
2518
2562
  }
2519
2563
  /** Paginated vote history across DAOs. */
2520
2564
  async getVoteHistory(userAddress, opts = {}) {
2521
2565
  const qs = buildQuery({ limit: opts.limit, offset: opts.offset });
2522
2566
  return this.http.get(
2523
- `/dao/dashboard/vote-history/${encodeURIComponent(userAddress)}${qs}`
2567
+ `/dao/dashboard/vote-history/${encodePathParam(userAddress)}${qs}`
2524
2568
  );
2525
2569
  }
2526
2570
  /** Activity feed (proposal-created/vote-cast/etc.) across user's DAOs. */
2527
2571
  async getActivity(userAddress, opts = {}) {
2528
2572
  const qs = buildQuery({ limit: opts.limit, daoId: opts.daoId });
2529
2573
  return this.http.get(
2530
- `/dao/dashboard/activity/${encodeURIComponent(userAddress)}${qs}`
2574
+ `/dao/dashboard/activity/${encodePathParam(userAddress)}${qs}`
2531
2575
  );
2532
2576
  }
2533
2577
  /** Items the user must act on (sign prepared messages, claim NFTs, …). */
2534
2578
  async getPendingActions(userAddress) {
2535
2579
  return this.http.get(
2536
- `/dao/dashboard/pending-actions/${encodeURIComponent(userAddress)}`
2580
+ `/dao/dashboard/pending-actions/${encodePathParam(userAddress)}`
2537
2581
  );
2538
2582
  }
2539
2583
  /** Governance impact metrics — weight delivered, success rate, streak. */
2540
2584
  async getImpact(userAddress) {
2541
2585
  return this.http.get(
2542
- `/dao/dashboard/impact/${encodeURIComponent(userAddress)}`
2586
+ `/dao/dashboard/impact/${encodePathParam(userAddress)}`
2543
2587
  );
2544
2588
  }
2545
2589
  };
@@ -2555,13 +2599,13 @@ function buildQuery2(params) {
2555
2599
  return qs ? `?${qs}` : "";
2556
2600
  }
2557
2601
  function encodeDaoId(daoId) {
2558
- return encodeURIComponent(daoId);
2602
+ return encodePathParam(daoId);
2559
2603
  }
2560
2604
  function encodeProposalId(proposalId) {
2561
- return encodeURIComponent(proposalId);
2605
+ return encodePathParam(proposalId);
2562
2606
  }
2563
2607
  function encodeAddress(address) {
2564
- return encodeURIComponent(address);
2608
+ return encodePathParam(address);
2565
2609
  }
2566
2610
  var DaoClient = class {
2567
2611
  constructor(http) {
@@ -2767,7 +2811,7 @@ var AgentsClient = class {
2767
2811
  }
2768
2812
  /** Get agent details */
2769
2813
  async get(agentId) {
2770
- return this.http.get(`/api/agents/${encodeURIComponent(agentId)}`);
2814
+ return this.http.get(`/api/agents/${encodePathParam(agentId)}`);
2771
2815
  }
2772
2816
  /** List all agents */
2773
2817
  async list() {
@@ -2779,33 +2823,33 @@ var AgentsClient = class {
2779
2823
  * the caller is expected to sign and submit the prepared bytes.
2780
2824
  */
2781
2825
  async fund(agentId, request) {
2782
- return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/fund`, request);
2826
+ return this.http.post(`/api/agents/${encodePathParam(agentId)}/fund`, request);
2783
2827
  }
2784
2828
  /**
2785
2829
  * Execute a trade (agent-wallet OR owner). Returns a
2786
2830
  * `PreparedTransactionResponse` wrapped in a `success: true` envelope.
2787
2831
  */
2788
2832
  async trade(agentId, request) {
2789
- return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/trade`, request);
2833
+ return this.http.post(`/api/agents/${encodePathParam(agentId)}/trade`, request);
2790
2834
  }
2791
2835
  /**
2792
2836
  * Withdraw from agent treasury (owner-only). Returns a
2793
2837
  * `PreparedTransactionResponse` wrapped in a `success: true` envelope.
2794
2838
  */
2795
2839
  async withdraw(agentId, request) {
2796
- return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/withdraw`, request);
2840
+ return this.http.post(`/api/agents/${encodePathParam(agentId)}/withdraw`, request);
2797
2841
  }
2798
2842
  /** Pause an agent */
2799
2843
  async pause(agentId) {
2800
- return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/pause`, {});
2844
+ return this.http.post(`/api/agents/${encodePathParam(agentId)}/pause`, {});
2801
2845
  }
2802
2846
  /** Resume a paused agent */
2803
2847
  async resume(agentId) {
2804
- return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/resume`, {});
2848
+ return this.http.post(`/api/agents/${encodePathParam(agentId)}/resume`, {});
2805
2849
  }
2806
2850
  /** Revoke an agent (permanent) */
2807
2851
  async revoke(agentId) {
2808
- return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/revoke`, {});
2852
+ return this.http.post(`/api/agents/${encodePathParam(agentId)}/revoke`, {});
2809
2853
  }
2810
2854
  /**
2811
2855
  * Update agent rules.
@@ -2816,23 +2860,23 @@ var AgentsClient = class {
2816
2860
  * the verb mismatch.
2817
2861
  */
2818
2862
  async updateRules(agentId, rules) {
2819
- return this.http.patch(`/api/agents/${encodeURIComponent(agentId)}/rules`, rules);
2863
+ return this.http.patch(`/api/agents/${encodePathParam(agentId)}/rules`, rules);
2820
2864
  }
2821
2865
  /** Get agent events */
2822
2866
  async getEvents(agentId) {
2823
- return this.http.get(`/api/agents/${encodeURIComponent(agentId)}/events`);
2867
+ return this.http.get(`/api/agents/${encodePathParam(agentId)}/events`);
2824
2868
  }
2825
2869
  /** Get agent balances across chains */
2826
2870
  async getBalances(agentId) {
2827
- return this.http.get(`/api/agents/${encodeURIComponent(agentId)}/balances`);
2871
+ return this.http.get(`/api/agents/${encodePathParam(agentId)}/balances`);
2828
2872
  }
2829
2873
  /** Approve a pending agent operation */
2830
2874
  async approve(agentId, operationId) {
2831
- return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/approve/${encodeURIComponent(operationId)}`, {});
2875
+ return this.http.post(`/api/agents/${encodePathParam(agentId)}/approve/${encodePathParam(operationId)}`, {});
2832
2876
  }
2833
2877
  /** Reject a pending agent operation */
2834
2878
  async reject(agentId, operationId) {
2835
- return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/reject/${encodeURIComponent(operationId)}`, {});
2879
+ return this.http.post(`/api/agents/${encodePathParam(agentId)}/reject/${encodePathParam(operationId)}`, {});
2836
2880
  }
2837
2881
  };
2838
2882
 
@@ -2871,7 +2915,7 @@ var DeploymentClient = class {
2871
2915
  */
2872
2916
  async uploadFrontend(appId, bundle, filename = "bundle.tar.gz") {
2873
2917
  return this.http.upload(
2874
- `/api/deployment/apps/${encodeURIComponent(appId)}/frontend`,
2918
+ `/api/deployment/apps/${encodePathParam(appId)}/frontend`,
2875
2919
  bundle,
2876
2920
  filename,
2877
2921
  void 0,
@@ -2885,20 +2929,20 @@ var DeploymentClient = class {
2885
2929
  * until `runtime.runtimeState === 'RUNNING'` for the URL to be live.
2886
2930
  */
2887
2931
  async deploy(appId, request) {
2888
- return this.http.post(`/api/deployment/apps/${encodeURIComponent(appId)}/deploy`, request);
2932
+ return this.http.post(`/api/deployment/apps/${encodePathParam(appId)}/deploy`, request);
2889
2933
  }
2890
2934
  /**
2891
2935
  * Roll back to a previously-deployed image tag (must exist in
2892
2936
  * `runtime.deploymentHistory[]`).
2893
2937
  */
2894
2938
  async rollback(appId, request) {
2895
- return this.http.post(`/api/deployment/apps/${encodeURIComponent(appId)}/rollback`, request);
2939
+ return this.http.post(`/api/deployment/apps/${encodePathParam(appId)}/rollback`, request);
2896
2940
  }
2897
2941
  /**
2898
2942
  * Live combined lifecycle + runtime status of an app.
2899
2943
  */
2900
2944
  async status(appId) {
2901
- return this.http.get(`/api/deployment/apps/${encodeURIComponent(appId)}/status`);
2945
+ return this.http.get(`/api/deployment/apps/${encodePathParam(appId)}/status`);
2902
2946
  }
2903
2947
  /**
2904
2948
  * List all deployed apps for the authenticated developer.
@@ -2910,31 +2954,31 @@ var DeploymentClient = class {
2910
2954
  * Get app details.
2911
2955
  */
2912
2956
  async get(appId) {
2913
- return this.http.get(`/api/deployment/apps/${encodeURIComponent(appId)}`);
2957
+ return this.http.get(`/api/deployment/apps/${encodePathParam(appId)}`);
2914
2958
  }
2915
2959
  /**
2916
2960
  * Update app configuration. Runtime effect lands in PR-H.
2917
2961
  */
2918
2962
  async update(appId, updates) {
2919
- return this.http.put(`/api/deployment/apps/${encodeURIComponent(appId)}`, updates);
2963
+ return this.http.put(`/api/deployment/apps/${encodePathParam(appId)}`, updates);
2920
2964
  }
2921
2965
  /**
2922
2966
  * Delete an app. Runtime effect (namespace teardown) lands in PR-H.
2923
2967
  */
2924
2968
  async delete(appId) {
2925
- return this.http.delete(`/api/deployment/apps/${encodeURIComponent(appId)}`);
2969
+ return this.http.delete(`/api/deployment/apps/${encodePathParam(appId)}`);
2926
2970
  }
2927
2971
  /**
2928
2972
  * Suspend an app. Runtime effect (scale to zero) lands in PR-H.
2929
2973
  */
2930
2974
  async suspend(appId) {
2931
- return this.http.post(`/api/deployment/apps/${encodeURIComponent(appId)}/suspend`, {});
2975
+ return this.http.post(`/api/deployment/apps/${encodePathParam(appId)}/suspend`, {});
2932
2976
  }
2933
2977
  /**
2934
2978
  * Resume a suspended app. Runtime effect (scale back up) lands in PR-H.
2935
2979
  */
2936
2980
  async resume(appId) {
2937
- return this.http.post(`/api/deployment/apps/${encodeURIComponent(appId)}/resume`, {});
2981
+ return this.http.post(`/api/deployment/apps/${encodePathParam(appId)}/resume`, {});
2938
2982
  }
2939
2983
  /**
2940
2984
  * Get deployment statistics.
@@ -2961,7 +3005,7 @@ var DeploymentClient = class {
2961
3005
  * CGNAT / cloud metadata destinations (SSRF guard).
2962
3006
  */
2963
3007
  async setWebhook(appId, webhookUrl) {
2964
- return this.http.put(`/api/deployment/apps/${encodeURIComponent(appId)}/webhook`, {
3008
+ return this.http.put(`/api/deployment/apps/${encodePathParam(appId)}/webhook`, {
2965
3009
  webhookUrl
2966
3010
  });
2967
3011
  }
@@ -2977,7 +3021,7 @@ var DeploymentClient = class {
2977
3021
  * exposition format.
2978
3022
  */
2979
3023
  async getMetrics(appId) {
2980
- return this.http.getText(`/api/deployment/apps/${encodeURIComponent(appId)}/metrics`);
3024
+ return this.http.getText(`/api/deployment/apps/${encodePathParam(appId)}/metrics`);
2981
3025
  }
2982
3026
  /**
2983
3027
  * Rotate the smart-app's tenant-secret KEK (ADR-011 Phase 6).
@@ -2988,7 +3032,7 @@ var DeploymentClient = class {
2988
3032
  */
2989
3033
  async rotateKek(appId) {
2990
3034
  return this.http.post(
2991
- `/api/deployment/apps/${encodeURIComponent(appId)}/credentials/rotate-kek`,
3035
+ `/api/deployment/apps/${encodePathParam(appId)}/credentials/rotate-kek`,
2992
3036
  {}
2993
3037
  );
2994
3038
  }
@@ -3002,7 +3046,7 @@ var DeploymentClient = class {
3002
3046
  */
3003
3047
  async revokeKek(appId, version) {
3004
3048
  return this.http.post(
3005
- `/api/deployment/apps/${encodeURIComponent(appId)}/credentials/revoke-kek`,
3049
+ `/api/deployment/apps/${encodePathParam(appId)}/credentials/revoke-kek`,
3006
3050
  { version }
3007
3051
  );
3008
3052
  }
@@ -3182,16 +3226,6 @@ var TokensClient = class {
3182
3226
  async getMigrationsForToken(tokenId) {
3183
3227
  return this.http.get(`/tokens/${encodePathParam(tokenId)}/migrations`);
3184
3228
  }
3185
- /**
3186
- * Get token details. NOTE: collides with `client.getTokenInfo(...)` —
3187
- * see the class JSDoc above for the route-order details. Prefer
3188
- * `client.getTokenInfo(...)` unless you have a reason to call this one.
3189
- */
3190
- async getDetails(chain, tokenId) {
3191
- return this.http.get(
3192
- `/tokens/${encodePathParam(chain)}/${encodePathParam(tokenId)}`
3193
- );
3194
- }
3195
3229
  };
3196
3230
 
3197
3231
  // src/operator/operator-client.ts
@@ -3418,30 +3452,25 @@ var SmartEngineClient = class _SmartEngineClient {
3418
3452
  */
3419
3453
  static async connectToCluster(config) {
3420
3454
  const allowInsecure = config.allowInsecure ?? false;
3421
- const bootstrap = config.bootstrap ? [...config.bootstrap] : [...resolveNetwork(config.network).bootstrap];
3422
- if (bootstrap.length === 0) {
3423
- throw new SmartEngineError(
3424
- "connectToCluster requires either a non-empty `bootstrap` list or a known `network` name.",
3425
- 400
3426
- );
3427
- }
3428
- const discovery = new ClusterDiscoveryClient({
3429
- bootstrap,
3455
+ const resolved = await resolveClusterEndpoint({
3456
+ bootstrap: config.bootstrap,
3457
+ network: config.network,
3430
3458
  allowInsecure,
3431
- trustAnchor: config.trustAnchor ? {
3432
- network: config.trustAnchor.network,
3433
- registryTopicId: config.trustAnchor.registryTopicId,
3434
- mirrorNodeUrl: config.trustAnchor.mirrorNodeUrl,
3435
- allowInsecure
3436
- } : void 0
3459
+ trustAnchor: config.trustAnchor
3437
3460
  });
3438
- const cluster = await discovery.getRandomCluster();
3439
- if (!cluster) {
3461
+ if (!resolved.ok) {
3462
+ if (resolved.reason === "no-seeds") {
3463
+ throw new SmartEngineError(
3464
+ "connectToCluster requires either a non-empty `bootstrap` list or a known `network` name.",
3465
+ 400
3466
+ );
3467
+ }
3440
3468
  throw new SmartEngineError(
3441
3469
  "No active clusters available via bootstrap seeds. Check bootstrap URLs and network reachability.",
3442
3470
  503
3443
3471
  );
3444
3472
  }
3473
+ const cluster = resolved.cluster;
3445
3474
  const gatewayUrl = cluster.endpoints.gatewayUrl;
3446
3475
  validateClientUrl(gatewayUrl, allowInsecure);
3447
3476
  const auth = new ValidatorAuthClient({ security: { allowInsecure } });
@@ -3466,7 +3495,7 @@ var SmartEngineClient = class _SmartEngineClient {
3466
3495
  }
3467
3496
  /** Check if client has an auth token */
3468
3497
  isAuthenticated() {
3469
- return !!this.http.authToken;
3498
+ return this.http.getAuthToken() !== void 0;
3470
3499
  }
3471
3500
  /**
3472
3501
  * Get HTTP resilience health information
@@ -3697,7 +3726,7 @@ var RoutingClient = class {
3697
3726
  }
3698
3727
  /** Unregister a host. */
3699
3728
  async unregisterHost(hostId) {
3700
- return this.http.delete(`/routing/hosts/${encodeURIComponent(hostId)}`);
3729
+ return this.http.delete(`/routing/hosts/${encodePathParam(hostId)}`);
3701
3730
  }
3702
3731
  /** Get all registered hosts. */
3703
3732
  async getAllHosts() {
@@ -3709,19 +3738,19 @@ var RoutingClient = class {
3709
3738
  }
3710
3739
  /** Get a specific host by ID. */
3711
3740
  async getHost(hostId) {
3712
- return this.http.get(`/routing/hosts/${encodeURIComponent(hostId)}`);
3741
+ return this.http.get(`/routing/hosts/${encodePathParam(hostId)}`);
3713
3742
  }
3714
3743
  /** Trigger host re-verification. */
3715
3744
  async verifyHost(hostId) {
3716
- return this.http.post(`/routing/hosts/${encodeURIComponent(hostId)}/verify`, {});
3745
+ return this.http.post(`/routing/hosts/${encodePathParam(hostId)}/verify`, {});
3717
3746
  }
3718
3747
  /** Set routing configuration for an app. */
3719
3748
  async setRoutingConfig(appId, config) {
3720
- return this.http.put(`/routing/config/${encodeURIComponent(appId)}`, config);
3749
+ return this.http.put(`/routing/config/${encodePathParam(appId)}`, config);
3721
3750
  }
3722
3751
  /** Get routing configuration for an app. */
3723
3752
  async getRoutingConfig(appId) {
3724
- return this.http.get(`/routing/config/${encodeURIComponent(appId)}`);
3753
+ return this.http.get(`/routing/config/${encodePathParam(appId)}`);
3725
3754
  }
3726
3755
  /** Proxy a request through the gateway. */
3727
3756
  async proxyRequest(request) {
@@ -3737,7 +3766,7 @@ var RoutingClient = class {
3737
3766
  * field; treat `appId` as the success signal.
3738
3767
  */
3739
3768
  async mapDomainToApp(domain, appId) {
3740
- return this.http.post(`/routing/domains/${encodeURIComponent(domain)}/map`, { appId });
3769
+ return this.http.post(`/routing/domains/${encodePathParam(domain)}/map`, { appId });
3741
3770
  }
3742
3771
  };
3743
3772
 
@@ -3753,11 +3782,11 @@ var DomainsClient = class {
3753
3782
  }
3754
3783
  /** Check domain availability */
3755
3784
  async checkAvailability(domain) {
3756
- return this.http.get(`/domains/check/${encodeURIComponent(domain)}`);
3785
+ return this.http.get(`/domains/check/${encodePathParam(domain)}`);
3757
3786
  }
3758
3787
  /** Get domain information */
3759
3788
  async getInfo(domain) {
3760
- return this.http.get(`/domains/${encodeURIComponent(domain)}`);
3789
+ return this.http.get(`/domains/${encodePathParam(domain)}`);
3761
3790
  }
3762
3791
  /** List domains, optionally filtered by owner */
3763
3792
  async list(owner) {
@@ -3770,47 +3799,47 @@ var DomainsClient = class {
3770
3799
  * `apps/smart-gateway/src/domains/domains.controller.ts:226-234`).
3771
3800
  */
3772
3801
  async generateVerificationToken(domain, method) {
3773
- return this.http.post(`/domains/${encodeURIComponent(domain)}/verification`, { method });
3802
+ return this.http.post(`/domains/${encodePathParam(domain)}/verification`, { method });
3774
3803
  }
3775
3804
  /** Verify domain ownership */
3776
3805
  async verifyOwnership(domain, token) {
3777
- return this.http.post(`/domains/${encodeURIComponent(domain)}/verify`, { token });
3806
+ return this.http.post(`/domains/${encodePathParam(domain)}/verify`, { token });
3778
3807
  }
3779
3808
  /** Configure DNS records for a domain */
3780
3809
  async configureDns(domain, records) {
3781
- return this.http.post(`/domains/${encodeURIComponent(domain)}/dns`, { records });
3810
+ return this.http.post(`/domains/${encodePathParam(domain)}/dns`, { records });
3782
3811
  }
3783
3812
  /** Enable DNSSEC for a domain */
3784
3813
  async enableDnssec(domain) {
3785
- return this.http.post(`/domains/${encodeURIComponent(domain)}/dnssec/enable`, {});
3814
+ return this.http.post(`/domains/${encodePathParam(domain)}/dnssec/enable`, {});
3786
3815
  }
3787
3816
  /** Disable DNSSEC for a domain */
3788
3817
  async disableDnssec(domain) {
3789
- return this.http.post(`/domains/${encodeURIComponent(domain)}/dnssec/disable`, {});
3818
+ return this.http.post(`/domains/${encodePathParam(domain)}/dnssec/disable`, {});
3790
3819
  }
3791
3820
  /** Renew a domain */
3792
3821
  async renew(domain, years) {
3793
- return this.http.post(`/domains/${encodeURIComponent(domain)}/renew`, { years: years ?? 1 });
3822
+ return this.http.post(`/domains/${encodePathParam(domain)}/renew`, { years: years ?? 1 });
3794
3823
  }
3795
3824
  /** Initiate a domain transfer */
3796
3825
  async transfer(domain, request) {
3797
- return this.http.post(`/domains/${encodeURIComponent(domain)}/transfer`, request);
3826
+ return this.http.post(`/domains/${encodePathParam(domain)}/transfer`, request);
3798
3827
  }
3799
3828
  /** Approve a pending domain transfer */
3800
3829
  async approveTransfer(domain) {
3801
- return this.http.post(`/domains/${encodeURIComponent(domain)}/transfer/approve`, {});
3830
+ return this.http.post(`/domains/${encodePathParam(domain)}/transfer/approve`, {});
3802
3831
  }
3803
3832
  /** Reject a pending domain transfer */
3804
3833
  async rejectTransfer(domain) {
3805
- return this.http.post(`/domains/${encodeURIComponent(domain)}/transfer/reject`, {});
3834
+ return this.http.post(`/domains/${encodePathParam(domain)}/transfer/reject`, {});
3806
3835
  }
3807
3836
  /** Suspend a domain */
3808
3837
  async suspend(domain, reason) {
3809
- return this.http.post(`/domains/${encodeURIComponent(domain)}/suspend`, { reason });
3838
+ return this.http.post(`/domains/${encodePathParam(domain)}/suspend`, { reason });
3810
3839
  }
3811
3840
  /** Unsuspend a domain */
3812
3841
  async unsuspend(domain) {
3813
- return this.http.post(`/domains/${encodeURIComponent(domain)}/unsuspend`, {});
3842
+ return this.http.post(`/domains/${encodePathParam(domain)}/unsuspend`, {});
3814
3843
  }
3815
3844
  };
3816
3845
 
@@ -3837,7 +3866,7 @@ var DnsClient = class {
3837
3866
  }
3838
3867
  /** Get a specific zone */
3839
3868
  async getZone(zoneName) {
3840
- return this.http.get(`/dns/zones/${encodeURIComponent(zoneName)}`);
3869
+ return this.http.get(`/dns/zones/${encodePathParam(zoneName)}`);
3841
3870
  }
3842
3871
  /** Create a new DNS zone */
3843
3872
  async createZone(request) {
@@ -3845,38 +3874,38 @@ var DnsClient = class {
3845
3874
  }
3846
3875
  /** Delete a DNS zone */
3847
3876
  async deleteZone(zoneName) {
3848
- return this.http.delete(`/dns/zones/${encodeURIComponent(zoneName)}`);
3877
+ return this.http.delete(`/dns/zones/${encodePathParam(zoneName)}`);
3849
3878
  }
3850
3879
  /** Add a record to a zone */
3851
3880
  async addRecord(zoneName, record) {
3852
- return this.http.post(`/dns/zones/${encodeURIComponent(zoneName)}/records`, record);
3881
+ return this.http.post(`/dns/zones/${encodePathParam(zoneName)}/records`, record);
3853
3882
  }
3854
3883
  /** Update a record in a zone */
3855
3884
  async updateRecord(zoneName, recordId, updates) {
3856
3885
  return this.http.put(
3857
- `/dns/zones/${encodeURIComponent(zoneName)}/records/${encodeURIComponent(recordId)}`,
3886
+ `/dns/zones/${encodePathParam(zoneName)}/records/${encodePathParam(recordId)}`,
3858
3887
  updates
3859
3888
  );
3860
3889
  }
3861
3890
  /** Delete a record from a zone */
3862
3891
  async deleteRecord(zoneName, recordId) {
3863
3892
  return this.http.delete(
3864
- `/dns/zones/${encodeURIComponent(zoneName)}/records/${encodeURIComponent(recordId)}`
3893
+ `/dns/zones/${encodePathParam(zoneName)}/records/${encodePathParam(recordId)}`
3865
3894
  );
3866
3895
  }
3867
3896
  /** Generate DNSSEC keys for a zone */
3868
3897
  async generateDnssecKeys(zoneName, algorithm) {
3869
- return this.http.post(`/dns/zones/${encodeURIComponent(zoneName)}/dnssec/keys`, {
3898
+ return this.http.post(`/dns/zones/${encodePathParam(zoneName)}/dnssec/keys`, {
3870
3899
  algorithm
3871
3900
  });
3872
3901
  }
3873
3902
  /** Get DNSSEC keys for a zone */
3874
3903
  async getDnssecKeys(zoneName) {
3875
- return this.http.get(`/dns/zones/${encodeURIComponent(zoneName)}/dnssec/keys`);
3904
+ return this.http.get(`/dns/zones/${encodePathParam(zoneName)}/dnssec/keys`);
3876
3905
  }
3877
3906
  /** Get DS record for a zone (for registrar configuration) */
3878
3907
  async getDsRecord(zoneName) {
3879
- return this.http.get(`/dns/zones/${encodeURIComponent(zoneName)}/dnssec/ds`);
3908
+ return this.http.get(`/dns/zones/${encodePathParam(zoneName)}/dnssec/ds`);
3880
3909
  }
3881
3910
  /** Clear DNS cache */
3882
3911
  async clearCache() {
@@ -3977,7 +4006,7 @@ var DatabaseClient = class {
3977
4006
  async insert(collection, document) {
3978
4007
  const appId = this.getAppId();
3979
4008
  return this.http.post(
3980
- `/api/db/${encodeURIComponent(appId)}/${encodeURIComponent(collection)}`,
4009
+ `/api/db/${encodePathParam(appId)}/${encodePathParam(collection)}`,
3981
4010
  document
3982
4011
  );
3983
4012
  }
@@ -3995,7 +4024,7 @@ var DatabaseClient = class {
3995
4024
  if (options?.sort) params.set("sort", options.sort);
3996
4025
  const qs = params.toString();
3997
4026
  return this.http.get(
3998
- `/api/db/${encodeURIComponent(appId)}/${encodeURIComponent(collection)}${qs ? `?${qs}` : ""}`
4027
+ `/api/db/${encodePathParam(appId)}/${encodePathParam(collection)}${qs ? `?${qs}` : ""}`
3999
4028
  );
4000
4029
  }
4001
4030
  /**
@@ -4004,7 +4033,7 @@ var DatabaseClient = class {
4004
4033
  async update(collection, documentId, updates) {
4005
4034
  const appId = this.getAppId();
4006
4035
  return this.http.put(
4007
- `/api/db/${encodeURIComponent(appId)}/${encodeURIComponent(collection)}/${encodeURIComponent(documentId)}`,
4036
+ `/api/db/${encodePathParam(appId)}/${encodePathParam(collection)}/${encodePathParam(documentId)}`,
4008
4037
  updates
4009
4038
  );
4010
4039
  }
@@ -4014,7 +4043,7 @@ var DatabaseClient = class {
4014
4043
  async delete(collection, documentId) {
4015
4044
  const appId = this.getAppId();
4016
4045
  return this.http.delete(
4017
- `/api/db/${encodeURIComponent(appId)}/${encodeURIComponent(collection)}/${encodeURIComponent(documentId)}`
4046
+ `/api/db/${encodePathParam(appId)}/${encodePathParam(collection)}/${encodePathParam(documentId)}`
4018
4047
  );
4019
4048
  }
4020
4049
  /**
@@ -4026,7 +4055,7 @@ var DatabaseClient = class {
4026
4055
  */
4027
4056
  async listCollections() {
4028
4057
  const appId = this.getAppId();
4029
- return this.http.get(`/api/db/${encodeURIComponent(appId)}/collections`);
4058
+ return this.http.get(`/api/db/${encodePathParam(appId)}/collections`);
4030
4059
  }
4031
4060
  /**
4032
4061
  * Create a new collection in the database.
@@ -4036,7 +4065,7 @@ var DatabaseClient = class {
4036
4065
  */
4037
4066
  async createCollection(name) {
4038
4067
  const appId = this.getAppId();
4039
- return this.http.post(`/api/db/${encodeURIComponent(appId)}/collections`, { name });
4068
+ return this.http.post(`/api/db/${encodePathParam(appId)}/collections`, { name });
4040
4069
  }
4041
4070
  /**
4042
4071
  * Drop a collection and all its documents.
@@ -4047,7 +4076,7 @@ var DatabaseClient = class {
4047
4076
  async dropCollection(name) {
4048
4077
  const appId = this.getAppId();
4049
4078
  return this.http.delete(
4050
- `/api/db/${encodeURIComponent(appId)}/collections/${encodeURIComponent(name)}`
4079
+ `/api/db/${encodePathParam(appId)}/collections/${encodePathParam(name)}`
4051
4080
  );
4052
4081
  }
4053
4082
  // ========== State Proofs ==========
@@ -4056,7 +4085,7 @@ var DatabaseClient = class {
4056
4085
  */
4057
4086
  async getStateRoot() {
4058
4087
  const appId = this.getAppId();
4059
- return this.http.get(`/api/db/${encodeURIComponent(appId)}/state/root`);
4088
+ return this.http.get(`/api/db/${encodePathParam(appId)}/state/root`);
4060
4089
  }
4061
4090
  /**
4062
4091
  * Get a Merkle proof for a specific document
@@ -4064,7 +4093,7 @@ var DatabaseClient = class {
4064
4093
  async getDocumentProof(documentId) {
4065
4094
  const appId = this.getAppId();
4066
4095
  return this.http.get(
4067
- `/api/db/${encodeURIComponent(appId)}/${encodeURIComponent(documentId)}/proof`
4096
+ `/api/db/${encodePathParam(appId)}/${encodePathParam(documentId)}/proof`
4068
4097
  );
4069
4098
  }
4070
4099
  /**
@@ -4078,7 +4107,7 @@ var DatabaseClient = class {
4078
4107
  if (options?.limit !== void 0) params.set("limit", String(options.limit));
4079
4108
  const qs = params.toString();
4080
4109
  return this.http.get(
4081
- `/api/db/${encodeURIComponent(appId)}/state/transitions${qs ? `?${qs}` : ""}`
4110
+ `/api/db/${encodePathParam(appId)}/state/transitions${qs ? `?${qs}` : ""}`
4082
4111
  );
4083
4112
  }
4084
4113
  /**
@@ -4086,7 +4115,7 @@ var DatabaseClient = class {
4086
4115
  */
4087
4116
  async getDbStats() {
4088
4117
  const appId = this.getAppId();
4089
- return this.http.get(`/api/db/${encodeURIComponent(appId)}/stats`);
4118
+ return this.http.get(`/api/db/${encodePathParam(appId)}/stats`);
4090
4119
  }
4091
4120
  };
4092
4121
 
@@ -4103,28 +4132,28 @@ var StorageClient = class {
4103
4132
  */
4104
4133
  async upload(file, filename, metadata) {
4105
4134
  const appId = this.getAppId();
4106
- return this.http.upload(`/api/storage/${encodeURIComponent(appId)}/upload`, file, filename, metadata);
4135
+ return this.http.upload(`/api/storage/${encodePathParam(appId)}/upload`, file, filename, metadata);
4107
4136
  }
4108
4137
  /**
4109
4138
  * Download a file by CID
4110
4139
  */
4111
4140
  async download(cid) {
4112
4141
  const appId = this.getAppId();
4113
- return this.http.get(`/api/storage/${encodeURIComponent(appId)}/download/${encodeURIComponent(cid)}`);
4142
+ return this.http.get(`/api/storage/${encodePathParam(appId)}/download/${encodePathParam(cid)}`);
4114
4143
  }
4115
4144
  /**
4116
4145
  * Get file metadata
4117
4146
  */
4118
4147
  async getMetadata(cid) {
4119
4148
  const appId = this.getAppId();
4120
- return this.http.get(`/api/storage/${encodeURIComponent(appId)}/metadata/${encodeURIComponent(cid)}`);
4149
+ return this.http.get(`/api/storage/${encodePathParam(appId)}/metadata/${encodePathParam(cid)}`);
4121
4150
  }
4122
4151
  /**
4123
4152
  * Delete a file
4124
4153
  */
4125
4154
  async delete(cid) {
4126
4155
  const appId = this.getAppId();
4127
- return this.http.delete(`/api/storage/${encodeURIComponent(appId)}/${encodeURIComponent(cid)}`);
4156
+ return this.http.delete(`/api/storage/${encodePathParam(appId)}/${encodePathParam(cid)}`);
4128
4157
  }
4129
4158
  /**
4130
4159
  * Get file info.
@@ -4133,7 +4162,7 @@ var StorageClient = class {
4133
4162
  * bare-CID metadata route — every metadata lookup must go through
4134
4163
  * `getMetadata(cid)` (`/api/storage/:appId/metadata/:cid`) or the
4135
4164
  * stream body via `download(cid)`. This alias forwards to `download`
4136
- * for back-compat; remove in the next major SDK release.
4165
+ * for back-compat; **scheduled for removal in 4.0.0**.
4137
4166
  */
4138
4167
  async getFile(cid) {
4139
4168
  return this.download(cid);
@@ -4151,21 +4180,21 @@ var StorageClient = class {
4151
4180
  if (pagination?.limit !== void 0) params.set("limit", String(pagination.limit));
4152
4181
  if (pagination?.offset !== void 0) params.set("offset", String(pagination.offset));
4153
4182
  const qs = params.toString();
4154
- return this.http.get(`/api/storage/${encodeURIComponent(appId)}/files${qs ? `?${qs}` : ""}`);
4183
+ return this.http.get(`/api/storage/${encodePathParam(appId)}/files${qs ? `?${qs}` : ""}`);
4155
4184
  }
4156
4185
  /**
4157
4186
  * Get storage usage for the current app
4158
4187
  */
4159
4188
  async getUsage() {
4160
4189
  const appId = this.getAppId();
4161
- return this.http.get(`/api/storage/${encodeURIComponent(appId)}/usage`);
4190
+ return this.http.get(`/api/storage/${encodePathParam(appId)}/usage`);
4162
4191
  }
4163
4192
  /**
4164
4193
  * Check if a file exists
4165
4194
  */
4166
4195
  async exists(cid) {
4167
4196
  const appId = this.getAppId();
4168
- return this.http.get(`/api/storage/${encodeURIComponent(appId)}/exists/${encodeURIComponent(cid)}`);
4197
+ return this.http.get(`/api/storage/${encodePathParam(appId)}/exists/${encodePathParam(cid)}`);
4169
4198
  }
4170
4199
  };
4171
4200
 
@@ -4182,7 +4211,7 @@ var FunctionsClient = class {
4182
4211
  */
4183
4212
  async deploy(request) {
4184
4213
  const appId = this.getAppId();
4185
- return this.http.post(`/api/functions/${encodeURIComponent(appId)}`, request);
4214
+ return this.http.post(`/api/functions/${encodePathParam(appId)}`, request);
4186
4215
  }
4187
4216
  /**
4188
4217
  * Invoke a function
@@ -4190,7 +4219,7 @@ var FunctionsClient = class {
4190
4219
  async invoke(functionId, payload) {
4191
4220
  const appId = this.getAppId();
4192
4221
  return this.http.post(
4193
- `/api/functions/${encodeURIComponent(appId)}/${encodeURIComponent(functionId)}/invoke`,
4222
+ `/api/functions/${encodePathParam(appId)}/${encodePathParam(functionId)}/invoke`,
4194
4223
  payload ?? {}
4195
4224
  );
4196
4225
  }
@@ -4199,7 +4228,7 @@ var FunctionsClient = class {
4199
4228
  */
4200
4229
  async list() {
4201
4230
  const appId = this.getAppId();
4202
- return this.http.get(`/api/functions/${encodeURIComponent(appId)}`);
4231
+ return this.http.get(`/api/functions/${encodePathParam(appId)}`);
4203
4232
  }
4204
4233
  /**
4205
4234
  * Get function details
@@ -4207,7 +4236,7 @@ var FunctionsClient = class {
4207
4236
  async get(functionId) {
4208
4237
  const appId = this.getAppId();
4209
4238
  return this.http.get(
4210
- `/api/functions/${encodeURIComponent(appId)}/${encodeURIComponent(functionId)}`
4239
+ `/api/functions/${encodePathParam(appId)}/${encodePathParam(functionId)}`
4211
4240
  );
4212
4241
  }
4213
4242
  /**
@@ -4216,7 +4245,7 @@ var FunctionsClient = class {
4216
4245
  async update(functionId, updates) {
4217
4246
  const appId = this.getAppId();
4218
4247
  return this.http.put(
4219
- `/api/functions/${encodeURIComponent(appId)}/${encodeURIComponent(functionId)}`,
4248
+ `/api/functions/${encodePathParam(appId)}/${encodePathParam(functionId)}`,
4220
4249
  updates
4221
4250
  );
4222
4251
  }
@@ -4226,7 +4255,7 @@ var FunctionsClient = class {
4226
4255
  async delete(functionId) {
4227
4256
  const appId = this.getAppId();
4228
4257
  return this.http.delete(
4229
- `/api/functions/${encodeURIComponent(appId)}/${encodeURIComponent(functionId)}`
4258
+ `/api/functions/${encodePathParam(appId)}/${encodePathParam(functionId)}`
4230
4259
  );
4231
4260
  }
4232
4261
  /**
@@ -4240,7 +4269,7 @@ var FunctionsClient = class {
4240
4269
  if (options?.level) params.set("level", options.level);
4241
4270
  const qs = params.toString();
4242
4271
  return this.http.get(
4243
- `/api/functions/${encodeURIComponent(appId)}/${encodeURIComponent(functionId)}/logs${qs ? `?${qs}` : ""}`
4272
+ `/api/functions/${encodePathParam(appId)}/${encodePathParam(functionId)}/logs${qs ? `?${qs}` : ""}`
4244
4273
  );
4245
4274
  }
4246
4275
  /**
@@ -4248,7 +4277,7 @@ var FunctionsClient = class {
4248
4277
  */
4249
4278
  async getStats() {
4250
4279
  const appId = this.getAppId();
4251
- return this.http.get(`/api/functions/${encodeURIComponent(appId)}/stats`);
4280
+ return this.http.get(`/api/functions/${encodePathParam(appId)}/stats`);
4252
4281
  }
4253
4282
  };
4254
4283
 
@@ -4265,28 +4294,28 @@ var MessagingClient = class {
4265
4294
  */
4266
4295
  async createChannel(config) {
4267
4296
  const appId = this.getAppId();
4268
- return this.http.post(`/api/messaging/${encodeURIComponent(appId)}/channels`, config);
4297
+ return this.http.post(`/api/messaging/${encodePathParam(appId)}/channels`, config);
4269
4298
  }
4270
4299
  /**
4271
4300
  * Delete a channel
4272
4301
  */
4273
4302
  async deleteChannel(channelId) {
4274
4303
  const appId = this.getAppId();
4275
- return this.http.delete(`/api/messaging/${encodeURIComponent(appId)}/channels/${encodeURIComponent(channelId)}`);
4304
+ return this.http.delete(`/api/messaging/${encodePathParam(appId)}/channels/${encodePathParam(channelId)}`);
4276
4305
  }
4277
4306
  /**
4278
4307
  * Get a channel by ID
4279
4308
  */
4280
4309
  async getChannel(channelId) {
4281
4310
  const appId = this.getAppId();
4282
- return this.http.get(`/api/messaging/${encodeURIComponent(appId)}/channels/${encodeURIComponent(channelId)}`);
4311
+ return this.http.get(`/api/messaging/${encodePathParam(appId)}/channels/${encodePathParam(channelId)}`);
4283
4312
  }
4284
4313
  /**
4285
4314
  * List all channels for the app
4286
4315
  */
4287
4316
  async listChannels() {
4288
4317
  const appId = this.getAppId();
4289
- return this.http.get(`/api/messaging/${encodeURIComponent(appId)}/channels`);
4318
+ return this.http.get(`/api/messaging/${encodePathParam(appId)}/channels`);
4290
4319
  }
4291
4320
  /**
4292
4321
  * Publish a message to a channel
@@ -4294,7 +4323,7 @@ var MessagingClient = class {
4294
4323
  async publish(channel, message, metadata) {
4295
4324
  const appId = this.getAppId();
4296
4325
  return this.http.post(
4297
- `/api/messaging/${encodeURIComponent(appId)}/channels/${encodeURIComponent(channel)}/publish`,
4326
+ `/api/messaging/${encodePathParam(appId)}/channels/${encodePathParam(channel)}/publish`,
4298
4327
  { data: message, metadata }
4299
4328
  );
4300
4329
  }
@@ -4309,7 +4338,7 @@ var MessagingClient = class {
4309
4338
  if (options?.after) params.set("after", options.after);
4310
4339
  const qs = params.toString();
4311
4340
  return this.http.get(
4312
- `/api/messaging/${encodeURIComponent(appId)}/channels/${encodeURIComponent(channel)}/history${qs ? `?${qs}` : ""}`
4341
+ `/api/messaging/${encodePathParam(appId)}/channels/${encodePathParam(channel)}/history${qs ? `?${qs}` : ""}`
4313
4342
  );
4314
4343
  }
4315
4344
  /**
@@ -4323,7 +4352,7 @@ var MessagingClient = class {
4323
4352
  async setPresence(channel, member) {
4324
4353
  const appId = this.getAppId();
4325
4354
  return this.http.post(
4326
- `/api/messaging/${encodeURIComponent(appId)}/channels/${encodeURIComponent(channel)}/presence`,
4355
+ `/api/messaging/${encodePathParam(appId)}/channels/${encodePathParam(channel)}/presence`,
4327
4356
  member
4328
4357
  );
4329
4358
  }
@@ -4339,7 +4368,7 @@ var MessagingClient = class {
4339
4368
  async removePresence(channel, clientId) {
4340
4369
  const appId = this.getAppId();
4341
4370
  return this.http.delete(
4342
- `/api/messaging/${encodeURIComponent(appId)}/channels/${encodeURIComponent(channel)}/presence/${encodeURIComponent(clientId)}`
4371
+ `/api/messaging/${encodePathParam(appId)}/channels/${encodePathParam(channel)}/presence/${encodePathParam(clientId)}`
4343
4372
  );
4344
4373
  }
4345
4374
  /**
@@ -4348,7 +4377,7 @@ var MessagingClient = class {
4348
4377
  async getPresence(channel) {
4349
4378
  const appId = this.getAppId();
4350
4379
  return this.http.get(
4351
- `/api/messaging/${encodeURIComponent(appId)}/channels/${encodeURIComponent(channel)}/presence`
4380
+ `/api/messaging/${encodePathParam(appId)}/channels/${encodePathParam(channel)}/presence`
4352
4381
  );
4353
4382
  }
4354
4383
  /**
@@ -4356,7 +4385,7 @@ var MessagingClient = class {
4356
4385
  */
4357
4386
  async getStats() {
4358
4387
  const appId = this.getAppId();
4359
- return this.http.get(`/api/messaging/${encodeURIComponent(appId)}/stats`);
4388
+ return this.http.get(`/api/messaging/${encodePathParam(appId)}/stats`);
4360
4389
  }
4361
4390
  };
4362
4391
 
@@ -4444,7 +4473,7 @@ var RulesClient = class {
4444
4473
  }
4445
4474
  /** Fetch a published rule by its HCS consensus timestamp. */
4446
4475
  async get(consensusTimestamp) {
4447
- return this.http.get(`/api/rules/${encodeURIComponent(consensusTimestamp)}`);
4476
+ return this.http.get(`/api/rules/${encodePathParam(consensusTimestamp)}`);
4448
4477
  }
4449
4478
  /** List rules owned by the authenticated entity, optionally filtered by type. */
4450
4479
  async listByOwner(filter) {
@@ -4461,13 +4490,13 @@ var RulesClient = class {
4461
4490
  /** Walk the version history of a published rule. */
4462
4491
  async getVersionHistory(consensusTimestamp) {
4463
4492
  return this.http.get(
4464
- `/api/rules/${encodeURIComponent(consensusTimestamp)}/versions`
4493
+ `/api/rules/${encodePathParam(consensusTimestamp)}/versions`
4465
4494
  );
4466
4495
  }
4467
4496
  /** Deprecate a published rule (owner-only). */
4468
4497
  async deprecate(consensusTimestamp) {
4469
4498
  return this.http.post(
4470
- `/api/rules/${encodeURIComponent(consensusTimestamp)}/deprecate`,
4499
+ `/api/rules/${encodePathParam(consensusTimestamp)}/deprecate`,
4471
4500
  {}
4472
4501
  );
4473
4502
  }
@@ -4505,7 +4534,7 @@ var EntitiesClient = class {
4505
4534
  }
4506
4535
  /** Fetch an entity by its canonical `entityId`. */
4507
4536
  async get(entityId) {
4508
- return this.http.get(`/api/entities/${encodeURIComponent(entityId)}`);
4537
+ return this.http.get(`/api/entities/${encodePathParam(entityId)}`);
4509
4538
  }
4510
4539
  /** List entities owned by the authenticated wallet, optionally filtered by type. */
4511
4540
  async listByOwner(filter) {
@@ -4521,7 +4550,6 @@ var BaasClient = class _BaasClient {
4521
4550
  appId;
4522
4551
  timeout;
4523
4552
  allowInsecure;
4524
- authToken = null;
4525
4553
  http;
4526
4554
  /** Last HTTP error (for getHttpHealth) */
4527
4555
  lastHttpError;
@@ -4608,30 +4636,25 @@ var BaasClient = class _BaasClient {
4608
4636
  */
4609
4637
  static async connectToCluster(config) {
4610
4638
  const allowInsecure = config.allowInsecure ?? false;
4611
- const bootstrap = config.bootstrap ? [...config.bootstrap] : [...resolveNetwork(config.network).bootstrap];
4612
- if (bootstrap.length === 0) {
4613
- throw new BaasError(
4614
- "connectToCluster requires either a non-empty `bootstrap` list or a known `network` name.",
4615
- 400
4616
- );
4617
- }
4618
- const discovery = new ClusterDiscoveryClient({
4619
- bootstrap,
4639
+ const resolved = await resolveClusterEndpoint({
4640
+ bootstrap: config.bootstrap,
4641
+ network: config.network,
4620
4642
  allowInsecure,
4621
- trustAnchor: config.trustAnchor ? {
4622
- network: config.trustAnchor.network,
4623
- registryTopicId: config.trustAnchor.registryTopicId,
4624
- mirrorNodeUrl: config.trustAnchor.mirrorNodeUrl,
4625
- allowInsecure
4626
- } : void 0
4643
+ trustAnchor: config.trustAnchor
4627
4644
  });
4628
- const cluster = await discovery.getRandomCluster();
4629
- if (!cluster) {
4645
+ if (!resolved.ok) {
4646
+ if (resolved.reason === "no-seeds") {
4647
+ throw new BaasError(
4648
+ "connectToCluster requires either a non-empty `bootstrap` list or a known `network` name.",
4649
+ 400
4650
+ );
4651
+ }
4630
4652
  throw new BaasError(
4631
4653
  "No active clusters available via bootstrap seeds. Check network reachability or bootstrap URLs.",
4632
4654
  503
4633
4655
  );
4634
4656
  }
4657
+ const cluster = resolved.cluster;
4635
4658
  return new _BaasClient({
4636
4659
  hostUrl: cluster.endpoints.gatewayUrl,
4637
4660
  appId: config.appId,
@@ -4649,7 +4672,7 @@ var BaasClient = class _BaasClient {
4649
4672
  }
4650
4673
  /** Check if the client is authenticated */
4651
4674
  isAuthenticated() {
4652
- return this.authToken !== null;
4675
+ return this.http.getAuthToken() !== void 0;
4653
4676
  }
4654
4677
  /** Get the current app ID */
4655
4678
  getAppId() {
@@ -4695,93 +4718,55 @@ var BaasClient = class _BaasClient {
4695
4718
  */
4696
4719
  async authenticate(options) {
4697
4720
  const { chain, walletAddress, publicKey, signFn } = options;
4698
- const challenge = await this.post("/api/auth/challenge", {
4699
- chain,
4700
- walletAddress,
4701
- appId: this.appId
4702
- });
4721
+ let challenge;
4722
+ try {
4723
+ challenge = await this.http.post("/api/auth/challenge", {
4724
+ chain,
4725
+ walletAddress,
4726
+ appId: this.appId
4727
+ });
4728
+ } catch (err) {
4729
+ throw asBaasError(err);
4730
+ }
4703
4731
  const signature = await signFn(challenge.message);
4704
- const result = await this.post("/api/auth/verify", {
4705
- challengeId: challenge.challengeId,
4706
- signature,
4707
- publicKey
4708
- });
4709
- this.authToken = result.token;
4710
- this.http.setAuthToken?.(result.token);
4732
+ let result;
4733
+ try {
4734
+ result = await this.http.post("/api/auth/verify", {
4735
+ challengeId: challenge.challengeId,
4736
+ signature,
4737
+ publicKey
4738
+ });
4739
+ } catch (err) {
4740
+ throw asBaasError(err);
4741
+ }
4742
+ this.http.setAuthToken(result.token);
4711
4743
  return result;
4712
4744
  }
4713
4745
  /** Validate the current session */
4714
4746
  async validateSession() {
4715
4747
  this.requireAuth();
4716
- return this.get("/api/auth/session");
4748
+ try {
4749
+ return await this.http.get("/api/auth/session");
4750
+ } catch (err) {
4751
+ throw asBaasError(err);
4752
+ }
4717
4753
  }
4718
4754
  /** Destroy the current session on server and clear local token */
4719
4755
  async logout() {
4720
- if (this.authToken) {
4756
+ if (this.http.getAuthToken()) {
4721
4757
  try {
4722
- await this.post("/api/auth/logout", {});
4758
+ await this.http.post("/api/auth/logout", {});
4723
4759
  } catch {
4724
4760
  }
4725
4761
  }
4726
- this.authToken = null;
4762
+ this.http.setAuthToken(void 0);
4727
4763
  }
4728
4764
  // ========== HTTP Helpers ==========
4729
4765
  requireAuth() {
4730
- if (!this.authToken) {
4766
+ if (!this.http.getAuthToken()) {
4731
4767
  throw new BaasError("Authentication required. Call authenticate() first.", 401);
4732
4768
  }
4733
4769
  }
4734
- getHeaders() {
4735
- const headers = {
4736
- "Content-Type": "application/json"
4737
- };
4738
- if (this.authToken) {
4739
- headers["Authorization"] = `Bearer ${this.authToken}`;
4740
- }
4741
- return headers;
4742
- }
4743
- async post(path, body) {
4744
- return this.request("POST", path, body);
4745
- }
4746
- async get(path) {
4747
- return this.request("GET", path);
4748
- }
4749
- async request(method, path, body) {
4750
- const url = `${this.hostUrl}${this.pathPrefix}${path}`;
4751
- const controller = new AbortController();
4752
- const timeoutId = setTimeout(() => controller.abort(), this.timeout);
4753
- try {
4754
- const options = {
4755
- method,
4756
- headers: this.getHeaders(),
4757
- signal: controller.signal
4758
- };
4759
- if (body !== void 0) {
4760
- options.body = JSON.stringify(body);
4761
- }
4762
- const response = await fetch(url, options);
4763
- clearTimeout(timeoutId);
4764
- if (!response.ok) {
4765
- const errorData = await response.json().catch(() => ({}));
4766
- throw new BaasError(
4767
- errorData.message || `API error: ${response.status} ${response.statusText}`,
4768
- response.status,
4769
- errorData
4770
- );
4771
- }
4772
- const text = await response.text();
4773
- if (!text) return void 0;
4774
- return JSON.parse(text);
4775
- } catch (error) {
4776
- clearTimeout(timeoutId);
4777
- if (error instanceof BaasError) throw error;
4778
- const err = error;
4779
- if (err.name === "AbortError") {
4780
- throw new BaasError("Request timeout", 408);
4781
- }
4782
- throw new BaasError(`Network error: ${err.message}`, 0, { originalError: err.message });
4783
- }
4784
- }
4785
4770
  };
4786
4771
  var BaasError = class extends Error {
4787
4772
  constructor(message, statusCode, details) {
@@ -4793,6 +4778,17 @@ var BaasError = class extends Error {
4793
4778
  statusCode;
4794
4779
  details;
4795
4780
  };
4781
+ function asBaasError(err) {
4782
+ if (err instanceof BaasError) return err;
4783
+ if (err instanceof SdkHttpError) {
4784
+ const details = err.details ?? void 0;
4785
+ return new BaasError(err.message, err.statusCode, details);
4786
+ }
4787
+ const e = err;
4788
+ return new BaasError(`Network error: ${e?.message ?? String(err)}`, 0, {
4789
+ originalError: e?.message ?? String(err)
4790
+ });
4791
+ }
4796
4792
  function validateUrl2(url, allowInsecure = false) {
4797
4793
  try {
4798
4794
  const parsed = new URL(url);