@bounded-sh/client
Bounded JS SDK
Bounded is a provable realtime backend for web and React Native applications.
Welcome to the Bounded JavaScript SDK. This SDK lets JavaScript and TypeScript applications authenticate users, read and write policy-governed data, subscribe to realtime updates, and call Bounded services.
Table of Contents
Installation
Install the SDK via npm:
npm install @bounded-sh/client
Or with Yarn:
yarn add @bounded-sh/client
Getting Started
Initialization
Before using the SDK, initialize it with your Application ID. Hosted Bounded Auth email login is the default human-login provider.
import { init } from '@bounded-sh/client';
await init({ appId: 'YOUR_APP_ID' });
Authentication
Human login runs through the hosted redirect or popup helpers, which bind the returned token to the app id and registered redirect URI. Inline app-origin OTP helpers are retired.
import { loginWithRedirect, completeLoginFromRedirect } from '@bounded-sh/client';
// Start hosted login:
await loginWithRedirect({ redirectUri: 'https://yourapp.com/auth/callback', methods: ['email'] });
// On your callback page, on load:
const user = await completeLoginFromRedirect();
You can also listen for authentication state changes:
import { onAuthStateChanged } from '@bounded-sh/client';
const unsubscribe = onAuthStateChanged((user) => {
if (user) {
console.log('User logged in:', user.address);
} else {
console.log('User logged out');
}
});
// Later:
unsubscribe();
Usage
Get Current User
import { getCurrentUser } from '@bounded-sh/client';
const user = await getCurrentUser();
if (user) {
console.log('Current user:', user.address);
} else {
console.log('No user is currently logged in.');
}
Set Data
import { set } from '@bounded-sh/client';
const path = 'path/to/data';
const data = { key: 'value' };
await set(path, data);
console.log(`Data set at ${path}`);
On-Chain and Off-Chain Data
The set and get functions automatically handle whether data is stored on-chain or off-chain based on your application's policy configuration in the Tarobase Console.
On-Chain Data:
If the data path corresponds to on-chain storage defined in your application policy, the
setfunction will store data on-chain.The data must adhere to the
fieldsschema defined in your Tarobase policy.Transactions are handled automatically, and users may be prompted to approve blockchain transactions.
On-chain transactions require an explicit Solana RPC URL in
init({ rpcUrl }); the SDK does not choose a bundled mainnet/devnet RPC when this is omitted.
Off-Chain Data:
- If the data path corresponds to off-chain storage, the
setfunction will store data off-chain.
Important:
Manage your data storage preferences and define policies at the Tarobase Console.
Ensure that for on-chain data, the parameters you provide to
setmatch thefieldsspecified in your Tarobase policy.The policy also controls what can be
setorgetin your application.For information on how to form your policy specifically for your app's use-cases, view the policy docs here.
Subscribe
import { subscribe } from '@bounded-sh/client';
// Subscribe to a single document
const unsubscribe = await subscribe('users/123/profile', {
onData: (data) => console.log('Data updated:', data),
onError: (e) => console.error(e.message),
});
// Subscribe to a filtered, live collection feed
await subscribe('orders', {
filter: { status: 'open', amount: { $gt: 100 } },
limit: 50,
onData: (orders) => console.log('Live open orders:', orders),
});
// Later, to stop receiving updates:
await unsubscribe();
Get Data
import { get } from '@bounded-sh/client';
// Read a single document
const message = await get('messages/abc123');
// Query a collection with a structured filter, sort, limit, and cursor pagination
const recent = await get('messages', {
filter: { text: { $regex: '^f', $options: 'i' } }, // text starting with "f"
sort: { tarobase_created_at: -1 },
limit: 20,
// cursor: previousPage.nextCursor, // opaque keyset cursor (no numeric offset)
});
console.log('Messages:', recent);
filter uses MongoDB-style operators ($gt, $gte, $lt, $lte, $ne,
$in, $nin, $all, $size, $elemMatch, $exists, $type, $regex,
$and, $or, $nor) evaluated server-side. See the
Querying reference for the full table.
Note: The older natural-language
promptoption is legacy and no longer filters results — always use the structuredfilteroption above.
Note: Similar to set, the get and subscribe functions will automatically retrieve data from on-chain or off-chain storage based on your application's configuration.
Counting, Aggregation, Search, and Joins
import { count, aggregate, queryAggregate, search, get } from '@bounded-sh/client';
// Count matching documents
const { value: openCount } = await count('orders', { filter: { status: 'open' } });
// Single scalar aggregate: count | uniqueCount | sum | avg | min | max
const { value: total } = await aggregate('orders', 'sum', { field: 'amount' });
// Grouped aggregation → one row per group
const byCategory = await queryAggregate('spend', { groupBy: ['category'], count: true, sum: ['amount'] });
// Full-text search (collection must declare `search: { fields: [...] }` in policy)
const docs = await search('orgs/o1/docs', 'quarterly report', { fields: ['title', 'body'] });
// Relationship join via `shape` (collection must declare `links` in policy)
const projects = await get('projects', { shape: { owner: {} } });
Get Multiple Documents
Use getMany to efficiently fetch multiple documents in a single request:
import { getMany } from '@bounded-sh/client';
// Fetch multiple documents at once (max 30 paths)
const results = await getMany([
'users/123/profile',
'users/456/profile',
'posts/789'
]);
// Each result contains: { path, data, error? }
results.forEach(result => {
if (result.error) {
console.log(`Error for ${result.path}: ${result.error.message}`);
} else {
console.log(`Data for ${result.path}:`, result.data);
}
});
The getMany function:
- Accepts up to 30 document paths per request
- Returns results in the same order as the input paths
- Includes per-document error handling (NOT_FOUND, UNAUTHORIZED)
- Automatically caches successful fetches
Additional Resources
For more comprehensive examples, detailed guides, and API references, please visit our documentation site:
Quickstart Guide
React Native Support
React Native and Expo are supported through the same @bounded-sh/client
package. See REACT_NATIVE.md for platform setup, hosted
login, and guest login examples.
Contributing
Contributions are welcome! Please open an issue or submit a pull request on GitHub.
License
This Bounded JS SDK project is licensed under the MIT License.
Thank you for using the Bounded JS SDK. If you have questions or need help, please create an issue.