Skip to content

Commit 944509a

Browse files
committed
Add CryptAPI wrapper and HTTP debugging with enhanced error logging
1 parent 4fe190a commit 944509a

File tree

4 files changed

+371
-35
lines changed

4 files changed

+371
-35
lines changed

src/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ import fs from 'fs';
88

99
import { registerRoutes } from './routes/index.js';
1010
import { errorHandler } from './middleware/error-handler.js';
11+
import { enableHttpDebugging } from './utils/http-debug.js';
12+
13+
// Enable HTTP debugging for detailed request/response logging
14+
console.log('Enabling HTTP debugging for detailed request/response logging');
15+
enableHttpDebugging();
1116

1217
// Load environment variables
1318
dotenvFlow.config();

src/services/payment-service.js

Lines changed: 135 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import cryptapi from 'cryptapi';
1+
import { createCryptAPIClient } from '../utils/cryptapi-wrapper.js';
22
import { supabase } from '../utils/supabase.js';
33
import { emailService } from './email-service.js';
44
import dotenv from 'dotenv-flow';
@@ -17,6 +17,8 @@ export const paymentService = {
1717
* @private
1818
*/
1919
_getCryptAPIClient(coin) {
20+
console.log(`Payment service: Getting CryptAPI client for coin: ${coin}`);
21+
2022
// Get cryptocurrency wallet addresses from environment variables or use defaults
2123
const addresses = {
2224
btc: process.env.BITCOIN_ADDRESS || "bc1q254klmlgtanf8xez28gy7r0enpyhk88r2499pt",
@@ -25,20 +27,39 @@ export const paymentService = {
2527
usdc: process.env.USDC_ADDRESS || "0x402282c72a2f2b9f059C3b39Fa63932D6AA09f11"
2628
};
2729

30+
console.log(`Payment service: Using address for ${coin}: ${addresses[coin]}`);
31+
2832
if (!addresses[coin]) {
33+
console.error(`Payment service: Unsupported cryptocurrency: ${coin}`);
2934
throw new Error(`Unsupported cryptocurrency: ${coin}`);
3035
}
3136

32-
// Initialize the CryptAPI client
33-
const api = cryptapi();
37+
// Initialize the CryptAPI client using our wrapper
38+
console.log('Payment service: Initializing CryptAPI client with wrapper');
39+
const api = createCryptAPIClient();
40+
console.log('Payment service: CryptAPI client initialized with wrapper');
3441

3542
// Return an object with methods for creating addresses and handling callbacks
3643
return {
3744
createAddress: (options) => {
38-
return api._createAddress(coin, addresses[coin], options.callback, {
39-
pending: options.pending,
40-
parameters: options.parameters
41-
});
45+
console.log('Payment service: Creating address with CryptAPI with options:', JSON.stringify(options));
46+
console.log(`Payment service: CryptAPI endpoint: /${coin}/create`);
47+
console.log(`Payment service: CryptAPI address: ${addresses[coin]}`);
48+
console.log(`Payment service: CryptAPI callback URL: ${options.callback}`);
49+
50+
try {
51+
const result = api._createAddress(coin, addresses[coin], options.callback, {
52+
pending: options.pending,
53+
parameters: options.parameters
54+
});
55+
56+
console.log('Payment service: CryptAPI createAddress successful');
57+
return result;
58+
} catch (error) {
59+
console.error('Payment service: Error in CryptAPI createAddress:', error);
60+
console.error('Payment service: Error stack:', error.stack);
61+
throw error;
62+
}
4263
}
4364
};
4465
},
@@ -104,37 +125,57 @@ export const paymentService = {
104125
console.log('Payment service: Subscription created in Supabase:', JSON.stringify(subscription));
105126

106127
// Generate payment invoice
128+
console.log('Payment service: Preparing to generate payment invoice');
107129
console.log('Payment service: Getting CryptAPI client for', coin);
108-
const cryptapiClient = this._getCryptAPIClient(coin);
109-
const callbackUrl = 'https://pdf.profullstack.com/api/1/payment-callback';
110130

111-
console.log('Payment service: Creating address with CryptAPI');
112-
const invoice = await cryptapiClient.createAddress({
113-
callback: callbackUrl,
114-
pending: true,
115-
parameters: {
116-
subscription_id: subscription.id,
117-
email
131+
try {
132+
const cryptapiClient = this._getCryptAPIClient(coin);
133+
const callbackUrl = 'https://pdf.profullstack.com/api/1/payment-callback';
134+
135+
console.log('Payment service: Creating address with CryptAPI');
136+
console.log('Payment service: Using callback URL:', callbackUrl);
137+
138+
const requestParams = {
139+
callback: callbackUrl,
140+
pending: true,
141+
parameters: {
142+
subscription_id: subscription.id,
143+
email
144+
}
145+
};
146+
147+
console.log('Payment service: CryptAPI request parameters:', JSON.stringify(requestParams));
148+
149+
const invoice = await cryptapiClient.createAddress(requestParams);
150+
151+
if (!invoice) {
152+
console.error('Payment service: CryptAPI returned null or undefined response');
153+
throw new Error('CryptAPI returned null or undefined response');
154+
}
155+
156+
console.log('Payment service: CryptAPI response:', JSON.stringify(invoice));
157+
158+
// Validate the response
159+
if (!invoice.address_in) {
160+
console.error('Payment service: CryptAPI response missing address_in:', JSON.stringify(invoice));
161+
throw new Error('CryptAPI response missing payment address');
162+
}
163+
164+
// Update subscription with payment details
165+
console.log('Payment service: Updating subscription with payment details');
166+
const { error: updateError } = await supabase
167+
.from('subscriptions')
168+
.update({
169+
payment_address: invoice.address_in,
170+
payment_info: invoice
171+
})
172+
.eq('id', subscription.id);
173+
174+
if (updateError) {
175+
console.error('Payment service: Error updating subscription with payment details:', updateError);
176+
console.error('Error details:', JSON.stringify(updateError));
177+
throw updateError;
118178
}
119-
});
120-
121-
console.log('Payment service: CryptAPI response:', JSON.stringify(invoice));
122-
123-
// Update subscription with payment details
124-
console.log('Payment service: Updating subscription with payment details');
125-
const { error: updateError } = await supabase
126-
.from('subscriptions')
127-
.update({
128-
payment_address: invoice.address_in,
129-
payment_info: invoice
130-
})
131-
.eq('id', subscription.id);
132-
133-
if (updateError) {
134-
console.error('Payment service: Error updating subscription with payment details:', updateError);
135-
console.error('Error details:', JSON.stringify(updateError));
136-
throw updateError;
137-
}
138179

139180
// Send subscription confirmation email
140181
try {
@@ -158,9 +199,68 @@ export const paymentService = {
158199

159200
console.log('Payment service: Returning subscription result:', JSON.stringify(result));
160201
return result;
202+
} catch (cryptapiError) {
203+
console.error('Payment service: Error in CryptAPI operations:', cryptapiError);
204+
console.error('Payment service: Error stack:', cryptapiError.stack);
205+
206+
// Add more detailed error information for CryptAPI errors
207+
if (cryptapiError.response) {
208+
console.error('Payment service: CryptAPI error response status:', cryptapiError.response.status);
209+
console.error('Payment service: CryptAPI error response headers:', JSON.stringify(cryptapiError.response.headers));
210+
console.error('Payment service: CryptAPI error response data:', JSON.stringify(cryptapiError.response.data));
211+
}
212+
213+
// Check if it's a 404 error from Unirest
214+
if (cryptapiError.message && cryptapiError.message.includes('got 404 response')) {
215+
console.error('Payment service: 404 error detected - CryptAPI endpoint might be incorrect or service might be down');
216+
}
217+
218+
throw cryptapiError;
219+
}
161220
} catch (error) {
162221
console.error('Payment service: Unexpected error in createSubscription:', error);
163222
console.error('Error stack:', error.stack);
223+
224+
// Add more detailed error information
225+
if (error.response) {
226+
console.error('Payment service: Error response status:', error.response.status);
227+
console.error('Payment service: Error response headers:', JSON.stringify(error.response.headers));
228+
console.error('Payment service: Error response data:', JSON.stringify(error.response.data));
229+
} else if (error.request) {
230+
console.error('Payment service: Error request sent but no response received');
231+
console.error('Payment service: Error request details:', JSON.stringify(error.request));
232+
} else {
233+
console.error('Payment service: Error message:', error.message);
234+
}
235+
236+
// Check if it's a 404 error from Unirest
237+
if (error.message && error.message.includes('got 404 response')) {
238+
console.error('Payment service: 404 error detected - CryptAPI endpoint might be incorrect or service might be down');
239+
240+
// Generate a curl command for manual testing of the CryptAPI endpoint
241+
try {
242+
const baseURL = 'https://cryptapi.io/api/';
243+
const testCoin = coin || 'btc';
244+
const testAddress = process.env.BITCOIN_ADDRESS || "bc1q254klmlgtanf8xez28gy7r0enpyhk88r2499pt";
245+
const callbackUrl = 'https://pdf.profullstack.com/api/1/payment-callback';
246+
247+
// Build query parameters
248+
const queryParams = new URLSearchParams();
249+
queryParams.append('address', testAddress);
250+
queryParams.append('callback', callbackUrl);
251+
queryParams.append('pending', 'true');
252+
253+
const fullURL = `${baseURL}${testCoin}/create?${queryParams.toString()}`;
254+
const curlCommand = `curl -v "${fullURL}"`;
255+
256+
console.error('Payment service: Try testing the CryptAPI endpoint with this curl command:');
257+
console.error(curlCommand);
258+
console.error('Payment service: If this also fails, the CryptAPI service might be down or the endpoint might have changed.');
259+
} catch (curlError) {
260+
console.error('Payment service: Error generating test curl command:', curlError);
261+
}
262+
}
263+
164264
throw error;
165265
}
166266
},

src/utils/cryptapi-wrapper.js

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/**
2+
* CryptAPI wrapper with enhanced logging
3+
*/
4+
import cryptapi from 'cryptapi';
5+
import util from 'util';
6+
7+
/**
8+
* Create a wrapped CryptAPI client with enhanced logging
9+
* @returns {Object} - Enhanced CryptAPI client
10+
*/
11+
export function createCryptAPIClient() {
12+
console.log('CryptAPI Wrapper: Creating CryptAPI client');
13+
14+
// Create the original client
15+
const originalClient = cryptapi();
16+
17+
// Get the original _createAddress method
18+
const originalCreateAddress = originalClient._createAddress;
19+
20+
// Override the _createAddress method with our enhanced version
21+
originalClient._createAddress = function(coin, address, callback, options) {
22+
console.log('CryptAPI Wrapper: _createAddress called with:');
23+
console.log(` - Coin: ${coin}`);
24+
console.log(` - Address: ${address}`);
25+
console.log(` - Callback URL: ${callback}`);
26+
console.log(` - Options: ${util.inspect(options, { depth: null })}`);
27+
28+
// Construct the full URL that will be called
29+
const baseURL = 'https://cryptapi.io/api/';
30+
const endpoint = `/${coin}/create`;
31+
32+
// Build query parameters
33+
const queryParams = new URLSearchParams();
34+
queryParams.append('address', address);
35+
queryParams.append('callback', callback);
36+
37+
// Add any additional parameters from options
38+
if (options) {
39+
if (options.pending) {
40+
queryParams.append('pending', options.pending);
41+
}
42+
43+
if (options.parameters) {
44+
for (const [key, value] of Object.entries(options.parameters)) {
45+
queryParams.append(`parameters[${key}]`, value);
46+
}
47+
}
48+
}
49+
50+
const fullURL = `${baseURL}${coin}/create?${queryParams.toString()}`;
51+
console.log(`CryptAPI Wrapper: Full URL that will be called: ${fullURL}`);
52+
53+
// Generate a curl command for manual testing
54+
const curlCommand = `curl -v "${fullURL}"`;
55+
console.log(`CryptAPI Wrapper: Equivalent curl command for testing:`);
56+
console.log(curlCommand);
57+
58+
try {
59+
// Call the original method
60+
const result = originalCreateAddress.call(originalClient, coin, address, callback, options);
61+
62+
// Log the result
63+
console.log('CryptAPI Wrapper: _createAddress result:');
64+
console.log(util.inspect(result, { depth: null }));
65+
66+
// Return the result
67+
return result;
68+
} catch (error) {
69+
console.error('CryptAPI Wrapper: Error in _createAddress:');
70+
console.error(error);
71+
72+
// Log detailed error information
73+
if (error.response) {
74+
console.error('CryptAPI Wrapper: Error response status:', error.response.status);
75+
console.error('CryptAPI Wrapper: Error response headers:', JSON.stringify(error.response.headers));
76+
console.error('CryptAPI Wrapper: Error response data:', JSON.stringify(error.response.data));
77+
} else if (error.request) {
78+
console.error('CryptAPI Wrapper: Error request sent but no response received');
79+
console.error('CryptAPI Wrapper: Error request details:', JSON.stringify(error.request));
80+
} else {
81+
console.error('CryptAPI Wrapper: Error message:', error.message);
82+
}
83+
84+
// Rethrow the error
85+
throw error;
86+
}
87+
};
88+
89+
return originalClient;
90+
}

0 commit comments

Comments
 (0)