UNPKG

@moneygraph/sdk

Version:

AI-native SDK for global payouts powered by StratosPay

165 lines (164 loc) 6.14 kB
"use strict"; /** * MoneyGraph SDK - API Client * * Dual-mode HTTP client that automatically detects sandbox vs live mode * based on API key prefix (sk_test_* = sandbox, sk_live_* = live). */ Object.defineProperty(exports, "__esModule", { value: true }); exports.ApiClient = exports.MoneyGraphError = void 0; class MoneyGraphError extends Error { constructor(message, code, statusCode, details) { super(message); this.name = 'MoneyGraphError'; this.code = code; this.statusCode = statusCode; this.details = details; } } exports.MoneyGraphError = MoneyGraphError; class ApiClient { constructor(options) { this.apiKey = options.apiKey; this.baseUrl = options.baseUrl || 'https://stratospay.com/api/v1'; this.timeout = options.timeout || 30000; // Detect mode from API key prefix this.mode = this.detectMode(options.apiKey); } detectMode(apiKey) { if (apiKey.startsWith('sk_test_') || apiKey.startsWith('pk_test_')) { return 'sandbox'; } if (apiKey.startsWith('sk_live_') || apiKey.startsWith('pk_live_')) { return 'live'; } // Default to sandbox for safety return 'sandbox'; } get isSandbox() { return this.mode === 'sandbox'; } get isLive() { return this.mode === 'live'; } mapStatusCodeToError(status, message) { switch (status) { case 400: if (message.toLowerCase().includes('invalid api key')) { return 'INVALID_API_KEY'; } return 'VALIDATION_ERROR'; case 401: return 'UNAUTHORIZED'; case 403: if (message.toLowerCase().includes('kyc already approved')) { return 'KYC_ALREADY_APPROVED'; } return 'FORBIDDEN'; case 404: if (message.toLowerCase().includes('user not found')) { return 'CUSTOMER_NOT_FOUND'; } if (message.toLowerCase().includes('director')) { return 'DIRECTOR_NOT_FOUND'; } return 'NOT_FOUND'; case 429: return 'RATE_LIMITED'; default: return 'INTERNAL_ERROR'; } } async request(method, endpoint, options = {}) { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), this.timeout); try { let url = `${this.baseUrl}${endpoint}`; // Add query params if (options.params) { const queryParams = new URLSearchParams(); for (const [key, value] of Object.entries(options.params)) { queryParams.append(key, String(value)); } url += `?${queryParams.toString()}`; } const headers = { 'Accept': 'application/json', 'Authorization': `Bearer ${this.apiKey}`, ...options.headers, }; if (options.body) { headers['Content-Type'] = 'application/json'; } const response = await fetch(url, { method, headers, body: options.body ? JSON.stringify(options.body) : undefined, signal: controller.signal, }); const data = await response.json(); if (!response.ok || data.status === 'failed') { const errorCode = this.mapStatusCodeToError(response.status, data.message); throw new MoneyGraphError(data.message || `Request failed with status ${response.status}`, errorCode, response.status, data.data); } return data.data; } catch (error) { if (error instanceof MoneyGraphError) { throw error; } if (error instanceof Error) { if (error.name === 'AbortError') { throw new MoneyGraphError('Request timed out', 'NETWORK_ERROR', undefined, { timeout: this.timeout }); } throw new MoneyGraphError(error.message, 'NETWORK_ERROR', undefined, { originalError: error.name }); } throw new MoneyGraphError('Unknown error occurred', 'INTERNAL_ERROR'); } finally { clearTimeout(timeoutId); } } async get(endpoint, params) { return this.request('GET', endpoint, { params }); } async post(endpoint, body) { return this.request('POST', endpoint, { body }); } async put(endpoint, body) { return this.request('PUT', endpoint, { body }); } async delete(endpoint) { return this.request('DELETE', endpoint); } /** * Upload a file (for KYC documents) */ async uploadFile(endpoint, file, filename) { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), this.timeout * 2); try { const formData = new FormData(); const blob = file instanceof Blob ? file : new Blob([new Uint8Array(file)]); formData.append('file', blob, filename); const response = await fetch(`${this.baseUrl}${endpoint}`, { method: 'POST', headers: { 'Authorization': `Bearer ${this.apiKey}`, 'Accept': 'application/json', }, body: formData, signal: controller.signal, }); const data = await response.json(); if (!response.ok || data.status === 'failed') { const errorCode = this.mapStatusCodeToError(response.status, data.message); throw new MoneyGraphError(data.message, errorCode, response.status); } } finally { clearTimeout(timeoutId); } } } exports.ApiClient = ApiClient;