bybit-api
Version:
Complete & robust Node.js SDK for Bybit's REST APIs and WebSockets, with TypeScript & strong end to end tests.
155 lines (153 loc) • 7.21 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getSignKeyType = getSignKeyType;
exports.hashMessage = hashMessage;
exports.signMessage = signMessage;
exports.signBinaryData = signBinaryData;
exports.checkWebCryptoAPISupported = checkWebCryptoAPISupported;
const typeGuards_1 = require("./typeGuards");
function bufferToB64(buffer) {
let binary = '';
const bytes = new Uint8Array(buffer);
const len = bytes.byteLength;
for (let i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return globalThis.btoa(binary);
}
/**
* Determine the key type based on the secret format
* RSA keys contain "-----BEGIN PRIVATE KEY-----" or "-----BEGIN RSA PRIVATE KEY-----"
* HMAC keys are plain strings
*/
function getSignKeyType(secret) {
if (secret.includes('PRIVATE KEY')) {
return 'RSASSA-PKCS1-v1_5';
}
return 'HMAC';
}
/**
* Import a key for signing based on its type
*/
function importKey(secret, type, algorithm, encoder) {
return __awaiter(this, void 0, void 0, function* () {
switch (type) {
case 'RSASSA-PKCS1-v1_5': {
// Remove PEM headers/footers and whitespace to get base64 content
const base64Key = secret.replace(/(?:-----BEGIN RSA PRIVATE KEY-----|-----BEGIN PRIVATE KEY-----|-----END RSA PRIVATE KEY-----|-----END PRIVATE KEY-----|\s+)/g, '');
const binaryKey = Uint8Array.from(atob(base64Key), (c) => c.charCodeAt(0));
return crypto.subtle.importKey('pkcs8', binaryKey.buffer, { name: type, hash: { name: algorithm } }, false, ['sign']);
}
case 'HMAC': {
return globalThis.crypto.subtle.importKey('raw', encoder.encode(secret), { name: type, hash: algorithm }, false, ['sign']);
}
default: {
throw (0, typeGuards_1.neverGuard)(type, `Unhandled key type: "${type}"`);
}
}
});
}
/**
* Similar to node crypto's `createHash()` function
*/
function hashMessage(message, method, algorithm) {
return __awaiter(this, void 0, void 0, function* () {
const encoder = new TextEncoder();
const buffer = yield globalThis.crypto.subtle.digest(algorithm, encoder.encode(message));
switch (method) {
case 'hex': {
return Array.from(new Uint8Array(buffer))
.map((byte) => byte.toString(16).padStart(2, '0'))
.join('');
}
case 'base64': {
return bufferToB64(buffer);
}
default: {
throw (0, typeGuards_1.neverGuard)(method, `Unhandled sign method: "${method}"`);
}
}
});
}
/**
* Sign a message, with a secret, using the Web Crypto API
* Automatically detects key type (HMAC vs RSA) and uses appropriate signing method
* RSA keys use base64 encoding, HMAC keys use hex encoding (for backwards compatibility)
*/
function signMessage(message_1, secret_1, method_1) {
return __awaiter(this, arguments, void 0, function* (message, secret, method, algorithm = 'SHA-256') {
const encoder = new TextEncoder();
const signKeyType = getSignKeyType(secret);
// Automatically determine encoding method based on key type if not specified
const encodeMethod = method || (signKeyType === 'RSASSA-PKCS1-v1_5' ? 'base64' : 'hex');
const key = yield importKey(secret, signKeyType, algorithm, encoder);
const buffer = yield globalThis.crypto.subtle.sign({ name: signKeyType }, key, encoder.encode(message));
switch (encodeMethod) {
case 'hex': {
return Array.from(new Uint8Array(buffer))
.map((byte) => byte.toString(16).padStart(2, '0'))
.join('');
}
case 'base64': {
return bufferToB64(buffer);
}
default: {
throw (0, typeGuards_1.neverGuard)(encodeMethod, `Unhandled sign method: "${encodeMethod}"`);
}
}
});
}
/**
* Sign binary data (Buffer/Uint8Array) with a secret, using the Web Crypto API
* Automatically detects key type (HMAC vs RSA) and uses appropriate signing method
* RSA keys use base64 encoding, HMAC keys use hex encoding (for backwards compatibility)
*
* Note: This function works in both Node.js and browser environments.
* In Node.js, you can pass a Buffer. In browsers, pass Uint8Array.
*/
function signBinaryData(data_1, secret_1, method_1) {
return __awaiter(this, arguments, void 0, function* (data, secret, method, algorithm = 'SHA-256') {
const encoder = new TextEncoder();
const signKeyType = getSignKeyType(secret);
// Automatically determine encoding method based on key type if not specified
const encodeMethod = method || (signKeyType === 'RSASSA-PKCS1-v1_5' ? 'base64' : 'hex');
const key = yield importKey(secret, signKeyType, algorithm, encoder);
// Convert to Uint8Array for Web Crypto API compatibility
// Buffer is a subclass of Uint8Array in Node.js, but we need a proper Uint8Array
// with ArrayBuffer (not ArrayBufferLike) to satisfy the BufferSource type constraint
const dataArray = Uint8Array.from(data);
const buffer = yield globalThis.crypto.subtle.sign({ name: signKeyType }, key, dataArray);
switch (encodeMethod) {
case 'hex': {
return Array.from(new Uint8Array(buffer))
.map((byte) => byte.toString(16).padStart(2, '0'))
.join('');
}
case 'base64': {
return bufferToB64(buffer);
}
default: {
throw (0, typeGuards_1.neverGuard)(encodeMethod, `Unhandled sign method: "${encodeMethod}"`);
}
}
});
}
function checkWebCryptoAPISupported() {
if (!globalThis.crypto) {
throw new Error(`Web Crypto API unavailable. Authentication will not work.
Are you using an old Node.js release? Refer to the current Node.js LTS version. Node.js v18 reached end of life in April 2025! You should be using Node LTS or newer (v22 or above)!
If you prefer to continue using an outdated Node.js version, check github for an example on using the node:crypto module for sign instead:
https://github.com/tiagosiebler/bybit-api/blob/master/examples/fasterHmacSign.ts
`);
}
}
//# sourceMappingURL=webCryptoAPI.js.map