@stoar/sdk
v0.1.2
Published
JavaScript/TypeScript SDK for STOAR - Decentralized file storage on Arweave
Downloads
8
Maintainers
Readme
STOAR SDK
A TypeScript/JavaScript SDK for interacting with STOAR - a decentralized file storage system built on Arweave.
Features
- 🚀 Simple API: Easy-to-use client for file uploads and management
- 🔐 Wallet Support: Compatible with ArConnect browser extension and JSON wallet files
- 📦 Batch Uploads: Efficient batch file uploads using AR bundles
- 🔄 S3 Compatibility: Familiar S3-like API for easy migration
- 💾 Permanent Storage: Leverage Arweave's permanent, decentralized storage
- 🧪 Well Tested: Comprehensive unit and integration tests
- 📘 TypeScript: Full TypeScript support with complete type definitions
Installation
npm install @stoar/sdk
# or
yarn add @stoar/sdk
# or
bun add @stoar/sdkQuick Start
Basic File Upload
import { StoarClient } from '@stoar/sdk';
// Initialize client
const client = new StoarClient({
appName: 'My App',
appVersion: '1.0.0'
});
// Initialize with ArConnect wallet (browser)
await client.init();
// Upload a file
const file = new Uint8Array([1, 2, 3, 4]);
const result = await client.uploadFile(file, {
name: 'my-file.bin',
size: file.length,
contentType: 'application/octet-stream'
});
console.log('Uploaded!', result.url);Using JSON Wallet
import { StoarClient } from '@stoar/sdk';
import fs from 'fs';
// Load wallet from file
const walletData = fs.readFileSync('path/to/wallet.json', 'utf8');
const client = new StoarClient();
await client.init(walletData);
// Upload file
const result = await client.uploadFile(
Buffer.from('Hello, Arweave!'),
{
name: 'hello.txt',
size: 15,
contentType: 'text/plain'
}
);Batch Upload
STOAR SDK now supports advanced batching capabilities that significantly reduce transaction costs:
Method 1: Auto-batching
// Enable auto-batching - all subsequent uploads are automatically bundled
client.enableBatching({
timeout: 30000, // Auto-commit after 30 seconds
maxFiles: 100, // Or when 100 files are added
maxBytes: 100 * 1024 * 1024 // Or when 100MB is reached
});
// These uploads are automatically batched together
await client.uploadFile(data1, metadata1);
await client.uploadFile(data2, metadata2);
await client.uploadFile(data3, metadata3);
// Disable and commit any remaining files
await client.disableBatching();Method 2: Manual batch control
// Create a batch
const batchId = client.createBatch({
maxFiles: 50,
autoCommit: false // Manual control
});
// Add files to the batch
await client.uploadFile(data1, metadata1, { batch: batchId });
await client.uploadFile(data2, metadata2, { batch: batchId });
// Check batch status
const status = client.getBatchStatus(batchId);
console.log(`Files in batch: ${status.fileCount}`);
// Commit when ready
const result = await client.commitBatch(batchId);
console.log(`Bundle created: ${result.bundleId}`);
console.log(`Cost savings: ${result.fileCount - 1} transaction fees saved!`);Method 3: Direct batch upload
const files = [
{
data: Buffer.from('File 1 content'),
metadata: { name: 'file1.txt', size: 14, contentType: 'text/plain' }
},
{
data: Buffer.from('File 2 content'),
metadata: { name: 'file2.txt', size: 14, contentType: 'text/plain' }
}
];
const batchResult = await client.uploadBatch(files, {
bundleTags: { 'Batch-Name': 'My Batch Upload' },
progress: (status) => {
console.log(`Progress: ${status.completed}/${status.total}`);
}
});
console.log('Batch uploaded!', batchResult.bundleUrl);Benefits of Batching:
- 💰 90%+ cost reduction for multi-file uploads
- 🚀 Faster uploads with single network transaction
- ⚡ Atomic operations - all files succeed or fail together
- 📊 Perfect for NFT collections and bulk data
S3 Compatibility Layer
For easy migration from S3-based applications:
import { StoarClient, StoarS3Client } from '@stoar/sdk';
const client = new StoarClient();
await client.init();
const s3 = new StoarS3Client(client, {
bucket: 'my-bucket',
region: 'us-east-1'
});
// Use familiar S3 API
await s3.putObject({
Key: 'path/to/file.txt',
Body: 'Hello, S3 compatibility!',
ContentType: 'text/plain',
Metadata: {
author: 'John Doe',
version: '1.0'
}
});
// Retrieve object
const object = await s3.getObject({ Key: 'path/to/file.txt' });
console.log(new TextDecoder().decode(object.Body));
// List objects
const list = await s3.listObjects({ Prefix: 'path/' });
console.log(list.Contents);API Reference
StoarClient
Constructor
new StoarClient(config?: StoarConfig)StoarConfig Options:
arweave?: Arweave- Custom Arweave instancegateway?: string- Arweave gateway URL (default: 'https://arweave.net')wallet?: string | ArrayBuffer | object- Wallet dataappName?: string- Application name for taggingappVersion?: string- Application version for tagging
Methods
init(walletSource?)
Initialize the client with a wallet.
// Browser wallet (ArConnect)
await client.init();
// JSON wallet string
await client.init(jsonWalletString);
// JWK object
await client.init(jwkObject);
// ArrayBuffer
await client.init(walletArrayBuffer);uploadFile(data, metadata, options?)
Upload a single file (supports batching).
await client.uploadFile(
data: Buffer | Uint8Array | string,
metadata: {
name: string;
size: number;
contentType: string;
lastModified?: number;
},
options?: {
tags?: Record<string, string>;
contentType?: string;
encrypt?: boolean;
progress?: (progress: number) => void;
batch?: boolean | string; // Enable batching or specify batch ID
}
);uploadBatch(files, options?)
Upload multiple files as a bundle.
await client.uploadBatch(
files: Array<{
data: Buffer | Uint8Array;
metadata: FileMetadata;
}>,
options?: {
tags?: Record<string, string>;
bundleTags?: Record<string, string>;
progress?: (progress: {
completed: number;
total: number;
current?: string;
}) => void;
concurrent?: number;
}
);query(options?)
Query transactions using Arweave's GraphQL endpoint. This method has been updated to use GraphQL instead of the deprecated ArQL, providing better performance and more reliable results.
// Basic query
const results = await client.query({
limit: 20,
owner: 'wallet-address'
});
// Query with tags
const taggedResults = await client.query({
tags: {
'App-Name': 'STOAR SDK',
'Content-Type': 'image/png'
},
limit: 50
});
// Pagination with cursor
const page2 = await client.query({
limit: 20,
after: 'cursor-from-previous-query'
});
// Filter by block height
const recentTxs = await client.query({
minBlock: 1000000,
maxBlock: 1100000
});Query Options:
limit: Number of results to return (default: 10)after: Cursor for paginationtags: Filter by transaction tagsowner: Filter by wallet addressminBlock: Minimum block heightmaxBlock: Maximum block height
Returns: Array of QueryResult objects containing:
id: Transaction IDowner: Owner wallet addresstags: Transaction tags as key-value pairsblock: Block information (height and timestamp)fee: Transaction fee in winstonquantity: Transfer amount in winston
getFile(transactionId)
Retrieve file data by transaction ID.
const data: Uint8Array = await client.getFile('transaction-id');getAddress()
Get wallet address.
const address: string = client.getAddress();getBalance()
Get wallet balance in AR.
const balance: string = await client.getBalance();createBatch(options?)
Create a new batch for bundling files.
const batchId: string = client.createBatch({
maxFiles?: number; // Maximum files in batch
maxBytes?: number; // Maximum total size
timeout?: number; // Auto-commit timeout in ms
autoCommit?: boolean; // Enable auto-commit
});commitBatch(batchId)
Commit a batch and upload as bundle.
const result: BatchCommitResult = await client.commitBatch(batchId);
// Returns: { batchId, bundleId, bundleUrl, fileCount, totalSize, totalCost, files }getBatchStatus(batchId)
Get the current status of a batch.
const status: BatchStatus = client.getBatchStatus(batchId);
// Returns: { batchId, fileCount, totalSize, status, createdAt, error? }enableBatching(options?)
Enable auto-batching for all subsequent uploads.
client.enableBatching({
timeout?: number; // Auto-commit timeout
maxFiles?: number; // Max files before auto-commit
maxBytes?: number; // Max size before auto-commit
});disableBatching()
Disable auto-batching and commit any pending files.
const result = await client.disableBatching();
// Returns BatchCommitResult if files were pending, void otherwiseStoarS3Client
S3-compatible interface for STOAR.
Constructor
new StoarS3Client(stoarClient: StoarClient, config: S3CompatibleConfig)Methods
putObject(params)- Upload an objectgetObject(params)- Retrieve an objectdeleteObject(params)- Delete an object (creates delete marker)headObject(params)- Get object metadatalistObjects(params)- List objects in bucketcopyObject(params)- Copy an object
Error Handling
The SDK provides specific error types:
import {
StoarError,
UploadError,
BundleError,
WalletError,
InsufficientBalanceError
} from '@stoar/sdk';
try {
await client.uploadFile(data, metadata);
} catch (error) {
if (error instanceof InsufficientBalanceError) {
console.error('Insufficient balance:', error.message);
console.error('Required:', error.required, 'AR');
console.error('Available:', error.available, 'AR');
} else if (error instanceof UploadError) {
console.error('Upload failed:', error.message);
} else if (error instanceof WalletError) {
console.error('Wallet error:', error.message);
} else if (error instanceof BundleError) {
console.error('Bundle error:', error.message);
}
}Environment Configuration
You can configure the SDK using environment variables:
# Custom Arweave gateway
ARWEAVE_GATEWAY=https://arweave.net
# Application info
APP_NAME=MyApp
APP_VERSION=1.0.0Development
Building
bun run buildTesting
# Run tests
bun run test
# Run tests with UI
bun run test:ui
# Run tests with coverage
bun run test:coverageLinting
bun run lint
bun run lint:fixExamples
Check out the examples/ directory for more usage examples:
- Batch Upload - Comprehensive batch upload examples
- NFT Batch Explained - How to upload NFT collections efficiently
- S3 Storage Test - S3 compatibility layer examples
- S3 Upload Test - S3-style uploads
- S3 Query Test - Querying with S3 interface
Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
