@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