@renegade-fi/core
Version:
VanillaJS library for Renegade
185 lines • 7.86 kB
JavaScript
import axios from 'axios';
import invariant from 'tiny-invariant';
import { RENEGADE_AUTH_HEADER_NAME, RENEGADE_SDK_VERSION_HEADER, RENEGADE_SIG_EXPIRATION_HEADER_NAME, SIG_EXPIRATION_BUFFER_MS, } from '../constants.js';
import { BaseError } from '../errors/base.js';
import { parseBigJSON } from './bigJSON.js';
import { getVersionNumber } from './getVersion.js';
export async function postRelayerRaw(url, body, headers = {}) {
try {
const response = await axios.post(url, body, {
headers,
validateStatus: null, // Allow any status code to pass through
transformResponse: (data) => {
try {
return parseBigJSON(data);
}
catch {
// If parsing fails, return raw data
return data;
}
},
});
// For non-2xx responses, throw error with raw data
if (response.status < 200 || response.status >= 300) {
throw new BaseError(response.data);
}
return response.data;
}
catch (error) {
if (axios.isAxiosError(error)) {
if (error.response) {
// The request was made and the server responded with a status code
// that falls out of the range of 2xx
console.error('Response error:', error.response.data);
throw new BaseError(error.response.data);
}
if (error.request) {
// The request was made but no response was received
console.error('Request error: No response received');
}
else {
// Something happened in setting up the request that triggered an Error
console.error('Error:', error.message);
}
}
else {
// Non-Axios error
console.error('Error:', error);
}
throw error; // Rethrow the error for further handling or logging
}
}
export async function getRelayerRaw(url, headers = {}) {
try {
const response = await axios.get(url, {
headers,
transformResponse: (data) => {
try {
if (url.includes('/order-history') ||
url.includes('/open-orders') ||
url.includes('/metadata')) {
// We use ts-ignore here because TypeScript doesn't recognize the
// `context` argument in the JSON.parse reviver
// @ts-ignore
return JSON.parse(data, (key, value, context) => {
if (typeof value === 'number' && key !== 'price') {
if (context?.source === undefined) {
console.warn(`No JSON source for ${key}, converting parsed value to BigInt`);
return BigInt(value);
}
return BigInt(context.source);
}
return value;
});
}
if (url.includes('/price')) {
return JSON.parse(data);
}
return parseBigJSON(data);
}
catch (_error) {
return data;
}
},
});
// console.log(`GET ${url} response: `, response.data)
// Process the response data as needed
return response.data; // Assuming the function should return the response data
}
catch (error) {
if (axios.isAxiosError(error)) {
if (error.response) {
// The request was made and the server responded with a status code
// that falls out of the range of 2xx
console.error('Response error:', error.response.data);
}
else if (error.request) {
// The request was made but no response was received
console.error('Request error: No response received');
}
else {
// Something happened in setting up the request that triggered an Error
console.error('Error:', error.message);
}
}
else {
// Non-Axios error
console.error('Error:', error);
}
throw error; // Rethrow the error for further handling or logging
}
}
export async function postRelayerWithAuth(config, url, body, requestType) {
const symmetricKey = config.getSymmetricKey(requestType);
invariant(symmetricKey, 'Failed to derive symmetric key');
const path = getPathFromUrl(url);
const headers = {
'Content-Type': 'application/json',
};
const headersWithAuth = addExpiringAuthToHeaders(config, path, headers, body ?? '', symmetricKey, SIG_EXPIRATION_BUFFER_MS);
return await postRelayerRaw(url, body, headersWithAuth);
}
export async function postRelayerWithAdmin(config, url, body) {
const { adminKey } = config;
invariant(adminKey, 'Admin key is required');
const symmetricKey = config.utils.b64_to_hex_hmac_key(adminKey);
const path = getPathFromUrl(url);
const headers = {
'Content-Type': 'application/json',
};
const headersWithAuth = addExpiringAuthToHeaders(config, path, headers, body ?? '', symmetricKey, SIG_EXPIRATION_BUFFER_MS);
return await postRelayerRaw(url, body, headersWithAuth);
}
export async function getRelayerWithAuth(config, url) {
const symmetricKey = config.getSymmetricKey();
invariant(symmetricKey, 'Failed to derive symmetric key');
const path = getPathFromUrl(url);
const headers = {
'Content-Type': 'application/json',
};
const headersWithAuth = addExpiringAuthToHeaders(config, path, headers, '', // Body
symmetricKey, SIG_EXPIRATION_BUFFER_MS);
return await getRelayerRaw(url, headersWithAuth);
}
export async function getRelayerWithAdmin(config, url) {
const { adminKey } = config;
invariant(adminKey, 'Admin key is required');
const symmetricKey = config.utils.b64_to_hex_hmac_key(adminKey);
const path = getPathFromUrl(url);
const headers = {
'Content-Type': 'application/json',
};
const headersWithAuth = addExpiringAuthToHeaders(config, path, headers, '', // Body
symmetricKey, SIG_EXPIRATION_BUFFER_MS);
return await getRelayerRaw(url, headersWithAuth);
}
export async function postWithSymmetricKey(config, { body, headers = {}, key, url, }) {
const path = getPathFromUrl(url);
const headersWithAuth = addExpiringAuthToHeaders(config, path, headers, body ?? '', key, SIG_EXPIRATION_BUFFER_MS);
return await postRelayerRaw(url, body, headersWithAuth);
}
/// Get the path from a URL
function getPathFromUrl(url) {
try {
const parsedUrl = new URL(url);
return parsedUrl.pathname + parsedUrl.search || '/';
}
catch {
return url.startsWith('/') ? url : `/${url}`;
}
}
/// Add an auth expiration and signature to a set of headers
export function addExpiringAuthToHeaders(config, path, headers, body, key, expiration) {
// Add a timestamp
const expirationTs = Date.now() + expiration;
const versionString = `typescript-v${getVersionNumber()}`;
const headersWithExpiration = {
...headers,
[RENEGADE_SIG_EXPIRATION_HEADER_NAME]: expirationTs.toString(),
[RENEGADE_SDK_VERSION_HEADER]: versionString,
};
// Add the signature
const auth = config.utils.create_request_signature(path, headersWithExpiration, body, key);
return { ...headersWithExpiration, [RENEGADE_AUTH_HEADER_NAME]: auth };
}
//# sourceMappingURL=http.js.map