@hsuite/smart-engines-sdk 3.0.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.
@@ -0,0 +1,3338 @@
1
+ 'use strict';
2
+
3
+ var common = require('@nestjs/common');
4
+ var zod = require('zod');
5
+
6
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
+ var __decorateClass = (decorators, target, key, kind) => {
8
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
9
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
10
+ if (decorator = decorators[i])
11
+ result = (decorator(result)) || result;
12
+ return result;
13
+ };
14
+ var __decorateParam = (index, decorator) => (target, key) => decorator(target, key, index);
15
+ var ChainTypeSchema = zod.z.enum([
16
+ "hedera",
17
+ "xrpl",
18
+ "polkadot",
19
+ "solana",
20
+ "stellar",
21
+ "ethereum",
22
+ "polygon",
23
+ "bitcoin",
24
+ "cardano"
25
+ ]);
26
+ var NetworkTypeSchema = zod.z.enum(["mainnet", "testnet", "devnet", "local"]);
27
+ zod.z.object({
28
+ chain: ChainTypeSchema,
29
+ network: NetworkTypeSchema,
30
+ nativeCurrency: zod.z.object({
31
+ name: zod.z.string(),
32
+ symbol: zod.z.string(),
33
+ decimals: zod.z.number().int().min(0)
34
+ }),
35
+ blockTime: zod.z.number().optional(),
36
+ rpcEndpoint: zod.z.string().url().optional()
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
+ var TokenCapabilitiesSchema = zod.z.object({
62
+ /**
63
+ * Pause all token operations globally
64
+ * - Hedera: Adds pauseKey to token
65
+ * - XRPL: Enables GlobalFreeze flag on issuer account
66
+ */
67
+ pausable: zod.z.boolean().default(false),
68
+ /**
69
+ * Freeze/restrict specific accounts from transacting
70
+ * - Hedera: Adds freezeKey to token
71
+ * - XRPL: Enables trust line freeze capability
72
+ */
73
+ restrictable: zod.z.boolean().default(false),
74
+ /**
75
+ * KYC/compliance controls for accounts
76
+ * - Hedera: Adds kycKey to token
77
+ * - XRPL: Requires authorized trust lines (RequireAuth)
78
+ */
79
+ compliant: zod.z.boolean().default(false),
80
+ /**
81
+ * Force remove tokens from accounts (compliance wipe)
82
+ * - Hedera: Adds wipeKey to token
83
+ * - XRPL: Enables clawback (lsfAllowTrustLineClawback)
84
+ */
85
+ wipeable: zod.z.boolean().default(false),
86
+ /**
87
+ * Mint additional supply after creation
88
+ * - Hedera: Adds supplyKey to token
89
+ * - XRPL: Issuer can always issue more via Payment
90
+ */
91
+ mintable: zod.z.boolean().default(true),
92
+ /**
93
+ * Burn tokens (reduce supply)
94
+ * - Hedera: Requires supplyKey
95
+ * - XRPL: Send back to issuer (reduces supply)
96
+ */
97
+ burnable: zod.z.boolean().default(true),
98
+ /**
99
+ * Allow transfers between accounts
100
+ * - All chains: Generally always supported
101
+ */
102
+ transferable: zod.z.boolean().default(true)
103
+ });
104
+ var AccountIdSchema = zod.z.string().min(1);
105
+ zod.z.object({
106
+ accountId: AccountIdSchema,
107
+ balance: zod.z.string(),
108
+ // String to handle large numbers and decimals
109
+ chain: ChainTypeSchema,
110
+ publicKey: zod.z.string().optional(),
111
+ metadata: zod.z.record(zod.z.any()).optional(),
112
+ createdAt: zod.z.date().optional(),
113
+ updatedAt: zod.z.date().optional()
114
+ });
115
+ zod.z.object({
116
+ accountId: AccountIdSchema,
117
+ chain: ChainTypeSchema,
118
+ nativeBalance: zod.z.string(),
119
+ tokens: zod.z.array(
120
+ zod.z.object({
121
+ tokenId: zod.z.string(),
122
+ balance: zod.z.string(),
123
+ decimals: zod.z.number().int().min(0),
124
+ symbol: zod.z.string().optional()
125
+ })
126
+ ).optional(),
127
+ timestamp: zod.z.date()
128
+ });
129
+ var SecurityModeSchema = zod.z.enum(["none", "partial", "full"]);
130
+ var sovereigntyRefinePredicate = (v) => {
131
+ if (v.securityMode === "partial") {
132
+ return !!v.entityId && !!v.appOwnerPublicKey;
133
+ }
134
+ if (v.securityMode === "full") {
135
+ return !!v.entityId;
136
+ }
137
+ return true;
138
+ };
139
+ var SOVEREIGNTY_REFINE_MESSAGE = "securityMode='partial' requires entityId+appOwnerPublicKey; 'full' requires entityId";
140
+ var SovereigntyFieldsRawSchema = zod.z.object({
141
+ securityMode: SecurityModeSchema.default("none"),
142
+ entityId: zod.z.string().optional(),
143
+ appOwnerPublicKey: zod.z.string().optional()
144
+ });
145
+ SovereigntyFieldsRawSchema.refine(sovereigntyRefinePredicate, { message: SOVEREIGNTY_REFINE_MESSAGE });
146
+ var HederaKeyShapeSchema = zod.z.lazy(
147
+ () => zod.z.union([
148
+ zod.z.object({ type: zod.z.literal("ed25519"), key: zod.z.string() }),
149
+ zod.z.object({
150
+ type: zod.z.literal("keyList"),
151
+ threshold: zod.z.number().int().nonnegative(),
152
+ keys: zod.z.array(HederaKeyShapeSchema)
153
+ })
154
+ ])
155
+ );
156
+ var HederaAuthorizationSetShapeSchema = zod.z.object({
157
+ chain: zod.z.literal("hedera"),
158
+ adminKey: HederaKeyShapeSchema,
159
+ supplyKey: HederaKeyShapeSchema.optional(),
160
+ freezeKey: HederaKeyShapeSchema.optional(),
161
+ wipeKey: HederaKeyShapeSchema.optional(),
162
+ pauseKey: HederaKeyShapeSchema.optional(),
163
+ kycKey: HederaKeyShapeSchema.optional()
164
+ });
165
+ var XrplAuthorizationSetShapeSchema = zod.z.object({
166
+ chain: zod.z.literal("xrpl"),
167
+ signerEntries: zod.z.array(
168
+ zod.z.object({
169
+ account: zod.z.string(),
170
+ weight: zod.z.number().int().nonnegative()
171
+ })
172
+ ),
173
+ signerQuorum: zod.z.number().int().nonnegative(),
174
+ masterDisabled: zod.z.boolean()
175
+ });
176
+ var StellarAuthorizationSetShapeSchema = zod.z.object({
177
+ chain: zod.z.literal("stellar"),
178
+ signers: zod.z.array(
179
+ zod.z.object({
180
+ key: zod.z.string(),
181
+ weight: zod.z.number().int().nonnegative()
182
+ })
183
+ ),
184
+ thresholds: zod.z.object({
185
+ low: zod.z.number().int().nonnegative(),
186
+ med: zod.z.number().int().nonnegative(),
187
+ high: zod.z.number().int().nonnegative()
188
+ }),
189
+ masterWeight: zod.z.number().int().nonnegative()
190
+ });
191
+ var PolkadotSignatoryShapeSchema = zod.z.lazy(
192
+ () => zod.z.union([
193
+ zod.z.object({ type: zod.z.literal("account"), address: zod.z.string() }),
194
+ zod.z.object({
195
+ type: zod.z.literal("multisig"),
196
+ address: zod.z.string(),
197
+ threshold: zod.z.number().int().positive(),
198
+ signatories: zod.z.array(PolkadotSignatoryShapeSchema)
199
+ })
200
+ ])
201
+ );
202
+ var PolkadotAuthorizationSetShapeSchema = zod.z.object({
203
+ chain: zod.z.literal("polkadot"),
204
+ address: zod.z.string(),
205
+ signatory: PolkadotSignatoryShapeSchema,
206
+ ss58Format: zod.z.number().int().nonnegative()
207
+ });
208
+ var PreparedTransactionAuthorizationSetSchema = zod.z.discriminatedUnion("chain", [
209
+ HederaAuthorizationSetShapeSchema,
210
+ XrplAuthorizationSetShapeSchema,
211
+ StellarAuthorizationSetShapeSchema,
212
+ PolkadotAuthorizationSetShapeSchema
213
+ ]);
214
+ var PreparedTransactionSovereigntySchema = zod.z.discriminatedUnion("mode", [
215
+ zod.z.object({ mode: zod.z.literal("none") }),
216
+ zod.z.object({
217
+ mode: zod.z.literal("partial"),
218
+ entityId: zod.z.string(),
219
+ validatorPublicKeys: zod.z.array(zod.z.string()),
220
+ authorizationSet: PreparedTransactionAuthorizationSetSchema.optional()
221
+ }),
222
+ zod.z.object({
223
+ mode: zod.z.literal("full"),
224
+ entityId: zod.z.string(),
225
+ validatorPublicKeys: zod.z.array(zod.z.string()),
226
+ authorizationSet: PreparedTransactionAuthorizationSetSchema.optional()
227
+ })
228
+ ]);
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
+ var CreateAccountRequestSchema = zod.z.object({
298
+ chain: ChainTypeSchema,
299
+ initialBalance: zod.z.string(),
300
+ publicKey: zod.z.string().optional(),
301
+ memo: zod.z.string().optional(),
302
+ /**
303
+ * Who pays the chain fee for this transaction. Resolution happens in the
304
+ * controller layer (`resolvePayerAccountId`): explicit `payerAccountId`
305
+ * wins, else the JWT-authenticated smart-app's wallet address, else the
306
+ * request is rejected with 400. The validator **never** silently falls
307
+ * back to its own operator account.
308
+ */
309
+ payerAccountId: zod.z.string().optional(),
310
+ /**
311
+ * HCS consensus timestamp of the validator rules (REQUIRED).
312
+ * Format: "1766490325.123456789"
313
+ */
314
+ validatorTimestamp: zod.z.string().min(1, "validatorTimestamp is required"),
315
+ /**
316
+ * HCS topic ID where validator rules are stored (REQUIRED).
317
+ */
318
+ validatorTopicId: zod.z.string().min(1, "validatorTopicId is required"),
319
+ /**
320
+ * Whether to remove admin key after creation (makes entity immutable).
321
+ * Default: true for production-grade immutability.
322
+ */
323
+ immutable: zod.z.boolean().default(true),
324
+ /**
325
+ * Smart node security mode for the account key structure.
326
+ * - 'none': Owner-only key (no validator involvement)
327
+ * - 'partial': threshold(2, [appOwnerKey, tssKeyList]) — co-control
328
+ * - 'full': TSS KeyList only — full validator network control
329
+ * Default: 'none' for basic account creation via SDK.
330
+ */
331
+ securityMode: zod.z.enum(["none", "partial", "full"]).default("none"),
332
+ /**
333
+ * App owner's public key (required for 'partial' security mode).
334
+ * The owner key + TSS network key form a threshold-2 multi-sig.
335
+ */
336
+ appOwnerPublicKey: zod.z.string().optional(),
337
+ metadata: zod.z.record(zod.z.any()).optional()
338
+ });
339
+ zod.z.object({
340
+ accountId: AccountIdSchema,
341
+ publicKey: zod.z.string().optional(),
342
+ privateKey: zod.z.string().optional(),
343
+ // Only returned on creation, store securely!
344
+ transactionId: zod.z.string(),
345
+ chain: ChainTypeSchema,
346
+ timestamp: zod.z.date().optional()
347
+ });
348
+ var TransferRequestSchema = zod.z.object({
349
+ chain: ChainTypeSchema,
350
+ from: AccountIdSchema,
351
+ to: AccountIdSchema,
352
+ amount: zod.z.string(),
353
+ tokenId: zod.z.string().optional(),
354
+ // undefined = native token
355
+ memo: zod.z.string().optional(),
356
+ /** See CreateAccountRequestSchema.payerAccountId — same resolution rules. */
357
+ payerAccountId: zod.z.string().optional(),
358
+ metadata: zod.z.record(zod.z.any()).optional()
359
+ });
360
+ zod.z.object({
361
+ transactionId: zod.z.string(),
362
+ status: zod.z.enum(["pending", "success", "failed"]),
363
+ chain: ChainTypeSchema,
364
+ fee: zod.z.string().optional(),
365
+ timestamp: zod.z.date().optional()
366
+ });
367
+ zod.z.object({
368
+ chain: ChainTypeSchema,
369
+ accountId: AccountIdSchema
370
+ });
371
+ zod.z.object({
372
+ chain: ChainTypeSchema,
373
+ transactionId: zod.z.string()
374
+ });
375
+ var CreateTokenRequestSchema = zod.z.object({
376
+ chain: ChainTypeSchema,
377
+ name: zod.z.string().min(1).max(100),
378
+ symbol: zod.z.string().min(1).max(10),
379
+ decimals: zod.z.number().int().min(0).max(18),
380
+ initialSupply: zod.z.string(),
381
+ type: zod.z.enum(["fungible", "nft"]),
382
+ treasury: AccountIdSchema.optional(),
383
+ /**
384
+ * Token capabilities define what operations the token supports.
385
+ * These are validated against chain support and translated to native implementations.
386
+ *
387
+ * @example
388
+ * ```typescript
389
+ * capabilities: {
390
+ * pausable: true, // Hedera: pauseKey, XRPL: GlobalFreeze
391
+ * restrictable: true, // Hedera: freezeKey, XRPL: TrustLineFreeze
392
+ * compliant: true, // Hedera: kycKey, XRPL: RequireAuth
393
+ * wipeable: true, // Hedera: wipeKey, XRPL: Clawback
394
+ * mintable: true, // Allow additional minting
395
+ * burnable: true, // Allow burning
396
+ * }
397
+ * ```
398
+ */
399
+ capabilities: TokenCapabilitiesSchema.optional().default({
400
+ pausable: false,
401
+ restrictable: false,
402
+ compliant: false,
403
+ wipeable: false,
404
+ mintable: true,
405
+ burnable: true,
406
+ transferable: true
407
+ }),
408
+ /**
409
+ * HCS consensus timestamp of the validator rules (REQUIRED).
410
+ * Format: "1766490325.123456789"
411
+ */
412
+ validatorTimestamp: zod.z.string().min(1, "validatorTimestamp is required"),
413
+ /**
414
+ * HCS topic ID where validator rules are stored (REQUIRED).
415
+ */
416
+ validatorTopicId: zod.z.string().min(1, "validatorTopicId is required"),
417
+ /**
418
+ * Whether to remove admin key after creation (makes entity immutable).
419
+ * Default: true for production-grade immutability.
420
+ */
421
+ immutable: zod.z.boolean().default(true),
422
+ /** See CreateAccountRequestSchema.payerAccountId — same resolution rules. */
423
+ payerAccountId: zod.z.string().optional(),
424
+ metadata: zod.z.record(zod.z.any()).optional()
425
+ });
426
+ zod.z.object({
427
+ tokenId: zod.z.string(),
428
+ transactionId: zod.z.string(),
429
+ chain: ChainTypeSchema,
430
+ timestamp: zod.z.date().optional()
431
+ });
432
+ var MintTokenRequestSchema = zod.z.object({
433
+ chain: ChainTypeSchema,
434
+ tokenId: zod.z.string(),
435
+ /** Amount to mint (fungible tokens). Ignored for NFTs. */
436
+ amount: zod.z.string().optional(),
437
+ /** Recipient account (fungible: transfer after mint; NFT: Hedera mints to treasury). */
438
+ recipient: AccountIdSchema.optional(),
439
+ /**
440
+ * NFT metadata entries — one per NFT to mint.
441
+ * Each entry becomes on-chain metadata (e.g. IPFS CID, encoded memo).
442
+ * On Hedera: passed to TokenMintTransaction.setMetadata().
443
+ * On XRPL: used as URI in NFTokenMint.
444
+ */
445
+ nftMetadata: zod.z.array(zod.z.string()).optional(),
446
+ /** Additional chain-specific options. */
447
+ metadata: zod.z.record(zod.z.any()).optional(),
448
+ /** See CreateAccountRequestSchema.payerAccountId — same resolution rules. */
449
+ payerAccountId: zod.z.string().optional()
450
+ });
451
+ var BurnTokenRequestSchema = zod.z.object({
452
+ chain: ChainTypeSchema,
453
+ tokenId: zod.z.string(),
454
+ amount: zod.z.string(),
455
+ /** See CreateAccountRequestSchema.payerAccountId — same resolution rules. */
456
+ payerAccountId: zod.z.string().optional(),
457
+ metadata: zod.z.record(zod.z.any()).optional()
458
+ });
459
+ var TokenActionRequestSchema = zod.z.object({
460
+ chain: ChainTypeSchema,
461
+ tokenId: zod.z.string(),
462
+ accountId: AccountIdSchema.optional(),
463
+ // Required for account-specific actions
464
+ amount: zod.z.string().optional(),
465
+ // Required for wipe action
466
+ /** See CreateAccountRequestSchema.payerAccountId — same resolution rules. */
467
+ payerAccountId: zod.z.string().optional(),
468
+ metadata: zod.z.record(zod.z.any()).optional()
469
+ });
470
+ var ActionResultSchema = zod.z.object({
471
+ success: zod.z.boolean(),
472
+ transactionId: zod.z.string(),
473
+ chain: ChainTypeSchema,
474
+ /** The native chain operation that was executed */
475
+ chainOperation: zod.z.string(),
476
+ /** Additional context or notes about the operation */
477
+ notes: zod.z.array(zod.z.string()).optional(),
478
+ /** Timestamp of the operation */
479
+ timestamp: zod.z.date().optional()
480
+ });
481
+ ActionResultSchema.extend({
482
+ tokenId: zod.z.string(),
483
+ /** The capabilities that were enabled for this token */
484
+ enabledCapabilities: zod.z.array(zod.z.string())
485
+ });
486
+ var ValidatorSignatureSchema = zod.z.object({
487
+ /** Validator's node ID */
488
+ validatorId: zod.z.string(),
489
+ /** Validator's public key (hex-encoded) */
490
+ publicKey: zod.z.string(),
491
+ /** Signature over the transaction bytes (hex-encoded) */
492
+ signature: zod.z.string(),
493
+ /** When this signature was created */
494
+ signedAt: zod.z.date(),
495
+ /** Signature algorithm used */
496
+ algorithm: zod.z.enum(["ed25519", "ecdsa-secp256k1", "bls12-381"]).optional()
497
+ });
498
+ var HederaPreparedMetadataSchema = zod.z.object({
499
+ /** Hedera node account IDs that will process this transaction */
500
+ nodeAccountIds: zod.z.array(zod.z.string()).optional(),
501
+ /** Maximum transaction fee in tinybars */
502
+ maxTransactionFee: zod.z.string().optional(),
503
+ /** Transaction memo */
504
+ memo: zod.z.string().optional(),
505
+ /** Schedule info if this is a scheduled transaction */
506
+ scheduleInfo: zod.z.object({
507
+ scheduleId: zod.z.string(),
508
+ adminKey: zod.z.string().optional()
509
+ }).optional()
510
+ });
511
+ var XRPLPreparedMetadataSchema = zod.z.object({
512
+ /** Sequence number for this transaction */
513
+ sequence: zod.z.number().optional(),
514
+ /** Last ledger sequence for expiration */
515
+ lastLedgerSequence: zod.z.number().optional(),
516
+ /** Signer list info for multi-sig */
517
+ signerList: zod.z.array(
518
+ zod.z.object({
519
+ account: zod.z.string(),
520
+ signerWeight: zod.z.number()
521
+ })
522
+ ).optional(),
523
+ /** Quorum weight required */
524
+ signerQuorum: zod.z.number().optional()
525
+ });
526
+ var SolanaPreparedMetadataSchema = zod.z.object({
527
+ /** Recent blockhash for transaction validity */
528
+ recentBlockhash: zod.z.string().optional(),
529
+ /** Fee payer account */
530
+ feePayer: zod.z.string().optional(),
531
+ /** Program IDs involved */
532
+ programIds: zod.z.array(zod.z.string()).optional(),
533
+ /** Squads v4 multisig PDA address (partial/full modes) */
534
+ squadsMultisigPda: zod.z.string().optional(),
535
+ /** Squads v4 vault PDA address (partial/full modes) */
536
+ squadsVaultPda: zod.z.string().optional(),
537
+ /** Index of the vault transaction proposal */
538
+ squadsTransactionIndex: zod.z.number().optional(),
539
+ /** Proposal PDA address */
540
+ squadsProposalAddress: zod.z.string().optional(),
541
+ /** Whether the multisig was created in this call (vs already existed) */
542
+ multisigCreated: zod.z.boolean().optional(),
543
+ /** Security mode used to prepare this transaction */
544
+ securityMode: zod.z.enum(["none", "partial", "full"]).optional(),
545
+ /** SPL Token mint address (token-create and all SPL operations) */
546
+ splMint: zod.z.string().optional()
547
+ });
548
+ var PolkadotPreparedMetadataSchema = zod.z.object({
549
+ /** Era for transaction mortality */
550
+ era: zod.z.string().optional(),
551
+ /** Nonce for the sender */
552
+ nonce: zod.z.number().optional(),
553
+ /** Tip for priority */
554
+ tip: zod.z.string().optional(),
555
+ /** Spec version for runtime */
556
+ specVersion: zod.z.number().optional()
557
+ });
558
+ var ChainPreparedMetadataSchema = zod.z.union([
559
+ HederaPreparedMetadataSchema,
560
+ XRPLPreparedMetadataSchema,
561
+ SolanaPreparedMetadataSchema,
562
+ PolkadotPreparedMetadataSchema,
563
+ zod.z.record(zod.z.any())
564
+ // Allow extension for future chains
565
+ ]);
566
+ zod.z.object({
567
+ /** The blockchain this transaction is for */
568
+ chain: ChainTypeSchema,
569
+ /** Type of transaction (e.g., 'TokenCreate', 'Payment', 'NFTMint') */
570
+ transactionType: zod.z.string(),
571
+ /** Pre-assigned transaction ID for tracking */
572
+ transactionId: zod.z.string(),
573
+ /** Base64-encoded frozen transaction bytes ready for submission */
574
+ transactionBytes: zod.z.string(),
575
+ /** When this prepared transaction expires */
576
+ expiresAt: zod.z.date(),
577
+ /** Validator signatures collected for this transaction */
578
+ validatorSignatures: zod.z.array(ValidatorSignatureSchema),
579
+ /** Required payer account ID (caller must fund this account) */
580
+ payerAccountId: zod.z.string().optional(),
581
+ /** Estimated network fee */
582
+ estimatedFee: zod.z.string().optional(),
583
+ /** Number of signatures required for submission */
584
+ requiredSignatures: zod.z.number().optional(),
585
+ /** Whether the transaction has enough signatures to submit */
586
+ readyToSubmit: zod.z.boolean().default(false),
587
+ /** Chain-specific metadata */
588
+ metadata: ChainPreparedMetadataSchema.optional(),
589
+ /**
590
+ * Sovereignty metadata: the mode and (for partial/full) the on-chain
591
+ * authorization set the validator is binding to. Lets smart-apps and tests
592
+ * inspect the authorization topology without decoding chain-native bytes.
593
+ */
594
+ sovereignty: PreparedTransactionSovereigntySchema.optional()
595
+ });
596
+ zod.z.object({
597
+ /** The original transaction ID */
598
+ transactionId: zod.z.string(),
599
+ /** The blockchain */
600
+ chain: ChainTypeSchema,
601
+ /** Whether submission was successful */
602
+ success: zod.z.boolean(),
603
+ /** Consensus timestamp (Hedera) or ledger/block info */
604
+ consensusTimestamp: zod.z.string().optional(),
605
+ /** Block or ledger number */
606
+ blockNumber: zod.z.number().optional(),
607
+ /** Actual fee paid */
608
+ actualFee: zod.z.string().optional(),
609
+ /** Receipt or confirmation data */
610
+ receipt: zod.z.record(zod.z.any()).optional(),
611
+ /** Error message if submission failed */
612
+ error: zod.z.string().optional()
613
+ });
614
+ zod.z.object({
615
+ chain: zod.z.literal("hedera"),
616
+ payerAccountId: zod.z.string().optional(),
617
+ name: zod.z.string().min(1).max(100),
618
+ symbol: zod.z.string().min(1).max(10),
619
+ decimals: zod.z.number().int().min(0).max(18),
620
+ initialSupply: zod.z.string(),
621
+ treasuryAccountId: zod.z.string().min(1, "treasuryAccountId is required"),
622
+ memo: zod.z.string().optional(),
623
+ tokenType: zod.z.enum(["FUNGIBLE_COMMON", "NON_FUNGIBLE_UNIQUE"]).default("FUNGIBLE_COMMON"),
624
+ supplyKey: zod.z.string().optional(),
625
+ adminKey: zod.z.string().optional(),
626
+ pauseKey: zod.z.string().optional(),
627
+ freezeKey: zod.z.string().optional(),
628
+ kycKey: zod.z.string().optional(),
629
+ wipeKey: zod.z.string().optional(),
630
+ validatorTimestamp: zod.z.string().min(1),
631
+ validatorTopicId: zod.z.string().min(1)
632
+ }).merge(SovereigntyFieldsRawSchema).refine(sovereigntyRefinePredicate, { message: SOVEREIGNTY_REFINE_MESSAGE });
633
+ zod.z.object({
634
+ chain: zod.z.literal("xrpl"),
635
+ payerAccountId: zod.z.string().optional(),
636
+ // User's XRPL account whose authorization we're configuring.
637
+ accountAddress: zod.z.string().min(25).max(34),
638
+ validatorTimestamp: zod.z.string().min(1),
639
+ validatorTopicId: zod.z.string().min(1)
640
+ }).merge(SovereigntyFieldsRawSchema).refine(sovereigntyRefinePredicate, { message: SOVEREIGNTY_REFINE_MESSAGE });
641
+ zod.z.object({
642
+ chain: zod.z.literal("stellar"),
643
+ payerAccountId: zod.z.string().optional(),
644
+ // The master public key of the new Stellar account.
645
+ publicKey: zod.z.string().min(56).max(56),
646
+ startingBalance: zod.z.string().regex(/^\d+(\.\d+)?$/),
647
+ validatorTimestamp: zod.z.string().min(1),
648
+ validatorTopicId: zod.z.string().min(1)
649
+ }).merge(SovereigntyFieldsRawSchema).refine(
650
+ (v) => {
651
+ if (v.securityMode === "partial" || v.securityMode === "full") {
652
+ return !!v.entityId;
653
+ }
654
+ return true;
655
+ },
656
+ { message: "securityMode='partial'/'full' requires entityId" }
657
+ );
658
+
659
+ // src/discovery/mirror-node.ts
660
+ function validateUrl(url, allowInsecure = false) {
661
+ try {
662
+ const parsed = new URL(url);
663
+ if (!["http:", "https:"].includes(parsed.protocol)) {
664
+ throw new Error(`Invalid protocol: ${parsed.protocol}`);
665
+ }
666
+ if (!allowInsecure && parsed.protocol !== "https:") {
667
+ throw new Error(
668
+ "HTTPS is required for secure connections. Set allowInsecure=true to override."
669
+ );
670
+ }
671
+ const hostname = parsed.hostname.toLowerCase();
672
+ const blockedPatterns = [
673
+ /^localhost$/i,
674
+ /^127\./,
675
+ /^10\./,
676
+ /^172\.(1[6-9]|2[0-9]|3[01])\./,
677
+ /^192\.168\./,
678
+ /^169\.254\./,
679
+ /^::1$/,
680
+ /^fe80:/i,
681
+ /^fc00:/i,
682
+ /^fd00:/i
683
+ ];
684
+ const isPrivate = blockedPatterns.some((pattern) => pattern.test(hostname));
685
+ if (isPrivate && !allowInsecure) {
686
+ throw new Error(
687
+ "Private/internal URLs are blocked. Set allowInsecure=true for local development."
688
+ );
689
+ }
690
+ return parsed;
691
+ } catch (error) {
692
+ if (error instanceof Error && error.message.includes("Invalid URL")) {
693
+ throw new MirrorNodeError(`Invalid URL format: ${url}`, 400);
694
+ }
695
+ throw error;
696
+ }
697
+ }
698
+ function validateTopicId(topicId) {
699
+ if (!/^\d+\.\d+\.\d+$/.test(topicId)) {
700
+ throw new MirrorNodeError(
701
+ `Invalid topic ID format: ${topicId}. Expected format: 0.0.123456`,
702
+ 400
703
+ );
704
+ }
705
+ }
706
+ var MIRROR_NODE_URLS = {
707
+ mainnet: "https://mainnet-public.mirrornode.hedera.com",
708
+ testnet: "https://testnet.mirrornode.hedera.com",
709
+ previewnet: "https://previewnet.mirrornode.hedera.com"
710
+ };
711
+ var MirrorNodeClient = class _MirrorNodeClient {
712
+ baseUrl;
713
+ timeout;
714
+ allowInsecure;
715
+ constructor(config) {
716
+ this.allowInsecure = config.allowInsecure ?? false;
717
+ const validatedUrl = validateUrl(config.baseUrl, this.allowInsecure);
718
+ this.baseUrl = validatedUrl.origin;
719
+ this.timeout = config.timeout || 3e4;
720
+ }
721
+ /**
722
+ * Create client for a specific network
723
+ */
724
+ static forNetwork(network) {
725
+ const baseUrl = MIRROR_NODE_URLS[network];
726
+ if (!baseUrl) {
727
+ throw new Error(`Unknown network: ${network}`);
728
+ }
729
+ return new _MirrorNodeClient({ baseUrl });
730
+ }
731
+ /**
732
+ * Get topic messages from mirror node
733
+ *
734
+ * @param topicId - HCS topic ID (e.g., '0.0.123456')
735
+ * @param options - Query options
736
+ * @returns Topic messages
737
+ */
738
+ async getTopicMessages(topicId, options) {
739
+ validateTopicId(topicId);
740
+ const params = new URLSearchParams();
741
+ if (options?.limit) {
742
+ params.set("limit", options.limit.toString());
743
+ }
744
+ if (options?.order) {
745
+ params.set("order", options.order);
746
+ }
747
+ if (options?.timestampStart) {
748
+ params.set("timestamp", `gte:${options.timestampStart}`);
749
+ }
750
+ if (options?.timestampEnd) {
751
+ params.set("timestamp", `lte:${options.timestampEnd}`);
752
+ }
753
+ if (options?.sequenceNumberStart) {
754
+ params.set("sequencenumber", `gte:${options.sequenceNumberStart}`);
755
+ }
756
+ const url = `${this.baseUrl}/api/v1/topics/${topicId}/messages?${params.toString()}`;
757
+ const controller = new AbortController();
758
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
759
+ try {
760
+ const response = await fetch(url, {
761
+ method: "GET",
762
+ headers: {
763
+ Accept: "application/json"
764
+ },
765
+ signal: controller.signal
766
+ });
767
+ clearTimeout(timeoutId);
768
+ if (!response.ok) {
769
+ throw new MirrorNodeError(
770
+ `Mirror node error: ${response.status} ${response.statusText}`,
771
+ response.status
772
+ );
773
+ }
774
+ const data = await response.json();
775
+ return data.messages;
776
+ } catch (error) {
777
+ clearTimeout(timeoutId);
778
+ if (error instanceof MirrorNodeError) {
779
+ throw error;
780
+ }
781
+ const err = error;
782
+ if (err.name === "AbortError") {
783
+ throw new MirrorNodeError("Mirror node request timeout", 408);
784
+ }
785
+ throw new MirrorNodeError(`Mirror node network error: ${err.message}`, 0);
786
+ }
787
+ }
788
+ /**
789
+ * Get all topic messages with pagination
790
+ *
791
+ * @param topicId - HCS topic ID
792
+ * @param maxMessages - Maximum messages to fetch (default: 1000)
793
+ * @returns All topic messages
794
+ */
795
+ async getAllTopicMessages(topicId, maxMessages = 1e3) {
796
+ validateTopicId(topicId);
797
+ const safeMaxMessages = Math.min(maxMessages, 1e4);
798
+ const allMessages = [];
799
+ let nextPath = `/api/v1/topics/${topicId}/messages?limit=100&order=desc`;
800
+ while (nextPath && allMessages.length < safeMaxMessages) {
801
+ const controller = new AbortController();
802
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
803
+ try {
804
+ const fullUrl = `${this.baseUrl}${nextPath}`;
805
+ const response = await fetch(fullUrl, {
806
+ method: "GET",
807
+ headers: { Accept: "application/json" },
808
+ signal: controller.signal
809
+ });
810
+ clearTimeout(timeoutId);
811
+ if (!response.ok) {
812
+ throw new MirrorNodeError(
813
+ `Mirror node error: ${response.status} ${response.statusText}`,
814
+ response.status
815
+ );
816
+ }
817
+ const data = await response.json();
818
+ allMessages.push(...data.messages);
819
+ if (data.links.next) {
820
+ const nextLink = data.links.next;
821
+ if (nextLink.startsWith("/api/v1/topics/")) {
822
+ nextPath = nextLink;
823
+ } else {
824
+ nextPath = void 0;
825
+ }
826
+ } else {
827
+ nextPath = void 0;
828
+ }
829
+ } catch (error) {
830
+ clearTimeout(timeoutId);
831
+ if (error instanceof MirrorNodeError) {
832
+ throw error;
833
+ }
834
+ const err = error;
835
+ throw new MirrorNodeError(`Mirror node error: ${err.message}`, 0);
836
+ }
837
+ }
838
+ return allMessages.slice(0, safeMaxMessages);
839
+ }
840
+ /**
841
+ * Decode base64 message content
842
+ */
843
+ static decodeMessage(base64Message) {
844
+ if (typeof Buffer !== "undefined") {
845
+ return Buffer.from(base64Message, "base64").toString("utf-8");
846
+ }
847
+ return atob(base64Message);
848
+ }
849
+ };
850
+ var MirrorNodeError = class extends Error {
851
+ constructor(message, statusCode) {
852
+ super(message);
853
+ this.statusCode = statusCode;
854
+ this.name = "MirrorNodeError";
855
+ }
856
+ statusCode;
857
+ };
858
+
859
+ // src/discovery/validator-discovery.ts
860
+ var ValidatorDiscoveryClient = class {
861
+ mirrorNode;
862
+ registryTopicId;
863
+ cacheTtlMs;
864
+ cache = null;
865
+ constructor(config) {
866
+ const mirrorNodeUrl = config.mirrorNodeUrl || MIRROR_NODE_URLS[config.network];
867
+ if (!mirrorNodeUrl) {
868
+ throw new Error(`Unknown network: ${config.network}`);
869
+ }
870
+ this.mirrorNode = new MirrorNodeClient({
871
+ baseUrl: mirrorNodeUrl,
872
+ allowInsecure: config.allowInsecure
873
+ });
874
+ this.registryTopicId = config.registryTopicId;
875
+ this.cacheTtlMs = config.cacheTtlMs ?? 6e4;
876
+ }
877
+ /**
878
+ * Get all active validators from the registry
879
+ *
880
+ * Results are cached for efficiency. Use `forceRefresh` to bypass cache.
881
+ *
882
+ * @param forceRefresh - Force refresh from mirror node
883
+ * @returns List of active validators
884
+ */
885
+ async getValidators(forceRefresh = false) {
886
+ if (!forceRefresh && this.cache && this.isCacheValid()) {
887
+ return this.cache.validators;
888
+ }
889
+ const messages = await this.mirrorNode.getAllTopicMessages(
890
+ this.registryTopicId,
891
+ 500
892
+ // Max messages to fetch
893
+ );
894
+ const validatorMap = /* @__PURE__ */ new Map();
895
+ const leftValidators = /* @__PURE__ */ new Set();
896
+ for (const msg of messages) {
897
+ try {
898
+ const content = MirrorNodeClient.decodeMessage(msg.message);
899
+ const raw = JSON.parse(content);
900
+ const entry = normalizeRegistryEntry(raw);
901
+ if (!entry) continue;
902
+ if (entry.messageType === "validator.leave") {
903
+ leftValidators.add(entry.nodeId);
904
+ continue;
905
+ }
906
+ if (leftValidators.has(entry.nodeId)) {
907
+ continue;
908
+ }
909
+ if (!validatorMap.has(entry.nodeId)) {
910
+ validatorMap.set(entry.nodeId, entry);
911
+ }
912
+ } catch {
913
+ continue;
914
+ }
915
+ }
916
+ const validators = Array.from(validatorMap.values());
917
+ this.cache = {
918
+ validators,
919
+ lastUpdated: Date.now()
920
+ };
921
+ return validators;
922
+ }
923
+ /**
924
+ * Get validators with API endpoints available
925
+ *
926
+ * @param forceRefresh - Force refresh from mirror node
927
+ * @returns Validators with apiEndpoint configured
928
+ */
929
+ async getValidatorsWithEndpoints(forceRefresh = false) {
930
+ const validators = await this.getValidators(forceRefresh);
931
+ return validators.filter((v) => v.networkEndpoints?.apiEndpoint);
932
+ }
933
+ /**
934
+ * Get a random validator from the registry
935
+ *
936
+ * @param forceRefresh - Force refresh from mirror node
937
+ * @returns Random validator info or null if none available
938
+ */
939
+ async getRandomValidator(forceRefresh = false) {
940
+ const validators = await this.getValidatorsWithEndpoints(forceRefresh);
941
+ if (validators.length === 0) {
942
+ return null;
943
+ }
944
+ const randomBytes = new Uint32Array(1);
945
+ crypto.getRandomValues(randomBytes);
946
+ const randomIndex = randomBytes[0] % validators.length;
947
+ return validators[randomIndex];
948
+ }
949
+ /**
950
+ * Get a random validator API endpoint URL
951
+ *
952
+ * @param forceRefresh - Force refresh from mirror node
953
+ * @returns Random validator API URL or null if none available
954
+ */
955
+ async getRandomValidatorUrl(forceRefresh = false) {
956
+ const validator = await this.getRandomValidator(forceRefresh);
957
+ return validator?.networkEndpoints?.apiEndpoint ?? null;
958
+ }
959
+ /**
960
+ * Get validator by node ID
961
+ *
962
+ * @param nodeId - Validator node ID (e.g., 'validator-1')
963
+ * @param forceRefresh - Force refresh from mirror node
964
+ * @returns Validator info or null if not found
965
+ */
966
+ async getValidatorByNodeId(nodeId, forceRefresh = false) {
967
+ const validators = await this.getValidators(forceRefresh);
968
+ return validators.find((v) => v.nodeId === nodeId) ?? null;
969
+ }
970
+ /**
971
+ * Get validators by capability
972
+ *
973
+ * @param capability - Required capability (e.g., 'hedera', 'xrpl', 'dkg')
974
+ * @param forceRefresh - Force refresh from mirror node
975
+ * @returns Validators with the specified capability
976
+ */
977
+ async getValidatorsByCapability(capability, forceRefresh = false) {
978
+ const validators = await this.getValidatorsWithEndpoints(forceRefresh);
979
+ return validators.filter((v) => v.capabilities?.includes(capability));
980
+ }
981
+ /**
982
+ * Clear the validator cache
983
+ */
984
+ clearCache() {
985
+ this.cache = null;
986
+ }
987
+ /**
988
+ * Check if cache is still valid
989
+ */
990
+ isCacheValid() {
991
+ if (!this.cache) return false;
992
+ return Date.now() - this.cache.lastUpdated < this.cacheTtlMs;
993
+ }
994
+ };
995
+ function normalizeRegistryEntry(raw) {
996
+ if (raw.messageType && typeof raw.nodeId === "string") {
997
+ return raw;
998
+ }
999
+ if (raw.type === "validator.register") {
1000
+ if (raw.validatorType && raw.validatorType !== void 0 && raw.validatorType !== null) {
1001
+ if (typeof raw.validatorType === "string" && raw.validatorType !== "node") {
1002
+ return null;
1003
+ }
1004
+ }
1005
+ const nodeId = typeof raw.validatorId === "string" && raw.validatorId || typeof raw.nodeId === "string" && raw.nodeId || null;
1006
+ if (!nodeId) return null;
1007
+ const endpoint = typeof raw.endpoint === "string" ? raw.endpoint : void 0;
1008
+ if (!endpoint) return null;
1009
+ const capabilities = Array.isArray(raw.capabilities) ? raw.capabilities.filter((c) => typeof c === "string") : void 0;
1010
+ return {
1011
+ validatorTimestamp: typeof raw.timestamp === "string" ? raw.timestamp : "",
1012
+ nodeId,
1013
+ type: "consensus",
1014
+ networkEndpoints: { apiEndpoint: endpoint },
1015
+ publicKey: typeof raw.publicKey === "string" ? raw.publicKey : void 0,
1016
+ capabilities,
1017
+ metadata: {},
1018
+ registeredAt: typeof raw.timestamp === "string" ? raw.timestamp : "",
1019
+ messageType: "validator.join"
1020
+ };
1021
+ }
1022
+ return null;
1023
+ }
1024
+
1025
+ // src/auth/validator-auth.ts
1026
+ var SUPPORTED_AUTH_CHAINS = [
1027
+ "hedera",
1028
+ "xrpl",
1029
+ "polkadot",
1030
+ "stellar",
1031
+ "solana"
1032
+ ];
1033
+ function validateValidatorUrl(url, allowInsecure = false) {
1034
+ try {
1035
+ const parsed = new URL(url);
1036
+ if (!["http:", "https:"].includes(parsed.protocol)) {
1037
+ throw new ValidatorAuthError(`Invalid protocol: ${parsed.protocol}`, 400);
1038
+ }
1039
+ if (!allowInsecure && parsed.protocol !== "https:") {
1040
+ throw new ValidatorAuthError(
1041
+ "HTTPS is required for validator connections. Set allowInsecure=true for local development.",
1042
+ 400
1043
+ );
1044
+ }
1045
+ const hostname = parsed.hostname.toLowerCase();
1046
+ const isLocalhost = hostname === "localhost" || hostname === "127.0.0.1" || hostname === "::1";
1047
+ if (isLocalhost && !allowInsecure) {
1048
+ throw new ValidatorAuthError(
1049
+ "Localhost connections blocked in secure mode. Set allowInsecure=true for local development.",
1050
+ 400
1051
+ );
1052
+ }
1053
+ return parsed.origin;
1054
+ } catch (error) {
1055
+ if (error instanceof ValidatorAuthError) {
1056
+ throw error;
1057
+ }
1058
+ throw new ValidatorAuthError(`Invalid validator URL: ${url}`, 400);
1059
+ }
1060
+ }
1061
+ function sanitizeInput(input, fieldName, maxLength = 256) {
1062
+ if (typeof input !== "string") {
1063
+ throw new ValidatorAuthError(`${fieldName} must be a string`, 400);
1064
+ }
1065
+ if (input.length > maxLength) {
1066
+ throw new ValidatorAuthError(`${fieldName} exceeds maximum length of ${maxLength}`, 400);
1067
+ }
1068
+ return input.replace(/[\x00-\x1F\x7F]/g, "");
1069
+ }
1070
+ var ValidatorAuthClient = class {
1071
+ timeout;
1072
+ allowInsecure;
1073
+ constructor(config) {
1074
+ this.timeout = config?.timeout ?? 3e4;
1075
+ this.allowInsecure = config?.security?.allowInsecure ?? false;
1076
+ }
1077
+ /**
1078
+ * Request authentication challenge from validator
1079
+ *
1080
+ * @param validatorUrl - Validator API base URL
1081
+ * @param chain - Blockchain type
1082
+ * @param address - Wallet address
1083
+ * @returns Challenge to sign
1084
+ */
1085
+ async requestChallenge(validatorUrl, chain, address) {
1086
+ const safeUrl = validateValidatorUrl(validatorUrl, this.allowInsecure);
1087
+ const safeAddress = sanitizeInput(address, "address", 128);
1088
+ if (!SUPPORTED_AUTH_CHAINS.includes(chain)) {
1089
+ throw new ValidatorAuthError(`Invalid chain type: ${chain}`, 400);
1090
+ }
1091
+ const url = `${safeUrl}/auth/validator/challenge`;
1092
+ const controller = new AbortController();
1093
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
1094
+ try {
1095
+ const response = await fetch(url, {
1096
+ method: "POST",
1097
+ headers: {
1098
+ "Content-Type": "application/json"
1099
+ },
1100
+ body: JSON.stringify({ chain, address: safeAddress }),
1101
+ signal: controller.signal
1102
+ });
1103
+ clearTimeout(timeoutId);
1104
+ if (!response.ok) {
1105
+ const error = await response.json().catch(() => ({}));
1106
+ throw new ValidatorAuthError(
1107
+ `Challenge request failed: ${response.status} ${response.statusText}`,
1108
+ response.status,
1109
+ error
1110
+ );
1111
+ }
1112
+ return await response.json();
1113
+ } catch (error) {
1114
+ clearTimeout(timeoutId);
1115
+ if (error instanceof ValidatorAuthError) {
1116
+ throw error;
1117
+ }
1118
+ const err = error;
1119
+ if (err.name === "AbortError") {
1120
+ throw new ValidatorAuthError("Challenge request timeout", 408);
1121
+ }
1122
+ throw new ValidatorAuthError(`Challenge request failed: ${err.message}`, 0);
1123
+ }
1124
+ }
1125
+ /**
1126
+ * Authenticate with signed challenge
1127
+ *
1128
+ * @param validatorUrl - Validator API base URL
1129
+ * @param request - Authentication request with signature
1130
+ * @returns Session token and info
1131
+ */
1132
+ async authenticate(validatorUrl, request) {
1133
+ const safeUrl = validateValidatorUrl(validatorUrl, this.allowInsecure);
1134
+ const sanitizedRequest = {
1135
+ chain: request.chain,
1136
+ address: sanitizeInput(request.address, "address", 128),
1137
+ publicKey: sanitizeInput(request.publicKey, "publicKey", 512),
1138
+ signature: sanitizeInput(request.signature, "signature", 1024),
1139
+ challenge: sanitizeInput(request.challenge, "challenge", 512),
1140
+ metadata: request.metadata ? {
1141
+ nodeId: request.metadata.nodeId ? sanitizeInput(request.metadata.nodeId, "nodeId", 64) : void 0,
1142
+ endpoint: request.metadata.endpoint ? sanitizeInput(request.metadata.endpoint, "endpoint", 256) : void 0,
1143
+ capabilities: request.metadata.capabilities,
1144
+ appId: request.metadata.appId ? sanitizeInput(request.metadata.appId, "appId", 64) : void 0,
1145
+ appName: request.metadata.appName ? sanitizeInput(request.metadata.appName, "appName", 128) : void 0
1146
+ } : void 0
1147
+ };
1148
+ if (!SUPPORTED_AUTH_CHAINS.includes(sanitizedRequest.chain)) {
1149
+ throw new ValidatorAuthError(`Invalid chain type: ${sanitizedRequest.chain}`, 400);
1150
+ }
1151
+ if (!/^[0-9a-fA-F]+$/.test(sanitizedRequest.signature.replace(/_.*$/, ""))) {
1152
+ throw new ValidatorAuthError("Invalid signature format: must be hex encoded", 400);
1153
+ }
1154
+ const url = `${safeUrl}/auth/validator/authenticate`;
1155
+ const controller = new AbortController();
1156
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
1157
+ try {
1158
+ const response = await fetch(url, {
1159
+ method: "POST",
1160
+ headers: {
1161
+ "Content-Type": "application/json"
1162
+ },
1163
+ body: JSON.stringify(sanitizedRequest),
1164
+ signal: controller.signal
1165
+ });
1166
+ clearTimeout(timeoutId);
1167
+ if (!response.ok) {
1168
+ const error = await response.json().catch(() => ({}));
1169
+ throw new ValidatorAuthError(
1170
+ `Authentication failed: ${response.status} ${response.statusText}`,
1171
+ response.status,
1172
+ error
1173
+ );
1174
+ }
1175
+ return await response.json();
1176
+ } catch (error) {
1177
+ clearTimeout(timeoutId);
1178
+ if (error instanceof ValidatorAuthError) {
1179
+ throw error;
1180
+ }
1181
+ const err = error;
1182
+ if (err.name === "AbortError") {
1183
+ throw new ValidatorAuthError("Authentication request timeout", 408);
1184
+ }
1185
+ throw new ValidatorAuthError(`Authentication failed: ${err.message}`, 0);
1186
+ }
1187
+ }
1188
+ /**
1189
+ * Get current session info
1190
+ *
1191
+ * @param validatorUrl - Validator API base URL
1192
+ * @param token - Session token
1193
+ * @returns Session information
1194
+ */
1195
+ async getSession(validatorUrl, token) {
1196
+ const safeUrl = validateValidatorUrl(validatorUrl, this.allowInsecure);
1197
+ const safeToken = sanitizeInput(token, "token", 2048);
1198
+ const url = `${safeUrl}/auth/validator/session`;
1199
+ const controller = new AbortController();
1200
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
1201
+ try {
1202
+ const response = await fetch(url, {
1203
+ method: "GET",
1204
+ headers: {
1205
+ Authorization: `Bearer ${safeToken}`
1206
+ },
1207
+ signal: controller.signal
1208
+ });
1209
+ clearTimeout(timeoutId);
1210
+ if (!response.ok) {
1211
+ const error = await response.json().catch(() => ({}));
1212
+ throw new ValidatorAuthError(
1213
+ `Session request failed: ${response.status} ${response.statusText}`,
1214
+ response.status,
1215
+ error
1216
+ );
1217
+ }
1218
+ return await response.json();
1219
+ } catch (error) {
1220
+ clearTimeout(timeoutId);
1221
+ if (error instanceof ValidatorAuthError) {
1222
+ throw error;
1223
+ }
1224
+ const err = error;
1225
+ if (err.name === "AbortError") {
1226
+ throw new ValidatorAuthError("Session request timeout", 408);
1227
+ }
1228
+ throw new ValidatorAuthError(`Session request failed: ${err.message}`, 0);
1229
+ }
1230
+ }
1231
+ /**
1232
+ * Sign challenge with Hedera private key
1233
+ *
1234
+ * @param challenge - Challenge string from validator
1235
+ * @param privateKey - Hedera PrivateKey instance from @hashgraph/sdk
1236
+ * @returns Hex-encoded signature
1237
+ */
1238
+ signChallengeHedera(challenge, privateKey) {
1239
+ const messageBytes = Buffer.from(challenge, "utf-8");
1240
+ const signature = privateKey.sign(messageBytes);
1241
+ return Buffer.from(signature).toString("hex");
1242
+ }
1243
+ /**
1244
+ * Sign challenge with XRPL wallet
1245
+ *
1246
+ * @param challenge - Challenge string from validator
1247
+ * @param wallet - XRPL Wallet instance from xrpl library
1248
+ * @returns Hex-encoded signature
1249
+ */
1250
+ signChallengeXRPL(challenge, wallet) {
1251
+ const signature = wallet.sign(challenge);
1252
+ if (typeof signature === "string" && /^[0-9A-Fa-f]+$/.test(signature)) {
1253
+ return signature;
1254
+ }
1255
+ return Buffer.from(signature).toString("hex");
1256
+ }
1257
+ /**
1258
+ * Complete authentication flow in one call
1259
+ *
1260
+ * @param validatorUrl - Validator API base URL
1261
+ * @param chain - Blockchain type
1262
+ * @param address - Wallet address
1263
+ * @param publicKey - Public key (hex)
1264
+ * @param signFn - Function to sign the challenge
1265
+ * @param metadata - Optional metadata
1266
+ * @returns Session token and info
1267
+ */
1268
+ async authenticateWithSigner(validatorUrl, chain, address, publicKey, signFn, metadata) {
1269
+ const challengeResponse = await this.requestChallenge(validatorUrl, chain, address);
1270
+ const signature = await signFn(challengeResponse.challenge);
1271
+ return this.authenticate(validatorUrl, {
1272
+ chain,
1273
+ address,
1274
+ publicKey,
1275
+ signature,
1276
+ challenge: challengeResponse.challenge,
1277
+ metadata
1278
+ });
1279
+ }
1280
+ };
1281
+ var ValidatorAuthError = class extends Error {
1282
+ constructor(message, statusCode, details) {
1283
+ super(message);
1284
+ this.statusCode = statusCode;
1285
+ this.details = details;
1286
+ this.name = "ValidatorAuthError";
1287
+ }
1288
+ statusCode;
1289
+ details;
1290
+ };
1291
+
1292
+ // src/http/index.ts
1293
+ var SdkHttpError = class extends Error {
1294
+ constructor(message, statusCode, details) {
1295
+ super(message);
1296
+ this.statusCode = statusCode;
1297
+ this.details = details;
1298
+ this.name = "SdkHttpError";
1299
+ }
1300
+ statusCode;
1301
+ details;
1302
+ };
1303
+ function createHttpClient(config) {
1304
+ const timeout = config.timeout ?? 3e4;
1305
+ function getHeaders(contentType) {
1306
+ const headers = {};
1307
+ {
1308
+ headers["Content-Type"] = contentType;
1309
+ }
1310
+ if (config.authToken) {
1311
+ headers["Authorization"] = `Bearer ${config.authToken}`;
1312
+ }
1313
+ if (config.apiKey) {
1314
+ headers["X-API-Key"] = config.apiKey;
1315
+ }
1316
+ return headers;
1317
+ }
1318
+ function setAuthToken(token) {
1319
+ config.authToken = token;
1320
+ }
1321
+ async function request(method, path, body) {
1322
+ const url = `${config.baseUrl}${path}`;
1323
+ const controller = new AbortController();
1324
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
1325
+ try {
1326
+ const init = {
1327
+ method,
1328
+ headers: getHeaders("application/json"),
1329
+ signal: controller.signal
1330
+ };
1331
+ if (body !== void 0) {
1332
+ init.body = JSON.stringify(body);
1333
+ }
1334
+ const response = await fetch(url, init);
1335
+ clearTimeout(timeoutId);
1336
+ if (!response.ok) {
1337
+ const errorData = await response.json().catch(() => ({}));
1338
+ throw new SdkHttpError(
1339
+ errorData.message || `API error: ${response.status} ${response.statusText}`,
1340
+ response.status,
1341
+ errorData
1342
+ );
1343
+ }
1344
+ const text = await response.text();
1345
+ if (!text) return void 0;
1346
+ return JSON.parse(text);
1347
+ } catch (error) {
1348
+ clearTimeout(timeoutId);
1349
+ if (error instanceof SdkHttpError) throw error;
1350
+ const err = error;
1351
+ if (err.name === "AbortError") {
1352
+ throw new SdkHttpError("Request timeout", 408);
1353
+ }
1354
+ throw new SdkHttpError(`Network error: ${err.message}`, 0, error);
1355
+ }
1356
+ }
1357
+ async function upload(path, file, filename, metadata) {
1358
+ const url = `${config.baseUrl}${path}`;
1359
+ const controller = new AbortController();
1360
+ const timeoutId = setTimeout(() => controller.abort(), timeout * 2);
1361
+ try {
1362
+ const formData = new FormData();
1363
+ const blob = file instanceof Blob ? file : new Blob([new Uint8Array(file)]);
1364
+ formData.append("file", blob, filename);
1365
+ if (metadata) {
1366
+ for (const [key, value] of Object.entries(metadata)) {
1367
+ formData.append(key, value);
1368
+ }
1369
+ }
1370
+ const headers = {};
1371
+ if (config.authToken) {
1372
+ headers["Authorization"] = `Bearer ${config.authToken}`;
1373
+ }
1374
+ if (config.apiKey) {
1375
+ headers["X-API-Key"] = config.apiKey;
1376
+ }
1377
+ const response = await fetch(url, {
1378
+ method: "POST",
1379
+ headers,
1380
+ body: formData,
1381
+ signal: controller.signal
1382
+ });
1383
+ clearTimeout(timeoutId);
1384
+ if (!response.ok) {
1385
+ const errorData = await response.json().catch(() => ({}));
1386
+ throw new SdkHttpError(
1387
+ errorData.message || `Upload error: ${response.status} ${response.statusText}`,
1388
+ response.status,
1389
+ errorData
1390
+ );
1391
+ }
1392
+ return response.json();
1393
+ } catch (error) {
1394
+ clearTimeout(timeoutId);
1395
+ if (error instanceof SdkHttpError) throw error;
1396
+ const err = error;
1397
+ if (err.name === "AbortError") {
1398
+ throw new SdkHttpError("Upload timeout", 408);
1399
+ }
1400
+ throw new SdkHttpError(`Upload error: ${err.message}`, 0, error);
1401
+ }
1402
+ }
1403
+ const client = {
1404
+ post: (path, body) => request("POST", path, body),
1405
+ get: (path) => request("GET", path),
1406
+ put: (path, body) => request("PUT", path, body),
1407
+ delete: (path) => request("DELETE", path),
1408
+ upload,
1409
+ setAuthToken
1410
+ };
1411
+ return client;
1412
+ }
1413
+ function encodePathParam(param) {
1414
+ return encodeURIComponent(param).replace(/%2F/gi, "");
1415
+ }
1416
+
1417
+ // src/subscription/index.ts
1418
+ var SubscriptionClient = class {
1419
+ constructor(http) {
1420
+ this.http = http;
1421
+ }
1422
+ http;
1423
+ /**
1424
+ * Request a new subscription.
1425
+ * Creates a deposit wallet and returns deposit instructions.
1426
+ */
1427
+ async request(request) {
1428
+ return this.http.post("/subscription/request", request);
1429
+ }
1430
+ /**
1431
+ * Get subscription status by app ID
1432
+ */
1433
+ async getStatus(appId) {
1434
+ return this.http.get(`/subscription/status/${encodeURIComponent(appId)}`);
1435
+ }
1436
+ /**
1437
+ * Mint subscription NFT after deposit is confirmed
1438
+ */
1439
+ async mintNft(appId) {
1440
+ return this.http.post(`/subscription/mint/${encodeURIComponent(appId)}`, {});
1441
+ }
1442
+ /**
1443
+ * Renew subscription by extending period
1444
+ */
1445
+ async renew(request) {
1446
+ return this.http.post("/subscription/renew", request);
1447
+ }
1448
+ /**
1449
+ * Fetch available subscription tiers from the network.
1450
+ *
1451
+ * Use this instead of hard-coding tier names -- the validator returns the
1452
+ * canonical list of tiers together with pricing, limits, and features.
1453
+ *
1454
+ * @returns Array of {@link SubscriptionTierInfo} objects.
1455
+ *
1456
+ * @example
1457
+ * ```typescript
1458
+ * const tiers = await subscription.getTiers();
1459
+ * console.log(tiers.map(t => `${t.name}: $${t.priceUsd}/mo`));
1460
+ * ```
1461
+ */
1462
+ async getTiers() {
1463
+ try {
1464
+ return await this.http.get("/subscription/tiers");
1465
+ } catch (err) {
1466
+ const isNotFound = err != null && typeof err === "object" && "statusCode" in err && err.statusCode === 404;
1467
+ if (!isNotFound) throw err;
1468
+ const cfg = await this.http.get("/subscription/config");
1469
+ return (cfg.availableTiers || []).map((raw) => {
1470
+ const tier = raw.tier ?? raw.name;
1471
+ const displayName = raw.name ?? raw.displayName ?? String(tier);
1472
+ const monthlyPriceHsuite = Number(
1473
+ raw.monthlyPriceHsuite ?? raw.depositAmount ?? 0
1474
+ );
1475
+ const apiCallsPerDay = Number(raw.apiCallsPerDay ?? 0);
1476
+ const rawNetworks = raw.allowedNetworks ?? raw.supportedNetworks ?? [];
1477
+ const supportedNetworks = rawNetworks.some(
1478
+ (n) => n === "mainnet"
1479
+ ) ? ["hedera", "xrpl"] : ["hedera"];
1480
+ return {
1481
+ name: tier,
1482
+ displayName,
1483
+ description: raw.description ?? `${displayName} tier`,
1484
+ priceUsd: Number(raw.priceUsd ?? 0),
1485
+ depositAmount: String(monthlyPriceHsuite),
1486
+ apiCallsPerDay: Number.isFinite(apiCallsPerDay) ? apiCallsPerDay : Number.MAX_SAFE_INTEGER,
1487
+ supportedNetworks,
1488
+ features: raw.features ?? []
1489
+ };
1490
+ });
1491
+ }
1492
+ }
1493
+ /**
1494
+ * Get subscription configuration
1495
+ */
1496
+ async getConfig() {
1497
+ return this.http.get("/subscription/config");
1498
+ }
1499
+ /**
1500
+ * List all subscriptions
1501
+ */
1502
+ async list() {
1503
+ return this.http.get("/subscription/list");
1504
+ }
1505
+ /**
1506
+ * List subscriptions by status
1507
+ */
1508
+ async listByStatus(status) {
1509
+ return this.http.get(`/subscription/list/status/${encodeURIComponent(status)}`);
1510
+ }
1511
+ /**
1512
+ * Get subscription balance
1513
+ */
1514
+ async getBalance(appId) {
1515
+ return this.http.get(`/subscription/balance/${encodeURIComponent(appId)}`);
1516
+ }
1517
+ };
1518
+
1519
+ // src/tss/index.ts
1520
+ var TSSClient = class {
1521
+ constructor(http) {
1522
+ this.http = http;
1523
+ }
1524
+ http;
1525
+ /**
1526
+ * Create a multi-sig entity with TSS
1527
+ */
1528
+ async createEntity(options) {
1529
+ return this.http.post("/tss/entity/create", options);
1530
+ }
1531
+ /**
1532
+ * Reshare keys when cluster membership changes.
1533
+ * Redistributes secret shares WITHOUT changing public keys.
1534
+ */
1535
+ async reshareCluster(request) {
1536
+ return this.http.post("/tss/cluster/reshare", request);
1537
+ }
1538
+ /**
1539
+ * Get entity details by ID
1540
+ */
1541
+ async getEntity(entityId) {
1542
+ return this.http.get(`/tss/entity/${encodeURIComponent(entityId)}`);
1543
+ }
1544
+ /**
1545
+ * Sign a transaction using MPC — chain-agnostic.
1546
+ * Routes to the correct chain backend based on the `chain` parameter.
1547
+ *
1548
+ * @param request - MPC signing request with chain, entityId, and transaction bytes
1549
+ */
1550
+ async signMPC(request) {
1551
+ const chain = request.chain || "hedera";
1552
+ return this.http.post(`/tss/${encodeURIComponent(chain)}/sign-mpc`, request);
1553
+ }
1554
+ /**
1555
+ * Get known validators and their public keys
1556
+ */
1557
+ async getValidators() {
1558
+ return this.http.get("/tss/validators");
1559
+ }
1560
+ /**
1561
+ * Force announcement of this node's public key
1562
+ */
1563
+ async announceKey() {
1564
+ return this.http.post("/tss/announce", {});
1565
+ }
1566
+ /**
1567
+ * Get TSS statistics
1568
+ */
1569
+ async getStats() {
1570
+ return this.http.get("/tss/stats");
1571
+ }
1572
+ /**
1573
+ * List all TSS entities
1574
+ */
1575
+ async listEntities() {
1576
+ return this.http.get("/tss/entities");
1577
+ }
1578
+ /**
1579
+ * TSS health check
1580
+ */
1581
+ async getHealth() {
1582
+ return this.http.get("/tss/health");
1583
+ }
1584
+ /**
1585
+ * List DKG ceremonies and their statistics
1586
+ */
1587
+ async listCeremonies() {
1588
+ return this.http.get("/tss/multisig/ceremonies");
1589
+ }
1590
+ /**
1591
+ * Get multi-sig transaction status by transaction ID
1592
+ */
1593
+ async getMultiSigStatus(txId) {
1594
+ return this.http.get(`/tss/multisig/transactions/${encodeURIComponent(txId)}`);
1595
+ }
1596
+ };
1597
+
1598
+ // src/ipfs/index.ts
1599
+ var IPFSClient = class {
1600
+ constructor(http) {
1601
+ this.http = http;
1602
+ }
1603
+ http;
1604
+ /**
1605
+ * Upload a file to IPFS
1606
+ *
1607
+ * @param file - File data as Blob or Buffer
1608
+ * @param filename - Name of the file
1609
+ * @param metadata - Optional metadata key-value pairs
1610
+ * @returns Upload result with CID
1611
+ */
1612
+ async upload(file, filename, metadata) {
1613
+ return this.http.upload("/ipfs/upload", file, filename, metadata);
1614
+ }
1615
+ /**
1616
+ * Pin content by CID to ensure it persists
1617
+ */
1618
+ async pin(cid) {
1619
+ return this.http.post(`/ipfs/pin/${encodeURIComponent(cid)}`, {});
1620
+ }
1621
+ /**
1622
+ * Unpin content by CID
1623
+ */
1624
+ async unpin(cid) {
1625
+ return this.http.delete(`/ipfs/unpin/${encodeURIComponent(cid)}`);
1626
+ }
1627
+ /**
1628
+ * Get a file by CID
1629
+ */
1630
+ async getFile(cid) {
1631
+ return this.http.get(`/ipfs/file/${encodeURIComponent(cid)}`);
1632
+ }
1633
+ /**
1634
+ * Get raw content by CID
1635
+ */
1636
+ async getContent(cid) {
1637
+ return this.http.get(`/ipfs/${encodeURIComponent(cid)}`);
1638
+ }
1639
+ /**
1640
+ * Get file metadata by CID
1641
+ */
1642
+ async getMetadata(cid) {
1643
+ return this.http.get(`/ipfs/metadata/${encodeURIComponent(cid)}`);
1644
+ }
1645
+ /**
1646
+ * List all pinned content
1647
+ */
1648
+ async listPins() {
1649
+ return this.http.get("/ipfs/pins");
1650
+ }
1651
+ /**
1652
+ * Get IPFS node status
1653
+ */
1654
+ async getStatus() {
1655
+ return this.http.get("/ipfs/status");
1656
+ }
1657
+ /**
1658
+ * Get storage usage information
1659
+ */
1660
+ async getStorageUsage() {
1661
+ return this.http.get("/ipfs/storage");
1662
+ }
1663
+ };
1664
+
1665
+ // src/transactions/index.ts
1666
+ var TransactionsClient = class {
1667
+ constructor(http) {
1668
+ this.http = http;
1669
+ }
1670
+ http;
1671
+ /**
1672
+ * Get transaction preparation service info
1673
+ */
1674
+ async getInfo() {
1675
+ return this.http.get("/info");
1676
+ }
1677
+ /**
1678
+ * Prepare a transfer transaction for local signing
1679
+ */
1680
+ async prepareTransfer(request) {
1681
+ return this.http.post("/transfer/prepare", request);
1682
+ }
1683
+ /**
1684
+ * Prepare an NFT mint transaction
1685
+ */
1686
+ async prepareNftMint(request) {
1687
+ return this.http.post("/nft/mint/prepare", request);
1688
+ }
1689
+ /**
1690
+ * Prepare an NFT burn transaction
1691
+ */
1692
+ async prepareNftBurn(request) {
1693
+ return this.http.post("/nft/burn/prepare", request);
1694
+ }
1695
+ /**
1696
+ * Prepare an NFT transfer transaction
1697
+ */
1698
+ async prepareNftTransfer(request) {
1699
+ return this.http.post("/nft/transfer/prepare", request);
1700
+ }
1701
+ /**
1702
+ * Prepare a token creation transaction
1703
+ */
1704
+ async prepareTokenCreate(request) {
1705
+ return this.http.post("/token/create/prepare", request);
1706
+ }
1707
+ /**
1708
+ * Prepare a token mint transaction
1709
+ */
1710
+ async prepareTokenMint(request) {
1711
+ return this.http.post("/token/mint/prepare", request);
1712
+ }
1713
+ /**
1714
+ * Prepare a fungible token burn transaction (Hedera).
1715
+ *
1716
+ * For NFT burn use `prepareNftBurn` with a serialNumber.
1717
+ */
1718
+ async prepareTokenBurn(request) {
1719
+ return this.http.post("/token/burn/prepare", request);
1720
+ }
1721
+ /**
1722
+ * Prepare a token association transaction
1723
+ */
1724
+ async prepareTokenAssociation(request) {
1725
+ return this.http.post("/token/associate/prepare", request);
1726
+ }
1727
+ // ── Capability actions (Hedera) ──────────────────────────────────────
1728
+ /** Prepare a token pause transaction (capability: pausable). */
1729
+ async prepareTokenPause(request) {
1730
+ return this.http.post("/token/pause/prepare", request);
1731
+ }
1732
+ /** Prepare a token unpause transaction (capability: pausable). */
1733
+ async prepareTokenUnpause(request) {
1734
+ return this.http.post("/token/unpause/prepare", request);
1735
+ }
1736
+ /**
1737
+ * Prepare a token restrict (freeze account) transaction (capability:
1738
+ * restrictable). Freezes `accountId` from transacting `tokenId`.
1739
+ */
1740
+ async prepareTokenRestrict(request) {
1741
+ return this.http.post("/token/restrict/prepare", request);
1742
+ }
1743
+ /** Prepare a token unrestrict (unfreeze account) transaction. */
1744
+ async prepareTokenUnrestrict(request) {
1745
+ return this.http.post("/token/unrestrict/prepare", request);
1746
+ }
1747
+ /**
1748
+ * Prepare a token compliance-enable (grant KYC) transaction (capability:
1749
+ * compliant).
1750
+ */
1751
+ async prepareTokenComplianceEnable(request) {
1752
+ return this.http.post("/token/compliance/enable/prepare", request);
1753
+ }
1754
+ /** Prepare a token compliance-disable (revoke KYC) transaction. */
1755
+ async prepareTokenComplianceDisable(request) {
1756
+ return this.http.post("/token/compliance/disable/prepare", request);
1757
+ }
1758
+ /**
1759
+ * Prepare a token wipe transaction (capability: wipeable). Force-removes
1760
+ * `amount` of `tokenId` from `accountId`.
1761
+ */
1762
+ async prepareTokenWipe(request) {
1763
+ return this.http.post("/token/wipe/prepare", request);
1764
+ }
1765
+ /**
1766
+ * Prepare a topic creation transaction
1767
+ */
1768
+ async prepareTopicCreate(request) {
1769
+ return this.http.post("/topic/create/prepare", request);
1770
+ }
1771
+ /**
1772
+ * Prepare a topic message submission transaction
1773
+ */
1774
+ async prepareTopicMessage(request) {
1775
+ return this.http.post("/topic/message/prepare", request);
1776
+ }
1777
+ /**
1778
+ * Prepare a trust line transaction (e.g. XRPL trust lines)
1779
+ */
1780
+ async prepareTrustLine(request) {
1781
+ return this.http.post("/trustline/prepare", request);
1782
+ }
1783
+ };
1784
+
1785
+ // src/snapshots/index.ts
1786
+ var SnapshotsClient = class {
1787
+ constructor(http) {
1788
+ this.http = http;
1789
+ }
1790
+ http;
1791
+ /**
1792
+ * Generate a new snapshot for a token
1793
+ *
1794
+ * @param tokenId - Token identifier
1795
+ * @param options - Generation options (format, filters)
1796
+ */
1797
+ async generate(tokenId, options) {
1798
+ return this.http.post(
1799
+ `/snapshots/generate/${encodeURIComponent(tokenId)}`,
1800
+ options || {}
1801
+ );
1802
+ }
1803
+ /**
1804
+ * Get snapshot details by ID
1805
+ */
1806
+ async get(snapshotId) {
1807
+ return this.http.get(`/snapshots/${encodeURIComponent(snapshotId)}`);
1808
+ }
1809
+ /**
1810
+ * List snapshots for a token
1811
+ */
1812
+ async listByToken(tokenId, pagination) {
1813
+ const params = new URLSearchParams();
1814
+ if (pagination?.page !== void 0) params.set("page", String(pagination.page));
1815
+ if (pagination?.limit !== void 0) params.set("limit", String(pagination.limit));
1816
+ const qs = params.toString();
1817
+ return this.http.get(
1818
+ `/snapshots/token/${encodeURIComponent(tokenId)}${qs ? `?${qs}` : ""}`
1819
+ );
1820
+ }
1821
+ /**
1822
+ * Download snapshot data
1823
+ *
1824
+ * @param snapshotId - Snapshot ID
1825
+ * @param format - Output format (json or csv)
1826
+ */
1827
+ async download(snapshotId, format) {
1828
+ const params = format ? `?format=${encodeURIComponent(format)}` : "";
1829
+ return this.http.get(
1830
+ `/snapshots/${encodeURIComponent(snapshotId)}/download${params}`
1831
+ );
1832
+ }
1833
+ };
1834
+
1835
+ // src/settlement/index.ts
1836
+ var SettlementClient = class {
1837
+ constructor(http) {
1838
+ this.http = http;
1839
+ }
1840
+ http;
1841
+ /**
1842
+ * Initiate a new settlement operation.
1843
+ * Submits source-chain payment details and begins the conversion pipeline.
1844
+ */
1845
+ async initiate(request) {
1846
+ return this.http.post("/settlement/initiate", request);
1847
+ }
1848
+ /**
1849
+ * Get the current status of a settlement by ID.
1850
+ */
1851
+ async getStatus(settlementId) {
1852
+ return this.http.get(`/settlement/${encodeURIComponent(settlementId)}/status`);
1853
+ }
1854
+ /**
1855
+ * Confirm that XRP has landed on the destination address.
1856
+ * Advances the settlement to the next processing step.
1857
+ */
1858
+ async confirmXrpLanded(settlementId) {
1859
+ return this.http.post(`/settlement/${encodeURIComponent(settlementId)}/confirm-xrp`, {});
1860
+ }
1861
+ /**
1862
+ * Get settlement history for a given entity.
1863
+ */
1864
+ async getHistory(entityId) {
1865
+ return this.http.get(`/settlement/history/${encodeURIComponent(entityId)}`);
1866
+ }
1867
+ };
1868
+
1869
+ // src/client.ts
1870
+ var SmartEngineClient = class _SmartEngineClient {
1871
+ baseUrl;
1872
+ allowInsecure;
1873
+ http;
1874
+ /** Separate HTTP client for /api/transactions (non-v3 base path) */
1875
+ txHttp;
1876
+ /** Last HTTP error (for getHttpHealth) */
1877
+ lastHttpError;
1878
+ // ========== Sub-Clients ==========
1879
+ /** Application subscription management */
1880
+ subscription;
1881
+ /** Threshold Signature Scheme — chain-agnostic MPC operations */
1882
+ tss;
1883
+ /** IPFS decentralized file storage */
1884
+ ipfs;
1885
+ /** Transaction preparation for local signing (sovereignty model) */
1886
+ transactions;
1887
+ /** Token holder snapshot generation and retrieval */
1888
+ snapshots;
1889
+ /** Cross-chain settlement operations */
1890
+ settlement;
1891
+ constructor(config) {
1892
+ this.allowInsecure = config.allowInsecure ?? false;
1893
+ this.baseUrl = validateClientUrl(config.baseUrl, this.allowInsecure);
1894
+ this.http = createHttpClient({
1895
+ baseUrl: `${this.baseUrl}/api/v3`,
1896
+ apiKey: config.apiKey,
1897
+ authToken: config.authToken,
1898
+ timeout: config.timeout
1899
+ });
1900
+ this.txHttp = createHttpClient({
1901
+ baseUrl: `${this.baseUrl}/api/transactions`,
1902
+ apiKey: config.apiKey,
1903
+ authToken: config.authToken,
1904
+ timeout: config.timeout
1905
+ });
1906
+ this.subscription = new SubscriptionClient(this.http);
1907
+ this.tss = new TSSClient(this.http);
1908
+ this.ipfs = new IPFSClient(this.http);
1909
+ this.transactions = new TransactionsClient(this.txHttp);
1910
+ this.snapshots = new SnapshotsClient(this.http);
1911
+ this.settlement = new SettlementClient(this.http);
1912
+ }
1913
+ /**
1914
+ * Connect to the smart-engines network with auto-discovery and authentication
1915
+ *
1916
+ * This method:
1917
+ * 1. Discovers validators via HCS registry topic
1918
+ * 2. Selects a random validator with API endpoint
1919
+ * 3. Authenticates with Web3-style challenge-response
1920
+ * 4. Returns a configured client ready to use
1921
+ */
1922
+ static async connectToNetwork(config) {
1923
+ const allowInsecure = config.allowInsecure ?? false;
1924
+ const discovery = new ValidatorDiscoveryClient({
1925
+ network: config.network,
1926
+ registryTopicId: config.registryTopicId,
1927
+ mirrorNodeUrl: config.mirrorNodeUrl
1928
+ });
1929
+ const validator = await discovery.getRandomValidator();
1930
+ if (!validator || !validator.networkEndpoints?.apiEndpoint) {
1931
+ throw new SmartEngineError2(
1932
+ "No validators available. Check registry topic and network configuration.",
1933
+ 503
1934
+ );
1935
+ }
1936
+ const validatorUrl = validator.networkEndpoints.apiEndpoint;
1937
+ validateClientUrl(validatorUrl, allowInsecure);
1938
+ const auth = new ValidatorAuthClient({
1939
+ security: { allowInsecure }
1940
+ });
1941
+ const session = await auth.authenticateWithSigner(
1942
+ validatorUrl,
1943
+ config.chain,
1944
+ config.address,
1945
+ config.publicKey,
1946
+ config.signFn,
1947
+ config.metadata
1948
+ );
1949
+ const client = new _SmartEngineClient({
1950
+ baseUrl: validatorUrl,
1951
+ authToken: session.token,
1952
+ allowInsecure
1953
+ });
1954
+ return { client, validator, session };
1955
+ }
1956
+ /** Get the current validator URL */
1957
+ getBaseUrl() {
1958
+ return this.baseUrl;
1959
+ }
1960
+ /** Check if client has an auth token */
1961
+ isAuthenticated() {
1962
+ return !!this.http.authToken;
1963
+ }
1964
+ /**
1965
+ * Get HTTP resilience health information
1966
+ * @returns Object with circuit breaker state and last error (if any)
1967
+ */
1968
+ getHttpHealth() {
1969
+ return {
1970
+ breaker: null,
1971
+ lastError: this.lastHttpError
1972
+ };
1973
+ }
1974
+ // ========== Health & Info ==========
1975
+ /** Get health status of the validator */
1976
+ async getHealth() {
1977
+ return this.http.get("/health");
1978
+ }
1979
+ /** Get list of supported chains */
1980
+ async getSupportedChains() {
1981
+ return this.http.get("/chains");
1982
+ }
1983
+ // ========== Account Operations ==========
1984
+ /** Create a new account on the specified chain */
1985
+ async createAccount(request) {
1986
+ const validated = CreateAccountRequestSchema.parse(request);
1987
+ return this.http.post("/accounts", validated);
1988
+ }
1989
+ /** Get account information */
1990
+ async getAccountInfo(chain, accountId) {
1991
+ return this.http.get(`/accounts/${encodePathParam(chain)}/${encodePathParam(accountId)}`);
1992
+ }
1993
+ /** Get account balance */
1994
+ async getBalance(chain, accountId) {
1995
+ return this.http.get(`/accounts/${encodePathParam(chain)}/${encodePathParam(accountId)}/balance`);
1996
+ }
1997
+ // ========== Transaction Operations ==========
1998
+ /** Execute a transfer transaction */
1999
+ async transfer(request) {
2000
+ const validated = TransferRequestSchema.parse(request);
2001
+ return this.http.post("/transfer", validated);
2002
+ }
2003
+ /** Get transaction details */
2004
+ async getTransaction(chain, txId) {
2005
+ return this.http.get(`/transactions/${encodePathParam(chain)}/${encodePathParam(txId)}`);
2006
+ }
2007
+ /** Get transaction receipt */
2008
+ async getTransactionReceipt(chain, txId) {
2009
+ return this.http.get(`/transactions/${encodePathParam(chain)}/${encodePathParam(txId)}/receipt`);
2010
+ }
2011
+ // ========== Token Operations ==========
2012
+ /** Create a new token */
2013
+ async createToken(request) {
2014
+ const validated = CreateTokenRequestSchema.parse(request);
2015
+ return this.http.post("/tokens", validated);
2016
+ }
2017
+ /** Mint tokens */
2018
+ async mintToken(request) {
2019
+ const validated = MintTokenRequestSchema.parse(request);
2020
+ return this.http.post("/tokens/mint", validated);
2021
+ }
2022
+ /** Get token information */
2023
+ async getTokenInfo(chain, tokenId) {
2024
+ return this.http.get(`/tokens/${encodePathParam(chain)}/${encodePathParam(tokenId)}`);
2025
+ }
2026
+ /** Burn tokens to reduce supply */
2027
+ async burnToken(request) {
2028
+ const validated = BurnTokenRequestSchema.parse(request);
2029
+ return this.http.post("/tokens/burn", validated);
2030
+ }
2031
+ /** Pause all token operations globally */
2032
+ async pauseToken(request) {
2033
+ const validated = TokenActionRequestSchema.parse(request);
2034
+ return this.http.post("/tokens/pause", validated);
2035
+ }
2036
+ /** Unpause token operations */
2037
+ async unpauseToken(request) {
2038
+ const validated = TokenActionRequestSchema.parse(request);
2039
+ return this.http.post("/tokens/unpause", validated);
2040
+ }
2041
+ /** Freeze/restrict an account from transacting the token */
2042
+ async restrictAccount(request) {
2043
+ const validated = TokenActionRequestSchema.parse(request);
2044
+ if (!validated.accountId) {
2045
+ throw new SmartEngineError2("accountId is required for restrictAccount", 400);
2046
+ }
2047
+ return this.http.post("/tokens/restrict", validated);
2048
+ }
2049
+ /** Unfreeze an account */
2050
+ async unrestrictAccount(request) {
2051
+ const validated = TokenActionRequestSchema.parse(request);
2052
+ if (!validated.accountId) {
2053
+ throw new SmartEngineError2("accountId is required for unrestrictAccount", 400);
2054
+ }
2055
+ return this.http.post("/tokens/unrestrict", validated);
2056
+ }
2057
+ /** Grant KYC/compliance approval to an account */
2058
+ async enableCompliance(request) {
2059
+ const validated = TokenActionRequestSchema.parse(request);
2060
+ if (!validated.accountId) {
2061
+ throw new SmartEngineError2("accountId is required for enableCompliance", 400);
2062
+ }
2063
+ return this.http.post("/tokens/compliance/enable", validated);
2064
+ }
2065
+ /** Revoke KYC/compliance approval from an account */
2066
+ async disableCompliance(request) {
2067
+ const validated = TokenActionRequestSchema.parse(request);
2068
+ if (!validated.accountId) {
2069
+ throw new SmartEngineError2("accountId is required for disableCompliance", 400);
2070
+ }
2071
+ return this.http.post("/tokens/compliance/disable", validated);
2072
+ }
2073
+ /** Force remove tokens from an account (compliance action) */
2074
+ async wipeFromAccount(request) {
2075
+ const validated = TokenActionRequestSchema.parse(request);
2076
+ if (!validated.accountId) {
2077
+ throw new SmartEngineError2("accountId is required for wipeFromAccount", 400);
2078
+ }
2079
+ if (!validated.amount) {
2080
+ throw new SmartEngineError2("amount is required for wipeFromAccount", 400);
2081
+ }
2082
+ return this.http.post("/tokens/wipe", validated);
2083
+ }
2084
+ // ========== Capabilities Discovery ==========
2085
+ /** Get capability support matrix for all chains */
2086
+ async getAllCapabilities() {
2087
+ return this.http.get("/capabilities");
2088
+ }
2089
+ /** Get capability support for a specific chain */
2090
+ async getChainCapabilities(chain) {
2091
+ return this.http.get(`/capabilities/${encodePathParam(chain)}`);
2092
+ }
2093
+ /** Get comprehensive system status */
2094
+ async getSystemStatus() {
2095
+ return this.http.get("/status");
2096
+ }
2097
+ // ========== Messaging Operations ==========
2098
+ /** Submit a message to consensus */
2099
+ async submitMessage(chain, topicId, message) {
2100
+ if (message.length > 1024 * 1024) {
2101
+ throw new SmartEngineError2("Message too large (max 1MB)", 400);
2102
+ }
2103
+ return this.http.post(`/messages/${encodePathParam(chain)}/${encodePathParam(topicId)}`, {
2104
+ message
2105
+ });
2106
+ }
2107
+ // ========== Cluster Operations ==========
2108
+ /** Get cluster health status */
2109
+ async getClusterHealth() {
2110
+ return this.http.get("/cluster/health");
2111
+ }
2112
+ /** Get cluster status including node details */
2113
+ async getClusterStatus() {
2114
+ return this.http.get("/cluster/status");
2115
+ }
2116
+ // ========== Metrics & Monitoring ==========
2117
+ /** Get Prometheus-format metrics */
2118
+ async getMetrics() {
2119
+ return this.http.get("/metrics");
2120
+ }
2121
+ /** Get queue statistics for monitoring */
2122
+ async getQueueStats() {
2123
+ return this.http.get("/monitoring/queue");
2124
+ }
2125
+ /** Get circuit breaker status for all services */
2126
+ async getCircuitBreakerStatus() {
2127
+ return this.http.get("/monitoring/circuit-breakers");
2128
+ }
2129
+ // ========== Signature Verification ==========
2130
+ /** Verify an arbitrary signature */
2131
+ async verifySignature(request) {
2132
+ return this.http.post("/auth/verify-signature", request);
2133
+ }
2134
+ };
2135
+ var SmartEngineError2 = class extends Error {
2136
+ constructor(message, statusCode, details) {
2137
+ super(message);
2138
+ this.statusCode = statusCode;
2139
+ this.details = details;
2140
+ this.name = "SmartEngineError";
2141
+ }
2142
+ statusCode;
2143
+ details;
2144
+ };
2145
+ function validateClientUrl(url, allowInsecure = false) {
2146
+ try {
2147
+ const parsed = new URL(url);
2148
+ if (!["http:", "https:"].includes(parsed.protocol)) {
2149
+ throw new SmartEngineError2(`Invalid protocol: ${parsed.protocol}`, 400);
2150
+ }
2151
+ if (!allowInsecure && parsed.protocol !== "https:") {
2152
+ throw new SmartEngineError2(
2153
+ "HTTPS is required for secure connections. Set allowInsecure=true for local development.",
2154
+ 400
2155
+ );
2156
+ }
2157
+ return parsed.origin;
2158
+ } catch (error) {
2159
+ if (error instanceof SmartEngineError2) throw error;
2160
+ throw new SmartEngineError2(`Invalid URL: ${url}`, 400);
2161
+ }
2162
+ }
2163
+
2164
+ // src/gateway/routing/index.ts
2165
+ var RoutingClient = class {
2166
+ constructor(http) {
2167
+ this.http = http;
2168
+ }
2169
+ http;
2170
+ /** Register a new host */
2171
+ async registerHost(request) {
2172
+ return this.http.post("/routing/hosts", request);
2173
+ }
2174
+ /** Unregister a host */
2175
+ async unregisterHost(hostId) {
2176
+ return this.http.delete(`/routing/hosts/${encodeURIComponent(hostId)}`);
2177
+ }
2178
+ /** Get all registered hosts */
2179
+ async getAllHosts() {
2180
+ return this.http.get("/routing/hosts");
2181
+ }
2182
+ /** Get only verified hosts */
2183
+ async getVerifiedHosts() {
2184
+ return this.http.get("/routing/hosts/verified");
2185
+ }
2186
+ /** Get a specific host by ID */
2187
+ async getHost(hostId) {
2188
+ return this.http.get(`/routing/hosts/${encodeURIComponent(hostId)}`);
2189
+ }
2190
+ /** Verify a host */
2191
+ async verifyHost(hostId) {
2192
+ return this.http.post(`/routing/hosts/${encodeURIComponent(hostId)}/verify`, {});
2193
+ }
2194
+ /** Set routing configuration for an app */
2195
+ async setRoutingConfig(appId, config) {
2196
+ return this.http.put(`/routing/config/${encodeURIComponent(appId)}`, config);
2197
+ }
2198
+ /** Get routing configuration for an app */
2199
+ async getRoutingConfig(appId) {
2200
+ return this.http.get(`/routing/config/${encodeURIComponent(appId)}`);
2201
+ }
2202
+ /** Proxy a request through the gateway */
2203
+ async proxyRequest(request) {
2204
+ return this.http.post("/routing/proxy", request);
2205
+ }
2206
+ /** Get routing statistics */
2207
+ async getStats() {
2208
+ return this.http.get("/routing/stats");
2209
+ }
2210
+ /** Map a domain to an application */
2211
+ async mapDomainToApp(domain, appId) {
2212
+ return this.http.post(`/routing/domains/${encodeURIComponent(domain)}/map`, { appId });
2213
+ }
2214
+ };
2215
+
2216
+ // src/gateway/domains/index.ts
2217
+ var DomainsClient = class {
2218
+ constructor(http) {
2219
+ this.http = http;
2220
+ }
2221
+ http;
2222
+ /** Register a new domain */
2223
+ async register(request) {
2224
+ return this.http.post("/domains", request);
2225
+ }
2226
+ /** Check domain availability */
2227
+ async checkAvailability(domain) {
2228
+ return this.http.get(`/domains/check/${encodeURIComponent(domain)}`);
2229
+ }
2230
+ /** Get domain information */
2231
+ async getInfo(domain) {
2232
+ return this.http.get(`/domains/${encodeURIComponent(domain)}`);
2233
+ }
2234
+ /** List domains, optionally filtered by owner */
2235
+ async list(owner) {
2236
+ const params = owner ? `?owner=${encodeURIComponent(owner)}` : "";
2237
+ return this.http.get(`/domains${params}`);
2238
+ }
2239
+ /** Generate a verification token */
2240
+ async generateVerificationToken(domain, method) {
2241
+ return this.http.post(`/domains/${encodeURIComponent(domain)}/verification`, { method });
2242
+ }
2243
+ /** Verify domain ownership */
2244
+ async verifyOwnership(domain, token) {
2245
+ return this.http.post(`/domains/${encodeURIComponent(domain)}/verify`, { token });
2246
+ }
2247
+ /** Configure DNS records for a domain */
2248
+ async configureDns(domain, records) {
2249
+ return this.http.post(`/domains/${encodeURIComponent(domain)}/dns`, { records });
2250
+ }
2251
+ /** Enable DNSSEC for a domain */
2252
+ async enableDnssec(domain) {
2253
+ return this.http.post(`/domains/${encodeURIComponent(domain)}/dnssec/enable`, {});
2254
+ }
2255
+ /** Disable DNSSEC for a domain */
2256
+ async disableDnssec(domain) {
2257
+ return this.http.post(`/domains/${encodeURIComponent(domain)}/dnssec/disable`, {});
2258
+ }
2259
+ /** Renew a domain */
2260
+ async renew(domain, years) {
2261
+ return this.http.post(`/domains/${encodeURIComponent(domain)}/renew`, { years: years ?? 1 });
2262
+ }
2263
+ /** Initiate a domain transfer */
2264
+ async transfer(domain, request) {
2265
+ return this.http.post(`/domains/${encodeURIComponent(domain)}/transfer`, request);
2266
+ }
2267
+ /** Approve a pending domain transfer */
2268
+ async approveTransfer(domain) {
2269
+ return this.http.post(`/domains/${encodeURIComponent(domain)}/transfer/approve`, {});
2270
+ }
2271
+ /** Reject a pending domain transfer */
2272
+ async rejectTransfer(domain) {
2273
+ return this.http.post(`/domains/${encodeURIComponent(domain)}/transfer/reject`, {});
2274
+ }
2275
+ /** Suspend a domain */
2276
+ async suspend(domain, reason) {
2277
+ return this.http.post(`/domains/${encodeURIComponent(domain)}/suspend`, { reason });
2278
+ }
2279
+ /** Unsuspend a domain */
2280
+ async unsuspend(domain) {
2281
+ return this.http.post(`/domains/${encodeURIComponent(domain)}/unsuspend`, {});
2282
+ }
2283
+ };
2284
+
2285
+ // src/gateway/dns/index.ts
2286
+ var DnsClient = class {
2287
+ constructor(http) {
2288
+ this.http = http;
2289
+ }
2290
+ http;
2291
+ /** Resolve a DNS name */
2292
+ async resolve(name, type, dnssec) {
2293
+ const params = new URLSearchParams({ name });
2294
+ if (type) params.set("type", type);
2295
+ if (dnssec !== void 0) params.set("dnssec", String(dnssec));
2296
+ return this.http.get(`/dns/resolve?${params.toString()}`);
2297
+ }
2298
+ /** Batch resolve multiple DNS queries */
2299
+ async resolveBatch(queries) {
2300
+ return this.http.post("/dns/resolve/batch", { queries });
2301
+ }
2302
+ /** List all DNS zones */
2303
+ async listZones() {
2304
+ return this.http.get("/dns/zones");
2305
+ }
2306
+ /** Get a specific zone */
2307
+ async getZone(zoneName) {
2308
+ return this.http.get(`/dns/zones/${encodeURIComponent(zoneName)}`);
2309
+ }
2310
+ /** Create a new DNS zone */
2311
+ async createZone(request) {
2312
+ return this.http.post("/dns/zones", request);
2313
+ }
2314
+ /** Delete a DNS zone */
2315
+ async deleteZone(zoneName) {
2316
+ return this.http.delete(`/dns/zones/${encodeURIComponent(zoneName)}`);
2317
+ }
2318
+ /** Add a record to a zone */
2319
+ async addRecord(zoneName, record) {
2320
+ return this.http.post(`/dns/zones/${encodeURIComponent(zoneName)}/records`, record);
2321
+ }
2322
+ /** Update a record in a zone */
2323
+ async updateRecord(zoneName, recordId, updates) {
2324
+ return this.http.put(
2325
+ `/dns/zones/${encodeURIComponent(zoneName)}/records/${encodeURIComponent(recordId)}`,
2326
+ updates
2327
+ );
2328
+ }
2329
+ /** Delete a record from a zone */
2330
+ async deleteRecord(zoneName, recordId) {
2331
+ return this.http.delete(
2332
+ `/dns/zones/${encodeURIComponent(zoneName)}/records/${encodeURIComponent(recordId)}`
2333
+ );
2334
+ }
2335
+ /** Generate DNSSEC keys for a zone */
2336
+ async generateDnssecKeys(zoneName, algorithm) {
2337
+ return this.http.post(`/dns/zones/${encodeURIComponent(zoneName)}/dnssec/keys`, {
2338
+ algorithm
2339
+ });
2340
+ }
2341
+ /** Get DNSSEC keys for a zone */
2342
+ async getDnssecKeys(zoneName) {
2343
+ return this.http.get(`/dns/zones/${encodeURIComponent(zoneName)}/dnssec/keys`);
2344
+ }
2345
+ /** Get DS record for a zone (for registrar configuration) */
2346
+ async getDsRecord(zoneName) {
2347
+ return this.http.get(`/dns/zones/${encodeURIComponent(zoneName)}/dnssec/ds`);
2348
+ }
2349
+ /** Clear DNS cache */
2350
+ async clearCache() {
2351
+ return this.http.post("/dns/cache/clear", {});
2352
+ }
2353
+ };
2354
+
2355
+ // src/gateway/client.ts
2356
+ var SmartGatewayClient = class {
2357
+ http;
2358
+ /** Host routing and proxy management */
2359
+ routing;
2360
+ /** Domain registration and management */
2361
+ domains;
2362
+ /** DNS resolution and zone management */
2363
+ dns;
2364
+ constructor(config) {
2365
+ const baseUrl = config.baseUrl.replace(/\/+$/, "");
2366
+ this.http = createHttpClient({
2367
+ baseUrl: `${baseUrl}/api/v3`,
2368
+ apiKey: config.apiKey,
2369
+ authToken: config.authToken,
2370
+ timeout: config.timeout
2371
+ });
2372
+ this.routing = new RoutingClient(this.http);
2373
+ this.domains = new DomainsClient(this.http);
2374
+ this.dns = new DnsClient(this.http);
2375
+ }
2376
+ // ========== Health & Metrics ==========
2377
+ /** Get gateway health status */
2378
+ async getHealth() {
2379
+ return this.http.get("/health");
2380
+ }
2381
+ /** Get gateway status with host and domain counts */
2382
+ async getStatus() {
2383
+ return this.http.get("/status");
2384
+ }
2385
+ /** Check gateway readiness */
2386
+ async getReadiness() {
2387
+ return this.http.get("/ready");
2388
+ }
2389
+ /** Check gateway liveness */
2390
+ async getLiveness() {
2391
+ return this.http.get("/live");
2392
+ }
2393
+ /** Get detailed gateway metrics */
2394
+ async getMetrics(refresh) {
2395
+ const params = refresh ? "?refresh=true" : "";
2396
+ return this.http.get(`/metrics${params}`);
2397
+ }
2398
+ /** Get metrics summary */
2399
+ async getMetricsSummary() {
2400
+ return this.http.get("/metrics/summary");
2401
+ }
2402
+ };
2403
+
2404
+ // src/baas/database/index.ts
2405
+ var DatabaseClient = class {
2406
+ constructor(http, getAppId) {
2407
+ this.http = http;
2408
+ this.getAppId = getAppId;
2409
+ }
2410
+ http;
2411
+ getAppId;
2412
+ /**
2413
+ * Insert a document into a collection
2414
+ */
2415
+ async insert(collection, document) {
2416
+ const appId = this.getAppId();
2417
+ return this.http.post(
2418
+ `/api/db/${encodeURIComponent(appId)}/${encodeURIComponent(collection)}`,
2419
+ document
2420
+ );
2421
+ }
2422
+ /**
2423
+ * Find documents in a collection
2424
+ */
2425
+ async find(collection, query, options) {
2426
+ const appId = this.getAppId();
2427
+ const params = new URLSearchParams();
2428
+ if (query && Object.keys(query).length > 0) {
2429
+ params.set("query", JSON.stringify(query));
2430
+ }
2431
+ if (options?.limit !== void 0) params.set("limit", String(options.limit));
2432
+ if (options?.skip !== void 0) params.set("skip", String(options.skip));
2433
+ if (options?.sort) params.set("sort", options.sort);
2434
+ const qs = params.toString();
2435
+ return this.http.get(
2436
+ `/api/db/${encodeURIComponent(appId)}/${encodeURIComponent(collection)}${qs ? `?${qs}` : ""}`
2437
+ );
2438
+ }
2439
+ /**
2440
+ * Update a document in a collection
2441
+ */
2442
+ async update(collection, documentId, updates) {
2443
+ const appId = this.getAppId();
2444
+ return this.http.put(
2445
+ `/api/db/${encodeURIComponent(appId)}/${encodeURIComponent(collection)}/${encodeURIComponent(documentId)}`,
2446
+ updates
2447
+ );
2448
+ }
2449
+ /**
2450
+ * Delete a document from a collection
2451
+ */
2452
+ async delete(collection, documentId) {
2453
+ const appId = this.getAppId();
2454
+ return this.http.delete(
2455
+ `/api/db/${encodeURIComponent(appId)}/${encodeURIComponent(collection)}/${encodeURIComponent(documentId)}`
2456
+ );
2457
+ }
2458
+ /**
2459
+ * List collections for the app
2460
+ */
2461
+ async listCollections() {
2462
+ const appId = this.getAppId();
2463
+ return this.http.get(`/api/db/${encodeURIComponent(appId)}`);
2464
+ }
2465
+ // ========== State Proofs ==========
2466
+ /**
2467
+ * Get the current state root for the app
2468
+ */
2469
+ async getStateRoot() {
2470
+ const appId = this.getAppId();
2471
+ return this.http.get(`/api/db/${encodeURIComponent(appId)}/state/root`);
2472
+ }
2473
+ /**
2474
+ * Get a Merkle proof for a specific document
2475
+ */
2476
+ async getDocumentProof(documentId) {
2477
+ const appId = this.getAppId();
2478
+ return this.http.get(
2479
+ `/api/db/${encodeURIComponent(appId)}/${encodeURIComponent(documentId)}/proof`
2480
+ );
2481
+ }
2482
+ /**
2483
+ * Get state transitions (audit log)
2484
+ */
2485
+ async getStateTransitions(options) {
2486
+ const appId = this.getAppId();
2487
+ const params = new URLSearchParams();
2488
+ if (options?.fromBlock !== void 0) params.set("fromBlock", String(options.fromBlock));
2489
+ if (options?.toBlock !== void 0) params.set("toBlock", String(options.toBlock));
2490
+ if (options?.limit !== void 0) params.set("limit", String(options.limit));
2491
+ const qs = params.toString();
2492
+ return this.http.get(
2493
+ `/api/db/${encodeURIComponent(appId)}/state/transitions${qs ? `?${qs}` : ""}`
2494
+ );
2495
+ }
2496
+ /**
2497
+ * Get database statistics
2498
+ */
2499
+ async getDbStats() {
2500
+ const appId = this.getAppId();
2501
+ return this.http.get(`/api/db/${encodeURIComponent(appId)}/stats`);
2502
+ }
2503
+ };
2504
+
2505
+ // src/baas/storage/index.ts
2506
+ var StorageClient = class {
2507
+ constructor(http, getAppId) {
2508
+ this.http = http;
2509
+ this.getAppId = getAppId;
2510
+ }
2511
+ http;
2512
+ getAppId;
2513
+ /**
2514
+ * Upload a file to storage
2515
+ */
2516
+ async upload(file, filename, metadata) {
2517
+ const appId = this.getAppId();
2518
+ return this.http.upload(`/api/storage/${encodeURIComponent(appId)}/upload`, file, filename, metadata);
2519
+ }
2520
+ /**
2521
+ * Download a file by CID
2522
+ */
2523
+ async download(cid) {
2524
+ return this.http.get(`/api/storage/download/${encodeURIComponent(cid)}`);
2525
+ }
2526
+ /**
2527
+ * Get file metadata
2528
+ */
2529
+ async getMetadata(cid) {
2530
+ return this.http.get(`/api/storage/metadata/${encodeURIComponent(cid)}`);
2531
+ }
2532
+ /**
2533
+ * Delete a file
2534
+ */
2535
+ async delete(cid) {
2536
+ const appId = this.getAppId();
2537
+ return this.http.delete(`/api/storage/${encodeURIComponent(appId)}/${encodeURIComponent(cid)}`);
2538
+ }
2539
+ /**
2540
+ * Get file info
2541
+ */
2542
+ async getFile(cid) {
2543
+ const appId = this.getAppId();
2544
+ return this.http.get(`/api/storage/${encodeURIComponent(appId)}/${encodeURIComponent(cid)}`);
2545
+ }
2546
+ /**
2547
+ * List all files for the app
2548
+ */
2549
+ async listFiles(pagination) {
2550
+ const appId = this.getAppId();
2551
+ const params = new URLSearchParams();
2552
+ if (pagination?.limit !== void 0) params.set("limit", String(pagination.limit));
2553
+ if (pagination?.skip !== void 0) params.set("skip", String(pagination.skip));
2554
+ const qs = params.toString();
2555
+ return this.http.get(`/api/storage/${encodeURIComponent(appId)}/files${qs ? `?${qs}` : ""}`);
2556
+ }
2557
+ /**
2558
+ * Get storage usage for the current app
2559
+ */
2560
+ async getUsage() {
2561
+ return this.http.get("/api/storage/usage");
2562
+ }
2563
+ /**
2564
+ * Check if a file exists
2565
+ */
2566
+ async exists(cid) {
2567
+ return this.http.get(`/api/storage/exists/${encodeURIComponent(cid)}`);
2568
+ }
2569
+ };
2570
+
2571
+ // src/baas/functions/index.ts
2572
+ var FunctionsClient = class {
2573
+ constructor(http, getAppId) {
2574
+ this.http = http;
2575
+ this.getAppId = getAppId;
2576
+ }
2577
+ http;
2578
+ getAppId;
2579
+ /**
2580
+ * Deploy a new function
2581
+ */
2582
+ async deploy(request) {
2583
+ const appId = this.getAppId();
2584
+ return this.http.post(`/api/functions/${encodeURIComponent(appId)}`, request);
2585
+ }
2586
+ /**
2587
+ * Invoke a function
2588
+ */
2589
+ async invoke(functionId, payload) {
2590
+ return this.http.post(`/api/functions/${encodeURIComponent(functionId)}/invoke`, payload ?? {});
2591
+ }
2592
+ /**
2593
+ * List all functions
2594
+ */
2595
+ async list() {
2596
+ return this.http.get("/api/functions");
2597
+ }
2598
+ /**
2599
+ * Get function details
2600
+ */
2601
+ async get(functionId) {
2602
+ return this.http.get(`/api/functions/${encodeURIComponent(functionId)}`);
2603
+ }
2604
+ /**
2605
+ * Update a function
2606
+ */
2607
+ async update(functionId, updates) {
2608
+ return this.http.put(`/api/functions/${encodeURIComponent(functionId)}`, updates);
2609
+ }
2610
+ /**
2611
+ * Delete a function
2612
+ */
2613
+ async delete(functionId) {
2614
+ return this.http.delete(`/api/functions/${encodeURIComponent(functionId)}`);
2615
+ }
2616
+ /**
2617
+ * Get function execution logs
2618
+ */
2619
+ async getLogs(functionId, options) {
2620
+ const params = new URLSearchParams();
2621
+ if (options?.limit !== void 0) params.set("limit", String(options.limit));
2622
+ if (options?.startTime) params.set("startTime", options.startTime);
2623
+ if (options?.level) params.set("level", options.level);
2624
+ const qs = params.toString();
2625
+ return this.http.get(`/api/functions/${encodeURIComponent(functionId)}/logs${qs ? `?${qs}` : ""}`);
2626
+ }
2627
+ /**
2628
+ * Get function statistics for an app
2629
+ */
2630
+ async getStats() {
2631
+ const appId = this.getAppId();
2632
+ return this.http.get(`/api/functions/${encodeURIComponent(appId)}/stats`);
2633
+ }
2634
+ };
2635
+
2636
+ // src/baas/messaging/index.ts
2637
+ var MessagingClient = class {
2638
+ constructor(http, getAppId) {
2639
+ this.http = http;
2640
+ this.getAppId = getAppId;
2641
+ }
2642
+ http;
2643
+ getAppId;
2644
+ /**
2645
+ * Create a new channel
2646
+ */
2647
+ async createChannel(config) {
2648
+ const appId = this.getAppId();
2649
+ return this.http.post(`/api/messaging/${encodeURIComponent(appId)}/channels`, config);
2650
+ }
2651
+ /**
2652
+ * Delete a channel
2653
+ */
2654
+ async deleteChannel(channelId) {
2655
+ const appId = this.getAppId();
2656
+ return this.http.delete(`/api/messaging/${encodeURIComponent(appId)}/channels/${encodeURIComponent(channelId)}`);
2657
+ }
2658
+ /**
2659
+ * Get a channel by ID
2660
+ */
2661
+ async getChannel(channelId) {
2662
+ const appId = this.getAppId();
2663
+ return this.http.get(`/api/messaging/${encodeURIComponent(appId)}/channels/${encodeURIComponent(channelId)}`);
2664
+ }
2665
+ /**
2666
+ * List all channels for the app
2667
+ */
2668
+ async listChannels() {
2669
+ const appId = this.getAppId();
2670
+ return this.http.get(`/api/messaging/${encodeURIComponent(appId)}/channels`);
2671
+ }
2672
+ /**
2673
+ * Publish a message to a channel
2674
+ */
2675
+ async publish(channel, message, metadata) {
2676
+ const appId = this.getAppId();
2677
+ return this.http.post(
2678
+ `/api/messaging/${encodeURIComponent(appId)}/channels/${encodeURIComponent(channel)}/publish`,
2679
+ { data: message, metadata }
2680
+ );
2681
+ }
2682
+ /**
2683
+ * Get message history for a channel
2684
+ */
2685
+ async getHistory(channel, options) {
2686
+ const appId = this.getAppId();
2687
+ const params = new URLSearchParams();
2688
+ if (options?.limit !== void 0) params.set("limit", String(options.limit));
2689
+ if (options?.before) params.set("before", options.before);
2690
+ if (options?.after) params.set("after", options.after);
2691
+ const qs = params.toString();
2692
+ return this.http.get(
2693
+ `/api/messaging/${encodeURIComponent(appId)}/channels/${encodeURIComponent(channel)}/history${qs ? `?${qs}` : ""}`
2694
+ );
2695
+ }
2696
+ /**
2697
+ * Set presence for a member
2698
+ */
2699
+ async setPresence(member) {
2700
+ const appId = this.getAppId();
2701
+ return this.http.post(`/api/messaging/${encodeURIComponent(appId)}/presence`, member);
2702
+ }
2703
+ /**
2704
+ * Remove presence for a member
2705
+ */
2706
+ async removePresence(memberId) {
2707
+ const appId = this.getAppId();
2708
+ return this.http.delete(`/api/messaging/${encodeURIComponent(appId)}/presence/${encodeURIComponent(memberId)}`);
2709
+ }
2710
+ /**
2711
+ * Get presence info for a channel
2712
+ */
2713
+ async getPresence(channel) {
2714
+ const appId = this.getAppId();
2715
+ return this.http.get(`/api/messaging/${encodeURIComponent(appId)}/presence/${encodeURIComponent(channel)}`);
2716
+ }
2717
+ /**
2718
+ * Get messaging statistics
2719
+ */
2720
+ async getStats() {
2721
+ const appId = this.getAppId();
2722
+ return this.http.get(`/api/messaging/${encodeURIComponent(appId)}/stats`);
2723
+ }
2724
+ };
2725
+
2726
+ // src/baas/deployment/index.ts
2727
+ var DeploymentClient = class {
2728
+ constructor(http) {
2729
+ this.http = http;
2730
+ }
2731
+ http;
2732
+ /**
2733
+ * Create (deploy) a new app
2734
+ */
2735
+ async create(request) {
2736
+ return this.http.post("/api/deployment/apps", request);
2737
+ }
2738
+ /**
2739
+ * List all deployed apps
2740
+ */
2741
+ async list() {
2742
+ return this.http.get("/api/deployment/apps");
2743
+ }
2744
+ /**
2745
+ * Get app details
2746
+ */
2747
+ async get(appId) {
2748
+ return this.http.get(`/api/deployment/apps/${encodeURIComponent(appId)}`);
2749
+ }
2750
+ /**
2751
+ * Update app configuration
2752
+ */
2753
+ async update(appId, updates) {
2754
+ return this.http.put(`/api/deployment/apps/${encodeURIComponent(appId)}`, updates);
2755
+ }
2756
+ /**
2757
+ * Delete an app
2758
+ */
2759
+ async delete(appId) {
2760
+ return this.http.delete(`/api/deployment/apps/${encodeURIComponent(appId)}`);
2761
+ }
2762
+ /**
2763
+ * Suspend an app
2764
+ */
2765
+ async suspend(appId) {
2766
+ return this.http.post(`/api/deployment/apps/${encodeURIComponent(appId)}/suspend`, {});
2767
+ }
2768
+ /**
2769
+ * Resume a suspended app
2770
+ */
2771
+ async resume(appId) {
2772
+ return this.http.post(`/api/deployment/apps/${encodeURIComponent(appId)}/resume`, {});
2773
+ }
2774
+ /**
2775
+ * Get deployment statistics
2776
+ */
2777
+ async getStats() {
2778
+ return this.http.get("/api/deployment/stats");
2779
+ }
2780
+ };
2781
+
2782
+ // src/baas/agents/index.ts
2783
+ var AgentsClient = class {
2784
+ constructor(http) {
2785
+ this.http = http;
2786
+ }
2787
+ http;
2788
+ /** Register a new agent */
2789
+ async register(request) {
2790
+ return this.http.post("/api/agents/register", request);
2791
+ }
2792
+ /** Get agent details */
2793
+ async get(agentId) {
2794
+ return this.http.get(`/api/agents/${encodeURIComponent(agentId)}`);
2795
+ }
2796
+ /** List all agents */
2797
+ async list() {
2798
+ return this.http.get("/api/agents");
2799
+ }
2800
+ /** Fund an agent */
2801
+ async fund(agentId, request) {
2802
+ return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/fund`, request);
2803
+ }
2804
+ /** Execute a trade */
2805
+ async trade(agentId, request) {
2806
+ return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/trade`, request);
2807
+ }
2808
+ /** Withdraw funds from agent */
2809
+ async withdraw(agentId, request) {
2810
+ return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/withdraw`, request);
2811
+ }
2812
+ /** Pause an agent */
2813
+ async pause(agentId) {
2814
+ return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/pause`, {});
2815
+ }
2816
+ /** Resume a paused agent */
2817
+ async resume(agentId) {
2818
+ return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/resume`, {});
2819
+ }
2820
+ /** Revoke an agent (permanent) */
2821
+ async revoke(agentId) {
2822
+ return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/revoke`, {});
2823
+ }
2824
+ /** Update agent rules */
2825
+ async updateRules(agentId, rules) {
2826
+ return this.http.put(`/api/agents/${encodeURIComponent(agentId)}/rules`, rules);
2827
+ }
2828
+ /** Get agent events */
2829
+ async getEvents(agentId) {
2830
+ return this.http.get(`/api/agents/${encodeURIComponent(agentId)}/events`);
2831
+ }
2832
+ /** Get agent balances across chains */
2833
+ async getBalances(agentId) {
2834
+ return this.http.get(`/api/agents/${encodeURIComponent(agentId)}/balances`);
2835
+ }
2836
+ /** Approve a pending agent operation */
2837
+ async approve(agentId, operationId) {
2838
+ return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/approve/${encodeURIComponent(operationId)}`, {});
2839
+ }
2840
+ /** Reject a pending agent operation */
2841
+ async reject(agentId, operationId) {
2842
+ return this.http.post(`/api/agents/${encodeURIComponent(agentId)}/reject/${encodeURIComponent(operationId)}`, {});
2843
+ }
2844
+ };
2845
+
2846
+ // src/baas/client.ts
2847
+ var BaasClient = class {
2848
+ hostUrl;
2849
+ pathPrefix;
2850
+ appId;
2851
+ timeout;
2852
+ allowInsecure;
2853
+ authToken = null;
2854
+ http;
2855
+ /** Last HTTP error (for getHttpHealth) */
2856
+ lastHttpError;
2857
+ // ========== Sub-Clients ==========
2858
+ /** Trustless database with state proofs and Merkle verification */
2859
+ db;
2860
+ /** Decentralized file storage */
2861
+ storage;
2862
+ /** Serverless function deployment and invocation */
2863
+ functions;
2864
+ /** Real-time pub/sub messaging with channels, history, and presence */
2865
+ messaging;
2866
+ /** App deployment lifecycle management */
2867
+ deployment;
2868
+ /** Autonomous smart agent management */
2869
+ agents;
2870
+ constructor(config) {
2871
+ this.allowInsecure = config.allowInsecure ?? false;
2872
+ this.hostUrl = validateUrl2(config.hostUrl, this.allowInsecure);
2873
+ this.appId = config.appId;
2874
+ this.timeout = config.timeout ?? 3e4;
2875
+ const prefix = (config.pathPrefix ?? "").replace(/\/$/, "");
2876
+ this.pathPrefix = prefix ? prefix.startsWith("/") ? prefix : `/${prefix}` : "";
2877
+ const baseUrlWithPrefix = this.pathPrefix ? this.hostUrl.replace(/\/$/, "") + this.pathPrefix : this.hostUrl;
2878
+ this.http = createHttpClient({
2879
+ baseUrl: baseUrlWithPrefix,
2880
+ timeout: this.timeout
2881
+ });
2882
+ const getAppId = () => this.requireAppId();
2883
+ this.db = new DatabaseClient(this.http, getAppId);
2884
+ this.storage = new StorageClient(this.http, getAppId);
2885
+ this.functions = new FunctionsClient(this.http, getAppId);
2886
+ this.messaging = new MessagingClient(this.http, getAppId);
2887
+ this.deployment = new DeploymentClient(this.http);
2888
+ this.agents = new AgentsClient(this.http);
2889
+ }
2890
+ /** Set the app ID (for newly registered apps) */
2891
+ setAppId(appId) {
2892
+ this.appId = appId;
2893
+ }
2894
+ /** Check if the client is authenticated */
2895
+ isAuthenticated() {
2896
+ return this.authToken !== null;
2897
+ }
2898
+ /** Get the current app ID */
2899
+ getAppId() {
2900
+ return this.appId;
2901
+ }
2902
+ /**
2903
+ * Get HTTP resilience health information
2904
+ * @returns Object with circuit breaker state and last error (if any)
2905
+ */
2906
+ getHttpHealth() {
2907
+ return {
2908
+ breaker: null,
2909
+ lastError: this.lastHttpError
2910
+ };
2911
+ }
2912
+ requireAppId() {
2913
+ if (!this.appId) {
2914
+ throw new BaasError(
2915
+ "App ID required. Either provide appId in config or call register() first.",
2916
+ 400
2917
+ );
2918
+ }
2919
+ return this.appId;
2920
+ }
2921
+ // ========== Authentication ==========
2922
+ /**
2923
+ * Authenticate with the BaaS host using wallet challenge-response
2924
+ *
2925
+ * 1. Requests a challenge message from the host
2926
+ * 2. Signs the challenge with the provided signing function
2927
+ * 3. Submits the signature for verification
2928
+ * 4. Stores the JWT token for subsequent requests
2929
+ */
2930
+ async authenticate(options) {
2931
+ const { chain, walletAddress, publicKey, signFn } = options;
2932
+ const challenge = await this.post("/api/auth/challenge", {
2933
+ chain,
2934
+ walletAddress,
2935
+ appId: this.appId
2936
+ });
2937
+ const signature = await signFn(challenge.message);
2938
+ const result = await this.post("/api/auth/verify", {
2939
+ challengeId: challenge.challengeId,
2940
+ signature,
2941
+ publicKey
2942
+ });
2943
+ this.authToken = result.token;
2944
+ this.http.setAuthToken?.(result.token);
2945
+ return result;
2946
+ }
2947
+ /** Validate the current session */
2948
+ async validateSession() {
2949
+ this.requireAuth();
2950
+ return this.get("/api/auth/session");
2951
+ }
2952
+ /** Destroy the current session on server and clear local token */
2953
+ async logout() {
2954
+ if (this.authToken) {
2955
+ try {
2956
+ await this.post("/api/auth/logout", {});
2957
+ } catch {
2958
+ }
2959
+ }
2960
+ this.authToken = null;
2961
+ }
2962
+ // ========== App Registration ==========
2963
+ /** Register a new app on the BaaS host */
2964
+ async register(request) {
2965
+ this.requireAuth();
2966
+ return this.post("/api/deployment/apps", request);
2967
+ }
2968
+ // ========== HTTP Helpers ==========
2969
+ requireAuth() {
2970
+ if (!this.authToken) {
2971
+ throw new BaasError("Authentication required. Call authenticate() first.", 401);
2972
+ }
2973
+ }
2974
+ getHeaders() {
2975
+ const headers = {
2976
+ "Content-Type": "application/json"
2977
+ };
2978
+ if (this.authToken) {
2979
+ headers["Authorization"] = `Bearer ${this.authToken}`;
2980
+ }
2981
+ return headers;
2982
+ }
2983
+ async post(path, body) {
2984
+ return this.request("POST", path, body);
2985
+ }
2986
+ async get(path) {
2987
+ return this.request("GET", path);
2988
+ }
2989
+ async request(method, path, body) {
2990
+ const url = `${this.hostUrl}${this.pathPrefix}${path}`;
2991
+ const controller = new AbortController();
2992
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
2993
+ try {
2994
+ const options = {
2995
+ method,
2996
+ headers: this.getHeaders(),
2997
+ signal: controller.signal
2998
+ };
2999
+ if (body !== void 0) {
3000
+ options.body = JSON.stringify(body);
3001
+ }
3002
+ const response = await fetch(url, options);
3003
+ clearTimeout(timeoutId);
3004
+ if (!response.ok) {
3005
+ const errorData = await response.json().catch(() => ({}));
3006
+ throw new BaasError(
3007
+ errorData.message || `API error: ${response.status} ${response.statusText}`,
3008
+ response.status,
3009
+ errorData
3010
+ );
3011
+ }
3012
+ const text = await response.text();
3013
+ if (!text) return void 0;
3014
+ return JSON.parse(text);
3015
+ } catch (error) {
3016
+ clearTimeout(timeoutId);
3017
+ if (error instanceof BaasError) throw error;
3018
+ const err = error;
3019
+ if (err.name === "AbortError") {
3020
+ throw new BaasError("Request timeout", 408);
3021
+ }
3022
+ throw new BaasError(`Network error: ${err.message}`, 0, { originalError: err.message });
3023
+ }
3024
+ }
3025
+ };
3026
+ var BaasError = class extends Error {
3027
+ constructor(message, statusCode, details) {
3028
+ super(message);
3029
+ this.statusCode = statusCode;
3030
+ this.details = details;
3031
+ this.name = "BaasError";
3032
+ }
3033
+ statusCode;
3034
+ details;
3035
+ };
3036
+ function validateUrl2(url, allowInsecure = false) {
3037
+ try {
3038
+ const parsed = new URL(url);
3039
+ if (!["http:", "https:"].includes(parsed.protocol)) {
3040
+ throw new BaasError(`Invalid protocol: ${parsed.protocol}`, 400);
3041
+ }
3042
+ if (!allowInsecure && parsed.protocol !== "https:") {
3043
+ throw new BaasError(
3044
+ "HTTPS is required for secure connections. Set allowInsecure=true for local development.",
3045
+ 400
3046
+ );
3047
+ }
3048
+ return parsed.origin;
3049
+ } catch (error) {
3050
+ if (error instanceof BaasError) throw error;
3051
+ throw new BaasError(`Invalid URL: ${url}`, 400);
3052
+ }
3053
+ }
3054
+
3055
+ // src/nestjs/smart-engine.service.ts
3056
+ var SMART_ENGINE_CONFIG = "SMART_ENGINE_CONFIG";
3057
+ exports.SmartEngineService = class SmartEngineService {
3058
+ constructor(config) {
3059
+ this.config = config;
3060
+ }
3061
+ config;
3062
+ logger = new common.Logger(exports.SmartEngineService.name);
3063
+ client = null;
3064
+ baasClient = null;
3065
+ connected = false;
3066
+ reconnectTimer = null;
3067
+ reconnectAttempts = 0;
3068
+ /**
3069
+ * Initialize the service when the module starts
3070
+ */
3071
+ async onModuleInit() {
3072
+ if (!this.config) {
3073
+ this.logger.warn(
3074
+ "SmartEngineService initialized without configuration. Call configure() before using."
3075
+ );
3076
+ return;
3077
+ }
3078
+ await this.initialize(this.config);
3079
+ }
3080
+ /**
3081
+ * Clean up resources when the module is destroyed
3082
+ */
3083
+ async onModuleDestroy() {
3084
+ await this.shutdown();
3085
+ }
3086
+ /**
3087
+ * Initialize the service with configuration
3088
+ *
3089
+ * Can be called manually if not using DI configuration
3090
+ */
3091
+ async initialize(config) {
3092
+ this.logger.log(`Initializing SmartEngineService for ${config.baseUrl}`);
3093
+ try {
3094
+ this.client = new SmartEngineClient({
3095
+ baseUrl: config.baseUrl,
3096
+ apiKey: config.apiKey,
3097
+ authToken: config.authToken,
3098
+ timeout: config.timeout,
3099
+ allowInsecure: config.allowInsecure
3100
+ });
3101
+ this.baasClient = this.createBaasClient(this.client);
3102
+ if (config.testConnection !== false) {
3103
+ await this.testConnection();
3104
+ }
3105
+ this.connected = true;
3106
+ this.reconnectAttempts = 0;
3107
+ this.logger.log("SmartEngineService initialized successfully");
3108
+ } catch (error) {
3109
+ const err = error;
3110
+ this.logger.error(`Failed to initialize SmartEngineService: ${err.message}`);
3111
+ if (config.autoReconnect) {
3112
+ this.scheduleReconnect(config);
3113
+ } else {
3114
+ throw error;
3115
+ }
3116
+ }
3117
+ }
3118
+ /**
3119
+ * Gracefully shutdown the service
3120
+ */
3121
+ async shutdown() {
3122
+ this.logger.log("Shutting down SmartEngineService");
3123
+ if (this.reconnectTimer) {
3124
+ clearTimeout(this.reconnectTimer);
3125
+ this.reconnectTimer = null;
3126
+ }
3127
+ this.client = null;
3128
+ this.baasClient = null;
3129
+ this.connected = false;
3130
+ this.logger.log("SmartEngineService shutdown complete");
3131
+ }
3132
+ /**
3133
+ * Get the SmartEngineClient instance
3134
+ *
3135
+ * @throws SmartEngineError if client is not initialized
3136
+ */
3137
+ getClient() {
3138
+ if (!this.client) {
3139
+ throw new SmartEngineError2(
3140
+ "SmartEngineClient not initialized. Ensure SmartEngineService is configured properly.",
3141
+ 500
3142
+ );
3143
+ }
3144
+ return this.client;
3145
+ }
3146
+ /**
3147
+ * Get the BaaS client for simplified blockchain access
3148
+ *
3149
+ * The BaaS client provides a simplified interface for applications
3150
+ * that need managed blockchain infrastructure access.
3151
+ *
3152
+ * @throws SmartEngineError if client is not initialized
3153
+ */
3154
+ getBaasClient() {
3155
+ if (!this.baasClient) {
3156
+ throw new SmartEngineError2(
3157
+ "BaasClient not initialized. Ensure SmartEngineService is configured properly.",
3158
+ 500
3159
+ );
3160
+ }
3161
+ return this.baasClient;
3162
+ }
3163
+ /**
3164
+ * Check if the service is connected and healthy
3165
+ */
3166
+ isConnected() {
3167
+ return this.connected;
3168
+ }
3169
+ /**
3170
+ * Test the connection to the validator
3171
+ */
3172
+ async testConnection() {
3173
+ if (!this.client) {
3174
+ return false;
3175
+ }
3176
+ try {
3177
+ const health = await this.client.getHealth();
3178
+ this.connected = health.status === "healthy" || health.status === "ok";
3179
+ return this.connected;
3180
+ } catch (error) {
3181
+ const err = error;
3182
+ this.logger.warn(`Connection test failed: ${err.message}`);
3183
+ this.connected = false;
3184
+ return false;
3185
+ }
3186
+ }
3187
+ /**
3188
+ * Get the current connection status
3189
+ */
3190
+ getStatus() {
3191
+ return {
3192
+ connected: this.connected,
3193
+ baseUrl: this.client?.getBaseUrl() ?? null,
3194
+ authenticated: this.client?.isAuthenticated() ?? false,
3195
+ reconnectAttempts: this.reconnectAttempts
3196
+ };
3197
+ }
3198
+ /**
3199
+ * Create a SmartGatewayClient for gateway operations
3200
+ */
3201
+ createGatewayClient(config) {
3202
+ return new SmartGatewayClient(config);
3203
+ }
3204
+ /**
3205
+ * Create a BaaS client for host operations
3206
+ */
3207
+ createHostClient(config) {
3208
+ return new BaasClient(config);
3209
+ }
3210
+ /**
3211
+ * Create a BaaS client wrapper around the SmartEngineClient
3212
+ */
3213
+ createBaasClient(client) {
3214
+ return {
3215
+ client,
3216
+ isHealthy: async () => {
3217
+ try {
3218
+ const health = await client.getHealth();
3219
+ return health.status === "healthy" || health.status === "ok";
3220
+ } catch {
3221
+ return false;
3222
+ }
3223
+ },
3224
+ getBaseUrl: () => client.getBaseUrl()
3225
+ };
3226
+ }
3227
+ /**
3228
+ * Schedule a reconnection attempt
3229
+ */
3230
+ scheduleReconnect(config) {
3231
+ const maxAttempts = config.maxReconnectAttempts ?? 0;
3232
+ const interval = config.reconnectInterval ?? 5e3;
3233
+ if (maxAttempts > 0 && this.reconnectAttempts >= maxAttempts) {
3234
+ this.logger.error(`Max reconnection attempts (${maxAttempts}) reached. Giving up.`);
3235
+ return;
3236
+ }
3237
+ this.reconnectAttempts++;
3238
+ this.logger.log(`Scheduling reconnection attempt ${this.reconnectAttempts} in ${interval}ms`);
3239
+ this.reconnectTimer = setTimeout(async () => {
3240
+ try {
3241
+ await this.initialize(config);
3242
+ } catch {
3243
+ }
3244
+ }, interval);
3245
+ }
3246
+ };
3247
+ exports.SmartEngineService = __decorateClass([
3248
+ common.Injectable(),
3249
+ __decorateParam(0, common.Optional()),
3250
+ __decorateParam(0, common.Inject(SMART_ENGINE_CONFIG))
3251
+ ], exports.SmartEngineService);
3252
+
3253
+ // src/nestjs/smart-engine.module.ts
3254
+ exports.SmartEngineModule = class SmartEngineModule {
3255
+ /**
3256
+ * Configure the module with static configuration
3257
+ *
3258
+ * @param config - SmartEngine service configuration
3259
+ * @param isGlobal - Whether to make the module global (default: true)
3260
+ */
3261
+ static forRoot(config, isGlobal = true) {
3262
+ return {
3263
+ module: exports.SmartEngineModule,
3264
+ global: isGlobal,
3265
+ providers: [
3266
+ {
3267
+ provide: SMART_ENGINE_CONFIG,
3268
+ useValue: config
3269
+ },
3270
+ exports.SmartEngineService
3271
+ ],
3272
+ exports: [exports.SmartEngineService]
3273
+ };
3274
+ }
3275
+ /**
3276
+ * Configure the module with async configuration
3277
+ *
3278
+ * Supports factory functions, configuration classes, and existing providers.
3279
+ *
3280
+ * @param options - Async configuration options
3281
+ */
3282
+ static forRootAsync(options) {
3283
+ const asyncProviders = this.createAsyncProviders(options);
3284
+ return {
3285
+ module: exports.SmartEngineModule,
3286
+ global: options.isGlobal ?? true,
3287
+ imports: options.imports || [],
3288
+ providers: [...asyncProviders, exports.SmartEngineService],
3289
+ exports: [exports.SmartEngineService]
3290
+ };
3291
+ }
3292
+ /**
3293
+ * Create async providers based on configuration options
3294
+ */
3295
+ static createAsyncProviders(options) {
3296
+ if (options.useFactory) {
3297
+ return [
3298
+ {
3299
+ provide: SMART_ENGINE_CONFIG,
3300
+ useFactory: options.useFactory,
3301
+ inject: options.inject || []
3302
+ }
3303
+ ];
3304
+ }
3305
+ if (options.useClass) {
3306
+ return [
3307
+ {
3308
+ provide: options.useClass,
3309
+ useClass: options.useClass
3310
+ },
3311
+ {
3312
+ provide: SMART_ENGINE_CONFIG,
3313
+ useFactory: async (optionsFactory) => optionsFactory.createSmartEngineOptions(),
3314
+ inject: [options.useClass]
3315
+ }
3316
+ ];
3317
+ }
3318
+ if (options.useExisting) {
3319
+ return [
3320
+ {
3321
+ provide: SMART_ENGINE_CONFIG,
3322
+ useFactory: async (optionsFactory) => optionsFactory.createSmartEngineOptions(),
3323
+ inject: [options.useExisting]
3324
+ }
3325
+ ];
3326
+ }
3327
+ throw new Error(
3328
+ "Invalid SmartEngineModuleAsyncOptions: must provide useFactory, useClass, or useExisting"
3329
+ );
3330
+ }
3331
+ };
3332
+ exports.SmartEngineModule = __decorateClass([
3333
+ common.Module({})
3334
+ ], exports.SmartEngineModule);
3335
+
3336
+ exports.SMART_ENGINE_CONFIG = SMART_ENGINE_CONFIG;
3337
+ //# sourceMappingURL=index.js.map
3338
+ //# sourceMappingURL=index.js.map