squash
This commit is contained in:
178
example/client.ts
Normal file
178
example/client.ts
Normal file
@@ -0,0 +1,178 @@
|
||||
import fetch from "node-fetch";
|
||||
import {
|
||||
BulkAccountLoader,
|
||||
calculateAskPrice,
|
||||
calculateBidPrice,
|
||||
convertToNumber,
|
||||
DLOB,
|
||||
DLOBOrders,
|
||||
DLOBOrdersCoder,
|
||||
DriftClient,
|
||||
EventSubscriber,
|
||||
getVariant,
|
||||
initialize,
|
||||
MarketType,
|
||||
OrderActionRecord,
|
||||
OrderRecord,
|
||||
PRICE_PRECISION,
|
||||
Wallet,
|
||||
WrappedEvent,
|
||||
} from "@drift-labs/sdk";
|
||||
import { Connection, Keypair, PublicKey } from "@solana/web3.js";
|
||||
|
||||
/********** SET THESE **********/
|
||||
|
||||
const dlobServerURL = "http://localhost:6969/orders/idl";
|
||||
// const dlobServerURL = "https://dlob.drift.trade/orders/idl";
|
||||
// const rpcEndpoint = "https://solana-api.syndica.io/access-token/eqLMxrnnLgz5eSGKsPIaFK0dSvJeYCNviWhnIgaAH3YdM0K6C6tQdctk94Rb9mCX/rpc";
|
||||
// const driftEnv = "mainnet-beta";
|
||||
|
||||
// const dlobServerURL = "https://master.dlob.drift.trade/orders/idl";
|
||||
const rpcEndpoint = "https://api.devnet.solana.com";
|
||||
const driftEnv = "devnet";
|
||||
|
||||
const initializedKey = [1, 2, 3, 4, 5]; // private key to initialize driftClient
|
||||
|
||||
|
||||
/*******************************/
|
||||
|
||||
//@ts-ignore
|
||||
const sdkConfig = initialize({ env: driftEnv });
|
||||
|
||||
const stateCommitment = 'confirmed';
|
||||
const keypair = Keypair.fromSecretKey(Uint8Array.from(initializedKey));
|
||||
const wallet = new Wallet(keypair);
|
||||
const connection = new Connection(rpcEndpoint, stateCommitment);
|
||||
const driftClientPublicKey = new PublicKey(sdkConfig.DRIFT_PROGRAM_ID);
|
||||
|
||||
|
||||
/********** initializing driftClient as usual **********/
|
||||
const bulkAccountLoader = new BulkAccountLoader(
|
||||
connection,
|
||||
stateCommitment,
|
||||
1000
|
||||
);
|
||||
const driftClient = new DriftClient({
|
||||
connection,
|
||||
wallet,
|
||||
programID: driftClientPublicKey,
|
||||
accountSubscription: {
|
||||
type: 'polling',
|
||||
accountLoader: bulkAccountLoader,
|
||||
},
|
||||
env: driftEnv,
|
||||
userStats: true,
|
||||
});
|
||||
const eventSubscriber = new EventSubscriber(connection, driftClient.program, {
|
||||
maxTx: 8192,
|
||||
maxEventsPerType: 8192,
|
||||
orderBy: 'blockchain',
|
||||
orderDir: 'desc',
|
||||
commitment: stateCommitment,
|
||||
logProviderConfig: {
|
||||
type: 'polling',
|
||||
frequency: 1000,
|
||||
// type: 'websocket',
|
||||
},
|
||||
});
|
||||
|
||||
let maxDlobSlot = 0;
|
||||
const dlob = new DLOB();
|
||||
|
||||
driftClient.subscribe().then((success) => {
|
||||
if (!success) {
|
||||
throw new Error("DriftClient subscription failed");
|
||||
}
|
||||
eventSubscriber.subscribe().then((success) => {
|
||||
if (!success) {
|
||||
throw new Error("EventSubscriber subscription failed");
|
||||
}
|
||||
|
||||
/********** Example for updating dlob on events **********/
|
||||
|
||||
eventSubscriber.eventEmitter.on('newEvent', async (event: WrappedEvent<any>) => {
|
||||
// NOTE: only apply events if they're newer than the last
|
||||
// only apply new events if they're newer than the last slot we've seen
|
||||
if (event.eventType === "OrderRecord") {
|
||||
const record = event as OrderRecord;
|
||||
if (maxDlobSlot > 0 && event.slot > maxDlobSlot) {
|
||||
dlob.handleOrderRecord(record);
|
||||
console.log(`Handled OrderRecord event for market ${record.order.marketIndex}`);
|
||||
printDlob(record.order.marketIndex, dlob);
|
||||
}
|
||||
} else if (event.eventType === "OrderActionRecord") {
|
||||
const record = event as OrderActionRecord;
|
||||
if (maxDlobSlot > 0 && event.slot > maxDlobSlot) {
|
||||
dlob.handleOrderActionRecord(record);
|
||||
console.log(`Handled OrderActionRecord event for market ${record.marketIndex}, action: ${getVariant(record.action)} ${getVariant(record.actionExplanation)}`);
|
||||
printDlob(record.marketIndex, dlob);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
doDlobDemo();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
/********** Example for initializing dlob **********/
|
||||
|
||||
function getLatestSlotFromOrders(dlobOrders: DLOBOrders): number {
|
||||
return Math.max(...dlobOrders.map((dlobOrder) => dlobOrder.order.slot.toNumber()));
|
||||
}
|
||||
|
||||
function printDlob(marketIndex: number, dlob: DLOB) {
|
||||
const currSlot = bulkAccountLoader.mostRecentSlot;
|
||||
const marketAccount = driftClient.getPerpMarketAccount(marketIndex);
|
||||
const oracle = driftClient.getOracleDataForPerpMarket(marketIndex);
|
||||
|
||||
// you can also set vBid and vAsk to undefined to omit the vAMM price node from bids and asks
|
||||
const vBid = calculateBidPrice(marketAccount!, oracle);
|
||||
const vAsk = calculateAskPrice(marketAccount!, oracle);
|
||||
|
||||
const dlobBids = dlob.getBids(marketIndex, vBid, currSlot, MarketType.PERP, oracle);
|
||||
const dlobAsks = dlob.getAsks(marketIndex, vAsk, currSlot, MarketType.PERP, oracle);
|
||||
|
||||
console.log(`DLOB for market ${marketIndex}:`);
|
||||
console.log("Asks");
|
||||
const dlobAsksArray = Array(...dlobAsks).reverse();
|
||||
let countAsks = dlobAsksArray.length;
|
||||
for (const ask of dlobAsksArray) {
|
||||
const isVamm = ask.isVammNode();
|
||||
console.log(` [${countAsks}] ${isVamm ? "vAMMNode" : getVariant(ask.order?.orderType)} ${convertToNumber(ask.getPrice(oracle, currSlot), PRICE_PRECISION)}`);
|
||||
countAsks--;
|
||||
}
|
||||
|
||||
console.log("Bids");
|
||||
let countBids = 0;
|
||||
for (const bid of dlobBids) {
|
||||
const isVamm = bid.isVammNode();
|
||||
console.log(` [${countBids}] ${isVamm ? "vAMMNode" : getVariant(bid.order?.orderType)} ${convertToNumber(bid.getPrice(oracle, currSlot), PRICE_PRECISION)}`);
|
||||
countBids++;
|
||||
}
|
||||
|
||||
console.log("");
|
||||
}
|
||||
|
||||
function doDlobDemo() {
|
||||
const dlobCoder = DLOBOrdersCoder.create();
|
||||
fetch(dlobServerURL)
|
||||
.then(
|
||||
(r) => {
|
||||
r.arrayBuffer().then((b) => {
|
||||
const dlobOrders = dlobCoder.decode(Buffer.from(b));
|
||||
// console.log(JSON.stringify(dlobOrders, null, 2));
|
||||
|
||||
console.log(`dlob orders count: ${dlobOrders.length}`);
|
||||
dlob.initFromOrders(dlobOrders);
|
||||
|
||||
maxDlobSlot = getLatestSlotFromOrders(dlobOrders);
|
||||
console.log(`maxSlot from DLOB init orders: ${maxDlobSlot}`);
|
||||
|
||||
console.log("Initialized DLOb from server");
|
||||
printDlob(0, dlob);
|
||||
printDlob(1, dlob);
|
||||
printDlob(2, dlob);
|
||||
});
|
||||
});
|
||||
}
|
||||
203
example/clientWithSlot.ts
Normal file
203
example/clientWithSlot.ts
Normal file
@@ -0,0 +1,203 @@
|
||||
/**
|
||||
* Usage:
|
||||
* ts-node clientWithSlot.ts
|
||||
*/
|
||||
|
||||
import fetch from "node-fetch";
|
||||
import {
|
||||
BulkAccountLoader,
|
||||
calculateAskPrice,
|
||||
calculateBidPrice,
|
||||
convertToNumber,
|
||||
DLOB,
|
||||
DLOBOrders,
|
||||
DLOBOrdersCoder,
|
||||
DriftClient,
|
||||
DriftClientSubscriptionConfig,
|
||||
EventSubscriber,
|
||||
getVariant,
|
||||
initialize,
|
||||
LogProviderConfig,
|
||||
MarketType,
|
||||
OrderActionRecord,
|
||||
OrderRecord,
|
||||
PRICE_PRECISION,
|
||||
Wallet,
|
||||
WrappedEvent,
|
||||
} from "@drift-labs/sdk";
|
||||
import { Connection, Keypair, PublicKey } from "@solana/web3.js";
|
||||
|
||||
/********** SET THESE **********/
|
||||
|
||||
// const dlobServerURL = "http://localhost:6969/orders/idlWithSlot";
|
||||
const dlobServerURL = "https://dlob.drift.trade/orders/idlWithSlot";
|
||||
const rpcEndpoint = "https://api.mainnet-beta.solana.com";
|
||||
const driftEnv = "mainnet-beta";
|
||||
|
||||
// const dlobServerURL = "https://master.dlob.drift.trade/orders/idlWithSlot";
|
||||
// const rpcEndpoint = "https://api.devnet.solana.com";
|
||||
// const driftEnv = "devnet";
|
||||
|
||||
const initializedKey = [1, 2, 3, 4, 5]; // private key to initialize driftClient
|
||||
const useWebsocket = true;
|
||||
const levelsToPrint = 10;
|
||||
|
||||
/*******************************/
|
||||
|
||||
//@ts-ignore
|
||||
const sdkConfig = initialize({ env: driftEnv });
|
||||
|
||||
const stateCommitment = 'confirmed';
|
||||
const keypair = Keypair.fromSecretKey(Uint8Array.from(initializedKey));
|
||||
const wallet = new Wallet(keypair);
|
||||
const connection = new Connection(rpcEndpoint, stateCommitment);
|
||||
const driftClientPublicKey = new PublicKey(sdkConfig.DRIFT_PROGRAM_ID);
|
||||
let lastSeenSlot = 0;
|
||||
|
||||
/********** initializing driftClient as usual **********/
|
||||
var accountSubscription: DriftClientSubscriptionConfig;
|
||||
var logProviderConfig: LogProviderConfig;
|
||||
if (useWebsocket) {
|
||||
accountSubscription = {
|
||||
type: 'websocket',
|
||||
};
|
||||
logProviderConfig = {
|
||||
type: 'websocket',
|
||||
};
|
||||
} else {
|
||||
accountSubscription = {
|
||||
type: 'polling',
|
||||
accountLoader: new BulkAccountLoader(
|
||||
connection,
|
||||
stateCommitment,
|
||||
10000
|
||||
),
|
||||
};
|
||||
logProviderConfig = {
|
||||
type: 'polling',
|
||||
frequency: 10000,
|
||||
};
|
||||
}
|
||||
const driftClient = new DriftClient({
|
||||
connection,
|
||||
wallet,
|
||||
programID: driftClientPublicKey,
|
||||
accountSubscription,
|
||||
env: driftEnv,
|
||||
userStats: true,
|
||||
});
|
||||
const eventSubscriber = new EventSubscriber(connection, driftClient.program, {
|
||||
maxTx: 8192,
|
||||
maxEventsPerType: 8192,
|
||||
orderBy: 'blockchain',
|
||||
orderDir: 'desc',
|
||||
commitment: stateCommitment,
|
||||
logProviderConfig,
|
||||
});
|
||||
|
||||
const maxDlobSlot = 0;
|
||||
const dlob = new DLOB();
|
||||
|
||||
driftClient.subscribe().then((success) => {
|
||||
if (!success) {
|
||||
throw new Error("DriftClient subscription failed");
|
||||
}
|
||||
eventSubscriber.subscribe().then((success) => {
|
||||
if (!success) {
|
||||
throw new Error("EventSubscriber subscription failed");
|
||||
}
|
||||
|
||||
/********** Example for updating dlob on events **********/
|
||||
|
||||
eventSubscriber.eventEmitter.on('newEvent', async (event: WrappedEvent<any>) => {
|
||||
// NOTE: only apply events if they're newer than the last
|
||||
// only apply new events if they're newer than the last slot we've seen
|
||||
lastSeenSlot = event.slot;
|
||||
if (event.eventType === "OrderRecord") {
|
||||
const record = event as OrderRecord;
|
||||
if (maxDlobSlot > 0 && event.slot > maxDlobSlot) {
|
||||
dlob.handleOrderRecord(record, event.slot);
|
||||
console.log(`Handled OrderRecord event for market ${record.order.marketIndex}`);
|
||||
printDlob(record.order.marketIndex, dlob);
|
||||
}
|
||||
} else if (event.eventType === "OrderActionRecord") {
|
||||
const record = event as OrderActionRecord;
|
||||
if (maxDlobSlot > 0 && event.slot > maxDlobSlot) {
|
||||
dlob.handleOrderActionRecord(record, event.slot);
|
||||
console.log(`Handled OrderActionRecord event for market ${record.marketIndex}, action: ${getVariant(record.action)} ${getVariant(record.actionExplanation)}`);
|
||||
printDlob(record.marketIndex, dlob);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
setInterval(doDlobDemo, 10000);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
/********** Example for initializing dlob **********/
|
||||
|
||||
function _getLatestSlotFromOrders(dlobOrders: DLOBOrders): number {
|
||||
return Math.max(...dlobOrders.map((dlobOrder) => dlobOrder.order.slot.toNumber()));
|
||||
}
|
||||
|
||||
function printDlob(marketIndex: number, dlob: DLOB) {
|
||||
const currSlot = lastSeenSlot;
|
||||
if (lastSeenSlot === 0) {
|
||||
console.log('waiting for first slot update...');
|
||||
return;
|
||||
}
|
||||
const marketAccount = driftClient.getPerpMarketAccount(marketIndex);
|
||||
const oracle = driftClient.getOracleDataForPerpMarket(marketIndex);
|
||||
|
||||
// you can also set vBid and vAsk to undefined to omit the vAMM price node from bids and asks
|
||||
const vBid = calculateBidPrice(marketAccount!, oracle);
|
||||
const vAsk = calculateAskPrice(marketAccount!, oracle);
|
||||
|
||||
const dlobBids = dlob.getBids(marketIndex, vBid, lastSeenSlot, MarketType.PERP, oracle);
|
||||
const dlobAsks = dlob.getAsks(marketIndex, vAsk, lastSeenSlot, MarketType.PERP, oracle);
|
||||
|
||||
console.log(`DLOB for market ${marketIndex}:`);
|
||||
console.log("Asks");
|
||||
const dlobAsksArray = Array(...dlobAsks).reverse();
|
||||
let countAsks = dlobAsksArray.length;
|
||||
for (const ask of dlobAsksArray) {
|
||||
const isVamm = ask.isVammNode();
|
||||
if (countAsks < levelsToPrint) {
|
||||
console.log(` [${countAsks - 1}] ${isVamm ? "vAMMNode" : getVariant(ask.order?.orderType)} ${convertToNumber(ask.getPrice(oracle, currSlot), PRICE_PRECISION)} (oraclePriceOffset: ${ask.order?.oraclePriceOffset || 0 * PRICE_PRECISION})`);
|
||||
}
|
||||
countAsks--;
|
||||
}
|
||||
|
||||
console.log("Bids");
|
||||
let countBids = 0;
|
||||
for (const bid of dlobBids) {
|
||||
const isVamm = bid.isVammNode();
|
||||
if (countBids < levelsToPrint) {
|
||||
console.log(` [${countBids}] ${isVamm ? "vAMMNode" : getVariant(bid.order?.orderType)} ${convertToNumber(bid.getPrice(oracle, currSlot), PRICE_PRECISION)} (oraclePriceOffset: ${bid.order?.oraclePriceOffset || 0 * PRICE_PRECISION})`);
|
||||
}
|
||||
countBids++;
|
||||
}
|
||||
|
||||
console.log("");
|
||||
}
|
||||
|
||||
function doDlobDemo() {
|
||||
const dlobCoder = DLOBOrdersCoder.create();
|
||||
fetch(dlobServerURL)
|
||||
.then(
|
||||
async (r) => {
|
||||
console.log(`dlob server response: ${r.status} ${r.statusText}`);
|
||||
const resp = await r.json();
|
||||
lastSeenSlot = resp['slot'];
|
||||
console.log(`Latest dlob slot: ${lastSeenSlot}`);
|
||||
const dlobOrdersBuffer = Buffer.from(resp['data'], 'base64');
|
||||
const dlobOrders = dlobCoder.decode(Buffer.from(dlobOrdersBuffer));
|
||||
console.log(`Total Dlob orders count: ${dlobOrders.length}`);
|
||||
dlob.initFromOrders(dlobOrders, lastSeenSlot);
|
||||
|
||||
const marketIndex = 0;
|
||||
console.log("Initialized DLOb from server");
|
||||
printDlob(marketIndex, dlob);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user