TypeScript client for the VALR cryptocurrency exchange API with full type safety, WebSocket support, and comprehensive endpoint coverage
npm install valr-typescript-clientA comprehensive, fully-typed TypeScript/JavaScript client for the VALR cryptocurrency exchange API.
- ✅ Full TypeScript Support - Complete type definitions for all endpoints and responses
- ✅ Comprehensive API Coverage - All 147 REST endpoints implemented
- ✅ WebSocket Support - Real-time market data and account updates (coming soon)
- ✅ Modern Architecture - Built with axios, supports both ESM and CommonJS
- ✅ Automatic Authentication - HMAC SHA512 request signing handled automatically
- ✅ Error Handling - Custom error classes for different error types
- ✅ Rate Limit Aware - Built-in awareness of VALR API rate limits
- ✅ Subaccount Support - Easy subaccount impersonation
``bash`
npm install valr-typescript-client
or
`bash`
yarn add valr-typescript-client
or
`bash`
pnpm add valr-typescript-client
`typescript
import { ValrClient } from 'valr-typescript-client';
const client = new ValrClient();
// Get server time
const time = await client.public.getServerTime();
console.log('Server time:', time);
// Get market summary for all pairs
const markets = await client.public.getMarketSummary();
console.log('Markets:', markets);
// Get order book for a specific pair
const orderBook = await client.public.getOrderBook('BTCZAR');
console.log('Order book:', orderBook);
// Get currencies
const currencies = await client.public.getCurrencies();
console.log('Supported currencies:', currencies);
`
`typescript
import { ValrClient } from 'valr-typescript-client';
const client = new ValrClient({
apiKey: 'your-api-key',
apiSecret: 'your-api-secret',
});
// Get account balances
const balances = await client.account.getBalances();
console.log('Balances:', balances);
// Place a limit order
const order = await client.trading.placeLimitOrder({
pair: 'BTCZAR',
side: 'BUY',
quantity: '0.001',
price: '500000',
postOnly: 'POST_ONLY_REPRICE',
customerOrderId: 'my-order-1',
});
console.log('Order placed:', order);
// Get open orders
const openOrders = await client.trading.getAllOpenOrders();
console.log('Open orders:', openOrders);
// Get trade history
const trades = await client.account.getTradeHistory({
skip: 0,
limit: 100,
});
console.log('Trade history:', trades);
`
`typescript
// Place a market order
const marketOrder = await client.trading.placeMarketOrder({
pair: 'ETHZAR',
side: 'BUY',
quoteAmount: '1000', // Spend 1000 ZAR
});
// Place a stop-limit order
const stopOrder = await client.trading.placeStopLimitOrder({
pair: 'BTCZAR',
side: 'SELL',
quantity: '0.001',
price: '450000',
stopPrice: '460000',
});
// Place batch orders
const batchOrders = await client.trading.placeBatchOrders({
requests: [
{
pair: 'BTCZAR',
side: 'BUY',
quantity: '0.001',
price: '480000',
postOnly: 'POST_ONLY_REPRICE',
},
{
pair: 'ETHZAR',
side: 'BUY',
quantity: '0.01',
price: '30000',
postOnly: 'POST_ONLY_REPRICE',
},
],
});
// Get order status
const orderStatus = await client.trading.getOrderStatus('BTCZAR', order.id);
console.log('Order status:', orderStatus);
// Cancel order
await client.trading.cancelOrder({
pair: 'BTCZAR',
orderId: order.id,
});
`
`typescript
// Get crypto deposit address
const depositAddress = await client.wallets.getCryptoDepositAddress('BTC');
console.log('Deposit to:', depositAddress.address);
// Withdraw crypto
const withdrawal = await client.wallets.withdrawCrypto({
currency: 'BTC',
amount: '0.001',
address: 'bc1q...',
});
console.log('Withdrawal ID:', withdrawal.id);
// Get bank accounts
const bankAccounts = await client.wallets.getBankAccounts('ZAR');
console.log('Bank accounts:', bankAccounts);
`
`typescript
// Get open futures positions
const positions = await client.futures.getOpenPositions();
console.log('Open positions:', positions);
// Get leverage info
const leverage = await client.futures.getLeverageInfo('BTCUSDTPERP');
console.log('Current leverage:', leverage);
// Update leverage
await client.futures.updateLeverage('BTCUSDTPERP', {
leverageMultiple: 5,
});
`
`typescript
const client = new ValrClient({
apiKey: 'your-primary-account-api-key',
apiSecret: 'your-primary-account-api-secret',
subaccountId: 'subaccount-id',
});
// All requests will now be made on behalf of the subaccount
const balances = await client.account.getBalances();
// Change subaccount or clear
client.setSubaccountId('different-subaccount-id');
client.setSubaccountId(undefined); // Back to primary account
`
The client organizes endpoints into logical categories:
- client.public - Public market data (no auth required)
- client.account - Account information, balances, history
- client.trading - Order placement and management
- client.wallets - Deposits and withdrawals
- client.futures - Futures positions and leverage
- client.margin - Margin trading
- client.loans - Lending and borrowing
- client.earn - Staking and earning products
- client.pay - Payment functionality
- client.bundles - Currency bundles
- client.health - API health status
VALR API uses HMAC SHA512 signatures for authentication. This client handles all signature generation automatically.
1. Enable 2FA on your VALR account
2. Navigate to Account → API Keys
3. Create a new API key with appropriate permissions:
- View: Read-only access to account data
- Trade: Place and cancel orders
- Transfer: Transfer between accounts
- Withdraw: Withdraw funds
- Never commit your API keys to version control
- Store keys in environment variables:
`typescript`
const client = new ValrClient({
apiKey: process.env.VALR_API_KEY,
apiSecret: process.env.VALR_API_SECRET,
});
- Use minimal permissions for each key
- Regularly rotate your API keys
- Delete unused API keys
This package includes cryptographic checksums to verify package integrity and protect against supply chain attacks.
After installing from npm or any registry, you can verify the package integrity:
`bashUsing npm script (cross-platform)
npm run verify
This will verify that:
- All
dist/ files (the compiled JavaScript you actually execute) match the official build
- The package hasn't been tampered with after publication
- You're running the exact code from the GitHub release
- Shows you the Git commit SHA of the source code it was built fromWhat you're verifying: The compiled JavaScript files in
dist/ are what run when you use this package. The checksums prove these match the official build from GitHub Actions.$3
The checksum verification checks:
Distribution files (
dist/) - What actually executes:
- dist/index.js, dist/index.mjs - Compiled JavaScript (ESM/CJS)
- dist/index.d.ts, dist/index.d.mts - TypeScript definitions
- dist/*.map - Source mapsSource files (
src/) - For transparency:
- Original TypeScript source code
- Allows you to inspect what the dist was built from
- Enables reproducible builds (advanced users)Metadata:
- Git commit SHA - Links to exact source code on GitHub
- Build timestamp - When the package was built
- Package version - Version number
Security model: Checksums prove your
dist/ files match the official GitHub Actions build. You can inspect the source code at the Git commit shown in the checksums.$3
If you prefer to build from source yourself:
`bash
Clone the repository
git clone https://github.com/yashutanna/valr-typescript-client.git
cd valr-typescript-clientCheckout a specific release
git checkout v1.0.9Install dependencies (use ci for reproducible builds)
npm ciBuild
npm run buildRun tests
npm test
`$3
For maximum trust, verify the official build was created from clean source code:
`bash
Clone and checkout the release
git clone https://github.com/yashutanna/valr-typescript-client.git
cd valr-typescript-client
git checkout v1.0.9Build from source
npm ci
npm run buildCompare your build with official checksums
bash scripts/build-and-verify.sh
`This attempts to reproduce the official build and compares your locally-built
dist/ files with the checksums from the official release. Note that perfect reproducibility is challenging with JavaScript builds, but the script will show you any differences.$3
Every package published to npm includes:
-
CHECKSUMS.txt - SHA256 hashes of all files
- Git commit SHA that was built
- Build timestamp
- Verification scriptsThe checksums are available in multiple places:
- In the repository - Committed with each release (permanent Git history)
- GitHub Releases - Attached as an asset to every release
- npm package - Included at
node_modules/valr-typescript-client/CHECKSUMS.txt
- GitHub Actions - Available as workflow artifactsTo verify a specific release, check the Git tag or GitHub release assets.
Error Handling
The client throws typed errors for different failure scenarios:
`typescript
import {
ValrError,
ValrAuthenticationError,
ValrRateLimitError,
ValrValidationError,
ValrApiError,
} from 'valr-typescript-client';try {
await client.trading.placeLimitOrder({
pair: 'BTCZAR',
side: 'BUY',
quantity: '0.001',
price: '500000',
});
} catch (error) {
if (error instanceof ValrAuthenticationError) {
console.error('Authentication failed - check your API keys');
} else if (error instanceof ValrRateLimitError) {
console.error('Rate limit exceeded - slow down requests');
} else if (error instanceof ValrValidationError) {
console.error('Validation error:', error.errors);
} else if (error instanceof ValrApiError) {
console.error('API error:', error.statusCode, error.message);
} else if (error instanceof ValrError) {
console.error('VALR error:', error.message);
} else {
console.error('Unknown error:', error);
}
}
`Rate Limits
VALR enforces rate limits on API requests:
- 2000 requests per minute per API key
- 1200 requests per minute per IP address
- Some endpoints have stricter per-second limits (e.g., order placement: 400/s)
The client automatically includes rate limit information in error responses when limits are exceeded.
TypeScript Support
The client is written in TypeScript and provides comprehensive type definitions:
`typescript
import type {
CurrencyPair,
OrderSide,
OrderStatus,
Balance,
MarketSummary,
OrderResponse,
} from 'valr-typescript-client';// All API responses are fully typed
const balances: Balance[] = await client.account.getBalances();
const markets: MarketSummary[] = await client.public.getMarketSummary();
// Request parameters are type-checked
await client.trading.placeLimitOrder({
pair: 'BTCZAR', // Type: CurrencyPair
side: 'BUY', // Type: OrderSide
quantity: '0.001',
price: '500000',
postOnly: 'POST_ONLY_REPRICE', // Type-checked enum
});
`Development
`bash
Install dependencies
npm installBuild the project
npm run buildRun tests
npm testRun tests in watch mode
npm run test:watchType check
npm run type-check
``Contributions are welcome! Please feel free to submit a Pull Request.
MIT
- VALR Website
- VALR API Documentation
- GitHub Repository
- NPM Package
This is an unofficial client library and is not affiliated with or endorsed by VALR. Use at your own risk.
For issues and questions: