@drift-labs/sdk-browser
Version:
SDK for Drift Protocol
160 lines (159 loc) • 6.9 kB
JavaScript
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.fastDecode = exports.restingOrderBeet = exports.orderIdBeet = void 0;
const phoenix_sdk_1 = require("@ellipsis-labs/phoenix-sdk");
const beet = __importStar(require("@metaplex-foundation/beet"));
exports.orderIdBeet = new beet.BeetArgsStruct([
['priceInTicks', beet.u64],
['orderSequenceNumber', beet.u64],
], 'fIFOOrderId');
exports.restingOrderBeet = new beet.BeetArgsStruct([
['traderIndex', beet.u64],
['numBaseLots', beet.u64],
['lastValidSlot', beet.u64],
['lastValidUnixTimestampInSeconds', beet.u64],
], 'fIFORestingOrder');
function deserializeRedBlackTree(data, keyDeserializer, valueDeserializer) {
const tree = new Map();
const treeNodes = deserializeRedBlackTreeNodes(data, keyDeserializer, valueDeserializer);
const nodes = treeNodes[0];
const freeNodes = treeNodes[1];
for (const [index, [key, value]] of nodes.entries()) {
if (!freeNodes.has(index)) {
tree.set(key, value);
}
}
return tree;
}
function deserializeRedBlackTreeNodes(data, keyDeserializer, valueDeserializer) {
let offset = 0;
const keySize = keyDeserializer.byteSize;
const valueSize = valueDeserializer.byteSize;
const nodes = new Array();
// Skip RBTree header
offset += 16;
// Skip node allocator size
offset += 8;
const bumpIndex = data.readInt32LE(offset);
offset += 4;
let freeListHead = data.readInt32LE(offset);
offset += 4;
const freeListPointers = new Array();
for (let index = 0; offset < data.length && index < bumpIndex - 1; index++) {
const registers = new Array();
for (let i = 0; i < 4; i++) {
registers.push(data.readInt32LE(offset)); // skip padding
offset += 4;
}
const [key] = keyDeserializer.deserialize(data.subarray(offset, offset + keySize));
offset += keySize;
const [value] = valueDeserializer.deserialize(data.subarray(offset, offset + valueSize));
offset += valueSize;
nodes.push([key, value]);
freeListPointers.push([index, registers[0]]);
}
const freeNodes = new Set();
let indexToRemove = freeListHead - 1;
let counter = 0;
// If there's an infinite loop here, that means that the state is corrupted
while (freeListHead < bumpIndex) {
// We need to subtract 1 because the node allocator is 1-indexed
const next = freeListPointers[freeListHead - 1];
[indexToRemove, freeListHead] = next;
freeNodes.add(indexToRemove);
counter += 1;
if (counter > bumpIndex) {
throw new Error('Infinite loop detected');
}
}
return [nodes, freeNodes];
}
const fastDecode = (buffer) => {
let offset = phoenix_sdk_1.marketHeaderBeet.byteSize;
const [header] = phoenix_sdk_1.marketHeaderBeet.deserialize(buffer.subarray(0, offset));
const paddingLen = 8 * 32;
let remaining = buffer.subarray(offset + paddingLen);
offset = 0;
const baseLotsPerBaseUnit = Number(remaining.readBigUInt64LE(offset));
offset += 8;
const quoteLotsPerBaseUnitPerTick = Number(remaining.readBigUInt64LE(offset));
offset += 8;
const sequenceNumber = Number(remaining.readBigUInt64LE(offset));
offset += 8;
const takerFeeBps = Number(remaining.readBigUInt64LE(offset));
offset += 8;
const collectedQuoteLotFees = Number(remaining.readBigUInt64LE(offset));
offset += 8;
const unclaimedQuoteLotFees = Number(remaining.readBigUInt64LE(offset));
offset += 8;
remaining = remaining.subarray(offset);
const totalNumBids = (0, phoenix_sdk_1.toNum)(header.marketSizeParams.bidsSize);
const totalNumAsks = (0, phoenix_sdk_1.toNum)(header.marketSizeParams.asksSize);
const totalBidsSize = 16 +
16 +
(16 + exports.orderIdBeet.byteSize + exports.restingOrderBeet.byteSize) * totalNumBids;
const totalAsksSize = 16 +
16 +
(16 + exports.orderIdBeet.byteSize + exports.restingOrderBeet.byteSize) * totalNumAsks;
offset = 0;
const bidBuffer = remaining.subarray(offset, offset + totalBidsSize);
offset += totalBidsSize;
const askBuffer = remaining.subarray(offset, offset + totalAsksSize);
const bidsUnsorted = deserializeRedBlackTree(bidBuffer, exports.orderIdBeet, exports.restingOrderBeet);
const asksUnsorted = deserializeRedBlackTree(askBuffer, exports.orderIdBeet, exports.restingOrderBeet);
const bids = [...bidsUnsorted].sort((a, b) => {
const priceComparison = (0, phoenix_sdk_1.sign)((0, phoenix_sdk_1.toBN)(b[0].priceInTicks).sub((0, phoenix_sdk_1.toBN)(a[0].priceInTicks)));
if (priceComparison !== 0) {
return priceComparison;
}
return (0, phoenix_sdk_1.sign)((0, phoenix_sdk_1.getUiOrderSequenceNumber)(a[0]).sub((0, phoenix_sdk_1.getUiOrderSequenceNumber)(b[0])));
});
const asks = [...asksUnsorted].sort((a, b) => {
const priceComparison = (0, phoenix_sdk_1.sign)((0, phoenix_sdk_1.toBN)(a[0].priceInTicks).sub((0, phoenix_sdk_1.toBN)(b[0].priceInTicks)));
if (priceComparison !== 0) {
return priceComparison;
}
return (0, phoenix_sdk_1.sign)((0, phoenix_sdk_1.getUiOrderSequenceNumber)(a[0]).sub((0, phoenix_sdk_1.getUiOrderSequenceNumber)(b[0])));
});
const traders = new Map();
const traderPubkeyToTraderIndex = new Map();
const traderIndexToTraderPubkey = new Map();
return {
header,
baseLotsPerBaseUnit,
quoteLotsPerBaseUnitPerTick,
sequenceNumber,
takerFeeBps,
collectedQuoteLotFees,
unclaimedQuoteLotFees,
bids,
asks,
traders,
traderPubkeyToTraderIndex,
traderIndexToTraderPubkey,
};
};
exports.fastDecode = fastDecode;
;