@thespidercode/openbook-swap
Version:
Ready-to-use swap tool using Openbook DEX
129 lines (128 loc) • 5.27 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.EVENT_QUEUE_LAYOUT = exports.REQUEST_QUEUE_LAYOUT = exports.decodeEventQueue = exports.decodeRequestQueue = exports.decodeEventsSince = void 0;
const buffer_layout_1 = require("buffer-layout");
const layout_1 = require("./layout");
const REQUEST_QUEUE_HEADER = (0, buffer_layout_1.struct)([
(0, buffer_layout_1.blob)(5),
(0, layout_1.accountFlagsLayout)('accountFlags'),
(0, buffer_layout_1.u32)('head'),
(0, layout_1.zeros)(4),
(0, buffer_layout_1.u32)('count'),
(0, layout_1.zeros)(4),
(0, buffer_layout_1.u32)('nextSeqNum'),
(0, layout_1.zeros)(4),
]);
const REQUEST_FLAGS = (0, buffer_layout_1.bits)((0, buffer_layout_1.u8)(), false, 'requestFlags');
REQUEST_FLAGS.addBoolean('newOrder');
REQUEST_FLAGS.addBoolean('cancelOrder');
REQUEST_FLAGS.addBoolean('bid');
REQUEST_FLAGS.addBoolean('postOnly');
REQUEST_FLAGS.addBoolean('ioc');
const REQUEST = (0, buffer_layout_1.struct)([
REQUEST_FLAGS,
(0, buffer_layout_1.u8)('openOrdersSlot'),
(0, buffer_layout_1.u8)('feeTier'),
(0, buffer_layout_1.blob)(5),
(0, layout_1.u64)('maxBaseSizeOrCancelId'),
(0, layout_1.u64)('nativeQuoteQuantityLocked'),
(0, layout_1.u128)('orderId'),
(0, layout_1.publicKeyLayout)('openOrders'),
(0, layout_1.u64)('clientOrderId'),
]);
const EVENT_QUEUE_HEADER = (0, buffer_layout_1.struct)([
(0, buffer_layout_1.blob)(5),
(0, layout_1.accountFlagsLayout)('accountFlags'),
(0, buffer_layout_1.u32)('head'),
(0, layout_1.zeros)(4),
(0, buffer_layout_1.u32)('count'),
(0, layout_1.zeros)(4),
(0, buffer_layout_1.u32)('seqNum'),
(0, layout_1.zeros)(4),
]);
const EVENT_FLAGS = (0, buffer_layout_1.bits)((0, buffer_layout_1.u8)(), false, 'eventFlags');
EVENT_FLAGS.addBoolean('fill');
EVENT_FLAGS.addBoolean('out');
EVENT_FLAGS.addBoolean('bid');
EVENT_FLAGS.addBoolean('maker');
const EVENT = (0, buffer_layout_1.struct)([
EVENT_FLAGS,
(0, buffer_layout_1.u8)('openOrdersSlot'),
(0, buffer_layout_1.u8)('feeTier'),
(0, buffer_layout_1.blob)(5),
(0, layout_1.u64)('nativeQuantityReleased'),
(0, layout_1.u64)('nativeQuantityPaid'),
(0, layout_1.u64)('nativeFeeOrRebate'),
(0, layout_1.u128)('orderId'),
(0, layout_1.publicKeyLayout)('openOrders'),
(0, layout_1.u64)('clientOrderId'),
]);
function decodeQueueItem(headerLayout, nodeLayout, buffer, nodeIndex) {
return nodeLayout.decode(buffer, headerLayout.span + nodeIndex * nodeLayout.span);
}
function decodeQueue(headerLayout, nodeLayout, buffer, history) {
const header = headerLayout.decode(buffer);
const allocLen = Math.floor((buffer.length - headerLayout.span) / nodeLayout.span);
const nodes = [];
if (history) {
for (let i = 0; i < Math.min(history, allocLen); ++i) {
const nodeIndex = (header.head + header.count + allocLen - 1 - i) % allocLen;
nodes.push(decodeQueueItem(headerLayout, nodeLayout, buffer, nodeIndex));
}
}
else {
for (let i = 0; i < header.count; ++i) {
const nodeIndex = (header.head + i) % allocLen;
nodes.push(decodeQueueItem(headerLayout, nodeLayout, buffer, nodeIndex));
}
}
return { header, nodes };
}
function decodeEventsSince(buffer, lastSeqNum) {
const header = EVENT_QUEUE_HEADER.decode(buffer);
const allocLen = Math.floor((buffer.length - EVENT_QUEUE_HEADER.span) / EVENT.span);
// calculate number of missed events
// account for u32 & ringbuffer overflows
const modulo32Uint = 0x100000000;
let missedEvents = (header.seqNum - lastSeqNum + modulo32Uint) % modulo32Uint;
if (missedEvents > allocLen) {
missedEvents = allocLen - 1;
}
const startSeq = (header.seqNum - missedEvents + modulo32Uint) % modulo32Uint;
// define boundary indexes in ring buffer [start;end)
const endIndex = (header.head + header.count) % allocLen;
const startIndex = (endIndex - missedEvents + allocLen) % allocLen;
const results = [];
for (let i = 0; i < missedEvents; ++i) {
const nodeIndex = (startIndex + i) % allocLen;
const event = decodeQueueItem(EVENT_QUEUE_HEADER, EVENT, buffer, nodeIndex);
event.seqNum = (startSeq + i) % modulo32Uint;
results.push(event);
}
return results;
}
exports.decodeEventsSince = decodeEventsSince;
function decodeRequestQueue(buffer, history) {
const { header, nodes } = decodeQueue(REQUEST_QUEUE_HEADER, REQUEST, buffer, history);
if (!header.accountFlags.initialized || !header.accountFlags.requestQueue) {
throw new Error('Invalid requests queue');
}
return nodes;
}
exports.decodeRequestQueue = decodeRequestQueue;
function decodeEventQueue(buffer, history) {
const { header, nodes } = decodeQueue(EVENT_QUEUE_HEADER, EVENT, buffer, history);
if (!header.accountFlags.initialized || !header.accountFlags.eventQueue) {
throw new Error('Invalid events queue');
}
return nodes;
}
exports.decodeEventQueue = decodeEventQueue;
exports.REQUEST_QUEUE_LAYOUT = {
HEADER: REQUEST_QUEUE_HEADER,
NODE: REQUEST,
};
exports.EVENT_QUEUE_LAYOUT = {
HEADER: EVENT_QUEUE_HEADER,
NODE: EVENT,
};