Skip to Content
Developers APIClient Protocol

Client Protocol

The TOS Network client protocol defines how applications, wallets, and services interact with TOS nodes. Built on the principle of “Don’t Trust, Verify it”, the protocol ensures secure, efficient, and verifiable communication between clients and the network.

Protocol Overview

Core Components

  • JSON-RPC 2.0: Primary API protocol for client-server communication
  • WebSocket: Real-time event streaming and subscriptions
  • REST API: HTTP-based endpoints for simple queries
  • Authentication: Secure access control and API key management
  • Encryption: End-to-end encryption for sensitive operations

Transport Layers

ProtocolPortPurposeSecurity
HTTP/HTTPS8080/8443JSON-RPC APITLS 1.3
WebSocket8081Real-time eventsWSS (WebSocket Secure)
gRPC8082High-performance APImTLS
TCP Raw2080P2P communicationCustom encryption

JSON-RPC API

Basic Structure

All JSON-RPC requests follow the standard format:

{ "jsonrpc": "2.0", "method": "method_name", "params": { "parameter1": "value1", "parameter2": "value2" }, "id": 1 }

Response format:

{ "jsonrpc": "2.0", "result": { "data": "response_data" }, "id": 1 }

Error response:

{ "jsonrpc": "2.0", "error": { "code": -32000, "message": "Error description", "data": "Additional error information" }, "id": 1 }

Core API Methods

Network Information

// Get network information const networkInfo = await client.request({ method: 'get_network_info', params: {} }); // Response { "network_id": "mainnet", "version": "1.0.0", "block_height": 1250000, "difficulty": 15000000, "hash_rate": "125.5 TH/s", "peer_count": 45, "ai_mining_ratio": 0.42, "energy_efficiency": 0.85 }

Block Operations

// Get block by height const block = await client.request({ method: 'get_block', params: { height: 1250000, include_transactions: true } }); // Get block by hash const blockByHash = await client.request({ method: 'get_block', params: { hash: "0x1234567890abcdef...", include_transactions: false } }); // Get latest block const latestBlock = await client.request({ method: 'get_latest_block', params: { include_transactions: true } });

Transaction Operations

// Send transaction const txResult = await client.request({ method: 'send_transaction', params: { from: "tos1sender-address...", to: "tos1recipient-address...", amount: 100.5, fee: 0.01, privacy_level: "high", use_energy: true, smart_contract: { code: "contract_bytecode", parameters: ["param1", "param2"] } } }); // Get transaction const transaction = await client.request({ method: 'get_transaction', params: { hash: "0xabcdef1234567890..." } }); // Get transaction history const history = await client.request({ method: 'get_transaction_history', params: { address: "tos1address...", limit: 50, offset: 0, include_pending: true } });

Wallet Operations

// Get balance const balance = await client.request({ method: 'get_balance', params: { address: "tos1address...", include_pending: true, privacy_view: "owner" // owner, public, encrypted } }); // Create new address const newAddress = await client.request({ method: 'create_address', params: { wallet_name: "main_wallet", address_type: "stealth", // standard, stealth, multisig privacy_level: "high" } }); // Sign message const signature = await client.request({ method: 'sign_message', params: { address: "tos1address...", message: "Message to sign", signature_type: "ecdsa" // ecdsa, schnorr, ring } });

Mining Operations

// Get mining info const miningInfo = await client.request({ method: 'get_mining_info', params: {} }); // Start mining const miningResult = await client.request({ method: 'start_mining', params: { miner_address: "tos1miner-address...", threads: 4, ai_mining: true, gpu_devices: [0, 1] } }); // Stop mining await client.request({ method: 'stop_mining', params: {} }); // Get mining statistics const miningStats = await client.request({ method: 'get_mining_stats', params: { period: "24h" // 1h, 24h, 7d, 30d } });

Advanced API Methods

Privacy Operations

// Create confidential transaction const confidentialTx = await client.request({ method: 'create_confidential_transaction', params: { inputs: [ { address: "tos1input-address...", amount: 50.0, privacy_proof: "zero_knowledge_proof_data" } ], outputs: [ { address: "tos1output-address...", amount: 49.5, stealth_payment: true } ], ring_size: 11, // For ring signatures mixnet_hops: 3 } }); // Generate stealth address const stealthAddress = await client.request({ method: 'generate_stealth_address', params: { public_spend_key: "spend_key_data", public_view_key: "view_key_data", payment_id: "optional_payment_id" } });

Smart Contract Operations

// Deploy smart contract const deployment = await client.request({ method: 'deploy_smart_contract', params: { bytecode: "compiled_contract_bytecode", constructor_params: ["param1", "param2"], gas_limit: 1000000, gas_price: 0.001, deployer_address: "tos1deployer-address..." } }); // Call smart contract const contractResult = await client.request({ method: 'call_smart_contract', params: { contract_address: "tos1contract-address...", method: "transfer", parameters: ["tos1recipient...", 100], caller_address: "tos1caller-address...", gas_limit: 500000 } }); // Get contract state const contractState = await client.request({ method: 'get_contract_state', params: { contract_address: "tos1contract-address...", variable_name: "balances", key: "tos1address..." } });

WebSocket API

Connection Setup

const WebSocket = require('ws'); class TOSWebSocketClient { constructor(url) { this.ws = new WebSocket(url); this.subscriptions = new Map(); this.requestId = 0; this.ws.on('message', this.handleMessage.bind(this)); this.ws.on('open', this.handleOpen.bind(this)); this.ws.on('error', this.handleError.bind(this)); } handleMessage(data) { const message = JSON.parse(data); if (message.method === 'subscription') { // Handle subscription notification const callback = this.subscriptions.get(message.params.subscription); if (callback) { callback(message.params.result); } } else if (message.id) { // Handle response to request this.handleResponse(message); } } subscribe(topic, callback) { const id = ++this.requestId; this.ws.send(JSON.stringify({ jsonrpc: '2.0', method: 'subscribe', params: { topic: topic }, id: id })); this.subscriptions.set(id, callback); return id; } unsubscribe(subscriptionId) { this.ws.send(JSON.stringify({ jsonrpc: '2.0', method: 'unsubscribe', params: { subscription: subscriptionId }, id: ++this.requestId })); this.subscriptions.delete(subscriptionId); } }

Subscription Topics

Block Notifications

const client = new TOSWebSocketClient('wss://node.tos.network:8081'); // Subscribe to new blocks const blockSubscription = client.subscribe('new_blocks', (block) => { console.log('New block:', block); console.log('Height:', block.height); console.log('Hash:', block.hash); console.log('Transactions:', block.transactions.length); }); // Subscribe to block confirmations const confirmationSubscription = client.subscribe('block_confirmations', (confirmation) => { console.log('Block confirmed:', confirmation.block_hash); console.log('Confirmations:', confirmation.confirmations); });

Transaction Notifications

// Subscribe to pending transactions const pendingTxSubscription = client.subscribe('pending_transactions', (tx) => { console.log('Pending transaction:', tx.hash); console.log('From:', tx.from); console.log('To:', tx.to); console.log('Amount:', tx.amount); }); // Subscribe to confirmed transactions const confirmedTxSubscription = client.subscribe('confirmed_transactions', (tx) => { console.log('Transaction confirmed:', tx.hash); console.log('Block height:', tx.block_height); console.log('Confirmations:', tx.confirmations); }); // Subscribe to transactions for specific address const addressTxSubscription = client.subscribe('address_transactions', (tx) => { console.log('Transaction for address:', tx.address); console.log('Transaction hash:', tx.hash); console.log('Type:', tx.type); // incoming, outgoing }, { address: 'tos1your-address...' });

Mining Notifications

// Subscribe to mining events const miningSubscription = client.subscribe('mining_events', (event) => { switch (event.type) { case 'block_found': console.log('Block found!', event.block_hash); break; case 'difficulty_adjustment': console.log('Difficulty adjusted:', event.new_difficulty); break; case 'ai_mining_reward': console.log('AI mining reward:', event.reward_amount); break; } });

REST API

HTTP Endpoints

Basic Information

GET /api/v1/network/info Content-Type: application/json Response: { "network_id": "mainnet", "version": "1.0.0", "block_height": 1250000, "difficulty": 15000000, "total_supply": "21000000", "circulating_supply": "15750000" }

Block Data

GET /api/v1/blocks/latest GET /api/v1/blocks/1250000 GET /api/v1/blocks/0x1234567890abcdef... Response: { "height": 1250000, "hash": "0x1234567890abcdef...", "previous_hash": "0xfedcba0987654321...", "timestamp": 1672531200, "difficulty": 15000000, "nonce": 4294967295, "merkle_root": "0xabcdef1234567890...", "transaction_count": 156, "size": 1048576, "miner": "tos1miner-address...", "ai_mining": true }

Transaction Data

GET /api/v1/transactions/0xabcdef1234567890... Response: { "hash": "0xabcdef1234567890...", "from": "tos1sender-address...", "to": "tos1recipient-address...", "amount": 100.5, "fee": 0.01, "block_height": 1250000, "block_hash": "0x1234567890abcdef...", "confirmations": 6, "timestamp": 1672531200, "privacy_level": "high", "energy_used": 50 }

Address Information

GET /api/v1/addresses/tos1address.../balance GET /api/v1/addresses/tos1address.../transactions?limit=50&offset=0 Balance Response: { "address": "tos1address...", "balance": 1000.5, "pending_balance": 50.25, "energy": 500, "nonce": 42 }

Authentication and Security

API Key Authentication

class AuthenticatedTOSClient { constructor(apiKey, baseUrl) { this.apiKey = apiKey; this.baseUrl = baseUrl; } async request(method, params) { const timestamp = Date.now(); const signature = this.signRequest(method, params, timestamp); const response = await fetch(`${this.baseUrl}/api/v1/rpc`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-API-Key': this.apiKey, 'X-Timestamp': timestamp.toString(), 'X-Signature': signature }, body: JSON.stringify({ jsonrpc: '2.0', method: method, params: params, id: 1 }) }); return response.json(); } signRequest(method, params, timestamp) { const payload = JSON.stringify({ method, params, timestamp }); return crypto .createHmac('sha256', this.apiKey) .update(payload) .digest('hex'); } }

OAuth 2.0 Integration

class OAuth2TOSClient { constructor(clientId, clientSecret, redirectUri) { this.clientId = clientId; this.clientSecret = clientSecret; this.redirectUri = redirectUri; this.accessToken = null; } getAuthorizationUrl() { const params = new URLSearchParams({ response_type: 'code', client_id: this.clientId, redirect_uri: this.redirectUri, scope: 'read_balance send_transactions mine_blocks', state: crypto.randomBytes(16).toString('hex') }); return `https://auth.tos.network/oauth/authorize?${params}`; } async exchangeCodeForToken(code) { const response = await fetch('https://auth.tos.network/oauth/token', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ grant_type: 'authorization_code', code: code, client_id: this.clientId, client_secret: this.clientSecret, redirect_uri: this.redirectUri }) }); const tokenData = await response.json(); this.accessToken = tokenData.access_token; return tokenData; } async authenticatedRequest(method, params) { if (!this.accessToken) { throw new Error('No access token available'); } const response = await fetch('https://node.tos.network/api/v1/rpc', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${this.accessToken}` }, body: JSON.stringify({ jsonrpc: '2.0', method: method, params: params, id: 1 }) }); return response.json(); } }

Client Implementation Examples

Python Client

import requests import json import websocket import threading from typing import Dict, Any, Callable class TOSNetworkClient: def __init__(self, node_url: str, api_key: str = None): self.node_url = node_url.rstrip('/') self.api_key = api_key self.request_id = 0 def _get_headers(self) -> Dict[str, str]: headers = {'Content-Type': 'application/json'} if self.api_key: headers['X-API-Key'] = self.api_key return headers def _next_id(self) -> int: self.request_id += 1 return self.request_id def call(self, method: str, params: Dict[str, Any] = None) -> Dict[str, Any]: """Make JSON-RPC call to TOS node""" payload = { 'jsonrpc': '2.0', 'method': method, 'params': params or {}, 'id': self._next_id() } response = requests.post( f'{self.node_url}/api/v1/rpc', headers=self._get_headers(), data=json.dumps(payload) ) if response.status_code == 200: result = response.json() if 'error' in result: raise Exception(f"RPC Error: {result['error']}") return result.get('result', {}) else: raise Exception(f"HTTP Error: {response.status_code}") # Network methods def get_network_info(self) -> Dict[str, Any]: return self.call('get_network_info') def get_block_height(self) -> int: return self.call('get_block_height')['height'] # Block methods def get_block(self, height_or_hash: Any, include_transactions: bool = True) -> Dict[str, Any]: if isinstance(height_or_hash, int): params = {'height': height_or_hash} else: params = {'hash': height_or_hash} params['include_transactions'] = include_transactions return self.call('get_block', params) def get_latest_block(self, include_transactions: bool = True) -> Dict[str, Any]: return self.call('get_latest_block', {'include_transactions': include_transactions}) # Transaction methods def send_transaction(self, from_addr: str, to_addr: str, amount: float, fee: float = 0.01, privacy_level: str = 'medium') -> Dict[str, Any]: return self.call('send_transaction', { 'from': from_addr, 'to': to_addr, 'amount': amount, 'fee': fee, 'privacy_level': privacy_level }) def get_transaction(self, tx_hash: str) -> Dict[str, Any]: return self.call('get_transaction', {'hash': tx_hash}) # Wallet methods def get_balance(self, address: str) -> Dict[str, Any]: return self.call('get_balance', {'address': address}) def create_address(self, wallet_name: str = 'default') -> Dict[str, Any]: return self.call('create_address', {'wallet_name': wallet_name}) # Mining methods def start_mining(self, miner_address: str, threads: int = 4, ai_mining: bool = True) -> Dict[str, Any]: return self.call('start_mining', { 'miner_address': miner_address, 'threads': threads, 'ai_mining': ai_mining }) def stop_mining(self) -> Dict[str, Any]: return self.call('stop_mining') def get_mining_info(self) -> Dict[str, Any]: return self.call('get_mining_info') class TOSWebSocketClient: def __init__(self, ws_url: str): self.ws_url = ws_url self.ws = None self.subscriptions = {} self.request_id = 0 def connect(self): """Connect to WebSocket""" self.ws = websocket.WebSocketApp( self.ws_url, on_message=self._on_message, on_error=self._on_error, on_close=self._on_close ) # Run in separate thread wst = threading.Thread(target=self.ws.run_forever) wst.daemon = True wst.start() def _on_message(self, ws, message): data = json.loads(message) if 'method' in data and data['method'] == 'subscription': # Handle subscription notification sub_id = data['params']['subscription'] if sub_id in self.subscriptions: callback = self.subscriptions[sub_id] callback(data['params']['result']) def _on_error(self, ws, error): print(f"WebSocket error: {error}") def _on_close(self, ws, close_status_code, close_msg): print("WebSocket connection closed") def subscribe(self, topic: str, callback: Callable) -> int: """Subscribe to topic and return subscription ID""" sub_id = self._next_id() request = { 'jsonrpc': '2.0', 'method': 'subscribe', 'params': {'topic': topic}, 'id': sub_id } self.ws.send(json.dumps(request)) self.subscriptions[sub_id] = callback return sub_id def unsubscribe(self, sub_id: int): """Unsubscribe from topic""" request = { 'jsonrpc': '2.0', 'method': 'unsubscribe', 'params': {'subscription': sub_id}, 'id': self._next_id() } self.ws.send(json.dumps(request)) if sub_id in self.subscriptions: del self.subscriptions[sub_id] def _next_id(self) -> int: self.request_id += 1 return self.request_id # Usage example if __name__ == '__main__': # Create client client = TOSNetworkClient('https://node.tos.network', api_key='your-api-key') # Get network info network_info = client.get_network_info() print(f"Network: {network_info['network_id']}") print(f"Block height: {network_info['block_height']}") # Get latest block latest_block = client.get_latest_block() print(f"Latest block hash: {latest_block['hash']}") # WebSocket example ws_client = TOSWebSocketClient('wss://node.tos.network:8081') ws_client.connect() # Subscribe to new blocks def on_new_block(block): print(f"New block: {block['height']} - {block['hash']}") ws_client.subscribe('new_blocks', on_new_block)

Go Client

package main import ( "bytes" "encoding/json" "fmt" "io" "net/http" "sync" "time" "github.com/gorilla/websocket" ) type TOSClient struct { nodeURL string apiKey string client *http.Client requestID int64 mutex sync.Mutex } type JSONRPCRequest struct { JSONRPC string `json:"jsonrpc"` Method string `json:"method"` Params interface{} `json:"params"` ID int64 `json:"id"` } type JSONRPCResponse struct { JSONRPC string `json:"jsonrpc"` Result json.RawMessage `json:"result,omitempty"` Error *JSONRPCError `json:"error,omitempty"` ID int64 `json:"id"` } type JSONRPCError struct { Code int `json:"code"` Message string `json:"message"` Data interface{} `json:"data,omitempty"` } func NewTOSClient(nodeURL, apiKey string) *TOSClient { return &TOSClient{ nodeURL: nodeURL, apiKey: apiKey, client: &http.Client{ Timeout: 30 * time.Second, }, } } func (c *TOSClient) nextID() int64 { c.mutex.Lock() defer c.mutex.Unlock() c.requestID++ return c.requestID } func (c *TOSClient) Call(method string, params interface{}) (json.RawMessage, error) { request := JSONRPCRequest{ JSONRPC: "2.0", Method: method, Params: params, ID: c.nextID(), } requestBody, err := json.Marshal(request) if err != nil { return nil, fmt.Errorf("failed to marshal request: %v", err) } req, err := http.NewRequest("POST", c.nodeURL+"/api/v1/rpc", bytes.NewBuffer(requestBody)) if err != nil { return nil, fmt.Errorf("failed to create request: %v", err) } req.Header.Set("Content-Type", "application/json") if c.apiKey != "" { req.Header.Set("X-API-Key", c.apiKey) } resp, err := c.client.Do(req) if err != nil { return nil, fmt.Errorf("failed to send request: %v", err) } defer resp.Body.Close() responseBody, err := io.ReadAll(resp.Body) if err != nil { return nil, fmt.Errorf("failed to read response: %v", err) } var jsonRPCResp JSONRPCResponse if err := json.Unmarshal(responseBody, &jsonRPCResp); err != nil { return nil, fmt.Errorf("failed to unmarshal response: %v", err) } if jsonRPCResp.Error != nil { return nil, fmt.Errorf("RPC error %d: %s", jsonRPCResp.Error.Code, jsonRPCResp.Error.Message) } return jsonRPCResp.Result, nil } // Network methods func (c *TOSClient) GetNetworkInfo() (map[string]interface{}, error) { result, err := c.Call("get_network_info", nil) if err != nil { return nil, err } var networkInfo map[string]interface{} if err := json.Unmarshal(result, &networkInfo); err != nil { return nil, err } return networkInfo, nil } // Block methods func (c *TOSClient) GetBlock(heightOrHash interface{}, includeTransactions bool) (map[string]interface{}, error) { params := map[string]interface{}{ "include_transactions": includeTransactions, } switch v := heightOrHash.(type) { case int, int64: params["height"] = v case string: params["hash"] = v default: return nil, fmt.Errorf("invalid heightOrHash type") } result, err := c.Call("get_block", params) if err != nil { return nil, err } var block map[string]interface{} if err := json.Unmarshal(result, &block); err != nil { return nil, err } return block, nil } // Transaction methods func (c *TOSClient) SendTransaction(from, to string, amount, fee float64) (map[string]interface{}, error) { params := map[string]interface{}{ "from": from, "to": to, "amount": amount, "fee": fee, } result, err := c.Call("send_transaction", params) if err != nil { return nil, err } var txResult map[string]interface{} if err := json.Unmarshal(result, &txResult); err != nil { return nil, err } return txResult, nil } // WebSocket client type TOSWebSocketClient struct { conn *websocket.Conn subscriptions map[int64]func(interface{}) requestID int64 mutex sync.RWMutex } func NewTOSWebSocketClient(wsURL string) (*TOSWebSocketClient, error) { conn, _, err := websocket.DefaultDialer.Dial(wsURL, nil) if err != nil { return nil, fmt.Errorf("failed to connect to WebSocket: %v", err) } client := &TOSWebSocketClient{ conn: conn, subscriptions: make(map[int64]func(interface{})), } go client.readMessages() return client, nil } func (c *TOSWebSocketClient) readMessages() { for { _, message, err := c.conn.ReadMessage() if err != nil { fmt.Printf("WebSocket read error: %v\n", err) return } var response map[string]interface{} if err := json.Unmarshal(message, &response); err != nil { fmt.Printf("Failed to unmarshal WebSocket message: %v\n", err) continue } if method, ok := response["method"].(string); ok && method == "subscription" { if params, ok := response["params"].(map[string]interface{}); ok { if subID, ok := params["subscription"].(float64); ok { c.mutex.RLock() if callback, exists := c.subscriptions[int64(subID)]; exists { callback(params["result"]) } c.mutex.RUnlock() } } } } } func (c *TOSWebSocketClient) Subscribe(topic string, callback func(interface{})) (int64, error) { c.mutex.Lock() c.requestID++ subID := c.requestID c.subscriptions[subID] = callback c.mutex.Unlock() request := map[string]interface{}{ "jsonrpc": "2.0", "method": "subscribe", "params": map[string]string{"topic": topic}, "id": subID, } if err := c.conn.WriteJSON(request); err != nil { c.mutex.Lock() delete(c.subscriptions, subID) c.mutex.Unlock() return 0, fmt.Errorf("failed to send subscription request: %v", err) } return subID, nil } func (c *TOSWebSocketClient) Unsubscribe(subID int64) error { request := map[string]interface{}{ "jsonrpc": "2.0", "method": "unsubscribe", "params": map[string]int64{"subscription": subID}, "id": c.requestID + 1, } if err := c.conn.WriteJSON(request); err != nil { return fmt.Errorf("failed to send unsubscription request: %v", err) } c.mutex.Lock() delete(c.subscriptions, subID) c.mutex.Unlock() return nil } func (c *TOSWebSocketClient) Close() error { return c.conn.Close() } // Example usage func main() { // Create HTTP client client := NewTOSClient("https://node.tos.network", "your-api-key") // Get network info networkInfo, err := client.GetNetworkInfo() if err != nil { fmt.Printf("Error getting network info: %v\n", err) return } fmt.Printf("Network ID: %v\n", networkInfo["network_id"]) fmt.Printf("Block Height: %v\n", networkInfo["block_height"]) // WebSocket example wsClient, err := NewTOSWebSocketClient("wss://node.tos.network:8081") if err != nil { fmt.Printf("Error creating WebSocket client: %v\n", err) return } defer wsClient.Close() // Subscribe to new blocks subID, err := wsClient.Subscribe("new_blocks", func(data interface{}) { if block, ok := data.(map[string]interface{}); ok { fmt.Printf("New block: %v - %v\n", block["height"], block["hash"]) } }) if err != nil { fmt.Printf("Error subscribing to new blocks: %v\n", err) return } // Keep the program running time.Sleep(30 * time.Second) // Unsubscribe wsClient.Unsubscribe(subID) }

Error Handling

Standard Error Codes

CodeMessageDescription
-32700Parse errorInvalid JSON received
-32600Invalid RequestJSON-RPC request is invalid
-32601Method not foundRequested method does not exist
-32602Invalid paramsInvalid method parameters
-32603Internal errorInternal JSON-RPC error
-32000Server errorTOS Network specific errors

TOS-Specific Error Codes

CodeMessageDescription
-40001Insufficient balanceNot enough funds for transaction
-40002Invalid addressAddress format is incorrect
-40003Transaction rejectedTransaction validation failed
-40004Block not foundRequested block does not exist
-40005Mining errorMining operation failed
-40006Privacy errorPrivacy operation failed
-40007Smart contract errorContract execution failed

Error Handling Example

class TOSErrorHandler { static handle(error) { switch (error.code) { case -40001: return { type: 'INSUFFICIENT_BALANCE', message: 'Insufficient funds for this transaction', action: 'Please check your balance and try again' }; case -40002: return { type: 'INVALID_ADDRESS', message: 'The provided address is not valid', action: 'Please verify the address format' }; case -40003: return { type: 'TRANSACTION_REJECTED', message: 'Transaction was rejected by the network', action: 'Check transaction parameters and network status' }; default: return { type: 'UNKNOWN_ERROR', message: error.message || 'An unknown error occurred', action: 'Please try again or contact support' }; } } } // Usage try { const result = await client.sendTransaction(params); } catch (error) { const handledError = TOSErrorHandler.handle(error); console.error(handledError.message); // Show user-friendly error message }

Rate Limiting

Default Limits

  • Unauthenticated: 100 requests per minute
  • API Key: 1,000 requests per minute
  • OAuth2: 5,000 requests per minute
  • WebSocket: 10 subscriptions per connection

Rate Limit Headers

X-RateLimit-Limit: 1000 X-RateLimit-Remaining: 999 X-RateLimit-Reset: 1672531260

Rate Limiting Implementation

class RateLimiter { constructor(maxRequests, windowMs) { this.maxRequests = maxRequests; this.windowMs = windowMs; this.requests = []; } canMakeRequest() { const now = Date.now(); const windowStart = now - this.windowMs; // Remove old requests this.requests = this.requests.filter(time => time > windowStart); if (this.requests.length < this.maxRequests) { this.requests.push(now); return true; } return false; } timeUntilReset() { if (this.requests.length === 0) return 0; const oldestRequest = Math.min(...this.requests); return Math.max(0, this.windowMs - (Date.now() - oldestRequest)); } } // Usage in client const rateLimiter = new RateLimiter(1000, 60000); // 1000 requests per minute async function makeRequest(client, method, params) { if (!rateLimiter.canMakeRequest()) { const waitTime = rateLimiter.timeUntilReset(); throw new Error(`Rate limit exceeded. Try again in ${waitTime}ms`); } return client.call(method, params); }

The TOS Network client protocol provides a robust, secure, and efficient way to interact with the TOS blockchain. By following the “Don’t Trust, Verify it” principle, all protocol interactions are transparent and verifiable, ensuring the highest level of security and reliability for applications built on the TOS Network.

Last updated on