JavaScript SDK for multi-user NOVA: Secure file sharing on NEAR with Shade/TEEs key management.
npm install nova-sdk-jsVersion: 1.0.3
License: MIT
Network: NEAR Protocol (Mainnet & Testnet)
Package: nova-sdk-js
A JavaScript/TypeScript SDK for NOVA's secure, decentralized file-sharing primitive on NEAR. NOVA hybridizes on-chain access control with off-chain TEE-secured keys via Shade Agents, using nonce-based ed25519-signed tokens for ephemeral, verifiable access. This ensures privacy-first data sharing for AI datasets, healthcare/financial records, and sensitive documents.
- š Zero-Knowledge Architecture - Keys managed in TEE; never exposed to SDK
- š IPFS Storage - Decentralized file storage via Pinata
- āļø NEAR Blockchain - Immutable access control & transaction logs
- š”ļø API Key Auth - Secure authentication via API keys (get yours at nova-sdk.com)
- š Automated Signing - MCP server signs transactions using keys from Shade TEE
- š„ Group Management - Fine-grained membership with automatic key rotation on revocation
- š Composite Operations - Simplified workflows for upload/retrieve
- š¦ TypeScript Support - Full type definitions included
``bash`
npm install nova-sdk-js
NOVA SDK operates on NEAR mainnet by default. All operations consume real NEAR tokens.
Typical costs (mainnet):
- Register group: ~0.05 NEAR (~$0.15 USD)
- Upload file: ~0.01 NEAR (incl. IPFS storage)
- Retrieve file: ~0.001 NEAR
For development, use testnet
1. Create a NOVA account at nova-sdk.com
2. Generate an API key from the "Manage Account" menu
3. Fund your account with NEAR tokens for transaction fees
typescript
import { NovaSdk } from 'nova-sdk-js';// Initialize with your account ID and API key
const sdk = new NovaSdk('alice.nova-sdk.near', {
apiKey: process.env.NOVA_API_KEY
});
// Register group (you become owner)
await sdk.registerGroup('confidential-docs');
// Upload a file
const result = await sdk.upload('my-group', Buffer.from('Hello NOVA!'), 'hello.txt');
console.log('Uploaded:', result.cid);
// Retrieve the file
const { data } = await sdk.retrieve('my-group', result.cid);
console.log('Retrieved:', data.toString());
`That's it! The SDK automatically:
- Authenticates using your API key
- Manages session tokens (auto-refresh before 24h expiry)
- Handles all encryption/decryption client-side
Configuration Options
`typescript
// Standard usage (mainnet)
const sdk = new NovaSdk('alice.nova-sdk.near', {
apiKey: process.env.NOVA_API_KEY // Required: get yours at nova-sdk.com
});// Testnet configuration
const sdk = new NovaSdk('alice.nova-sdk-5.testnet', {
apiKey: process.env.NOVA_API_KEY,
rpcUrl: 'https://rpc.testnet.near.org',
contractId: 'nova-sdk-5.testnet',
});
// Custom MCP server (advanced)
const sdk = new NovaSdk('alice.nova-sdk.near', {
apiKey: process.env.NOVA_API_KEY,
mcpUrl: 'https://your-mcp-server.com',
authUrl: 'https://your-auth-server.com',
});
`
š Core Operations
$3
`typescript
import fs from 'fs';// Upload (encrypts client-side, stores on IPFS, records on NEAR)
const fileData = fs.readFileSync('./document.pdf');
const result = await sdk.upload('my-group', fileData, 'document.pdf');
console.log('CID:', result.cid); // IPFS content ID
console.log('TX:', result.trans_id); // NEAR transaction ID
console.log('Hash:', result.file_hash); // SHA-256 of plaintext
// Retrieve (fetches from IPFS, decrypts client-side)
const { data } = await sdk.retrieve('my-group', result.cid);
fs.writeFileSync('./downloaded.pdf', data);
`$3
`typescript
// Create a group (you become owner)
await sdk.registerGroup('team-files');// Add members
await sdk.addGroupMember('team-files', 'bob.nova-sdk.near');
await sdk.addGroupMember('team-files', 'carol.nova-sdk.near');
// Check authorization
const isAuthorized = await sdk.isAuthorized('team-files', 'bob.nova-sdk.near');
// Revoke access (triggers automatic key rotation)
await sdk.revokeGroupMember('team-files', 'bob.nova-sdk.near');
`$3
These don't require authentication:
`typescript
// Account balance
const balance = await sdk.getBalance();// Group info
const owner = await sdk.getGroupOwner('team-files');
const checksum = await sdk.getGroupChecksum('team-files');
// Transaction history
const transactions = await sdk.getTransactionsForGroup('team-files');
// Fee estimation
const fee = await sdk.estimateFee('register_group');
`How It Works
$3
`
1. SDK calls prepare_upload ā MCP returns encryption key from TEE
2. SDK encrypts file locally (AES-256-GCM)
3. SDK calls finalize_upload with encrypted data
4. MCP uploads to IPFS and records on NEAR
5. Returns: { cid, trans_id, file_hash }
`$3
`
1. SDK calls prepare_retrieve ā MCP returns key + encrypted data
2. SDK decrypts locally (AES-256-GCM)
3. Returns: { data, ipfs_hash, group_id }
`Key point: Plaintext data and encryption keys never travel together. The MCP server never sees your unencrypted files.
Authentication
The SDK uses API keys for secure authentication. Get your key at nova-sdk.com:
1. Create or log into your NOVA account
2. Click "Manage Account"
3. Click "Generate API Key"
4. Copy the key (shown only once!)
`bash
Store in .env (never commit to git!)
NOVA_ACCOUNT_ID=alice.nova-sdk.near
NOVA_API_KEY=nova_sk_xxxxxxxxxxxxxxxxxxxxx
`
`typescript
// Use environment variables
const sdk = new NovaSdk(process.env.NOVA_ACCOUNT_ID, {
apiKey: process.env.NOVA_API_KEY
});// Force refresh session token
await sdk.refreshToken();
// Get network info
const info = sdk.getNetworkInfo();
`Note: One API key per account. Generating a new key invalidates the old one.
Error Handling
`typescript
import { NovaSdk, NovaError } from 'nova-sdk-js';try {
await sdk.upload('my-group', data, 'file.txt');
} catch (e) {
if (e instanceof NovaError) {
if (e.message.includes('not found')) {
console.error('Account not found - create one at nova-sdk.com');
} else if (e.message.includes('not authorized')) {
console.error('Not a member of this group');
} else if (e.message.includes('Insufficient')) {
console.error('Need more NEAR - deposit at nova-sdk.com');
} else {
console.error('NOVA error:', e.message);
}
}
}
`Costs (Mainnet)
Some operations require NEAR token deposits (paid from user's NOVA account):
-
registerGroup() - ~0.05 NEAR
- addGroupMember() - ~0.001 NEAR
- revokeGroupMember() - ~0.001 NEAR
- upload() - ~0.003 NEAR (claim token + record Tx)
- retrieve() - 0.001 NEAR (claim only)Ensure your NOVA account has sufficient balance before calling these methods.
API Reference
$3
`typescript
new NovaSdk(accountId: string, config?: NovaSdkConfig)
`$3
| Method | Description |
|--------|-------------|
|
upload(groupId, data, filename) | Upload encrypted file |
| retrieve(groupId, cid) | Retrieve and decrypt file |
| registerGroup(groupId) | Create new group |
| addGroupMember(groupId, memberId) | Add member to group |
| revokeGroupMember(groupId, memberId) | Remove member (rotates key) |
| authStatus(groupId?) | Check authentication status |
| isAuthorized(groupId, userId?) | Check group authorization |
| getGroupOwner(groupId) | Get group owner |
| getGroupChecksum(groupId) | Get TEE attestation checksum |
| getTransactionsForGroup(groupId) | List group transactions |
| getBalance(accountId?) | Get NEAR balance |
| estimateFee(action) | Estimate operation cost |
| refreshToken() | Force token refresh |
| computeHash(data) | SHA-256 hash (sync) |
| computeHashAsync(data)` | SHA-256 hash (async) |MIT LICENSE - Copyright (c) 2026 CivicTech OĆ
- NOVA Documentation
- NEAR Protocol
- IPFS
- Pinata
- Phala TEE
- NEAR JavaScript API
- Issues: GitHub Issues
- Discussions: GitHub Discussions