@drift-labs/sdk
Version:
SDK for Drift Protocol
351 lines (350 loc) • 12.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.decodeUser = void 0;
const anchor_1 = require("../isomorphic/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 isolatedPositionScaledBalance = readUnsignedBigInt64LE(buffer, offset + 72);
const openOrders = buffer.readUInt8(offset + 94);
const positionFlag = buffer.readUInt8(offset + 95);
if (baseAssetAmount.eq(numericConstants_1.ZERO) &&
openOrders === 0 &&
quoteAssetAmount.eq(numericConstants_1.ZERO) &&
lpShares.eq(numericConstants_1.ZERO) &&
isolatedPositionScaledBalance.eq(numericConstants_1.ZERO) &&
!((positionFlag &
(types_1.PositionFlag.BeingLiquidated | types_1.PositionFlag.Bankruptcy)) >
0)) {
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 += 24;
const lastQuoteAssetAmountPerLp = readSignedBigInt64LE(buffer, offset);
offset += 8;
offset += 2; // skip padding[u8; 2]
const maxMarginRatio = buffer.readUInt16LE(offset); // offset+90
offset += 2;
const marketIndex = buffer.readUInt16LE(offset); // offset+92
offset += 4; // advance past marketIndex(2) + openOrders(1) + positionFlag(1)
perpPositions.push({
lastCumulativeFundingRate,
baseAssetAmount,
quoteAssetAmount,
quoteBreakEvenAmount,
quoteEntryAmount,
openBids,
openAsks,
settledPnl,
lpShares,
remainderBaseAssetAmount: 0,
lastQuoteAssetAmountPerLp,
marketIndex,
openOrders,
maxMarginRatio,
positionFlag,
isolatedPositionScaledBalance,
});
}
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;
offset += 1; // marginMode (removed)
const poolId = buffer.readUint8(offset);
offset += 1;
offset += 3; // padding
const lastFuelBonusUpdateTs = buffer.readUint32LE(offset);
offset += 4;
const specialUserStatus = buffer.readUInt8(offset);
offset += 1;
offset += 11; // padding
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,
poolId,
lastFuelBonusUpdateTs,
specialUserStatus,
};
}
exports.decodeUser = decodeUser;