@hsuite/smart-engines-sdk 3.3.0 → 3.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1100,6 +1100,99 @@ var ClusterDiscoveryClient = class {
1100
1100
  }
1101
1101
  };
1102
1102
 
1103
+ // src/discovery/discovery-client.ts
1104
+ var DiscoveryClient = class {
1105
+ constructor(http) {
1106
+ this.http = http;
1107
+ this.platformImages = new PlatformImagesClient(http);
1108
+ }
1109
+ http;
1110
+ /** Platform-image manifest discovery endpoints. */
1111
+ platformImages;
1112
+ /**
1113
+ * `GET /api/v3/discovery/clusters` — active-set cluster registry,
1114
+ * grouped by `clusterId`. This is the same data the bootstrap-seed
1115
+ * flow consumes for random-pick connect.
1116
+ */
1117
+ async listClusters() {
1118
+ return this.http.get("/discovery/clusters");
1119
+ }
1120
+ /**
1121
+ * `GET /api/v3/discovery/clusters/all` — every node-level record
1122
+ * (debug / audit view). Includes nodes that the active-set filter
1123
+ * dropped (e.g. recently-departed validators still in the registry's
1124
+ * eventual-consistency window).
1125
+ */
1126
+ async listAllClusters() {
1127
+ return this.http.get("/discovery/clusters/all");
1128
+ }
1129
+ /**
1130
+ * `GET /api/v3/discovery/clusters/:nodeId` — per-nodeId registry row.
1131
+ * Returns `{ record: null }` (not 404) when the nodeId is unknown to
1132
+ * this validator's registry view, so callers can branch without
1133
+ * try/catch.
1134
+ */
1135
+ async getClusterByNode(nodeId) {
1136
+ return this.http.get(`/discovery/clusters/${encodeURIComponent(nodeId)}`);
1137
+ }
1138
+ };
1139
+ var PlatformImagesClient = class {
1140
+ constructor(http) {
1141
+ this.http = http;
1142
+ }
1143
+ http;
1144
+ /**
1145
+ * `GET /api/v3/discovery/platform-images` — every signed manifest the
1146
+ * cluster has on record. One row per `(imageName, version)` pair.
1147
+ */
1148
+ async list() {
1149
+ return this.http.get("/discovery/platform-images");
1150
+ }
1151
+ /**
1152
+ * `GET /api/v3/discovery/platform-images/envelopes` — full signed
1153
+ * envelopes (manifest + signature + publicKey). Heavier payload than
1154
+ * {@link list}; for external re-verifiers that want to independently
1155
+ * confirm authenticity.
1156
+ */
1157
+ async listEnvelopes() {
1158
+ return this.http.get("/discovery/platform-images/envelopes");
1159
+ }
1160
+ /**
1161
+ * `GET /api/v3/discovery/platform-images/:imageName` — every version
1162
+ * of a single image. Useful for "which tags has the cluster
1163
+ * authorized?" queries.
1164
+ */
1165
+ async get(imageName) {
1166
+ return this.http.get(`/discovery/platform-images/${encodeURIComponent(imageName)}`);
1167
+ }
1168
+ /**
1169
+ * `GET /api/v3/discovery/platform-images/:imageName/:version` —
1170
+ * single signed manifest. Returns `{ manifest: null }` when the
1171
+ * `(imageName, version)` pair is unknown.
1172
+ */
1173
+ async getVersion(imageName, version) {
1174
+ return this.http.get(
1175
+ `/discovery/platform-images/${encodeURIComponent(imageName)}/${encodeURIComponent(version)}`
1176
+ );
1177
+ }
1178
+ /**
1179
+ * `GET /api/v3/discovery/platform-images/:imageName/:version/verify?digest=...`
1180
+ * — content-addressed verify gate. Returns `{ verified: true }` only
1181
+ * when the supplied SHA-256 digest matches the on-record manifest.
1182
+ *
1183
+ * Use before pulling an image off a registry to make sure you're
1184
+ * about to run cluster-signed bits and not whatever drifted into
1185
+ * the registry namespace.
1186
+ */
1187
+ async verify(imageName, version, digest) {
1188
+ return this.http.get(
1189
+ `/discovery/platform-images/${encodeURIComponent(imageName)}/${encodeURIComponent(
1190
+ version
1191
+ )}/verify?digest=${encodeURIComponent(digest)}`
1192
+ );
1193
+ }
1194
+ };
1195
+
1103
1196
  // src/auth/validator-auth.ts
1104
1197
  var SUPPORTED_AUTH_CHAINS = [
1105
1198
  "hedera",
@@ -1382,7 +1475,7 @@ function createHttpClient(config) {
1382
1475
  const timeout = config.timeout ?? 3e4;
1383
1476
  function getHeaders(contentType) {
1384
1477
  const headers = {};
1385
- {
1478
+ if (contentType) {
1386
1479
  headers["Content-Type"] = contentType;
1387
1480
  }
1388
1481
  if (config.authToken) {
@@ -1432,6 +1525,36 @@ function createHttpClient(config) {
1432
1525
  throw new SdkHttpError(`Network error: ${err.message}`, 0, error);
1433
1526
  }
1434
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
+ }
1435
1558
  async function upload(path, file, filename, metadata, fieldName = "file") {
1436
1559
  const url = `${config.baseUrl}${path}`;
1437
1560
  const controller = new AbortController();
@@ -1482,7 +1605,9 @@ function createHttpClient(config) {
1482
1605
  post: (path, body) => request("POST", path, body),
1483
1606
  get: (path) => request("GET", path),
1484
1607
  put: (path, body) => request("PUT", path, body),
1608
+ patch: (path, body) => request("PATCH", path, body),
1485
1609
  delete: (path) => request("DELETE", path),
1610
+ getText,
1486
1611
  upload: ((path, file, filename, metadata, fieldName) => upload(path, file, filename, metadata, fieldName)),
1487
1612
  setAuthToken
1488
1613
  };
@@ -1618,6 +1743,80 @@ var SubscriptionClient = class {
1618
1743
  async getBalance(appId) {
1619
1744
  return this.http.get(`/subscription/balance/${encodeURIComponent(appId)}`);
1620
1745
  }
1746
+ // ─── Tier-Change Endpoints ────────────────────────────────────────────────
1747
+ /**
1748
+ * Schedule a tier downgrade. The downgrade takes effect at the next
1749
+ * renewal — the deposit is NOT partially refunded mid-lock. Excess
1750
+ * collateral returns on eventual cancel.
1751
+ */
1752
+ async downgrade(request) {
1753
+ return this.http.post("/subscription/downgrade", request);
1754
+ }
1755
+ /**
1756
+ * Request a tier upgrade. The server records the upgrade and returns
1757
+ * top-up deposit instructions for the price delta. The new tier flips
1758
+ * only once the on-chain top-up is confirmed by the deposit monitor.
1759
+ */
1760
+ async upgrade(request) {
1761
+ return this.http.post("/subscription/upgrade", request);
1762
+ }
1763
+ /** Cancel a pending (not-yet-applied) tier change. */
1764
+ async cancelTierChange(request) {
1765
+ return this.http.post("/subscription/tier-change/cancel", request);
1766
+ }
1767
+ // ─── Internal / Usage / Billing ───────────────────────────────────────────
1768
+ /**
1769
+ * Check whether a developer wallet has any active subscription. Used by
1770
+ * smart-host's deploy gate via the cluster-internal API-key path; smart-app
1771
+ * callers should not rely on this endpoint (server-side it requires the
1772
+ * `INTERNAL_SERVICE_MESH_ROUTES` allowlist + an `X-API-Key` header).
1773
+ */
1774
+ async getActiveFor(walletAddress) {
1775
+ return this.http.get(
1776
+ `/subscription/active-for/${encodeURIComponent(walletAddress)}`
1777
+ );
1778
+ }
1779
+ /** Today's consumption breakdown by category for an app. Owner-only. */
1780
+ async getUsage(appId) {
1781
+ return this.http.get(`/subscription/usage/${encodeURIComponent(appId)}`);
1782
+ }
1783
+ /**
1784
+ * Current usage with overage info: usage percent, grace status,
1785
+ * upgrade suggestion, projected days until limit. Owner-only.
1786
+ */
1787
+ async getUsageStatus(appId) {
1788
+ return this.http.get(`/subscription/usage/status/${encodeURIComponent(appId)}`);
1789
+ }
1790
+ /**
1791
+ * Subscription balance deduction history. Pagination + ISO-8601 range
1792
+ * filtering supported. Owner-only.
1793
+ */
1794
+ async getBilling(appId, options) {
1795
+ const params = new URLSearchParams();
1796
+ if (options?.limit !== void 0) params.append("limit", String(options.limit));
1797
+ if (options?.offset !== void 0) params.append("offset", String(options.offset));
1798
+ if (options?.from) params.append("from", options.from);
1799
+ if (options?.to) params.append("to", options.to);
1800
+ const qs = params.toString();
1801
+ return this.http.get(
1802
+ `/subscription/billing/${encodeURIComponent(appId)}${qs ? `?${qs}` : ""}`
1803
+ );
1804
+ }
1805
+ /**
1806
+ * Mint a customer-subscription NFT on behalf of a smart-app.
1807
+ *
1808
+ * Distinct from `mintNft(appId)`, which mints the smart-app's own
1809
+ * developer-level subscription NFT. This endpoint mints a *customer*
1810
+ * NFT held by an end-user wallet — used by smart-host's
1811
+ * `XrplCustomerNftIssuerAdapter` when an app calls
1812
+ * `SubscriptionService.issueCustomerSubscription()` from the sandbox.
1813
+ *
1814
+ * v1 is XRPL-only (the `customerChain` field is a literal `'xrpl'`).
1815
+ * Internal-by-design — server-side gated by `X-API-Key`.
1816
+ */
1817
+ async mintCustomer(request) {
1818
+ return this.http.post("/subscription/customer/mint", request);
1819
+ }
1621
1820
  };
1622
1821
 
1623
1822
  // src/tss/index.ts
@@ -1646,14 +1845,19 @@ var TSSClient = class {
1646
1845
  return this.http.get(`/tss/entity/${encodeURIComponent(entityId)}`);
1647
1846
  }
1648
1847
  /**
1649
- * Sign a transaction using MPC — chain-agnostic.
1650
- * Routes to the correct chain backend based on the `chain` parameter.
1848
+ * Sign a transaction using MPC.
1651
1849
  *
1652
- * @param request - MPC signing request with chain, entityId, and transaction bytes
1850
+ * Routes to `POST /api/v3/tss/hedera/sign-mpc`. Only `'hedera'` is wired
1851
+ * server-side today (see
1852
+ * `apps/smart-validator/src/tss/tss.controller.ts:279`); other chain
1853
+ * signing paths run via their own controllers (XRPL multisig, Polkadot
1854
+ * MPC) and are not exposed through this sub-client. The `chain` field is
1855
+ * carried into the request body so the validator can log + route, but
1856
+ * any non-`'hedera'` value will 404.
1653
1857
  */
1654
1858
  async signMPC(request) {
1655
- const chain = request.chain || "hedera";
1656
- return this.http.post(`/tss/${encodeURIComponent(chain)}/sign-mpc`, request);
1859
+ const chain = "hedera";
1860
+ return this.http.post(`/tss/${chain}/sign-mpc`, { ...request, chain });
1657
1861
  }
1658
1862
  /**
1659
1863
  * Get known validators and their public keys
@@ -1697,6 +1901,42 @@ var TSSClient = class {
1697
1901
  async getMultiSigStatus(txId) {
1698
1902
  return this.http.get(`/tss/multisig/transactions/${encodeURIComponent(txId)}`);
1699
1903
  }
1904
+ /**
1905
+ * Async-job variant of {@link createEntity}.
1906
+ *
1907
+ * Server returns 202 + `{ jobId, statusUrl, status: 'pending' }` immediately;
1908
+ * the DKG ceremony runs in the background. Poll {@link getJob} until the
1909
+ * status reaches `'success'` or `'failed'`.
1910
+ */
1911
+ async createEntityAsync(options) {
1912
+ return this.http.post("/tss/entity/create/async", options);
1913
+ }
1914
+ /**
1915
+ * Async-job variant of {@link reshareCluster}. Returns 202 + a polling
1916
+ * descriptor; resharing runs in the background.
1917
+ */
1918
+ async reshareClusterAsync(request) {
1919
+ return this.http.post("/tss/cluster/reshare/async", request);
1920
+ }
1921
+ /**
1922
+ * Poll the status of an async TSS-ceremony job kicked off via
1923
+ * {@link createEntityAsync} or {@link reshareClusterAsync}.
1924
+ */
1925
+ async getJob(jobId) {
1926
+ return this.http.get(`/tss/jobs/${encodeURIComponent(jobId)}`);
1927
+ }
1928
+ /**
1929
+ * Sign a hex payload as smart-app entity `appId` via the cluster's TSS
1930
+ * quorum. Used by smart-deployer for per-entity BLS12-381 signatures over
1931
+ * deployment-context payloads (trustless APP_TOKEN replacement).
1932
+ *
1933
+ * Payload constraints (enforced server-side):
1934
+ * - even-length lowercase hex
1935
+ * - ≥32 bytes, ≤8KB
1936
+ */
1937
+ async signForApp(appId, request) {
1938
+ return this.http.post(`/tss/entity/${encodeURIComponent(appId)}/sign`, request);
1939
+ }
1700
1940
  };
1701
1941
 
1702
1942
  // src/ipfs/index.ts
@@ -1766,12 +2006,59 @@ var IPFSClient = class {
1766
2006
  }
1767
2007
  };
1768
2008
 
2009
+ // src/hedera-tss/index.ts
2010
+ var HederaTssClient = class {
2011
+ constructor(http) {
2012
+ this.http = http;
2013
+ }
2014
+ http;
2015
+ /** Create a Hedera account whose keys are controlled by the TSS cluster. */
2016
+ async createAccount(request) {
2017
+ return this.http.post("/hedera/tss/create-account", request);
2018
+ }
2019
+ /** Update an existing account's memo via TSS-signed transaction. */
2020
+ async updateMemo(request) {
2021
+ return this.http.post("/hedera/tss/update-memo", request);
2022
+ }
2023
+ /** Create a TSS-controlled HCS topic. */
2024
+ async createTopic(request) {
2025
+ return this.http.post("/hedera/tss/create-topic", request);
2026
+ }
2027
+ /** Submit a message to an HCS topic via TSS signing. */
2028
+ async submitMessage(request) {
2029
+ return this.http.post("/hedera/tss/submit-message", request);
2030
+ }
2031
+ /** Create an HTS token with TSS-controlled admin/supply/freeze/pause/wipe keys. */
2032
+ async createToken(request) {
2033
+ return this.http.post("/hedera/tss/create-token", request);
2034
+ }
2035
+ /** Mint tokens via TSS signing — optionally rule-validated via `validatorTopicId`. */
2036
+ async mintToken(request) {
2037
+ return this.http.post("/hedera/tss/mint-token", request);
2038
+ }
2039
+ };
2040
+
1769
2041
  // src/transactions/chains/hedera.ts
1770
2042
  var HederaTransactionsClient = class {
1771
- constructor(http) {
2043
+ constructor(http, tssHttp) {
1772
2044
  this.http = http;
2045
+ this.tss = new HederaTssClient(tssHttp ?? http);
1773
2046
  }
1774
2047
  http;
2048
+ /**
2049
+ * TSS-signed Hedera operations (`/api/v3/hedera/tss/*`).
2050
+ *
2051
+ * Distinct from the prepare-only routes on this class:
2052
+ * - `client.hedera.prepareTopicCreate(...)` returns bytes for local sign+submit.
2053
+ * - `client.hedera.tss.createTopic(...)` makes the cluster sign+submit in one call.
2054
+ *
2055
+ * `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.
2060
+ */
2061
+ tss;
1775
2062
  /** Prepare an HCS topic creation transaction. */
1776
2063
  async prepareTopicCreate(request) {
1777
2064
  return this.http.post("/topic/create/prepare", { ...request, chain: "hedera" });
@@ -1804,6 +2091,16 @@ var XrplTransactionsClient = class {
1804
2091
  async prepareTrustLine(request) {
1805
2092
  return this.http.post("/trustline/prepare", { ...request, chain: "xrpl" });
1806
2093
  }
2094
+ /**
2095
+ * Prepare the ordered XRPL account-setup transaction set
2096
+ * (SignerListSet + AccountSet DisableMaster) for sovereignty mode.
2097
+ *
2098
+ * Returns `{ steps, sovereignty }`. Caller signs + submits each step in
2099
+ * order; the master key remains usable until the final AccountSet lands.
2100
+ */
2101
+ async prepareAccountSetup(request) {
2102
+ return this.http.post("/xrpl/account-setup/prepare", { ...request, chain: "xrpl" });
2103
+ }
1807
2104
  };
1808
2105
 
1809
2106
  // src/transactions/chains/solana.ts
@@ -1860,6 +2157,28 @@ var TransactionsClient = class {
1860
2157
  async prepareNftTransfer(request) {
1861
2158
  return this.http.post("/nft/transfer/prepare", request);
1862
2159
  }
2160
+ /**
2161
+ * Prepare an NFT collection-create transaction (Polkadot pallet-nfts /
2162
+ * Solana Metaplex master-edition).
2163
+ */
2164
+ async prepareNftCollectionCreate(request) {
2165
+ return this.http.post("/nft/collection/create/prepare", request);
2166
+ }
2167
+ /** Prepare an NFT item set-metadata transaction (Polkadot pallet-nfts/uniques). */
2168
+ async prepareNftSetMetadata(request) {
2169
+ return this.http.post("/nft/set-metadata/prepare", request);
2170
+ }
2171
+ /** Prepare an NFT collection set-metadata transaction (Polkadot pallet-nfts/uniques). */
2172
+ async prepareNftCollectionSetMetadata(request) {
2173
+ return this.http.post("/nft/collection/set-metadata/prepare", request);
2174
+ }
2175
+ /**
2176
+ * Prepare an NFT collection-lock transaction (Polkadot pallet-nfts only).
2177
+ * Asset Hub runtimes on pallet-uniques fallback will reject with a 4xx.
2178
+ */
2179
+ async prepareNftCollectionLock(request) {
2180
+ return this.http.post("/nft/collection/lock/prepare", request);
2181
+ }
1863
2182
  /** Prepare a token creation transaction (Hedera, Solana, Polkadot, Cardano). */
1864
2183
  async prepareTokenCreate(request) {
1865
2184
  return this.http.post("/token/create/prepare", request);
@@ -2170,6 +2489,246 @@ var GovernanceClient = class {
2170
2489
  }
2171
2490
  };
2172
2491
 
2492
+ // src/dao/dashboard-client.ts
2493
+ function buildQuery(params) {
2494
+ const search = new URLSearchParams();
2495
+ for (const [key, value] of Object.entries(params)) {
2496
+ if (value === void 0) continue;
2497
+ search.set(key, String(value));
2498
+ }
2499
+ const qs = search.toString();
2500
+ return qs ? `?${qs}` : "";
2501
+ }
2502
+ var DaoDashboardClient = class {
2503
+ constructor(http) {
2504
+ this.http = http;
2505
+ }
2506
+ http;
2507
+ /** Aggregated dashboard counters for a user's governance home screen. */
2508
+ async getStats(userAddress) {
2509
+ return this.http.get(
2510
+ `/dao/dashboard/stats/${encodeURIComponent(userAddress)}`
2511
+ );
2512
+ }
2513
+ /** Active proposals across every DAO the user belongs to, with vote state. */
2514
+ async getActiveProposals(userAddress) {
2515
+ return this.http.get(
2516
+ `/dao/dashboard/active-proposals/${encodeURIComponent(userAddress)}`
2517
+ );
2518
+ }
2519
+ /** Paginated vote history across DAOs. */
2520
+ async getVoteHistory(userAddress, opts = {}) {
2521
+ const qs = buildQuery({ limit: opts.limit, offset: opts.offset });
2522
+ return this.http.get(
2523
+ `/dao/dashboard/vote-history/${encodeURIComponent(userAddress)}${qs}`
2524
+ );
2525
+ }
2526
+ /** Activity feed (proposal-created/vote-cast/etc.) across user's DAOs. */
2527
+ async getActivity(userAddress, opts = {}) {
2528
+ const qs = buildQuery({ limit: opts.limit, daoId: opts.daoId });
2529
+ return this.http.get(
2530
+ `/dao/dashboard/activity/${encodeURIComponent(userAddress)}${qs}`
2531
+ );
2532
+ }
2533
+ /** Items the user must act on (sign prepared messages, claim NFTs, …). */
2534
+ async getPendingActions(userAddress) {
2535
+ return this.http.get(
2536
+ `/dao/dashboard/pending-actions/${encodeURIComponent(userAddress)}`
2537
+ );
2538
+ }
2539
+ /** Governance impact metrics — weight delivered, success rate, streak. */
2540
+ async getImpact(userAddress) {
2541
+ return this.http.get(
2542
+ `/dao/dashboard/impact/${encodeURIComponent(userAddress)}`
2543
+ );
2544
+ }
2545
+ };
2546
+
2547
+ // src/dao/dao-client.ts
2548
+ function buildQuery2(params) {
2549
+ const search = new URLSearchParams();
2550
+ for (const [key, value] of Object.entries(params)) {
2551
+ if (value === void 0) continue;
2552
+ search.set(key, String(value));
2553
+ }
2554
+ const qs = search.toString();
2555
+ return qs ? `?${qs}` : "";
2556
+ }
2557
+ function encodeDaoId(daoId) {
2558
+ return encodeURIComponent(daoId);
2559
+ }
2560
+ function encodeProposalId(proposalId) {
2561
+ return encodeURIComponent(proposalId);
2562
+ }
2563
+ function encodeAddress(address) {
2564
+ return encodeURIComponent(address);
2565
+ }
2566
+ var DaoClient = class {
2567
+ constructor(http) {
2568
+ this.http = http;
2569
+ this.dashboard = new DaoDashboardClient(http);
2570
+ }
2571
+ http;
2572
+ /** Per-user rollups for the smart-app's governance home screen. */
2573
+ dashboard;
2574
+ // ─── Lifecycle ────────────────────────────────────────────────────────────
2575
+ /** Create a new DAO. */
2576
+ async create(request) {
2577
+ return this.http.post("/dao/create", request);
2578
+ }
2579
+ /** List DAOs with optional status / creator filters. */
2580
+ async list(opts = {}) {
2581
+ const qs = buildQuery2({ status: opts.status, createdBy: opts.createdBy });
2582
+ return this.http.get(`/dao/list${qs}`);
2583
+ }
2584
+ /** Fetch a single DAO by ID. */
2585
+ async get(daoId) {
2586
+ return this.http.get(`/dao/${encodeDaoId(daoId)}`);
2587
+ }
2588
+ /** Fetch a DAO together with its proposals (single round-trip). */
2589
+ async getWithProposals(daoId) {
2590
+ return this.http.get(`/dao/${encodeDaoId(daoId)}/with-proposals`);
2591
+ }
2592
+ // ─── Proposals ────────────────────────────────────────────────────────────
2593
+ /** List proposals for a DAO, optionally filtered by status / proposer. */
2594
+ async listProposals(daoId, opts = {}) {
2595
+ const qs = buildQuery2({ status: opts.status, proposer: opts.proposer });
2596
+ return this.http.get(`/dao/${encodeDaoId(daoId)}/proposals${qs}`);
2597
+ }
2598
+ /** Create a proposal (server activates the proposal immediately). */
2599
+ async createProposal(daoId, request) {
2600
+ return this.http.post(`/dao/${encodeDaoId(daoId)}/proposals`, request);
2601
+ }
2602
+ /**
2603
+ * Prepare a proposal for off-chain signing (returns the message to sign).
2604
+ * Use {@link signProposal} to submit the signature once captured.
2605
+ */
2606
+ async prepareProposal(daoId, request) {
2607
+ return this.http.post(
2608
+ `/dao/${encodeDaoId(daoId)}/proposals/prepare`,
2609
+ request
2610
+ );
2611
+ }
2612
+ /** Submit the signed prepared-proposal payload. */
2613
+ async signProposal(daoId, proposalId, request) {
2614
+ return this.http.post(
2615
+ `/dao/${encodeDaoId(daoId)}/proposals/${encodeProposalId(proposalId)}/sign`,
2616
+ request
2617
+ );
2618
+ }
2619
+ /** Prepare a vote message for off-chain signing. */
2620
+ async prepareVote(daoId, proposalId, request) {
2621
+ return this.http.post(
2622
+ `/dao/${encodeDaoId(daoId)}/proposals/${encodeProposalId(proposalId)}/prepare-vote`,
2623
+ request
2624
+ );
2625
+ }
2626
+ /** Submit the signed prepared-vote payload. */
2627
+ async submitVote(daoId, proposalId, request) {
2628
+ return this.http.post(
2629
+ `/dao/${encodeDaoId(daoId)}/proposals/${encodeProposalId(proposalId)}/submit-vote`,
2630
+ request
2631
+ );
2632
+ }
2633
+ /**
2634
+ * Cast a vote directly (no separate prepare/sign hop — server records the
2635
+ * vote on the caller's behalf). Use {@link prepareVote} + {@link submitVote}
2636
+ * when the smart-app's signing model requires client-side signing.
2637
+ */
2638
+ async vote(daoId, proposalId, request) {
2639
+ return this.http.post(
2640
+ `/dao/${encodeDaoId(daoId)}/proposals/${encodeProposalId(proposalId)}/vote`,
2641
+ request
2642
+ );
2643
+ }
2644
+ /**
2645
+ * Manually execute a passed proposal via TSS. Proposals auto-execute after
2646
+ * the execution delay; this endpoint is for the governance-admin override
2647
+ * path.
2648
+ */
2649
+ async execute(daoId, proposalId) {
2650
+ return this.http.post(
2651
+ `/dao/${encodeDaoId(daoId)}/proposals/${encodeProposalId(proposalId)}/execute`,
2652
+ {}
2653
+ );
2654
+ }
2655
+ /** Paginated vote list for a proposal. */
2656
+ async getVotes(daoId, proposalId, opts = {}) {
2657
+ const qs = buildQuery2({ limit: opts.limit, offset: opts.offset });
2658
+ return this.http.get(
2659
+ `/dao/${encodeDaoId(daoId)}/proposals/${encodeProposalId(proposalId)}/votes${qs}`
2660
+ );
2661
+ }
2662
+ /** Resolved tally / quorum / pass-fail for a proposal. */
2663
+ async getResults(daoId, proposalId) {
2664
+ return this.http.get(
2665
+ `/dao/${encodeDaoId(daoId)}/proposals/${encodeProposalId(proposalId)}/results`
2666
+ );
2667
+ }
2668
+ /** Raw vote counts by option ID (no quorum / pass logic). */
2669
+ async getVoteCounts(daoId, proposalId) {
2670
+ return this.http.get(
2671
+ `/dao/${encodeDaoId(daoId)}/proposals/${encodeProposalId(proposalId)}/vote-counts`
2672
+ );
2673
+ }
2674
+ /** Fetch a single voter's vote on a proposal. */
2675
+ async getVoterRecord(daoId, proposalId, voterAddress) {
2676
+ return this.http.get(
2677
+ `/dao/${encodeDaoId(daoId)}/proposals/${encodeProposalId(proposalId)}/voter/${encodeAddress(voterAddress)}`
2678
+ );
2679
+ }
2680
+ /** Fetch a single proposal by ID. */
2681
+ async getProposal(daoId, proposalId) {
2682
+ return this.http.get(
2683
+ `/dao/${encodeDaoId(daoId)}/proposals/${encodeProposalId(proposalId)}`
2684
+ );
2685
+ }
2686
+ // ─── Treasury ─────────────────────────────────────────────────────────────
2687
+ /** Per-chain treasury balances for a DAO. */
2688
+ async getTreasury(daoId, chain) {
2689
+ const qs = buildQuery2({ chain });
2690
+ return this.http.get(`/dao/${encodeDaoId(daoId)}/treasury${qs}`);
2691
+ }
2692
+ /** Paginated treasury transaction history (in/out/swap). */
2693
+ async getTreasuryHistory(daoId, opts = {}) {
2694
+ const qs = buildQuery2({
2695
+ chain: opts.chain,
2696
+ limit: opts.limit,
2697
+ offset: opts.offset
2698
+ });
2699
+ return this.http.get(`/dao/${encodeDaoId(daoId)}/treasury/history${qs}`);
2700
+ }
2701
+ // ─── Members ──────────────────────────────────────────────────────────────
2702
+ /** List a DAO's members, optionally filtered by status. */
2703
+ async listMembers(daoId, opts = {}) {
2704
+ const qs = buildQuery2({ status: opts.status });
2705
+ return this.http.get(`/dao/${encodeDaoId(daoId)}/members${qs}`);
2706
+ }
2707
+ /** Add a member to a DAO. */
2708
+ async addMember(daoId, request) {
2709
+ return this.http.post(`/dao/${encodeDaoId(daoId)}/members`, request);
2710
+ }
2711
+ /** Remove a member from a DAO. */
2712
+ async removeMember(daoId, address) {
2713
+ return this.http.delete(
2714
+ `/dao/${encodeDaoId(daoId)}/members/${encodeAddress(address)}`
2715
+ );
2716
+ }
2717
+ /** Bind a held membership NFT serial to a member record. */
2718
+ async claimMemberNft(daoId, address, request) {
2719
+ return this.http.post(
2720
+ `/dao/${encodeDaoId(daoId)}/members/${encodeAddress(address)}/claim-nft`,
2721
+ request
2722
+ );
2723
+ }
2724
+ /** Fetch the NFT serials + status for a member. */
2725
+ async getMemberNft(daoId, address) {
2726
+ return this.http.get(
2727
+ `/dao/${encodeDaoId(daoId)}/members/${encodeAddress(address)}/nft`
2728
+ );
2729
+ }
2730
+ };
2731
+
2173
2732
  // src/personhood/personhood-client.ts
2174
2733
  var PersonhoodClient = class {
2175
2734
  constructor(http) {
@@ -2214,15 +2773,25 @@ var AgentsClient = class {
2214
2773
  async list() {
2215
2774
  return this.http.get("/api/agents");
2216
2775
  }
2217
- /** Fund an agent */
2776
+ /**
2777
+ * Fund agent treasury (owner-only). Returns a
2778
+ * `PreparedTransactionResponse` wrapped in a `success: true` envelope —
2779
+ * the caller is expected to sign and submit the prepared bytes.
2780
+ */
2218
2781
  async fund(agentId, request) {
2219
2782
  return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/fund`, request);
2220
2783
  }
2221
- /** Execute a trade */
2784
+ /**
2785
+ * Execute a trade (agent-wallet OR owner). Returns a
2786
+ * `PreparedTransactionResponse` wrapped in a `success: true` envelope.
2787
+ */
2222
2788
  async trade(agentId, request) {
2223
2789
  return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/trade`, request);
2224
2790
  }
2225
- /** Withdraw funds from agent */
2791
+ /**
2792
+ * Withdraw from agent treasury (owner-only). Returns a
2793
+ * `PreparedTransactionResponse` wrapped in a `success: true` envelope.
2794
+ */
2226
2795
  async withdraw(agentId, request) {
2227
2796
  return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/withdraw`, request);
2228
2797
  }
@@ -2238,9 +2807,16 @@ var AgentsClient = class {
2238
2807
  async revoke(agentId) {
2239
2808
  return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/revoke`, {});
2240
2809
  }
2241
- /** Update agent rules */
2810
+ /**
2811
+ * Update agent rules.
2812
+ *
2813
+ * Server route is PATCH `/api/agents/:agentId/rules`
2814
+ * (`agents.controller.ts:375`). The previous PUT variant 404'd because
2815
+ * Nest matched the dynamic `:agentId` GET/POST handlers and rejected
2816
+ * the verb mismatch.
2817
+ */
2242
2818
  async updateRules(agentId, rules) {
2243
- return this.http.put(`/api/agents/${encodeURIComponent(agentId)}/rules`, rules);
2819
+ return this.http.patch(`/api/agents/${encodeURIComponent(agentId)}/rules`, rules);
2244
2820
  }
2245
2821
  /** Get agent events */
2246
2822
  async getEvents(agentId) {
@@ -2366,6 +2942,276 @@ var DeploymentClient = class {
2366
2942
  async getStats() {
2367
2943
  return this.http.get("/api/deployment/stats");
2368
2944
  }
2945
+ /**
2946
+ * Register or update the developer-facing webhook URL for runtime
2947
+ * lifecycle events (`runtime.deploying` / `running` / `failed` /
2948
+ * `suspended` / `resumed` / `retired`).
2949
+ *
2950
+ * The host's `DeployWebhookDispatcher` POSTs to this URL whenever the
2951
+ * smart-deployer reconciler emits a `runtime.*` NATS event, signed with
2952
+ * the returned `webhookSecret`:
2953
+ *
2954
+ * `X-HSuite-Signature: sha256=<hmac-sha256(secret, raw-body)>`
2955
+ *
2956
+ * Store `webhookSecret` server-side and re-compute the signature over
2957
+ * the raw delivery body to verify authenticity. The secret is surfaced
2958
+ * only on PUT — re-call this method to rotate.
2959
+ *
2960
+ * Server validates: HTTPS only, no loopback / RFC1918 / link-local /
2961
+ * CGNAT / cloud metadata destinations (SSRF guard).
2962
+ */
2963
+ async setWebhook(appId, webhookUrl) {
2964
+ return this.http.put(`/api/deployment/apps/${encodeURIComponent(appId)}/webhook`, {
2965
+ webhookUrl
2966
+ });
2967
+ }
2968
+ /**
2969
+ * Per-app Prometheus metrics in the standard exposition format
2970
+ * (text/plain; version=0.0.4). The server filters smart-deployer's
2971
+ * `/metrics` to lines that mention this app's `appId` label, while
2972
+ * preserving HELP / TYPE comment lines and cluster-wide metrics.
2973
+ *
2974
+ * Returned as a raw string so callers can pipe directly into a
2975
+ * Prometheus parser (`prom-client`, `parse-prometheus-text-format`,
2976
+ * etc.) without an intermediate JSON decode that would corrupt the
2977
+ * exposition format.
2978
+ */
2979
+ async getMetrics(appId) {
2980
+ return this.http.getText(`/api/deployment/apps/${encodeURIComponent(appId)}/metrics`);
2981
+ }
2982
+ /**
2983
+ * Rotate the smart-app's tenant-secret KEK (ADR-011 Phase 6).
2984
+ *
2985
+ * Re-encrypts every `runtime.env` envelope at the new KEK version
2986
+ * transparently. Previous versions remain valid until explicitly
2987
+ * revoked via {@link revokeKek}. Owner-only.
2988
+ */
2989
+ async rotateKek(appId) {
2990
+ return this.http.post(
2991
+ `/api/deployment/apps/${encodeURIComponent(appId)}/credentials/rotate-kek`,
2992
+ {}
2993
+ );
2994
+ }
2995
+ /**
2996
+ * Revoke a tenant-secret KEK version (ADR-011 Phase 6 emergency burn).
2997
+ *
2998
+ * Envelopes at the revoked version become operationally dead —
2999
+ * decryption inside the smart-app pod fails. Owner-only and
3000
+ * **irreversible**. Returns the cumulative list of revoked versions
3001
+ * for this app.
3002
+ */
3003
+ async revokeKek(appId, version) {
3004
+ return this.http.post(
3005
+ `/api/deployment/apps/${encodeURIComponent(appId)}/credentials/revoke-kek`,
3006
+ { version }
3007
+ );
3008
+ }
3009
+ };
3010
+
3011
+ // src/bridge/bridge-client.ts
3012
+ var BridgeClient = class {
3013
+ constructor(http) {
3014
+ this.http = http;
3015
+ }
3016
+ http;
3017
+ /** Create a new bridge instance — triggers DKG + TSS entity creation server-side. */
3018
+ async create(request) {
3019
+ return this.http.post("/bridge/create", request);
3020
+ }
3021
+ /** List bridges. Both filters are optional. */
3022
+ async list(options) {
3023
+ const params = new URLSearchParams();
3024
+ if (options?.status) params.append("status", options.status);
3025
+ if (options?.sourceChain) params.append("sourceChain", options.sourceChain);
3026
+ const qs = params.toString();
3027
+ return this.http.get(`/bridge/list${qs ? `?${qs}` : ""}`);
3028
+ }
3029
+ /** Get bridge configuration. */
3030
+ async get(bridgeId) {
3031
+ return this.http.get(`/bridge/${encodePathParam(bridgeId)}`);
3032
+ }
3033
+ /** Port tokens from source → destination. */
3034
+ async port(bridgeId, request) {
3035
+ return this.http.post(`/bridge/${encodePathParam(bridgeId)}/port`, request);
3036
+ }
3037
+ /**
3038
+ * Return tokens from destination → source. Only meaningful on two-way
3039
+ * bridges; the validator rejects the call on one-way bridges with a 400.
3040
+ *
3041
+ * Method name is `return_` to avoid colliding with the reserved JS
3042
+ * keyword in some downstream codegen. Prefer `client.bridge.return(...)`
3043
+ * via the named alias below.
3044
+ */
3045
+ async return(bridgeId, request) {
3046
+ return this.http.post(`/bridge/${encodePathParam(bridgeId)}/return`, request);
3047
+ }
3048
+ /** Get claim status by claim ID under a given bridge. */
3049
+ async getStatus(bridgeId, claimId) {
3050
+ return this.http.get(
3051
+ `/bridge/${encodePathParam(bridgeId)}/status/${encodePathParam(claimId)}`
3052
+ );
3053
+ }
3054
+ /** Get aggregate supply view for a bridge. */
3055
+ async getSupply(bridgeId) {
3056
+ return this.http.get(`/bridge/${encodePathParam(bridgeId)}/supply`);
3057
+ }
3058
+ /** List bridge claims with optional pagination. */
3059
+ async listClaims(bridgeId, options) {
3060
+ const params = new URLSearchParams();
3061
+ if (options?.limit !== void 0) params.append("limit", String(options.limit));
3062
+ if (options?.offset !== void 0) params.append("offset", String(options.offset));
3063
+ const qs = params.toString();
3064
+ return this.http.get(
3065
+ `/bridge/${encodePathParam(bridgeId)}/claims${qs ? `?${qs}` : ""}`
3066
+ );
3067
+ }
3068
+ };
3069
+
3070
+ // src/resources/resources-client.ts
3071
+ var ResourcesClient = class {
3072
+ constructor(http) {
3073
+ this.http = http;
3074
+ }
3075
+ http;
3076
+ /** Network-wide consumption summary across all nodes. */
3077
+ async getSummary() {
3078
+ return this.http.get("/resources/summary");
3079
+ }
3080
+ /** Current-day consumption breakdown for an app. */
3081
+ async getConsumption(appId) {
3082
+ return this.http.get(`/resources/consumption/${encodePathParam(appId)}`);
3083
+ }
3084
+ /** Daily usage history from the persistent store. `days` defaults to 30 server-side. */
3085
+ async getHistory(appId, days) {
3086
+ const qs = days !== void 0 ? `?days=${days}` : "";
3087
+ return this.http.get(
3088
+ `/resources/consumption/${encodePathParam(appId)}/history${qs}`
3089
+ );
3090
+ }
3091
+ /** Paginated billing ledger. All filters optional. */
3092
+ async getLedger(appId, options) {
3093
+ const params = new URLSearchParams();
3094
+ if (options?.limit !== void 0) params.append("limit", String(options.limit));
3095
+ if (options?.offset !== void 0) params.append("offset", String(options.offset));
3096
+ if (options?.since) params.append("since", options.since);
3097
+ if (options?.until) params.append("until", options.until);
3098
+ if (options?.category) params.append("category", options.category);
3099
+ const qs = params.toString();
3100
+ return this.http.get(
3101
+ `/resources/consumption/${encodePathParam(appId)}/ledger${qs ? `?${qs}` : ""}`
3102
+ );
3103
+ }
3104
+ /**
3105
+ * Current consumption status with threshold warnings and upgrade hints.
3106
+ * `dailyLimit` overrides the per-app tier default and is rare —
3107
+ * smart-app callers should leave it unset.
3108
+ */
3109
+ async getStatus(appId, dailyLimit) {
3110
+ const qs = dailyLimit !== void 0 ? `?dailyLimit=${dailyLimit}` : "";
3111
+ return this.http.get(
3112
+ `/resources/consumption/${encodePathParam(appId)}/status${qs}`
3113
+ );
3114
+ }
3115
+ /** Consumption aggregated by category over the supplied window. */
3116
+ async getBreakdown(appId, options) {
3117
+ const params = new URLSearchParams();
3118
+ if (options?.since) params.append("since", options.since);
3119
+ if (options?.until) params.append("until", options.until);
3120
+ const qs = params.toString();
3121
+ return this.http.get(
3122
+ `/resources/consumption/${encodePathParam(appId)}/breakdown${qs ? `?${qs}` : ""}`
3123
+ );
3124
+ }
3125
+ /** Per-node consumption reports. */
3126
+ async listNodes() {
3127
+ return this.http.get("/resources/nodes");
3128
+ }
3129
+ /** Single node's report. */
3130
+ async getNode(nodeId) {
3131
+ return this.http.get(`/resources/nodes/${encodePathParam(nodeId)}`);
3132
+ }
3133
+ };
3134
+
3135
+ // src/envelope/envelope-client.ts
3136
+ var EnvelopeClient = class {
3137
+ constructor(http) {
3138
+ this.http = http;
3139
+ }
3140
+ http;
3141
+ /**
3142
+ * Seal `plaintext` under the per-app KEK for `appId` at `kekVersion`.
3143
+ * Returns the canonical envelope shape suitable for persistence in
3144
+ * Mongo / NATS / on the EventBus.
3145
+ */
3146
+ async encrypt(request) {
3147
+ return this.http.post("/envelope/encrypt", request);
3148
+ }
3149
+ /**
3150
+ * Open `envelope` for `appId`. The plaintext is returned in the response
3151
+ * body — callers MUST treat it as ephemeral (no logs, no Mongo, no
3152
+ * NATS broadcast). The validator never persists or replays it.
3153
+ */
3154
+ async decrypt(request) {
3155
+ return this.http.post("/envelope/decrypt", request);
3156
+ }
3157
+ };
3158
+
3159
+ // src/tokens/tokens-client.ts
3160
+ var TokensClient = class {
3161
+ constructor(http) {
3162
+ this.http = http;
3163
+ }
3164
+ http;
3165
+ /** Initiate a token migration to TSS-controlled keys. */
3166
+ async migrate(request) {
3167
+ return this.http.post("/tokens/migrate", request);
3168
+ }
3169
+ /** List all known migrations on this validator. */
3170
+ async listMigrations() {
3171
+ return this.http.get("/tokens/migrations");
3172
+ }
3173
+ /**
3174
+ * Get one migration's status by id. The server returns
3175
+ * `{ error: string }` (NOT a 404) when the migration is unknown, so the
3176
+ * union type makes the failure mode explicit.
3177
+ */
3178
+ async getMigration(migrationId) {
3179
+ return this.http.get(`/tokens/migrations/${encodePathParam(migrationId)}`);
3180
+ }
3181
+ /** All migrations recorded against a specific token id. */
3182
+ async getMigrationsForToken(tokenId) {
3183
+ return this.http.get(`/tokens/${encodePathParam(tokenId)}/migrations`);
3184
+ }
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
+ };
3196
+
3197
+ // src/operator/operator-client.ts
3198
+ var OperatorClient = class {
3199
+ constructor(http) {
3200
+ this.http = http;
3201
+ }
3202
+ http;
3203
+ /** Get the on-chain HBAR + token balance of an operator account. */
3204
+ async getBalance(chain, accountId) {
3205
+ return this.http.get(
3206
+ `/operator/balance/${encodePathParam(chain)}/${encodePathParam(accountId)}`
3207
+ );
3208
+ }
3209
+ /** Get top-up guidance for an operator account (recommended balance + status). */
3210
+ async getTopup(chain, accountId) {
3211
+ return this.http.get(
3212
+ `/operator/topup/${encodePathParam(chain)}/${encodePathParam(accountId)}`
3213
+ );
3214
+ }
2369
3215
  };
2370
3216
 
2371
3217
  // src/client.ts
@@ -2402,12 +3248,26 @@ var SmartEngineClient = class _SmartEngineClient {
2402
3248
  settlement;
2403
3249
  /** Governance proposal dry-run (simulate-only) */
2404
3250
  governance;
3251
+ /** DAO governance — DAOs, proposals, votes, treasury, members, dashboard */
3252
+ dao;
2405
3253
  /** Personhood verification (HPP one-human-one-member) */
2406
3254
  personhood;
2407
3255
  /** BaaS smart-agent lifecycle (register/fund/trade/withdraw/pause/resume/revoke/...) */
2408
3256
  agents;
2409
3257
  /** BaaS smart-app deployment lifecycle (init/uploadFrontend/deploy/rollback/status/...) */
2410
3258
  deployments;
3259
+ /** Universal Token Bridge — port/return/claim across chains */
3260
+ bridge;
3261
+ /** Network + per-app resource consumption (summary, history, ledger, nodes) */
3262
+ resources;
3263
+ /** AES-256-GCM envelope encrypt/decrypt under the TSS-backed master KEK */
3264
+ envelope;
3265
+ /** Token migration — move existing tokens to TSS-controlled keys */
3266
+ tokens;
3267
+ /** Operator account funding helpers (balance + top-up guidance) */
3268
+ operator;
3269
+ /** Discovery endpoints — cluster registry + platform-image manifests */
3270
+ discovery;
2411
3271
  constructor(config) {
2412
3272
  this.allowInsecure = config.allowInsecure ?? false;
2413
3273
  this.baseUrl = validateClientUrl(config.baseUrl, this.allowInsecure);
@@ -2427,7 +3287,7 @@ var SmartEngineClient = class _SmartEngineClient {
2427
3287
  this.tss = new TSSClient(this.http);
2428
3288
  this.ipfs = new IPFSClient(this.http);
2429
3289
  this.transactions = new TransactionsClient(this.txHttp);
2430
- this.hedera = new HederaTransactionsClient(this.txHttp);
3290
+ this.hedera = new HederaTransactionsClient(this.txHttp, this.http);
2431
3291
  this.xrpl = new XrplTransactionsClient(this.txHttp);
2432
3292
  this.solana = new SolanaTransactionsClient(this.txHttp);
2433
3293
  this.polkadot = new PolkadotTransactionsClient(this.txHttp);
@@ -2435,6 +3295,7 @@ var SmartEngineClient = class _SmartEngineClient {
2435
3295
  this.historicalBalance = HistoricalBalanceClient.fromHttp(this.http);
2436
3296
  this.settlement = new SettlementClient(this.http);
2437
3297
  this.governance = new GovernanceClient(this.http);
3298
+ this.dao = new DaoClient(this.http);
2438
3299
  this.personhood = new PersonhoodClient(this.http);
2439
3300
  const rootHttp = createHttpClient({
2440
3301
  baseUrl: this.baseUrl,
@@ -2444,6 +3305,12 @@ var SmartEngineClient = class _SmartEngineClient {
2444
3305
  });
2445
3306
  this.agents = new AgentsClient(rootHttp);
2446
3307
  this.deployments = new DeploymentClient(rootHttp);
3308
+ this.bridge = new BridgeClient(this.http);
3309
+ this.resources = new ResourcesClient(this.http);
3310
+ this.envelope = new EnvelopeClient(this.http);
3311
+ this.tokens = new TokensClient(this.http);
3312
+ this.operator = new OperatorClient(this.http);
3313
+ this.discovery = new DiscoveryClient(this.http);
2447
3314
  }
2448
3315
  /**
2449
3316
  * Build a `SmartEngineClient` from a plain env object. Reads:
@@ -2659,7 +3526,19 @@ var SmartEngineClient = class _SmartEngineClient {
2659
3526
  const validated = MintTokenRequestSchema.parse(request);
2660
3527
  return this.http.post("/tokens/mint", validated);
2661
3528
  }
2662
- /** Get token information */
3529
+ /**
3530
+ * Get token information.
3531
+ *
3532
+ * Route `GET /api/v3/tokens/:chain/:tokenId` is registered twice on the
3533
+ * validator: by `ValidatorController` at
3534
+ * `apps/smart-validator/src/validator.controller.ts:497` and by
3535
+ * `TokenMigrationController` at
3536
+ * `apps/smart-validator/src/token-migration/token-migration.controller.ts:173`.
3537
+ * Nest resolves routes in `controllers: [...]` order — `ValidatorController`
3538
+ * is registered first (`apps/smart-validator/src/smart-validator.module.ts:1222`),
3539
+ * so `multiChain.getTokenInfo(chain, tokenId)` wins and the
3540
+ * token-migration handler is unreachable via this path.
3541
+ */
2663
3542
  async getTokenInfo(chain, tokenId) {
2664
3543
  return this.http.get(`/tokens/${encodePathParam(chain)}/${encodePathParam(tokenId)}`);
2665
3544
  }
@@ -2807,47 +3686,56 @@ var RoutingClient = class {
2807
3686
  this.http = http;
2808
3687
  }
2809
3688
  http;
2810
- /** Register a new host */
3689
+ /**
3690
+ * Register a new host. The server validates the payload via Zod (appId
3691
+ * pattern, IP/hostname format, port range) and kicks off async
3692
+ * verification. Response includes the registered host plus a status
3693
+ * message about verification.
3694
+ */
2811
3695
  async registerHost(request) {
2812
3696
  return this.http.post("/routing/hosts", request);
2813
3697
  }
2814
- /** Unregister a host */
3698
+ /** Unregister a host. */
2815
3699
  async unregisterHost(hostId) {
2816
3700
  return this.http.delete(`/routing/hosts/${encodeURIComponent(hostId)}`);
2817
3701
  }
2818
- /** Get all registered hosts */
3702
+ /** Get all registered hosts. */
2819
3703
  async getAllHosts() {
2820
3704
  return this.http.get("/routing/hosts");
2821
3705
  }
2822
- /** Get only verified hosts */
3706
+ /** Get only verified hosts. */
2823
3707
  async getVerifiedHosts() {
2824
3708
  return this.http.get("/routing/hosts/verified");
2825
3709
  }
2826
- /** Get a specific host by ID */
3710
+ /** Get a specific host by ID. */
2827
3711
  async getHost(hostId) {
2828
3712
  return this.http.get(`/routing/hosts/${encodeURIComponent(hostId)}`);
2829
3713
  }
2830
- /** Verify a host */
3714
+ /** Trigger host re-verification. */
2831
3715
  async verifyHost(hostId) {
2832
3716
  return this.http.post(`/routing/hosts/${encodeURIComponent(hostId)}/verify`, {});
2833
3717
  }
2834
- /** Set routing configuration for an app */
3718
+ /** Set routing configuration for an app. */
2835
3719
  async setRoutingConfig(appId, config) {
2836
3720
  return this.http.put(`/routing/config/${encodeURIComponent(appId)}`, config);
2837
3721
  }
2838
- /** Get routing configuration for an app */
3722
+ /** Get routing configuration for an app. */
2839
3723
  async getRoutingConfig(appId) {
2840
3724
  return this.http.get(`/routing/config/${encodeURIComponent(appId)}`);
2841
3725
  }
2842
- /** Proxy a request through the gateway */
3726
+ /** Proxy a request through the gateway. */
2843
3727
  async proxyRequest(request) {
2844
3728
  return this.http.post("/routing/proxy", request);
2845
3729
  }
2846
- /** Get routing statistics */
3730
+ /** Get routing statistics. */
2847
3731
  async getStats() {
2848
3732
  return this.http.get("/routing/stats");
2849
3733
  }
2850
- /** Map a domain to an application */
3734
+ /**
3735
+ * Map a domain/subdomain to an application for hostname-based routing.
3736
+ * The server returns `{ domain, appId, message }` — there is no `success`
3737
+ * field; treat `appId` as the success signal.
3738
+ */
2851
3739
  async mapDomainToApp(domain, appId) {
2852
3740
  return this.http.post(`/routing/domains/${encodeURIComponent(domain)}/map`, { appId });
2853
3741
  }
@@ -2876,7 +3764,11 @@ var DomainsClient = class {
2876
3764
  const params = owner ? `?owner=${encodeURIComponent(owner)}` : "";
2877
3765
  return this.http.get(`/domains${params}`);
2878
3766
  }
2879
- /** Generate a verification token */
3767
+ /**
3768
+ * Generate a verification token. Server accepts one of `dns-txt`,
3769
+ * `dns-cname`, `http-file`, `email` (see controller Swagger enum at
3770
+ * `apps/smart-gateway/src/domains/domains.controller.ts:226-234`).
3771
+ */
2880
3772
  async generateVerificationToken(domain, method) {
2881
3773
  return this.http.post(`/domains/${encodeURIComponent(domain)}/verification`, { method });
2882
3774
  }
@@ -2992,6 +3884,23 @@ var DnsClient = class {
2992
3884
  }
2993
3885
  };
2994
3886
 
3887
+ // src/gateway/health/index.ts
3888
+ var HealthClient = class {
3889
+ constructor(http) {
3890
+ this.http = http;
3891
+ }
3892
+ http;
3893
+ /**
3894
+ * Per-cluster aggregate health probe. Wraps
3895
+ * `GET /api/v3/cluster/health` — see
3896
+ * `apps/smart-gateway/src/health/health.controller.ts:213-263`. Returns
3897
+ * local validator + host + genesis state in a single payload.
3898
+ */
3899
+ async getCluster() {
3900
+ return this.http.get("/cluster/health");
3901
+ }
3902
+ };
3903
+
2995
3904
  // src/gateway/client.ts
2996
3905
  var SmartGatewayClient = class {
2997
3906
  http;
@@ -3001,6 +3910,8 @@ var SmartGatewayClient = class {
3001
3910
  domains;
3002
3911
  /** DNS resolution and zone management */
3003
3912
  dns;
3913
+ /** Per-cluster aggregate health probe (validator + host + genesis state) */
3914
+ health;
3004
3915
  constructor(config) {
3005
3916
  const baseUrl = config.baseUrl.replace(/\/+$/, "");
3006
3917
  this.http = createHttpClient({
@@ -3012,30 +3923,41 @@ var SmartGatewayClient = class {
3012
3923
  this.routing = new RoutingClient(this.http);
3013
3924
  this.domains = new DomainsClient(this.http);
3014
3925
  this.dns = new DnsClient(this.http);
3926
+ this.health = new HealthClient(this.http);
3015
3927
  }
3016
3928
  // ========== Health & Metrics ==========
3017
- /** Get gateway health status */
3929
+ /** Get gateway-only health status (binary `status: 'ok'` snapshot). */
3018
3930
  async getHealth() {
3019
3931
  return this.http.get("/health");
3020
3932
  }
3021
- /** Get gateway status with host and domain counts */
3933
+ /**
3934
+ * Get detailed gateway status — `subsystems` tree (dns/routing/verification)
3935
+ * plus the operating `mode` snapshot. Aggregated counts live on `getMetrics()`.
3936
+ */
3022
3937
  async getStatus() {
3023
3938
  return this.http.get("/status");
3024
3939
  }
3025
- /** Check gateway readiness */
3940
+ /**
3941
+ * Check gateway readiness. Returns either `{ status: 'ready', ... }` with
3942
+ * a verified host count or `{ status: 'not_ready', reason, ... }`.
3943
+ */
3026
3944
  async getReadiness() {
3027
3945
  return this.http.get("/ready");
3028
3946
  }
3029
- /** Check gateway liveness */
3947
+ /** Check gateway liveness. */
3030
3948
  async getLiveness() {
3031
3949
  return this.http.get("/live");
3032
3950
  }
3033
- /** Get detailed gateway metrics */
3951
+ /**
3952
+ * Get aggregated network metrics across all clusters — per-cluster health,
3953
+ * chain connectivity, gateway counts, and genesis state. Server caches the
3954
+ * payload (default 30s); pass `refresh=true` to force a fresh fetch.
3955
+ */
3034
3956
  async getMetrics(refresh) {
3035
3957
  const params = refresh ? "?refresh=true" : "";
3036
3958
  return this.http.get(`/metrics${params}`);
3037
3959
  }
3038
- /** Get metrics summary */
3960
+ /** Get lightweight network summary (status-badge-friendly). */
3039
3961
  async getMetricsSummary() {
3040
3962
  return this.http.get("/metrics/summary");
3041
3963
  }
@@ -3096,11 +4018,37 @@ var DatabaseClient = class {
3096
4018
  );
3097
4019
  }
3098
4020
  /**
3099
- * List collections for the app
4021
+ * List collections for the app.
4022
+ *
4023
+ * Server route is `/api/db/:appId/collections`
4024
+ * (`database.controller.ts:106`). The previous bare-`:appId` GET 404'd
4025
+ * — Nest reserves that pattern for the document-find router below.
3100
4026
  */
3101
4027
  async listCollections() {
3102
4028
  const appId = this.getAppId();
3103
- return this.http.get(`/api/db/${encodeURIComponent(appId)}`);
4029
+ return this.http.get(`/api/db/${encodeURIComponent(appId)}/collections`);
4030
+ }
4031
+ /**
4032
+ * Create a new collection in the database.
4033
+ *
4034
+ * Server returns `{ success: true; collection: string }`
4035
+ * (`database.controller.ts:96`).
4036
+ */
4037
+ async createCollection(name) {
4038
+ const appId = this.getAppId();
4039
+ return this.http.post(`/api/db/${encodeURIComponent(appId)}/collections`, { name });
4040
+ }
4041
+ /**
4042
+ * Drop a collection and all its documents.
4043
+ *
4044
+ * Server returns `{ success: true }`
4045
+ * (`database.controller.ts:133`).
4046
+ */
4047
+ async dropCollection(name) {
4048
+ const appId = this.getAppId();
4049
+ return this.http.delete(
4050
+ `/api/db/${encodeURIComponent(appId)}/collections/${encodeURIComponent(name)}`
4051
+ );
3104
4052
  }
3105
4053
  // ========== State Proofs ==========
3106
4054
  /**
@@ -3161,13 +4109,15 @@ var StorageClient = class {
3161
4109
  * Download a file by CID
3162
4110
  */
3163
4111
  async download(cid) {
3164
- return this.http.get(`/api/storage/download/${encodeURIComponent(cid)}`);
4112
+ const appId = this.getAppId();
4113
+ return this.http.get(`/api/storage/${encodeURIComponent(appId)}/download/${encodeURIComponent(cid)}`);
3165
4114
  }
3166
4115
  /**
3167
4116
  * Get file metadata
3168
4117
  */
3169
4118
  async getMetadata(cid) {
3170
- return this.http.get(`/api/storage/metadata/${encodeURIComponent(cid)}`);
4119
+ const appId = this.getAppId();
4120
+ return this.http.get(`/api/storage/${encodeURIComponent(appId)}/metadata/${encodeURIComponent(cid)}`);
3171
4121
  }
3172
4122
  /**
3173
4123
  * Delete a file
@@ -3177,20 +4127,29 @@ var StorageClient = class {
3177
4127
  return this.http.delete(`/api/storage/${encodeURIComponent(appId)}/${encodeURIComponent(cid)}`);
3178
4128
  }
3179
4129
  /**
3180
- * Get file info
4130
+ * Get file info.
4131
+ *
4132
+ * @deprecated The smart-host storage controller does not expose a
4133
+ * bare-CID metadata route — every metadata lookup must go through
4134
+ * `getMetadata(cid)` (`/api/storage/:appId/metadata/:cid`) or the
4135
+ * stream body via `download(cid)`. This alias forwards to `download`
4136
+ * for back-compat; remove in the next major SDK release.
3181
4137
  */
3182
4138
  async getFile(cid) {
3183
- const appId = this.getAppId();
3184
- return this.http.get(`/api/storage/${encodeURIComponent(appId)}/${encodeURIComponent(cid)}`);
4139
+ return this.download(cid);
3185
4140
  }
3186
4141
  /**
3187
4142
  * List all files for the app
4143
+ *
4144
+ * @param pagination.offset Server reads `offset`; the legacy `skip`
4145
+ * option was a client-only synonym that the server silently ignored.
4146
+ * Use `offset` going forward.
3188
4147
  */
3189
4148
  async listFiles(pagination) {
3190
4149
  const appId = this.getAppId();
3191
4150
  const params = new URLSearchParams();
3192
4151
  if (pagination?.limit !== void 0) params.set("limit", String(pagination.limit));
3193
- if (pagination?.skip !== void 0) params.set("skip", String(pagination.skip));
4152
+ if (pagination?.offset !== void 0) params.set("offset", String(pagination.offset));
3194
4153
  const qs = params.toString();
3195
4154
  return this.http.get(`/api/storage/${encodeURIComponent(appId)}/files${qs ? `?${qs}` : ""}`);
3196
4155
  }
@@ -3198,13 +4157,15 @@ var StorageClient = class {
3198
4157
  * Get storage usage for the current app
3199
4158
  */
3200
4159
  async getUsage() {
3201
- return this.http.get("/api/storage/usage");
4160
+ const appId = this.getAppId();
4161
+ return this.http.get(`/api/storage/${encodeURIComponent(appId)}/usage`);
3202
4162
  }
3203
4163
  /**
3204
4164
  * Check if a file exists
3205
4165
  */
3206
4166
  async exists(cid) {
3207
- return this.http.get(`/api/storage/exists/${encodeURIComponent(cid)}`);
4167
+ const appId = this.getAppId();
4168
+ return this.http.get(`/api/storage/${encodeURIComponent(appId)}/exists/${encodeURIComponent(cid)}`);
3208
4169
  }
3209
4170
  };
3210
4171
 
@@ -3227,42 +4188,60 @@ var FunctionsClient = class {
3227
4188
  * Invoke a function
3228
4189
  */
3229
4190
  async invoke(functionId, payload) {
3230
- return this.http.post(`/api/functions/${encodeURIComponent(functionId)}/invoke`, payload ?? {});
4191
+ const appId = this.getAppId();
4192
+ return this.http.post(
4193
+ `/api/functions/${encodeURIComponent(appId)}/${encodeURIComponent(functionId)}/invoke`,
4194
+ payload ?? {}
4195
+ );
3231
4196
  }
3232
4197
  /**
3233
- * List all functions
4198
+ * List all functions for the current app
3234
4199
  */
3235
4200
  async list() {
3236
- return this.http.get("/api/functions");
4201
+ const appId = this.getAppId();
4202
+ return this.http.get(`/api/functions/${encodeURIComponent(appId)}`);
3237
4203
  }
3238
4204
  /**
3239
4205
  * Get function details
3240
4206
  */
3241
4207
  async get(functionId) {
3242
- return this.http.get(`/api/functions/${encodeURIComponent(functionId)}`);
4208
+ const appId = this.getAppId();
4209
+ return this.http.get(
4210
+ `/api/functions/${encodeURIComponent(appId)}/${encodeURIComponent(functionId)}`
4211
+ );
3243
4212
  }
3244
4213
  /**
3245
4214
  * Update a function
3246
4215
  */
3247
4216
  async update(functionId, updates) {
3248
- return this.http.put(`/api/functions/${encodeURIComponent(functionId)}`, updates);
4217
+ const appId = this.getAppId();
4218
+ return this.http.put(
4219
+ `/api/functions/${encodeURIComponent(appId)}/${encodeURIComponent(functionId)}`,
4220
+ updates
4221
+ );
3249
4222
  }
3250
4223
  /**
3251
4224
  * Delete a function
3252
4225
  */
3253
4226
  async delete(functionId) {
3254
- return this.http.delete(`/api/functions/${encodeURIComponent(functionId)}`);
4227
+ const appId = this.getAppId();
4228
+ return this.http.delete(
4229
+ `/api/functions/${encodeURIComponent(appId)}/${encodeURIComponent(functionId)}`
4230
+ );
3255
4231
  }
3256
4232
  /**
3257
4233
  * Get function execution logs
3258
4234
  */
3259
4235
  async getLogs(functionId, options) {
4236
+ const appId = this.getAppId();
3260
4237
  const params = new URLSearchParams();
3261
4238
  if (options?.limit !== void 0) params.set("limit", String(options.limit));
3262
4239
  if (options?.startTime) params.set("startTime", options.startTime);
3263
4240
  if (options?.level) params.set("level", options.level);
3264
4241
  const qs = params.toString();
3265
- return this.http.get(`/api/functions/${encodeURIComponent(functionId)}/logs${qs ? `?${qs}` : ""}`);
4242
+ return this.http.get(
4243
+ `/api/functions/${encodeURIComponent(appId)}/${encodeURIComponent(functionId)}/logs${qs ? `?${qs}` : ""}`
4244
+ );
3266
4245
  }
3267
4246
  /**
3268
4247
  * Get function statistics for an app
@@ -3334,25 +4313,43 @@ var MessagingClient = class {
3334
4313
  );
3335
4314
  }
3336
4315
  /**
3337
- * Set presence for a member
4316
+ * Set presence for a member in a channel.
4317
+ *
4318
+ * BREAKING CHANGE (SDK 3.3.0): presence is channel-scoped on the server
4319
+ * (`messaging.controller.ts:312`). Previous signature
4320
+ * `setPresence(member)` hit a non-existent appId-scoped route and 404'd
4321
+ * in production. The channel is now the first argument.
3338
4322
  */
3339
- async setPresence(member) {
4323
+ async setPresence(channel, member) {
3340
4324
  const appId = this.getAppId();
3341
- return this.http.post(`/api/messaging/${encodeURIComponent(appId)}/presence`, member);
4325
+ return this.http.post(
4326
+ `/api/messaging/${encodeURIComponent(appId)}/channels/${encodeURIComponent(channel)}/presence`,
4327
+ member
4328
+ );
3342
4329
  }
3343
4330
  /**
3344
- * Remove presence for a member
4331
+ * Remove a member's presence from a channel.
4332
+ *
4333
+ * BREAKING CHANGE (SDK 3.3.0): server route is
4334
+ * `/api/messaging/:appId/channels/:channel/presence/:clientId`
4335
+ * (`messaging.controller.ts:352`). `channel` is now the first arg and
4336
+ * `clientId` (not `memberId`) the second — they're the same identifier
4337
+ * but renamed to match the server param.
3345
4338
  */
3346
- async removePresence(memberId) {
4339
+ async removePresence(channel, clientId) {
3347
4340
  const appId = this.getAppId();
3348
- return this.http.delete(`/api/messaging/${encodeURIComponent(appId)}/presence/${encodeURIComponent(memberId)}`);
4341
+ return this.http.delete(
4342
+ `/api/messaging/${encodeURIComponent(appId)}/channels/${encodeURIComponent(channel)}/presence/${encodeURIComponent(clientId)}`
4343
+ );
3349
4344
  }
3350
4345
  /**
3351
4346
  * Get presence info for a channel
3352
4347
  */
3353
4348
  async getPresence(channel) {
3354
4349
  const appId = this.getAppId();
3355
- return this.http.get(`/api/messaging/${encodeURIComponent(appId)}/presence/${encodeURIComponent(channel)}`);
4350
+ return this.http.get(
4351
+ `/api/messaging/${encodeURIComponent(appId)}/channels/${encodeURIComponent(channel)}/presence`
4352
+ );
3356
4353
  }
3357
4354
  /**
3358
4355
  * Get messaging statistics