@ln-markets/sdk
Version:
TypeScript SDK for LNMarkets API v2
82 lines • 3.31 kB
JavaScript
import camelcaseKeys from 'camelcase-keys';
import { createHmac } from 'node:crypto';
import { URL, URLSearchParams } from 'node:url';
import { fetch } from 'undici';
import { createRouter } from './routes/index.js';
import { getHostname } from './utils.js';
class HttpError extends Error {
status;
statusText;
constructor(status, statusText, message) {
super(message);
this.name = 'HttpError';
this.status = status;
this.statusText = statusText;
}
}
export const createRestClient = (options = {}) => {
const { headers = {}, key = process.env.LNM_API_KEY, network = process.env.LNM_API_NETWORK ?? 'mainnet', passphrase = process.env.LNM_API_PASSPHRASE, secret = process.env.LNM_API_SECRET, } = options;
const hostname = process.env.LNM_API_HOSTNAME ?? getHostname(network);
const request = async (options) => {
const { body, method, path, query, requireAuth } = options;
if (requireAuth) {
if (!key) {
throw new Error('You need an API key to use an authenticated route');
}
else if (!secret) {
throw new Error('You need an API secret to use an authenticated route');
}
else if (!passphrase) {
throw new Error('You need an API passphrase to use an authenticated route');
}
const timestamp = Date.now();
const payload = /^(GET|DELETE)$/.test(method)
? new URLSearchParams(Object.fromEntries(Object.entries(query ?? {}).map(([key, value]) => [
key,
JSON.stringify(value),
]))).toString()
: JSON.stringify(body ?? {});
const signature = createHmac('sha256', secret)
.update(`${timestamp}${method}/v2${path}${payload}`)
.digest('base64');
Object.assign(headers, {
'LNM-ACCESS-KEY': key,
'LNM-ACCESS-PASSPHRASE': passphrase,
'LNM-ACCESS-SIGNATURE': signature,
'LNM-ACCESS-TIMESTAMP': timestamp,
});
}
const url = new URL(`https://${hostname}/v2${path}`);
if (query) {
for (const [key, value] of Object.entries(query)) {
url.searchParams.append(key, value.toString());
}
}
if (body && /^(POST|PUT)$/.test(method)) {
Object.assign(headers, {
'Content-Type': 'application/json',
});
}
const payload = /^(POST|PUT)$/.test(method)
? JSON.stringify(body)
: undefined;
const response = await fetch(url, {
body: payload,
headers,
method,
mode: 'cors',
});
if (response.ok) {
if (response.headers.get('content-type')?.includes('application/json')) {
return response
.json()
.then((value) => camelcaseKeys(value, { deep: true }));
}
return response.text();
}
const text = await response.text();
throw new HttpError(response.status, response.statusText, text);
};
return createRouter(request);
};
//# sourceMappingURL=rest.js.map