@drift-labs/sdk
Version:
SDK for Drift Protocol
360 lines (359 loc) • 12.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.decodeUser = void 0;
const anchor_1 = require("@coral-xyz/anchor");
const types_1 = require("../types");
const web3_js_1 = require("@solana/web3.js");
const numericConstants_1 = require("../constants/numericConstants");
function readUnsignedBigInt64LE(buffer, offset) {
return new anchor_1.BN(buffer.subarray(offset, offset + 8), 10, 'le');
}
function readSignedBigInt64LE(buffer, offset) {
const unsignedValue = new anchor_1.BN(buffer.subarray(offset, offset + 8), 10, 'le');
if (unsignedValue.testn(63)) {
const inverted = unsignedValue.notn(64).addn(1);
return inverted.neg();
}
else {
return unsignedValue;
}
}
function decodeUser(buffer) {
let offset = 8;
const authority = new web3_js_1.PublicKey(buffer.slice(offset, offset + 32));
offset += 32;
const delegate = new web3_js_1.PublicKey(buffer.slice(offset, offset + 32));
offset += 32;
const name = [];
for (let i = 0; i < 32; i++) {
name.push(buffer.readUint8(offset + i));
}
offset += 32;
const spotPositions = [];
for (let i = 0; i < 8; i++) {
const scaledBalance = readUnsignedBigInt64LE(buffer, offset);
const openOrders = buffer.readUInt8(offset + 35);
if (scaledBalance.eq(numericConstants_1.ZERO) && openOrders === 0) {
offset += 40;
continue;
}
offset += 8;
const openBids = readSignedBigInt64LE(buffer, offset);
offset += 8;
const openAsks = readSignedBigInt64LE(buffer, offset);
offset += 8;
const cumulativeDeposits = readSignedBigInt64LE(buffer, offset);
offset += 8;
const marketIndex = buffer.readUInt16LE(offset);
offset += 2;
const balanceTypeNum = buffer.readUInt8(offset);
let balanceType;
if (balanceTypeNum === 0) {
balanceType = types_1.SpotBalanceType.DEPOSIT;
}
else {
balanceType = types_1.SpotBalanceType.BORROW;
}
offset += 6;
spotPositions.push({
scaledBalance,
openBids,
openAsks,
cumulativeDeposits,
marketIndex,
balanceType,
openOrders,
});
}
const perpPositions = [];
for (let i = 0; i < 8; i++) {
const baseAssetAmount = readSignedBigInt64LE(buffer, offset + 8);
const quoteAssetAmount = readSignedBigInt64LE(buffer, offset + 16);
const lpShares = readUnsignedBigInt64LE(buffer, offset + 64);
const openOrders = buffer.readUInt8(offset + 94);
if (baseAssetAmount.eq(numericConstants_1.ZERO) &&
openOrders === 0 &&
quoteAssetAmount.eq(numericConstants_1.ZERO) &&
lpShares.eq(numericConstants_1.ZERO)) {
offset += 96;
continue;
}
const lastCumulativeFundingRate = readSignedBigInt64LE(buffer, offset);
offset += 24;
const quoteBreakEvenAmount = readSignedBigInt64LE(buffer, offset);
offset += 8;
const quoteEntryAmount = readSignedBigInt64LE(buffer, offset);
offset += 8;
const openBids = readSignedBigInt64LE(buffer, offset);
offset += 8;
const openAsks = readSignedBigInt64LE(buffer, offset);
offset += 8;
const settledPnl = readSignedBigInt64LE(buffer, offset);
offset += 16;
const lastBaseAssetAmountPerLp = readSignedBigInt64LE(buffer, offset);
offset += 8;
const lastQuoteAssetAmountPerLp = readSignedBigInt64LE(buffer, offset);
offset += 8;
const maxMarginRatio = buffer.readUInt16LE(offset);
offset += 4;
const marketIndex = buffer.readUInt16LE(offset);
offset += 3;
const perLpBase = buffer.readUInt8(offset);
offset += 1;
perpPositions.push({
lastCumulativeFundingRate,
baseAssetAmount,
quoteAssetAmount,
quoteBreakEvenAmount,
quoteEntryAmount,
openBids,
openAsks,
settledPnl,
lpShares,
remainderBaseAssetAmount: 0,
lastBaseAssetAmountPerLp,
lastQuoteAssetAmountPerLp,
marketIndex,
openOrders,
perLpBase,
maxMarginRatio,
});
}
const orders = [];
for (let i = 0; i < 32; i++) {
// skip order if it's not open
if (buffer.readUint8(offset + 82) !== 1) {
offset += 96;
continue;
}
const slot = readUnsignedBigInt64LE(buffer, offset);
offset += 8;
const price = readUnsignedBigInt64LE(buffer, offset);
offset += 8;
const baseAssetAmount = readUnsignedBigInt64LE(buffer, offset);
offset += 8;
const baseAssetAmountFilled = readUnsignedBigInt64LE(buffer, offset);
offset += 8;
const quoteAssetAmountFilled = readUnsignedBigInt64LE(buffer, offset);
offset += 8;
const triggerPrice = readUnsignedBigInt64LE(buffer, offset);
offset += 8;
const auctionStartPrice = readSignedBigInt64LE(buffer, offset);
offset += 8;
const auctionEndPrice = readSignedBigInt64LE(buffer, offset);
offset += 8;
const maxTs = readSignedBigInt64LE(buffer, offset);
offset += 8;
const oraclePriceOffset = buffer.readInt32LE(offset);
offset += 4;
const orderId = buffer.readUInt32LE(offset);
offset += 4;
const marketIndex = buffer.readUInt16LE(offset);
offset += 2;
const orderStatusNum = buffer.readUInt8(offset);
let status;
if (orderStatusNum === 0) {
status = types_1.OrderStatus.INIT;
}
else if (orderStatusNum === 1) {
status = types_1.OrderStatus.OPEN;
}
offset += 1;
const orderTypeNum = buffer.readUInt8(offset);
let orderType;
if (orderTypeNum === 0) {
orderType = types_1.OrderType.MARKET;
}
else if (orderTypeNum === 1) {
orderType = types_1.OrderType.LIMIT;
}
else if (orderTypeNum === 2) {
orderType = types_1.OrderType.TRIGGER_MARKET;
}
else if (orderTypeNum === 3) {
orderType = types_1.OrderType.TRIGGER_LIMIT;
}
else if (orderTypeNum === 4) {
orderType = types_1.OrderType.ORACLE;
}
offset += 1;
const marketTypeNum = buffer.readUInt8(offset);
let marketType;
if (marketTypeNum === 0) {
marketType = types_1.MarketType.SPOT;
}
else {
marketType = types_1.MarketType.PERP;
}
offset += 1;
const userOrderId = buffer.readUint8(offset);
offset += 1;
const existingPositionDirectionNum = buffer.readUInt8(offset);
let existingPositionDirection;
if (existingPositionDirectionNum === 0) {
existingPositionDirection = types_1.PositionDirection.LONG;
}
else {
existingPositionDirection = types_1.PositionDirection.SHORT;
}
offset += 1;
const positionDirectionNum = buffer.readUInt8(offset);
let direction;
if (positionDirectionNum === 0) {
direction = types_1.PositionDirection.LONG;
}
else {
direction = types_1.PositionDirection.SHORT;
}
offset += 1;
const reduceOnly = buffer.readUInt8(offset) === 1;
offset += 1;
const postOnly = buffer.readUInt8(offset) === 1;
offset += 1;
const immediateOrCancel = buffer.readUInt8(offset) === 1;
offset += 1;
const triggerConditionNum = buffer.readUInt8(offset);
let triggerCondition;
if (triggerConditionNum === 0) {
triggerCondition = types_1.OrderTriggerCondition.ABOVE;
}
else if (triggerConditionNum === 1) {
triggerCondition = types_1.OrderTriggerCondition.BELOW;
}
else if (triggerConditionNum === 2) {
triggerCondition = types_1.OrderTriggerCondition.TRIGGERED_ABOVE;
}
else if (triggerConditionNum === 3) {
triggerCondition = types_1.OrderTriggerCondition.TRIGGERED_BELOW;
}
offset += 1;
const auctionDuration = buffer.readUInt8(offset);
offset += 1;
const postedSlotTail = buffer.readUint8(offset);
offset += 1;
const bitFlags = buffer.readUint8(offset);
offset += 1;
offset += 1; // padding
orders.push({
slot,
price,
baseAssetAmount,
quoteAssetAmount: undefined,
baseAssetAmountFilled,
quoteAssetAmountFilled,
triggerPrice,
auctionStartPrice,
auctionEndPrice,
maxTs,
oraclePriceOffset,
orderId,
marketIndex,
status,
orderType,
marketType,
userOrderId,
existingPositionDirection,
direction,
reduceOnly,
postOnly,
immediateOrCancel,
triggerCondition,
auctionDuration,
bitFlags,
postedSlotTail,
});
}
const lastAddPerpLpSharesTs = readSignedBigInt64LE(buffer, offset);
offset += 8;
const totalDeposits = readUnsignedBigInt64LE(buffer, offset);
offset += 8;
const totalWithdraws = readUnsignedBigInt64LE(buffer, offset);
offset += 8;
const totalSocialLoss = readUnsignedBigInt64LE(buffer, offset);
offset += 8;
const settledPerpPnl = readSignedBigInt64LE(buffer, offset);
offset += 8;
const cumulativeSpotFees = readSignedBigInt64LE(buffer, offset);
offset += 8;
const cumulativePerpFunding = readSignedBigInt64LE(buffer, offset);
offset += 8;
const liquidationMarginFreed = readUnsignedBigInt64LE(buffer, offset);
offset += 8;
const lastActiveSlot = readUnsignedBigInt64LE(buffer, offset);
offset += 8;
const nextOrderId = buffer.readUInt32LE(offset);
offset += 4;
const maxMarginRatio = buffer.readUInt32LE(offset);
offset += 4;
const nextLiquidationId = buffer.readUInt16LE(offset);
offset += 2;
const subAccountId = buffer.readUInt16LE(offset);
offset += 2;
const status = buffer.readUInt8(offset);
offset += 1;
const isMarginTradingEnabled = buffer.readUInt8(offset) === 1;
offset += 1;
const idle = buffer.readUInt8(offset) === 1;
offset += 1;
const openOrders = buffer.readUInt8(offset);
offset += 1;
const hasOpenOrder = buffer.readUInt8(offset) === 1;
offset += 1;
const openAuctions = buffer.readUInt8(offset);
offset += 1;
const hasOpenAuction = buffer.readUInt8(offset) === 1;
offset += 1;
let marginMode;
const marginModeNum = buffer.readUInt8(offset);
if (marginModeNum === 0) {
marginMode = types_1.MarginMode.DEFAULT;
}
else if (marginModeNum === 1) {
marginMode = types_1.MarginMode.HIGH_LEVERAGE;
}
else if (marginModeNum === 2) {
marginMode = types_1.MarginMode.HIGH_LEVERAGE_MAINTENANCE;
}
else {
console.error(`Detected unknown margin mode: ${marginModeNum}. Please update @drift-labs/sdk for latest IDL.`);
marginMode = types_1.MarginMode.DEFAULT;
}
offset += 1;
const poolId = buffer.readUint8(offset);
offset += 1;
offset += 3; // padding
const lastFuelBonusUpdateTs = buffer.readUint32LE(offset);
offset += 4;
return {
authority,
delegate,
name,
spotPositions,
perpPositions,
orders,
lastAddPerpLpSharesTs,
totalDeposits,
totalWithdraws,
totalSocialLoss,
settledPerpPnl,
cumulativeSpotFees,
cumulativePerpFunding,
liquidationMarginFreed,
lastActiveSlot,
nextOrderId,
maxMarginRatio,
nextLiquidationId,
subAccountId,
status,
isMarginTradingEnabled,
idle,
openOrders,
hasOpenOrder,
openAuctions,
hasOpenAuction,
marginMode,
poolId,
lastFuelBonusUpdateTs,
};
}
exports.decodeUser = decodeUser;