@rebarxyz/sdk
v0.0.29
Published
> **TypeScript SDK for building decentralized data networks with automated logic**
Downloads
206
Readme
Rebar SDK
TypeScript SDK for building decentralized data networks with automated logic
Rebar lets you create interconnected data nodes that automatically calculate, trigger actions, and react to changes—all on-chain. Perfect for DeFi strategies, IoT monitoring, financial modeling, and automation workflows.
🚀 Quick Start
npm install @rebarxyz/sdkimport { RebarClient } from '@rebarxyz/sdk';
import { HDWallet } from '@rebarxyz/rivet/wallet';
// Connect to network (read-only)
const client = new RebarClient('https://rpc.rebar.xyz');
// Or with wallet for transactions
const wallet = HDWallet.fromMnemonic(process.env.MNEMONIC!, { prefix: 'rebar' });
const client = new RebarClient('https://rpc.rebar.xyz', wallet, 'rebar1...');🏗️ Core Concepts
Rebar organizes data into 5 node types that work together:
| Node Type | Purpose | Example | |-----------|---------|---------| | Input | Store live data | Temperature sensor, price feed | | Calculated | Auto-compute from inputs | Moving average, portfolio value | | Function | Execute complex logic | Risk assessment, data processing | | Action | Define external tasks | Send alert, execute trade | | Trigger | Monitor & activate actions | Alert when price > $100 |
📊 Build Your First Network
Example: DeFi Price Monitor
// 1. Create price input (updated by oracle)
const btcPrice = await client.createData({
name: 'BTC/USD Price',
description: 'Live Bitcoin price from CoinGecko',
valueType: 'float',
value: '45000'
});
// 2. Calculate price threshold (simple calculation)
const priceThreshold = await client.createCalculation({
name: 'Price Threshold (45k)',
description: 'Fixed threshold for price alerts',
inputs: [],
calculationType: 'expression',
calculation: '45000.0',
valueType: 'float'
});
// 3. Define alert action
const alertAction = await client.createAction({
name: 'Price Alert',
description: 'Send notification when price changes significantly',
schema: JSON.stringify({
type: 'object',
properties: {
message: { type: 'string' },
price: { type: 'number' }
}
}),
cost: '0',
completionValidation: 'signer'
});
// 4. Create trigger for price above threshold
const priceTrigger = await client.createTrigger({
name: 'High Price Alert',
description: 'Trigger when price exceeds threshold',
inputs: [btcPrice.address, priceThreshold.address],
triggerLogic: `${btcPrice.address} > ${priceThreshold.address}`,
triggerLogicType: 'expression',
action: alertAction.address
});
// 5. Update price (triggers calculation cascade)
await client.addData({
address: btcPrice.address,
value: '47250'
});🔧 SDK Methods
Node Creation
All creation methods return the transaction response by default, or expanded response with { expanded: true }:
// Input nodes - store updatable data
const sensor = await client.createData({
name: 'Temperature Sensor',
valueType: 'float',
value: '22.5',
validation: 'signer' // or 'anyone', 'owner'
});
// Calculated nodes - auto-compute from inputs
const fahrenheit = await client.createCalculation({
name: 'Temperature (°F)',
inputs: [sensor.address],
calculationType: 'expression', // or 'starlark'
calculation: `${sensor.address} * 9/5 + 32`,
valueType: 'float'
});
// Function nodes - complex logic with state
const processor = await client.createFunction({
name: 'Temperature Processor',
calculation: `
def process_temp(temp, state):
# Simple processing - double the temperature
return temp * 2.0
return process_temp(${sensor.address}, state)`,
calculationType: 'starlark',
inputs: [sensor.address],
state: JSON.stringify({ lastReading: 0 })
});
// Action nodes - external tasks
const notification = await client.createAction({
name: 'SMS Alert',
schema: JSON.stringify({
type: 'object',
properties: {
recipient: { type: 'string' },
message: { type: 'string' }
}
}),
cost: '100urebar',
completionValidation: 'anyone'
});
// Trigger nodes - conditional activation
const trigger = await client.createTrigger({
name: 'High Temperature Alert',
inputs: [fahrenheit.address],
triggerLogic: `${fahrenheit.address} > 85.0`,
triggerLogicType: 'expression',
action: notification.address
});Data Operations
// Read node values (type-safe with generics)
const temp = await client.getValue<number>(sensor.address);
const node = await client.getNode(sensor.address);
const allNodes = await client.getAllNodes();
// Update input nodes
await client.addData({
address: sensor.address,
value: '25.3'
});
// Batch updates (more efficient)
await client.addDataBatch([
{ address: sensor1.address, value: '23.1', signer: signerAddress, nonce: 1 },
{ address: sensor2.address, value: '24.8', signer: signerAddress, nonce: 2 }
]);
// One-off calculations (no node creation)
const result = await client.runCalculation({
valueType: 'float',
calculationType: 'expression',
calculation: 'temp * 1.8 + 32',
inputs: [sensor.address]
});
// Complete triggered actions
await client.completeTriggerAction({
triggerAddress: trigger.address,
actionAddress: notification.address
});📡 Real-time Monitoring
WebSocket support for live updates:
// Watch for new blocks
const blockWatcher = client.watchBlocks(() => {
console.log('New block mined');
});
// Watch specific nodes for recalculations
const recalcWatcher = client.watchRecalcs([sensor.address, fahrenheit.address], () => {
console.log('Node values updated');
});
// Watch for trigger activations
const triggerWatcher = client.watchTriggers((event) => {
console.log(`Trigger ${event.triggerAddress} activated`);
console.log(`Action needed: ${event.actionAddress}`);
console.log(`Data: ${event.actionData}`);
}, [trigger.address]); // Optional: filter by trigger
// Clean up
blockWatcher.close();
recalcWatcher.close();
triggerWatcher.close();🛡️ Error Handling
SDK errors include a stable string code and optional details for programmatic handling.
import { RebarClient, isRebarError, REBAR_ERROR_CODES } from '@rebarxyz/sdk';
try {
const client = new RebarClient('https://rpc.rebar.xyz');
await client.createData({ name: 'Temp', valueType: 'float', value: '72.1' });
} catch (err) {
if (isRebarError(err)) {
if (err.code === REBAR_ERROR_CODES.walletRequired) {
console.error('Connect a wallet before sending transactions.');
}
console.error(err.code, err.details);
return;
}
throw err;
}🎯 Type Generation CLI
Generate type-safe interfaces for your nodes:
# Initialize config
npx @rebarxyz/sdk/cli --init
# Edit rebar.config.json
{
"baseUrl": "https://rpc.rebar.xyz",
"nodes": {
"btcPrice": "rebar1abc...",
"ethPrice": "rebar1def..."
},
"output": "./src/rebar-types.ts"
}
# Generate types
npx @rebarxyz/sdk/cliUse generated types:
import { btcPrice, ethPrice, type BtcPrice, type EthPrice } from './rebar-types';
// Fully type-safe node access
const currentBtc = await client.getValue<BtcPrice>(btcPrice);
const currentEth = await client.getValue<EthPrice>(ethPrice);🔄 Advanced Examples
Portfolio Tracker
// Portfolio inputs
const btcHoldings = await client.createData({ name: 'BTC Holdings', valueType: 'float', value: '0.5' });
const ethHoldings = await client.createData({ name: 'ETH Holdings', valueType: 'float', value: '10' });
const btcPrice = await client.createData({ name: 'BTC Price', valueType: 'float', value: '45000' });
const ethPrice = await client.createData({ name: 'ETH Price', valueType: 'float', value: '3000' });
// Portfolio value calculation
const portfolioValue = await client.createCalculation({
name: 'Total Portfolio Value',
inputs: [btcHoldings.address, ethHoldings.address, btcPrice.address, ethPrice.address],
calculationType: 'expression',
calculation: `${btcHoldings.address} * ${btcPrice.address} + ${ethHoldings.address} * ${ethPrice.address}`,
valueType: 'float'
});
// Rebalancing trigger
const rebalanceAction = await client.createAction({
name: 'Rebalance Portfolio',
schema: JSON.stringify({ type: 'object', properties: { action: { type: 'string' } } }),
cost: '0',
completionValidation: 'signer'
});
const rebalanceTrigger = await client.createTrigger({
name: 'Portfolio Imbalance Detector',
inputs: [btcHoldings.address, ethHoldings.address, btcPrice.address, ethPrice.address, portfolioValue.address],
triggerLogic: `
btc_value = ${btcHoldings.address} * ${btcPrice.address}
btc_percent = btc_value / ${portfolioValue.address}
target_percent = 0.6
diff = btc_percent - target_percent
# Check if difference is greater than 10% (0.1)
return diff > 0.1 or diff < -0.1`,
triggerLogicType: 'starlark',
action: rebalanceAction.address
});IoT Sensor Network
// Multiple sensor inputs
const sensors = await Promise.all([
client.createData({ name: 'Living Room Temp', valueType: 'float', value: '22' }),
client.createData({ name: 'Bedroom Temp', valueType: 'float', value: '20' }),
client.createData({ name: 'Kitchen Temp', valueType: 'float', value: '24' })
]);
// Average temperature using Starlark's mean function
const avgTemp = await client.createCalculation({
name: 'House Average Temperature',
inputs: sensors.map(s => s.address),
calculationType: 'starlark',
calculation: `
temp_list = [${sensors.map(s => s.address).join(', ')}]
return mean(temp_list)`,
valueType: 'float'
});
// HVAC control action
const hvacControl = await client.createAction({
name: 'HVAC Control',
schema: JSON.stringify({
type: 'object',
properties: {
action: { type: 'string', enum: ['heat', 'cool', 'off'] },
targetTemp: { type: 'number' }
}
}),
cost: '50urebar',
completionValidation: 'anyone'
});
// Temperature control triggers
const coolTrigger = await client.createTrigger({
name: 'Cooling Trigger',
inputs: [avgTemp.address],
triggerLogic: `${avgTemp.address} > 25.0`,
triggerLogicType: 'expression',
action: hvacControl.address
});🔒 Error Handling
import { NodeNotFoundError, WalletRequiredError } from '@rebarxyz/sdk';
try {
const value = await client.getValue('rebar1invalid...');
} catch (error) {
if (error instanceof NodeNotFoundError) {
console.log('Node not found');
} else if (error instanceof WalletRequiredError) {
console.log('Transaction requires wallet');
}
}🌐 Network Support
- Mainnet:
https://rpc.rebar.xyz - Testnet:
https://testnet-rpc.rebar.xyz - Local:
http://localhost:26657
📚 API Reference
Client Options
const client = new RebarClient(
'https://rpc.rebar.xyz', // RPC endpoint
wallet, // Optional: OfflineDirectSigner (e.g. HDWallet/Keplr/Leap)
'rebar1...', // Optional: default signer address
{ errorMode: 'safe' } // Optional: 'safe' (default) | 'strict'
);
await client.ready(); // Wait for full initialization (optional)Per-call override for search/query methods:
const strictPage = await client.searchNodeUpdates(
{ address: 'rebar1...', limit: 20 },
{ errorMode: 'strict' }
);Transaction Options
All transaction methods support an optional options parameter:
// Get expanded response with transaction details
const response = await client.createData(params, { expanded: true });
console.log(response.txHash, response.height, response.gasUsed);
// Get just the message response (default)
const response = await client.createData(params);
console.log(response.address);Value Types
Supported valueType options for nodes:
- Primitives:
string,int,float,bool,uint256 - Arrays:
string[],int[],float[],bool[],uint256[] - Complex:
json,json[]
Calculation Types
expression: Simple mathematical expressions with node addressesstarlark: Python-like scripting with basic built-ins:sum,mean,pow
🛠️ Development
# Build SDK
bun run build
# Run tests
bun test
# Generate types from chain
bun run generate-types📄 License
MIT License - see LICENSE file for details.
