From 6ebd2527cdce2b15bd6cc270a499f9d52ffa9af5 Mon Sep 17 00:00:00 2001 From: Matt Date: Tue, 13 May 2025 19:37:22 +0200 Subject: [PATCH] fixes --- src/api/wrenClient.ts | 85 +++++++++++++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 23 deletions(-) diff --git a/src/api/wrenClient.ts b/src/api/wrenClient.ts index adb9870..ecd83b7 100644 --- a/src/api/wrenClient.ts +++ b/src/api/wrenClient.ts @@ -52,8 +52,8 @@ const createApiClient = () => { console.log('[wrenClient] Creating API client with key:', config.wrenApiKey ? '********' + config.wrenApiKey.slice(-4) : 'MISSING'); const client = axios.create({ - // Updated base URL to match the sample code - baseURL: 'https://www.wren.co/api', + // Base URL to Wren API + baseURL: 'https://www.wren.co', headers: { 'Authorization': `Bearer ${config.wrenApiKey}`, 'Content-Type': 'application/json' @@ -130,7 +130,8 @@ export async function getPortfolios(): Promise { console.log('[wrenClient] Getting portfolios with token:', config.wrenApiKey ? '********' + config.wrenApiKey.slice(-4) : 'MISSING'); const api = createApiClient(); - const response = await api.get('/portfolios'); + // Updated endpoint to match documentation + const response = await api.get('/api/portfolios'); if (!response.data?.portfolios?.length) { console.warn('[wrenClient] No portfolios returned from API, using fallback'); @@ -177,41 +178,70 @@ export async function createOffsetOrder( console.log(`[wrenClient] Creating offset order: portfolio=${portfolioId}, tons=${tons}`); const api = createApiClient(); - // Updated to use the correct endpoint and parameter names - const response = await api.post('/offset-orders', { + // Updated to use the correct endpoint and match exact API format from documentation + const response = await api.post('/api/offset-orders', { + // Using exactly the format shown in API docs portfolioId, tons, - dryRun, - currency: 'USD' + dryRun + // Currency is not shown as a parameter in the API docs }); + // Add detailed response logging + console.log('[wrenClient] Offset order response:', + response.status, + response.data ? 'has data' : 'no data'); + + if (response.status === 400) { + console.error('[wrenClient] Bad request details:', response.data); + throw new Error(`Failed to create offset order: ${JSON.stringify(response.data)}`); + } + const order = response.data; + if (!order) { + throw new Error('Empty response received from offset order API'); + } + + // Log to help diagnose issues + console.log('[wrenClient] Order data keys:', Object.keys(order).join(', ')); + if (order.portfolio) { + console.log('[wrenClient] Portfolio data keys:', Object.keys(order.portfolio).join(', ')); + } // Updated to handle costPerTon vs pricePerTon let pricePerTon = 200; - if (order.portfolio?.pricePerTon !== undefined && order.portfolio.pricePerTon !== null) { + if (order.portfolio?.pricePerTon !== undefined) { pricePerTon = typeof order.portfolio.pricePerTon === 'number' ? order.portfolio.pricePerTon : parseFloat(order.portfolio.pricePerTon) || 200; - } else if (order.portfolio?.costPerTon !== undefined && order.portfolio.costPerTon !== null) { + } else if (order.portfolio?.costPerTon !== undefined) { pricePerTon = typeof order.portfolio.costPerTon === 'number' ? order.portfolio.costPerTon : parseFloat(order.portfolio.costPerTon) || 200; } - // Adjusted to use camelCase as per API response + // Create a safe method to extract properties with fallbacks + const getSafeProp = (obj: any, prop: string, fallback: any) => { + if (!obj) return fallback; + return obj[prop] !== undefined ? obj[prop] : fallback; + }; + + // Use safe accessor to avoid undefined errors + const portfolio = order.portfolio || {}; + + // Adjusted to use camelCase as per API docs response format return { - id: order.id, - amountCharged: order.amountCharged, - currency: order.currency || 'USD', - tons: order.tons, + id: getSafeProp(order, 'id', ''), + amountCharged: getSafeProp(order, 'amountCharged', 0), + currency: getSafeProp(order, 'currency', 'USD'), + tons: getSafeProp(order, 'tons', 0), portfolio: { - id: order.portfolio.id, - name: order.portfolio.name, - description: order.portfolio.description || '', - projects: order.portfolio.projects || [], + id: getSafeProp(portfolio, 'id', 1), + name: getSafeProp(portfolio, 'name', 'Default Portfolio'), + description: getSafeProp(portfolio, 'description', ''), + projects: getSafeProp(portfolio, 'projects', []), pricePerTon, - currency: order.currency || 'USD' + currency: getSafeProp(order, 'currency', 'USD') }, - status: order.status, - createdAt: order.createdAt || order.created_at, - dryRun: order.dryRun + status: getSafeProp(order, 'status', ''), + createdAt: getSafeProp(order, 'createdAt', new Date().toISOString()), + dryRun: getSafeProp(order, 'dryRun', false) }; } catch (error: unknown) { logError(error); @@ -221,15 +251,24 @@ export async function createOffsetOrder( console.error('[wrenClient] Axios error details:', { status: axiosError.response?.status, + statusText: axiosError.response?.statusText, data: axiosError.response?.data, config: { url: axiosError.config?.url, method: axiosError.config?.method, headers: axiosError.config?.headers ? 'Headers present' : 'No headers', - baseURL: axiosError.config?.baseURL + baseURL: axiosError.config?.baseURL, + data: axiosError.config?.data } }); + if (axiosError.response?.status === 400) { + // Provide more specific error for 400 Bad Request + const responseData = axiosError.response.data as any; + const errorMessage = responseData?.message || responseData?.error || 'Invalid request format'; + throw new Error(`Bad request: ${errorMessage}`); + } + if (axiosError.code === 'ECONNABORTED') { throw new Error('Request timed out. Please try again.'); }