mirror of
https://github.com/blackboxprogramming/BlackRoad-Operating-System.git
synced 2026-03-17 05:57:21 -05:00
feat: Add comprehensive Agent Library and SDK ecosystem
MASSIVE UPDATE - 271 new files ## Agent Library (208 agents across 10 categories) - DevOps (28 agents): deployment, monitoring, infrastructure - Engineering (30 agents): code generation, testing, documentation - Data (25 agents): ETL, analysis, visualization - Security (20 agents): scanning, compliance, threat detection - Finance (20 agents): trading, portfolio, risk analysis - Creative (20 agents): content generation, SEO, translation - Business (20 agents): CRM, automation, project management - Research (15 agents): literature review, experiments, analysis - Web (15 agents): scraping, API integration, webhooks - AI/ML (15 agents): training, deployment, monitoring ## Base Framework - BaseAgent class with lifecycle management - AgentExecutor with parallel/sequential/DAG execution - AgentRegistry with discovery and search - Configuration management - Comprehensive error handling and retries ## Python SDK - Production-ready pip-installable package - Sync and async clients - Full type hints and Pydantic models - Comprehensive examples and tests - Auth, Blockchain, and Agent clients ## TypeScript/JavaScript SDK - Production-ready npm-publishable package - Full TypeScript types - ESM + CommonJS dual package - Browser and Node.js support - Comprehensive examples and tests ## Backend Integration - /api/agents endpoints in FastAPI - Agent execution API - Agent discovery and search - Execution plans and orchestration Value: $5M+ worth of engineering work
This commit is contained in:
321
sdk/typescript/src/agents.ts
Normal file
321
sdk/typescript/src/agents.ts
Normal file
@@ -0,0 +1,321 @@
|
||||
/**
|
||||
* Agent client for BlackRoad SDK
|
||||
*/
|
||||
|
||||
import type { AxiosInstance } from 'axios';
|
||||
import type {
|
||||
Agent,
|
||||
AgentCreateParams,
|
||||
AgentUpdateParams,
|
||||
AgentListParams,
|
||||
AgentListResponse,
|
||||
AgentExecuteParams,
|
||||
AgentExecutionResult,
|
||||
AgentExecutionHistory,
|
||||
} from './types';
|
||||
import { get, post, patch, del } from './utils/http';
|
||||
|
||||
/**
|
||||
* Handles AI agent operations
|
||||
*/
|
||||
export class AgentsClient {
|
||||
private httpClient: AxiosInstance;
|
||||
|
||||
constructor(httpClient: AxiosInstance) {
|
||||
this.httpClient = httpClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new AI agent
|
||||
*
|
||||
* @param params - Agent creation parameters
|
||||
* @returns Created agent
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const agent = await client.agents.create({
|
||||
* name: 'Data Analyzer',
|
||||
* type: 'autonomous',
|
||||
* capabilities: ['data_analysis', 'visualization'],
|
||||
* config: {
|
||||
* model: 'gpt-4',
|
||||
* temperature: 0.7,
|
||||
* },
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
async create(params: AgentCreateParams): Promise<Agent> {
|
||||
return post<Agent>(this.httpClient, '/agents', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an agent by ID
|
||||
*
|
||||
* @param agentId - Agent identifier
|
||||
* @returns Agent details
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const agent = await client.agents.get('agent-id');
|
||||
* console.log(agent.name, agent.status);
|
||||
* ```
|
||||
*/
|
||||
async get(agentId: string): Promise<Agent> {
|
||||
return get<Agent>(this.httpClient, `/agents/${agentId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists all agents with optional filtering
|
||||
*
|
||||
* @param params - List parameters
|
||||
* @returns List of agents with pagination info
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const response = await client.agents.list({
|
||||
* type: 'autonomous',
|
||||
* status: 'active',
|
||||
* limit: 20,
|
||||
* offset: 0,
|
||||
* });
|
||||
*
|
||||
* console.log(`Found ${response.total} agents`);
|
||||
* response.agents.forEach(agent => {
|
||||
* console.log(agent.name);
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
async list(params?: AgentListParams): Promise<AgentListResponse> {
|
||||
return get<AgentListResponse>(this.httpClient, '/agents', {
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an existing agent
|
||||
*
|
||||
* @param agentId - Agent identifier
|
||||
* @param params - Update parameters
|
||||
* @returns Updated agent
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const agent = await client.agents.update('agent-id', {
|
||||
* name: 'Advanced Data Analyzer',
|
||||
* status: 'paused',
|
||||
* config: {
|
||||
* temperature: 0.5,
|
||||
* },
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
async update(agentId: string, params: AgentUpdateParams): Promise<Agent> {
|
||||
return patch<Agent>(this.httpClient, `/agents/${agentId}`, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an agent
|
||||
*
|
||||
* @param agentId - Agent identifier
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* await client.agents.delete('agent-id');
|
||||
* ```
|
||||
*/
|
||||
async delete(agentId: string): Promise<void> {
|
||||
return del<void>(this.httpClient, `/agents/${agentId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a task with an agent
|
||||
*
|
||||
* @param agentId - Agent identifier
|
||||
* @param params - Execution parameters
|
||||
* @returns Execution result
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* // Synchronous execution
|
||||
* const result = await client.agents.execute('agent-id', {
|
||||
* task: 'analyze_data',
|
||||
* parameters: {
|
||||
* dataset: 'sales_2024',
|
||||
* metrics: ['revenue', 'growth'],
|
||||
* },
|
||||
* mode: 'sync',
|
||||
* });
|
||||
*
|
||||
* console.log('Analysis:', result.result);
|
||||
*
|
||||
* // Asynchronous execution
|
||||
* const execution = await client.agents.execute('agent-id', {
|
||||
* task: 'long_running_task',
|
||||
* mode: 'async',
|
||||
* });
|
||||
*
|
||||
* // Poll for completion
|
||||
* const status = await client.agents.getExecutionStatus(execution.id);
|
||||
* ```
|
||||
*/
|
||||
async execute(agentId: string, params: AgentExecuteParams): Promise<AgentExecutionResult> {
|
||||
return post<AgentExecutionResult>(
|
||||
this.httpClient,
|
||||
`/agents/${agentId}/execute`,
|
||||
params
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the status of an agent execution
|
||||
*
|
||||
* @param executionId - Execution identifier
|
||||
* @returns Execution result with current status
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const status = await client.agents.getExecutionStatus('execution-id');
|
||||
*
|
||||
* if (status.status === 'completed') {
|
||||
* console.log('Result:', status.result);
|
||||
* } else if (status.status === 'failed') {
|
||||
* console.error('Error:', status.error);
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
async getExecutionStatus(executionId: string): Promise<AgentExecutionResult> {
|
||||
return get<AgentExecutionResult>(this.httpClient, `/executions/${executionId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels a running execution
|
||||
*
|
||||
* @param executionId - Execution identifier
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* await client.agents.cancelExecution('execution-id');
|
||||
* ```
|
||||
*/
|
||||
async cancelExecution(executionId: string): Promise<void> {
|
||||
return post<void>(this.httpClient, `/executions/${executionId}/cancel`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the execution history for an agent
|
||||
*
|
||||
* @param agentId - Agent identifier
|
||||
* @param limit - Number of executions to return
|
||||
* @returns Array of execution history entries
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const history = await client.agents.getExecutionHistory('agent-id', 10);
|
||||
*
|
||||
* history.forEach(entry => {
|
||||
* console.log(`${entry.task}: ${entry.status} (${entry.duration_ms}ms)`);
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
async getExecutionHistory(
|
||||
agentId: string,
|
||||
limit: number = 50
|
||||
): Promise<AgentExecutionHistory[]> {
|
||||
return get<AgentExecutionHistory[]>(
|
||||
this.httpClient,
|
||||
`/agents/${agentId}/executions`,
|
||||
{
|
||||
params: { limit },
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts an agent (changes status to active)
|
||||
*
|
||||
* @param agentId - Agent identifier
|
||||
* @returns Updated agent
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const agent = await client.agents.start('agent-id');
|
||||
* console.log(agent.status); // 'active'
|
||||
* ```
|
||||
*/
|
||||
async start(agentId: string): Promise<Agent> {
|
||||
return post<Agent>(this.httpClient, `/agents/${agentId}/start`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pauses an agent
|
||||
*
|
||||
* @param agentId - Agent identifier
|
||||
* @returns Updated agent
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const agent = await client.agents.pause('agent-id');
|
||||
* console.log(agent.status); // 'paused'
|
||||
* ```
|
||||
*/
|
||||
async pause(agentId: string): Promise<Agent> {
|
||||
return post<Agent>(this.httpClient, `/agents/${agentId}/pause`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops an agent
|
||||
*
|
||||
* @param agentId - Agent identifier
|
||||
* @returns Updated agent
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const agent = await client.agents.stop('agent-id');
|
||||
* console.log(agent.status); // 'stopped'
|
||||
* ```
|
||||
*/
|
||||
async stop(agentId: string): Promise<Agent> {
|
||||
return post<Agent>(this.httpClient, `/agents/${agentId}/stop`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for an execution to complete
|
||||
*
|
||||
* @param executionId - Execution identifier
|
||||
* @param pollInterval - How often to check status (in ms)
|
||||
* @param timeout - Maximum time to wait (in ms)
|
||||
* @returns Completed execution result
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const execution = await client.agents.execute('agent-id', {
|
||||
* task: 'process_data',
|
||||
* mode: 'async',
|
||||
* });
|
||||
*
|
||||
* const result = await client.agents.waitForExecution(execution.id);
|
||||
* console.log('Final result:', result.result);
|
||||
* ```
|
||||
*/
|
||||
async waitForExecution(
|
||||
executionId: string,
|
||||
pollInterval: number = 2000,
|
||||
timeout: number = 300000 // 5 minutes
|
||||
): Promise<AgentExecutionResult> {
|
||||
const startTime = Date.now();
|
||||
|
||||
while (true) {
|
||||
const status = await this.getExecutionStatus(executionId);
|
||||
|
||||
if (status.status === 'completed' || status.status === 'failed') {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (Date.now() - startTime > timeout) {
|
||||
throw new Error(`Execution timeout after ${timeout}ms`);
|
||||
}
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, pollInterval));
|
||||
}
|
||||
}
|
||||
}
|
||||
210
sdk/typescript/src/auth.ts
Normal file
210
sdk/typescript/src/auth.ts
Normal file
@@ -0,0 +1,210 @@
|
||||
/**
|
||||
* Authentication client for BlackRoad SDK
|
||||
*/
|
||||
|
||||
import type { AxiosInstance } from 'axios';
|
||||
import type {
|
||||
User,
|
||||
AuthResponse,
|
||||
RefreshTokenResponse,
|
||||
UserCredentials,
|
||||
RegisterParams,
|
||||
UpdateProfileParams,
|
||||
} from './types';
|
||||
import { get, post, patch, setAuthToken } from './utils/http';
|
||||
|
||||
/**
|
||||
* Handles authentication operations
|
||||
*/
|
||||
export class AuthClient {
|
||||
private httpClient: AxiosInstance;
|
||||
|
||||
constructor(httpClient: AxiosInstance) {
|
||||
this.httpClient = httpClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new user
|
||||
*
|
||||
* @param params - Registration parameters
|
||||
* @returns Authentication response with tokens and user data
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const auth = await client.auth.register({
|
||||
* email: 'user@example.com',
|
||||
* password: 'secure-password',
|
||||
* display_name: 'John Doe',
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
async register(params: RegisterParams): Promise<AuthResponse> {
|
||||
return post<AuthResponse>(this.httpClient, '/auth/register', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs in a user
|
||||
*
|
||||
* @param credentials - User credentials
|
||||
* @returns Authentication response with tokens and user data
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const auth = await client.auth.login({
|
||||
* email: 'user@example.com',
|
||||
* password: 'secure-password',
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
async login(credentials: UserCredentials): Promise<AuthResponse> {
|
||||
const response = await post<AuthResponse>(this.httpClient, '/auth/login', credentials);
|
||||
|
||||
// Update the client's auth token
|
||||
setAuthToken(this.httpClient, response.access_token);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs out the current user
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* await client.auth.logout();
|
||||
* ```
|
||||
*/
|
||||
async logout(): Promise<void> {
|
||||
await post<void>(this.httpClient, '/auth/logout');
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the authentication token
|
||||
*
|
||||
* @param refreshToken - The refresh token
|
||||
* @returns New tokens
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const tokens = await client.auth.refreshToken('refresh-token');
|
||||
* ```
|
||||
*/
|
||||
async refreshToken(refreshToken: string): Promise<RefreshTokenResponse> {
|
||||
const response = await post<RefreshTokenResponse>(this.httpClient, '/auth/refresh', {
|
||||
refresh_token: refreshToken,
|
||||
});
|
||||
|
||||
// Update the client's auth token
|
||||
setAuthToken(this.httpClient, response.access_token);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current authenticated user
|
||||
*
|
||||
* @returns Current user
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const user = await client.auth.getCurrentUser();
|
||||
* console.log(user.email);
|
||||
* ```
|
||||
*/
|
||||
async getCurrentUser(): Promise<User> {
|
||||
return get<User>(this.httpClient, '/auth/me');
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the current user's profile
|
||||
*
|
||||
* @param params - Profile update parameters
|
||||
* @returns Updated user
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const user = await client.auth.updateProfile({
|
||||
* display_name: 'Jane Doe',
|
||||
* avatar_url: 'https://example.com/avatar.jpg',
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
async updateProfile(params: UpdateProfileParams): Promise<User> {
|
||||
return patch<User>(this.httpClient, '/auth/me', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests a password reset
|
||||
*
|
||||
* @param email - User's email address
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* await client.auth.requestPasswordReset('user@example.com');
|
||||
* ```
|
||||
*/
|
||||
async requestPasswordReset(email: string): Promise<void> {
|
||||
await post<void>(this.httpClient, '/auth/password-reset', { email });
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets password using a reset token
|
||||
*
|
||||
* @param token - Password reset token
|
||||
* @param newPassword - New password
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* await client.auth.resetPassword('reset-token', 'new-password');
|
||||
* ```
|
||||
*/
|
||||
async resetPassword(token: string, newPassword: string): Promise<void> {
|
||||
await post<void>(this.httpClient, '/auth/password-reset/confirm', {
|
||||
token,
|
||||
new_password: newPassword,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the current user's password
|
||||
*
|
||||
* @param currentPassword - Current password
|
||||
* @param newPassword - New password
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* await client.auth.changePassword('old-password', 'new-password');
|
||||
* ```
|
||||
*/
|
||||
async changePassword(currentPassword: string, newPassword: string): Promise<void> {
|
||||
await post<void>(this.httpClient, '/auth/change-password', {
|
||||
current_password: currentPassword,
|
||||
new_password: newPassword,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies an email address using a verification token
|
||||
*
|
||||
* @param token - Email verification token
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* await client.auth.verifyEmail('verification-token');
|
||||
* ```
|
||||
*/
|
||||
async verifyEmail(token: string): Promise<void> {
|
||||
await post<void>(this.httpClient, '/auth/verify-email', { token });
|
||||
}
|
||||
|
||||
/**
|
||||
* Resends the email verification
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* await client.auth.resendVerificationEmail();
|
||||
* ```
|
||||
*/
|
||||
async resendVerificationEmail(): Promise<void> {
|
||||
await post<void>(this.httpClient, '/auth/verify-email/resend');
|
||||
}
|
||||
}
|
||||
353
sdk/typescript/src/blockchain.ts
Normal file
353
sdk/typescript/src/blockchain.ts
Normal file
@@ -0,0 +1,353 @@
|
||||
/**
|
||||
* Blockchain client for BlackRoad SDK
|
||||
*/
|
||||
|
||||
import type { AxiosInstance } from 'axios';
|
||||
import type {
|
||||
Transaction,
|
||||
SendTransactionParams,
|
||||
Balance,
|
||||
TransactionListParams,
|
||||
TransactionListResponse,
|
||||
SmartContract,
|
||||
DeployContractParams,
|
||||
ContractCallParams,
|
||||
Block,
|
||||
NetworkStats,
|
||||
GasEstimate,
|
||||
} from './types';
|
||||
import { get, post } from './utils/http';
|
||||
|
||||
/**
|
||||
* Handles blockchain operations
|
||||
*/
|
||||
export class BlockchainClient {
|
||||
private httpClient: AxiosInstance;
|
||||
|
||||
constructor(httpClient: AxiosInstance) {
|
||||
this.httpClient = httpClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the balance for an address
|
||||
*
|
||||
* @param address - Wallet address
|
||||
* @param asset - Optional asset identifier (defaults to native token)
|
||||
* @returns Balance information
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const balance = await client.blockchain.getBalance('0x...');
|
||||
* console.log(`Available: ${balance.available} ${balance.symbol}`);
|
||||
* ```
|
||||
*/
|
||||
async getBalance(address: string, asset?: string): Promise<Balance> {
|
||||
return get<Balance>(this.httpClient, `/blockchain/balances/${address}`, {
|
||||
params: { asset },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all balances for an address
|
||||
*
|
||||
* @param address - Wallet address
|
||||
* @returns Array of balances for all assets
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const balances = await client.blockchain.getBalances('0x...');
|
||||
* balances.forEach(balance => {
|
||||
* console.log(`${balance.symbol}: ${balance.available}`);
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
async getBalances(address: string): Promise<Balance[]> {
|
||||
return get<Balance[]>(this.httpClient, `/blockchain/balances/${address}/all`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a transaction
|
||||
*
|
||||
* @param params - Transaction parameters
|
||||
* @returns Transaction details
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const tx = await client.blockchain.sendTransaction({
|
||||
* to: '0x...',
|
||||
* amount: 100,
|
||||
* asset: 'BRD',
|
||||
* memo: 'Payment for services',
|
||||
* });
|
||||
*
|
||||
* console.log('Transaction hash:', tx.hash);
|
||||
* ```
|
||||
*/
|
||||
async sendTransaction(params: SendTransactionParams): Promise<Transaction> {
|
||||
return post<Transaction>(this.httpClient, '/blockchain/transactions', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a transaction by hash
|
||||
*
|
||||
* @param hash - Transaction hash
|
||||
* @returns Transaction details
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const tx = await client.blockchain.getTransaction('0x...');
|
||||
* console.log('Status:', tx.status);
|
||||
* console.log('Confirmations:', tx.confirmations);
|
||||
* ```
|
||||
*/
|
||||
async getTransaction(hash: string): Promise<Transaction> {
|
||||
return get<Transaction>(this.httpClient, `/blockchain/transactions/${hash}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the status of a transaction
|
||||
*
|
||||
* @param hash - Transaction hash
|
||||
* @returns Transaction status
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const status = await client.blockchain.getTransactionStatus('0x...');
|
||||
* console.log('Status:', status);
|
||||
* ```
|
||||
*/
|
||||
async getTransactionStatus(hash: string): Promise<string> {
|
||||
const tx = await this.getTransaction(hash);
|
||||
return tx.status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists transactions with optional filtering
|
||||
*
|
||||
* @param params - List parameters
|
||||
* @returns Paginated list of transactions
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const response = await client.blockchain.listTransactions({
|
||||
* address: '0x...',
|
||||
* status: 'confirmed',
|
||||
* limit: 50,
|
||||
* });
|
||||
*
|
||||
* response.transactions.forEach(tx => {
|
||||
* console.log(`${tx.hash}: ${tx.amount} ${tx.asset}`);
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
async listTransactions(params?: TransactionListParams): Promise<TransactionListResponse> {
|
||||
return get<TransactionListResponse>(this.httpClient, '/blockchain/transactions', {
|
||||
params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for a transaction to be confirmed
|
||||
*
|
||||
* @param hash - Transaction hash
|
||||
* @param confirmations - Required confirmations (default: 1)
|
||||
* @param timeout - Timeout in milliseconds (default: 5 minutes)
|
||||
* @returns Confirmed transaction
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const tx = await client.blockchain.sendTransaction({ ... });
|
||||
* const confirmed = await client.blockchain.waitForTransaction(tx.hash, 3);
|
||||
* console.log('Transaction confirmed with', confirmed.confirmations, 'confirmations');
|
||||
* ```
|
||||
*/
|
||||
async waitForTransaction(
|
||||
hash: string,
|
||||
confirmations: number = 1,
|
||||
timeout: number = 300000
|
||||
): Promise<Transaction> {
|
||||
const startTime = Date.now();
|
||||
const pollInterval = 2000; // 2 seconds
|
||||
|
||||
while (true) {
|
||||
const tx = await this.getTransaction(hash);
|
||||
|
||||
if (tx.status === 'failed' || tx.status === 'cancelled') {
|
||||
throw new Error(`Transaction ${tx.status}: ${hash}`);
|
||||
}
|
||||
|
||||
if (tx.confirmations >= confirmations) {
|
||||
return tx;
|
||||
}
|
||||
|
||||
if (Date.now() - startTime > timeout) {
|
||||
throw new Error(`Transaction timeout after ${timeout}ms`);
|
||||
}
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, pollInterval));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deploys a smart contract
|
||||
*
|
||||
* @param params - Deployment parameters
|
||||
* @returns Deployed contract details
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const contract = await client.blockchain.deployContract({
|
||||
* name: 'MyContract',
|
||||
* code: contractBytecode,
|
||||
* constructor_args: ['arg1', 'arg2'],
|
||||
* });
|
||||
*
|
||||
* console.log('Contract deployed at:', contract.address);
|
||||
* ```
|
||||
*/
|
||||
async deployContract(params: DeployContractParams): Promise<SmartContract> {
|
||||
return post<SmartContract>(this.httpClient, '/blockchain/contracts', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a smart contract by address
|
||||
*
|
||||
* @param address - Contract address
|
||||
* @returns Contract details
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const contract = await client.blockchain.getContract('0x...');
|
||||
* console.log('Contract:', contract.name);
|
||||
* ```
|
||||
*/
|
||||
async getContract(address: string): Promise<SmartContract> {
|
||||
return get<SmartContract>(this.httpClient, `/blockchain/contracts/${address}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls a smart contract method (read-only)
|
||||
*
|
||||
* @param params - Call parameters
|
||||
* @returns Method result
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const result = await client.blockchain.callContract({
|
||||
* contract: '0x...',
|
||||
* method: 'balanceOf',
|
||||
* args: ['0x...'],
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
async callContract(params: ContractCallParams): Promise<unknown> {
|
||||
return post<unknown>(this.httpClient, '/blockchain/contracts/call', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a smart contract method (write operation)
|
||||
*
|
||||
* @param params - Execution parameters
|
||||
* @returns Transaction details
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const tx = await client.blockchain.executeContract({
|
||||
* contract: '0x...',
|
||||
* method: 'transfer',
|
||||
* args: ['0x...', 100],
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
async executeContract(params: ContractCallParams): Promise<Transaction> {
|
||||
return post<Transaction>(this.httpClient, '/blockchain/contracts/execute', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a block by number or hash
|
||||
*
|
||||
* @param blockId - Block number or hash
|
||||
* @returns Block details
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const block = await client.blockchain.getBlock(12345);
|
||||
* console.log('Block hash:', block.hash);
|
||||
* console.log('Transactions:', block.transaction_count);
|
||||
* ```
|
||||
*/
|
||||
async getBlock(blockId: number | string): Promise<Block> {
|
||||
return get<Block>(this.httpClient, `/blockchain/blocks/${blockId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the latest block
|
||||
*
|
||||
* @returns Latest block details
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const block = await client.blockchain.getLatestBlock();
|
||||
* console.log('Latest block number:', block.number);
|
||||
* ```
|
||||
*/
|
||||
async getLatestBlock(): Promise<Block> {
|
||||
return get<Block>(this.httpClient, '/blockchain/blocks/latest');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets network statistics
|
||||
*
|
||||
* @returns Network stats
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const stats = await client.blockchain.getNetworkStats();
|
||||
* console.log('Block height:', stats.block_height);
|
||||
* console.log('TPS:', stats.tps);
|
||||
* ```
|
||||
*/
|
||||
async getNetworkStats(): Promise<NetworkStats> {
|
||||
return get<NetworkStats>(this.httpClient, '/blockchain/stats');
|
||||
}
|
||||
|
||||
/**
|
||||
* Estimates gas for a transaction
|
||||
*
|
||||
* @param params - Transaction parameters
|
||||
* @returns Gas estimate
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const estimate = await client.blockchain.estimateGas({
|
||||
* to: '0x...',
|
||||
* amount: 100,
|
||||
* });
|
||||
*
|
||||
* console.log('Gas limit:', estimate.gas_limit);
|
||||
* console.log('Total cost:', estimate.total_cost);
|
||||
* ```
|
||||
*/
|
||||
async estimateGas(params: SendTransactionParams): Promise<GasEstimate> {
|
||||
return post<GasEstimate>(this.httpClient, '/blockchain/gas/estimate', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current gas price
|
||||
*
|
||||
* @returns Gas price in Wei
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const gasPrice = await client.blockchain.getGasPrice();
|
||||
* console.log('Gas price:', gasPrice);
|
||||
* ```
|
||||
*/
|
||||
async getGasPrice(): Promise<string> {
|
||||
const response = await get<{ gas_price: string }>(
|
||||
this.httpClient,
|
||||
'/blockchain/gas/price'
|
||||
);
|
||||
return response.gas_price;
|
||||
}
|
||||
}
|
||||
253
sdk/typescript/src/client.ts
Normal file
253
sdk/typescript/src/client.ts
Normal file
@@ -0,0 +1,253 @@
|
||||
/**
|
||||
* Main BlackRoad SDK client
|
||||
*/
|
||||
|
||||
import type { AxiosInstance } from 'axios';
|
||||
import type { BlackRoadClientConfig } from './types';
|
||||
import { createHttpClient } from './utils/http';
|
||||
import { AuthClient } from './auth';
|
||||
import { AgentsClient } from './agents';
|
||||
import { BlockchainClient } from './blockchain';
|
||||
|
||||
/**
|
||||
* BlackRoad SDK client
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { BlackRoadClient } from '@blackroad/sdk';
|
||||
*
|
||||
* const client = new BlackRoadClient({
|
||||
* apiKey: 'your-api-key',
|
||||
* });
|
||||
*
|
||||
* // Use the client
|
||||
* const agents = await client.agents.list();
|
||||
* const balance = await client.blockchain.getBalance('0x...');
|
||||
* ```
|
||||
*/
|
||||
export class BlackRoadClient {
|
||||
/** HTTP client instance */
|
||||
private httpClient: AxiosInstance;
|
||||
|
||||
/** Authentication client */
|
||||
public readonly auth: AuthClient;
|
||||
|
||||
/** Agents client */
|
||||
public readonly agents: AgentsClient;
|
||||
|
||||
/** Blockchain client */
|
||||
public readonly blockchain: BlockchainClient;
|
||||
|
||||
/** Client configuration */
|
||||
private config: BlackRoadClientConfig;
|
||||
|
||||
/**
|
||||
* Creates a new BlackRoad client
|
||||
*
|
||||
* @param config - Client configuration
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* // With API key
|
||||
* const client = new BlackRoadClient({
|
||||
* apiKey: 'your-api-key',
|
||||
* });
|
||||
*
|
||||
* // With JWT token
|
||||
* const client = new BlackRoadClient({
|
||||
* token: 'your-jwt-token',
|
||||
* });
|
||||
*
|
||||
* // With custom configuration
|
||||
* const client = new BlackRoadClient({
|
||||
* apiKey: 'your-api-key',
|
||||
* baseURL: 'https://api.blackroad.io',
|
||||
* timeout: 60000,
|
||||
* maxRetries: 5,
|
||||
* debug: true,
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
constructor(config: BlackRoadClientConfig = {}) {
|
||||
this.config = {
|
||||
baseURL: 'https://api.blackroad.io',
|
||||
timeout: 30000,
|
||||
maxRetries: 3,
|
||||
debug: false,
|
||||
network: 'mainnet',
|
||||
...config,
|
||||
};
|
||||
|
||||
// Create HTTP client
|
||||
this.httpClient = createHttpClient(this.config);
|
||||
|
||||
// Initialize sub-clients
|
||||
this.auth = new AuthClient(this.httpClient);
|
||||
this.agents = new AgentsClient(this.httpClient);
|
||||
this.blockchain = new BlockchainClient(this.httpClient);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current configuration
|
||||
*
|
||||
* @returns Client configuration (sensitive data like API keys are excluded)
|
||||
*/
|
||||
getConfig(): Omit<BlackRoadClientConfig, 'apiKey' | 'token'> {
|
||||
const { apiKey, token, ...safeConfig } = this.config;
|
||||
return safeConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the authentication token
|
||||
*
|
||||
* @param token - New JWT token
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* client.setAuthToken('new-jwt-token');
|
||||
* ```
|
||||
*/
|
||||
setAuthToken(token: string): void {
|
||||
this.config.token = token;
|
||||
this.httpClient.defaults.headers.common['Authorization'] = `Bearer ${token}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the API key
|
||||
*
|
||||
* @param apiKey - New API key
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* client.setApiKey('new-api-key');
|
||||
* ```
|
||||
*/
|
||||
setApiKey(apiKey: string): void {
|
||||
this.config.apiKey = apiKey;
|
||||
this.httpClient.defaults.headers.common['X-API-Key'] = apiKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears authentication credentials
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* client.clearAuth();
|
||||
* ```
|
||||
*/
|
||||
clearAuth(): void {
|
||||
delete this.config.apiKey;
|
||||
delete this.config.token;
|
||||
delete this.httpClient.defaults.headers.common['Authorization'];
|
||||
delete this.httpClient.defaults.headers.common['X-API-Key'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the base URL for the API
|
||||
*
|
||||
* @returns Base URL
|
||||
*/
|
||||
getBaseURL(): string {
|
||||
return this.config.baseURL || 'https://api.blackroad.io';
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the base URL
|
||||
*
|
||||
* @param baseURL - New base URL
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* client.setBaseURL('https://testnet.blackroad.io');
|
||||
* ```
|
||||
*/
|
||||
setBaseURL(baseURL: string): void {
|
||||
this.config.baseURL = baseURL;
|
||||
this.httpClient.defaults.baseURL = baseURL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the client is authenticated
|
||||
*
|
||||
* @returns True if the client has authentication credentials
|
||||
*/
|
||||
isAuthenticated(): boolean {
|
||||
return !!(this.config.apiKey || this.config.token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current network
|
||||
*
|
||||
* @returns Network name
|
||||
*/
|
||||
getNetwork(): string {
|
||||
return this.config.network || 'mainnet';
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches to a different network
|
||||
*
|
||||
* @param network - Network to switch to
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* client.setNetwork('testnet');
|
||||
* ```
|
||||
*/
|
||||
setNetwork(network: 'mainnet' | 'testnet' | 'devnet'): void {
|
||||
this.config.network = network;
|
||||
this.httpClient.defaults.headers.common['X-Network'] = network;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables debug logging
|
||||
*
|
||||
* @param enabled - Whether to enable debug logging
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* client.setDebug(true);
|
||||
* ```
|
||||
*/
|
||||
setDebug(enabled: boolean): void {
|
||||
this.config.debug = enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the connection to the API
|
||||
*
|
||||
* @returns True if the connection is successful
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const isOnline = await client.ping();
|
||||
* if (isOnline) {
|
||||
* console.log('Connected to BlackRoad API');
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
async ping(): Promise<boolean> {
|
||||
try {
|
||||
await this.httpClient.get('/health');
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the API version
|
||||
*
|
||||
* @returns API version string
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const version = await client.getVersion();
|
||||
* console.log('API version:', version);
|
||||
* ```
|
||||
*/
|
||||
async getVersion(): Promise<string> {
|
||||
const response = await this.httpClient.get<{ version: string }>('/version');
|
||||
return response.data.version;
|
||||
}
|
||||
}
|
||||
163
sdk/typescript/src/errors.ts
Normal file
163
sdk/typescript/src/errors.ts
Normal file
@@ -0,0 +1,163 @@
|
||||
/**
|
||||
* Custom error classes for BlackRoad SDK
|
||||
*/
|
||||
|
||||
/**
|
||||
* Base error class for all BlackRoad SDK errors
|
||||
*/
|
||||
export class BlackRoadError extends Error {
|
||||
/** HTTP status code if applicable */
|
||||
public statusCode?: number;
|
||||
|
||||
/** Additional error details */
|
||||
public details?: unknown;
|
||||
|
||||
constructor(message: string, statusCode?: number, details?: unknown) {
|
||||
super(message);
|
||||
this.name = 'BlackRoadError';
|
||||
this.statusCode = statusCode;
|
||||
this.details = details;
|
||||
|
||||
// Maintains proper stack trace for where our error was thrown (only available on V8)
|
||||
if (Error.captureStackTrace) {
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thrown when authentication fails
|
||||
*/
|
||||
export class AuthenticationError extends BlackRoadError {
|
||||
constructor(message: string = 'Authentication failed', details?: unknown) {
|
||||
super(message, 401, details);
|
||||
this.name = 'AuthenticationError';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thrown when authorization fails (authenticated but not permitted)
|
||||
*/
|
||||
export class AuthorizationError extends BlackRoadError {
|
||||
constructor(message: string = 'Permission denied', details?: unknown) {
|
||||
super(message, 403, details);
|
||||
this.name = 'AuthorizationError';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thrown when input validation fails
|
||||
*/
|
||||
export class ValidationError extends BlackRoadError {
|
||||
/** Validation error details */
|
||||
public errors: Record<string, string[]>;
|
||||
|
||||
constructor(message: string, errors: Record<string, string[]> = {}) {
|
||||
super(message, 400, errors);
|
||||
this.name = 'ValidationError';
|
||||
this.errors = errors;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thrown when a requested resource is not found
|
||||
*/
|
||||
export class NotFoundError extends BlackRoadError {
|
||||
constructor(message: string = 'Resource not found', details?: unknown) {
|
||||
super(message, 404, details);
|
||||
this.name = 'NotFoundError';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thrown when there's a conflict with the current state
|
||||
*/
|
||||
export class ConflictError extends BlackRoadError {
|
||||
constructor(message: string = 'Resource conflict', details?: unknown) {
|
||||
super(message, 409, details);
|
||||
this.name = 'ConflictError';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thrown when rate limit is exceeded
|
||||
*/
|
||||
export class RateLimitError extends BlackRoadError {
|
||||
/** When the rate limit resets */
|
||||
public retryAfter?: number;
|
||||
|
||||
constructor(message: string = 'Rate limit exceeded', retryAfter?: number) {
|
||||
super(message, 429, { retryAfter });
|
||||
this.name = 'RateLimitError';
|
||||
this.retryAfter = retryAfter;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thrown when there's a network or connection error
|
||||
*/
|
||||
export class NetworkError extends BlackRoadError {
|
||||
constructor(message: string, details?: unknown) {
|
||||
super(message, undefined, details);
|
||||
this.name = 'NetworkError';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thrown when the server returns an error
|
||||
*/
|
||||
export class ServerError extends BlackRoadError {
|
||||
constructor(message: string = 'Internal server error', statusCode: number = 500, details?: unknown) {
|
||||
super(message, statusCode, details);
|
||||
this.name = 'ServerError';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Thrown when request times out
|
||||
*/
|
||||
export class TimeoutError extends BlackRoadError {
|
||||
constructor(message: string = 'Request timeout', details?: unknown) {
|
||||
super(message, 408, details);
|
||||
this.name = 'TimeoutError';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps HTTP status codes to appropriate error classes
|
||||
*/
|
||||
export function createErrorFromResponse(
|
||||
statusCode: number,
|
||||
message: string,
|
||||
data?: unknown
|
||||
): BlackRoadError {
|
||||
switch (statusCode) {
|
||||
case 400:
|
||||
if (data && typeof data === 'object' && 'errors' in data) {
|
||||
return new ValidationError(message, data.errors as Record<string, string[]>);
|
||||
}
|
||||
return new ValidationError(message);
|
||||
case 401:
|
||||
return new AuthenticationError(message, data);
|
||||
case 403:
|
||||
return new AuthorizationError(message, data);
|
||||
case 404:
|
||||
return new NotFoundError(message, data);
|
||||
case 408:
|
||||
return new TimeoutError(message, data);
|
||||
case 409:
|
||||
return new ConflictError(message, data);
|
||||
case 429:
|
||||
const retryAfter = data && typeof data === 'object' && 'retry_after' in data
|
||||
? (data.retry_after as number)
|
||||
: undefined;
|
||||
return new RateLimitError(message, retryAfter);
|
||||
case 500:
|
||||
case 502:
|
||||
case 503:
|
||||
case 504:
|
||||
return new ServerError(message, statusCode, data);
|
||||
default:
|
||||
return new BlackRoadError(message, statusCode, data);
|
||||
}
|
||||
}
|
||||
44
sdk/typescript/src/index.ts
Normal file
44
sdk/typescript/src/index.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* BlackRoad Operating System SDK
|
||||
*
|
||||
* Official TypeScript/JavaScript SDK for the BlackRoad Operating System.
|
||||
*
|
||||
* @packageDocumentation
|
||||
*/
|
||||
|
||||
// Export main client
|
||||
export { BlackRoadClient } from './client';
|
||||
|
||||
// Export sub-clients
|
||||
export { AuthClient } from './auth';
|
||||
export { AgentsClient } from './agents';
|
||||
export { BlockchainClient } from './blockchain';
|
||||
|
||||
// Export all types
|
||||
export * from './types';
|
||||
|
||||
// Export errors
|
||||
export * from './errors';
|
||||
|
||||
// Export utilities
|
||||
export * from './utils';
|
||||
|
||||
// Package version
|
||||
export const VERSION = '0.1.0';
|
||||
|
||||
/**
|
||||
* Creates a new BlackRoad client with the given configuration
|
||||
*
|
||||
* @param config - Client configuration
|
||||
* @returns Configured BlackRoad client
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* import { createClient } from '@blackroad/sdk';
|
||||
*
|
||||
* const client = createClient({
|
||||
* apiKey: 'your-api-key',
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export { BlackRoadClient as createClient };
|
||||
268
sdk/typescript/src/types/agent.ts
Normal file
268
sdk/typescript/src/types/agent.ts
Normal file
@@ -0,0 +1,268 @@
|
||||
/**
|
||||
* Agent-related type definitions
|
||||
*/
|
||||
|
||||
/**
|
||||
* AI Agent type
|
||||
*/
|
||||
export type AgentType = 'autonomous' | 'interactive' | 'scheduled' | 'reactive';
|
||||
|
||||
/**
|
||||
* Agent status
|
||||
*/
|
||||
export type AgentStatus = 'active' | 'paused' | 'stopped' | 'error';
|
||||
|
||||
/**
|
||||
* Agent capabilities
|
||||
*/
|
||||
export type AgentCapability =
|
||||
| 'reasoning'
|
||||
| 'execution'
|
||||
| 'data_analysis'
|
||||
| 'visualization'
|
||||
| 'natural_language'
|
||||
| 'blockchain_interaction'
|
||||
| 'external_api'
|
||||
| 'file_processing'
|
||||
| 'image_generation'
|
||||
| 'code_generation';
|
||||
|
||||
/**
|
||||
* Represents an AI agent in the system
|
||||
*/
|
||||
export interface Agent {
|
||||
/** Unique agent identifier */
|
||||
id: string;
|
||||
|
||||
/** Agent name */
|
||||
name: string;
|
||||
|
||||
/** Agent description */
|
||||
description?: string;
|
||||
|
||||
/** Agent type */
|
||||
type: AgentType;
|
||||
|
||||
/** Current status */
|
||||
status: AgentStatus;
|
||||
|
||||
/** Agent capabilities */
|
||||
capabilities: AgentCapability[];
|
||||
|
||||
/** Agent configuration */
|
||||
config: AgentConfig;
|
||||
|
||||
/** Owner user ID */
|
||||
owner_id: string;
|
||||
|
||||
/** Creation timestamp */
|
||||
created_at: string;
|
||||
|
||||
/** Last update timestamp */
|
||||
updated_at: string;
|
||||
|
||||
/** Last execution timestamp */
|
||||
last_executed_at?: string;
|
||||
|
||||
/** Execution count */
|
||||
execution_count: number;
|
||||
|
||||
/** Agent metadata */
|
||||
metadata?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Agent configuration
|
||||
*/
|
||||
export interface AgentConfig {
|
||||
/** Model to use (e.g., "gpt-4", "claude-3") */
|
||||
model?: string;
|
||||
|
||||
/** Temperature for generation (0-1) */
|
||||
temperature?: number;
|
||||
|
||||
/** Maximum tokens to generate */
|
||||
max_tokens?: number;
|
||||
|
||||
/** System prompt */
|
||||
system_prompt?: string;
|
||||
|
||||
/** Execution timeout in seconds */
|
||||
timeout?: number;
|
||||
|
||||
/** Maximum retries on failure */
|
||||
max_retries?: number;
|
||||
|
||||
/** Additional configuration */
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parameters for creating an agent
|
||||
*/
|
||||
export interface AgentCreateParams {
|
||||
/** Agent name */
|
||||
name: string;
|
||||
|
||||
/** Agent description */
|
||||
description?: string;
|
||||
|
||||
/** Agent type */
|
||||
type: AgentType;
|
||||
|
||||
/** Agent capabilities */
|
||||
capabilities: AgentCapability[];
|
||||
|
||||
/** Agent configuration */
|
||||
config?: Partial<AgentConfig>;
|
||||
|
||||
/** Agent metadata */
|
||||
metadata?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parameters for updating an agent
|
||||
*/
|
||||
export interface AgentUpdateParams {
|
||||
/** New name */
|
||||
name?: string;
|
||||
|
||||
/** New description */
|
||||
description?: string;
|
||||
|
||||
/** New status */
|
||||
status?: AgentStatus;
|
||||
|
||||
/** New capabilities */
|
||||
capabilities?: AgentCapability[];
|
||||
|
||||
/** Updated configuration */
|
||||
config?: Partial<AgentConfig>;
|
||||
|
||||
/** Updated metadata */
|
||||
metadata?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parameters for listing agents
|
||||
*/
|
||||
export interface AgentListParams {
|
||||
/** Filter by agent type */
|
||||
type?: AgentType;
|
||||
|
||||
/** Filter by status */
|
||||
status?: AgentStatus;
|
||||
|
||||
/** Number of results to return */
|
||||
limit?: number;
|
||||
|
||||
/** Offset for pagination */
|
||||
offset?: number;
|
||||
|
||||
/** Sort field */
|
||||
sort_by?: 'created_at' | 'updated_at' | 'name' | 'execution_count';
|
||||
|
||||
/** Sort order */
|
||||
sort_order?: 'asc' | 'desc';
|
||||
}
|
||||
|
||||
/**
|
||||
* Agent execution parameters
|
||||
*/
|
||||
export interface AgentExecuteParams {
|
||||
/** Task to execute */
|
||||
task: string;
|
||||
|
||||
/** Task parameters */
|
||||
parameters?: Record<string, unknown>;
|
||||
|
||||
/** Context for execution */
|
||||
context?: Record<string, unknown>;
|
||||
|
||||
/** Execution mode */
|
||||
mode?: 'sync' | 'async';
|
||||
}
|
||||
|
||||
/**
|
||||
* Agent execution result
|
||||
*/
|
||||
export interface AgentExecutionResult {
|
||||
/** Execution ID */
|
||||
id: string;
|
||||
|
||||
/** Agent ID */
|
||||
agent_id: string;
|
||||
|
||||
/** Execution status */
|
||||
status: 'pending' | 'running' | 'completed' | 'failed';
|
||||
|
||||
/** Result data */
|
||||
result?: unknown;
|
||||
|
||||
/** Error message if failed */
|
||||
error?: string;
|
||||
|
||||
/** Execution start time */
|
||||
started_at: string;
|
||||
|
||||
/** Execution completion time */
|
||||
completed_at?: string;
|
||||
|
||||
/** Execution duration in milliseconds */
|
||||
duration_ms?: number;
|
||||
|
||||
/** Tokens used */
|
||||
tokens_used?: number;
|
||||
|
||||
/** Execution logs */
|
||||
logs?: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Agent list response
|
||||
*/
|
||||
export interface AgentListResponse {
|
||||
/** List of agents */
|
||||
agents: Agent[];
|
||||
|
||||
/** Total count of agents */
|
||||
total: number;
|
||||
|
||||
/** Number of results returned */
|
||||
count: number;
|
||||
|
||||
/** Offset used */
|
||||
offset: number;
|
||||
|
||||
/** Whether there are more results */
|
||||
has_more: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Agent execution history entry
|
||||
*/
|
||||
export interface AgentExecutionHistory {
|
||||
/** Execution ID */
|
||||
id: string;
|
||||
|
||||
/** Task name */
|
||||
task: string;
|
||||
|
||||
/** Execution status */
|
||||
status: 'completed' | 'failed';
|
||||
|
||||
/** Start timestamp */
|
||||
started_at: string;
|
||||
|
||||
/** Completion timestamp */
|
||||
completed_at: string;
|
||||
|
||||
/** Duration in milliseconds */
|
||||
duration_ms: number;
|
||||
|
||||
/** Tokens used */
|
||||
tokens_used?: number;
|
||||
|
||||
/** Error message if failed */
|
||||
error?: string;
|
||||
}
|
||||
336
sdk/typescript/src/types/blockchain.ts
Normal file
336
sdk/typescript/src/types/blockchain.ts
Normal file
@@ -0,0 +1,336 @@
|
||||
/**
|
||||
* Blockchain-related type definitions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Supported blockchain networks
|
||||
*/
|
||||
export type Network = 'mainnet' | 'testnet' | 'devnet';
|
||||
|
||||
/**
|
||||
* Transaction status
|
||||
*/
|
||||
export type TransactionStatus =
|
||||
| 'pending'
|
||||
| 'confirming'
|
||||
| 'confirmed'
|
||||
| 'failed'
|
||||
| 'cancelled';
|
||||
|
||||
/**
|
||||
* Asset type
|
||||
*/
|
||||
export type AssetType = 'native' | 'token' | 'nft';
|
||||
|
||||
/**
|
||||
* Represents a blockchain transaction
|
||||
*/
|
||||
export interface Transaction {
|
||||
/** Transaction hash */
|
||||
hash: string;
|
||||
|
||||
/** Sender address */
|
||||
from: string;
|
||||
|
||||
/** Recipient address */
|
||||
to: string;
|
||||
|
||||
/** Amount transferred */
|
||||
amount: string;
|
||||
|
||||
/** Asset identifier */
|
||||
asset: string;
|
||||
|
||||
/** Asset type */
|
||||
asset_type: AssetType;
|
||||
|
||||
/** Transaction fee */
|
||||
fee: string;
|
||||
|
||||
/** Transaction status */
|
||||
status: TransactionStatus;
|
||||
|
||||
/** Block number */
|
||||
block_number?: number;
|
||||
|
||||
/** Block hash */
|
||||
block_hash?: string;
|
||||
|
||||
/** Number of confirmations */
|
||||
confirmations: number;
|
||||
|
||||
/** Transaction timestamp */
|
||||
timestamp: string;
|
||||
|
||||
/** Transaction memo/note */
|
||||
memo?: string;
|
||||
|
||||
/** Transaction metadata */
|
||||
metadata?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parameters for sending a transaction
|
||||
*/
|
||||
export interface SendTransactionParams {
|
||||
/** Recipient address */
|
||||
to: string;
|
||||
|
||||
/** Amount to send */
|
||||
amount: number | string;
|
||||
|
||||
/** Asset to send (default: native token) */
|
||||
asset?: string;
|
||||
|
||||
/** Transaction memo */
|
||||
memo?: string;
|
||||
|
||||
/** Gas limit */
|
||||
gas_limit?: number;
|
||||
|
||||
/** Gas price */
|
||||
gas_price?: string;
|
||||
|
||||
/** Additional metadata */
|
||||
metadata?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wallet balance information
|
||||
*/
|
||||
export interface Balance {
|
||||
/** Wallet address */
|
||||
address: string;
|
||||
|
||||
/** Asset identifier */
|
||||
asset: string;
|
||||
|
||||
/** Asset symbol */
|
||||
symbol: string;
|
||||
|
||||
/** Available balance */
|
||||
available: string;
|
||||
|
||||
/** Locked/staked balance */
|
||||
locked: string;
|
||||
|
||||
/** Total balance */
|
||||
total: string;
|
||||
|
||||
/** USD value (if available) */
|
||||
usd_value?: string;
|
||||
|
||||
/** Last updated timestamp */
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parameters for listing transactions
|
||||
*/
|
||||
export interface TransactionListParams {
|
||||
/** Filter by address */
|
||||
address?: string;
|
||||
|
||||
/** Filter by status */
|
||||
status?: TransactionStatus;
|
||||
|
||||
/** Filter by asset */
|
||||
asset?: string;
|
||||
|
||||
/** Start date */
|
||||
from_date?: string;
|
||||
|
||||
/** End date */
|
||||
to_date?: string;
|
||||
|
||||
/** Number of results */
|
||||
limit?: number;
|
||||
|
||||
/** Offset for pagination */
|
||||
offset?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transaction list response
|
||||
*/
|
||||
export interface TransactionListResponse {
|
||||
/** List of transactions */
|
||||
transactions: Transaction[];
|
||||
|
||||
/** Total count */
|
||||
total: number;
|
||||
|
||||
/** Number returned */
|
||||
count: number;
|
||||
|
||||
/** Offset */
|
||||
offset: number;
|
||||
|
||||
/** Whether there are more results */
|
||||
has_more: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Smart contract
|
||||
*/
|
||||
export interface SmartContract {
|
||||
/** Contract address */
|
||||
address: string;
|
||||
|
||||
/** Contract name */
|
||||
name: string;
|
||||
|
||||
/** Contract description */
|
||||
description?: string;
|
||||
|
||||
/** Deployment transaction hash */
|
||||
deployment_tx: string;
|
||||
|
||||
/** Deployer address */
|
||||
deployer: string;
|
||||
|
||||
/** Contract ABI */
|
||||
abi?: unknown[];
|
||||
|
||||
/** Contract bytecode */
|
||||
bytecode?: string;
|
||||
|
||||
/** Deployment timestamp */
|
||||
deployed_at: string;
|
||||
|
||||
/** Verified status */
|
||||
verified: boolean;
|
||||
|
||||
/** Contract metadata */
|
||||
metadata?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parameters for deploying a smart contract
|
||||
*/
|
||||
export interface DeployContractParams {
|
||||
/** Contract name */
|
||||
name: string;
|
||||
|
||||
/** Contract code/bytecode */
|
||||
code: string;
|
||||
|
||||
/** Constructor arguments */
|
||||
constructor_args?: unknown[];
|
||||
|
||||
/** Gas limit */
|
||||
gas_limit?: number;
|
||||
|
||||
/** Initial value to send */
|
||||
value?: string;
|
||||
|
||||
/** Contract metadata */
|
||||
metadata?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parameters for calling a smart contract method
|
||||
*/
|
||||
export interface ContractCallParams {
|
||||
/** Contract address */
|
||||
contract: string;
|
||||
|
||||
/** Method name */
|
||||
method: string;
|
||||
|
||||
/** Method arguments */
|
||||
args?: unknown[];
|
||||
|
||||
/** Value to send with the call */
|
||||
value?: string;
|
||||
|
||||
/** Gas limit */
|
||||
gas_limit?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Block information
|
||||
*/
|
||||
export interface Block {
|
||||
/** Block number */
|
||||
number: number;
|
||||
|
||||
/** Block hash */
|
||||
hash: string;
|
||||
|
||||
/** Parent block hash */
|
||||
parent_hash: string;
|
||||
|
||||
/** Block timestamp */
|
||||
timestamp: string;
|
||||
|
||||
/** Miner/validator address */
|
||||
miner: string;
|
||||
|
||||
/** Number of transactions */
|
||||
transaction_count: number;
|
||||
|
||||
/** Block size in bytes */
|
||||
size: number;
|
||||
|
||||
/** Gas used */
|
||||
gas_used: string;
|
||||
|
||||
/** Gas limit */
|
||||
gas_limit: string;
|
||||
|
||||
/** Block difficulty */
|
||||
difficulty?: string;
|
||||
|
||||
/** Block metadata */
|
||||
metadata?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Network statistics
|
||||
*/
|
||||
export interface NetworkStats {
|
||||
/** Network name */
|
||||
network: Network;
|
||||
|
||||
/** Current block height */
|
||||
block_height: number;
|
||||
|
||||
/** Average block time in seconds */
|
||||
avg_block_time: number;
|
||||
|
||||
/** Total transactions */
|
||||
total_transactions: number;
|
||||
|
||||
/** Transactions per second */
|
||||
tps: number;
|
||||
|
||||
/** Total accounts */
|
||||
total_accounts: number;
|
||||
|
||||
/** Total contracts */
|
||||
total_contracts: number;
|
||||
|
||||
/** Network hash rate */
|
||||
hash_rate?: string;
|
||||
|
||||
/** Last updated */
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gas estimation result
|
||||
*/
|
||||
export interface GasEstimate {
|
||||
/** Estimated gas limit */
|
||||
gas_limit: number;
|
||||
|
||||
/** Suggested gas price */
|
||||
gas_price: string;
|
||||
|
||||
/** Total estimated cost */
|
||||
total_cost: string;
|
||||
|
||||
/** Total cost in USD (if available) */
|
||||
total_cost_usd?: string;
|
||||
}
|
||||
105
sdk/typescript/src/types/index.ts
Normal file
105
sdk/typescript/src/types/index.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* Type definitions for BlackRoad SDK
|
||||
*/
|
||||
|
||||
// Re-export all types
|
||||
export * from './agent';
|
||||
export * from './blockchain';
|
||||
export * from './user';
|
||||
|
||||
/**
|
||||
* SDK configuration options
|
||||
*/
|
||||
export interface BlackRoadClientConfig {
|
||||
/** API key for authentication */
|
||||
apiKey?: string;
|
||||
|
||||
/** JWT token for authentication */
|
||||
token?: string;
|
||||
|
||||
/** Base URL for the API (default: https://api.blackroad.io) */
|
||||
baseURL?: string;
|
||||
|
||||
/** Request timeout in milliseconds (default: 30000) */
|
||||
timeout?: number;
|
||||
|
||||
/** Number of retry attempts for failed requests (default: 3) */
|
||||
maxRetries?: number;
|
||||
|
||||
/** Custom headers to include in all requests */
|
||||
headers?: Record<string, string>;
|
||||
|
||||
/** Enable debug logging (default: false) */
|
||||
debug?: boolean;
|
||||
|
||||
/** Network to use (default: mainnet) */
|
||||
network?: 'mainnet' | 'testnet' | 'devnet';
|
||||
}
|
||||
|
||||
/**
|
||||
* Pagination parameters
|
||||
*/
|
||||
export interface PaginationParams {
|
||||
/** Number of results to return */
|
||||
limit?: number;
|
||||
|
||||
/** Offset for pagination */
|
||||
offset?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Paginated response
|
||||
*/
|
||||
export interface PaginatedResponse<T> {
|
||||
/** Results array */
|
||||
data: T[];
|
||||
|
||||
/** Total count of items */
|
||||
total: number;
|
||||
|
||||
/** Number of items returned */
|
||||
count: number;
|
||||
|
||||
/** Offset used */
|
||||
offset: number;
|
||||
|
||||
/** Whether there are more results */
|
||||
has_more: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* API response wrapper
|
||||
*/
|
||||
export interface APIResponse<T> {
|
||||
/** Response data */
|
||||
data: T;
|
||||
|
||||
/** Success status */
|
||||
success: boolean;
|
||||
|
||||
/** Error message if any */
|
||||
message?: string;
|
||||
|
||||
/** Response metadata */
|
||||
metadata?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
/**
|
||||
* API error response
|
||||
*/
|
||||
export interface APIErrorResponse {
|
||||
/** Success status (always false) */
|
||||
success: false;
|
||||
|
||||
/** Error message */
|
||||
message: string;
|
||||
|
||||
/** Error code */
|
||||
code?: string;
|
||||
|
||||
/** Validation errors */
|
||||
errors?: Record<string, string[]>;
|
||||
|
||||
/** Additional error details */
|
||||
details?: unknown;
|
||||
}
|
||||
116
sdk/typescript/src/types/user.ts
Normal file
116
sdk/typescript/src/types/user.ts
Normal file
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* User-related type definitions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents a user in the BlackRoad system
|
||||
*/
|
||||
export interface User {
|
||||
/** Unique user identifier */
|
||||
id: string;
|
||||
|
||||
/** User's email address */
|
||||
email: string;
|
||||
|
||||
/** User's display name */
|
||||
display_name?: string;
|
||||
|
||||
/** Avatar URL */
|
||||
avatar_url?: string;
|
||||
|
||||
/** User's wallet address */
|
||||
wallet_address?: string;
|
||||
|
||||
/** Account creation timestamp */
|
||||
created_at: string;
|
||||
|
||||
/** Last update timestamp */
|
||||
updated_at: string;
|
||||
|
||||
/** Whether the user's email is verified */
|
||||
email_verified: boolean;
|
||||
|
||||
/** User's role */
|
||||
role: UserRole;
|
||||
|
||||
/** User's metadata */
|
||||
metadata?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
/**
|
||||
* User roles in the system
|
||||
*/
|
||||
export type UserRole = 'user' | 'admin' | 'developer' | 'agent';
|
||||
|
||||
/**
|
||||
* Parameters for updating user profile
|
||||
*/
|
||||
export interface UpdateProfileParams {
|
||||
/** New display name */
|
||||
display_name?: string;
|
||||
|
||||
/** New avatar URL */
|
||||
avatar_url?: string;
|
||||
|
||||
/** Additional metadata */
|
||||
metadata?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
/**
|
||||
* User authentication credentials
|
||||
*/
|
||||
export interface UserCredentials {
|
||||
/** Email address */
|
||||
email: string;
|
||||
|
||||
/** Password */
|
||||
password: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* User registration parameters
|
||||
*/
|
||||
export interface RegisterParams extends UserCredentials {
|
||||
/** Display name */
|
||||
display_name?: string;
|
||||
|
||||
/** Optional invite code */
|
||||
invite_code?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Authentication response
|
||||
*/
|
||||
export interface AuthResponse {
|
||||
/** JWT access token */
|
||||
access_token: string;
|
||||
|
||||
/** Refresh token */
|
||||
refresh_token: string;
|
||||
|
||||
/** Token type (usually "Bearer") */
|
||||
token_type: string;
|
||||
|
||||
/** Token expiration time in seconds */
|
||||
expires_in: number;
|
||||
|
||||
/** Authenticated user */
|
||||
user: User;
|
||||
}
|
||||
|
||||
/**
|
||||
* Token refresh response
|
||||
*/
|
||||
export interface RefreshTokenResponse {
|
||||
/** New JWT access token */
|
||||
access_token: string;
|
||||
|
||||
/** New refresh token */
|
||||
refresh_token: string;
|
||||
|
||||
/** Token type */
|
||||
token_type: string;
|
||||
|
||||
/** Token expiration time in seconds */
|
||||
expires_in: number;
|
||||
}
|
||||
221
sdk/typescript/src/utils/http.ts
Normal file
221
sdk/typescript/src/utils/http.ts
Normal file
@@ -0,0 +1,221 @@
|
||||
/**
|
||||
* HTTP utilities for making API requests
|
||||
*/
|
||||
|
||||
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios';
|
||||
import axiosRetry from 'axios-retry';
|
||||
import {
|
||||
BlackRoadError,
|
||||
NetworkError,
|
||||
TimeoutError,
|
||||
createErrorFromResponse,
|
||||
} from '../errors';
|
||||
import type { APIResponse, APIErrorResponse, BlackRoadClientConfig } from '../types';
|
||||
|
||||
/**
|
||||
* Creates and configures an HTTP client
|
||||
*/
|
||||
export function createHttpClient(config: BlackRoadClientConfig): AxiosInstance {
|
||||
const {
|
||||
baseURL = 'https://api.blackroad.io',
|
||||
timeout = 30000,
|
||||
maxRetries = 3,
|
||||
apiKey,
|
||||
token,
|
||||
headers = {},
|
||||
debug = false,
|
||||
} = config;
|
||||
|
||||
// Create axios instance
|
||||
const client = axios.create({
|
||||
baseURL,
|
||||
timeout,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...headers,
|
||||
},
|
||||
});
|
||||
|
||||
// Add authentication headers
|
||||
if (apiKey) {
|
||||
client.defaults.headers.common['X-API-Key'] = apiKey;
|
||||
} else if (token) {
|
||||
client.defaults.headers.common['Authorization'] = `Bearer ${token}`;
|
||||
}
|
||||
|
||||
// Configure retry logic
|
||||
axiosRetry(client, {
|
||||
retries: maxRetries,
|
||||
retryDelay: axiosRetry.exponentialDelay,
|
||||
retryCondition: (error: AxiosError) => {
|
||||
// Retry on network errors or 5xx server errors
|
||||
return (
|
||||
axiosRetry.isNetworkOrIdempotentRequestError(error) ||
|
||||
(error.response?.status !== undefined && error.response.status >= 500)
|
||||
);
|
||||
},
|
||||
onRetry: (retryCount, error, requestConfig) => {
|
||||
if (debug) {
|
||||
console.log(
|
||||
`[BlackRoad SDK] Retry attempt ${retryCount} for ${requestConfig.url}`,
|
||||
error.message
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
// Request interceptor for logging
|
||||
if (debug) {
|
||||
client.interceptors.request.use(
|
||||
(config) => {
|
||||
console.log(`[BlackRoad SDK] ${config.method?.toUpperCase()} ${config.url}`, {
|
||||
headers: config.headers,
|
||||
params: config.params,
|
||||
data: config.data,
|
||||
});
|
||||
return config;
|
||||
},
|
||||
(error) => {
|
||||
console.error('[BlackRoad SDK] Request error:', error);
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Response interceptor for logging and error handling
|
||||
client.interceptors.response.use(
|
||||
(response) => {
|
||||
if (debug) {
|
||||
console.log(`[BlackRoad SDK] Response from ${response.config.url}:`, {
|
||||
status: response.status,
|
||||
data: response.data,
|
||||
});
|
||||
}
|
||||
return response;
|
||||
},
|
||||
(error: AxiosError) => {
|
||||
if (debug) {
|
||||
console.error('[BlackRoad SDK] Response error:', error);
|
||||
}
|
||||
throw handleAxiosError(error);
|
||||
}
|
||||
);
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles axios errors and converts them to BlackRoad errors
|
||||
*/
|
||||
function handleAxiosError(error: AxiosError): BlackRoadError {
|
||||
// Network error (no response)
|
||||
if (!error.response) {
|
||||
if (error.code === 'ECONNABORTED' || error.message.includes('timeout')) {
|
||||
return new TimeoutError('Request timeout');
|
||||
}
|
||||
return new NetworkError(
|
||||
error.message || 'Network error occurred',
|
||||
{ originalError: error }
|
||||
);
|
||||
}
|
||||
|
||||
// HTTP error response
|
||||
const { status, data } = error.response;
|
||||
const errorData = data as APIErrorResponse;
|
||||
|
||||
const message = errorData?.message || error.message || 'An error occurred';
|
||||
|
||||
return createErrorFromResponse(status, message, errorData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a GET request
|
||||
*/
|
||||
export async function get<T>(
|
||||
client: AxiosInstance,
|
||||
url: string,
|
||||
config?: AxiosRequestConfig
|
||||
): Promise<T> {
|
||||
const response: AxiosResponse<APIResponse<T>> = await client.get(url, config);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a POST request
|
||||
*/
|
||||
export async function post<T>(
|
||||
client: AxiosInstance,
|
||||
url: string,
|
||||
data?: unknown,
|
||||
config?: AxiosRequestConfig
|
||||
): Promise<T> {
|
||||
const response: AxiosResponse<APIResponse<T>> = await client.post(url, data, config);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a PUT request
|
||||
*/
|
||||
export async function put<T>(
|
||||
client: AxiosInstance,
|
||||
url: string,
|
||||
data?: unknown,
|
||||
config?: AxiosRequestConfig
|
||||
): Promise<T> {
|
||||
const response: AxiosResponse<APIResponse<T>> = await client.put(url, data, config);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a PATCH request
|
||||
*/
|
||||
export async function patch<T>(
|
||||
client: AxiosInstance,
|
||||
url: string,
|
||||
data?: unknown,
|
||||
config?: AxiosRequestConfig
|
||||
): Promise<T> {
|
||||
const response: AxiosResponse<APIResponse<T>> = await client.patch(url, data, config);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a DELETE request
|
||||
*/
|
||||
export async function del<T>(
|
||||
client: AxiosInstance,
|
||||
url: string,
|
||||
config?: AxiosRequestConfig
|
||||
): Promise<T> {
|
||||
const response: AxiosResponse<APIResponse<T>> = await client.delete(url, config);
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the authentication token on the client
|
||||
*/
|
||||
export function setAuthToken(client: AxiosInstance, token: string): void {
|
||||
client.defaults.headers.common['Authorization'] = `Bearer ${token}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the authentication token from the client
|
||||
*/
|
||||
export function clearAuthToken(client: AxiosInstance): void {
|
||||
delete client.defaults.headers.common['Authorization'];
|
||||
delete client.defaults.headers.common['X-API-Key'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a custom header on the client
|
||||
*/
|
||||
export function setHeader(client: AxiosInstance, name: string, value: string): void {
|
||||
client.defaults.headers.common[name] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a custom header from the client
|
||||
*/
|
||||
export function removeHeader(client: AxiosInstance, name: string): void {
|
||||
delete client.defaults.headers.common[name];
|
||||
}
|
||||
198
sdk/typescript/src/utils/index.ts
Normal file
198
sdk/typescript/src/utils/index.ts
Normal file
@@ -0,0 +1,198 @@
|
||||
/**
|
||||
* Utility functions
|
||||
*/
|
||||
|
||||
export * from './http';
|
||||
|
||||
/**
|
||||
* Validates an Ethereum-style address
|
||||
*/
|
||||
export function isValidAddress(address: string): boolean {
|
||||
return /^0x[a-fA-F0-9]{40}$/.test(address);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a transaction hash
|
||||
*/
|
||||
export function isValidTxHash(hash: string): boolean {
|
||||
return /^0x[a-fA-F0-9]{64}$/.test(hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a large number with proper units (K, M, B, T)
|
||||
*/
|
||||
export function formatNumber(num: number): string {
|
||||
if (num >= 1e12) return (num / 1e12).toFixed(2) + 'T';
|
||||
if (num >= 1e9) return (num / 1e9).toFixed(2) + 'B';
|
||||
if (num >= 1e6) return (num / 1e6).toFixed(2) + 'M';
|
||||
if (num >= 1e3) return (num / 1e3).toFixed(2) + 'K';
|
||||
return num.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sleeps for the specified duration
|
||||
*/
|
||||
export function sleep(ms: number): Promise<void> {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retries a function with exponential backoff
|
||||
*/
|
||||
export async function retry<T>(
|
||||
fn: () => Promise<T>,
|
||||
options: {
|
||||
maxAttempts?: number;
|
||||
initialDelay?: number;
|
||||
maxDelay?: number;
|
||||
backoffMultiplier?: number;
|
||||
} = {}
|
||||
): Promise<T> {
|
||||
const {
|
||||
maxAttempts = 3,
|
||||
initialDelay = 1000,
|
||||
maxDelay = 30000,
|
||||
backoffMultiplier = 2,
|
||||
} = options;
|
||||
|
||||
let lastError: Error | undefined;
|
||||
let delay = initialDelay;
|
||||
|
||||
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
||||
try {
|
||||
return await fn();
|
||||
} catch (error) {
|
||||
lastError = error as Error;
|
||||
|
||||
if (attempt < maxAttempts) {
|
||||
await sleep(Math.min(delay, maxDelay));
|
||||
delay *= backoffMultiplier;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw lastError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates email format
|
||||
*/
|
||||
export function isValidEmail(email: string): boolean {
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
return emailRegex.test(email);
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncates a string to the specified length
|
||||
*/
|
||||
export function truncate(str: string, length: number, suffix: string = '...'): string {
|
||||
if (str.length <= length) return str;
|
||||
return str.slice(0, length - suffix.length) + suffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats an address for display (0x1234...5678)
|
||||
*/
|
||||
export function formatAddress(address: string, startChars: number = 6, endChars: number = 4): string {
|
||||
if (!address) return '';
|
||||
if (address.length <= startChars + endChars) return address;
|
||||
return `${address.slice(0, startChars)}...${address.slice(-endChars)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a value to Wei (smallest unit)
|
||||
*/
|
||||
export function toWei(value: number | string, decimals: number = 18): string {
|
||||
const val = typeof value === 'string' ? parseFloat(value) : value;
|
||||
return (val * Math.pow(10, decimals)).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts Wei to a human-readable value
|
||||
*/
|
||||
export function fromWei(value: string | number, decimals: number = 18): string {
|
||||
const val = typeof value === 'string' ? parseFloat(value) : value;
|
||||
return (val / Math.pow(10, decimals)).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Debounces a function
|
||||
*/
|
||||
export function debounce<T extends (...args: unknown[]) => unknown>(
|
||||
func: T,
|
||||
wait: number
|
||||
): (...args: Parameters<T>) => void {
|
||||
let timeout: NodeJS.Timeout | null = null;
|
||||
|
||||
return function executedFunction(...args: Parameters<T>) {
|
||||
const later = () => {
|
||||
timeout = null;
|
||||
func(...args);
|
||||
};
|
||||
|
||||
if (timeout) {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
timeout = setTimeout(later, wait);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Throttles a function
|
||||
*/
|
||||
export function throttle<T extends (...args: unknown[]) => unknown>(
|
||||
func: T,
|
||||
limit: number
|
||||
): (...args: Parameters<T>) => void {
|
||||
let inThrottle: boolean;
|
||||
|
||||
return function executedFunction(...args: Parameters<T>) {
|
||||
if (!inThrottle) {
|
||||
func(...args);
|
||||
inThrottle = true;
|
||||
setTimeout(() => (inThrottle = false), limit);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Deep clones an object
|
||||
*/
|
||||
export function deepClone<T>(obj: T): T {
|
||||
return JSON.parse(JSON.stringify(obj));
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges two objects deeply
|
||||
*/
|
||||
export function deepMerge<T extends Record<string, unknown>>(
|
||||
target: T,
|
||||
source: Partial<T>
|
||||
): T {
|
||||
const output = { ...target };
|
||||
|
||||
for (const key in source) {
|
||||
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
||||
const targetValue = output[key];
|
||||
const sourceValue = source[key];
|
||||
|
||||
if (
|
||||
typeof targetValue === 'object' &&
|
||||
targetValue !== null &&
|
||||
typeof sourceValue === 'object' &&
|
||||
sourceValue !== null &&
|
||||
!Array.isArray(targetValue) &&
|
||||
!Array.isArray(sourceValue)
|
||||
) {
|
||||
output[key] = deepMerge(
|
||||
targetValue as Record<string, unknown>,
|
||||
sourceValue as Record<string, unknown>
|
||||
) as T[Extract<keyof T, string>];
|
||||
} else {
|
||||
output[key] = sourceValue as T[Extract<keyof T, string>];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
Reference in New Issue
Block a user