@hsuite/smart-engines-sdk 3.2.1 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -5479,29 +5479,6 @@ zod.z.object({
5479
5479
  blockTime: zod.z.number().optional(),
5480
5480
  rpcEndpoint: zod.z.string().url().optional()
5481
5481
  });
5482
- var NetworkMembershipTypeSchema = zod.z.enum(["validator", "host", "gateway"]);
5483
- var MembershipStatusSchema = zod.z.enum(["pending", "active", "exiting", "exited", "banned"]);
5484
- zod.z.object({
5485
- nodeId: zod.z.string().min(1),
5486
- networkType: NetworkMembershipTypeSchema,
5487
- chain: zod.z.enum(["hedera", "xrpl", "polkadot", "solana"]),
5488
- endpoint: zod.z.string().url(),
5489
- publicKey: zod.z.string().min(1),
5490
- joinedAt: zod.z.string().datetime(),
5491
- depositTxId: zod.z.string().min(1),
5492
- status: MembershipStatusSchema,
5493
- networkConfig: zod.z.record(zod.z.unknown()).optional()
5494
- });
5495
- var NetworkDepositRequirementsSchema = zod.z.object({
5496
- depositAmount: zod.z.string().min(1),
5497
- lockDurationDays: zod.z.number().int().positive(),
5498
- renewalWindowDays: zod.z.number().int().positive().optional()
5499
- });
5500
- zod.z.object({
5501
- validator: NetworkDepositRequirementsSchema,
5502
- host: NetworkDepositRequirementsSchema,
5503
- gateway: NetworkDepositRequirementsSchema
5504
- });
5505
5482
  var TokenCapabilitiesSchema = zod.z.object({
5506
5483
  /**
5507
5484
  * Pause all token operations globally
@@ -5666,74 +5643,6 @@ var PreparedTransactionSovereigntySchema = zod.z.discriminatedUnion("mode", [
5666
5643
  authorizationSet: PreparedTransactionAuthorizationSetSchema.optional()
5667
5644
  })
5668
5645
  ]);
5669
- var TransactionStatusSchema = zod.z.enum(["pending", "success", "failed", "expired"]);
5670
- var TransactionTypeSchema = zod.z.enum([
5671
- "transfer",
5672
- "token_transfer",
5673
- "account_create",
5674
- "token_create",
5675
- "token_mint",
5676
- "token_burn",
5677
- "contract_call",
5678
- "contract_create",
5679
- "topic_message",
5680
- "other"
5681
- ]);
5682
- zod.z.object({
5683
- id: zod.z.string(),
5684
- chain: ChainTypeSchema,
5685
- type: TransactionTypeSchema,
5686
- status: TransactionStatusSchema,
5687
- timestamp: zod.z.date(),
5688
- from: AccountIdSchema,
5689
- to: AccountIdSchema.optional(),
5690
- amount: zod.z.string().optional(),
5691
- fee: zod.z.string(),
5692
- memo: zod.z.string().optional(),
5693
- metadata: zod.z.record(zod.z.any()).optional()
5694
- });
5695
- zod.z.object({
5696
- transactionId: zod.z.string(),
5697
- chain: ChainTypeSchema,
5698
- status: TransactionStatusSchema,
5699
- blockNumber: zod.z.number().optional(),
5700
- blockHash: zod.z.string().optional(),
5701
- timestamp: zod.z.date(),
5702
- gasUsed: zod.z.string().optional(),
5703
- effectiveFee: zod.z.string(),
5704
- logs: zod.z.array(zod.z.any()).optional(),
5705
- metadata: zod.z.record(zod.z.any()).optional()
5706
- });
5707
- var TokenTypeSchema = zod.z.enum(["fungible", "nft", "semi_fungible"]);
5708
- var TokenSchema = zod.z.object({
5709
- tokenId: zod.z.string(),
5710
- chain: ChainTypeSchema,
5711
- name: zod.z.string(),
5712
- symbol: zod.z.string(),
5713
- decimals: zod.z.number().int().min(0),
5714
- totalSupply: zod.z.string(),
5715
- type: TokenTypeSchema,
5716
- creator: AccountIdSchema.optional(),
5717
- metadata: zod.z.record(zod.z.any()).optional(),
5718
- createdAt: zod.z.date().optional()
5719
- });
5720
- zod.z.object({
5721
- name: zod.z.string(),
5722
- description: zod.z.string().optional(),
5723
- image: zod.z.string().url().optional(),
5724
- attributes: zod.z.array(
5725
- zod.z.object({
5726
- trait_type: zod.z.string(),
5727
- value: zod.z.union([zod.z.string(), zod.z.number(), zod.z.boolean()])
5728
- })
5729
- ).optional(),
5730
- external_url: zod.z.string().url().optional()
5731
- });
5732
- TokenSchema.extend({
5733
- holders: zod.z.number().optional(),
5734
- transferCount: zod.z.number().optional(),
5735
- circulatingSupply: zod.z.string().optional()
5736
- });
5737
5646
  var CreateAccountRequestSchema = zod.z.object({
5738
5647
  chain: ChainTypeSchema,
5739
5648
  initialBalance: zod.z.string(),
@@ -6094,9 +6003,11 @@ zod.z.object({
6094
6003
  var discovery_exports = {};
6095
6004
  __export(discovery_exports, {
6096
6005
  ClusterDiscoveryClient: () => ClusterDiscoveryClient,
6006
+ DiscoveryClient: () => DiscoveryClient,
6097
6007
  MIRROR_NODE_URLS: () => MIRROR_NODE_URLS,
6098
6008
  MirrorNodeClient: () => MirrorNodeClient,
6099
6009
  MirrorNodeError: () => MirrorNodeError,
6010
+ PlatformImagesClient: () => PlatformImagesClient,
6100
6011
  ValidatorDiscoveryClient: () => ValidatorDiscoveryClient
6101
6012
  });
6102
6013
 
@@ -6645,6 +6556,99 @@ var ClusterDiscoveryClient = class {
6645
6556
  }
6646
6557
  };
6647
6558
 
6559
+ // src/discovery/discovery-client.ts
6560
+ var DiscoveryClient = class {
6561
+ constructor(http) {
6562
+ this.http = http;
6563
+ this.platformImages = new PlatformImagesClient(http);
6564
+ }
6565
+ http;
6566
+ /** Platform-image manifest discovery endpoints. */
6567
+ platformImages;
6568
+ /**
6569
+ * `GET /api/v3/discovery/clusters` — active-set cluster registry,
6570
+ * grouped by `clusterId`. This is the same data the bootstrap-seed
6571
+ * flow consumes for random-pick connect.
6572
+ */
6573
+ async listClusters() {
6574
+ return this.http.get("/discovery/clusters");
6575
+ }
6576
+ /**
6577
+ * `GET /api/v3/discovery/clusters/all` — every node-level record
6578
+ * (debug / audit view). Includes nodes that the active-set filter
6579
+ * dropped (e.g. recently-departed validators still in the registry's
6580
+ * eventual-consistency window).
6581
+ */
6582
+ async listAllClusters() {
6583
+ return this.http.get("/discovery/clusters/all");
6584
+ }
6585
+ /**
6586
+ * `GET /api/v3/discovery/clusters/:nodeId` — per-nodeId registry row.
6587
+ * Returns `{ record: null }` (not 404) when the nodeId is unknown to
6588
+ * this validator's registry view, so callers can branch without
6589
+ * try/catch.
6590
+ */
6591
+ async getClusterByNode(nodeId) {
6592
+ return this.http.get(`/discovery/clusters/${encodeURIComponent(nodeId)}`);
6593
+ }
6594
+ };
6595
+ var PlatformImagesClient = class {
6596
+ constructor(http) {
6597
+ this.http = http;
6598
+ }
6599
+ http;
6600
+ /**
6601
+ * `GET /api/v3/discovery/platform-images` — every signed manifest the
6602
+ * cluster has on record. One row per `(imageName, version)` pair.
6603
+ */
6604
+ async list() {
6605
+ return this.http.get("/discovery/platform-images");
6606
+ }
6607
+ /**
6608
+ * `GET /api/v3/discovery/platform-images/envelopes` — full signed
6609
+ * envelopes (manifest + signature + publicKey). Heavier payload than
6610
+ * {@link list}; for external re-verifiers that want to independently
6611
+ * confirm authenticity.
6612
+ */
6613
+ async listEnvelopes() {
6614
+ return this.http.get("/discovery/platform-images/envelopes");
6615
+ }
6616
+ /**
6617
+ * `GET /api/v3/discovery/platform-images/:imageName` — every version
6618
+ * of a single image. Useful for "which tags has the cluster
6619
+ * authorized?" queries.
6620
+ */
6621
+ async get(imageName) {
6622
+ return this.http.get(`/discovery/platform-images/${encodeURIComponent(imageName)}`);
6623
+ }
6624
+ /**
6625
+ * `GET /api/v3/discovery/platform-images/:imageName/:version` —
6626
+ * single signed manifest. Returns `{ manifest: null }` when the
6627
+ * `(imageName, version)` pair is unknown.
6628
+ */
6629
+ async getVersion(imageName, version) {
6630
+ return this.http.get(
6631
+ `/discovery/platform-images/${encodeURIComponent(imageName)}/${encodeURIComponent(version)}`
6632
+ );
6633
+ }
6634
+ /**
6635
+ * `GET /api/v3/discovery/platform-images/:imageName/:version/verify?digest=...`
6636
+ * — content-addressed verify gate. Returns `{ verified: true }` only
6637
+ * when the supplied SHA-256 digest matches the on-record manifest.
6638
+ *
6639
+ * Use before pulling an image off a registry to make sure you're
6640
+ * about to run cluster-signed bits and not whatever drifted into
6641
+ * the registry namespace.
6642
+ */
6643
+ async verify(imageName, version, digest) {
6644
+ return this.http.get(
6645
+ `/discovery/platform-images/${encodeURIComponent(imageName)}/${encodeURIComponent(
6646
+ version
6647
+ )}/verify?digest=${encodeURIComponent(digest)}`
6648
+ );
6649
+ }
6650
+ };
6651
+
6648
6652
  // src/auth/index.ts
6649
6653
  var auth_exports = {};
6650
6654
  __export(auth_exports, {
@@ -6949,7 +6953,7 @@ function createHttpClient(config) {
6949
6953
  const timeout = config.timeout ?? 3e4;
6950
6954
  function getHeaders(contentType) {
6951
6955
  const headers = {};
6952
- {
6956
+ if (contentType) {
6953
6957
  headers["Content-Type"] = contentType;
6954
6958
  }
6955
6959
  if (config.authToken) {
@@ -6999,6 +7003,36 @@ function createHttpClient(config) {
6999
7003
  throw new SdkHttpError(`Network error: ${err.message}`, 0, error);
7000
7004
  }
7001
7005
  }
7006
+ async function getText(path) {
7007
+ const url = `${config.baseUrl}${path}`;
7008
+ const controller = new AbortController();
7009
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
7010
+ try {
7011
+ const response = await fetch(url, {
7012
+ method: "GET",
7013
+ headers: getHeaders(),
7014
+ signal: controller.signal
7015
+ });
7016
+ clearTimeout(timeoutId);
7017
+ if (!response.ok) {
7018
+ const errBody = await response.json().catch(() => ({}));
7019
+ throw new SdkHttpError(
7020
+ errBody.message || `API error: ${response.status} ${response.statusText}`,
7021
+ response.status,
7022
+ errBody
7023
+ );
7024
+ }
7025
+ return await response.text();
7026
+ } catch (error) {
7027
+ clearTimeout(timeoutId);
7028
+ if (error instanceof SdkHttpError) throw error;
7029
+ const err = error;
7030
+ if (err.name === "AbortError") {
7031
+ throw new SdkHttpError("Request timeout", 408);
7032
+ }
7033
+ throw new SdkHttpError(`Network error: ${err.message}`, 0, error);
7034
+ }
7035
+ }
7002
7036
  async function upload(path, file, filename, metadata, fieldName = "file") {
7003
7037
  const url = `${config.baseUrl}${path}`;
7004
7038
  const controller = new AbortController();
@@ -7049,7 +7083,9 @@ function createHttpClient(config) {
7049
7083
  post: (path, body) => request("POST", path, body),
7050
7084
  get: (path) => request("GET", path),
7051
7085
  put: (path, body) => request("PUT", path, body),
7086
+ patch: (path, body) => request("PATCH", path, body),
7052
7087
  delete: (path) => request("DELETE", path),
7088
+ getText,
7053
7089
  upload: ((path, file, filename, metadata, fieldName) => upload(path, file, filename, metadata, fieldName)),
7054
7090
  setAuthToken
7055
7091
  };
@@ -7070,6 +7106,35 @@ function isRuleRejected(err) {
7070
7106
  return obj.ruleAtoms.every((a) => typeof a === "string");
7071
7107
  }
7072
7108
 
7109
+ // src/network-presets.ts
7110
+ var KNOWN_NETWORKS = {
7111
+ testnet: {
7112
+ bootstrap: ["https://gateway.testnet.hsuite.network"]
7113
+ },
7114
+ mainnet: {
7115
+ // Mainnet entrypoint reserved. The SDK still resolves the name so
7116
+ // upgrade-by-flipping-NETWORK works; the bootstrap URL is the
7117
+ // pre-allocated DNS we own. If mainnet isn't deployed yet, the discovery
7118
+ // fetch will fail at runtime with the same "no seed reachable" error
7119
+ // any unreachable URL produces — the caller learns the network is not
7120
+ // live, rather than getting a baffling "unknown network" TypeScript
7121
+ // error at compile time.
7122
+ bootstrap: ["https://gateway.hsuite.network"]
7123
+ }
7124
+ };
7125
+ function resolveNetwork(name) {
7126
+ const preset = KNOWN_NETWORKS[name];
7127
+ if (!preset) {
7128
+ throw new Error(
7129
+ `Unknown network: "${name}". Known networks: ${Object.keys(KNOWN_NETWORKS).join(", ")}`
7130
+ );
7131
+ }
7132
+ return preset;
7133
+ }
7134
+ function isKnownNetwork(name) {
7135
+ return Object.prototype.hasOwnProperty.call(KNOWN_NETWORKS, name);
7136
+ }
7137
+
7073
7138
  // src/subscription/index.ts
7074
7139
  var subscription_exports = {};
7075
7140
  __export(subscription_exports, {
@@ -7174,6 +7239,80 @@ var SubscriptionClient = class {
7174
7239
  async getBalance(appId) {
7175
7240
  return this.http.get(`/subscription/balance/${encodeURIComponent(appId)}`);
7176
7241
  }
7242
+ // ─── Tier-Change Endpoints ────────────────────────────────────────────────
7243
+ /**
7244
+ * Schedule a tier downgrade. The downgrade takes effect at the next
7245
+ * renewal — the deposit is NOT partially refunded mid-lock. Excess
7246
+ * collateral returns on eventual cancel.
7247
+ */
7248
+ async downgrade(request) {
7249
+ return this.http.post("/subscription/downgrade", request);
7250
+ }
7251
+ /**
7252
+ * Request a tier upgrade. The server records the upgrade and returns
7253
+ * top-up deposit instructions for the price delta. The new tier flips
7254
+ * only once the on-chain top-up is confirmed by the deposit monitor.
7255
+ */
7256
+ async upgrade(request) {
7257
+ return this.http.post("/subscription/upgrade", request);
7258
+ }
7259
+ /** Cancel a pending (not-yet-applied) tier change. */
7260
+ async cancelTierChange(request) {
7261
+ return this.http.post("/subscription/tier-change/cancel", request);
7262
+ }
7263
+ // ─── Internal / Usage / Billing ───────────────────────────────────────────
7264
+ /**
7265
+ * Check whether a developer wallet has any active subscription. Used by
7266
+ * smart-host's deploy gate via the cluster-internal API-key path; smart-app
7267
+ * callers should not rely on this endpoint (server-side it requires the
7268
+ * `INTERNAL_SERVICE_MESH_ROUTES` allowlist + an `X-API-Key` header).
7269
+ */
7270
+ async getActiveFor(walletAddress) {
7271
+ return this.http.get(
7272
+ `/subscription/active-for/${encodeURIComponent(walletAddress)}`
7273
+ );
7274
+ }
7275
+ /** Today's consumption breakdown by category for an app. Owner-only. */
7276
+ async getUsage(appId) {
7277
+ return this.http.get(`/subscription/usage/${encodeURIComponent(appId)}`);
7278
+ }
7279
+ /**
7280
+ * Current usage with overage info: usage percent, grace status,
7281
+ * upgrade suggestion, projected days until limit. Owner-only.
7282
+ */
7283
+ async getUsageStatus(appId) {
7284
+ return this.http.get(`/subscription/usage/status/${encodeURIComponent(appId)}`);
7285
+ }
7286
+ /**
7287
+ * Subscription balance deduction history. Pagination + ISO-8601 range
7288
+ * filtering supported. Owner-only.
7289
+ */
7290
+ async getBilling(appId, options) {
7291
+ const params = new URLSearchParams();
7292
+ if (options?.limit !== void 0) params.append("limit", String(options.limit));
7293
+ if (options?.offset !== void 0) params.append("offset", String(options.offset));
7294
+ if (options?.from) params.append("from", options.from);
7295
+ if (options?.to) params.append("to", options.to);
7296
+ const qs = params.toString();
7297
+ return this.http.get(
7298
+ `/subscription/billing/${encodeURIComponent(appId)}${qs ? `?${qs}` : ""}`
7299
+ );
7300
+ }
7301
+ /**
7302
+ * Mint a customer-subscription NFT on behalf of a smart-app.
7303
+ *
7304
+ * Distinct from `mintNft(appId)`, which mints the smart-app's own
7305
+ * developer-level subscription NFT. This endpoint mints a *customer*
7306
+ * NFT held by an end-user wallet — used by smart-host's
7307
+ * `XrplCustomerNftIssuerAdapter` when an app calls
7308
+ * `SubscriptionService.issueCustomerSubscription()` from the sandbox.
7309
+ *
7310
+ * v1 is XRPL-only (the `customerChain` field is a literal `'xrpl'`).
7311
+ * Internal-by-design — server-side gated by `X-API-Key`.
7312
+ */
7313
+ async mintCustomer(request) {
7314
+ return this.http.post("/subscription/customer/mint", request);
7315
+ }
7177
7316
  };
7178
7317
 
7179
7318
  // src/tss/index.ts
@@ -7202,14 +7341,19 @@ var TSSClient = class {
7202
7341
  return this.http.get(`/tss/entity/${encodeURIComponent(entityId)}`);
7203
7342
  }
7204
7343
  /**
7205
- * Sign a transaction using MPC — chain-agnostic.
7206
- * Routes to the correct chain backend based on the `chain` parameter.
7344
+ * Sign a transaction using MPC.
7207
7345
  *
7208
- * @param request - MPC signing request with chain, entityId, and transaction bytes
7346
+ * Routes to `POST /api/v3/tss/hedera/sign-mpc`. Only `'hedera'` is wired
7347
+ * server-side today (see
7348
+ * `apps/smart-validator/src/tss/tss.controller.ts:279`); other chain
7349
+ * signing paths run via their own controllers (XRPL multisig, Polkadot
7350
+ * MPC) and are not exposed through this sub-client. The `chain` field is
7351
+ * carried into the request body so the validator can log + route, but
7352
+ * any non-`'hedera'` value will 404.
7209
7353
  */
7210
7354
  async signMPC(request) {
7211
- const chain = request.chain || "hedera";
7212
- return this.http.post(`/tss/${encodeURIComponent(chain)}/sign-mpc`, request);
7355
+ const chain = "hedera";
7356
+ return this.http.post(`/tss/${chain}/sign-mpc`, { ...request, chain });
7213
7357
  }
7214
7358
  /**
7215
7359
  * Get known validators and their public keys
@@ -7253,6 +7397,42 @@ var TSSClient = class {
7253
7397
  async getMultiSigStatus(txId) {
7254
7398
  return this.http.get(`/tss/multisig/transactions/${encodeURIComponent(txId)}`);
7255
7399
  }
7400
+ /**
7401
+ * Async-job variant of {@link createEntity}.
7402
+ *
7403
+ * Server returns 202 + `{ jobId, statusUrl, status: 'pending' }` immediately;
7404
+ * the DKG ceremony runs in the background. Poll {@link getJob} until the
7405
+ * status reaches `'success'` or `'failed'`.
7406
+ */
7407
+ async createEntityAsync(options) {
7408
+ return this.http.post("/tss/entity/create/async", options);
7409
+ }
7410
+ /**
7411
+ * Async-job variant of {@link reshareCluster}. Returns 202 + a polling
7412
+ * descriptor; resharing runs in the background.
7413
+ */
7414
+ async reshareClusterAsync(request) {
7415
+ return this.http.post("/tss/cluster/reshare/async", request);
7416
+ }
7417
+ /**
7418
+ * Poll the status of an async TSS-ceremony job kicked off via
7419
+ * {@link createEntityAsync} or {@link reshareClusterAsync}.
7420
+ */
7421
+ async getJob(jobId) {
7422
+ return this.http.get(`/tss/jobs/${encodeURIComponent(jobId)}`);
7423
+ }
7424
+ /**
7425
+ * Sign a hex payload as smart-app entity `appId` via the cluster's TSS
7426
+ * quorum. Used by smart-deployer for per-entity BLS12-381 signatures over
7427
+ * deployment-context payloads (trustless APP_TOKEN replacement).
7428
+ *
7429
+ * Payload constraints (enforced server-side):
7430
+ * - even-length lowercase hex
7431
+ * - ≥32 bytes, ≤8KB
7432
+ */
7433
+ async signForApp(appId, request) {
7434
+ return this.http.post(`/tss/entity/${encodeURIComponent(appId)}/sign`, request);
7435
+ }
7256
7436
  };
7257
7437
 
7258
7438
  // src/ipfs/index.ts
@@ -7322,12 +7502,59 @@ var IPFSClient = class {
7322
7502
  }
7323
7503
  };
7324
7504
 
7505
+ // src/hedera-tss/index.ts
7506
+ var HederaTssClient = class {
7507
+ constructor(http) {
7508
+ this.http = http;
7509
+ }
7510
+ http;
7511
+ /** Create a Hedera account whose keys are controlled by the TSS cluster. */
7512
+ async createAccount(request) {
7513
+ return this.http.post("/hedera/tss/create-account", request);
7514
+ }
7515
+ /** Update an existing account's memo via TSS-signed transaction. */
7516
+ async updateMemo(request) {
7517
+ return this.http.post("/hedera/tss/update-memo", request);
7518
+ }
7519
+ /** Create a TSS-controlled HCS topic. */
7520
+ async createTopic(request) {
7521
+ return this.http.post("/hedera/tss/create-topic", request);
7522
+ }
7523
+ /** Submit a message to an HCS topic via TSS signing. */
7524
+ async submitMessage(request) {
7525
+ return this.http.post("/hedera/tss/submit-message", request);
7526
+ }
7527
+ /** Create an HTS token with TSS-controlled admin/supply/freeze/pause/wipe keys. */
7528
+ async createToken(request) {
7529
+ return this.http.post("/hedera/tss/create-token", request);
7530
+ }
7531
+ /** Mint tokens via TSS signing — optionally rule-validated via `validatorTopicId`. */
7532
+ async mintToken(request) {
7533
+ return this.http.post("/hedera/tss/mint-token", request);
7534
+ }
7535
+ };
7536
+
7325
7537
  // src/transactions/chains/hedera.ts
7326
7538
  var HederaTransactionsClient = class {
7327
- constructor(http) {
7539
+ constructor(http, tssHttp) {
7328
7540
  this.http = http;
7541
+ this.tss = new HederaTssClient(tssHttp ?? http);
7329
7542
  }
7330
7543
  http;
7544
+ /**
7545
+ * TSS-signed Hedera operations (`/api/v3/hedera/tss/*`).
7546
+ *
7547
+ * Distinct from the prepare-only routes on this class:
7548
+ * - `client.hedera.prepareTopicCreate(...)` returns bytes for local sign+submit.
7549
+ * - `client.hedera.tss.createTopic(...)` makes the cluster sign+submit in one call.
7550
+ *
7551
+ * `tssHttp` is the validator's `/api/v3`-rooted HTTP client (different from
7552
+ * the `/api/transactions` one this class uses for prepare paths). When the
7553
+ * legacy single-arg constructor is used (no tssHttp passed), `tss` falls
7554
+ * back to the same `http` instance for backwards compatibility — callers
7555
+ * outside `SmartEngineClient` rarely use the TSS surface.
7556
+ */
7557
+ tss;
7331
7558
  /** Prepare an HCS topic creation transaction. */
7332
7559
  async prepareTopicCreate(request) {
7333
7560
  return this.http.post("/topic/create/prepare", { ...request, chain: "hedera" });
@@ -7360,6 +7587,16 @@ var XrplTransactionsClient = class {
7360
7587
  async prepareTrustLine(request) {
7361
7588
  return this.http.post("/trustline/prepare", { ...request, chain: "xrpl" });
7362
7589
  }
7590
+ /**
7591
+ * Prepare the ordered XRPL account-setup transaction set
7592
+ * (SignerListSet + AccountSet DisableMaster) for sovereignty mode.
7593
+ *
7594
+ * Returns `{ steps, sovereignty }`. Caller signs + submits each step in
7595
+ * order; the master key remains usable until the final AccountSet lands.
7596
+ */
7597
+ async prepareAccountSetup(request) {
7598
+ return this.http.post("/xrpl/account-setup/prepare", { ...request, chain: "xrpl" });
7599
+ }
7363
7600
  };
7364
7601
 
7365
7602
  // src/transactions/chains/solana.ts
@@ -7416,6 +7653,28 @@ var TransactionsClient = class {
7416
7653
  async prepareNftTransfer(request) {
7417
7654
  return this.http.post("/nft/transfer/prepare", request);
7418
7655
  }
7656
+ /**
7657
+ * Prepare an NFT collection-create transaction (Polkadot pallet-nfts /
7658
+ * Solana Metaplex master-edition).
7659
+ */
7660
+ async prepareNftCollectionCreate(request) {
7661
+ return this.http.post("/nft/collection/create/prepare", request);
7662
+ }
7663
+ /** Prepare an NFT item set-metadata transaction (Polkadot pallet-nfts/uniques). */
7664
+ async prepareNftSetMetadata(request) {
7665
+ return this.http.post("/nft/set-metadata/prepare", request);
7666
+ }
7667
+ /** Prepare an NFT collection set-metadata transaction (Polkadot pallet-nfts/uniques). */
7668
+ async prepareNftCollectionSetMetadata(request) {
7669
+ return this.http.post("/nft/collection/set-metadata/prepare", request);
7670
+ }
7671
+ /**
7672
+ * Prepare an NFT collection-lock transaction (Polkadot pallet-nfts only).
7673
+ * Asset Hub runtimes on pallet-uniques fallback will reject with a 4xx.
7674
+ */
7675
+ async prepareNftCollectionLock(request) {
7676
+ return this.http.post("/nft/collection/lock/prepare", request);
7677
+ }
7419
7678
  /** Prepare a token creation transaction (Hedera, Solana, Polkadot, Cardano). */
7420
7679
  async prepareTokenCreate(request) {
7421
7680
  return this.http.post("/token/create/prepare", request);
@@ -7736,72 +7995,319 @@ var GovernanceClient = class {
7736
7995
  }
7737
7996
  };
7738
7997
 
7739
- // src/personhood/index.ts
7740
- var personhood_exports = {};
7741
- __export(personhood_exports, {
7742
- PERSONHOOD_VERIFIER_NOT_CONFIGURED: () => PERSONHOOD_VERIFIER_NOT_CONFIGURED,
7743
- PersonhoodClient: () => PersonhoodClient,
7744
- isPersonhoodVerifierNotConfigured: () => isPersonhoodVerifierNotConfigured
7998
+ // src/dao/index.ts
7999
+ var dao_exports = {};
8000
+ __export(dao_exports, {
8001
+ DaoClient: () => DaoClient,
8002
+ DaoDashboardClient: () => DaoDashboardClient
7745
8003
  });
7746
8004
 
7747
- // src/personhood/personhood-client.ts
7748
- var PERSONHOOD_VERIFIER_NOT_CONFIGURED = "personhood_verifier_not_configured";
7749
- var PersonhoodClient = class {
8005
+ // src/dao/dashboard-client.ts
8006
+ function buildQuery(params) {
8007
+ const search = new URLSearchParams();
8008
+ for (const [key, value] of Object.entries(params)) {
8009
+ if (value === void 0) continue;
8010
+ search.set(key, String(value));
8011
+ }
8012
+ const qs = search.toString();
8013
+ return qs ? `?${qs}` : "";
8014
+ }
8015
+ var DaoDashboardClient = class {
7750
8016
  constructor(http) {
7751
8017
  this.http = http;
7752
8018
  }
7753
8019
  http;
7754
- /**
7755
- * Verify a personhood proof for `candidate`.
7756
- *
7757
- * Returns the issued cert on accept, `null` on clean rejection. All
7758
- * other failure modes (validation, transport, 5xx) propagate as
7759
- * `SdkHttpError`.
7760
- */
7761
- async verify(params) {
7762
- const result = await this.http.post(
7763
- "/personhood/verify",
7764
- {
7765
- candidate: params.candidate,
7766
- proof: params.proof
7767
- }
8020
+ /** Aggregated dashboard counters for a user's governance home screen. */
8021
+ async getStats(userAddress) {
8022
+ return this.http.get(
8023
+ `/dao/dashboard/stats/${encodeURIComponent(userAddress)}`
8024
+ );
8025
+ }
8026
+ /** Active proposals across every DAO the user belongs to, with vote state. */
8027
+ async getActiveProposals(userAddress) {
8028
+ return this.http.get(
8029
+ `/dao/dashboard/active-proposals/${encodeURIComponent(userAddress)}`
8030
+ );
8031
+ }
8032
+ /** Paginated vote history across DAOs. */
8033
+ async getVoteHistory(userAddress, opts = {}) {
8034
+ const qs = buildQuery({ limit: opts.limit, offset: opts.offset });
8035
+ return this.http.get(
8036
+ `/dao/dashboard/vote-history/${encodeURIComponent(userAddress)}${qs}`
8037
+ );
8038
+ }
8039
+ /** Activity feed (proposal-created/vote-cast/etc.) across user's DAOs. */
8040
+ async getActivity(userAddress, opts = {}) {
8041
+ const qs = buildQuery({ limit: opts.limit, daoId: opts.daoId });
8042
+ return this.http.get(
8043
+ `/dao/dashboard/activity/${encodeURIComponent(userAddress)}${qs}`
8044
+ );
8045
+ }
8046
+ /** Items the user must act on (sign prepared messages, claim NFTs, …). */
8047
+ async getPendingActions(userAddress) {
8048
+ return this.http.get(
8049
+ `/dao/dashboard/pending-actions/${encodeURIComponent(userAddress)}`
8050
+ );
8051
+ }
8052
+ /** Governance impact metrics — weight delivered, success rate, streak. */
8053
+ async getImpact(userAddress) {
8054
+ return this.http.get(
8055
+ `/dao/dashboard/impact/${encodeURIComponent(userAddress)}`
7768
8056
  );
7769
- if (result === void 0) return null;
7770
- return result;
7771
8057
  }
7772
8058
  };
7773
- function isPersonhoodVerifierNotConfigured(err) {
7774
- if (!(err instanceof SdkHttpError)) return false;
7775
- if (err.statusCode !== 503) return false;
7776
- const d = err.details;
7777
- if (d === null || typeof d !== "object") return false;
7778
- return d.error === PERSONHOOD_VERIFIER_NOT_CONFIGURED;
7779
- }
7780
8059
 
7781
- // src/baas/agents/types.ts
7782
- var VALID_CHAIN_NAMES = /* @__PURE__ */ new Set([
7783
- "hedera",
7784
- "xrpl",
7785
- "polkadot",
7786
- "solana",
7787
- "stellar",
7788
- "ethereum",
7789
- "polygon",
7790
- "bitcoin"
7791
- ]);
7792
- function validateAgentRules(rules) {
7793
- const errors = [];
7794
- if (rules.maxTradeAmount !== void 0) {
7795
- if (!isPositiveDecimalString(rules.maxTradeAmount)) {
7796
- errors.push("maxTradeAmount must be a positive decimal string");
7797
- }
8060
+ // src/dao/dao-client.ts
8061
+ function buildQuery2(params) {
8062
+ const search = new URLSearchParams();
8063
+ for (const [key, value] of Object.entries(params)) {
8064
+ if (value === void 0) continue;
8065
+ search.set(key, String(value));
8066
+ }
8067
+ const qs = search.toString();
8068
+ return qs ? `?${qs}` : "";
8069
+ }
8070
+ function encodeDaoId(daoId) {
8071
+ return encodeURIComponent(daoId);
8072
+ }
8073
+ function encodeProposalId(proposalId) {
8074
+ return encodeURIComponent(proposalId);
8075
+ }
8076
+ function encodeAddress(address) {
8077
+ return encodeURIComponent(address);
8078
+ }
8079
+ var DaoClient = class {
8080
+ constructor(http) {
8081
+ this.http = http;
8082
+ this.dashboard = new DaoDashboardClient(http);
7798
8083
  }
7799
- if (rules.allowedPairs !== void 0) {
7800
- if (!Array.isArray(rules.allowedPairs)) {
7801
- errors.push("allowedPairs must be an array of strings");
7802
- } else {
7803
- for (const pair of rules.allowedPairs) {
7804
- if (typeof pair !== "string" || pair.trim().length === 0) {
8084
+ http;
8085
+ /** Per-user rollups for the smart-app's governance home screen. */
8086
+ dashboard;
8087
+ // ─── Lifecycle ────────────────────────────────────────────────────────────
8088
+ /** Create a new DAO. */
8089
+ async create(request) {
8090
+ return this.http.post("/dao/create", request);
8091
+ }
8092
+ /** List DAOs with optional status / creator filters. */
8093
+ async list(opts = {}) {
8094
+ const qs = buildQuery2({ status: opts.status, createdBy: opts.createdBy });
8095
+ return this.http.get(`/dao/list${qs}`);
8096
+ }
8097
+ /** Fetch a single DAO by ID. */
8098
+ async get(daoId) {
8099
+ return this.http.get(`/dao/${encodeDaoId(daoId)}`);
8100
+ }
8101
+ /** Fetch a DAO together with its proposals (single round-trip). */
8102
+ async getWithProposals(daoId) {
8103
+ return this.http.get(`/dao/${encodeDaoId(daoId)}/with-proposals`);
8104
+ }
8105
+ // ─── Proposals ────────────────────────────────────────────────────────────
8106
+ /** List proposals for a DAO, optionally filtered by status / proposer. */
8107
+ async listProposals(daoId, opts = {}) {
8108
+ const qs = buildQuery2({ status: opts.status, proposer: opts.proposer });
8109
+ return this.http.get(`/dao/${encodeDaoId(daoId)}/proposals${qs}`);
8110
+ }
8111
+ /** Create a proposal (server activates the proposal immediately). */
8112
+ async createProposal(daoId, request) {
8113
+ return this.http.post(`/dao/${encodeDaoId(daoId)}/proposals`, request);
8114
+ }
8115
+ /**
8116
+ * Prepare a proposal for off-chain signing (returns the message to sign).
8117
+ * Use {@link signProposal} to submit the signature once captured.
8118
+ */
8119
+ async prepareProposal(daoId, request) {
8120
+ return this.http.post(
8121
+ `/dao/${encodeDaoId(daoId)}/proposals/prepare`,
8122
+ request
8123
+ );
8124
+ }
8125
+ /** Submit the signed prepared-proposal payload. */
8126
+ async signProposal(daoId, proposalId, request) {
8127
+ return this.http.post(
8128
+ `/dao/${encodeDaoId(daoId)}/proposals/${encodeProposalId(proposalId)}/sign`,
8129
+ request
8130
+ );
8131
+ }
8132
+ /** Prepare a vote message for off-chain signing. */
8133
+ async prepareVote(daoId, proposalId, request) {
8134
+ return this.http.post(
8135
+ `/dao/${encodeDaoId(daoId)}/proposals/${encodeProposalId(proposalId)}/prepare-vote`,
8136
+ request
8137
+ );
8138
+ }
8139
+ /** Submit the signed prepared-vote payload. */
8140
+ async submitVote(daoId, proposalId, request) {
8141
+ return this.http.post(
8142
+ `/dao/${encodeDaoId(daoId)}/proposals/${encodeProposalId(proposalId)}/submit-vote`,
8143
+ request
8144
+ );
8145
+ }
8146
+ /**
8147
+ * Cast a vote directly (no separate prepare/sign hop — server records the
8148
+ * vote on the caller's behalf). Use {@link prepareVote} + {@link submitVote}
8149
+ * when the smart-app's signing model requires client-side signing.
8150
+ */
8151
+ async vote(daoId, proposalId, request) {
8152
+ return this.http.post(
8153
+ `/dao/${encodeDaoId(daoId)}/proposals/${encodeProposalId(proposalId)}/vote`,
8154
+ request
8155
+ );
8156
+ }
8157
+ /**
8158
+ * Manually execute a passed proposal via TSS. Proposals auto-execute after
8159
+ * the execution delay; this endpoint is for the governance-admin override
8160
+ * path.
8161
+ */
8162
+ async execute(daoId, proposalId) {
8163
+ return this.http.post(
8164
+ `/dao/${encodeDaoId(daoId)}/proposals/${encodeProposalId(proposalId)}/execute`,
8165
+ {}
8166
+ );
8167
+ }
8168
+ /** Paginated vote list for a proposal. */
8169
+ async getVotes(daoId, proposalId, opts = {}) {
8170
+ const qs = buildQuery2({ limit: opts.limit, offset: opts.offset });
8171
+ return this.http.get(
8172
+ `/dao/${encodeDaoId(daoId)}/proposals/${encodeProposalId(proposalId)}/votes${qs}`
8173
+ );
8174
+ }
8175
+ /** Resolved tally / quorum / pass-fail for a proposal. */
8176
+ async getResults(daoId, proposalId) {
8177
+ return this.http.get(
8178
+ `/dao/${encodeDaoId(daoId)}/proposals/${encodeProposalId(proposalId)}/results`
8179
+ );
8180
+ }
8181
+ /** Raw vote counts by option ID (no quorum / pass logic). */
8182
+ async getVoteCounts(daoId, proposalId) {
8183
+ return this.http.get(
8184
+ `/dao/${encodeDaoId(daoId)}/proposals/${encodeProposalId(proposalId)}/vote-counts`
8185
+ );
8186
+ }
8187
+ /** Fetch a single voter's vote on a proposal. */
8188
+ async getVoterRecord(daoId, proposalId, voterAddress) {
8189
+ return this.http.get(
8190
+ `/dao/${encodeDaoId(daoId)}/proposals/${encodeProposalId(proposalId)}/voter/${encodeAddress(voterAddress)}`
8191
+ );
8192
+ }
8193
+ /** Fetch a single proposal by ID. */
8194
+ async getProposal(daoId, proposalId) {
8195
+ return this.http.get(
8196
+ `/dao/${encodeDaoId(daoId)}/proposals/${encodeProposalId(proposalId)}`
8197
+ );
8198
+ }
8199
+ // ─── Treasury ─────────────────────────────────────────────────────────────
8200
+ /** Per-chain treasury balances for a DAO. */
8201
+ async getTreasury(daoId, chain) {
8202
+ const qs = buildQuery2({ chain });
8203
+ return this.http.get(`/dao/${encodeDaoId(daoId)}/treasury${qs}`);
8204
+ }
8205
+ /** Paginated treasury transaction history (in/out/swap). */
8206
+ async getTreasuryHistory(daoId, opts = {}) {
8207
+ const qs = buildQuery2({
8208
+ chain: opts.chain,
8209
+ limit: opts.limit,
8210
+ offset: opts.offset
8211
+ });
8212
+ return this.http.get(`/dao/${encodeDaoId(daoId)}/treasury/history${qs}`);
8213
+ }
8214
+ // ─── Members ──────────────────────────────────────────────────────────────
8215
+ /** List a DAO's members, optionally filtered by status. */
8216
+ async listMembers(daoId, opts = {}) {
8217
+ const qs = buildQuery2({ status: opts.status });
8218
+ return this.http.get(`/dao/${encodeDaoId(daoId)}/members${qs}`);
8219
+ }
8220
+ /** Add a member to a DAO. */
8221
+ async addMember(daoId, request) {
8222
+ return this.http.post(`/dao/${encodeDaoId(daoId)}/members`, request);
8223
+ }
8224
+ /** Remove a member from a DAO. */
8225
+ async removeMember(daoId, address) {
8226
+ return this.http.delete(
8227
+ `/dao/${encodeDaoId(daoId)}/members/${encodeAddress(address)}`
8228
+ );
8229
+ }
8230
+ /** Bind a held membership NFT serial to a member record. */
8231
+ async claimMemberNft(daoId, address, request) {
8232
+ return this.http.post(
8233
+ `/dao/${encodeDaoId(daoId)}/members/${encodeAddress(address)}/claim-nft`,
8234
+ request
8235
+ );
8236
+ }
8237
+ /** Fetch the NFT serials + status for a member. */
8238
+ async getMemberNft(daoId, address) {
8239
+ return this.http.get(
8240
+ `/dao/${encodeDaoId(daoId)}/members/${encodeAddress(address)}/nft`
8241
+ );
8242
+ }
8243
+ };
8244
+
8245
+ // src/personhood/index.ts
8246
+ var personhood_exports = {};
8247
+ __export(personhood_exports, {
8248
+ PERSONHOOD_VERIFIER_NOT_CONFIGURED: () => PERSONHOOD_VERIFIER_NOT_CONFIGURED,
8249
+ PersonhoodClient: () => PersonhoodClient,
8250
+ isPersonhoodVerifierNotConfigured: () => isPersonhoodVerifierNotConfigured
8251
+ });
8252
+
8253
+ // src/personhood/personhood-client.ts
8254
+ var PERSONHOOD_VERIFIER_NOT_CONFIGURED = "personhood_verifier_not_configured";
8255
+ var PersonhoodClient = class {
8256
+ constructor(http) {
8257
+ this.http = http;
8258
+ }
8259
+ http;
8260
+ /**
8261
+ * Verify a personhood proof for `candidate`.
8262
+ *
8263
+ * Returns the issued cert on accept, `null` on clean rejection. All
8264
+ * other failure modes (validation, transport, 5xx) propagate as
8265
+ * `SdkHttpError`.
8266
+ */
8267
+ async verify(params) {
8268
+ const result = await this.http.post(
8269
+ "/personhood/verify",
8270
+ {
8271
+ candidate: params.candidate,
8272
+ proof: params.proof
8273
+ }
8274
+ );
8275
+ if (result === void 0) return null;
8276
+ return result;
8277
+ }
8278
+ };
8279
+ function isPersonhoodVerifierNotConfigured(err) {
8280
+ if (!(err instanceof SdkHttpError)) return false;
8281
+ if (err.statusCode !== 503) return false;
8282
+ const d = err.details;
8283
+ if (d === null || typeof d !== "object") return false;
8284
+ return d.error === PERSONHOOD_VERIFIER_NOT_CONFIGURED;
8285
+ }
8286
+
8287
+ // src/baas/agents/types.ts
8288
+ var VALID_CHAIN_NAMES = /* @__PURE__ */ new Set([
8289
+ "hedera",
8290
+ "xrpl",
8291
+ "polkadot",
8292
+ "solana",
8293
+ "stellar",
8294
+ "ethereum",
8295
+ "polygon",
8296
+ "bitcoin"
8297
+ ]);
8298
+ function validateAgentRules(rules) {
8299
+ const errors = [];
8300
+ if (rules.maxTradeAmount !== void 0) {
8301
+ if (!isPositiveDecimalString(rules.maxTradeAmount)) {
8302
+ errors.push("maxTradeAmount must be a positive decimal string");
8303
+ }
8304
+ }
8305
+ if (rules.allowedPairs !== void 0) {
8306
+ if (!Array.isArray(rules.allowedPairs)) {
8307
+ errors.push("allowedPairs must be an array of strings");
8308
+ } else {
8309
+ for (const pair of rules.allowedPairs) {
8310
+ if (typeof pair !== "string" || pair.trim().length === 0) {
7805
8311
  errors.push("allowedPairs contains an empty or non-string entry");
7806
8312
  break;
7807
8313
  }
@@ -7855,15 +8361,25 @@ var AgentsClient = class {
7855
8361
  async list() {
7856
8362
  return this.http.get("/api/agents");
7857
8363
  }
7858
- /** Fund an agent */
8364
+ /**
8365
+ * Fund agent treasury (owner-only). Returns a
8366
+ * `PreparedTransactionResponse` wrapped in a `success: true` envelope —
8367
+ * the caller is expected to sign and submit the prepared bytes.
8368
+ */
7859
8369
  async fund(agentId, request) {
7860
8370
  return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/fund`, request);
7861
8371
  }
7862
- /** Execute a trade */
8372
+ /**
8373
+ * Execute a trade (agent-wallet OR owner). Returns a
8374
+ * `PreparedTransactionResponse` wrapped in a `success: true` envelope.
8375
+ */
7863
8376
  async trade(agentId, request) {
7864
8377
  return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/trade`, request);
7865
8378
  }
7866
- /** Withdraw funds from agent */
8379
+ /**
8380
+ * Withdraw from agent treasury (owner-only). Returns a
8381
+ * `PreparedTransactionResponse` wrapped in a `success: true` envelope.
8382
+ */
7867
8383
  async withdraw(agentId, request) {
7868
8384
  return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/withdraw`, request);
7869
8385
  }
@@ -7879,9 +8395,16 @@ var AgentsClient = class {
7879
8395
  async revoke(agentId) {
7880
8396
  return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/revoke`, {});
7881
8397
  }
7882
- /** Update agent rules */
8398
+ /**
8399
+ * Update agent rules.
8400
+ *
8401
+ * Server route is PATCH `/api/agents/:agentId/rules`
8402
+ * (`agents.controller.ts:375`). The previous PUT variant 404'd because
8403
+ * Nest matched the dynamic `:agentId` GET/POST handlers and rejected
8404
+ * the verb mismatch.
8405
+ */
7883
8406
  async updateRules(agentId, rules) {
7884
- return this.http.put(`/api/agents/${encodeURIComponent(agentId)}/rules`, rules);
8407
+ return this.http.patch(`/api/agents/${encodeURIComponent(agentId)}/rules`, rules);
7885
8408
  }
7886
8409
  /** Get agent events */
7887
8410
  async getEvents(agentId) {
@@ -8007,6 +8530,306 @@ var DeploymentClient = class {
8007
8530
  async getStats() {
8008
8531
  return this.http.get("/api/deployment/stats");
8009
8532
  }
8533
+ /**
8534
+ * Register or update the developer-facing webhook URL for runtime
8535
+ * lifecycle events (`runtime.deploying` / `running` / `failed` /
8536
+ * `suspended` / `resumed` / `retired`).
8537
+ *
8538
+ * The host's `DeployWebhookDispatcher` POSTs to this URL whenever the
8539
+ * smart-deployer reconciler emits a `runtime.*` NATS event, signed with
8540
+ * the returned `webhookSecret`:
8541
+ *
8542
+ * `X-HSuite-Signature: sha256=<hmac-sha256(secret, raw-body)>`
8543
+ *
8544
+ * Store `webhookSecret` server-side and re-compute the signature over
8545
+ * the raw delivery body to verify authenticity. The secret is surfaced
8546
+ * only on PUT — re-call this method to rotate.
8547
+ *
8548
+ * Server validates: HTTPS only, no loopback / RFC1918 / link-local /
8549
+ * CGNAT / cloud metadata destinations (SSRF guard).
8550
+ */
8551
+ async setWebhook(appId, webhookUrl) {
8552
+ return this.http.put(`/api/deployment/apps/${encodeURIComponent(appId)}/webhook`, {
8553
+ webhookUrl
8554
+ });
8555
+ }
8556
+ /**
8557
+ * Per-app Prometheus metrics in the standard exposition format
8558
+ * (text/plain; version=0.0.4). The server filters smart-deployer's
8559
+ * `/metrics` to lines that mention this app's `appId` label, while
8560
+ * preserving HELP / TYPE comment lines and cluster-wide metrics.
8561
+ *
8562
+ * Returned as a raw string so callers can pipe directly into a
8563
+ * Prometheus parser (`prom-client`, `parse-prometheus-text-format`,
8564
+ * etc.) without an intermediate JSON decode that would corrupt the
8565
+ * exposition format.
8566
+ */
8567
+ async getMetrics(appId) {
8568
+ return this.http.getText(`/api/deployment/apps/${encodeURIComponent(appId)}/metrics`);
8569
+ }
8570
+ /**
8571
+ * Rotate the smart-app's tenant-secret KEK (ADR-011 Phase 6).
8572
+ *
8573
+ * Re-encrypts every `runtime.env` envelope at the new KEK version
8574
+ * transparently. Previous versions remain valid until explicitly
8575
+ * revoked via {@link revokeKek}. Owner-only.
8576
+ */
8577
+ async rotateKek(appId) {
8578
+ return this.http.post(
8579
+ `/api/deployment/apps/${encodeURIComponent(appId)}/credentials/rotate-kek`,
8580
+ {}
8581
+ );
8582
+ }
8583
+ /**
8584
+ * Revoke a tenant-secret KEK version (ADR-011 Phase 6 emergency burn).
8585
+ *
8586
+ * Envelopes at the revoked version become operationally dead —
8587
+ * decryption inside the smart-app pod fails. Owner-only and
8588
+ * **irreversible**. Returns the cumulative list of revoked versions
8589
+ * for this app.
8590
+ */
8591
+ async revokeKek(appId, version) {
8592
+ return this.http.post(
8593
+ `/api/deployment/apps/${encodeURIComponent(appId)}/credentials/revoke-kek`,
8594
+ { version }
8595
+ );
8596
+ }
8597
+ };
8598
+
8599
+ // src/bridge/index.ts
8600
+ var bridge_exports = {};
8601
+ __export(bridge_exports, {
8602
+ BridgeClient: () => BridgeClient
8603
+ });
8604
+
8605
+ // src/bridge/bridge-client.ts
8606
+ var BridgeClient = class {
8607
+ constructor(http) {
8608
+ this.http = http;
8609
+ }
8610
+ http;
8611
+ /** Create a new bridge instance — triggers DKG + TSS entity creation server-side. */
8612
+ async create(request) {
8613
+ return this.http.post("/bridge/create", request);
8614
+ }
8615
+ /** List bridges. Both filters are optional. */
8616
+ async list(options) {
8617
+ const params = new URLSearchParams();
8618
+ if (options?.status) params.append("status", options.status);
8619
+ if (options?.sourceChain) params.append("sourceChain", options.sourceChain);
8620
+ const qs = params.toString();
8621
+ return this.http.get(`/bridge/list${qs ? `?${qs}` : ""}`);
8622
+ }
8623
+ /** Get bridge configuration. */
8624
+ async get(bridgeId) {
8625
+ return this.http.get(`/bridge/${encodePathParam(bridgeId)}`);
8626
+ }
8627
+ /** Port tokens from source → destination. */
8628
+ async port(bridgeId, request) {
8629
+ return this.http.post(`/bridge/${encodePathParam(bridgeId)}/port`, request);
8630
+ }
8631
+ /**
8632
+ * Return tokens from destination → source. Only meaningful on two-way
8633
+ * bridges; the validator rejects the call on one-way bridges with a 400.
8634
+ *
8635
+ * Method name is `return_` to avoid colliding with the reserved JS
8636
+ * keyword in some downstream codegen. Prefer `client.bridge.return(...)`
8637
+ * via the named alias below.
8638
+ */
8639
+ async return(bridgeId, request) {
8640
+ return this.http.post(`/bridge/${encodePathParam(bridgeId)}/return`, request);
8641
+ }
8642
+ /** Get claim status by claim ID under a given bridge. */
8643
+ async getStatus(bridgeId, claimId) {
8644
+ return this.http.get(
8645
+ `/bridge/${encodePathParam(bridgeId)}/status/${encodePathParam(claimId)}`
8646
+ );
8647
+ }
8648
+ /** Get aggregate supply view for a bridge. */
8649
+ async getSupply(bridgeId) {
8650
+ return this.http.get(`/bridge/${encodePathParam(bridgeId)}/supply`);
8651
+ }
8652
+ /** List bridge claims with optional pagination. */
8653
+ async listClaims(bridgeId, options) {
8654
+ const params = new URLSearchParams();
8655
+ if (options?.limit !== void 0) params.append("limit", String(options.limit));
8656
+ if (options?.offset !== void 0) params.append("offset", String(options.offset));
8657
+ const qs = params.toString();
8658
+ return this.http.get(
8659
+ `/bridge/${encodePathParam(bridgeId)}/claims${qs ? `?${qs}` : ""}`
8660
+ );
8661
+ }
8662
+ };
8663
+
8664
+ // src/resources/index.ts
8665
+ var resources_exports = {};
8666
+ __export(resources_exports, {
8667
+ ResourcesClient: () => ResourcesClient
8668
+ });
8669
+
8670
+ // src/resources/resources-client.ts
8671
+ var ResourcesClient = class {
8672
+ constructor(http) {
8673
+ this.http = http;
8674
+ }
8675
+ http;
8676
+ /** Network-wide consumption summary across all nodes. */
8677
+ async getSummary() {
8678
+ return this.http.get("/resources/summary");
8679
+ }
8680
+ /** Current-day consumption breakdown for an app. */
8681
+ async getConsumption(appId) {
8682
+ return this.http.get(`/resources/consumption/${encodePathParam(appId)}`);
8683
+ }
8684
+ /** Daily usage history from the persistent store. `days` defaults to 30 server-side. */
8685
+ async getHistory(appId, days) {
8686
+ const qs = days !== void 0 ? `?days=${days}` : "";
8687
+ return this.http.get(
8688
+ `/resources/consumption/${encodePathParam(appId)}/history${qs}`
8689
+ );
8690
+ }
8691
+ /** Paginated billing ledger. All filters optional. */
8692
+ async getLedger(appId, options) {
8693
+ const params = new URLSearchParams();
8694
+ if (options?.limit !== void 0) params.append("limit", String(options.limit));
8695
+ if (options?.offset !== void 0) params.append("offset", String(options.offset));
8696
+ if (options?.since) params.append("since", options.since);
8697
+ if (options?.until) params.append("until", options.until);
8698
+ if (options?.category) params.append("category", options.category);
8699
+ const qs = params.toString();
8700
+ return this.http.get(
8701
+ `/resources/consumption/${encodePathParam(appId)}/ledger${qs ? `?${qs}` : ""}`
8702
+ );
8703
+ }
8704
+ /**
8705
+ * Current consumption status with threshold warnings and upgrade hints.
8706
+ * `dailyLimit` overrides the per-app tier default and is rare —
8707
+ * smart-app callers should leave it unset.
8708
+ */
8709
+ async getStatus(appId, dailyLimit) {
8710
+ const qs = dailyLimit !== void 0 ? `?dailyLimit=${dailyLimit}` : "";
8711
+ return this.http.get(
8712
+ `/resources/consumption/${encodePathParam(appId)}/status${qs}`
8713
+ );
8714
+ }
8715
+ /** Consumption aggregated by category over the supplied window. */
8716
+ async getBreakdown(appId, options) {
8717
+ const params = new URLSearchParams();
8718
+ if (options?.since) params.append("since", options.since);
8719
+ if (options?.until) params.append("until", options.until);
8720
+ const qs = params.toString();
8721
+ return this.http.get(
8722
+ `/resources/consumption/${encodePathParam(appId)}/breakdown${qs ? `?${qs}` : ""}`
8723
+ );
8724
+ }
8725
+ /** Per-node consumption reports. */
8726
+ async listNodes() {
8727
+ return this.http.get("/resources/nodes");
8728
+ }
8729
+ /** Single node's report. */
8730
+ async getNode(nodeId) {
8731
+ return this.http.get(`/resources/nodes/${encodePathParam(nodeId)}`);
8732
+ }
8733
+ };
8734
+
8735
+ // src/envelope/index.ts
8736
+ var envelope_exports = {};
8737
+ __export(envelope_exports, {
8738
+ EnvelopeClient: () => EnvelopeClient
8739
+ });
8740
+
8741
+ // src/envelope/envelope-client.ts
8742
+ var EnvelopeClient = class {
8743
+ constructor(http) {
8744
+ this.http = http;
8745
+ }
8746
+ http;
8747
+ /**
8748
+ * Seal `plaintext` under the per-app KEK for `appId` at `kekVersion`.
8749
+ * Returns the canonical envelope shape suitable for persistence in
8750
+ * Mongo / NATS / on the EventBus.
8751
+ */
8752
+ async encrypt(request) {
8753
+ return this.http.post("/envelope/encrypt", request);
8754
+ }
8755
+ /**
8756
+ * Open `envelope` for `appId`. The plaintext is returned in the response
8757
+ * body — callers MUST treat it as ephemeral (no logs, no Mongo, no
8758
+ * NATS broadcast). The validator never persists or replays it.
8759
+ */
8760
+ async decrypt(request) {
8761
+ return this.http.post("/envelope/decrypt", request);
8762
+ }
8763
+ };
8764
+
8765
+ // src/tokens/index.ts
8766
+ var tokens_exports = {};
8767
+ __export(tokens_exports, {
8768
+ TokensClient: () => TokensClient
8769
+ });
8770
+
8771
+ // src/tokens/tokens-client.ts
8772
+ var TokensClient = class {
8773
+ constructor(http) {
8774
+ this.http = http;
8775
+ }
8776
+ http;
8777
+ /** Initiate a token migration to TSS-controlled keys. */
8778
+ async migrate(request) {
8779
+ return this.http.post("/tokens/migrate", request);
8780
+ }
8781
+ /** List all known migrations on this validator. */
8782
+ async listMigrations() {
8783
+ return this.http.get("/tokens/migrations");
8784
+ }
8785
+ /**
8786
+ * Get one migration's status by id. The server returns
8787
+ * `{ error: string }` (NOT a 404) when the migration is unknown, so the
8788
+ * union type makes the failure mode explicit.
8789
+ */
8790
+ async getMigration(migrationId) {
8791
+ return this.http.get(`/tokens/migrations/${encodePathParam(migrationId)}`);
8792
+ }
8793
+ /** All migrations recorded against a specific token id. */
8794
+ async getMigrationsForToken(tokenId) {
8795
+ return this.http.get(`/tokens/${encodePathParam(tokenId)}/migrations`);
8796
+ }
8797
+ /**
8798
+ * Get token details. NOTE: collides with `client.getTokenInfo(...)` —
8799
+ * see the class JSDoc above for the route-order details. Prefer
8800
+ * `client.getTokenInfo(...)` unless you have a reason to call this one.
8801
+ */
8802
+ async getDetails(chain, tokenId) {
8803
+ return this.http.get(
8804
+ `/tokens/${encodePathParam(chain)}/${encodePathParam(tokenId)}`
8805
+ );
8806
+ }
8807
+ };
8808
+
8809
+ // src/operator/index.ts
8810
+ var operator_exports = {};
8811
+ __export(operator_exports, {
8812
+ OperatorClient: () => OperatorClient
8813
+ });
8814
+
8815
+ // src/operator/operator-client.ts
8816
+ var OperatorClient = class {
8817
+ constructor(http) {
8818
+ this.http = http;
8819
+ }
8820
+ http;
8821
+ /** Get the on-chain HBAR + token balance of an operator account. */
8822
+ async getBalance(chain, accountId) {
8823
+ return this.http.get(
8824
+ `/operator/balance/${encodePathParam(chain)}/${encodePathParam(accountId)}`
8825
+ );
8826
+ }
8827
+ /** Get top-up guidance for an operator account (recommended balance + status). */
8828
+ async getTopup(chain, accountId) {
8829
+ return this.http.get(
8830
+ `/operator/topup/${encodePathParam(chain)}/${encodePathParam(accountId)}`
8831
+ );
8832
+ }
8010
8833
  };
8011
8834
 
8012
8835
  // src/client.ts
@@ -8043,12 +8866,26 @@ var SmartEngineClient = class _SmartEngineClient {
8043
8866
  settlement;
8044
8867
  /** Governance proposal dry-run (simulate-only) */
8045
8868
  governance;
8869
+ /** DAO governance — DAOs, proposals, votes, treasury, members, dashboard */
8870
+ dao;
8046
8871
  /** Personhood verification (HPP one-human-one-member) */
8047
8872
  personhood;
8048
8873
  /** BaaS smart-agent lifecycle (register/fund/trade/withdraw/pause/resume/revoke/...) */
8049
8874
  agents;
8050
8875
  /** BaaS smart-app deployment lifecycle (init/uploadFrontend/deploy/rollback/status/...) */
8051
8876
  deployments;
8877
+ /** Universal Token Bridge — port/return/claim across chains */
8878
+ bridge;
8879
+ /** Network + per-app resource consumption (summary, history, ledger, nodes) */
8880
+ resources;
8881
+ /** AES-256-GCM envelope encrypt/decrypt under the TSS-backed master KEK */
8882
+ envelope;
8883
+ /** Token migration — move existing tokens to TSS-controlled keys */
8884
+ tokens;
8885
+ /** Operator account funding helpers (balance + top-up guidance) */
8886
+ operator;
8887
+ /** Discovery endpoints — cluster registry + platform-image manifests */
8888
+ discovery;
8052
8889
  constructor(config) {
8053
8890
  this.allowInsecure = config.allowInsecure ?? false;
8054
8891
  this.baseUrl = validateClientUrl(config.baseUrl, this.allowInsecure);
@@ -8068,7 +8905,7 @@ var SmartEngineClient = class _SmartEngineClient {
8068
8905
  this.tss = new TSSClient(this.http);
8069
8906
  this.ipfs = new IPFSClient(this.http);
8070
8907
  this.transactions = new TransactionsClient(this.txHttp);
8071
- this.hedera = new HederaTransactionsClient(this.txHttp);
8908
+ this.hedera = new HederaTransactionsClient(this.txHttp, this.http);
8072
8909
  this.xrpl = new XrplTransactionsClient(this.txHttp);
8073
8910
  this.solana = new SolanaTransactionsClient(this.txHttp);
8074
8911
  this.polkadot = new PolkadotTransactionsClient(this.txHttp);
@@ -8076,6 +8913,7 @@ var SmartEngineClient = class _SmartEngineClient {
8076
8913
  this.historicalBalance = HistoricalBalanceClient.fromHttp(this.http);
8077
8914
  this.settlement = new SettlementClient(this.http);
8078
8915
  this.governance = new GovernanceClient(this.http);
8916
+ this.dao = new DaoClient(this.http);
8079
8917
  this.personhood = new PersonhoodClient(this.http);
8080
8918
  const rootHttp = createHttpClient({
8081
8919
  baseUrl: this.baseUrl,
@@ -8085,6 +8923,12 @@ var SmartEngineClient = class _SmartEngineClient {
8085
8923
  });
8086
8924
  this.agents = new AgentsClient(rootHttp);
8087
8925
  this.deployments = new DeploymentClient(rootHttp);
8926
+ this.bridge = new BridgeClient(this.http);
8927
+ this.resources = new ResourcesClient(this.http);
8928
+ this.envelope = new EnvelopeClient(this.http);
8929
+ this.tokens = new TokensClient(this.http);
8930
+ this.operator = new OperatorClient(this.http);
8931
+ this.discovery = new DiscoveryClient(this.http);
8088
8932
  }
8089
8933
  /**
8090
8934
  * Build a `SmartEngineClient` from a plain env object. Reads:
@@ -8168,7 +9012,18 @@ var SmartEngineClient = class _SmartEngineClient {
8168
9012
  * 2. (Optional) HCS trust-anchor membership cross-check.
8169
9013
  * 3. Random-pick over the verified set.
8170
9014
  *
8171
- * @example
9015
+ * @example Zero-config (recommended for smart-app callers)
9016
+ * ```ts
9017
+ * const { client, cluster, session } = await SmartEngineClient.connectToCluster({
9018
+ * network: 'testnet', // resolves canonical gateway entrypoint
9019
+ * chain: 'xrpl',
9020
+ * address: '...',
9021
+ * publicKey: '...',
9022
+ * signFn: async (challenge) => sign(challenge),
9023
+ * });
9024
+ * ```
9025
+ *
9026
+ * @example Custom seeds (private deployments / local dev)
8172
9027
  * ```ts
8173
9028
  * const { client, cluster, session } = await SmartEngineClient.connectToCluster({
8174
9029
  * bootstrap: ['https://sn1.testnet.hsuite.network', 'https://sn2.testnet.hsuite.network'],
@@ -8181,8 +9036,15 @@ var SmartEngineClient = class _SmartEngineClient {
8181
9036
  */
8182
9037
  static async connectToCluster(config) {
8183
9038
  const allowInsecure = config.allowInsecure ?? false;
9039
+ const bootstrap = config.bootstrap ? [...config.bootstrap] : [...resolveNetwork(config.network).bootstrap];
9040
+ if (bootstrap.length === 0) {
9041
+ throw new SmartEngineError2(
9042
+ "connectToCluster requires either a non-empty `bootstrap` list or a known `network` name.",
9043
+ 400
9044
+ );
9045
+ }
8184
9046
  const discovery = new ClusterDiscoveryClient({
8185
- bootstrap: config.bootstrap,
9047
+ bootstrap,
8186
9048
  allowInsecure,
8187
9049
  trustAnchor: config.trustAnchor ? {
8188
9050
  network: config.trustAnchor.network,
@@ -8282,7 +9144,19 @@ var SmartEngineClient = class _SmartEngineClient {
8282
9144
  const validated = MintTokenRequestSchema.parse(request);
8283
9145
  return this.http.post("/tokens/mint", validated);
8284
9146
  }
8285
- /** Get token information */
9147
+ /**
9148
+ * Get token information.
9149
+ *
9150
+ * Route `GET /api/v3/tokens/:chain/:tokenId` is registered twice on the
9151
+ * validator: by `ValidatorController` at
9152
+ * `apps/smart-validator/src/validator.controller.ts:497` and by
9153
+ * `TokenMigrationController` at
9154
+ * `apps/smart-validator/src/token-migration/token-migration.controller.ts:173`.
9155
+ * Nest resolves routes in `controllers: [...]` order — `ValidatorController`
9156
+ * is registered first (`apps/smart-validator/src/smart-validator.module.ts:1222`),
9157
+ * so `multiChain.getTokenInfo(chain, tokenId)` wins and the
9158
+ * token-migration handler is unreachable via this path.
9159
+ */
8286
9160
  async getTokenInfo(chain, tokenId) {
8287
9161
  return this.http.get(`/tokens/${encodePathParam(chain)}/${encodePathParam(tokenId)}`);
8288
9162
  }
@@ -8430,47 +9304,56 @@ var RoutingClient = class {
8430
9304
  this.http = http;
8431
9305
  }
8432
9306
  http;
8433
- /** Register a new host */
9307
+ /**
9308
+ * Register a new host. The server validates the payload via Zod (appId
9309
+ * pattern, IP/hostname format, port range) and kicks off async
9310
+ * verification. Response includes the registered host plus a status
9311
+ * message about verification.
9312
+ */
8434
9313
  async registerHost(request) {
8435
9314
  return this.http.post("/routing/hosts", request);
8436
9315
  }
8437
- /** Unregister a host */
9316
+ /** Unregister a host. */
8438
9317
  async unregisterHost(hostId) {
8439
9318
  return this.http.delete(`/routing/hosts/${encodeURIComponent(hostId)}`);
8440
9319
  }
8441
- /** Get all registered hosts */
9320
+ /** Get all registered hosts. */
8442
9321
  async getAllHosts() {
8443
9322
  return this.http.get("/routing/hosts");
8444
9323
  }
8445
- /** Get only verified hosts */
9324
+ /** Get only verified hosts. */
8446
9325
  async getVerifiedHosts() {
8447
9326
  return this.http.get("/routing/hosts/verified");
8448
9327
  }
8449
- /** Get a specific host by ID */
9328
+ /** Get a specific host by ID. */
8450
9329
  async getHost(hostId) {
8451
9330
  return this.http.get(`/routing/hosts/${encodeURIComponent(hostId)}`);
8452
9331
  }
8453
- /** Verify a host */
9332
+ /** Trigger host re-verification. */
8454
9333
  async verifyHost(hostId) {
8455
9334
  return this.http.post(`/routing/hosts/${encodeURIComponent(hostId)}/verify`, {});
8456
9335
  }
8457
- /** Set routing configuration for an app */
9336
+ /** Set routing configuration for an app. */
8458
9337
  async setRoutingConfig(appId, config) {
8459
9338
  return this.http.put(`/routing/config/${encodeURIComponent(appId)}`, config);
8460
9339
  }
8461
- /** Get routing configuration for an app */
9340
+ /** Get routing configuration for an app. */
8462
9341
  async getRoutingConfig(appId) {
8463
9342
  return this.http.get(`/routing/config/${encodeURIComponent(appId)}`);
8464
9343
  }
8465
- /** Proxy a request through the gateway */
9344
+ /** Proxy a request through the gateway. */
8466
9345
  async proxyRequest(request) {
8467
9346
  return this.http.post("/routing/proxy", request);
8468
9347
  }
8469
- /** Get routing statistics */
9348
+ /** Get routing statistics. */
8470
9349
  async getStats() {
8471
9350
  return this.http.get("/routing/stats");
8472
9351
  }
8473
- /** Map a domain to an application */
9352
+ /**
9353
+ * Map a domain/subdomain to an application for hostname-based routing.
9354
+ * The server returns `{ domain, appId, message }` — there is no `success`
9355
+ * field; treat `appId` as the success signal.
9356
+ */
8474
9357
  async mapDomainToApp(domain, appId) {
8475
9358
  return this.http.post(`/routing/domains/${encodeURIComponent(domain)}/map`, { appId });
8476
9359
  }
@@ -8499,7 +9382,11 @@ var DomainsClient = class {
8499
9382
  const params = owner ? `?owner=${encodeURIComponent(owner)}` : "";
8500
9383
  return this.http.get(`/domains${params}`);
8501
9384
  }
8502
- /** Generate a verification token */
9385
+ /**
9386
+ * Generate a verification token. Server accepts one of `dns-txt`,
9387
+ * `dns-cname`, `http-file`, `email` (see controller Swagger enum at
9388
+ * `apps/smart-gateway/src/domains/domains.controller.ts:226-234`).
9389
+ */
8503
9390
  async generateVerificationToken(domain, method) {
8504
9391
  return this.http.post(`/domains/${encodeURIComponent(domain)}/verification`, { method });
8505
9392
  }
@@ -8615,6 +9502,23 @@ var DnsClient = class {
8615
9502
  }
8616
9503
  };
8617
9504
 
9505
+ // src/gateway/health/index.ts
9506
+ var HealthClient = class {
9507
+ constructor(http) {
9508
+ this.http = http;
9509
+ }
9510
+ http;
9511
+ /**
9512
+ * Per-cluster aggregate health probe. Wraps
9513
+ * `GET /api/v3/cluster/health` — see
9514
+ * `apps/smart-gateway/src/health/health.controller.ts:213-263`. Returns
9515
+ * local validator + host + genesis state in a single payload.
9516
+ */
9517
+ async getCluster() {
9518
+ return this.http.get("/cluster/health");
9519
+ }
9520
+ };
9521
+
8618
9522
  // src/gateway/client.ts
8619
9523
  var SmartGatewayClient = class {
8620
9524
  http;
@@ -8624,6 +9528,8 @@ var SmartGatewayClient = class {
8624
9528
  domains;
8625
9529
  /** DNS resolution and zone management */
8626
9530
  dns;
9531
+ /** Per-cluster aggregate health probe (validator + host + genesis state) */
9532
+ health;
8627
9533
  constructor(config) {
8628
9534
  const baseUrl = config.baseUrl.replace(/\/+$/, "");
8629
9535
  this.http = createHttpClient({
@@ -8635,30 +9541,41 @@ var SmartGatewayClient = class {
8635
9541
  this.routing = new RoutingClient(this.http);
8636
9542
  this.domains = new DomainsClient(this.http);
8637
9543
  this.dns = new DnsClient(this.http);
9544
+ this.health = new HealthClient(this.http);
8638
9545
  }
8639
9546
  // ========== Health & Metrics ==========
8640
- /** Get gateway health status */
9547
+ /** Get gateway-only health status (binary `status: 'ok'` snapshot). */
8641
9548
  async getHealth() {
8642
9549
  return this.http.get("/health");
8643
9550
  }
8644
- /** Get gateway status with host and domain counts */
9551
+ /**
9552
+ * Get detailed gateway status — `subsystems` tree (dns/routing/verification)
9553
+ * plus the operating `mode` snapshot. Aggregated counts live on `getMetrics()`.
9554
+ */
8645
9555
  async getStatus() {
8646
9556
  return this.http.get("/status");
8647
9557
  }
8648
- /** Check gateway readiness */
9558
+ /**
9559
+ * Check gateway readiness. Returns either `{ status: 'ready', ... }` with
9560
+ * a verified host count or `{ status: 'not_ready', reason, ... }`.
9561
+ */
8649
9562
  async getReadiness() {
8650
9563
  return this.http.get("/ready");
8651
9564
  }
8652
- /** Check gateway liveness */
9565
+ /** Check gateway liveness. */
8653
9566
  async getLiveness() {
8654
9567
  return this.http.get("/live");
8655
9568
  }
8656
- /** Get detailed gateway metrics */
9569
+ /**
9570
+ * Get aggregated network metrics across all clusters — per-cluster health,
9571
+ * chain connectivity, gateway counts, and genesis state. Server caches the
9572
+ * payload (default 30s); pass `refresh=true` to force a fresh fetch.
9573
+ */
8657
9574
  async getMetrics(refresh) {
8658
9575
  const params = refresh ? "?refresh=true" : "";
8659
9576
  return this.http.get(`/metrics${params}`);
8660
9577
  }
8661
- /** Get metrics summary */
9578
+ /** Get lightweight network summary (status-badge-friendly). */
8662
9579
  async getMetricsSummary() {
8663
9580
  return this.http.get("/metrics/summary");
8664
9581
  }
@@ -9168,8 +10085,10 @@ __export(baas_exports, {
9168
10085
  BaasError: () => BaasError,
9169
10086
  DatabaseClient: () => DatabaseClient,
9170
10087
  DeploymentClient: () => DeploymentClient,
10088
+ EntitiesClient: () => EntitiesClient,
9171
10089
  FunctionsClient: () => FunctionsClient,
9172
10090
  MessagingClient: () => MessagingClient,
10091
+ RulesClient: () => RulesClient,
9173
10092
  StorageClient: () => StorageClient,
9174
10093
  validateAgentRules: () => validateAgentRules
9175
10094
  });
@@ -9229,11 +10148,37 @@ var DatabaseClient = class {
9229
10148
  );
9230
10149
  }
9231
10150
  /**
9232
- * List collections for the app
10151
+ * List collections for the app.
10152
+ *
10153
+ * Server route is `/api/db/:appId/collections`
10154
+ * (`database.controller.ts:106`). The previous bare-`:appId` GET 404'd
10155
+ * — Nest reserves that pattern for the document-find router below.
9233
10156
  */
9234
10157
  async listCollections() {
9235
10158
  const appId = this.getAppId();
9236
- return this.http.get(`/api/db/${encodeURIComponent(appId)}`);
10159
+ return this.http.get(`/api/db/${encodeURIComponent(appId)}/collections`);
10160
+ }
10161
+ /**
10162
+ * Create a new collection in the database.
10163
+ *
10164
+ * Server returns `{ success: true; collection: string }`
10165
+ * (`database.controller.ts:96`).
10166
+ */
10167
+ async createCollection(name) {
10168
+ const appId = this.getAppId();
10169
+ return this.http.post(`/api/db/${encodeURIComponent(appId)}/collections`, { name });
10170
+ }
10171
+ /**
10172
+ * Drop a collection and all its documents.
10173
+ *
10174
+ * Server returns `{ success: true }`
10175
+ * (`database.controller.ts:133`).
10176
+ */
10177
+ async dropCollection(name) {
10178
+ const appId = this.getAppId();
10179
+ return this.http.delete(
10180
+ `/api/db/${encodeURIComponent(appId)}/collections/${encodeURIComponent(name)}`
10181
+ );
9237
10182
  }
9238
10183
  // ========== State Proofs ==========
9239
10184
  /**
@@ -9294,13 +10239,15 @@ var StorageClient = class {
9294
10239
  * Download a file by CID
9295
10240
  */
9296
10241
  async download(cid) {
9297
- return this.http.get(`/api/storage/download/${encodeURIComponent(cid)}`);
10242
+ const appId = this.getAppId();
10243
+ return this.http.get(`/api/storage/${encodeURIComponent(appId)}/download/${encodeURIComponent(cid)}`);
9298
10244
  }
9299
10245
  /**
9300
10246
  * Get file metadata
9301
10247
  */
9302
10248
  async getMetadata(cid) {
9303
- return this.http.get(`/api/storage/metadata/${encodeURIComponent(cid)}`);
10249
+ const appId = this.getAppId();
10250
+ return this.http.get(`/api/storage/${encodeURIComponent(appId)}/metadata/${encodeURIComponent(cid)}`);
9304
10251
  }
9305
10252
  /**
9306
10253
  * Delete a file
@@ -9310,20 +10257,29 @@ var StorageClient = class {
9310
10257
  return this.http.delete(`/api/storage/${encodeURIComponent(appId)}/${encodeURIComponent(cid)}`);
9311
10258
  }
9312
10259
  /**
9313
- * Get file info
10260
+ * Get file info.
10261
+ *
10262
+ * @deprecated The smart-host storage controller does not expose a
10263
+ * bare-CID metadata route — every metadata lookup must go through
10264
+ * `getMetadata(cid)` (`/api/storage/:appId/metadata/:cid`) or the
10265
+ * stream body via `download(cid)`. This alias forwards to `download`
10266
+ * for back-compat; remove in the next major SDK release.
9314
10267
  */
9315
10268
  async getFile(cid) {
9316
- const appId = this.getAppId();
9317
- return this.http.get(`/api/storage/${encodeURIComponent(appId)}/${encodeURIComponent(cid)}`);
10269
+ return this.download(cid);
9318
10270
  }
9319
10271
  /**
9320
10272
  * List all files for the app
10273
+ *
10274
+ * @param pagination.offset Server reads `offset`; the legacy `skip`
10275
+ * option was a client-only synonym that the server silently ignored.
10276
+ * Use `offset` going forward.
9321
10277
  */
9322
10278
  async listFiles(pagination) {
9323
10279
  const appId = this.getAppId();
9324
10280
  const params = new URLSearchParams();
9325
10281
  if (pagination?.limit !== void 0) params.set("limit", String(pagination.limit));
9326
- if (pagination?.skip !== void 0) params.set("skip", String(pagination.skip));
10282
+ if (pagination?.offset !== void 0) params.set("offset", String(pagination.offset));
9327
10283
  const qs = params.toString();
9328
10284
  return this.http.get(`/api/storage/${encodeURIComponent(appId)}/files${qs ? `?${qs}` : ""}`);
9329
10285
  }
@@ -9331,13 +10287,15 @@ var StorageClient = class {
9331
10287
  * Get storage usage for the current app
9332
10288
  */
9333
10289
  async getUsage() {
9334
- return this.http.get("/api/storage/usage");
10290
+ const appId = this.getAppId();
10291
+ return this.http.get(`/api/storage/${encodeURIComponent(appId)}/usage`);
9335
10292
  }
9336
10293
  /**
9337
10294
  * Check if a file exists
9338
10295
  */
9339
10296
  async exists(cid) {
9340
- return this.http.get(`/api/storage/exists/${encodeURIComponent(cid)}`);
10297
+ const appId = this.getAppId();
10298
+ return this.http.get(`/api/storage/${encodeURIComponent(appId)}/exists/${encodeURIComponent(cid)}`);
9341
10299
  }
9342
10300
  };
9343
10301
 
@@ -9360,42 +10318,60 @@ var FunctionsClient = class {
9360
10318
  * Invoke a function
9361
10319
  */
9362
10320
  async invoke(functionId, payload) {
9363
- return this.http.post(`/api/functions/${encodeURIComponent(functionId)}/invoke`, payload ?? {});
10321
+ const appId = this.getAppId();
10322
+ return this.http.post(
10323
+ `/api/functions/${encodeURIComponent(appId)}/${encodeURIComponent(functionId)}/invoke`,
10324
+ payload ?? {}
10325
+ );
9364
10326
  }
9365
10327
  /**
9366
- * List all functions
10328
+ * List all functions for the current app
9367
10329
  */
9368
10330
  async list() {
9369
- return this.http.get("/api/functions");
10331
+ const appId = this.getAppId();
10332
+ return this.http.get(`/api/functions/${encodeURIComponent(appId)}`);
9370
10333
  }
9371
10334
  /**
9372
10335
  * Get function details
9373
10336
  */
9374
10337
  async get(functionId) {
9375
- return this.http.get(`/api/functions/${encodeURIComponent(functionId)}`);
10338
+ const appId = this.getAppId();
10339
+ return this.http.get(
10340
+ `/api/functions/${encodeURIComponent(appId)}/${encodeURIComponent(functionId)}`
10341
+ );
9376
10342
  }
9377
10343
  /**
9378
10344
  * Update a function
9379
10345
  */
9380
10346
  async update(functionId, updates) {
9381
- return this.http.put(`/api/functions/${encodeURIComponent(functionId)}`, updates);
10347
+ const appId = this.getAppId();
10348
+ return this.http.put(
10349
+ `/api/functions/${encodeURIComponent(appId)}/${encodeURIComponent(functionId)}`,
10350
+ updates
10351
+ );
9382
10352
  }
9383
10353
  /**
9384
10354
  * Delete a function
9385
10355
  */
9386
10356
  async delete(functionId) {
9387
- return this.http.delete(`/api/functions/${encodeURIComponent(functionId)}`);
10357
+ const appId = this.getAppId();
10358
+ return this.http.delete(
10359
+ `/api/functions/${encodeURIComponent(appId)}/${encodeURIComponent(functionId)}`
10360
+ );
9388
10361
  }
9389
10362
  /**
9390
10363
  * Get function execution logs
9391
10364
  */
9392
10365
  async getLogs(functionId, options) {
10366
+ const appId = this.getAppId();
9393
10367
  const params = new URLSearchParams();
9394
10368
  if (options?.limit !== void 0) params.set("limit", String(options.limit));
9395
10369
  if (options?.startTime) params.set("startTime", options.startTime);
9396
10370
  if (options?.level) params.set("level", options.level);
9397
10371
  const qs = params.toString();
9398
- return this.http.get(`/api/functions/${encodeURIComponent(functionId)}/logs${qs ? `?${qs}` : ""}`);
10372
+ return this.http.get(
10373
+ `/api/functions/${encodeURIComponent(appId)}/${encodeURIComponent(functionId)}/logs${qs ? `?${qs}` : ""}`
10374
+ );
9399
10375
  }
9400
10376
  /**
9401
10377
  * Get function statistics for an app
@@ -9467,25 +10443,43 @@ var MessagingClient = class {
9467
10443
  );
9468
10444
  }
9469
10445
  /**
9470
- * Set presence for a member
10446
+ * Set presence for a member in a channel.
10447
+ *
10448
+ * BREAKING CHANGE (SDK 3.3.0): presence is channel-scoped on the server
10449
+ * (`messaging.controller.ts:312`). Previous signature
10450
+ * `setPresence(member)` hit a non-existent appId-scoped route and 404'd
10451
+ * in production. The channel is now the first argument.
9471
10452
  */
9472
- async setPresence(member) {
10453
+ async setPresence(channel, member) {
9473
10454
  const appId = this.getAppId();
9474
- return this.http.post(`/api/messaging/${encodeURIComponent(appId)}/presence`, member);
10455
+ return this.http.post(
10456
+ `/api/messaging/${encodeURIComponent(appId)}/channels/${encodeURIComponent(channel)}/presence`,
10457
+ member
10458
+ );
9475
10459
  }
9476
10460
  /**
9477
- * Remove presence for a member
10461
+ * Remove a member's presence from a channel.
10462
+ *
10463
+ * BREAKING CHANGE (SDK 3.3.0): server route is
10464
+ * `/api/messaging/:appId/channels/:channel/presence/:clientId`
10465
+ * (`messaging.controller.ts:352`). `channel` is now the first arg and
10466
+ * `clientId` (not `memberId`) the second — they're the same identifier
10467
+ * but renamed to match the server param.
9478
10468
  */
9479
- async removePresence(memberId) {
10469
+ async removePresence(channel, clientId) {
9480
10470
  const appId = this.getAppId();
9481
- return this.http.delete(`/api/messaging/${encodeURIComponent(appId)}/presence/${encodeURIComponent(memberId)}`);
10471
+ return this.http.delete(
10472
+ `/api/messaging/${encodeURIComponent(appId)}/channels/${encodeURIComponent(channel)}/presence/${encodeURIComponent(clientId)}`
10473
+ );
9482
10474
  }
9483
10475
  /**
9484
10476
  * Get presence info for a channel
9485
10477
  */
9486
10478
  async getPresence(channel) {
9487
10479
  const appId = this.getAppId();
9488
- return this.http.get(`/api/messaging/${encodeURIComponent(appId)}/presence/${encodeURIComponent(channel)}`);
10480
+ return this.http.get(
10481
+ `/api/messaging/${encodeURIComponent(appId)}/channels/${encodeURIComponent(channel)}/presence`
10482
+ );
9489
10483
  }
9490
10484
  /**
9491
10485
  * Get messaging statistics
@@ -9568,8 +10562,90 @@ var CustomerSessionClient = class {
9568
10562
  }
9569
10563
  };
9570
10564
 
10565
+ // src/baas/rules/client.ts
10566
+ var RulesClient = class {
10567
+ constructor(http) {
10568
+ this.http = http;
10569
+ }
10570
+ http;
10571
+ /** Publish a canonical ValidatorRules document to HCS. */
10572
+ async publish(rule) {
10573
+ return this.http.post("/api/rules/publish", rule);
10574
+ }
10575
+ /** Fetch a published rule by its HCS consensus timestamp. */
10576
+ async get(consensusTimestamp) {
10577
+ return this.http.get(`/api/rules/${encodeURIComponent(consensusTimestamp)}`);
10578
+ }
10579
+ /** List rules owned by the authenticated entity, optionally filtered by type. */
10580
+ async listByOwner(filter) {
10581
+ const path = filter?.type ? `/api/rules?type=${encodeURIComponent(filter.type)}` : "/api/rules";
10582
+ return this.http.get(path);
10583
+ }
10584
+ /**
10585
+ * Simulate cluster-side evaluation of an action against a rule. Either
10586
+ * `ruleRef` (published) or `rule` (inline) must be supplied by the caller.
10587
+ */
10588
+ async simulate(params) {
10589
+ return this.http.post("/api/rules/simulate", params);
10590
+ }
10591
+ /** Walk the version history of a published rule. */
10592
+ async getVersionHistory(consensusTimestamp) {
10593
+ return this.http.get(
10594
+ `/api/rules/${encodeURIComponent(consensusTimestamp)}/versions`
10595
+ );
10596
+ }
10597
+ /** Deprecate a published rule (owner-only). */
10598
+ async deprecate(consensusTimestamp) {
10599
+ return this.http.post(
10600
+ `/api/rules/${encodeURIComponent(consensusTimestamp)}/deprecate`,
10601
+ {}
10602
+ );
10603
+ }
10604
+ };
10605
+
10606
+ // src/baas/entities/client.ts
10607
+ var EntitiesClient = class {
10608
+ constructor(http) {
10609
+ this.http = http;
10610
+ }
10611
+ http;
10612
+ /** Create a canonical token entity bound to a published rule. */
10613
+ async createToken(req) {
10614
+ return this.http.post("/api/entities/createToken", req);
10615
+ }
10616
+ /** Create a canonical account entity bound to a published rule. */
10617
+ async createAccount(req) {
10618
+ return this.http.post("/api/entities/createAccount", req);
10619
+ }
10620
+ /** Create a canonical topic entity bound to a published rule. */
10621
+ async createTopic(req) {
10622
+ return this.http.post("/api/entities/createTopic", req);
10623
+ }
10624
+ /** Create a canonical agent entity bound to a published rule. */
10625
+ async createAgent(req) {
10626
+ return this.http.post("/api/entities/createAgent", req);
10627
+ }
10628
+ /**
10629
+ * Mega-helper: build a token rule with a launchpad ModuleEntry attached,
10630
+ * publish it, create the token, and return the combined result in one HTTP
10631
+ * round-trip.
10632
+ */
10633
+ async launchpad(req) {
10634
+ return this.http.post("/api/entities/launchpad", req);
10635
+ }
10636
+ /** Fetch an entity by its canonical `entityId`. */
10637
+ async get(entityId) {
10638
+ return this.http.get(`/api/entities/${encodeURIComponent(entityId)}`);
10639
+ }
10640
+ /** List entities owned by the authenticated wallet, optionally filtered by type. */
10641
+ async listByOwner(filter) {
10642
+ const path = filter?.type ? `/api/entities?type=${encodeURIComponent(filter.type)}` : "/api/entities";
10643
+ return this.http.get(path);
10644
+ }
10645
+ };
10646
+
9571
10647
  // src/baas/client.ts
9572
- var BaasClient = class {
10648
+ var BaasClient = class _BaasClient {
9573
10649
  hostUrl;
9574
10650
  pathPrefix;
9575
10651
  appId;
@@ -9594,6 +10670,10 @@ var BaasClient = class {
9594
10670
  agents;
9595
10671
  /** Customer→smart-app session bridge (TokenGate Face B). */
9596
10672
  customerSession;
10673
+ /** Canonical validator-rules authoring surface (publish/get/list/simulate). */
10674
+ rules;
10675
+ /** Canonical entity authoring surface (token/account/topic/agent + launchpad). */
10676
+ entities;
9597
10677
  constructor(config) {
9598
10678
  this.allowInsecure = config.allowInsecure ?? false;
9599
10679
  this.hostUrl = validateUrl2(config.hostUrl, this.allowInsecure);
@@ -9606,14 +10686,92 @@ var BaasClient = class {
9606
10686
  baseUrl: baseUrlWithPrefix,
9607
10687
  timeout: this.timeout
9608
10688
  });
9609
- const getAppId = () => this.requireAppId();
9610
- this.db = new DatabaseClient(this.http, getAppId);
9611
- this.storage = new StorageClient(this.http, getAppId);
9612
- this.functions = new FunctionsClient(this.http, getAppId);
9613
- this.messaging = new MessagingClient(this.http, getAppId);
9614
- this.deployment = new DeploymentClient(this.http);
9615
- this.agents = new AgentsClient(this.http);
9616
- this.customerSession = new CustomerSessionClient(baseUrlWithPrefix, this.timeout);
10689
+ const getAppId = () => this.requireAppId();
10690
+ this.db = new DatabaseClient(this.http, getAppId);
10691
+ this.storage = new StorageClient(this.http, getAppId);
10692
+ this.functions = new FunctionsClient(this.http, getAppId);
10693
+ this.messaging = new MessagingClient(this.http, getAppId);
10694
+ this.deployment = new DeploymentClient(this.http);
10695
+ this.agents = new AgentsClient(this.http);
10696
+ this.customerSession = new CustomerSessionClient(baseUrlWithPrefix, this.timeout);
10697
+ this.rules = new RulesClient(this.http);
10698
+ this.entities = new EntitiesClient(this.http);
10699
+ }
10700
+ /**
10701
+ * Connect to the Smart Engines BaaS via cluster auto-discovery.
10702
+ *
10703
+ * Zero-config entrypoint flow:
10704
+ *
10705
+ * 1. Resolves the bootstrap seed list:
10706
+ * - `network: 'testnet' | 'mainnet'` → canonical Cloudflare-fronted
10707
+ * gateway via {@link KNOWN_NETWORKS}.
10708
+ * - `bootstrap: string[]` → explicit seed list (private deployments).
10709
+ * 2. Fetches `GET /api/v3/discovery/clusters` from the first reachable
10710
+ * seed; the response carries every active cluster's gateway URL.
10711
+ * 3. Random-picks one active cluster.
10712
+ * 4. Returns a `BaasClient` pointed at that cluster's gatewayUrl, with
10713
+ * `pathPrefix: '/host'` so all BaaS sub-clients (db / storage /
10714
+ * functions / messaging / agents / rules / entities) route through
10715
+ * the gateway's `/host/*` rewrite.
10716
+ *
10717
+ * @example Zero-config (recommended)
10718
+ * ```ts
10719
+ * const baas = await BaasClient.connectToCluster({
10720
+ * network: 'testnet',
10721
+ * appId: 'app_abc',
10722
+ * });
10723
+ *
10724
+ * await baas.db.insert('users', { name: 'Alice' });
10725
+ * ```
10726
+ *
10727
+ * @example Custom seeds (private deployments)
10728
+ * ```ts
10729
+ * const baas = await BaasClient.connectToCluster({
10730
+ * bootstrap: ['https://gateway.my-private-net.example'],
10731
+ * appId: 'app_abc',
10732
+ * });
10733
+ * ```
10734
+ *
10735
+ * @throws {BaasError} `503` when no cluster is reachable via any seed.
10736
+ * @throws {BaasError} `400` when bootstrap resolution yields an empty list
10737
+ * (only possible when the caller passes an empty array explicitly).
10738
+ */
10739
+ static async connectToCluster(config) {
10740
+ const allowInsecure = config.allowInsecure ?? false;
10741
+ const bootstrap = config.bootstrap ? [...config.bootstrap] : [...resolveNetwork(config.network).bootstrap];
10742
+ if (bootstrap.length === 0) {
10743
+ throw new BaasError(
10744
+ "connectToCluster requires either a non-empty `bootstrap` list or a known `network` name.",
10745
+ 400
10746
+ );
10747
+ }
10748
+ const discovery = new ClusterDiscoveryClient({
10749
+ bootstrap,
10750
+ allowInsecure,
10751
+ trustAnchor: config.trustAnchor ? {
10752
+ network: config.trustAnchor.network,
10753
+ registryTopicId: config.trustAnchor.registryTopicId,
10754
+ mirrorNodeUrl: config.trustAnchor.mirrorNodeUrl,
10755
+ allowInsecure
10756
+ } : void 0
10757
+ });
10758
+ const cluster = await discovery.getRandomCluster();
10759
+ if (!cluster) {
10760
+ throw new BaasError(
10761
+ "No active clusters available via bootstrap seeds. Check network reachability or bootstrap URLs.",
10762
+ 503
10763
+ );
10764
+ }
10765
+ return new _BaasClient({
10766
+ hostUrl: cluster.endpoints.gatewayUrl,
10767
+ appId: config.appId,
10768
+ appName: config.appName,
10769
+ timeout: config.timeout,
10770
+ allowInsecure,
10771
+ // BaaS traffic is gateway-routed at `/host/*` by default. Callers
10772
+ // pointing at a bare host can override with `pathPrefix: ''`.
10773
+ pathPrefix: config.pathPrefix ?? "/host"
10774
+ });
9617
10775
  }
9618
10776
  /** Set the app ID (for newly registered apps) */
9619
10777
  setAppId(appId) {
@@ -9627,6 +10785,16 @@ var BaasClient = class {
9627
10785
  getAppId() {
9628
10786
  return this.appId;
9629
10787
  }
10788
+ /**
10789
+ * Get the configured host URL. After
10790
+ * {@link BaasClient.connectToCluster} this is the gateway URL of the
10791
+ * cluster the SDK landed on after random-pick — useful for logging,
10792
+ * "behind the curtain" UIs, or debugging which cluster is serving a
10793
+ * given request.
10794
+ */
10795
+ getHostUrl() {
10796
+ return this.hostUrl;
10797
+ }
9630
10798
  /**
9631
10799
  * Get HTTP resilience health information
9632
10800
  * @returns Object with circuit breaker state and last error (if any)
@@ -9935,6 +11103,1370 @@ async function verifyPqcAttestation(cert, payload, registrySnapshot) {
9935
11103
  thresholdMet: true
9936
11104
  };
9937
11105
  }
11106
+
11107
+ // src/rules/atoms/index.ts
11108
+ var atom = {
11109
+ timeRange: (cfg) => ({
11110
+ inclusive: true,
11111
+ timezone: "UTC",
11112
+ ...cfg
11113
+ }),
11114
+ limits: (cfg) => ({
11115
+ decimals: 0,
11116
+ inclusive: true,
11117
+ ...cfg
11118
+ }),
11119
+ permissionList: (cfg) => ({
11120
+ mode: "whitelist",
11121
+ controller: "owner",
11122
+ allowSelfAdd: false,
11123
+ allowWildcards: false,
11124
+ requiredScope: "execute",
11125
+ entries: [],
11126
+ ...cfg
11127
+ }),
11128
+ rateLimiter: (cfg) => ({
11129
+ strategy: "all",
11130
+ includeCurrentOperation: true,
11131
+ ...cfg
11132
+ }),
11133
+ cooldown: (cfg) => ({ ...cfg }),
11134
+ approvalThreshold: (cfg) => ({
11135
+ decimals: 0,
11136
+ ...cfg
11137
+ }),
11138
+ approvedPairs: (cfg) => ({
11139
+ strictMode: true,
11140
+ ...cfg
11141
+ }),
11142
+ tradeLimit: (cfg) => ({
11143
+ periodMs: 864e5,
11144
+ decimals: 0,
11145
+ ...cfg
11146
+ }),
11147
+ snapshot: (cfg) => ({
11148
+ validationMode: "minimum",
11149
+ ...cfg
11150
+ }),
11151
+ cronSchedule: (cfg) => ({
11152
+ allowOutsideSchedule: false,
11153
+ toleranceMs: 0,
11154
+ ...cfg
11155
+ }),
11156
+ countApproval: (cfg) => ({
11157
+ maxCount: 0,
11158
+ allowDuplicates: false,
11159
+ maxApprovalAgeSec: 0,
11160
+ allowSelfApproval: false,
11161
+ ...cfg
11162
+ }),
11163
+ externalEvidence: (cfg) => ({
11164
+ requiredSignatures: 1,
11165
+ maxEvidenceAgeSec: 3600,
11166
+ verifyPayloadHash: true,
11167
+ ...cfg
11168
+ }),
11169
+ fieldValues: (cfg) => ({
11170
+ requireAll: true,
11171
+ ...cfg,
11172
+ constraints: cfg.constraints.map((c) => ({
11173
+ caseInsensitive: false,
11174
+ denyMode: false,
11175
+ ...c
11176
+ }))
11177
+ }),
11178
+ registryReference: (cfg) => ({
11179
+ requireAll: true,
11180
+ ...cfg,
11181
+ references: cfg.references.map((r) => ({ required: true, ...r }))
11182
+ }),
11183
+ schemaValidation: (cfg) => ({
11184
+ strict: false,
11185
+ allErrors: true,
11186
+ validateFormats: false,
11187
+ errorPrefix: "Schema validation failed",
11188
+ removeAdditional: false,
11189
+ useDefaults: false,
11190
+ coerceTypes: false,
11191
+ ...cfg
11192
+ }),
11193
+ stopLoss: (cfg) => ({ ...cfg }),
11194
+ workflowState: (cfg) => ({
11195
+ allowSelfTransition: false,
11196
+ ...cfg
11197
+ })
11198
+ };
11199
+
11200
+ // src/rules/molecules/index.ts
11201
+ var molecule = {
11202
+ tokenGate: (cfg) => ({
11203
+ overallOperator: "AND",
11204
+ allowDelegation: false,
11205
+ ...cfg,
11206
+ fungibles: cfg.fungibles ? { operator: "AND", ...cfg.fungibles } : void 0,
11207
+ nonFungibles: cfg.nonFungibles ? { operator: "OR", ...cfg.nonFungibles } : void 0
11208
+ }),
11209
+ airdrop: (cfg) => ({
11210
+ decimals: 0,
11211
+ claimMethod: "manual",
11212
+ ...cfg
11213
+ }),
11214
+ vesting: (cfg) => ({
11215
+ decimals: 0,
11216
+ cliffDurationMs: 0,
11217
+ initialUnlockPercent: 0,
11218
+ revocable: false,
11219
+ returnToTreasury: true,
11220
+ ...cfg
11221
+ }),
11222
+ governance: (cfg) => ({
11223
+ decimals: 0,
11224
+ votingPowerMethod: "token_balance",
11225
+ quorumPercent: 10,
11226
+ approvalThresholdPercent: 50,
11227
+ timeLockMs: 0,
11228
+ allowDelegation: true,
11229
+ allowVoteChange: false,
11230
+ maxActiveProposalsPerAccount: 3,
11231
+ proposalCooldownMs: 0,
11232
+ ...cfg
11233
+ }),
11234
+ streaming: (cfg) => ({
11235
+ decimals: 0,
11236
+ type: "linear",
11237
+ cancellable: true,
11238
+ pausable: false,
11239
+ cancelController: "sender",
11240
+ cliffDurationMs: 0,
11241
+ autoTopUp: false,
11242
+ ...cfg
11243
+ }),
11244
+ swap: (cfg = {}) => ({
11245
+ type: "atomic",
11246
+ requireAtomicity: true,
11247
+ ...cfg
11248
+ })
11249
+ };
11250
+
11251
+ // src/rules/builders/base-builder.ts
11252
+ var RuleBuildError = class extends Error {
11253
+ errors;
11254
+ constructor(message, errors) {
11255
+ super(message);
11256
+ this.name = "RuleBuildError";
11257
+ this.errors = errors;
11258
+ }
11259
+ };
11260
+ var BaseRuleBuilder = class {
11261
+ state;
11262
+ constructor(type, initial) {
11263
+ this.state = initial ?? {};
11264
+ this.state.version = "3.0";
11265
+ this.state.type = type;
11266
+ this.state.created = (/* @__PURE__ */ new Date()).toISOString();
11267
+ if (!this.state.defaultSecurity) this.state.defaultSecurity = "full";
11268
+ if (!this.state.defaultController) this.state.defaultController = "owner";
11269
+ }
11270
+ withSecurity(mode) {
11271
+ this.state.defaultSecurity = mode;
11272
+ return this;
11273
+ }
11274
+ withController(controller) {
11275
+ this.state.defaultController = controller;
11276
+ return this;
11277
+ }
11278
+ withGovernance(governance) {
11279
+ this.state.governance = governance;
11280
+ return this;
11281
+ }
11282
+ withTokenGates(tokenGates) {
11283
+ this.state.tokenGates = tokenGates;
11284
+ return this;
11285
+ }
11286
+ withTimeRange(timeRange) {
11287
+ this.state.timeRange = timeRange;
11288
+ return this;
11289
+ }
11290
+ withMetadata(metadata) {
11291
+ this.state.metadata = metadata;
11292
+ return this;
11293
+ }
11294
+ withModules(modules) {
11295
+ this.state.modules = modules;
11296
+ return this;
11297
+ }
11298
+ /** Add a single module entry on top of any previously set modules. */
11299
+ addModule(module) {
11300
+ this.state.modules = [...this.state.modules ?? [], module];
11301
+ return this;
11302
+ }
11303
+ withInvariants(invariants) {
11304
+ this.state.invariants = invariants;
11305
+ return this;
11306
+ }
11307
+ // ────────────────────────────────────────────────────────────────────────
11308
+ // PR F — first-class atom/molecule shortcuts (all arms)
11309
+ //
11310
+ // Each shortcut wraps the atom/molecule config as a canonical `ModuleEntry`
11311
+ // (lowercase-hyphenated type + `1.0.0` semver) and appends it to `modules`.
11312
+ // The cluster's organism registry maps `type → schema` at runtime; unknown
11313
+ // types fail-closed. These methods exist so smart-app authors can compose
11314
+ // atoms/molecules without hand-rolling `ModuleEntry` envelopes.
11315
+ // ────────────────────────────────────────────────────────────────────────
11316
+ /** Attach a per-tx + period + lifetime LimitsAtom config as a module. */
11317
+ withLimits(limits) {
11318
+ return this.addModule({
11319
+ type: "limits",
11320
+ version: "1.0.0",
11321
+ config: atom.limits(limits)
11322
+ });
11323
+ }
11324
+ /** Attach an operation-per-window RateLimiterAtom config as a module. */
11325
+ withRateLimiter(rateLimiter) {
11326
+ return this.addModule({
11327
+ type: "rate-limiter",
11328
+ version: "1.0.0",
11329
+ config: atom.rateLimiter(rateLimiter)
11330
+ });
11331
+ }
11332
+ /** Attach a pinned-state SnapshotAtom config as a module. */
11333
+ withSnapshot(snapshot) {
11334
+ return this.addModule({
11335
+ type: "snapshot",
11336
+ version: "1.0.0",
11337
+ config: atom.snapshot(snapshot)
11338
+ });
11339
+ }
11340
+ /** Attach a swap-molecule config as a module (atomic / pool / order / OTC). */
11341
+ withSwap(swap = {}) {
11342
+ return this.addModule({
11343
+ type: "swap",
11344
+ version: "1.0.0",
11345
+ config: molecule.swap(swap)
11346
+ });
11347
+ }
11348
+ /** Attach an airdrop-molecule config as a module. */
11349
+ withAirdrop(airdrop) {
11350
+ return this.addModule({
11351
+ type: "airdrop",
11352
+ version: "1.0.0",
11353
+ config: molecule.airdrop(airdrop)
11354
+ });
11355
+ }
11356
+ /** Attach a vesting-molecule config as a module (beneficiary-scoped lockup). */
11357
+ withVesting(vesting) {
11358
+ return this.addModule({
11359
+ type: "vesting",
11360
+ version: "1.0.0",
11361
+ config: molecule.vesting(vesting)
11362
+ });
11363
+ }
11364
+ /** Attach a streaming-molecule config as a module (continuous payment). */
11365
+ withStreaming(streaming) {
11366
+ return this.addModule({
11367
+ type: "streaming",
11368
+ version: "1.0.0",
11369
+ config: molecule.streaming(streaming)
11370
+ });
11371
+ }
11372
+ /**
11373
+ * Attach a rich `GovernanceMoleculeConfig` as a module. Distinct from
11374
+ * `withGovernance(GovernanceConfig)` — that one sets the canonical top-level
11375
+ * governance field (DAO token + quorum/timelock/threshold). The molecule
11376
+ * variant exposes the full proposal-lifecycle config (delegation, veto
11377
+ * council, voting eligibility, etc.).
11378
+ */
11379
+ withGovernanceModule(governance) {
11380
+ return this.addModule({
11381
+ type: "governance",
11382
+ version: "1.0.0",
11383
+ config: molecule.governance(governance)
11384
+ });
11385
+ }
11386
+ /**
11387
+ * Attach a CooldownAtom config as a module. Token/account/topic arms only —
11388
+ * the agent arm carries `cooldown` as a first-class canonical field.
11389
+ */
11390
+ withCooldown(cooldown) {
11391
+ return this.addModule({
11392
+ type: "cooldown",
11393
+ version: "1.0.0",
11394
+ config: atom.cooldown(cooldown)
11395
+ });
11396
+ }
11397
+ /**
11398
+ * Attach an ApprovalThresholdAtom config as a module. Token/account/topic
11399
+ * arms only — the agent arm carries `approvalThreshold` as a first-class
11400
+ * canonical field.
11401
+ */
11402
+ withApprovalThreshold(threshold) {
11403
+ return this.addModule({
11404
+ type: "approval-threshold",
11405
+ version: "1.0.0",
11406
+ config: atom.approvalThreshold(threshold)
11407
+ });
11408
+ }
11409
+ /** Validate + return the typed, schema-conformant rule. Throws on invalid. */
11410
+ build() {
11411
+ const result = this.schema().safeParse(this.state);
11412
+ if (!result.success) {
11413
+ const errors = result.error.issues.map((issue) => {
11414
+ const path = issue.path.join(".");
11415
+ return path ? `${path}: ${issue.message}` : issue.message;
11416
+ });
11417
+ throw new RuleBuildError(`Invalid ${this.state.type ?? "rule"}: ${errors.join("; ")}`, errors);
11418
+ }
11419
+ return result.data;
11420
+ }
11421
+ /** Return the in-progress partial — handy for templates that finish the rule later. */
11422
+ partial() {
11423
+ return this.state;
11424
+ }
11425
+ };
11426
+ var SmartNodeSecuritySchema = zod.z.enum(["partial", "full"]);
11427
+ var OperationControllerSchema = zod.z.enum(["owner", "dao"]);
11428
+ var OperationLimitsSchema = zod.z.object({
11429
+ maxPerTransaction: zod.z.string().optional(),
11430
+ dailyLimit: zod.z.string().optional(),
11431
+ weeklyLimit: zod.z.string().optional(),
11432
+ monthlyLimit: zod.z.string().optional(),
11433
+ totalLimit: zod.z.string().optional(),
11434
+ cooldownSeconds: zod.z.number().int().min(0).optional(),
11435
+ minPerTransaction: zod.z.string().optional()
11436
+ }).strict();
11437
+ var BaseOperationConfigSchema = zod.z.object({
11438
+ enabled: zod.z.boolean(),
11439
+ controller: OperationControllerSchema.optional(),
11440
+ requiresApproval: zod.z.boolean().optional(),
11441
+ limits: OperationLimitsSchema.optional()
11442
+ }).strict();
11443
+ var MintOperationConfigSchema = BaseOperationConfigSchema.extend({}).strict();
11444
+ var UpdateOperationConfigSchema = BaseOperationConfigSchema.extend({
11445
+ allowedFields: zod.z.array(zod.z.string()).optional()
11446
+ }).strict();
11447
+ var PayloadSchemaRefSchema = zod.z.discriminatedUnion("kind", [
11448
+ zod.z.object({ kind: zod.z.literal("builtin"), id: zod.z.string().min(1) }).strict(),
11449
+ zod.z.object({ kind: zod.z.literal("jsonschema"), schema: zod.z.record(zod.z.unknown()) }).strict()
11450
+ ]);
11451
+ var SubmitOperationConfigSchema = BaseOperationConfigSchema.extend({
11452
+ maxMessageSize: zod.z.number().int().min(0).optional(),
11453
+ rateLimit: zod.z.object({
11454
+ maxMessages: zod.z.number().int().min(1),
11455
+ periodSeconds: zod.z.number().int().min(1)
11456
+ }).strict().optional(),
11457
+ payloadSchema: PayloadSchemaRefSchema.optional()
11458
+ }).strict();
11459
+ var BurnOperationConfigSchema = BaseOperationConfigSchema.extend({
11460
+ allowHolderBurn: zod.z.boolean().optional()
11461
+ }).strict();
11462
+ var TransferOperationConfigSchema = BaseOperationConfigSchema.extend({
11463
+ blacklistEnabled: zod.z.boolean().optional(),
11464
+ requiresKyc: zod.z.boolean().optional(),
11465
+ whitelist: zod.z.array(zod.z.string()).optional(),
11466
+ blacklist: zod.z.array(zod.z.string()).optional()
11467
+ }).strict();
11468
+ var FreezeOperationConfigSchema = BaseOperationConfigSchema.extend({
11469
+ requiresMultisig: zod.z.boolean().optional()
11470
+ }).strict();
11471
+ var PauseOperationConfigSchema = BaseOperationConfigSchema.extend({}).strict();
11472
+ var TokenOperationsConfigSchema = zod.z.object({
11473
+ mint: MintOperationConfigSchema.optional(),
11474
+ burn: BurnOperationConfigSchema.optional(),
11475
+ transfer: TransferOperationConfigSchema.optional(),
11476
+ freeze: FreezeOperationConfigSchema.optional(),
11477
+ pause: PauseOperationConfigSchema.optional(),
11478
+ wipe: BaseOperationConfigSchema.optional(),
11479
+ update: UpdateOperationConfigSchema.optional(),
11480
+ associate: BaseOperationConfigSchema.optional(),
11481
+ dissociate: BaseOperationConfigSchema.optional(),
11482
+ grantKyc: BaseOperationConfigSchema.optional(),
11483
+ revokeKyc: BaseOperationConfigSchema.optional()
11484
+ }).strict();
11485
+ var AccountOperationsConfigSchema = zod.z.object({
11486
+ transfer: TransferOperationConfigSchema.optional(),
11487
+ update: UpdateOperationConfigSchema.optional(),
11488
+ delete: BaseOperationConfigSchema.optional(),
11489
+ approveAllowance: BaseOperationConfigSchema.optional(),
11490
+ deleteAllowance: BaseOperationConfigSchema.optional(),
11491
+ stake: BaseOperationConfigSchema.optional(),
11492
+ unstake: BaseOperationConfigSchema.optional()
11493
+ }).strict();
11494
+ var TopicOperationsConfigSchema = zod.z.object({
11495
+ submit: SubmitOperationConfigSchema.optional(),
11496
+ update: UpdateOperationConfigSchema.optional(),
11497
+ delete: BaseOperationConfigSchema.optional()
11498
+ }).strict();
11499
+ var KeyConditionSchema = zod.z.object({
11500
+ enabled: zod.z.boolean().optional(),
11501
+ security: SmartNodeSecuritySchema.optional(),
11502
+ controller: OperationControllerSchema.optional(),
11503
+ requiresApproval: zod.z.boolean().optional(),
11504
+ threshold: zod.z.number().int().min(1).optional()
11505
+ }).strict();
11506
+ var TokenKeyConditionsSchema = zod.z.object({
11507
+ admin: KeyConditionSchema.optional(),
11508
+ supply: KeyConditionSchema.optional(),
11509
+ freeze: KeyConditionSchema.optional(),
11510
+ pause: KeyConditionSchema.optional(),
11511
+ wipe: KeyConditionSchema.optional(),
11512
+ kyc: KeyConditionSchema.optional(),
11513
+ feeSchedule: KeyConditionSchema.optional()
11514
+ }).strict();
11515
+ var AccountKeyConditionsSchema = zod.z.object({
11516
+ admin: KeyConditionSchema.optional(),
11517
+ signing: KeyConditionSchema.optional()
11518
+ }).strict();
11519
+ var TopicKeyConditionsSchema = zod.z.object({
11520
+ admin: KeyConditionSchema.optional(),
11521
+ submit: KeyConditionSchema.optional()
11522
+ }).strict();
11523
+ var FixedFeeConditionSchema = zod.z.object({
11524
+ enabled: zod.z.boolean(),
11525
+ amount: zod.z.string(),
11526
+ feeTokenId: zod.z.string().optional(),
11527
+ feeCollectorAccountId: zod.z.string(),
11528
+ allCollectorsAreExempt: zod.z.boolean().optional()
11529
+ }).strict();
11530
+ var FractionalFeeConditionSchema = zod.z.object({
11531
+ enabled: zod.z.boolean(),
11532
+ numerator: zod.z.number().int(),
11533
+ denominator: zod.z.number().int().min(1),
11534
+ minimumAmount: zod.z.string().optional(),
11535
+ maximumAmount: zod.z.string().optional(),
11536
+ feeCollectorAccountId: zod.z.string(),
11537
+ netOfTransfers: zod.z.boolean().optional()
11538
+ }).strict();
11539
+ var RoyaltyFeeConditionSchema = zod.z.object({
11540
+ enabled: zod.z.boolean(),
11541
+ numerator: zod.z.number().int(),
11542
+ denominator: zod.z.number().int().min(1),
11543
+ fallbackFee: FixedFeeConditionSchema.optional(),
11544
+ feeCollectorAccountId: zod.z.string()
11545
+ }).strict();
11546
+ var FeeConditionsSchema = zod.z.object({
11547
+ fixed: zod.z.array(FixedFeeConditionSchema).optional(),
11548
+ fractional: zod.z.array(FractionalFeeConditionSchema).optional(),
11549
+ royalty: zod.z.array(RoyaltyFeeConditionSchema).optional()
11550
+ }).strict();
11551
+ var TimeRangeSchema = zod.z.object({
11552
+ start: zod.z.union([zod.z.number(), zod.z.string()]),
11553
+ end: zod.z.union([zod.z.number(), zod.z.string()])
11554
+ }).strict();
11555
+ var FungibleTokenGateSchema = zod.z.object({
11556
+ tokenId: zod.z.string(),
11557
+ minBalance: zod.z.string(),
11558
+ timeRange: TimeRangeSchema.optional()
11559
+ }).strict();
11560
+ var NonFungibleTokenGateSchema = zod.z.object({
11561
+ tokenId: zod.z.string(),
11562
+ serialNumbers: zod.z.array(zod.z.string()).optional(),
11563
+ timeRange: TimeRangeSchema.optional()
11564
+ }).strict();
11565
+ var TokenGateConditionsSchema = zod.z.object({
11566
+ fungibles: zod.z.object({
11567
+ tokens: zod.z.array(FungibleTokenGateSchema)
11568
+ }),
11569
+ nonFungibles: zod.z.object({
11570
+ tokens: zod.z.array(NonFungibleTokenGateSchema)
11571
+ }),
11572
+ timeRange: TimeRangeSchema.nullable()
11573
+ }).strict();
11574
+ var GovernanceConfigSchema = zod.z.object({
11575
+ daoTokenId: zod.z.string().optional(),
11576
+ proposalThreshold: zod.z.string().optional(),
11577
+ votingThreshold: zod.z.string().optional(),
11578
+ votingPeriodSeconds: zod.z.number().int().min(0).optional(),
11579
+ timelockSeconds: zod.z.number().int().min(0).optional(),
11580
+ quorumPercentage: zod.z.number().min(0).max(100).optional(),
11581
+ /** Pluggable wisdom-weight function (SDK-GOV-1). Registered server-side under `registryKey`. */
11582
+ wisdomWeightFn: zod.z.object({
11583
+ registryKey: zod.z.string().min(1)
11584
+ }).strict().optional(),
11585
+ /** Multi-hop liquid delegation (SDK-GOV-1 / whitepaper §A.7). */
11586
+ delegation: zod.z.object({
11587
+ maxHops: zod.z.number().int().min(1).max(10),
11588
+ decayPerHop: zod.z.number().min(0).max(1),
11589
+ concentrationAlert: zod.z.number().min(0).max(1).optional()
11590
+ }).strict().optional()
11591
+ }).strict();
11592
+ var ValidatorMetadataSchema = zod.z.object({
11593
+ version: zod.z.string(),
11594
+ previousVersion: zod.z.string().optional(),
11595
+ deprecatedAt: zod.z.string().optional(),
11596
+ expiresAt: zod.z.string().optional(),
11597
+ description: zod.z.string().max(500).optional(),
11598
+ author: zod.z.string().optional(),
11599
+ tags: zod.z.array(zod.z.string()).optional(),
11600
+ documentationUrl: zod.z.string().url().optional()
11601
+ }).strict();
11602
+ var RuleInvariantsSchema = zod.z.object({
11603
+ maxSupply: zod.z.string().optional(),
11604
+ minBalance: zod.z.string().optional(),
11605
+ minQuorumPercentage: zod.z.number().min(0).max(100).optional(),
11606
+ minTimelockSeconds: zod.z.number().int().min(0).optional(),
11607
+ immutableFields: zod.z.array(zod.z.string())
11608
+ }).strict();
11609
+ var SoulboundAllowedActionSchema = zod.z.enum(["burn", "wipe", "mint"]);
11610
+ var SoulboundNftConfigSchema = zod.z.object({
11611
+ enforced: zod.z.boolean(),
11612
+ allowedActions: zod.z.array(SoulboundAllowedActionSchema).optional()
11613
+ }).strict();
11614
+ var ModuleEntrySchema = zod.z.object({
11615
+ type: zod.z.string().min(1).max(64).regex(/^[a-z][a-z0-9-]*$/, "Module type must be lowercase alphanumeric with hyphens"),
11616
+ version: zod.z.string().min(1).max(20).regex(/^\d+\.\d+\.\d+$/, "Version must be semver (e.g. 1.0.0)"),
11617
+ config: zod.z.record(zod.z.unknown())
11618
+ });
11619
+ var TokenValidatorRulesSchema = zod.z.object({
11620
+ version: zod.z.literal("3.0"),
11621
+ type: zod.z.literal("token"),
11622
+ created: zod.z.string(),
11623
+ smartNodeSecurity: SmartNodeSecuritySchema.optional(),
11624
+ defaultSecurity: SmartNodeSecuritySchema.optional(),
11625
+ defaultController: OperationControllerSchema.optional(),
11626
+ operations: TokenOperationsConfigSchema,
11627
+ keys: TokenKeyConditionsSchema.optional(),
11628
+ fees: FeeConditionsSchema.optional(),
11629
+ tokenGates: TokenGateConditionsSchema.optional(),
11630
+ timeRange: TimeRangeSchema.nullable().optional(),
11631
+ governance: GovernanceConfigSchema.optional(),
11632
+ metadata: ValidatorMetadataSchema.optional(),
11633
+ modules: zod.z.array(ModuleEntrySchema).max(10).optional(),
11634
+ soulbound: SoulboundNftConfigSchema.optional(),
11635
+ invariants: RuleInvariantsSchema.optional()
11636
+ }).strict().refine((data) => data.smartNodeSecurity || data.defaultSecurity, {
11637
+ message: "Either smartNodeSecurity or defaultSecurity must be provided"
11638
+ });
11639
+ var AccountValidatorRulesSchema = zod.z.object({
11640
+ version: zod.z.literal("3.0"),
11641
+ type: zod.z.literal("account"),
11642
+ created: zod.z.string(),
11643
+ smartNodeSecurity: SmartNodeSecuritySchema.optional(),
11644
+ defaultSecurity: SmartNodeSecuritySchema.optional(),
11645
+ defaultController: OperationControllerSchema.optional(),
11646
+ operations: AccountOperationsConfigSchema,
11647
+ keys: AccountKeyConditionsSchema.optional(),
11648
+ tokenGates: TokenGateConditionsSchema.optional(),
11649
+ timeRange: TimeRangeSchema.nullable().optional(),
11650
+ governance: GovernanceConfigSchema.optional(),
11651
+ metadata: ValidatorMetadataSchema.optional(),
11652
+ modules: zod.z.array(ModuleEntrySchema).max(10).optional(),
11653
+ invariants: RuleInvariantsSchema.optional()
11654
+ }).strict().refine((data) => data.smartNodeSecurity || data.defaultSecurity, {
11655
+ message: "Either smartNodeSecurity or defaultSecurity must be provided"
11656
+ });
11657
+ var TopicValidatorRulesSchema = zod.z.object({
11658
+ version: zod.z.literal("3.0"),
11659
+ type: zod.z.literal("topic"),
11660
+ created: zod.z.string(),
11661
+ smartNodeSecurity: SmartNodeSecuritySchema.optional(),
11662
+ defaultSecurity: SmartNodeSecuritySchema.optional(),
11663
+ defaultController: OperationControllerSchema.optional(),
11664
+ operations: TopicOperationsConfigSchema,
11665
+ keys: TopicKeyConditionsSchema.optional(),
11666
+ tokenGates: TokenGateConditionsSchema.optional(),
11667
+ timeRange: TimeRangeSchema.nullable().optional(),
11668
+ governance: GovernanceConfigSchema.optional(),
11669
+ metadata: ValidatorMetadataSchema.optional(),
11670
+ modules: zod.z.array(ModuleEntrySchema).max(10).optional(),
11671
+ invariants: RuleInvariantsSchema.optional()
11672
+ }).strict().refine((data) => data.smartNodeSecurity || data.defaultSecurity, {
11673
+ message: "Either smartNodeSecurity or defaultSecurity must be provided"
11674
+ });
11675
+ var AgentTypeSchema = zod.z.enum(["trading", "monitoring", "analytics", "custom"]);
11676
+ var AgentPermissionScopeSchema = zod.z.enum(["read", "execute", "modify", "admin"]);
11677
+ var AgentControllerTypeSchema = zod.z.enum(["owner", "dao", "multisig", "automated"]);
11678
+ var AgentAccessControlModeSchema = zod.z.enum([
11679
+ "whitelist",
11680
+ "blacklist",
11681
+ "public",
11682
+ "token_gated"
11683
+ ]);
11684
+ var AgentPermissionEntrySchema = zod.z.object({
11685
+ accountId: zod.z.string(),
11686
+ scope: AgentPermissionScopeSchema.optional(),
11687
+ expiresAt: zod.z.union([zod.z.string(), zod.z.date()]).optional(),
11688
+ label: zod.z.string().optional(),
11689
+ metadata: zod.z.record(zod.z.unknown()).optional()
11690
+ }).strict();
11691
+ var AgentPermissionsSchema = zod.z.object({
11692
+ mode: AgentAccessControlModeSchema.optional(),
11693
+ entries: zod.z.array(AgentPermissionEntrySchema),
11694
+ controller: AgentControllerTypeSchema.optional(),
11695
+ allowSelfAdd: zod.z.boolean().optional(),
11696
+ maxEntries: zod.z.number().int().min(0).optional(),
11697
+ requiredScope: AgentPermissionScopeSchema.optional(),
11698
+ allowWildcards: zod.z.boolean().optional()
11699
+ }).strict();
11700
+ var AgentTradeLimitsSchema = zod.z.object({
11701
+ maxPerTrade: zod.z.string(),
11702
+ dailyLimit: zod.z.string(),
11703
+ periodMs: zod.z.number().int().min(0).optional(),
11704
+ decimals: zod.z.number().int().min(0).optional()
11705
+ }).strict();
11706
+ var AgentTokenPairSchema = zod.z.object({
11707
+ baseToken: zod.z.string(),
11708
+ quoteToken: zod.z.string(),
11709
+ chain: zod.z.string()
11710
+ }).strict();
11711
+ var AgentApprovedPairsSchema = zod.z.object({
11712
+ pairs: zod.z.array(AgentTokenPairSchema),
11713
+ strictMode: zod.z.boolean().optional()
11714
+ }).strict();
11715
+ var AgentCooldownSchema = zod.z.object({
11716
+ cooldownMs: zod.z.number().int().min(0),
11717
+ perAction: zod.z.record(zod.z.string(), zod.z.number().int().min(0)).optional()
11718
+ }).strict();
11719
+ var AgentApprovalThresholdSchema = zod.z.object({
11720
+ threshold: zod.z.string(),
11721
+ currency: zod.z.string().optional(),
11722
+ decimals: zod.z.number().int().min(0).optional(),
11723
+ controller: OperationControllerSchema.optional()
11724
+ }).strict();
11725
+ var AgentOperationalWindowSchema = zod.z.object({
11726
+ from: zod.z.union([zod.z.number(), zod.z.string()]),
11727
+ to: zod.z.union([zod.z.number(), zod.z.string()]),
11728
+ timezone: zod.z.string().optional(),
11729
+ inclusive: zod.z.boolean().optional()
11730
+ }).strict();
11731
+ var AgentAllocationLimitsSchema = zod.z.object({
11732
+ min: zod.z.union([zod.z.number(), zod.z.string()]).optional(),
11733
+ max: zod.z.union([zod.z.number(), zod.z.string()]).optional(),
11734
+ tokenId: zod.z.string().optional(),
11735
+ decimals: zod.z.number().int().min(0).optional(),
11736
+ inclusive: zod.z.boolean().optional()
11737
+ }).strict();
11738
+ var AgentValidatorRulesSchema = zod.z.object({
11739
+ version: zod.z.literal("3.0"),
11740
+ type: zod.z.literal("agent"),
11741
+ created: zod.z.string(),
11742
+ smartNodeSecurity: SmartNodeSecuritySchema.optional(),
11743
+ defaultSecurity: SmartNodeSecuritySchema.optional(),
11744
+ defaultController: OperationControllerSchema.optional(),
11745
+ name: zod.z.string().optional(),
11746
+ agentType: AgentTypeSchema.optional(),
11747
+ permissions: AgentPermissionsSchema.optional(),
11748
+ tradeLimits: AgentTradeLimitsSchema.optional(),
11749
+ approvedPairs: AgentApprovedPairsSchema.optional(),
11750
+ cooldown: AgentCooldownSchema.optional(),
11751
+ approvalThreshold: AgentApprovalThresholdSchema.optional(),
11752
+ operationalWindow: AgentOperationalWindowSchema.optional(),
11753
+ allocationLimits: AgentAllocationLimitsSchema.optional(),
11754
+ tokenGates: TokenGateConditionsSchema.optional(),
11755
+ timeRange: TimeRangeSchema.nullable().optional(),
11756
+ governance: GovernanceConfigSchema.optional(),
11757
+ metadata: ValidatorMetadataSchema.optional(),
11758
+ modules: zod.z.array(ModuleEntrySchema).max(10).optional(),
11759
+ invariants: RuleInvariantsSchema.optional()
11760
+ }).strict().refine((data) => data.smartNodeSecurity || data.defaultSecurity, {
11761
+ message: "Either smartNodeSecurity or defaultSecurity must be provided"
11762
+ });
11763
+ var ValidatorRulesSchema = zod.z.union([
11764
+ TokenValidatorRulesSchema,
11765
+ AccountValidatorRulesSchema,
11766
+ TopicValidatorRulesSchema,
11767
+ AgentValidatorRulesSchema
11768
+ ]);
11769
+
11770
+ // src/rules/builders/token-rules-builder.ts
11771
+ var TokenRulesBuilder = class extends BaseRuleBuilder {
11772
+ constructor() {
11773
+ super("token");
11774
+ }
11775
+ schema() {
11776
+ return TokenValidatorRulesSchema;
11777
+ }
11778
+ /** Set the full operations config (required by the canonical schema). */
11779
+ withOperations(operations) {
11780
+ this.state.operations = operations;
11781
+ return this;
11782
+ }
11783
+ /** Patch-style operations merge: pass only the ops you want to set/change. */
11784
+ patchOperations(partial) {
11785
+ this.state.operations = { ...this.state.operations ?? {}, ...partial };
11786
+ return this;
11787
+ }
11788
+ withKeys(keys) {
11789
+ this.state.keys = keys;
11790
+ return this;
11791
+ }
11792
+ withFees(fees) {
11793
+ this.state.fees = fees;
11794
+ return this;
11795
+ }
11796
+ withSoulbound(soulbound) {
11797
+ this.state.soulbound = soulbound;
11798
+ return this;
11799
+ }
11800
+ };
11801
+ function forToken() {
11802
+ return new TokenRulesBuilder();
11803
+ }
11804
+
11805
+ // src/rules/builders/account-rules-builder.ts
11806
+ var AccountRulesBuilder = class extends BaseRuleBuilder {
11807
+ constructor() {
11808
+ super("account");
11809
+ }
11810
+ schema() {
11811
+ return AccountValidatorRulesSchema;
11812
+ }
11813
+ withOperations(operations) {
11814
+ this.state.operations = operations;
11815
+ return this;
11816
+ }
11817
+ patchOperations(partial) {
11818
+ this.state.operations = { ...this.state.operations ?? {}, ...partial };
11819
+ return this;
11820
+ }
11821
+ withKeys(keys) {
11822
+ this.state.keys = keys;
11823
+ return this;
11824
+ }
11825
+ };
11826
+ function forAccount() {
11827
+ return new AccountRulesBuilder();
11828
+ }
11829
+
11830
+ // src/rules/builders/topic-rules-builder.ts
11831
+ var TopicRulesBuilder = class extends BaseRuleBuilder {
11832
+ constructor() {
11833
+ super("topic");
11834
+ }
11835
+ schema() {
11836
+ return TopicValidatorRulesSchema;
11837
+ }
11838
+ withOperations(operations) {
11839
+ this.state.operations = operations;
11840
+ return this;
11841
+ }
11842
+ patchOperations(partial) {
11843
+ this.state.operations = { ...this.state.operations ?? {}, ...partial };
11844
+ return this;
11845
+ }
11846
+ withKeys(keys) {
11847
+ this.state.keys = keys;
11848
+ return this;
11849
+ }
11850
+ /**
11851
+ * Convenience: set the submit operation in one call.
11852
+ * Common usage on topics that gate message shape via JSON-Schema payload.
11853
+ */
11854
+ withSubmit(submit) {
11855
+ this.state.operations = {
11856
+ ...this.state.operations ?? {},
11857
+ submit
11858
+ };
11859
+ return this;
11860
+ }
11861
+ /**
11862
+ * Convenience: attach a JSON-Schema payload validation to the submit op.
11863
+ * Equivalent to `withSubmit({ enabled: true, payloadSchema: ref })`.
11864
+ */
11865
+ withPayloadSchema(payloadSchema) {
11866
+ return this.withSubmit({
11867
+ ...this.state.operations?.submit ?? { enabled: true },
11868
+ payloadSchema
11869
+ });
11870
+ }
11871
+ };
11872
+ function forTopic() {
11873
+ return new TopicRulesBuilder();
11874
+ }
11875
+
11876
+ // src/rules/builders/agent-rules-builder.ts
11877
+ var AgentRulesBuilder = class extends BaseRuleBuilder {
11878
+ constructor() {
11879
+ super("agent");
11880
+ }
11881
+ schema() {
11882
+ return AgentValidatorRulesSchema;
11883
+ }
11884
+ withName(name) {
11885
+ this.state.name = name;
11886
+ return this;
11887
+ }
11888
+ withAgentType(agentType) {
11889
+ this.state.agentType = agentType;
11890
+ return this;
11891
+ }
11892
+ withPermissions(permissions) {
11893
+ this.state.permissions = permissions;
11894
+ return this;
11895
+ }
11896
+ withTradeLimits(tradeLimits) {
11897
+ this.state.tradeLimits = tradeLimits;
11898
+ return this;
11899
+ }
11900
+ withApprovedPairs(approvedPairs) {
11901
+ this.state.approvedPairs = approvedPairs;
11902
+ return this;
11903
+ }
11904
+ withCooldown(cooldown) {
11905
+ this.state.cooldown = cooldown;
11906
+ return this;
11907
+ }
11908
+ withApprovalThreshold(approvalThreshold) {
11909
+ this.state.approvalThreshold = approvalThreshold;
11910
+ return this;
11911
+ }
11912
+ withOperationalWindow(window) {
11913
+ this.state.operationalWindow = window;
11914
+ return this;
11915
+ }
11916
+ withAllocationLimits(allocationLimits) {
11917
+ this.state.allocationLimits = allocationLimits;
11918
+ return this;
11919
+ }
11920
+ // ────────────────────────────────────────────────────────────────────────
11921
+ // PR F — Phase-6.6 AI atom shortcuts
11922
+ //
11923
+ // `MaxTradesPerWindow` and `RequireStructuredOutput` are optional atoms
11924
+ // (NOT registered as builtin organism modules) wired in the AI-inference
11925
+ // path of the smart-app's BaaS function. Attached here as canonical
11926
+ // `ModuleEntry`s so they ship inside the published rule and the cluster's
11927
+ // canonical evaluator can dispatch them.
11928
+ //
11929
+ // Atom sources:
11930
+ // libs/rules-engine/src/atoms/max-trades-per-window.atom.ts
11931
+ // libs/rules-engine/src/atoms/require-structured-output.atom.ts
11932
+ // ────────────────────────────────────────────────────────────────────────
11933
+ /**
11934
+ * Cap the agent at `maxTradesPerWindow` trades within a rolling `windowMs`
11935
+ * window. Count-based — orthogonal to `withTradeLimits` which is amount-based.
11936
+ */
11937
+ withMaxTradesPerWindow(config) {
11938
+ return this.addModule({
11939
+ type: "max-trades-per-window",
11940
+ version: "1.0.0",
11941
+ config: { ...config }
11942
+ });
11943
+ }
11944
+ /**
11945
+ * Pre-filter LLM responses against a JSON Schema (compiled by the cluster's
11946
+ * SchemaResolver via Ajv) before they are submitted to the agent's trade
11947
+ * endpoint. `outputName` is included in failure reasons for log triage.
11948
+ */
11949
+ withRequireStructuredOutput(config = {}) {
11950
+ return this.addModule({
11951
+ type: "require-structured-output",
11952
+ version: "1.0.0",
11953
+ config: { outputName: config.outputName ?? "LLM output" }
11954
+ });
11955
+ }
11956
+ };
11957
+ function forAgent() {
11958
+ return new AgentRulesBuilder();
11959
+ }
11960
+
11961
+ // src/rules/validate.ts
11962
+ function formatIssue(issue) {
11963
+ const path = issue.path.join(".");
11964
+ return path ? `${path}: ${issue.message}` : issue.message;
11965
+ }
11966
+ function pickArm(rule) {
11967
+ if (rule && typeof rule === "object" && "type" in rule) {
11968
+ const t = rule.type;
11969
+ if (t === "token") return TokenValidatorRulesSchema;
11970
+ if (t === "account") return AccountValidatorRulesSchema;
11971
+ if (t === "topic") return TopicValidatorRulesSchema;
11972
+ if (t === "agent") return AgentValidatorRulesSchema;
11973
+ }
11974
+ return ValidatorRulesSchema;
11975
+ }
11976
+ function validate(rule) {
11977
+ const result = pickArm(rule).safeParse(rule);
11978
+ if (result.success) {
11979
+ return { valid: true, errors: [] };
11980
+ }
11981
+ return {
11982
+ valid: false,
11983
+ errors: result.error.issues.map(formatIssue)
11984
+ };
11985
+ }
11986
+
11987
+ // src/rules/modules/index.ts
11988
+ function withLaunchpadDefaults(c) {
11989
+ return {
11990
+ launchTokenDecimals: 0,
11991
+ paymentTokenDecimals: 0,
11992
+ refundOnFailure: true,
11993
+ overflowPolicy: "proportional",
11994
+ platformFeePercent: 0,
11995
+ ...c
11996
+ };
11997
+ }
11998
+ function withStakingPoolDefaults(c) {
11999
+ return {
12000
+ stakingTokenDecimals: 0,
12001
+ distributionMethod: "proportional",
12002
+ lockPeriodMs: 0,
12003
+ earlyUnstakePenalty: 0,
12004
+ autoCompound: false,
12005
+ withdrawalCooldownMs: 0,
12006
+ emergencyWithdrawEnabled: true,
12007
+ ...c
12008
+ };
12009
+ }
12010
+ function withDaoDefaults(c) {
12011
+ return { smartNodeSecurity: "partial", ...c };
12012
+ }
12013
+ function withDexDefaults(c) {
12014
+ return {
12015
+ defaultSwapFeePercent: 0.3,
12016
+ multiHopEnabled: true,
12017
+ maxHops: 3,
12018
+ defaultSlippagePercent: 0.5,
12019
+ ...c
12020
+ };
12021
+ }
12022
+ var module_ = {
12023
+ launchpad: (config) => ({
12024
+ type: "launchpad",
12025
+ version: "1.0.0",
12026
+ config: withLaunchpadDefaults(config)
12027
+ }),
12028
+ stakingPool: (config) => ({
12029
+ type: "staking-pool",
12030
+ version: "1.0.0",
12031
+ config: withStakingPoolDefaults(config)
12032
+ }),
12033
+ dao: (config) => ({
12034
+ type: "dao",
12035
+ version: "1.0.0",
12036
+ config: withDaoDefaults(config)
12037
+ }),
12038
+ dex: (config) => ({
12039
+ type: "dex",
12040
+ version: "1.0.0",
12041
+ config: withDexDefaults(config)
12042
+ })
12043
+ // PR F — `agent` retired per Arc 6 Phase 6.5. Use `Rules.forAgent()` instead.
12044
+ };
12045
+
12046
+ // src/rules/templates/index.ts
12047
+ function toEpoch(d) {
12048
+ return typeof d === "number" ? d : d.getTime();
12049
+ }
12050
+ function meta(templateName, description) {
12051
+ return {
12052
+ version: "1.0.0",
12053
+ description: description ?? `${templateName} (Rules.template.${templateName})`,
12054
+ tags: [`template:${templateName}`]
12055
+ };
12056
+ }
12057
+ function fairLaunch(p) {
12058
+ const launchpad = module_.launchpad({
12059
+ name: p.name,
12060
+ launchTokenId: p.launchTokenId,
12061
+ launchTokenDecimals: p.launchTokenDecimals,
12062
+ paymentTokenId: p.paymentTokenId,
12063
+ paymentTokenDecimals: p.paymentTokenDecimals,
12064
+ totalTokensForSale: p.totalTokensForSale,
12065
+ pricePerToken: p.pricePerToken,
12066
+ hardCap: p.hardCap,
12067
+ softCap: p.softCap,
12068
+ publicWindow: atom.timeRange({
12069
+ from: toEpoch(p.publicStart),
12070
+ to: toEpoch(p.publicEnd)
12071
+ }),
12072
+ treasuryAccount: p.treasuryAccount,
12073
+ vestingSchedule: p.vestingSchedule,
12074
+ refundOnFailure: true,
12075
+ overflowPolicy: "proportional",
12076
+ description: `Fair-launch IDO for ${p.symbol}`
12077
+ });
12078
+ return forToken().withOperations({
12079
+ mint: { enabled: true, controller: "owner" },
12080
+ transfer: { enabled: true, controller: "owner" }
12081
+ }).addModule(launchpad).withMetadata(meta("fairLaunch", p.description)).build();
12082
+ }
12083
+ function tieredIDO(p) {
12084
+ const lowestTierBalance = p.tiers.reduce((acc, t) => {
12085
+ if (acc === "") return t.requiredBalance;
12086
+ const len = Math.max(acc.length, t.requiredBalance.length);
12087
+ const a = acc.padStart(len, "0");
12088
+ const b = t.requiredBalance.padStart(len, "0");
12089
+ return a < b ? acc : t.requiredBalance;
12090
+ }, "");
12091
+ const eligibility = molecule.tokenGate({
12092
+ fungibles: {
12093
+ tokens: [
12094
+ {
12095
+ tokenId: p.governanceTokenId,
12096
+ minBalance: lowestTierBalance || "0",
12097
+ checkBalance: true
12098
+ }
12099
+ ],
12100
+ operator: "AND"
12101
+ },
12102
+ overallOperator: "AND"
12103
+ });
12104
+ const launchpad = module_.launchpad({
12105
+ name: p.name,
12106
+ launchTokenId: p.launchTokenId,
12107
+ paymentTokenId: p.paymentTokenId,
12108
+ totalTokensForSale: p.totalTokensForSale,
12109
+ pricePerToken: p.pricePerToken,
12110
+ hardCap: p.hardCap,
12111
+ softCap: p.softCap,
12112
+ registrationWindow: atom.timeRange({
12113
+ from: toEpoch(p.registrationStart),
12114
+ to: toEpoch(p.registrationEnd)
12115
+ }),
12116
+ guaranteedWindow: atom.timeRange({
12117
+ from: toEpoch(p.guaranteedStart),
12118
+ to: toEpoch(p.guaranteedEnd)
12119
+ }),
12120
+ publicWindow: atom.timeRange({
12121
+ from: toEpoch(p.publicStart),
12122
+ to: toEpoch(p.publicEnd)
12123
+ }),
12124
+ eligibility,
12125
+ tiers: p.tiers,
12126
+ treasuryAccount: p.treasuryAccount,
12127
+ refundOnFailure: true,
12128
+ overflowPolicy: "proportional",
12129
+ description: `Tiered IDO for ${p.symbol}`
12130
+ });
12131
+ return forToken().withOperations({
12132
+ mint: { enabled: true, controller: "owner" },
12133
+ transfer: { enabled: true, controller: "owner" }
12134
+ }).addModule(launchpad).withMetadata(meta("tieredIDO", p.description)).build();
12135
+ }
12136
+ function simpleStaking(p) {
12137
+ const startEpoch = toEpoch(p.startAt);
12138
+ const endEpoch = p.endAt !== void 0 ? toEpoch(p.endAt) : void 0;
12139
+ const stakingPool = module_.stakingPool({
12140
+ name: p.name,
12141
+ poolType: "single",
12142
+ stakingTokenId: p.stakingTokenId,
12143
+ rewardTokens: [
12144
+ {
12145
+ tokenId: p.rewardTokenId,
12146
+ rewardRate: p.rewardRate,
12147
+ totalRewards: p.totalRewards
12148
+ }
12149
+ ],
12150
+ distributionMethod: "proportional",
12151
+ startAt: new Date(startEpoch).toISOString(),
12152
+ endAt: endEpoch !== void 0 ? new Date(endEpoch).toISOString() : void 0,
12153
+ lockPeriodMs: p.lockPeriodMs ?? 0,
12154
+ autoCompound: false,
12155
+ emergencyWithdrawEnabled: true,
12156
+ description: `Single-asset staking pool: ${p.name}`
12157
+ });
12158
+ return forToken().withOperations({
12159
+ transfer: { enabled: true, controller: "owner" }
12160
+ }).addModule(stakingPool).withMetadata(meta("simpleStaking", p.description)).build();
12161
+ }
12162
+ function tokenDAO(p) {
12163
+ const quorum = p.quorumPercent ?? 10;
12164
+ const timeLockMs = p.timeLockMs ?? 0;
12165
+ const governance = molecule.governance({
12166
+ governanceTokenId: p.governanceTokenId,
12167
+ quorumPercent: quorum,
12168
+ approvalThresholdPercent: p.approvalThresholdPercent ?? 50,
12169
+ proposalThreshold: p.proposalThreshold,
12170
+ votingPeriodMs: p.votingPeriodMs,
12171
+ timeLockMs
12172
+ });
12173
+ const dao = module_.dao({
12174
+ name: p.name,
12175
+ daoType: "token_governed",
12176
+ smartNodeSecurity: "full",
12177
+ governance,
12178
+ treasury: {
12179
+ accountId: p.treasuryAccountId,
12180
+ controlledTokens: p.controlledTokens
12181
+ },
12182
+ description: `Token-governed DAO: ${p.name}`
12183
+ });
12184
+ return forToken().withController("dao").withOperations({
12185
+ mint: { enabled: true, controller: "dao", requiresApproval: true },
12186
+ burn: { enabled: true, controller: "dao", requiresApproval: true },
12187
+ transfer: { enabled: true, controller: "owner" }
12188
+ }).withGovernance({
12189
+ daoTokenId: p.governanceTokenId,
12190
+ proposalThreshold: p.proposalThreshold,
12191
+ votingPeriodSeconds: Math.floor(p.votingPeriodMs / 1e3),
12192
+ timelockSeconds: Math.floor(timeLockMs / 1e3),
12193
+ quorumPercentage: quorum
12194
+ }).addModule(dao).withInvariants({
12195
+ minQuorumPercentage: quorum,
12196
+ minTimelockSeconds: Math.floor(timeLockMs / 1e3),
12197
+ immutableFields: ["governance", "treasury"]
12198
+ }).withMetadata(meta("tokenDAO", p.description)).build();
12199
+ }
12200
+ function multisigDAO(p) {
12201
+ if (p.threshold < 1 || p.threshold > p.signers.length) {
12202
+ throw new Error(
12203
+ `multisigDAO: threshold ${p.threshold} must be between 1 and signers.length (${p.signers.length})`
12204
+ );
12205
+ }
12206
+ const proposalExpirationMs = p.proposalExpirationMs ?? 7 * 24 * 60 * 60 * 1e3;
12207
+ const governance = molecule.governance({
12208
+ governanceTokenId: "multisig",
12209
+ proposalThreshold: "0",
12210
+ votingPeriodMs: proposalExpirationMs,
12211
+ quorumPercent: 0,
12212
+ approvalThresholdPercent: Math.floor(p.threshold / p.signers.length * 100)
12213
+ });
12214
+ const dao = module_.dao({
12215
+ name: p.name,
12216
+ daoType: "multisig",
12217
+ smartNodeSecurity: "full",
12218
+ governance,
12219
+ treasury: {
12220
+ accountId: p.treasuryAccountId,
12221
+ controlledTokens: p.controlledTokens
12222
+ },
12223
+ multisig: {
12224
+ signers: p.signers,
12225
+ threshold: p.threshold,
12226
+ proposalExpirationMs
12227
+ },
12228
+ description: `Multisig DAO: ${p.name}`
12229
+ });
12230
+ return forToken().withController("owner").withOperations({
12231
+ transfer: { enabled: true, controller: "owner", requiresApproval: true }
12232
+ }).addModule(dao).withMetadata(meta("multisigDAO", p.description)).build();
12233
+ }
12234
+ function simpleAMM(p) {
12235
+ const swapFeePercent = p.swapFeePercent ?? 0.3;
12236
+ const poolId = `${p.tokenA.tokenId}-${p.tokenB.tokenId}`;
12237
+ const dex = module_.dex({
12238
+ name: p.name,
12239
+ dexType: "amm",
12240
+ pools: [
12241
+ {
12242
+ poolId,
12243
+ tokenA: p.tokenA,
12244
+ tokenB: p.tokenB,
12245
+ curveType: "constant_product",
12246
+ swapFeePercent
12247
+ }
12248
+ ],
12249
+ defaultSwapFeePercent: swapFeePercent,
12250
+ multiHopEnabled: false,
12251
+ description: `Single-pool AMM: ${poolId}`
12252
+ });
12253
+ return forToken().withOperations({
12254
+ transfer: { enabled: true, controller: "owner" }
12255
+ }).addModule(dex).withMetadata(meta("simpleAMM", p.description)).build();
12256
+ }
12257
+ function vestingSchedule(p) {
12258
+ const startEpoch = toEpoch(p.startAt);
12259
+ const vestingMolecule = molecule.vesting({
12260
+ tokenId: p.tokenId,
12261
+ totalAmount: p.totalAmount,
12262
+ beneficiary: p.beneficiary,
12263
+ scheduleType: p.scheduleType,
12264
+ startAt: new Date(startEpoch).toISOString(),
12265
+ cliffDurationMs: p.cliffDurationMs ?? 0,
12266
+ vestingDurationMs: p.vestingDurationMs,
12267
+ treasuryAccount: p.treasuryAccount,
12268
+ returnToTreasury: p.treasuryAccount !== void 0
12269
+ });
12270
+ const vestingModule = {
12271
+ type: "vesting",
12272
+ version: "1.0.0",
12273
+ config: vestingMolecule
12274
+ };
12275
+ return forAccount().withOperations({
12276
+ transfer: { enabled: true, controller: "owner" }
12277
+ }).addModule(vestingModule).withMetadata(meta("vestingSchedule", p.description)).build();
12278
+ }
12279
+ function tradingAgent(p) {
12280
+ return forAgent().withName(p.name).withAgentType("trading").withTradeLimits({
12281
+ maxPerTrade: p.maxPerTrade,
12282
+ dailyLimit: p.dailyLimit
12283
+ }).withApprovedPairs({
12284
+ pairs: p.approvedPairs,
12285
+ strictMode: true
12286
+ }).withCooldown({ cooldownMs: p.cooldownMs ?? 0 }).withApprovalThreshold({
12287
+ threshold: p.approvalThreshold ?? "999999999"
12288
+ }).withMetadata(meta("tradingAgent", p.description)).build();
12289
+ }
12290
+ function utilityToken(p = {}) {
12291
+ return forToken().withSecurity("full").withController("owner").withOperations({
12292
+ mint: { enabled: true },
12293
+ burn: { enabled: true, allowHolderBurn: true },
12294
+ transfer: { enabled: true },
12295
+ update: { enabled: true, allowedFields: ["memo", "feeSchedule"] },
12296
+ pause: { enabled: true },
12297
+ freeze: { enabled: true }
12298
+ }).withKeys({
12299
+ admin: { enabled: true },
12300
+ supply: { enabled: true },
12301
+ freeze: { enabled: true },
12302
+ pause: { enabled: true }
12303
+ }).withMetadata(meta("utilityToken", p.description)).build();
12304
+ }
12305
+ function daoGovernedToken(p) {
12306
+ return forToken().withSecurity("partial").withController("dao").withOperations({
12307
+ mint: {
12308
+ enabled: true,
12309
+ controller: "dao",
12310
+ requiresApproval: true,
12311
+ limits: { maxPerTransaction: "1000000", cooldownSeconds: 86400 }
12312
+ },
12313
+ burn: { enabled: true, allowHolderBurn: true },
12314
+ transfer: { enabled: true },
12315
+ update: {
12316
+ enabled: true,
12317
+ controller: "dao",
12318
+ requiresApproval: true,
12319
+ allowedFields: ["memo", "feeSchedule"]
12320
+ },
12321
+ pause: { enabled: true, controller: "dao", requiresApproval: true },
12322
+ freeze: {
12323
+ enabled: true,
12324
+ controller: "dao",
12325
+ requiresApproval: true,
12326
+ requiresMultisig: true
12327
+ }
12328
+ }).withKeys({
12329
+ admin: { enabled: true, security: "full", controller: "dao", requiresApproval: true },
12330
+ supply: { enabled: true, security: "partial", controller: "dao", requiresApproval: true },
12331
+ freeze: { enabled: true, security: "partial", controller: "dao", requiresApproval: true },
12332
+ pause: { enabled: true, security: "full", controller: "dao", requiresApproval: true }
12333
+ }).withGovernance({
12334
+ daoTokenId: p.daoTokenId,
12335
+ quorumPercentage: 15,
12336
+ proposalThreshold: "1000",
12337
+ votingPeriodSeconds: 604800,
12338
+ timelockSeconds: 172800
12339
+ }).withMetadata(meta("daoGovernedToken", p.description)).build();
12340
+ }
12341
+ function soulboundNft(p = {}) {
12342
+ return forToken().withSecurity("partial").withController("dao").withOperations({
12343
+ mint: {
12344
+ enabled: true,
12345
+ controller: "dao",
12346
+ requiresApproval: true,
12347
+ limits: { maxPerTransaction: "1" }
12348
+ },
12349
+ burn: { enabled: false },
12350
+ transfer: { enabled: false },
12351
+ update: { enabled: true, allowedFields: [] },
12352
+ pause: { enabled: false },
12353
+ freeze: { enabled: false }
12354
+ }).withKeys({
12355
+ admin: { enabled: true, security: "full", controller: "dao" },
12356
+ supply: { enabled: true, security: "full", controller: "dao" }
12357
+ }).withSoulbound({ enforced: true, allowedActions: ["burn"] }).withMetadata(meta("soulboundNft", p.description)).build();
12358
+ }
12359
+ function subscriptionNft(p = {}) {
12360
+ return forToken().withSecurity("full").withController("owner").withOperations({
12361
+ mint: { enabled: true, limits: { maxPerTransaction: "1" } },
12362
+ burn: { enabled: true },
12363
+ transfer: { enabled: true },
12364
+ update: { enabled: true, allowedFields: ["memo"] },
12365
+ pause: { enabled: true, controller: "dao", requiresApproval: true },
12366
+ freeze: { enabled: true, controller: "dao", requiresMultisig: true }
12367
+ }).withKeys({
12368
+ admin: { enabled: true },
12369
+ supply: { enabled: true },
12370
+ freeze: { enabled: true, security: "partial", controller: "dao" },
12371
+ pause: { enabled: true, security: "partial", controller: "dao" }
12372
+ }).withMetadata(meta("subscriptionNft", p.description)).build();
12373
+ }
12374
+ function membershipNft(p = {}) {
12375
+ return forToken().withSecurity("full").withController("dao").withOperations({
12376
+ mint: {
12377
+ enabled: true,
12378
+ controller: "dao",
12379
+ requiresApproval: true,
12380
+ limits: { maxPerTransaction: "1" }
12381
+ },
12382
+ burn: { enabled: true, controller: "dao", requiresApproval: true },
12383
+ transfer: { enabled: false },
12384
+ update: { enabled: true, allowedFields: [] },
12385
+ pause: { enabled: false },
12386
+ freeze: { enabled: false }
12387
+ }).withKeys({
12388
+ admin: { enabled: true, security: "full", controller: "dao", requiresApproval: true },
12389
+ supply: { enabled: true, security: "full", controller: "dao", requiresApproval: true }
12390
+ }).withSoulbound({ enforced: true, allowedActions: ["burn"] }).withMetadata(meta("membershipNft", p.description)).build();
12391
+ }
12392
+ function managedAccount(p = {}) {
12393
+ return forAccount().withSecurity("partial").withController("dao").withOperations({
12394
+ transfer: { enabled: true, requiresKyc: true },
12395
+ update: { enabled: true, controller: "dao", allowedFields: ["memo"] },
12396
+ delete: { enabled: true, controller: "dao", requiresApproval: true },
12397
+ approveAllowance: { enabled: true, controller: "dao", requiresApproval: true },
12398
+ deleteAllowance: { enabled: true }
12399
+ }).withKeys({
12400
+ admin: { enabled: true, security: "partial", controller: "dao" },
12401
+ signing: { enabled: true, security: "full", controller: "owner" }
12402
+ }).withMetadata(meta("managedAccount", p.description)).build();
12403
+ }
12404
+ function systemTopic(p = {}) {
12405
+ return forTopic().withSecurity("full").withController("dao").withOperations({
12406
+ submit: {
12407
+ enabled: true,
12408
+ controller: "dao",
12409
+ requiresApproval: true,
12410
+ rateLimit: { maxMessages: 10, periodSeconds: 3600 }
12411
+ },
12412
+ update: { enabled: true, allowedFields: [] },
12413
+ delete: { enabled: false }
12414
+ }).withKeys({
12415
+ admin: { enabled: true, security: "full", controller: "dao", requiresApproval: true },
12416
+ submit: { enabled: true, security: "full", controller: "dao" }
12417
+ }).withMetadata(meta("systemTopic", p.description)).build();
12418
+ }
12419
+ function appTopic(p = {}) {
12420
+ return forTopic().withSecurity("partial").withController("owner").withOperations({
12421
+ submit: { enabled: true, rateLimit: { maxMessages: 100, periodSeconds: 3600 } },
12422
+ update: { enabled: true, allowedFields: ["memo"] },
12423
+ delete: { enabled: true }
12424
+ }).withKeys({
12425
+ admin: { enabled: true },
12426
+ submit: { enabled: true }
12427
+ }).withMetadata(meta("appTopic", p.description)).build();
12428
+ }
12429
+ var template = {
12430
+ fairLaunch,
12431
+ tieredIDO,
12432
+ simpleStaking,
12433
+ tokenDAO,
12434
+ multisigDAO,
12435
+ simpleAMM,
12436
+ vestingSchedule,
12437
+ tradingAgent,
12438
+ // PR F — canonical server-mirror templates
12439
+ utilityToken,
12440
+ daoGovernedToken,
12441
+ soulboundNft,
12442
+ subscriptionNft,
12443
+ membershipNft,
12444
+ managedAccount,
12445
+ systemTopic,
12446
+ appTopic
12447
+ };
12448
+
12449
+ // src/rules/index.ts
12450
+ var Rules = {
12451
+ /** Build a canonical `TokenValidatorRules`. */
12452
+ forToken,
12453
+ /** Build a canonical `AccountValidatorRules`. */
12454
+ forAccount,
12455
+ /** Build a canonical `TopicValidatorRules`. */
12456
+ forTopic,
12457
+ /** Build a canonical `AgentValidatorRules`. */
12458
+ forAgent,
12459
+ /** Local preflight — runs the canonical Zod schema, returns `{valid, errors}`. */
12460
+ validate,
12461
+ /** Atom factories — typed config for primitive rule pieces (`timeRange`, `limits`, …). */
12462
+ atom,
12463
+ /** Molecule factories — typed config for compound rules (`tokenGate`, `governance`, …). */
12464
+ molecule,
12465
+ /** Module factories — typed organism configs wrapped as canonical `ModuleEntry`. */
12466
+ module: module_,
12467
+ /** One-call template factories — ready-to-publish canonical ValidatorRules. */
12468
+ template
12469
+ };
9938
12470
  /*! Bundled license information:
9939
12471
 
9940
12472
  @scure/base/lib/index.js:
@@ -9952,9 +12484,32 @@ async function verifyPqcAttestation(cert, payload, registrySnapshot) {
9952
12484
  (*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
9953
12485
  */
9954
12486
 
12487
+ exports.AccountKeyConditionsSchema = AccountKeyConditionsSchema;
12488
+ exports.AccountOperationsConfigSchema = AccountOperationsConfigSchema;
12489
+ exports.AccountRulesBuilder = AccountRulesBuilder;
12490
+ exports.AccountValidatorRulesSchema = AccountValidatorRulesSchema;
12491
+ exports.AgentAccessControlModeSchema = AgentAccessControlModeSchema;
12492
+ exports.AgentAllocationLimitsSchema = AgentAllocationLimitsSchema;
12493
+ exports.AgentApprovalThresholdSchema = AgentApprovalThresholdSchema;
12494
+ exports.AgentApprovedPairsSchema = AgentApprovedPairsSchema;
12495
+ exports.AgentControllerTypeSchema = AgentControllerTypeSchema;
12496
+ exports.AgentCooldownSchema = AgentCooldownSchema;
12497
+ exports.AgentOperationalWindowSchema = AgentOperationalWindowSchema;
12498
+ exports.AgentPermissionEntrySchema = AgentPermissionEntrySchema;
12499
+ exports.AgentPermissionScopeSchema = AgentPermissionScopeSchema;
12500
+ exports.AgentPermissionsSchema = AgentPermissionsSchema;
12501
+ exports.AgentRulesBuilder = AgentRulesBuilder;
12502
+ exports.AgentTokenPairSchema = AgentTokenPairSchema;
12503
+ exports.AgentTradeLimitsSchema = AgentTradeLimitsSchema;
12504
+ exports.AgentTypeSchema = AgentTypeSchema;
12505
+ exports.AgentValidatorRulesSchema = AgentValidatorRulesSchema;
9955
12506
  exports.AgentsClient = AgentsClient;
9956
12507
  exports.BaasClient = BaasClient;
9957
12508
  exports.BaasError = BaasError;
12509
+ exports.BaseOperationConfigSchema = BaseOperationConfigSchema;
12510
+ exports.BaseRuleBuilder = BaseRuleBuilder;
12511
+ exports.BridgeClient = BridgeClient;
12512
+ exports.BurnOperationConfigSchema = BurnOperationConfigSchema;
9958
12513
  exports.CapabilityNotEnabledError = CapabilityNotEnabledError;
9959
12514
  exports.CapabilityValidationError = CapabilityValidationError;
9960
12515
  exports.CircuitBreaker = CircuitBreaker;
@@ -9963,62 +12518,144 @@ exports.ClusterDiscoveryClient = ClusterDiscoveryClient;
9963
12518
  exports.CustomerSessionClient = CustomerSessionClient;
9964
12519
  exports.DEFAULT_CIRCUIT_BREAKER_CONFIG = DEFAULT_CIRCUIT_BREAKER_CONFIG;
9965
12520
  exports.DEFAULT_RETRY_CONFIG = DEFAULT_RETRY_CONFIG;
12521
+ exports.DaoClient = DaoClient;
12522
+ exports.DaoDashboardClient = DaoDashboardClient;
9966
12523
  exports.DatabaseClient = DatabaseClient;
9967
12524
  exports.DeploymentClient = DeploymentClient;
12525
+ exports.DiscoveryClient = DiscoveryClient;
9968
12526
  exports.DnsClient = DnsClient;
9969
12527
  exports.DomainsClient = DomainsClient;
12528
+ exports.EntitiesClient = EntitiesClient;
12529
+ exports.EnvelopeClient = EnvelopeClient;
9970
12530
  exports.ErrorCode = ErrorCode;
12531
+ exports.FeeConditionsSchema = FeeConditionsSchema;
12532
+ exports.FixedFeeConditionSchema = FixedFeeConditionSchema;
12533
+ exports.FractionalFeeConditionSchema = FractionalFeeConditionSchema;
12534
+ exports.FreezeOperationConfigSchema = FreezeOperationConfigSchema;
9971
12535
  exports.FunctionsClient = FunctionsClient;
12536
+ exports.FungibleTokenGateSchema = FungibleTokenGateSchema;
9972
12537
  exports.GovernanceClient = GovernanceClient;
12538
+ exports.GovernanceConfigSchema = GovernanceConfigSchema;
12539
+ exports.HealthClient = HealthClient;
9973
12540
  exports.HederaTransactionsClient = HederaTransactionsClient;
12541
+ exports.HederaTssClient = HederaTssClient;
9974
12542
  exports.HistoricalBalanceClient = HistoricalBalanceClient;
9975
12543
  exports.HistoricalBalanceClientError = HistoricalBalanceClientError;
9976
12544
  exports.IPFSClient = IPFSClient;
12545
+ exports.KNOWN_NETWORKS = KNOWN_NETWORKS;
12546
+ exports.KeyConditionSchema = KeyConditionSchema;
9977
12547
  exports.MIRROR_NODE_URLS = MIRROR_NODE_URLS;
9978
12548
  exports.MessagingClient = MessagingClient;
12549
+ exports.MintOperationConfigSchema = MintOperationConfigSchema;
9979
12550
  exports.MirrorNodeClient = MirrorNodeClient;
9980
12551
  exports.MirrorNodeError = MirrorNodeError;
12552
+ exports.ModuleEntrySchema = ModuleEntrySchema;
12553
+ exports.NonFungibleTokenGateSchema = NonFungibleTokenGateSchema;
12554
+ exports.OperationControllerSchema = OperationControllerSchema;
12555
+ exports.OperationLimitsSchema = OperationLimitsSchema;
12556
+ exports.OperatorClient = OperatorClient;
9981
12557
  exports.PERSONHOOD_VERIFIER_NOT_CONFIGURED = PERSONHOOD_VERIFIER_NOT_CONFIGURED;
12558
+ exports.PauseOperationConfigSchema = PauseOperationConfigSchema;
12559
+ exports.PayloadSchemaRefSchema = PayloadSchemaRefSchema;
9982
12560
  exports.PersonhoodClient = PersonhoodClient;
12561
+ exports.PlatformImagesClient = PlatformImagesClient;
9983
12562
  exports.PolkadotTransactionsClient = PolkadotTransactionsClient;
9984
12563
  exports.PqcCertV1Schema = PqcCertV1Schema;
9985
12564
  exports.RateLimiter = RateLimiter;
12565
+ exports.ResourcesClient = ResourcesClient;
9986
12566
  exports.RoutingClient = RoutingClient;
12567
+ exports.RoyaltyFeeConditionSchema = RoyaltyFeeConditionSchema;
12568
+ exports.RuleBuildError = RuleBuildError;
12569
+ exports.RuleInvariantsSchema = RuleInvariantsSchema;
12570
+ exports.Rules = Rules;
12571
+ exports.RulesClient = RulesClient;
9987
12572
  exports.SdkHttpError = SdkHttpError;
9988
12573
  exports.SettlementClient = SettlementClient;
9989
12574
  exports.SmartEngineClient = SmartEngineClient;
9990
12575
  exports.SmartEngineError = SmartEngineError;
9991
12576
  exports.SmartGatewayClient = SmartGatewayClient;
12577
+ exports.SmartNodeSecuritySchema = SmartNodeSecuritySchema;
9992
12578
  exports.SnapshotsClient = SnapshotsClient;
9993
12579
  exports.SolanaTransactionsClient = SolanaTransactionsClient;
12580
+ exports.SoulboundAllowedActionSchema = SoulboundAllowedActionSchema;
12581
+ exports.SoulboundNftConfigSchema = SoulboundNftConfigSchema;
9994
12582
  exports.StorageClient = StorageClient;
12583
+ exports.SubmitOperationConfigSchema = SubmitOperationConfigSchema;
9995
12584
  exports.SubscriptionClient = SubscriptionClient;
9996
12585
  exports.TSSClient = TSSClient;
12586
+ exports.TimeRangeSchema = TimeRangeSchema;
12587
+ exports.TokenGateConditionsSchema = TokenGateConditionsSchema;
12588
+ exports.TokenKeyConditionsSchema = TokenKeyConditionsSchema;
12589
+ exports.TokenOperationsConfigSchema = TokenOperationsConfigSchema;
12590
+ exports.TokenRulesBuilder = TokenRulesBuilder;
12591
+ exports.TokenValidatorRulesSchema = TokenValidatorRulesSchema;
12592
+ exports.TokensClient = TokensClient;
12593
+ exports.TopicKeyConditionsSchema = TopicKeyConditionsSchema;
12594
+ exports.TopicOperationsConfigSchema = TopicOperationsConfigSchema;
12595
+ exports.TopicRulesBuilder = TopicRulesBuilder;
12596
+ exports.TopicValidatorRulesSchema = TopicValidatorRulesSchema;
9997
12597
  exports.TransactionsClient = TransactionsClient;
12598
+ exports.TransferOperationConfigSchema = TransferOperationConfigSchema;
9998
12599
  exports.UnsupportedCapabilityError = UnsupportedCapabilityError;
12600
+ exports.UpdateOperationConfigSchema = UpdateOperationConfigSchema;
9999
12601
  exports.ValidatorAuthClient = ValidatorAuthClient;
10000
12602
  exports.ValidatorAuthError = ValidatorAuthError;
10001
12603
  exports.ValidatorDiscoveryClient = ValidatorDiscoveryClient;
12604
+ exports.ValidatorMetadataSchema = ValidatorMetadataSchema;
12605
+ exports.ValidatorRulesSchema = ValidatorRulesSchema;
10002
12606
  exports.XrplTransactionsClient = XrplTransactionsClient;
12607
+ exports.appTopic = appTopic;
12608
+ exports.atom = atom;
10003
12609
  exports.auth = auth_exports;
10004
12610
  exports.baas = baas_exports;
12611
+ exports.bridge = bridge_exports;
10005
12612
  exports.chains = chains_exports;
10006
12613
  exports.createHttpClient = createHttpClient;
10007
12614
  exports.createResilientFetchWithBreaker = createResilientFetchWithBreaker;
10008
12615
  exports.createXrplWeb3Signer = createXrplWeb3Signer;
12616
+ exports.dao = dao_exports;
12617
+ exports.daoGovernedToken = daoGovernedToken;
10009
12618
  exports.discovery = discovery_exports;
10010
12619
  exports.encodePathParam = encodePathParam;
12620
+ exports.envelope = envelope_exports;
12621
+ exports.fairLaunch = fairLaunch;
10011
12622
  exports.fetchRegistrySnapshot = fetchRegistrySnapshot;
12623
+ exports.forAccount = forAccount;
12624
+ exports.forAgent = forAgent;
12625
+ exports.forToken = forToken;
12626
+ exports.forTopic = forTopic;
10012
12627
  exports.governance = governance_exports;
12628
+ exports.isKnownNetwork = isKnownNetwork;
10013
12629
  exports.isPersonhoodVerifierNotConfigured = isPersonhoodVerifierNotConfigured;
10014
12630
  exports.isRuleRejected = isRuleRejected;
12631
+ exports.managedAccount = managedAccount;
12632
+ exports.membershipNft = membershipNft;
12633
+ exports.module_ = module_;
12634
+ exports.molecule = molecule;
12635
+ exports.multisigDAO = multisigDAO;
12636
+ exports.operator = operator_exports;
10015
12637
  exports.parsePqcCert = parsePqcCert;
10016
12638
  exports.personhood = personhood_exports;
10017
12639
  exports.pqcVerify = pqc_verify_exports;
10018
12640
  exports.resilientFetch = resilientFetch;
12641
+ exports.resolveNetwork = resolveNetwork;
12642
+ exports.resources = resources_exports;
10019
12643
  exports.settlement = settlement_exports;
12644
+ exports.simpleAMM = simpleAMM;
12645
+ exports.simpleStaking = simpleStaking;
12646
+ exports.soulboundNft = soulboundNft;
10020
12647
  exports.subscription = subscription_exports;
12648
+ exports.subscriptionNft = subscriptionNft;
12649
+ exports.systemTopic = systemTopic;
12650
+ exports.template = template;
12651
+ exports.tieredIDO = tieredIDO;
12652
+ exports.tokenDAO = tokenDAO;
12653
+ exports.tokens = tokens_exports;
12654
+ exports.tradingAgent = tradingAgent;
12655
+ exports.utilityToken = utilityToken;
12656
+ exports.validate = validate;
10021
12657
  exports.validateAgentRules = validateAgentRules;
10022
12658
  exports.verifyPqcAttestation = verifyPqcAttestation;
12659
+ exports.vestingSchedule = vestingSchedule;
10023
12660
  //# sourceMappingURL=index.js.map
10024
12661
  //# sourceMappingURL=index.js.map