UNPKG

irys-complete-toolkit

Version:

Complete Irys SDK toolkit supporting all chains, tokens, and features

425 lines (364 loc) 10.4 kB
/** * Irys REST API Client * Comprehensive REST API client for Irys operations */ import { AccountInfo, TransactionInfo, IrysTag, BalanceApproval, IrysError, NetworkError } from '../types'; export class IrysRestClient { private baseUrl: string; private timeout: number; constructor(baseUrl: string = 'https://uploader.irys.xyz', timeout: number = 30000) { this.baseUrl = baseUrl.replace(/\/$/, ''); // Remove trailing slash this.timeout = timeout; } /** * Make HTTP request with error handling */ private async request( endpoint: string, options: RequestInit = {} ): Promise<any> { const url = `${this.baseUrl}${endpoint}`; const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), this.timeout); try { const response = await fetch(url, { ...options, signal: controller.signal, headers: { 'Content-Type': 'application/json', ...options.headers, }, }); clearTimeout(timeoutId); if (!response.ok) { const errorText = await response.text().catch(() => ''); throw new NetworkError( `HTTP ${response.status}: ${response.statusText}${errorText ? ` - ${errorText}` : ''}`, response.status ); } const contentType = response.headers.get('content-type'); if (contentType && contentType.includes('application/json')) { return await response.json(); } else { return await response.text(); } } catch (error) { clearTimeout(timeoutId); if (error instanceof NetworkError) { throw error; } if ((error as any)?.name === 'AbortError') { throw new IrysError(`Request timeout after ${this.timeout}ms`); } throw new IrysError(`Request failed: ${error}`); } } /** * Get general info about the Irys node */ async getInfo(): Promise<any> { return this.request('/info'); } /** * Get public information */ async getPublicInfo(): Promise<any> { return this.request('/public'); } /** * Get node status */ async getStatus(): Promise<any> { return this.request('/status'); } /** * Get account balance */ async getBalance(address: string, token?: string): Promise<string> { const params = new URLSearchParams({ address }); if (token) { params.append('token', token); } const result = await this.request(`/account/balance?${params}`); return result.balance || '0'; } /** * Get account information */ async getAccountInfo(address: string): Promise<AccountInfo> { const result = await this.request(`/account/${address}`); return result; } /** * Get transaction by ID */ async getTransaction(txId: string): Promise<TransactionInfo> { return this.request(`/tx/${txId}`); } /** * Get transaction status */ async getTransactionStatus(txId: string): Promise<any> { return this.request(`/tx/${txId}/status`); } /** * Get transaction data */ async getTransactionData(txId: string): Promise<any> { return this.request(`/tx/${txId}/data`); } /** * Get transaction metadata (tags) */ async getTransactionTags(txId: string): Promise<IrysTag[]> { const result = await this.request(`/tx/${txId}/tags`); return result.tags || []; } /** * Get balance approvals for an address */ async getBalanceApprovals( payingAddress?: string, token?: string, approvedAddress?: string ): Promise<BalanceApproval[]> { const params = new URLSearchParams(); if (payingAddress) params.append('payingAddress', payingAddress); if (token) params.append('token', token); if (approvedAddress) params.append('approvedAddress', approvedAddress); const result = await this.request(`/account/approval?${params}`); return result.approvals || []; } /** * Get upload price for data size */ async getPrice(bytes: number, target?: string): Promise<string> { const params = new URLSearchParams({ bytes: bytes.toString() }); if (target) params.append('target', target); const result = await this.request(`/price?${params}`); return result.price || '0'; } /** * Get upload prices for multiple data sizes */ async getPrices(sizes: number[]): Promise<Record<number, string>> { const promises = sizes.map(async size => { const price = await this.getPrice(size); return { size, price }; }); const results = await Promise.all(promises); return results.reduce((acc, { size, price }) => { acc[size] = price; return acc; }, {} as Record<number, string>); } /** * Post data to Irys (raw HTTP upload) */ async postData( data: string | ArrayBuffer | Uint8Array, tags: IrysTag[] = [], target?: string ): Promise<any> { const headers: Record<string, string> = {}; // Add tags as headers tags.forEach((tag, index) => { headers[`Tag-${index}-Name`] = tag.name; headers[`Tag-${index}-Value`] = tag.value; }); if (target) { headers['Target'] = target; } return this.request('/tx', { method: 'POST', headers, body: data as BodyInit, }); } /** * Get peers information */ async getPeers(): Promise<any> { return this.request('/peers'); } /** * Get wallet information */ async getWallet(address: string): Promise<any> { return this.request(`/wallet/${address}`); } /** * Get block by height */ async getBlock(height: number): Promise<any> { return this.request(`/block/height/${height}`); } /** * Get current block height */ async getCurrentHeight(): Promise<number> { const result = await this.request('/block/current'); return result.height || 0; } /** * Get network metrics */ async getMetrics(): Promise<any> { return this.request('/metrics'); } /** * Health check endpoint */ async healthCheck(): Promise<boolean> { try { await this.request('/health'); return true; } catch (error) { return false; } } /** * Download data from Irys gateway */ async downloadData(txId: string): Promise<any> { const gatewayUrl = `https://gateway.irys.xyz/${txId}`; try { const response = await fetch(gatewayUrl); if (!response.ok) { throw new NetworkError( `Failed to download data: ${response.status} ${response.statusText}`, response.status ); } const contentType = response.headers.get('content-type'); if (contentType && contentType.includes('application/json')) { return await response.json(); } else if (contentType && contentType.startsWith('text/')) { return await response.text(); } else { return await response.arrayBuffer(); } } catch (error) { if (error instanceof NetworkError) { throw error; } throw new IrysError(`Failed to download data: ${error}`); } } /** * Get data as stream (for large files) */ async downloadDataStream(txId: string): Promise<ReadableStream | null> { const gatewayUrl = `https://gateway.irys.xyz/${txId}`; try { const response = await fetch(gatewayUrl); if (!response.ok) { throw new NetworkError( `Failed to download data: ${response.status} ${response.statusText}`, response.status ); } return response.body; } catch (error) { if (error instanceof NetworkError) { throw error; } throw new IrysError(`Failed to download data stream: ${error}`); } } /** * Verify transaction receipt */ async verifyReceipt(receipt: any): Promise<boolean> { try { const result = await this.request('/receipt/verify', { method: 'POST', body: JSON.stringify(receipt), }); return result.valid === true; } catch (error) { throw new IrysError(`Failed to verify receipt: ${error}`); } } /** * Get transaction receipt */ async getReceipt(txId: string): Promise<any> { return this.request(`/tx/${txId}/receipt`); } /** * Search transactions by owner */ async searchTransactionsByOwner( owner: string, limit: number = 100, offset: number = 0 ): Promise<TransactionInfo[]> { const params = new URLSearchParams({ owner, limit: limit.toString(), offset: offset.toString(), }); const result = await this.request(`/tx/search?${params}`); return result.transactions || []; } /** * Search transactions by tag */ async searchTransactionsByTag( name: string, value: string, limit: number = 100, offset: number = 0 ): Promise<TransactionInfo[]> { const params = new URLSearchParams({ 'tag-name': name, 'tag-value': value, limit: limit.toString(), offset: offset.toString(), }); const result = await this.request(`/tx/search?${params}`); return result.transactions || []; } /** * Get bundle information */ async getBundleInfo(bundleId: string): Promise<any> { return this.request(`/bundle/${bundleId}`); } /** * Get data item from bundle */ async getDataItem(bundleId: string, itemId: string): Promise<any> { return this.request(`/bundle/${bundleId}/data/${itemId}`); } /** * Set custom base URL */ setBaseUrl(baseUrl: string): void { this.baseUrl = baseUrl.replace(/\/$/, ''); } /** * Set request timeout */ setTimeout(timeout: number): void { this.timeout = timeout; } /** * Get current configuration */ getConfig(): { baseUrl: string; timeout: number } { return { baseUrl: this.baseUrl, timeout: this.timeout, }; } }