@hsuite/smart-engines-sdk 3.0.0 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -18,3 +18,14 @@
18
18
  ```
19
19
  npm publish --access=public
20
20
  ```
21
+
22
+ ## 3.0.1 — 2026-05-11
23
+
24
+ **Documentation-only fix.** No code changes.
25
+
26
+ ### Fixed
27
+ - README rewritten end-to-end. The 3.0.0 README documented a non-existent
28
+ `apiKey` connect flow and Hedera-centric examples that contradicted the
29
+ XRPL-canonical architecture. The new README shows the actual Web3
30
+ challenge-response auth pattern, all BaaS sub-clients, the NestJS
31
+ integration, resilience primitives, and accurate peer-dep guidance.
package/README.md CHANGED
@@ -1,373 +1,342 @@
1
1
  # @hsuite/smart-engines-sdk
2
2
 
3
- Type-safe client SDK for Smart Engines multi-chain infrastructure. Build decentralized apps across Hedera, XRPL, Ethereum, Polygon, Solana, Polkadot, Stellar, and Bitcoin.
4
-
5
- ## Installation
3
+ Client SDK for the [Smart Engines V3](https://hsuite.finance) multi-chain
4
+ platform. Build smart-apps and smart-agents that authenticate via Web3
5
+ challenge-response, talk to the network's BaaS surface (database, storage,
6
+ messaging, functions, deployment), and execute chain operations across
7
+ Hedera, XRPL, Polkadot, Solana, Stellar, EVM, and Bitcoin.
6
8
 
7
9
  ```bash
8
- yarn add @hsuite/smart-engines-sdk
9
- # or
10
10
  npm install @hsuite/smart-engines-sdk
11
11
  ```
12
12
 
13
- ## Quick Start
13
+ Plus the peer deps your app actually uses:
14
14
 
15
- ```typescript
16
- import { SmartEngineClient } from '@hsuite/smart-engines-sdk';
15
+ ```bash
16
+ npm install xrpl # required XRPL is canonical for auth
17
+ npm install @hashgraph/sdk # only if your app does Hedera-side ops
18
+ npm install @nestjs/common @nestjs/core # only if you use the NestJS integration
19
+ npm install zod # peer (likely transitive in your app already)
20
+ ```
17
21
 
18
- // Connect to a validator
19
- const client = new SmartEngineClient({
20
- baseUrl: 'https://v3-testnet-sn1.hsuite.network',
21
- apiKey: 'your-api-key',
22
- });
22
+ ---
23
23
 
24
- // Check health
25
- const health = await client.getHealth();
26
- console.log(health.status); // 'ok'
27
- ```
24
+ ## Quick start — Web3 auth + register a smart-app
28
25
 
29
- ## Auto-Discovery with Authentication
26
+ The canonical smart-app bootstrap flow:
30
27
 
31
- Connect to the network automatically via HCS registry:
28
+ ```ts
29
+ import { BaasClient } from '@hsuite/smart-engines-sdk';
30
+ import { Wallet } from 'xrpl';
31
+ import { sign as xrplSign } from 'ripple-keypairs';
32
32
 
33
- ```typescript
34
- import { SmartEngineClient } from '@hsuite/smart-engines-sdk';
35
- import { PrivateKey } from '@hashgraph/sdk';
33
+ // 1. Your XRPL wallet (real production: load XRPL_SEED from env / secret store)
34
+ const wallet = Wallet.fromSeed(process.env.XRPL_SEED!);
36
35
 
37
- const privateKey = PrivateKey.fromString(process.env.HEDERA_PRIVATE_KEY!);
36
+ // 2. Construct the BaaS client
37
+ const baas = new BaasClient({
38
+ hostUrl: 'https://v3-testnet-gateway.hsuite.network',
39
+ appId: 'pending', // will be replaced after register()
40
+ pathPrefix: '/host', // gateway routes /host/* → smart-host
41
+ });
38
42
 
39
- const { client, validator, session } = await SmartEngineClient.connectToNetwork({
40
- network: 'testnet',
41
- registryTopicId: process.env.REGISTRY_TOPIC_ID!,
42
- chain: 'hedera',
43
- address: process.env.HEDERA_ACCOUNT_ID!,
44
- publicKey: privateKey.publicKey.toStringRaw(),
45
- signFn: (challenge) => {
46
- const sig = privateKey.sign(Buffer.from(challenge));
47
- return Buffer.from(sig).toString('hex');
43
+ // 3. Authenticate via Web3 challenge-response
44
+ // Cluster verifies with ripple-keypairs.verify(messageHex.toUpperCase(), signature, publicKey)
45
+ await baas.authenticate({
46
+ chain: 'xrpl',
47
+ walletAddress: wallet.address,
48
+ publicKey: wallet.publicKey,
49
+ signFn: (message) => {
50
+ const messageHex = Buffer.from(message, 'utf-8').toString('hex').toUpperCase();
51
+ return xrplSign(messageHex, wallet.privateKey);
48
52
  },
49
53
  });
50
54
 
51
- console.log(`Connected to ${validator.operator} at ${validator.endpoint}`);
52
- console.log(`Session expires: ${session.expiresAt}`);
53
- ```
54
-
55
- ## API Reference
55
+ // 4. Register a free_testnet smart-app (no HSUITE deposit on testnet; cluster runs DKG)
56
+ const app = await baas.register({
57
+ name: 'My Smart App',
58
+ services: ['database', 'storage', 'messaging', 'functions'],
59
+ });
56
60
 
57
- ### Account Operations
61
+ console.log(`Registered smart-app ${app.appId} — status: ${app.status}`);
62
+ baas.setAppId(app.appId);
63
+ ```
58
64
 
59
- ```typescript
60
- // Create account
61
- const account = await client.createAccount({
62
- chain: 'hedera',
63
- initialBalance: '10',
64
- validatorTimestamp: '1766490325.123456789',
65
- validatorTopicId: '0.0.98765',
66
- });
67
- console.log(`Account: ${account.accountId}`);
65
+ **Why XRPL?** Per the Smart Engines V3 architecture, XRPL is canonical for
66
+ smart-app authentication and registration. The cluster's validator/host pods
67
+ pay their own HCS fees from pod-local operator accounts; smart-apps never
68
+ need Hedera credentials for the framework. Smart-apps can still target any
69
+ chain (Hedera, Solana, …) for their own *business logic* — that's separate
70
+ from the dev wallet used to authenticate.
68
71
 
69
- // Get account info
70
- const info = await client.getAccountInfo('hedera', '0.0.12345');
72
+ **Faster bootstrap?** Use the [`@hsuite/smart-engines-cli`](https://www.npmjs.com/package/@hsuite/smart-engines-cli) — `hsuite init` generates a fresh XRPL wallet + funds it via the testnet faucet + writes `.env.local`, then `hsuite subscribe` registers the smart-app in one command.
71
73
 
72
- // Get balance (native + tokens)
73
- const balance = await client.getBalance('hedera', '0.0.12345');
74
- console.log(`Balance: ${balance.balance} | Tokens: ${balance.tokens.length}`);
75
- ```
74
+ ---
76
75
 
77
- ### Token Operations
76
+ ## Available clients
78
77
 
79
- ```typescript
80
- // Create a fungible token
81
- const token = await client.createToken({
82
- chain: 'hedera',
83
- name: 'My Token',
84
- symbol: 'MTK',
85
- decimals: 8,
86
- initialSupply: '1000000',
87
- type: 'fungible',
88
- validatorTimestamp: '1766490325.123456789',
89
- validatorTopicId: '0.0.98765',
90
- capabilities: {
91
- mintable: true,
92
- burnable: true,
93
- pausable: true,
94
- restrictable: true,
95
- compliant: true,
96
- wipeable: true,
97
- },
98
- });
99
- console.log(`Token: ${token.tokenId}`);
78
+ | Client | Purpose |
79
+ |---|---|
80
+ | `BaasClient` | Authentication + database + storage + functions + messaging + deployment + agents |
81
+ | `SmartEngineClient` | Chain operations: account create, token create / mint / burn / freeze / wipe, transfers, HCS topics, TSS, IPFS |
82
+ | `SmartGatewayClient` | Gateway operations: routing, domains, DNS |
83
+ | `ValidatorAuthClient` | Standalone Web3 challenge-response auth (lower-level than `BaasClient.authenticate`) |
84
+ | `ValidatorDiscoveryClient` | HCS-registry-based validator discovery |
85
+ | `TSSClient`, `IPFSClient`, `TransactionsClient`, `SettlementClient`, `SnapshotsClient` | Direct sub-client access for advanced flows |
86
+ | `MirrorNodeClient` | Hedera mirror-node helper (when your app does Hedera-side queries) |
100
87
 
101
- // Mint additional tokens
102
- await client.mintToken({
103
- chain: 'hedera',
104
- tokenId: token.tokenId,
105
- amount: '500000',
106
- });
88
+ All clients accept the same `pathPrefix: '/host'` option when consumed via
89
+ the cluster gateway. Set `pathPrefix: ''` for direct host access.
107
90
 
108
- // Burn tokens
109
- await client.burnToken({
110
- chain: 'hedera',
111
- tokenId: token.tokenId,
112
- amount: '100',
113
- });
91
+ ---
114
92
 
115
- // Get token info
116
- const tokenInfo = await client.getTokenInfo('hedera', token.tokenId);
117
- console.log(`Supply: ${tokenInfo.totalSupply}`);
118
- console.log(`Capabilities:`, tokenInfo.capabilities);
119
- ```
93
+ ## BaaS sub-clients
120
94
 
121
- ### Token Management (Universal Actions)
95
+ Once authenticated, every BaaS sub-client is reachable from a single
96
+ `BaasClient` instance:
122
97
 
123
- ```typescript
124
- // Pause all operations on a token
125
- await client.pauseToken({ chain: 'hedera', tokenId: '0.0.123' });
126
- await client.unpauseToken({ chain: 'hedera', tokenId: '0.0.123' });
98
+ ### Database (Merkle-anchored key-value store)
127
99
 
128
- // Freeze/unfreeze an account
129
- await client.restrictAccount({ chain: 'hedera', tokenId: '0.0.123', accountId: '0.0.456' });
130
- await client.unrestrictAccount({ chain: 'hedera', tokenId: '0.0.123', accountId: '0.0.456' });
100
+ ```ts
101
+ const record = await baas.db.insert('users', { name: 'Alice', role: 'developer' });
102
+ // { document, stateTransition: { merkleProof, stateRoot, ... } }
131
103
 
132
- // KYC grant/revoke
133
- await client.enableCompliance({ chain: 'hedera', tokenId: '0.0.123', accountId: '0.0.456' });
134
- await client.disableCompliance({ chain: 'hedera', tokenId: '0.0.123', accountId: '0.0.456' });
104
+ const found = await baas.db.find('users', { role: 'developer' });
105
+ // { documents: [...], count }
135
106
 
136
- // Wipe tokens from account (compliance action)
137
- await client.wipeFromAccount({ chain: 'hedera', tokenId: '0.0.123', accountId: '0.0.456', amount: '100' });
107
+ const updated = await baas.db.update('users', record.document._id, { role: 'admin' });
108
+ await baas.db.delete('users', record.document._id);
138
109
  ```
139
110
 
140
- ### Transaction Operations
111
+ Every write returns a cryptographic state-transition proof anchored on-chain — verifiable without re-reading the DB.
141
112
 
142
- ```typescript
143
- // Transfer native currency
144
- const tx = await client.transfer({
145
- chain: 'hedera',
146
- from: '0.0.12345',
147
- to: '0.0.67890',
148
- amount: '5.0',
149
- });
150
- console.log(`TX: ${tx.transactionId} Status: ${tx.status}`);
113
+ ### Storage (IPFS-backed)
151
114
 
152
- // Get transaction details
153
- const details = await client.getTransaction('hedera', tx.transactionId);
115
+ ```ts
116
+ const upload = await baas.storage.upload(file, 'avatar.png');
117
+ // → { fileId, cid, url: 'ipfs://bafy…', size }
154
118
 
155
- // Get receipt
156
- const receipt = await client.getTransactionReceipt('hedera', tx.transactionId);
119
+ const files = await baas.storage.list();
120
+ const usage = await baas.storage.getUsage();
157
121
  ```
158
122
 
159
- ### Multi-Chain Examples
123
+ ### Messaging (pub/sub channels)
160
124
 
161
- The same API works across all supported chains:
125
+ ```ts
126
+ await baas.messaging.publish('events', { type: 'user.created', userId: '...' });
127
+ const sub = await baas.messaging.subscribe('events');
128
+ ```
162
129
 
163
- ```typescript
164
- // Create accounts on different chains
165
- const hederaAccount = await client.createAccount({ chain: 'hedera', initialBalance: '10', ... });
166
- const xrplAccount = await client.createAccount({ chain: 'xrpl', initialBalance: '25', ... });
167
- const ethAccount = await client.createAccount({ chain: 'ethereum', initialBalance: '0.1', ... });
168
- const solAccount = await client.createAccount({ chain: 'solana', initialBalance: '1', ... });
130
+ ### Functions (verifiable compute)
169
131
 
170
- // Check balances across chains
171
- const chains = ['hedera', 'xrpl', 'ethereum', 'solana', 'polkadot', 'stellar', 'bitcoin'];
172
- for (const chain of chains) {
173
- const caps = await client.getChainCapabilities(chain);
174
- console.log(`${chain}: tokens=${caps.hasTokens} nfts=${caps.hasNFTs} dex=${caps.hasDEX}`);
175
- }
132
+ ```ts
133
+ const fn = await baas.functions.deploy({
134
+ name: 'compute-hash',
135
+ runtime: 'node20',
136
+ trigger: 'http',
137
+ code: '...', // your function source
138
+ });
176
139
 
177
- // Query capabilities
178
- const allCaps = await client.getAllCapabilities();
140
+ const result = await baas.functions.invoke(fn.functionId, { input: '...' });
141
+ // Cluster runs in isolated sandboxes across the validator quorum;
142
+ // 2-of-3 TSS consensus required before result is signed.
179
143
  ```
180
144
 
181
- ### Consensus Messaging (Hedera HCS)
145
+ ### Smart Agents (autonomous workers)
146
+
147
+ ```ts
148
+ const agent = await baas.agents.register({
149
+ name: 'Trading Bot',
150
+ capabilities: ['trade', 'withdraw'],
151
+ rules: {
152
+ maxTradeAmount: '1000',
153
+ allowedPairs: ['HBAR/USDC'],
154
+ dailyLimit: '5000',
155
+ requireApprovalAbove: '10000',
156
+ },
157
+ });
158
+
159
+ // Rules are pinned to HCS and enforced by the validator quorum.
160
+ // Every agent action is rules-checked, TSS-signed, then submitted on chain.
182
161
 
183
- ```typescript
184
- // Submit message to HCS topic
185
- const result = await client.submitMessage('hedera', '0.0.98765', JSON.stringify({
186
- type: 'governance.proposal',
187
- data: { title: 'Increase validator cap', description: '...' },
188
- }));
189
- console.log(`Sequence: ${result.sequenceNumber}`);
162
+ await baas.agents.fund(agent.agentId, { chain: 'hedera', amount: '500' });
163
+ await baas.agents.trade(agent.agentId, { chain: 'hedera', pair: 'HBAR/USDC', side: 'buy', amount: '100' });
164
+ await baas.agents.pause(agent.agentId);
165
+ await baas.agents.resume(agent.agentId);
166
+ const events = await baas.agents.getEvents(agent.agentId);
190
167
  ```
191
168
 
192
- ### Validator Management
193
-
194
- ```typescript
195
- // List validator templates
196
- const templates = await client.validators.listTemplates();
169
+ ### Deployment
197
170
 
198
- // Check validator health
199
- const health = await client.validators.getHealth();
171
+ ```ts
172
+ const deployment = await baas.deployment.create({
173
+ name: 'My Smart App v2',
174
+ services: ['database', 'storage', 'messaging'],
175
+ config: { /* app-specific */ },
176
+ });
200
177
 
201
- // Get validator info
202
- const validatorInfo = await client.validators.getInfo();
178
+ const apps = await baas.deployment.list();
179
+ const info = await baas.deployment.get(appId);
180
+ await baas.deployment.suspend(appId);
181
+ await baas.deployment.resume(appId);
203
182
  ```
204
183
 
205
- ### Subscription Management
184
+ ---
206
185
 
207
- ```typescript
208
- // Check subscription status
209
- const status = await client.subscription.getStatus('my-app-id');
186
+ ## Chain operations via `SmartEngineClient`
210
187
 
211
- // Request subscription (deposits HSUITE tokens)
212
- const sub = await client.subscription.request({
213
- appId: 'my-app',
214
- developerAccountId: '0.0.12345',
215
- chain: 'hedera',
216
- selectedTier: 'starter',
217
- selectedNetworks: ['hedera'],
218
- });
219
- console.log(`Deposit to: ${sub.depositWallet} Amount: ${sub.amount}`);
220
- ```
188
+ For direct chain operations independent of BaaS — e.g., a custodial backend
189
+ that creates accounts and tokens on behalf of users:
221
190
 
222
- ### BaaS (Backend-as-a-Service)
191
+ ```ts
192
+ import { SmartEngineClient } from '@hsuite/smart-engines-sdk';
223
193
 
224
- ```typescript
225
- import { BaasClient } from '@hsuite/smart-engines-sdk';
194
+ const client = new SmartEngineClient({
195
+ baseUrl: 'https://v3-testnet-gateway.hsuite.network',
196
+ // Auth via authToken (set after the Web3 challenge flow):
197
+ authToken: '<jwt-from-validator-auth-verify>',
198
+ });
226
199
 
227
- const baas = new BaasClient({
228
- hostUrl: 'https://host.hsuite.network',
229
- appId: 'my-app-id',
200
+ // Create an account on any supported chain
201
+ const account = await client.createAccount({
230
202
  chain: 'hedera',
203
+ initialBalance: '10',
204
+ validatorTimestamp: '...',
205
+ validatorTopicId: '0.0.98765',
231
206
  });
232
207
 
233
- // Authenticate with wallet
234
- await baas.authenticate({
235
- address: '0.0.12345',
236
- signFn: async (challenge) => privateKey.sign(Buffer.from(challenge)).toString('hex'),
208
+ // Create a fungible token
209
+ const token = await client.createToken({
210
+ chain: 'hedera',
211
+ name: 'My Token', symbol: 'MTK',
212
+ decimals: 8, initialSupply: '1000000',
213
+ type: 'fungible',
214
+ capabilities: { mintable: true, burnable: true, pausable: true, restrictable: true, compliant: true, wipeable: true },
215
+ validatorTimestamp: '...', validatorTopicId: '0.0.98765',
237
216
  });
238
217
 
239
- // Database operations (with Merkle proofs)
240
- const doc = await baas.database.insert('users', { name: 'Alice', role: 'admin' });
241
- const users = await baas.database.find('users', { role: 'admin' });
242
- const proof = await baas.database.getProof('users', doc.id); // Merkle proof
243
-
244
- // Storage (IPFS-backed)
245
- const file = await baas.storage.upload('data.json', Buffer.from(JSON.stringify(data)));
246
- const download = await baas.storage.download(file.fileId);
247
-
248
- // Serverless functions (Ed25519 code signing required)
249
- await baas.functions.deploy({
250
- name: 'process-payment',
251
- runtime: 'nodejs',
252
- signedCode: { code, signature, publicKey, timestamp, hash },
218
+ // Transfer
219
+ const tx = await client.transfer({
220
+ chain: 'hedera', from: '0.0.1', to: '0.0.2', amount: '1.5',
221
+ validatorTimestamp: '...', validatorTopicId: '0.0.98765',
253
222
  });
254
- const result = await baas.functions.invoke('process-payment', { amount: 100 });
255
223
 
256
- // Real-time messaging
257
- await baas.messaging.publish('notifications', { type: 'payment', amount: 100 });
258
- ```
224
+ // Balance + info
225
+ const balance = await client.getBalance('hedera', '0.0.12345');
226
+ const info = await client.getAccountInfo('hedera', '0.0.12345');
259
227
 
260
- ## Error Handling
228
+ // HCS topic ops, IPFS pinning, TSS signing — all available via sub-clients
229
+ await client.tss.signMPC({ chain: 'hedera', entityId: '...', transactionBytes: '0x...' });
230
+ await client.ipfs.upload(file, 'document.pdf');
231
+ await client.transactions.prepareTransfer({ chain: 'xrpl', from: '...', to: '...', amount: '100' });
232
+ ```
261
233
 
262
- All errors are instances of `SmartEngineError` with structured error codes:
234
+ ---
263
235
 
264
- ```typescript
265
- import { SmartEngineError, ErrorCode } from '@hsuite/smart-engines-sdk';
236
+ ## NestJS integration
266
237
 
267
- try {
268
- await client.transfer({ chain: 'hedera', from: '0.0.1', to: '0.0.2', amount: '999999' });
269
- } catch (error) {
270
- if (error instanceof SmartEngineError) {
271
- console.log(`Code: ${error.code}`); // e.g., 'INSUFFICIENT_BALANCE'
272
- console.log(`Status: ${error.statusCode}`); // e.g., 400
273
- console.log(`Retryable: ${error.isRetryable}`); // e.g., false
274
- console.log(`Context:`, error.context); // e.g., { chain: 'hedera' }
275
-
276
- switch (error.code) {
277
- case ErrorCode.INSUFFICIENT_BALANCE:
278
- console.log('Not enough funds');
279
- break;
280
- case ErrorCode.CHAIN_CONNECTION_ERROR:
281
- console.log('Network issue — will retry');
282
- if (error.isRetryable) { /* retry logic */ }
283
- break;
284
- case ErrorCode.RATE_LIMIT_EXCEEDED:
285
- console.log('Too many requests — back off');
286
- break;
287
- }
288
- }
289
- }
290
- ```
291
-
292
- ### Error Codes
293
-
294
- | Code | Description | Retryable |
295
- |------|-------------|-----------|
296
- | `INSUFFICIENT_BALANCE` | Not enough native or token balance | No |
297
- | `INVALID_ACCOUNT_ID` | Account doesn't exist or is deleted | No |
298
- | `CHAIN_CONNECTION_ERROR` | Network/RPC connectivity issue | Yes |
299
- | `CHAIN_TIMEOUT` | Request timed out | Yes |
300
- | `RATE_LIMIT_EXCEEDED` | Too many requests | Yes |
301
- | `INVALID_TRANSACTION` | Malformed or invalid transaction | No |
302
- | `TRANSACTION_FAILED` | Transaction executed but failed | No |
303
- | `CONTRACT_REVERT` | Smart contract execution reverted | No |
304
- | `TOKEN_NOT_ASSOCIATED` | Token not associated to account (Hedera) | No |
305
- | `TRUST_LINE_REQUIRED` | Trust line needed (XRPL/Stellar) | No |
306
- | `INVALID_SIGNATURE` | Bad signature on transaction | No |
307
-
308
- ## NestJS Integration
309
-
310
- ```typescript
238
+ ```ts
239
+ // app.module.ts
311
240
  import { Module } from '@nestjs/common';
312
- import { SmartEngineModule } from '@hsuite/smart-engines-sdk';
241
+ import { ConfigModule, ConfigService } from '@nestjs/config';
242
+ import { SmartEngineModule } from '@hsuite/smart-engines-sdk/nestjs';
313
243
 
314
244
  @Module({
315
245
  imports: [
316
- SmartEngineModule.forRoot({
317
- baseUrl: 'https://v3-testnet-sn1.hsuite.network',
318
- apiKey: process.env.SMART_ENGINE_API_KEY,
246
+ ConfigModule.forRoot({ isGlobal: true }),
247
+ SmartEngineModule.forRootAsync({
248
+ imports: [ConfigModule],
249
+ useFactory: (config: ConfigService) => ({
250
+ baseUrl: config.get('VALIDATOR_URL')!,
251
+ timeout: 30000,
252
+ testConnection: true,
253
+ autoReconnect: true,
254
+ reconnectInterval: 5000,
255
+ }),
256
+ inject: [ConfigService],
257
+ isGlobal: true,
319
258
  }),
320
259
  ],
321
260
  })
322
261
  export class AppModule {}
323
262
  ```
324
263
 
325
- Then inject:
264
+ Inject the `SmartEngineService` into your controllers / services for typed
265
+ access to `client.getHealth() / client.createAccount() / ...`.
266
+
267
+ ---
268
+
269
+ ## Resilience primitives
270
+
271
+ The SDK ships circuit-breaker, rate-limiter, and retry primitives used
272
+ internally — exposed for app-level use too:
273
+
274
+ ```ts
275
+ import { CircuitBreaker, RateLimiter, retryWithBackoff } from '@hsuite/smart-engines-sdk';
276
+
277
+ const breaker = new CircuitBreaker({ failureThreshold: 5, resetTimeoutMs: 30_000 });
278
+ const result = await breaker.execute(() => someFlakyOperation());
279
+
280
+ const limiter = new RateLimiter({ maxRequests: 60, windowMs: 60_000 });
281
+ if (limiter.isAllowed(walletAddress)) { /* proceed */ }
282
+
283
+ const value = await retryWithBackoff(
284
+ () => someTransientCall(),
285
+ { maxRetries: 3, initialDelayMs: 200, backoffMultiplier: 2 },
286
+ );
287
+ ```
326
288
 
327
- ```typescript
328
- import { Injectable } from '@nestjs/common';
329
- import { SmartEngineService } from '@hsuite/smart-engines-sdk';
289
+ ---
330
290
 
331
- @Injectable()
332
- export class PaymentService {
333
- constructor(private readonly smartEngine: SmartEngineService) {}
291
+ ## Error handling
334
292
 
335
- async processPayment(from: string, to: string, amount: string) {
336
- return this.smartEngine.client.transfer({
337
- chain: 'hedera',
338
- from,
339
- to,
340
- amount,
341
- });
293
+ ```ts
294
+ import { SmartEngineError, ErrorCode, UnsupportedCapabilityError, BaasError } from '@hsuite/smart-engines-sdk';
295
+
296
+ try {
297
+ await client.createToken({ chain: 'xrpl', name: 'X', symbol: 'X', type: 'fungible', /* ... */ capabilities: { wipeable: true } });
298
+ } catch (err) {
299
+ if (err instanceof UnsupportedCapabilityError) {
300
+ console.error(`${err.capability} not supported on ${err.chain}; alternatives:`, err.alternatives);
301
+ } else if (err instanceof SmartEngineError && err.code === ErrorCode.RATE_LIMIT_EXCEEDED) {
302
+ // back off + retry
303
+ } else if (err instanceof BaasError) {
304
+ console.error('BaaS request failed:', err.statusCode, err.details);
342
305
  }
343
306
  }
344
307
  ```
345
308
 
346
- ### Async configuration:
309
+ ---
347
310
 
348
- ```typescript
349
- SmartEngineModule.forRootAsync({
350
- useFactory: (config: ConfigService) => ({
351
- baseUrl: config.get('VALIDATOR_URL'),
352
- apiKey: config.get('API_KEY'),
353
- }),
354
- inject: [ConfigService],
355
- });
356
- ```
311
+ ## Peer dependencies
312
+
313
+ | Package | Required? | When |
314
+ |---|---|---|
315
+ | `xrpl` | required | Web3 auth signing (`Wallet.fromSeed`, `wallet.publicKey`, etc.) |
316
+ | `zod` | required | Schema validation (request/response shapes) |
317
+ | `@nestjs/common` + `@nestjs/core` | optional | Only if you import from `@hsuite/smart-engines-sdk/nestjs` |
318
+ | `@hashgraph/sdk` | optional | Only if your app does Hedera-side business logic |
319
+
320
+ `ripple-keypairs` is a transitive dep of `xrpl` — no separate install needed.
357
321
 
358
- ## Supported Chains
322
+ ---
323
+
324
+ ## Bundle
325
+
326
+ The SDK is a single 134 KB CJS bundle with workspace-only primitives
327
+ vendored in. Single-file `.d.ts` (84 KB) for full type ergonomics.
328
+
329
+ ```
330
+ @hsuite/smart-engines-sdk@3.0.0
331
+ dist/index.js 134 KB — main bundle
332
+ dist/index.d.ts 84 KB — types
333
+ dist/nestjs/index.js 104 KB — NestJS integration
334
+ dist/nestjs/index.d.ts 64 KB
335
+ ```
359
336
 
360
- | Chain | Account Ops | Tokens | NFTs | Messaging | DEX | Multi-Sig |
361
- |-------|------------|--------|------|-----------|-----|-----------|
362
- | Hedera | ✅ | ✅ HTS | ✅ | ✅ HCS | — | ✅ TSS |
363
- | XRPL | ✅ | ✅ Trust Lines | ✅ XLS-20 | — | ✅ Native | ✅ SignerList |
364
- | Ethereum | ✅ | ✅ ERC-20 | — | — | — | ✅ Safe |
365
- | Polygon | ✅ | ✅ ERC-20 | — | — | — | ✅ Safe |
366
- | Solana | ✅ | ✅ SPL | ✅ Metaplex | — | — | ✅ Squads |
367
- | Polkadot | ✅ | ✅ Assets | — | — | — | — |
368
- | Stellar | ✅ | ✅ Assets | — | — | ✅ SDEX | — |
369
- | Bitcoin | ✅ | — | — | — | — | — |
337
+ ---
370
338
 
371
339
  ## License
372
340
 
373
- Proprietary HSuite Trust
341
+ MIT. Built on the Smart Engines V3 architecture
342
+ ([github.com/HSuiteNetwork/smart-engines-multichain](https://github.com/HSuiteNetwork/smart-engines-multichain)).