@hsuite/smart-engines-sdk 3.2.0 → 3.3.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/CHANGELOG.md +116 -0
- package/README.md +51 -0
- package/dist/index.d.ts +20888 -1078
- package/dist/index.js +6954 -343
- package/dist/index.js.map +1 -1
- package/dist/nestjs/index.d.ts +8298 -810
- package/dist/nestjs/index.js +511 -303
- package/dist/nestjs/index.js.map +1 -1
- package/dist/pqc-verify/index.d.ts +99 -0
- package/dist/pqc-verify/index.js +167 -0
- package/dist/pqc-verify/index.js.map +1 -0
- package/package.json +11 -3
package/dist/nestjs/index.js
CHANGED
|
@@ -35,29 +35,6 @@ zod.z.object({
|
|
|
35
35
|
blockTime: zod.z.number().optional(),
|
|
36
36
|
rpcEndpoint: zod.z.string().url().optional()
|
|
37
37
|
});
|
|
38
|
-
var NetworkMembershipTypeSchema = zod.z.enum(["validator", "host", "gateway"]);
|
|
39
|
-
var MembershipStatusSchema = zod.z.enum(["pending", "active", "exiting", "exited", "banned"]);
|
|
40
|
-
zod.z.object({
|
|
41
|
-
nodeId: zod.z.string().min(1),
|
|
42
|
-
networkType: NetworkMembershipTypeSchema,
|
|
43
|
-
chain: zod.z.enum(["hedera", "xrpl", "polkadot", "solana"]),
|
|
44
|
-
endpoint: zod.z.string().url(),
|
|
45
|
-
publicKey: zod.z.string().min(1),
|
|
46
|
-
joinedAt: zod.z.string().datetime(),
|
|
47
|
-
depositTxId: zod.z.string().min(1),
|
|
48
|
-
status: MembershipStatusSchema,
|
|
49
|
-
networkConfig: zod.z.record(zod.z.unknown()).optional()
|
|
50
|
-
});
|
|
51
|
-
var NetworkDepositRequirementsSchema = zod.z.object({
|
|
52
|
-
depositAmount: zod.z.string().min(1),
|
|
53
|
-
lockDurationDays: zod.z.number().int().positive(),
|
|
54
|
-
renewalWindowDays: zod.z.number().int().positive().optional()
|
|
55
|
-
});
|
|
56
|
-
zod.z.object({
|
|
57
|
-
validator: NetworkDepositRequirementsSchema,
|
|
58
|
-
host: NetworkDepositRequirementsSchema,
|
|
59
|
-
gateway: NetworkDepositRequirementsSchema
|
|
60
|
-
});
|
|
61
38
|
var TokenCapabilitiesSchema = zod.z.object({
|
|
62
39
|
/**
|
|
63
40
|
* Pause all token operations globally
|
|
@@ -126,19 +103,16 @@ zod.z.object({
|
|
|
126
103
|
).optional(),
|
|
127
104
|
timestamp: zod.z.date()
|
|
128
105
|
});
|
|
129
|
-
var SecurityModeSchema = zod.z.enum(["
|
|
106
|
+
var SecurityModeSchema = zod.z.enum(["partial", "full"]);
|
|
130
107
|
var sovereigntyRefinePredicate = (v) => {
|
|
131
108
|
if (v.securityMode === "partial") {
|
|
132
109
|
return !!v.entityId && !!v.appOwnerPublicKey;
|
|
133
110
|
}
|
|
134
|
-
|
|
135
|
-
return !!v.entityId;
|
|
136
|
-
}
|
|
137
|
-
return true;
|
|
111
|
+
return !!v.entityId;
|
|
138
112
|
};
|
|
139
113
|
var SOVEREIGNTY_REFINE_MESSAGE = "securityMode='partial' requires entityId+appOwnerPublicKey; 'full' requires entityId";
|
|
140
114
|
var SovereigntyFieldsRawSchema = zod.z.object({
|
|
141
|
-
securityMode: SecurityModeSchema.default("
|
|
115
|
+
securityMode: SecurityModeSchema.default("full"),
|
|
142
116
|
entityId: zod.z.string().optional(),
|
|
143
117
|
appOwnerPublicKey: zod.z.string().optional()
|
|
144
118
|
});
|
|
@@ -212,7 +186,6 @@ var PreparedTransactionAuthorizationSetSchema = zod.z.discriminatedUnion("chain"
|
|
|
212
186
|
PolkadotAuthorizationSetShapeSchema
|
|
213
187
|
]);
|
|
214
188
|
var PreparedTransactionSovereigntySchema = zod.z.discriminatedUnion("mode", [
|
|
215
|
-
zod.z.object({ mode: zod.z.literal("none") }),
|
|
216
189
|
zod.z.object({
|
|
217
190
|
mode: zod.z.literal("partial"),
|
|
218
191
|
entityId: zod.z.string(),
|
|
@@ -226,74 +199,6 @@ var PreparedTransactionSovereigntySchema = zod.z.discriminatedUnion("mode", [
|
|
|
226
199
|
authorizationSet: PreparedTransactionAuthorizationSetSchema.optional()
|
|
227
200
|
})
|
|
228
201
|
]);
|
|
229
|
-
var TransactionStatusSchema = zod.z.enum(["pending", "success", "failed", "expired"]);
|
|
230
|
-
var TransactionTypeSchema = zod.z.enum([
|
|
231
|
-
"transfer",
|
|
232
|
-
"token_transfer",
|
|
233
|
-
"account_create",
|
|
234
|
-
"token_create",
|
|
235
|
-
"token_mint",
|
|
236
|
-
"token_burn",
|
|
237
|
-
"contract_call",
|
|
238
|
-
"contract_create",
|
|
239
|
-
"topic_message",
|
|
240
|
-
"other"
|
|
241
|
-
]);
|
|
242
|
-
zod.z.object({
|
|
243
|
-
id: zod.z.string(),
|
|
244
|
-
chain: ChainTypeSchema,
|
|
245
|
-
type: TransactionTypeSchema,
|
|
246
|
-
status: TransactionStatusSchema,
|
|
247
|
-
timestamp: zod.z.date(),
|
|
248
|
-
from: AccountIdSchema,
|
|
249
|
-
to: AccountIdSchema.optional(),
|
|
250
|
-
amount: zod.z.string().optional(),
|
|
251
|
-
fee: zod.z.string(),
|
|
252
|
-
memo: zod.z.string().optional(),
|
|
253
|
-
metadata: zod.z.record(zod.z.any()).optional()
|
|
254
|
-
});
|
|
255
|
-
zod.z.object({
|
|
256
|
-
transactionId: zod.z.string(),
|
|
257
|
-
chain: ChainTypeSchema,
|
|
258
|
-
status: TransactionStatusSchema,
|
|
259
|
-
blockNumber: zod.z.number().optional(),
|
|
260
|
-
blockHash: zod.z.string().optional(),
|
|
261
|
-
timestamp: zod.z.date(),
|
|
262
|
-
gasUsed: zod.z.string().optional(),
|
|
263
|
-
effectiveFee: zod.z.string(),
|
|
264
|
-
logs: zod.z.array(zod.z.any()).optional(),
|
|
265
|
-
metadata: zod.z.record(zod.z.any()).optional()
|
|
266
|
-
});
|
|
267
|
-
var TokenTypeSchema = zod.z.enum(["fungible", "nft", "semi_fungible"]);
|
|
268
|
-
var TokenSchema = zod.z.object({
|
|
269
|
-
tokenId: zod.z.string(),
|
|
270
|
-
chain: ChainTypeSchema,
|
|
271
|
-
name: zod.z.string(),
|
|
272
|
-
symbol: zod.z.string(),
|
|
273
|
-
decimals: zod.z.number().int().min(0),
|
|
274
|
-
totalSupply: zod.z.string(),
|
|
275
|
-
type: TokenTypeSchema,
|
|
276
|
-
creator: AccountIdSchema.optional(),
|
|
277
|
-
metadata: zod.z.record(zod.z.any()).optional(),
|
|
278
|
-
createdAt: zod.z.date().optional()
|
|
279
|
-
});
|
|
280
|
-
zod.z.object({
|
|
281
|
-
name: zod.z.string(),
|
|
282
|
-
description: zod.z.string().optional(),
|
|
283
|
-
image: zod.z.string().url().optional(),
|
|
284
|
-
attributes: zod.z.array(
|
|
285
|
-
zod.z.object({
|
|
286
|
-
trait_type: zod.z.string(),
|
|
287
|
-
value: zod.z.union([zod.z.string(), zod.z.number(), zod.z.boolean()])
|
|
288
|
-
})
|
|
289
|
-
).optional(),
|
|
290
|
-
external_url: zod.z.string().url().optional()
|
|
291
|
-
});
|
|
292
|
-
TokenSchema.extend({
|
|
293
|
-
holders: zod.z.number().optional(),
|
|
294
|
-
transferCount: zod.z.number().optional(),
|
|
295
|
-
circulatingSupply: zod.z.string().optional()
|
|
296
|
-
});
|
|
297
202
|
var CreateAccountRequestSchema = zod.z.object({
|
|
298
203
|
chain: ChainTypeSchema,
|
|
299
204
|
initialBalance: zod.z.string(),
|
|
@@ -323,12 +228,11 @@ var CreateAccountRequestSchema = zod.z.object({
|
|
|
323
228
|
immutable: zod.z.boolean().default(true),
|
|
324
229
|
/**
|
|
325
230
|
* Smart node security mode for the account key structure.
|
|
326
|
-
* - 'none': Owner-only key (no validator involvement)
|
|
327
231
|
* - 'partial': threshold(2, [appOwnerKey, tssKeyList]) — co-control
|
|
328
232
|
* - 'full': TSS KeyList only — full validator network control
|
|
329
|
-
* Default: '
|
|
233
|
+
* Default: 'full' (Arc 5 §7.5.2: 'none' removed).
|
|
330
234
|
*/
|
|
331
|
-
securityMode: zod.z.enum(["
|
|
235
|
+
securityMode: zod.z.enum(["partial", "full"]).default("full"),
|
|
332
236
|
/**
|
|
333
237
|
* App owner's public key (required for 'partial' security mode).
|
|
334
238
|
* The owner key + TSS network key form a threshold-2 multi-sig.
|
|
@@ -541,7 +445,7 @@ var SolanaPreparedMetadataSchema = zod.z.object({
|
|
|
541
445
|
/** Whether the multisig was created in this call (vs already existed) */
|
|
542
446
|
multisigCreated: zod.z.boolean().optional(),
|
|
543
447
|
/** Security mode used to prepare this transaction */
|
|
544
|
-
securityMode: zod.z.enum(["
|
|
448
|
+
securityMode: zod.z.enum(["partial", "full"]).optional(),
|
|
545
449
|
/** SPL Token mint address (token-create and all SPL operations) */
|
|
546
450
|
splMint: zod.z.string().optional()
|
|
547
451
|
});
|
|
@@ -647,12 +551,7 @@ zod.z.object({
|
|
|
647
551
|
validatorTimestamp: zod.z.string().min(1),
|
|
648
552
|
validatorTopicId: zod.z.string().min(1)
|
|
649
553
|
}).merge(SovereigntyFieldsRawSchema).refine(
|
|
650
|
-
(v) =>
|
|
651
|
-
if (v.securityMode === "partial" || v.securityMode === "full") {
|
|
652
|
-
return !!v.entityId;
|
|
653
|
-
}
|
|
654
|
-
return true;
|
|
655
|
-
},
|
|
554
|
+
(v) => !!v.entityId,
|
|
656
555
|
{ message: "securityMode='partial'/'full' requires entityId" }
|
|
657
556
|
);
|
|
658
557
|
|
|
@@ -1593,6 +1492,32 @@ function encodePathParam(param) {
|
|
|
1593
1492
|
return encodeURIComponent(param).replace(/%2F/gi, "");
|
|
1594
1493
|
}
|
|
1595
1494
|
|
|
1495
|
+
// src/network-presets.ts
|
|
1496
|
+
var KNOWN_NETWORKS = {
|
|
1497
|
+
testnet: {
|
|
1498
|
+
bootstrap: ["https://gateway.testnet.hsuite.network"]
|
|
1499
|
+
},
|
|
1500
|
+
mainnet: {
|
|
1501
|
+
// Mainnet entrypoint reserved. The SDK still resolves the name so
|
|
1502
|
+
// upgrade-by-flipping-NETWORK works; the bootstrap URL is the
|
|
1503
|
+
// pre-allocated DNS we own. If mainnet isn't deployed yet, the discovery
|
|
1504
|
+
// fetch will fail at runtime with the same "no seed reachable" error
|
|
1505
|
+
// any unreachable URL produces — the caller learns the network is not
|
|
1506
|
+
// live, rather than getting a baffling "unknown network" TypeScript
|
|
1507
|
+
// error at compile time.
|
|
1508
|
+
bootstrap: ["https://gateway.hsuite.network"]
|
|
1509
|
+
}
|
|
1510
|
+
};
|
|
1511
|
+
function resolveNetwork(name) {
|
|
1512
|
+
const preset = KNOWN_NETWORKS[name];
|
|
1513
|
+
if (!preset) {
|
|
1514
|
+
throw new Error(
|
|
1515
|
+
`Unknown network: "${name}". Known networks: ${Object.keys(KNOWN_NETWORKS).join(", ")}`
|
|
1516
|
+
);
|
|
1517
|
+
}
|
|
1518
|
+
return preset;
|
|
1519
|
+
}
|
|
1520
|
+
|
|
1596
1521
|
// src/subscription/index.ts
|
|
1597
1522
|
var SubscriptionClient = class {
|
|
1598
1523
|
constructor(http) {
|
|
@@ -2271,6 +2196,178 @@ var PersonhoodClient = class {
|
|
|
2271
2196
|
}
|
|
2272
2197
|
};
|
|
2273
2198
|
|
|
2199
|
+
// src/baas/agents/index.ts
|
|
2200
|
+
var AgentsClient = class {
|
|
2201
|
+
constructor(http) {
|
|
2202
|
+
this.http = http;
|
|
2203
|
+
}
|
|
2204
|
+
http;
|
|
2205
|
+
/** Register a new agent */
|
|
2206
|
+
async register(request) {
|
|
2207
|
+
return this.http.post("/api/agents/register", request);
|
|
2208
|
+
}
|
|
2209
|
+
/** Get agent details */
|
|
2210
|
+
async get(agentId) {
|
|
2211
|
+
return this.http.get(`/api/agents/${encodeURIComponent(agentId)}`);
|
|
2212
|
+
}
|
|
2213
|
+
/** List all agents */
|
|
2214
|
+
async list() {
|
|
2215
|
+
return this.http.get("/api/agents");
|
|
2216
|
+
}
|
|
2217
|
+
/** Fund an agent */
|
|
2218
|
+
async fund(agentId, request) {
|
|
2219
|
+
return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/fund`, request);
|
|
2220
|
+
}
|
|
2221
|
+
/** Execute a trade */
|
|
2222
|
+
async trade(agentId, request) {
|
|
2223
|
+
return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/trade`, request);
|
|
2224
|
+
}
|
|
2225
|
+
/** Withdraw funds from agent */
|
|
2226
|
+
async withdraw(agentId, request) {
|
|
2227
|
+
return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/withdraw`, request);
|
|
2228
|
+
}
|
|
2229
|
+
/** Pause an agent */
|
|
2230
|
+
async pause(agentId) {
|
|
2231
|
+
return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/pause`, {});
|
|
2232
|
+
}
|
|
2233
|
+
/** Resume a paused agent */
|
|
2234
|
+
async resume(agentId) {
|
|
2235
|
+
return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/resume`, {});
|
|
2236
|
+
}
|
|
2237
|
+
/** Revoke an agent (permanent) */
|
|
2238
|
+
async revoke(agentId) {
|
|
2239
|
+
return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/revoke`, {});
|
|
2240
|
+
}
|
|
2241
|
+
/** Update agent rules */
|
|
2242
|
+
async updateRules(agentId, rules) {
|
|
2243
|
+
return this.http.put(`/api/agents/${encodeURIComponent(agentId)}/rules`, rules);
|
|
2244
|
+
}
|
|
2245
|
+
/** Get agent events */
|
|
2246
|
+
async getEvents(agentId) {
|
|
2247
|
+
return this.http.get(`/api/agents/${encodeURIComponent(agentId)}/events`);
|
|
2248
|
+
}
|
|
2249
|
+
/** Get agent balances across chains */
|
|
2250
|
+
async getBalances(agentId) {
|
|
2251
|
+
return this.http.get(`/api/agents/${encodeURIComponent(agentId)}/balances`);
|
|
2252
|
+
}
|
|
2253
|
+
/** Approve a pending agent operation */
|
|
2254
|
+
async approve(agentId, operationId) {
|
|
2255
|
+
return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/approve/${encodeURIComponent(operationId)}`, {});
|
|
2256
|
+
}
|
|
2257
|
+
/** Reject a pending agent operation */
|
|
2258
|
+
async reject(agentId, operationId) {
|
|
2259
|
+
return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/reject/${encodeURIComponent(operationId)}`, {});
|
|
2260
|
+
}
|
|
2261
|
+
};
|
|
2262
|
+
|
|
2263
|
+
// src/baas/deployment/index.ts
|
|
2264
|
+
var DeploymentClient = class {
|
|
2265
|
+
constructor(http) {
|
|
2266
|
+
this.http = http;
|
|
2267
|
+
}
|
|
2268
|
+
http;
|
|
2269
|
+
/**
|
|
2270
|
+
* Step 1 — allocate appId + receive ephemeral push credentials for
|
|
2271
|
+
* the cluster's per-tenant Harbor project.
|
|
2272
|
+
*
|
|
2273
|
+
* Each app gets its own Harbor project (`hsuite-customers-<appId>`)
|
|
2274
|
+
* isolated by Harbor's RBAC. The push robot returned in
|
|
2275
|
+
* `registry.{username, password}` is scoped to that project only —
|
|
2276
|
+
* it cannot read or write any other tenant's images.
|
|
2277
|
+
*
|
|
2278
|
+
* **Single-use secret discipline:** `registry.password` is returned
|
|
2279
|
+
* exactly once and is NOT persisted server-side. Store it locally
|
|
2280
|
+
* for the `docker push` and discard. To rotate, call `init` again
|
|
2281
|
+
* (issues a new robot under the same project).
|
|
2282
|
+
*
|
|
2283
|
+
* Use the credentials to `docker login` + `docker push`, then call
|
|
2284
|
+
* {@link deploy} with the pushed image tag.
|
|
2285
|
+
*/
|
|
2286
|
+
async init(request) {
|
|
2287
|
+
return this.http.post("/api/deployment/apps/init", request);
|
|
2288
|
+
}
|
|
2289
|
+
/**
|
|
2290
|
+
* Step 3 (optional) — upload the SPA tarball.
|
|
2291
|
+
*
|
|
2292
|
+
* The tarball is content-addressed (SHA-256) and mounted read-only
|
|
2293
|
+
* into the customer's pod alongside the backend container. Returns
|
|
2294
|
+
* the hash + size so the caller can verify the upload.
|
|
2295
|
+
*/
|
|
2296
|
+
async uploadFrontend(appId, bundle, filename = "bundle.tar.gz") {
|
|
2297
|
+
return this.http.upload(
|
|
2298
|
+
`/api/deployment/apps/${encodeURIComponent(appId)}/frontend`,
|
|
2299
|
+
bundle,
|
|
2300
|
+
filename,
|
|
2301
|
+
void 0,
|
|
2302
|
+
"bundle"
|
|
2303
|
+
);
|
|
2304
|
+
}
|
|
2305
|
+
/**
|
|
2306
|
+
* Step 4 — reconcile the runtime to k8s.
|
|
2307
|
+
*
|
|
2308
|
+
* Returns immediately with `status: 'deploying'`. Poll {@link status}
|
|
2309
|
+
* until `runtime.runtimeState === 'RUNNING'` for the URL to be live.
|
|
2310
|
+
*/
|
|
2311
|
+
async deploy(appId, request) {
|
|
2312
|
+
return this.http.post(`/api/deployment/apps/${encodeURIComponent(appId)}/deploy`, request);
|
|
2313
|
+
}
|
|
2314
|
+
/**
|
|
2315
|
+
* Roll back to a previously-deployed image tag (must exist in
|
|
2316
|
+
* `runtime.deploymentHistory[]`).
|
|
2317
|
+
*/
|
|
2318
|
+
async rollback(appId, request) {
|
|
2319
|
+
return this.http.post(`/api/deployment/apps/${encodeURIComponent(appId)}/rollback`, request);
|
|
2320
|
+
}
|
|
2321
|
+
/**
|
|
2322
|
+
* Live combined lifecycle + runtime status of an app.
|
|
2323
|
+
*/
|
|
2324
|
+
async status(appId) {
|
|
2325
|
+
return this.http.get(`/api/deployment/apps/${encodeURIComponent(appId)}/status`);
|
|
2326
|
+
}
|
|
2327
|
+
/**
|
|
2328
|
+
* List all deployed apps for the authenticated developer.
|
|
2329
|
+
*/
|
|
2330
|
+
async list() {
|
|
2331
|
+
return this.http.get("/api/deployment/apps");
|
|
2332
|
+
}
|
|
2333
|
+
/**
|
|
2334
|
+
* Get app details.
|
|
2335
|
+
*/
|
|
2336
|
+
async get(appId) {
|
|
2337
|
+
return this.http.get(`/api/deployment/apps/${encodeURIComponent(appId)}`);
|
|
2338
|
+
}
|
|
2339
|
+
/**
|
|
2340
|
+
* Update app configuration. Runtime effect lands in PR-H.
|
|
2341
|
+
*/
|
|
2342
|
+
async update(appId, updates) {
|
|
2343
|
+
return this.http.put(`/api/deployment/apps/${encodeURIComponent(appId)}`, updates);
|
|
2344
|
+
}
|
|
2345
|
+
/**
|
|
2346
|
+
* Delete an app. Runtime effect (namespace teardown) lands in PR-H.
|
|
2347
|
+
*/
|
|
2348
|
+
async delete(appId) {
|
|
2349
|
+
return this.http.delete(`/api/deployment/apps/${encodeURIComponent(appId)}`);
|
|
2350
|
+
}
|
|
2351
|
+
/**
|
|
2352
|
+
* Suspend an app. Runtime effect (scale to zero) lands in PR-H.
|
|
2353
|
+
*/
|
|
2354
|
+
async suspend(appId) {
|
|
2355
|
+
return this.http.post(`/api/deployment/apps/${encodeURIComponent(appId)}/suspend`, {});
|
|
2356
|
+
}
|
|
2357
|
+
/**
|
|
2358
|
+
* Resume a suspended app. Runtime effect (scale back up) lands in PR-H.
|
|
2359
|
+
*/
|
|
2360
|
+
async resume(appId) {
|
|
2361
|
+
return this.http.post(`/api/deployment/apps/${encodeURIComponent(appId)}/resume`, {});
|
|
2362
|
+
}
|
|
2363
|
+
/**
|
|
2364
|
+
* Get deployment statistics.
|
|
2365
|
+
*/
|
|
2366
|
+
async getStats() {
|
|
2367
|
+
return this.http.get("/api/deployment/stats");
|
|
2368
|
+
}
|
|
2369
|
+
};
|
|
2370
|
+
|
|
2274
2371
|
// src/client.ts
|
|
2275
2372
|
var SmartEngineClient = class _SmartEngineClient {
|
|
2276
2373
|
baseUrl;
|
|
@@ -2307,6 +2404,10 @@ var SmartEngineClient = class _SmartEngineClient {
|
|
|
2307
2404
|
governance;
|
|
2308
2405
|
/** Personhood verification (HPP one-human-one-member) */
|
|
2309
2406
|
personhood;
|
|
2407
|
+
/** BaaS smart-agent lifecycle (register/fund/trade/withdraw/pause/resume/revoke/...) */
|
|
2408
|
+
agents;
|
|
2409
|
+
/** BaaS smart-app deployment lifecycle (init/uploadFrontend/deploy/rollback/status/...) */
|
|
2410
|
+
deployments;
|
|
2310
2411
|
constructor(config) {
|
|
2311
2412
|
this.allowInsecure = config.allowInsecure ?? false;
|
|
2312
2413
|
this.baseUrl = validateClientUrl(config.baseUrl, this.allowInsecure);
|
|
@@ -2335,6 +2436,40 @@ var SmartEngineClient = class _SmartEngineClient {
|
|
|
2335
2436
|
this.settlement = new SettlementClient(this.http);
|
|
2336
2437
|
this.governance = new GovernanceClient(this.http);
|
|
2337
2438
|
this.personhood = new PersonhoodClient(this.http);
|
|
2439
|
+
const rootHttp = createHttpClient({
|
|
2440
|
+
baseUrl: this.baseUrl,
|
|
2441
|
+
apiKey: config.apiKey,
|
|
2442
|
+
authToken: config.authToken,
|
|
2443
|
+
timeout: config.timeout
|
|
2444
|
+
});
|
|
2445
|
+
this.agents = new AgentsClient(rootHttp);
|
|
2446
|
+
this.deployments = new DeploymentClient(rootHttp);
|
|
2447
|
+
}
|
|
2448
|
+
/**
|
|
2449
|
+
* Build a `SmartEngineClient` from a plain env object. Reads:
|
|
2450
|
+
* - `VALIDATOR_URL` (required) — gateway/validator base URL
|
|
2451
|
+
* - `VALIDATOR_API_KEY` (optional) — API key for authenticated calls
|
|
2452
|
+
* - `APP_TOKEN` (optional) — session JWT from prior auth
|
|
2453
|
+
* - `ALLOW_INSECURE` (optional, `'true'`) — only for local dev
|
|
2454
|
+
* - `REQUEST_TIMEOUT` (optional, ms)
|
|
2455
|
+
*
|
|
2456
|
+
* Throws if `VALIDATOR_URL` is missing or invalid. Designed for BaaS
|
|
2457
|
+
* scheduled functions: `const client = SmartEngineClient.fromEnv(ctx.env)`.
|
|
2458
|
+
*/
|
|
2459
|
+
static fromEnv(env) {
|
|
2460
|
+
const baseUrl = env["VALIDATOR_URL"];
|
|
2461
|
+
if (!baseUrl) {
|
|
2462
|
+
throw new SmartEngineError("VALIDATOR_URL is required to build a SmartEngineClient", 500);
|
|
2463
|
+
}
|
|
2464
|
+
const timeoutRaw = env["REQUEST_TIMEOUT"];
|
|
2465
|
+
const timeout = timeoutRaw ? Number.parseInt(timeoutRaw, 10) : void 0;
|
|
2466
|
+
return new _SmartEngineClient({
|
|
2467
|
+
baseUrl,
|
|
2468
|
+
apiKey: env["VALIDATOR_API_KEY"],
|
|
2469
|
+
authToken: env["APP_TOKEN"],
|
|
2470
|
+
allowInsecure: env["ALLOW_INSECURE"] === "true",
|
|
2471
|
+
timeout: Number.isFinite(timeout) ? timeout : void 0
|
|
2472
|
+
});
|
|
2338
2473
|
}
|
|
2339
2474
|
/**
|
|
2340
2475
|
* Connect to the smart-engines network with auto-discovery and authentication
|
|
@@ -2354,7 +2489,7 @@ var SmartEngineClient = class _SmartEngineClient {
|
|
|
2354
2489
|
});
|
|
2355
2490
|
const validator = await discovery.getRandomValidator();
|
|
2356
2491
|
if (!validator || !validator.networkEndpoints?.apiEndpoint) {
|
|
2357
|
-
throw new
|
|
2492
|
+
throw new SmartEngineError(
|
|
2358
2493
|
"No validators available. Check registry topic and network configuration.",
|
|
2359
2494
|
503
|
|
2360
2495
|
);
|
|
@@ -2392,7 +2527,18 @@ var SmartEngineClient = class _SmartEngineClient {
|
|
|
2392
2527
|
* 2. (Optional) HCS trust-anchor membership cross-check.
|
|
2393
2528
|
* 3. Random-pick over the verified set.
|
|
2394
2529
|
*
|
|
2395
|
-
* @example
|
|
2530
|
+
* @example Zero-config (recommended for smart-app callers)
|
|
2531
|
+
* ```ts
|
|
2532
|
+
* const { client, cluster, session } = await SmartEngineClient.connectToCluster({
|
|
2533
|
+
* network: 'testnet', // resolves canonical gateway entrypoint
|
|
2534
|
+
* chain: 'xrpl',
|
|
2535
|
+
* address: '...',
|
|
2536
|
+
* publicKey: '...',
|
|
2537
|
+
* signFn: async (challenge) => sign(challenge),
|
|
2538
|
+
* });
|
|
2539
|
+
* ```
|
|
2540
|
+
*
|
|
2541
|
+
* @example Custom seeds (private deployments / local dev)
|
|
2396
2542
|
* ```ts
|
|
2397
2543
|
* const { client, cluster, session } = await SmartEngineClient.connectToCluster({
|
|
2398
2544
|
* bootstrap: ['https://sn1.testnet.hsuite.network', 'https://sn2.testnet.hsuite.network'],
|
|
@@ -2405,8 +2551,15 @@ var SmartEngineClient = class _SmartEngineClient {
|
|
|
2405
2551
|
*/
|
|
2406
2552
|
static async connectToCluster(config) {
|
|
2407
2553
|
const allowInsecure = config.allowInsecure ?? false;
|
|
2554
|
+
const bootstrap = config.bootstrap ? [...config.bootstrap] : [...resolveNetwork(config.network).bootstrap];
|
|
2555
|
+
if (bootstrap.length === 0) {
|
|
2556
|
+
throw new SmartEngineError(
|
|
2557
|
+
"connectToCluster requires either a non-empty `bootstrap` list or a known `network` name.",
|
|
2558
|
+
400
|
|
2559
|
+
);
|
|
2560
|
+
}
|
|
2408
2561
|
const discovery = new ClusterDiscoveryClient({
|
|
2409
|
-
bootstrap
|
|
2562
|
+
bootstrap,
|
|
2410
2563
|
allowInsecure,
|
|
2411
2564
|
trustAnchor: config.trustAnchor ? {
|
|
2412
2565
|
network: config.trustAnchor.network,
|
|
@@ -2417,7 +2570,7 @@ var SmartEngineClient = class _SmartEngineClient {
|
|
|
2417
2570
|
});
|
|
2418
2571
|
const cluster = await discovery.getRandomCluster();
|
|
2419
2572
|
if (!cluster) {
|
|
2420
|
-
throw new
|
|
2573
|
+
throw new SmartEngineError(
|
|
2421
2574
|
"No active clusters available via bootstrap seeds. Check bootstrap URLs and network reachability.",
|
|
2422
2575
|
503
|
|
2423
2576
|
);
|
|
@@ -2529,7 +2682,7 @@ var SmartEngineClient = class _SmartEngineClient {
|
|
|
2529
2682
|
async restrictAccount(request) {
|
|
2530
2683
|
const validated = TokenActionRequestSchema.parse(request);
|
|
2531
2684
|
if (!validated.accountId) {
|
|
2532
|
-
throw new
|
|
2685
|
+
throw new SmartEngineError("accountId is required for restrictAccount", 400);
|
|
2533
2686
|
}
|
|
2534
2687
|
return this.http.post("/tokens/restrict", validated);
|
|
2535
2688
|
}
|
|
@@ -2537,7 +2690,7 @@ var SmartEngineClient = class _SmartEngineClient {
|
|
|
2537
2690
|
async unrestrictAccount(request) {
|
|
2538
2691
|
const validated = TokenActionRequestSchema.parse(request);
|
|
2539
2692
|
if (!validated.accountId) {
|
|
2540
|
-
throw new
|
|
2693
|
+
throw new SmartEngineError("accountId is required for unrestrictAccount", 400);
|
|
2541
2694
|
}
|
|
2542
2695
|
return this.http.post("/tokens/unrestrict", validated);
|
|
2543
2696
|
}
|
|
@@ -2545,7 +2698,7 @@ var SmartEngineClient = class _SmartEngineClient {
|
|
|
2545
2698
|
async enableCompliance(request) {
|
|
2546
2699
|
const validated = TokenActionRequestSchema.parse(request);
|
|
2547
2700
|
if (!validated.accountId) {
|
|
2548
|
-
throw new
|
|
2701
|
+
throw new SmartEngineError("accountId is required for enableCompliance", 400);
|
|
2549
2702
|
}
|
|
2550
2703
|
return this.http.post("/tokens/compliance/enable", validated);
|
|
2551
2704
|
}
|
|
@@ -2553,7 +2706,7 @@ var SmartEngineClient = class _SmartEngineClient {
|
|
|
2553
2706
|
async disableCompliance(request) {
|
|
2554
2707
|
const validated = TokenActionRequestSchema.parse(request);
|
|
2555
2708
|
if (!validated.accountId) {
|
|
2556
|
-
throw new
|
|
2709
|
+
throw new SmartEngineError("accountId is required for disableCompliance", 400);
|
|
2557
2710
|
}
|
|
2558
2711
|
return this.http.post("/tokens/compliance/disable", validated);
|
|
2559
2712
|
}
|
|
@@ -2561,10 +2714,10 @@ var SmartEngineClient = class _SmartEngineClient {
|
|
|
2561
2714
|
async wipeFromAccount(request) {
|
|
2562
2715
|
const validated = TokenActionRequestSchema.parse(request);
|
|
2563
2716
|
if (!validated.accountId) {
|
|
2564
|
-
throw new
|
|
2717
|
+
throw new SmartEngineError("accountId is required for wipeFromAccount", 400);
|
|
2565
2718
|
}
|
|
2566
2719
|
if (!validated.amount) {
|
|
2567
|
-
throw new
|
|
2720
|
+
throw new SmartEngineError("amount is required for wipeFromAccount", 400);
|
|
2568
2721
|
}
|
|
2569
2722
|
return this.http.post("/tokens/wipe", validated);
|
|
2570
2723
|
}
|
|
@@ -2585,7 +2738,7 @@ var SmartEngineClient = class _SmartEngineClient {
|
|
|
2585
2738
|
/** Submit a message to consensus */
|
|
2586
2739
|
async submitMessage(chain, topicId, message) {
|
|
2587
2740
|
if (message.length > 1024 * 1024) {
|
|
2588
|
-
throw new
|
|
2741
|
+
throw new SmartEngineError("Message too large (max 1MB)", 400);
|
|
2589
2742
|
}
|
|
2590
2743
|
return this.http.post(`/messages/${encodePathParam(chain)}/${encodePathParam(topicId)}`, {
|
|
2591
2744
|
message
|
|
@@ -2619,7 +2772,7 @@ var SmartEngineClient = class _SmartEngineClient {
|
|
|
2619
2772
|
return this.http.post("/auth/verify-signature", request);
|
|
2620
2773
|
}
|
|
2621
2774
|
};
|
|
2622
|
-
var
|
|
2775
|
+
var SmartEngineError = class extends Error {
|
|
2623
2776
|
constructor(message, statusCode, details) {
|
|
2624
2777
|
super(message);
|
|
2625
2778
|
this.statusCode = statusCode;
|
|
@@ -2633,18 +2786,18 @@ function validateClientUrl(url, allowInsecure = false) {
|
|
|
2633
2786
|
try {
|
|
2634
2787
|
const parsed = new URL(url);
|
|
2635
2788
|
if (!["http:", "https:"].includes(parsed.protocol)) {
|
|
2636
|
-
throw new
|
|
2789
|
+
throw new SmartEngineError(`Invalid protocol: ${parsed.protocol}`, 400);
|
|
2637
2790
|
}
|
|
2638
2791
|
if (!allowInsecure && parsed.protocol !== "https:") {
|
|
2639
|
-
throw new
|
|
2792
|
+
throw new SmartEngineError(
|
|
2640
2793
|
"HTTPS is required for secure connections. Set allowInsecure=true for local development.",
|
|
2641
2794
|
400
|
|
2642
2795
|
);
|
|
2643
2796
|
}
|
|
2644
2797
|
return parsed.origin;
|
|
2645
2798
|
} catch (error) {
|
|
2646
|
-
if (error instanceof
|
|
2647
|
-
throw new
|
|
2799
|
+
if (error instanceof SmartEngineError) throw error;
|
|
2800
|
+
throw new SmartEngineError(`Invalid URL: ${url}`, 400);
|
|
2648
2801
|
}
|
|
2649
2802
|
}
|
|
2650
2803
|
|
|
@@ -3210,178 +3363,6 @@ var MessagingClient = class {
|
|
|
3210
3363
|
}
|
|
3211
3364
|
};
|
|
3212
3365
|
|
|
3213
|
-
// src/baas/deployment/index.ts
|
|
3214
|
-
var DeploymentClient = class {
|
|
3215
|
-
constructor(http) {
|
|
3216
|
-
this.http = http;
|
|
3217
|
-
}
|
|
3218
|
-
http;
|
|
3219
|
-
/**
|
|
3220
|
-
* Step 1 — allocate appId + receive ephemeral push credentials for
|
|
3221
|
-
* the cluster's per-tenant Harbor project.
|
|
3222
|
-
*
|
|
3223
|
-
* Each app gets its own Harbor project (`hsuite-customers-<appId>`)
|
|
3224
|
-
* isolated by Harbor's RBAC. The push robot returned in
|
|
3225
|
-
* `registry.{username, password}` is scoped to that project only —
|
|
3226
|
-
* it cannot read or write any other tenant's images.
|
|
3227
|
-
*
|
|
3228
|
-
* **Single-use secret discipline:** `registry.password` is returned
|
|
3229
|
-
* exactly once and is NOT persisted server-side. Store it locally
|
|
3230
|
-
* for the `docker push` and discard. To rotate, call `init` again
|
|
3231
|
-
* (issues a new robot under the same project).
|
|
3232
|
-
*
|
|
3233
|
-
* Use the credentials to `docker login` + `docker push`, then call
|
|
3234
|
-
* {@link deploy} with the pushed image tag.
|
|
3235
|
-
*/
|
|
3236
|
-
async init(request) {
|
|
3237
|
-
return this.http.post("/api/deployment/apps/init", request);
|
|
3238
|
-
}
|
|
3239
|
-
/**
|
|
3240
|
-
* Step 3 (optional) — upload the SPA tarball.
|
|
3241
|
-
*
|
|
3242
|
-
* The tarball is content-addressed (SHA-256) and mounted read-only
|
|
3243
|
-
* into the customer's pod alongside the backend container. Returns
|
|
3244
|
-
* the hash + size so the caller can verify the upload.
|
|
3245
|
-
*/
|
|
3246
|
-
async uploadFrontend(appId, bundle, filename = "bundle.tar.gz") {
|
|
3247
|
-
return this.http.upload(
|
|
3248
|
-
`/api/deployment/apps/${encodeURIComponent(appId)}/frontend`,
|
|
3249
|
-
bundle,
|
|
3250
|
-
filename,
|
|
3251
|
-
void 0,
|
|
3252
|
-
"bundle"
|
|
3253
|
-
);
|
|
3254
|
-
}
|
|
3255
|
-
/**
|
|
3256
|
-
* Step 4 — reconcile the runtime to k8s.
|
|
3257
|
-
*
|
|
3258
|
-
* Returns immediately with `status: 'deploying'`. Poll {@link status}
|
|
3259
|
-
* until `runtime.runtimeState === 'RUNNING'` for the URL to be live.
|
|
3260
|
-
*/
|
|
3261
|
-
async deploy(appId, request) {
|
|
3262
|
-
return this.http.post(`/api/deployment/apps/${encodeURIComponent(appId)}/deploy`, request);
|
|
3263
|
-
}
|
|
3264
|
-
/**
|
|
3265
|
-
* Roll back to a previously-deployed image tag (must exist in
|
|
3266
|
-
* `runtime.deploymentHistory[]`).
|
|
3267
|
-
*/
|
|
3268
|
-
async rollback(appId, request) {
|
|
3269
|
-
return this.http.post(`/api/deployment/apps/${encodeURIComponent(appId)}/rollback`, request);
|
|
3270
|
-
}
|
|
3271
|
-
/**
|
|
3272
|
-
* Live combined lifecycle + runtime status of an app.
|
|
3273
|
-
*/
|
|
3274
|
-
async status(appId) {
|
|
3275
|
-
return this.http.get(`/api/deployment/apps/${encodeURIComponent(appId)}/status`);
|
|
3276
|
-
}
|
|
3277
|
-
/**
|
|
3278
|
-
* List all deployed apps for the authenticated developer.
|
|
3279
|
-
*/
|
|
3280
|
-
async list() {
|
|
3281
|
-
return this.http.get("/api/deployment/apps");
|
|
3282
|
-
}
|
|
3283
|
-
/**
|
|
3284
|
-
* Get app details.
|
|
3285
|
-
*/
|
|
3286
|
-
async get(appId) {
|
|
3287
|
-
return this.http.get(`/api/deployment/apps/${encodeURIComponent(appId)}`);
|
|
3288
|
-
}
|
|
3289
|
-
/**
|
|
3290
|
-
* Update app configuration. Runtime effect lands in PR-H.
|
|
3291
|
-
*/
|
|
3292
|
-
async update(appId, updates) {
|
|
3293
|
-
return this.http.put(`/api/deployment/apps/${encodeURIComponent(appId)}`, updates);
|
|
3294
|
-
}
|
|
3295
|
-
/**
|
|
3296
|
-
* Delete an app. Runtime effect (namespace teardown) lands in PR-H.
|
|
3297
|
-
*/
|
|
3298
|
-
async delete(appId) {
|
|
3299
|
-
return this.http.delete(`/api/deployment/apps/${encodeURIComponent(appId)}`);
|
|
3300
|
-
}
|
|
3301
|
-
/**
|
|
3302
|
-
* Suspend an app. Runtime effect (scale to zero) lands in PR-H.
|
|
3303
|
-
*/
|
|
3304
|
-
async suspend(appId) {
|
|
3305
|
-
return this.http.post(`/api/deployment/apps/${encodeURIComponent(appId)}/suspend`, {});
|
|
3306
|
-
}
|
|
3307
|
-
/**
|
|
3308
|
-
* Resume a suspended app. Runtime effect (scale back up) lands in PR-H.
|
|
3309
|
-
*/
|
|
3310
|
-
async resume(appId) {
|
|
3311
|
-
return this.http.post(`/api/deployment/apps/${encodeURIComponent(appId)}/resume`, {});
|
|
3312
|
-
}
|
|
3313
|
-
/**
|
|
3314
|
-
* Get deployment statistics.
|
|
3315
|
-
*/
|
|
3316
|
-
async getStats() {
|
|
3317
|
-
return this.http.get("/api/deployment/stats");
|
|
3318
|
-
}
|
|
3319
|
-
};
|
|
3320
|
-
|
|
3321
|
-
// src/baas/agents/index.ts
|
|
3322
|
-
var AgentsClient = class {
|
|
3323
|
-
constructor(http) {
|
|
3324
|
-
this.http = http;
|
|
3325
|
-
}
|
|
3326
|
-
http;
|
|
3327
|
-
/** Register a new agent */
|
|
3328
|
-
async register(request) {
|
|
3329
|
-
return this.http.post("/api/agents/register", request);
|
|
3330
|
-
}
|
|
3331
|
-
/** Get agent details */
|
|
3332
|
-
async get(agentId) {
|
|
3333
|
-
return this.http.get(`/api/agents/${encodeURIComponent(agentId)}`);
|
|
3334
|
-
}
|
|
3335
|
-
/** List all agents */
|
|
3336
|
-
async list() {
|
|
3337
|
-
return this.http.get("/api/agents");
|
|
3338
|
-
}
|
|
3339
|
-
/** Fund an agent */
|
|
3340
|
-
async fund(agentId, request) {
|
|
3341
|
-
return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/fund`, request);
|
|
3342
|
-
}
|
|
3343
|
-
/** Execute a trade */
|
|
3344
|
-
async trade(agentId, request) {
|
|
3345
|
-
return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/trade`, request);
|
|
3346
|
-
}
|
|
3347
|
-
/** Withdraw funds from agent */
|
|
3348
|
-
async withdraw(agentId, request) {
|
|
3349
|
-
return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/withdraw`, request);
|
|
3350
|
-
}
|
|
3351
|
-
/** Pause an agent */
|
|
3352
|
-
async pause(agentId) {
|
|
3353
|
-
return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/pause`, {});
|
|
3354
|
-
}
|
|
3355
|
-
/** Resume a paused agent */
|
|
3356
|
-
async resume(agentId) {
|
|
3357
|
-
return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/resume`, {});
|
|
3358
|
-
}
|
|
3359
|
-
/** Revoke an agent (permanent) */
|
|
3360
|
-
async revoke(agentId) {
|
|
3361
|
-
return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/revoke`, {});
|
|
3362
|
-
}
|
|
3363
|
-
/** Update agent rules */
|
|
3364
|
-
async updateRules(agentId, rules) {
|
|
3365
|
-
return this.http.put(`/api/agents/${encodeURIComponent(agentId)}/rules`, rules);
|
|
3366
|
-
}
|
|
3367
|
-
/** Get agent events */
|
|
3368
|
-
async getEvents(agentId) {
|
|
3369
|
-
return this.http.get(`/api/agents/${encodeURIComponent(agentId)}/events`);
|
|
3370
|
-
}
|
|
3371
|
-
/** Get agent balances across chains */
|
|
3372
|
-
async getBalances(agentId) {
|
|
3373
|
-
return this.http.get(`/api/agents/${encodeURIComponent(agentId)}/balances`);
|
|
3374
|
-
}
|
|
3375
|
-
/** Approve a pending agent operation */
|
|
3376
|
-
async approve(agentId, operationId) {
|
|
3377
|
-
return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/approve/${encodeURIComponent(operationId)}`, {});
|
|
3378
|
-
}
|
|
3379
|
-
/** Reject a pending agent operation */
|
|
3380
|
-
async reject(agentId, operationId) {
|
|
3381
|
-
return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/reject/${encodeURIComponent(operationId)}`, {});
|
|
3382
|
-
}
|
|
3383
|
-
};
|
|
3384
|
-
|
|
3385
3366
|
// src/baas/customer-session/index.ts
|
|
3386
3367
|
var CustomerSessionClient = class {
|
|
3387
3368
|
constructor(baseUrl, timeoutMs = 3e4) {
|
|
@@ -3454,8 +3435,90 @@ var CustomerSessionClient = class {
|
|
|
3454
3435
|
}
|
|
3455
3436
|
};
|
|
3456
3437
|
|
|
3438
|
+
// src/baas/rules/client.ts
|
|
3439
|
+
var RulesClient = class {
|
|
3440
|
+
constructor(http) {
|
|
3441
|
+
this.http = http;
|
|
3442
|
+
}
|
|
3443
|
+
http;
|
|
3444
|
+
/** Publish a canonical ValidatorRules document to HCS. */
|
|
3445
|
+
async publish(rule) {
|
|
3446
|
+
return this.http.post("/api/rules/publish", rule);
|
|
3447
|
+
}
|
|
3448
|
+
/** Fetch a published rule by its HCS consensus timestamp. */
|
|
3449
|
+
async get(consensusTimestamp) {
|
|
3450
|
+
return this.http.get(`/api/rules/${encodeURIComponent(consensusTimestamp)}`);
|
|
3451
|
+
}
|
|
3452
|
+
/** List rules owned by the authenticated entity, optionally filtered by type. */
|
|
3453
|
+
async listByOwner(filter) {
|
|
3454
|
+
const path = filter?.type ? `/api/rules?type=${encodeURIComponent(filter.type)}` : "/api/rules";
|
|
3455
|
+
return this.http.get(path);
|
|
3456
|
+
}
|
|
3457
|
+
/**
|
|
3458
|
+
* Simulate cluster-side evaluation of an action against a rule. Either
|
|
3459
|
+
* `ruleRef` (published) or `rule` (inline) must be supplied by the caller.
|
|
3460
|
+
*/
|
|
3461
|
+
async simulate(params) {
|
|
3462
|
+
return this.http.post("/api/rules/simulate", params);
|
|
3463
|
+
}
|
|
3464
|
+
/** Walk the version history of a published rule. */
|
|
3465
|
+
async getVersionHistory(consensusTimestamp) {
|
|
3466
|
+
return this.http.get(
|
|
3467
|
+
`/api/rules/${encodeURIComponent(consensusTimestamp)}/versions`
|
|
3468
|
+
);
|
|
3469
|
+
}
|
|
3470
|
+
/** Deprecate a published rule (owner-only). */
|
|
3471
|
+
async deprecate(consensusTimestamp) {
|
|
3472
|
+
return this.http.post(
|
|
3473
|
+
`/api/rules/${encodeURIComponent(consensusTimestamp)}/deprecate`,
|
|
3474
|
+
{}
|
|
3475
|
+
);
|
|
3476
|
+
}
|
|
3477
|
+
};
|
|
3478
|
+
|
|
3479
|
+
// src/baas/entities/client.ts
|
|
3480
|
+
var EntitiesClient = class {
|
|
3481
|
+
constructor(http) {
|
|
3482
|
+
this.http = http;
|
|
3483
|
+
}
|
|
3484
|
+
http;
|
|
3485
|
+
/** Create a canonical token entity bound to a published rule. */
|
|
3486
|
+
async createToken(req) {
|
|
3487
|
+
return this.http.post("/api/entities/createToken", req);
|
|
3488
|
+
}
|
|
3489
|
+
/** Create a canonical account entity bound to a published rule. */
|
|
3490
|
+
async createAccount(req) {
|
|
3491
|
+
return this.http.post("/api/entities/createAccount", req);
|
|
3492
|
+
}
|
|
3493
|
+
/** Create a canonical topic entity bound to a published rule. */
|
|
3494
|
+
async createTopic(req) {
|
|
3495
|
+
return this.http.post("/api/entities/createTopic", req);
|
|
3496
|
+
}
|
|
3497
|
+
/** Create a canonical agent entity bound to a published rule. */
|
|
3498
|
+
async createAgent(req) {
|
|
3499
|
+
return this.http.post("/api/entities/createAgent", req);
|
|
3500
|
+
}
|
|
3501
|
+
/**
|
|
3502
|
+
* Mega-helper: build a token rule with a launchpad ModuleEntry attached,
|
|
3503
|
+
* publish it, create the token, and return the combined result in one HTTP
|
|
3504
|
+
* round-trip.
|
|
3505
|
+
*/
|
|
3506
|
+
async launchpad(req) {
|
|
3507
|
+
return this.http.post("/api/entities/launchpad", req);
|
|
3508
|
+
}
|
|
3509
|
+
/** Fetch an entity by its canonical `entityId`. */
|
|
3510
|
+
async get(entityId) {
|
|
3511
|
+
return this.http.get(`/api/entities/${encodeURIComponent(entityId)}`);
|
|
3512
|
+
}
|
|
3513
|
+
/** List entities owned by the authenticated wallet, optionally filtered by type. */
|
|
3514
|
+
async listByOwner(filter) {
|
|
3515
|
+
const path = filter?.type ? `/api/entities?type=${encodeURIComponent(filter.type)}` : "/api/entities";
|
|
3516
|
+
return this.http.get(path);
|
|
3517
|
+
}
|
|
3518
|
+
};
|
|
3519
|
+
|
|
3457
3520
|
// src/baas/client.ts
|
|
3458
|
-
var BaasClient = class {
|
|
3521
|
+
var BaasClient = class _BaasClient {
|
|
3459
3522
|
hostUrl;
|
|
3460
3523
|
pathPrefix;
|
|
3461
3524
|
appId;
|
|
@@ -3480,6 +3543,10 @@ var BaasClient = class {
|
|
|
3480
3543
|
agents;
|
|
3481
3544
|
/** Customer→smart-app session bridge (TokenGate Face B). */
|
|
3482
3545
|
customerSession;
|
|
3546
|
+
/** Canonical validator-rules authoring surface (publish/get/list/simulate). */
|
|
3547
|
+
rules;
|
|
3548
|
+
/** Canonical entity authoring surface (token/account/topic/agent + launchpad). */
|
|
3549
|
+
entities;
|
|
3483
3550
|
constructor(config) {
|
|
3484
3551
|
this.allowInsecure = config.allowInsecure ?? false;
|
|
3485
3552
|
this.hostUrl = validateUrl2(config.hostUrl, this.allowInsecure);
|
|
@@ -3500,6 +3567,84 @@ var BaasClient = class {
|
|
|
3500
3567
|
this.deployment = new DeploymentClient(this.http);
|
|
3501
3568
|
this.agents = new AgentsClient(this.http);
|
|
3502
3569
|
this.customerSession = new CustomerSessionClient(baseUrlWithPrefix, this.timeout);
|
|
3570
|
+
this.rules = new RulesClient(this.http);
|
|
3571
|
+
this.entities = new EntitiesClient(this.http);
|
|
3572
|
+
}
|
|
3573
|
+
/**
|
|
3574
|
+
* Connect to the Smart Engines BaaS via cluster auto-discovery.
|
|
3575
|
+
*
|
|
3576
|
+
* Zero-config entrypoint flow:
|
|
3577
|
+
*
|
|
3578
|
+
* 1. Resolves the bootstrap seed list:
|
|
3579
|
+
* - `network: 'testnet' | 'mainnet'` → canonical Cloudflare-fronted
|
|
3580
|
+
* gateway via {@link KNOWN_NETWORKS}.
|
|
3581
|
+
* - `bootstrap: string[]` → explicit seed list (private deployments).
|
|
3582
|
+
* 2. Fetches `GET /api/v3/discovery/clusters` from the first reachable
|
|
3583
|
+
* seed; the response carries every active cluster's gateway URL.
|
|
3584
|
+
* 3. Random-picks one active cluster.
|
|
3585
|
+
* 4. Returns a `BaasClient` pointed at that cluster's gatewayUrl, with
|
|
3586
|
+
* `pathPrefix: '/host'` so all BaaS sub-clients (db / storage /
|
|
3587
|
+
* functions / messaging / agents / rules / entities) route through
|
|
3588
|
+
* the gateway's `/host/*` rewrite.
|
|
3589
|
+
*
|
|
3590
|
+
* @example Zero-config (recommended)
|
|
3591
|
+
* ```ts
|
|
3592
|
+
* const baas = await BaasClient.connectToCluster({
|
|
3593
|
+
* network: 'testnet',
|
|
3594
|
+
* appId: 'app_abc',
|
|
3595
|
+
* });
|
|
3596
|
+
*
|
|
3597
|
+
* await baas.db.insert('users', { name: 'Alice' });
|
|
3598
|
+
* ```
|
|
3599
|
+
*
|
|
3600
|
+
* @example Custom seeds (private deployments)
|
|
3601
|
+
* ```ts
|
|
3602
|
+
* const baas = await BaasClient.connectToCluster({
|
|
3603
|
+
* bootstrap: ['https://gateway.my-private-net.example'],
|
|
3604
|
+
* appId: 'app_abc',
|
|
3605
|
+
* });
|
|
3606
|
+
* ```
|
|
3607
|
+
*
|
|
3608
|
+
* @throws {BaasError} `503` when no cluster is reachable via any seed.
|
|
3609
|
+
* @throws {BaasError} `400` when bootstrap resolution yields an empty list
|
|
3610
|
+
* (only possible when the caller passes an empty array explicitly).
|
|
3611
|
+
*/
|
|
3612
|
+
static async connectToCluster(config) {
|
|
3613
|
+
const allowInsecure = config.allowInsecure ?? false;
|
|
3614
|
+
const bootstrap = config.bootstrap ? [...config.bootstrap] : [...resolveNetwork(config.network).bootstrap];
|
|
3615
|
+
if (bootstrap.length === 0) {
|
|
3616
|
+
throw new BaasError(
|
|
3617
|
+
"connectToCluster requires either a non-empty `bootstrap` list or a known `network` name.",
|
|
3618
|
+
400
|
|
3619
|
+
);
|
|
3620
|
+
}
|
|
3621
|
+
const discovery = new ClusterDiscoveryClient({
|
|
3622
|
+
bootstrap,
|
|
3623
|
+
allowInsecure,
|
|
3624
|
+
trustAnchor: config.trustAnchor ? {
|
|
3625
|
+
network: config.trustAnchor.network,
|
|
3626
|
+
registryTopicId: config.trustAnchor.registryTopicId,
|
|
3627
|
+
mirrorNodeUrl: config.trustAnchor.mirrorNodeUrl,
|
|
3628
|
+
allowInsecure
|
|
3629
|
+
} : void 0
|
|
3630
|
+
});
|
|
3631
|
+
const cluster = await discovery.getRandomCluster();
|
|
3632
|
+
if (!cluster) {
|
|
3633
|
+
throw new BaasError(
|
|
3634
|
+
"No active clusters available via bootstrap seeds. Check network reachability or bootstrap URLs.",
|
|
3635
|
+
503
|
|
3636
|
+
);
|
|
3637
|
+
}
|
|
3638
|
+
return new _BaasClient({
|
|
3639
|
+
hostUrl: cluster.endpoints.gatewayUrl,
|
|
3640
|
+
appId: config.appId,
|
|
3641
|
+
appName: config.appName,
|
|
3642
|
+
timeout: config.timeout,
|
|
3643
|
+
allowInsecure,
|
|
3644
|
+
// BaaS traffic is gateway-routed at `/host/*` by default. Callers
|
|
3645
|
+
// pointing at a bare host can override with `pathPrefix: ''`.
|
|
3646
|
+
pathPrefix: config.pathPrefix ?? "/host"
|
|
3647
|
+
});
|
|
3503
3648
|
}
|
|
3504
3649
|
/** Set the app ID (for newly registered apps) */
|
|
3505
3650
|
setAppId(appId) {
|
|
@@ -3513,6 +3658,16 @@ var BaasClient = class {
|
|
|
3513
3658
|
getAppId() {
|
|
3514
3659
|
return this.appId;
|
|
3515
3660
|
}
|
|
3661
|
+
/**
|
|
3662
|
+
* Get the configured host URL. After
|
|
3663
|
+
* {@link BaasClient.connectToCluster} this is the gateway URL of the
|
|
3664
|
+
* cluster the SDK landed on after random-pick — useful for logging,
|
|
3665
|
+
* "behind the curtain" UIs, or debugging which cluster is serving a
|
|
3666
|
+
* given request.
|
|
3667
|
+
*/
|
|
3668
|
+
getHostUrl() {
|
|
3669
|
+
return this.hostUrl;
|
|
3670
|
+
}
|
|
3516
3671
|
/**
|
|
3517
3672
|
* Get HTTP resilience health information
|
|
3518
3673
|
* @returns Object with circuit breaker state and last error (if any)
|
|
@@ -3662,6 +3817,9 @@ function validateUrl2(url, allowInsecure = false) {
|
|
|
3662
3817
|
|
|
3663
3818
|
// src/nestjs/smart-engine.service.ts
|
|
3664
3819
|
var SMART_ENGINE_CONFIG = "SMART_ENGINE_CONFIG";
|
|
3820
|
+
var SDK_BAAS_CLIENT = "SDK_BAAS_CLIENT";
|
|
3821
|
+
var RULES_CLIENT = "RULES_CLIENT";
|
|
3822
|
+
var ENTITIES_CLIENT = "ENTITIES_CLIENT";
|
|
3665
3823
|
exports.SmartEngineService = class SmartEngineService {
|
|
3666
3824
|
constructor(config) {
|
|
3667
3825
|
this.config = config;
|
|
@@ -3744,7 +3902,7 @@ exports.SmartEngineService = class SmartEngineService {
|
|
|
3744
3902
|
*/
|
|
3745
3903
|
getClient() {
|
|
3746
3904
|
if (!this.client) {
|
|
3747
|
-
throw new
|
|
3905
|
+
throw new SmartEngineError(
|
|
3748
3906
|
"SmartEngineClient not initialized. Ensure SmartEngineService is configured properly.",
|
|
3749
3907
|
500
|
|
3750
3908
|
);
|
|
@@ -3761,7 +3919,7 @@ exports.SmartEngineService = class SmartEngineService {
|
|
|
3761
3919
|
*/
|
|
3762
3920
|
getBaasClient() {
|
|
3763
3921
|
if (!this.baasClient) {
|
|
3764
|
-
throw new
|
|
3922
|
+
throw new SmartEngineError(
|
|
3765
3923
|
"BaasClient not initialized. Ensure SmartEngineService is configured properly.",
|
|
3766
3924
|
500
|
|
3767
3925
|
);
|
|
@@ -3875,9 +4033,15 @@ exports.SmartEngineModule = class SmartEngineModule {
|
|
|
3875
4033
|
provide: SMART_ENGINE_CONFIG,
|
|
3876
4034
|
useValue: config
|
|
3877
4035
|
},
|
|
3878
|
-
exports.SmartEngineService
|
|
4036
|
+
exports.SmartEngineService,
|
|
4037
|
+
...this.createBaasProviders()
|
|
3879
4038
|
],
|
|
3880
|
-
exports: [
|
|
4039
|
+
exports: [
|
|
4040
|
+
exports.SmartEngineService,
|
|
4041
|
+
SDK_BAAS_CLIENT,
|
|
4042
|
+
RULES_CLIENT,
|
|
4043
|
+
ENTITIES_CLIENT
|
|
4044
|
+
]
|
|
3881
4045
|
};
|
|
3882
4046
|
}
|
|
3883
4047
|
/**
|
|
@@ -3893,10 +4057,48 @@ exports.SmartEngineModule = class SmartEngineModule {
|
|
|
3893
4057
|
module: exports.SmartEngineModule,
|
|
3894
4058
|
global: options.isGlobal ?? true,
|
|
3895
4059
|
imports: options.imports || [],
|
|
3896
|
-
providers: [
|
|
3897
|
-
|
|
4060
|
+
providers: [
|
|
4061
|
+
...asyncProviders,
|
|
4062
|
+
exports.SmartEngineService,
|
|
4063
|
+
...this.createBaasProviders()
|
|
4064
|
+
],
|
|
4065
|
+
exports: [
|
|
4066
|
+
exports.SmartEngineService,
|
|
4067
|
+
SDK_BAAS_CLIENT,
|
|
4068
|
+
RULES_CLIENT,
|
|
4069
|
+
ENTITIES_CLIENT
|
|
4070
|
+
]
|
|
3898
4071
|
};
|
|
3899
4072
|
}
|
|
4073
|
+
/**
|
|
4074
|
+
* Build the BaaS SDK providers — the full `BaasClient` and its `rules` /
|
|
4075
|
+
* `entities` sub-clients — all bound to dedicated injection tokens. Wired
|
|
4076
|
+
* into both `forRoot` and `forRootAsync` so consumers can
|
|
4077
|
+
* `@Inject(RULES_CLIENT) rules: RulesClient` directly.
|
|
4078
|
+
*/
|
|
4079
|
+
static createBaasProviders() {
|
|
4080
|
+
return [
|
|
4081
|
+
{
|
|
4082
|
+
provide: SDK_BAAS_CLIENT,
|
|
4083
|
+
useFactory: (config) => new BaasClient({
|
|
4084
|
+
hostUrl: config.baseUrl,
|
|
4085
|
+
timeout: config.timeout,
|
|
4086
|
+
allowInsecure: config.allowInsecure
|
|
4087
|
+
}),
|
|
4088
|
+
inject: [SMART_ENGINE_CONFIG]
|
|
4089
|
+
},
|
|
4090
|
+
{
|
|
4091
|
+
provide: RULES_CLIENT,
|
|
4092
|
+
useFactory: (baas) => baas.rules,
|
|
4093
|
+
inject: [SDK_BAAS_CLIENT]
|
|
4094
|
+
},
|
|
4095
|
+
{
|
|
4096
|
+
provide: ENTITIES_CLIENT,
|
|
4097
|
+
useFactory: (baas) => baas.entities,
|
|
4098
|
+
inject: [SDK_BAAS_CLIENT]
|
|
4099
|
+
}
|
|
4100
|
+
];
|
|
4101
|
+
}
|
|
3900
4102
|
/**
|
|
3901
4103
|
* Create async providers based on configuration options
|
|
3902
4104
|
*/
|
|
@@ -3941,6 +4143,12 @@ exports.SmartEngineModule = __decorateClass([
|
|
|
3941
4143
|
common.Module({})
|
|
3942
4144
|
], exports.SmartEngineModule);
|
|
3943
4145
|
|
|
4146
|
+
exports.ENTITIES_CLIENT = ENTITIES_CLIENT;
|
|
4147
|
+
exports.EntitiesClient = EntitiesClient;
|
|
4148
|
+
exports.RULES_CLIENT = RULES_CLIENT;
|
|
4149
|
+
exports.RulesClient = RulesClient;
|
|
4150
|
+
exports.SDK_BAAS_CLIENT = SDK_BAAS_CLIENT;
|
|
3944
4151
|
exports.SMART_ENGINE_CONFIG = SMART_ENGINE_CONFIG;
|
|
4152
|
+
exports.SdkBaasClient = BaasClient;
|
|
3945
4153
|
//# sourceMappingURL=index.js.map
|
|
3946
4154
|
//# sourceMappingURL=index.js.map
|