Zero-config connect
The hardest part of talking to a decentralised network is the chicken-and-egg problem: you need to know where the network is before you can ask it anything. Hardcoding https://some-validator-ip:3000 is brittle — that server might be down, rotated, or never the one you should be talking to.
connectToCluster solves this. You give it a network name; it resolves the network’s entrypoint, asks which clusters are active, and picks one of them at random.
The flow
Section titled “The flow”sequenceDiagram
participant App as Your app
participant SDK as SDK
participant Seed as Canonical gateway (KNOWN_NETWORKS)
participant Cluster as Chosen cluster gateway
App->>SDK: connectToCluster({ network: 'testnet', ... })
SDK->>SDK: resolveNetwork('testnet') → bootstrap seed list
SDK->>Seed: GET /api/v3/discovery/clusters
Seed-->>SDK: active cluster set (each with a gatewayUrl)
SDK->>SDK: random-pick one active cluster
SDK-->>App: BaasClient bound to that cluster's gateway
App->>Cluster: baas.authenticate(...) when you need a session
BaasClient.connectToCluster (Host / BaaS)
Section titled “BaasClient.connectToCluster (Host / BaaS)”This is the recommended zero-config entrypoint for smart-apps using the database, storage, functions, messaging, or agents.
-
Connect by network name.
import { BaasClient } from '@hsuite/smart-engines-sdk';const baas = await BaasClient.connectToCluster({network: 'testnet',appId: 'app_abc',});await baas.db.insert('users', { name: 'Alice' }); -
Authenticate when you need a session.
BaasClient.connectToClusterreturns the client directly (it does not authenticate for you — callbaas.authenticate(...)when you need an authenticated session; see Authentication).
It defaults pathPrefix to /host, because cluster discovery hands back the gateway URL and the gateway routes BaaS traffic under /host/*. If you point the SDK at a bare host that isn’t behind a gateway, override with pathPrefix: ''.
Options
Section titled “Options”| Option | Type | Notes |
|---|---|---|
network |
'testnet' | 'mainnet' | 'devnet' |
Resolves the canonical gateway entrypoint. Mutually exclusive with bootstrap. |
bootstrap |
string[] |
Explicit seed URLs (private deployments). Mutually exclusive with network. |
appId |
string |
Your app id (e.g. from a prior deployment.init()) |
appName |
string |
App display name (registration) |
pathPrefix |
string |
Defaults to /host. Set '' to hit a bare host. |
timeout |
number |
Request timeout in ms (default 30000) |
allowInsecure |
boolean |
Plain HTTP for the URLs you supply (bootstrap seeds, mirror node) — local dev only. Never admits plaintext registry entries. |
allowInsecureClusters |
boolean |
Accept a plaintext gatewayUrl returned by the registry — only for a registry you run locally. Never implied by allowInsecure. |
trustAnchor |
{ network, registryTopicId, mirrorNodeUrl?, onFailure?, expectedValidatorKeys } |
Optional on-chain HCS gate over the discovery response: every nodeId must be registered and each record must bind the advertised gatewayUrl. expectedValidatorKeys maps each nodeId to the Ed25519 public key (hex) that must have signed its registry record; an unsigned or wrongly signed record is rejected. onFailure defaults to 'reject' (a mirror error or an empty registry throws TrustAnchorError); 'passthrough' is a non-production opt-in that returns the seed’s list unverified. The testnet registry topic is 0.0.9143793. |
Validator raw tier — retired
Section titled “Validator raw tier — retired”Earlier SDK versions shipped a second, validator-direct profile
(SmartEngineClient + connectToNetwork) for raw-tier operations — accounts,
tokens, transfers, TSS, IPFS, transaction preparation against
/api/v3/{transactions,tss,ipfs,tokens,...}. As of SDK 8.0 it is retired:
that tier has no public origin — the public gateway does not route it, and
the on-chain validator registry publishes only a gatewayUrl, never a
validator API endpoint — so connectToNetwork could never reach a deployed
network. BaasClient.connectToCluster (above) is now the only public
entrypoint. Transfers move through the entity-scoped surface instead:
import { BaasClient } from '@hsuite/smart-engines-sdk';
const baas = await BaasClient.connectToCluster({ network: 'testnet', appId: 'app_abc' });await baas.authenticate({ chain: 'xrpl', walletAddress: wallet.address, publicKey: wallet.publicKey, signFn: sign });
const result = await baas.entities.transfer('entity-1', { chain: 'xrpl', to: 'rDestination...', amount: '1000000', // drops});See the 8.0 CHANGELOG entry for the full migration.
The bootstrap escape hatch
Section titled “The bootstrap escape hatch”For private deployments, local clusters, or pinning your own seed order, pass bootstrap instead of network:
const baas = await BaasClient.connectToCluster({ bootstrap: ['https://gateway.my-private-net.example'], appId: 'app_abc',});Passing both network and bootstrap is a compile-time TypeScript error — the config is a discriminated union, so the type system stops the “which one wins?” ambiguity before runtime.
Known networks
Section titled “Known networks”The SDK ships canonical entrypoints in KNOWN_NETWORKS:
| Network | Bootstrap entrypoint |
|---|---|
testnet Live |
https://gateway.testnet.hsuite.network |
mainnet |
https://gateway.hsuite.network Reserved |
devnet |
https://gateway.develop.hsuite.network Reserved |
The testnet is live on HSuite-operated validators. It opens to developers once the security audit is complete.
“Reserved” means the name resolves and type-checks today, but the network is not deployed for public use: discovery against it fails at runtime with the ordinary “no cluster reachable” error rather than a compile-time “unknown network” surprise. Mainnet has no date.
For testnet the SDK also ships the validator-registry anchor (the registry topic and each
validator’s signing key) used to verify post-quantum attestations.
Customers who run their own validators should not extend this map — pass bootstrap: [...] directly instead.
Picking a network from an env var
Section titled “Picking a network from an env var”networkFromEnv(explicit, env) resolves a NetworkName the same way the CLI does: an
explicit value you already have wins outright, otherwise env.HSUITE_NETWORK is used if
it names a known network, otherwise testnet.
import { networkFromEnv } from '@hsuite/smart-engines-sdk';
const baas = await BaasClient.connectToCluster({ network: networkFromEnv(undefined, process.env), // reads $HSUITE_NETWORK, else 'testnet' appId: 'app_abc',});Errors
Section titled “Errors”| Condition | Thrown |
|---|---|
| No cluster reachable via any seed | 503 |
Neither a known network nor a non-empty bootstrap list |
400 |
| A seed returned only plaintext gateways | InsecureClusterRegistryError |
trustAnchor set (with onFailure: 'reject') and the registry can’t be read or is empty |
TrustAnchorError |