@@ -55,8 +55,8 @@ const driftClientPublicKey = new PublicKey(sdkConfig.DRIFT_PROGRAM_ID);
|
|||||||
let lastSeenSlot = 0;
|
let lastSeenSlot = 0;
|
||||||
|
|
||||||
/********** initializing driftClient as usual **********/
|
/********** initializing driftClient as usual **********/
|
||||||
var accountSubscription: DriftClientSubscriptionConfig;
|
let accountSubscription: DriftClientSubscriptionConfig;
|
||||||
var logProviderConfig: LogProviderConfig;
|
let logProviderConfig: LogProviderConfig;
|
||||||
if (useWebsocket) {
|
if (useWebsocket) {
|
||||||
accountSubscription = {
|
accountSubscription = {
|
||||||
type: 'websocket',
|
type: 'websocket',
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@drift-labs/sdk": "2.48.0-beta.0",
|
"@drift-labs/sdk": "2.48.0-beta.9",
|
||||||
"@opentelemetry/api": "^1.1.0",
|
"@opentelemetry/api": "^1.1.0",
|
||||||
"@opentelemetry/auto-instrumentations-node": "^0.31.1",
|
"@opentelemetry/auto-instrumentations-node": "^0.31.1",
|
||||||
"@opentelemetry/exporter-prometheus": "^0.31.0",
|
"@opentelemetry/exporter-prometheus": "^0.31.0",
|
||||||
|
|||||||
92
src/index.ts
92
src/index.ts
@@ -16,7 +16,10 @@ import {
|
|||||||
DLOBOrdersCoder,
|
DLOBOrdersCoder,
|
||||||
DLOBSubscriber,
|
DLOBSubscriber,
|
||||||
DriftClient,
|
DriftClient,
|
||||||
|
DriftClientSubscriptionConfig,
|
||||||
DriftEnv,
|
DriftEnv,
|
||||||
|
SlotSource,
|
||||||
|
SlotSubscriber,
|
||||||
UserMap,
|
UserMap,
|
||||||
UserStatsMap,
|
UserStatsMap,
|
||||||
Wallet,
|
Wallet,
|
||||||
@@ -53,6 +56,7 @@ const sdkConfig = initialize({ env: process.env.ENV });
|
|||||||
const stateCommitment: Commitment = 'processed';
|
const stateCommitment: Commitment = 'processed';
|
||||||
const serverPort = process.env.PORT || 6969;
|
const serverPort = process.env.PORT || 6969;
|
||||||
export const ORDERBOOK_UPDATE_INTERVAL = 1000;
|
export const ORDERBOOK_UPDATE_INTERVAL = 1000;
|
||||||
|
const useWebsocket = process.env.USE_WEBSOCKET?.toLowerCase() === 'true';
|
||||||
|
|
||||||
const rateLimitCallsPerSecond = process.env.RATE_LIMIT_CALLS_PER_SECOND
|
const rateLimitCallsPerSecond = process.env.RATE_LIMIT_CALLS_PER_SECOND
|
||||||
? parseInt(process.env.RATE_LIMIT_CALLS_PER_SECOND)
|
? parseInt(process.env.RATE_LIMIT_CALLS_PER_SECOND)
|
||||||
@@ -117,6 +121,7 @@ const endpoint = process.env.ENDPOINT;
|
|||||||
const wsEndpoint = process.env.WS_ENDPOINT;
|
const wsEndpoint = process.env.WS_ENDPOINT;
|
||||||
logger.info(`RPC endpoint: ${endpoint}`);
|
logger.info(`RPC endpoint: ${endpoint}`);
|
||||||
logger.info(`WS endpoint: ${wsEndpoint}`);
|
logger.info(`WS endpoint: ${wsEndpoint}`);
|
||||||
|
logger.info(`useWebsocket: ${useWebsocket}`);
|
||||||
logger.info(`DriftEnv: ${driftEnv}`);
|
logger.info(`DriftEnv: ${driftEnv}`);
|
||||||
logger.info(`Commit: ${commitHash}`);
|
logger.info(`Commit: ${commitHash}`);
|
||||||
|
|
||||||
@@ -171,33 +176,51 @@ const main = async () => {
|
|||||||
commitment: stateCommitment,
|
commitment: stateCommitment,
|
||||||
});
|
});
|
||||||
|
|
||||||
const bulkAccountLoader = new BulkAccountLoader(
|
// only set when polling
|
||||||
connection,
|
let bulkAccountLoader: BulkAccountLoader | undefined;
|
||||||
stateCommitment,
|
|
||||||
ORDERBOOK_UPDATE_INTERVAL
|
// only set when using websockets
|
||||||
);
|
let slotSubscriber: SlotSubscriber | undefined;
|
||||||
|
|
||||||
|
let accountSubscription: DriftClientSubscriptionConfig;
|
||||||
|
let slotSource: SlotSource;
|
||||||
|
|
||||||
|
if (!useWebsocket) {
|
||||||
|
bulkAccountLoader = new BulkAccountLoader(
|
||||||
|
connection,
|
||||||
|
stateCommitment,
|
||||||
|
ORDERBOOK_UPDATE_INTERVAL
|
||||||
|
);
|
||||||
|
|
||||||
|
accountSubscription = {
|
||||||
|
type: 'polling',
|
||||||
|
accountLoader: bulkAccountLoader,
|
||||||
|
};
|
||||||
|
slotSource = {
|
||||||
|
getSlot: () => bulkAccountLoader!.getSlot(),
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
accountSubscription = {
|
||||||
|
type: 'websocket',
|
||||||
|
commitment: stateCommitment,
|
||||||
|
};
|
||||||
|
slotSubscriber = new SlotSubscriber(connection);
|
||||||
|
await slotSubscriber.subscribe();
|
||||||
|
slotSource = {
|
||||||
|
getSlot: () => slotSubscriber!.getSlot(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
driftClient = new DriftClient({
|
driftClient = new DriftClient({
|
||||||
connection,
|
connection,
|
||||||
wallet,
|
wallet,
|
||||||
programID: clearingHousePublicKey,
|
programID: clearingHousePublicKey,
|
||||||
accountSubscription: {
|
accountSubscription,
|
||||||
type: 'polling',
|
|
||||||
accountLoader: bulkAccountLoader,
|
|
||||||
},
|
|
||||||
env: driftEnv,
|
env: driftEnv,
|
||||||
userStats: true,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const dlobCoder = DLOBOrdersCoder.create();
|
const dlobCoder = DLOBOrdersCoder.create();
|
||||||
|
|
||||||
const lamportsBalance = await connection.getBalance(wallet.publicKey);
|
|
||||||
logger.info(
|
|
||||||
`DriftClient ProgramId: ${driftClient.program.programId.toBase58()}`
|
|
||||||
);
|
|
||||||
logger.info(`Wallet pubkey: ${wallet.publicKey.toBase58()}`);
|
|
||||||
logger.info(` . SOL balance: ${lamportsBalance / 10 ** 9}`);
|
|
||||||
|
|
||||||
await driftClient.subscribe();
|
await driftClient.subscribe();
|
||||||
driftClient.eventEmitter.on('error', (e) => {
|
driftClient.eventEmitter.on('error', (e) => {
|
||||||
logger.info('clearing house error');
|
logger.info('clearing house error');
|
||||||
@@ -205,28 +228,37 @@ const main = async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
setInterval(async () => {
|
setInterval(async () => {
|
||||||
lastSlotReceived = bulkAccountLoader.getSlot();
|
lastSlotReceived = slotSource.getSlot();
|
||||||
}, ORDERBOOK_UPDATE_INTERVAL);
|
}, ORDERBOOK_UPDATE_INTERVAL);
|
||||||
|
|
||||||
|
const userStatsMap = new UserStatsMap(driftClient);
|
||||||
|
|
||||||
|
logger.info(`Initializing userMap...`);
|
||||||
|
const initUserMapStart = Date.now();
|
||||||
const userMap = new UserMap(
|
const userMap = new UserMap(
|
||||||
driftClient,
|
driftClient,
|
||||||
driftClient.userAccountSubscriptionConfig,
|
driftClient.userAccountSubscriptionConfig,
|
||||||
false
|
false,
|
||||||
|
async (authorities) => {
|
||||||
|
await userStatsMap.sync(authorities);
|
||||||
|
},
|
||||||
|
{ hasOpenOrders: true }
|
||||||
);
|
);
|
||||||
await userMap.subscribe();
|
await userMap.subscribe();
|
||||||
const userStatsMap = new UserStatsMap(driftClient, {
|
logger.info(`userMap initialized in ${Date.now() - initUserMapStart} ms`);
|
||||||
type: 'polling',
|
|
||||||
accountLoader: new BulkAccountLoader(connection, stateCommitment, 0),
|
|
||||||
});
|
|
||||||
await userStatsMap.subscribe();
|
|
||||||
|
|
||||||
|
logger.info(`Initializing DLOBSubscriber...`);
|
||||||
|
const initDlobSubscriberStart = Date.now();
|
||||||
const dlobSubscriber = new DLOBSubscriber({
|
const dlobSubscriber = new DLOBSubscriber({
|
||||||
driftClient,
|
driftClient,
|
||||||
dlobSource: userMap,
|
dlobSource: userMap,
|
||||||
slotSource: bulkAccountLoader,
|
slotSource,
|
||||||
updateFrequency: ORDERBOOK_UPDATE_INTERVAL,
|
updateFrequency: ORDERBOOK_UPDATE_INTERVAL,
|
||||||
});
|
});
|
||||||
await dlobSubscriber.subscribe();
|
await dlobSubscriber.subscribe();
|
||||||
|
logger.info(
|
||||||
|
`DLOBSubscriber initialized in ${Date.now() - initDlobSubscriberStart} ms`
|
||||||
|
);
|
||||||
|
|
||||||
MARKET_SUBSCRIBERS = await initializeAllMarketSubscribers(driftClient);
|
MARKET_SUBSCRIBERS = await initializeAllMarketSubscribers(driftClient);
|
||||||
|
|
||||||
@@ -253,7 +285,7 @@ const main = async () => {
|
|||||||
// object with userAccount key and orders object serialized
|
// object with userAccount key and orders object serialized
|
||||||
const orders: Array<any> = [];
|
const orders: Array<any> = [];
|
||||||
const oracles: Array<any> = [];
|
const oracles: Array<any> = [];
|
||||||
const slot = bulkAccountLoader.getSlot();
|
const slot = slotSource.getSlot();
|
||||||
|
|
||||||
for (const market of driftClient.getPerpMarketAccounts()) {
|
for (const market of driftClient.getPerpMarketAccounts()) {
|
||||||
const oracle = driftClient.getOracleDataForPerpMarket(
|
const oracle = driftClient.getOracleDataForPerpMarket(
|
||||||
@@ -297,7 +329,7 @@ const main = async () => {
|
|||||||
app.get('/orders/json', async (_req, res, next) => {
|
app.get('/orders/json', async (_req, res, next) => {
|
||||||
try {
|
try {
|
||||||
// object with userAccount key and orders object serialized
|
// object with userAccount key and orders object serialized
|
||||||
const slot = bulkAccountLoader.getSlot();
|
const slot = slotSource.getSlot();
|
||||||
const orders: Array<any> = [];
|
const orders: Array<any> = [];
|
||||||
const oracles: Array<any> = [];
|
const oracles: Array<any> = [];
|
||||||
for (const market of driftClient.getPerpMarketAccounts()) {
|
for (const market of driftClient.getPerpMarketAccounts()) {
|
||||||
@@ -460,7 +492,7 @@ const main = async () => {
|
|||||||
|
|
||||||
res.end(
|
res.end(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
slot: bulkAccountLoader.getSlot(),
|
slot: slotSource.getSlot(),
|
||||||
data: dlobCoder.encode(dlobOrders).toString('base64'),
|
data: dlobCoder.encode(dlobOrders).toString('base64'),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -549,7 +581,7 @@ const main = async () => {
|
|||||||
.getDLOB()
|
.getDLOB()
|
||||||
.getRestingLimitBids(
|
.getRestingLimitBids(
|
||||||
normedMarketIndex,
|
normedMarketIndex,
|
||||||
bulkAccountLoader.getSlot(),
|
slotSource.getSlot(),
|
||||||
normedMarketType,
|
normedMarketType,
|
||||||
oracle
|
oracle
|
||||||
)
|
)
|
||||||
@@ -560,7 +592,7 @@ const main = async () => {
|
|||||||
.getDLOB()
|
.getDLOB()
|
||||||
.getRestingLimitAsks(
|
.getRestingLimitAsks(
|
||||||
normedMarketIndex,
|
normedMarketIndex,
|
||||||
bulkAccountLoader.getSlot(),
|
slotSource.getSlot(),
|
||||||
normedMarketType,
|
normedMarketType,
|
||||||
oracle
|
oracle
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -66,7 +66,6 @@ const main = async () => {
|
|||||||
accountLoader: bulkAccountLoader,
|
accountLoader: bulkAccountLoader,
|
||||||
},
|
},
|
||||||
env: driftEnv,
|
env: driftEnv,
|
||||||
userStats: true,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const slotSubscriber = new SlotSubscriber(connection, {});
|
const slotSubscriber = new SlotSubscriber(connection, {});
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import {
|
|||||||
PRICE_PRECISION,
|
PRICE_PRECISION,
|
||||||
getVariant,
|
getVariant,
|
||||||
ZERO,
|
ZERO,
|
||||||
|
BN,
|
||||||
} from '@drift-labs/sdk';
|
} from '@drift-labs/sdk';
|
||||||
|
|
||||||
import { logger, setLogLevel } from '../utils/logger';
|
import { logger, setLogLevel } from '../utils/logger';
|
||||||
@@ -74,7 +75,6 @@ const main = async () => {
|
|||||||
accountLoader: bulkAccountLoader,
|
accountLoader: bulkAccountLoader,
|
||||||
},
|
},
|
||||||
env: driftEnv,
|
env: driftEnv,
|
||||||
userStats: true,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const slotSubscriber = new SlotSubscriber(connection, {});
|
const slotSubscriber = new SlotSubscriber(connection, {});
|
||||||
@@ -147,7 +147,9 @@ const main = async () => {
|
|||||||
),
|
),
|
||||||
taker: fill.taker?.toBase58(),
|
taker: fill.taker?.toBase58(),
|
||||||
takerOrderId: fill.takerOrderId,
|
takerOrderId: fill.takerOrderId,
|
||||||
takerOrderDirection: getVariant(fill.takerOrderDirection),
|
takerOrderDirection: fill.takerOrderDirection
|
||||||
|
? getVariant(fill.takerOrderDirection)
|
||||||
|
: undefined,
|
||||||
takerOrderBaseAssetAmount: convertToNumber(
|
takerOrderBaseAssetAmount: convertToNumber(
|
||||||
fill.takerOrderBaseAssetAmount,
|
fill.takerOrderBaseAssetAmount,
|
||||||
BASE_PRECISION
|
BASE_PRECISION
|
||||||
@@ -183,7 +185,7 @@ const main = async () => {
|
|||||||
action: 'fill',
|
action: 'fill',
|
||||||
actionExplanation: getVariant(fill.actionExplanation),
|
actionExplanation: getVariant(fill.actionExplanation),
|
||||||
referrerReward: convertToNumber(
|
referrerReward: convertToNumber(
|
||||||
fill.referrerReward ?? ZERO,
|
new BN(fill.referrerReward ?? ZERO),
|
||||||
QUOTE_PRECISION
|
QUOTE_PRECISION
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -80,10 +80,10 @@
|
|||||||
enabled "2.0.x"
|
enabled "2.0.x"
|
||||||
kuler "^2.0.0"
|
kuler "^2.0.0"
|
||||||
|
|
||||||
"@drift-labs/sdk@2.48.0-beta.0":
|
"@drift-labs/sdk@2.48.0-beta.9":
|
||||||
version "2.48.0-beta.0"
|
version "2.48.0-beta.9"
|
||||||
resolved "https://registry.yarnpkg.com/@drift-labs/sdk/-/sdk-2.48.0-beta.0.tgz#dcda51d878bf458cc5e070528f8b0714f9c53589"
|
resolved "https://registry.yarnpkg.com/@drift-labs/sdk/-/sdk-2.48.0-beta.9.tgz#2d0c99f58387ff3c5e45859ae4fe088339c8dd55"
|
||||||
integrity sha512-okRb3ErrApZvks24AFMwLrmsdrcntLAUTRNcSfutg/Ri10hjMAIaiRdsYSbMZcDGWgjRq/+sozKIqiqfd7xfpg==
|
integrity sha512-y0wrq680nv7Uwvcg9jOrjZPXxoae9yRg8M9B4bQgDFeNJmZNmcEmnLhWQ+CbPi8u/O0glhOdtKUk4UF9eSPXAg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@coral-xyz/anchor" "0.28.1-beta.2"
|
"@coral-xyz/anchor" "0.28.1-beta.2"
|
||||||
"@ellipsis-labs/phoenix-sdk" "^1.4.2"
|
"@ellipsis-labs/phoenix-sdk" "^1.4.2"
|
||||||
|
|||||||
Reference in New Issue
Block a user