Skip to content

Commit 04a45f7

Browse files
authored
Merge pull request #481 from drift-labs/master
update pyth cranker
2 parents 4265335 + 12320e5 commit 04a45f7

File tree

10 files changed

+114
-41
lines changed

10 files changed

+114
-41
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
"main": "lib/index.js",
66
"license": "Apache-2.0",
77
"dependencies": {
8-
"@drift-labs/jit-proxy": "0.17.54",
9-
"@drift-labs/sdk": "2.124.0-beta.2",
8+
"@drift-labs/jit-proxy": "0.17.57",
9+
"@drift-labs/sdk": "2.124.0-beta.5",
1010
"@drift/common": "file:./drift-common/common-ts",
1111
"@opentelemetry/api": "1.7.0",
1212
"@opentelemetry/auto-instrumentations-node": "0.31.2",

src/bots/filler.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,12 @@ export class FillerBot extends TxThreaded implements Bot {
387387
this.pythLazerSubscriber = new PythLazerSubscriber(
388388
this.globalConfig.lazerEndpoints,
389389
this.globalConfig.lazerToken,
390-
pythLazerIdsChunks,
390+
pythLazerIdsChunks.map((ids) => {
391+
return {
392+
priceFeedIds: ids,
393+
channel: 'fixed_rate@200ms',
394+
};
395+
}),
391396
this.globalConfig.driftEnv
392397
);
393398
}

src/bots/makerBidAskTwapCrank.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,12 @@ export class MakerBidAskTwapCrank implements Bot {
221221
this.pythLazerSubscriber = new PythLazerSubscriber(
222222
this.globalConfig.lazerEndpoints,
223223
this.globalConfig.lazerToken,
224-
pythLazerIdsChunks,
224+
pythLazerIdsChunks.map((ids) => {
225+
return {
226+
priceFeedIds: ids,
227+
channel: 'fixed_rate@200ms',
228+
};
229+
}),
225230
this.globalConfig.driftEnv
226231
);
227232
}

src/bots/pythLazerCranker.ts

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@ import {
2525
sleepMs,
2626
} from '../utils';
2727
import { Agent, setGlobalDispatcher } from 'undici';
28-
import { PythLazerSubscriber } from '../pythLazerSubscriber';
28+
import {
29+
PythLazerPriceFeedArray,
30+
PythLazerSubscriber,
31+
} from '../pythLazerSubscriber';
32+
import { Channel } from '@pythnetwork/pyth-lazer-sdk';
2933

3034
setGlobalDispatcher(
3135
new Agent({
@@ -62,8 +66,11 @@ export class PythLazerCrankerBot implements Bot {
6266
throw new Error('Jito is not supported for pyth lazer cranker');
6367
}
6468

65-
let feedIdChunks: number[][] = [];
66-
if (!this.crankConfigs.pythLazerIds) {
69+
let feedIdChunks: PythLazerPriceFeedArray[] = [];
70+
if (
71+
!this.crankConfigs.pythLazerIds &&
72+
!this.crankConfigs.pythLazerIdsByChannel
73+
) {
6774
const spotMarkets =
6875
this.globalConfig.driftEnv === 'mainnet-beta'
6976
? MainnetSpotMarkets
@@ -89,9 +96,35 @@ export class PythLazerCrankerBot implements Bot {
8996
allFeedIds.push(market.pythLazerId!);
9097
}
9198
const allFeedIdsSet = new Set(allFeedIds);
92-
feedIdChunks = chunks(Array.from(allFeedIdsSet), 11);
99+
feedIdChunks = chunks(Array.from(allFeedIdsSet), 11).map((ids) => {
100+
return {
101+
priceFeedIds: ids,
102+
channel: 'fixed_rate@200ms',
103+
};
104+
});
105+
} else if (this.crankConfigs.pythLazerIdsByChannel) {
106+
for (const key of Object.keys(
107+
this.crankConfigs.pythLazerIdsByChannel
108+
) as Channel[]) {
109+
const ids = this.crankConfigs.pythLazerIdsByChannel[key];
110+
if (!ids || ids.length === 0) {
111+
continue;
112+
}
113+
feedIdChunks.push({
114+
priceFeedIds: ids,
115+
channel: key as Channel,
116+
});
117+
}
93118
} else {
94-
feedIdChunks = chunks(Array.from(this.crankConfigs.pythLazerIds), 11);
119+
feedIdChunks = chunks(
120+
Array.from(this.crankConfigs.pythLazerIds!),
121+
11
122+
).map((ids) => {
123+
return {
124+
priceFeedIds: ids,
125+
channel: 'real_time',
126+
};
127+
});
95128
}
96129
console.log(feedIdChunks);
97130

@@ -107,8 +140,7 @@ export class PythLazerCrankerBot implements Bot {
107140
this.globalConfig.driftEnv,
108141
undefined,
109142
undefined,
110-
undefined,
111-
this.crankConfigs.pythLazerChannel ?? 'fixed_rate@200ms'
143+
undefined
112144
);
113145
this.decodeFunc =
114146
this.driftClient.program.account.pythLazerOracle.coder.accounts.decodeUnchecked.bind(
@@ -176,9 +208,10 @@ export class PythLazerCrankerBot implements Bot {
176208
priceMessage,
177209
] of this.pythLazerClient.feedIdChunkToPriceMessage.entries()) {
178210
const feedIds = this.pythLazerClient.getPriceFeedIdsFromHash(feedIdsStr);
211+
const cus = Math.max(0, feedIds.length - 3) * 6_000 + 30_000;
179212
const ixs = [
180213
ComputeBudgetProgram.setComputeUnitLimit({
181-
units: 30_000,
214+
units: cus,
182215
}),
183216
];
184217
const priorityFees = Math.floor(

src/bots/trigger.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,10 @@ import {
5353
TransactionInstruction,
5454
} from '@solana/web3.js';
5555
import { PriceUpdateAccount } from '@pythnetwork/pyth-solana-receiver/lib/PythSolanaReceiver';
56-
import { PythLazerSubscriber } from '../pythLazerSubscriber';
56+
import {
57+
PythLazerPriceFeedArray,
58+
PythLazerSubscriber,
59+
} from '../pythLazerSubscriber';
5760
import { PriceServiceConnection } from '@pythnetwork/price-service-client';
5861

5962
const TRIGGER_ORDER_COOLDOWN_MS = 10000; // time to wait between triggering an order
@@ -76,7 +79,7 @@ function getPythLazerFeedIdChunks(
7679
spotMarkets: SpotMarketConfig[],
7780
perpMarkets: PerpMarketConfig[],
7881
chunkSize = 11
79-
): number[][] {
82+
): PythLazerPriceFeedArray[] {
8083
const allFeedIds: number[] = [];
8184
for (const market of [...spotMarkets, ...perpMarkets]) {
8285
if (
@@ -89,7 +92,12 @@ function getPythLazerFeedIdChunks(
8992
}
9093

9194
const allFeedIdsSet = new Set(allFeedIds);
92-
return chunks(Array.from(allFeedIdsSet), chunkSize);
95+
return chunks(Array.from(allFeedIdsSet), chunkSize).map((ids) => {
96+
return {
97+
priceFeedIds: ids,
98+
channel: 'fixed_rate@200ms',
99+
};
100+
});
93101
}
94102

95103
function getPythPullFeedIdsToCrank(

src/config.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,11 @@ export type PythLazerCrankerBotConfig = BaseBotConfig & {
124124
pythLazerChannel?: string;
125125
ignorePythLazerIds?: number[];
126126
pythLazerIds?: number[];
127+
pythLazerIdsByChannel?: {
128+
real_time: number[];
129+
'fixed_rate@50ms': number[];
130+
'fixed_rate@200ms': number[];
131+
};
127132
slotStalenessThresholdRestart: number;
128133
txSuccessRateThreshold: number;
129134
intervalMs: number;

src/experimental-bots/filler/fillerMultithreaded.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,12 @@ export class FillerMultithreaded {
400400
this.pythLazerSubscriber = new PythLazerSubscriber(
401401
this.globalConfig.lazerEndpoints,
402402
this.globalConfig.lazerToken,
403-
pythLazerIdsChunks,
403+
pythLazerIdsChunks.map((ids) => {
404+
return {
405+
priceFeedIds: ids,
406+
channel: 'fixed_rate@200ms',
407+
};
408+
}),
404409
this.globalConfig.driftEnv,
405410
new RedisClient({
406411
prefix: RedisClientPrefix.DLOB,

src/experimental-bots/swift/placerExample.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ export class SwiftPlacer {
5656
interval: NodeJS.Timeout | null = null;
5757
private ws: WebSocket | null = null;
5858
private signedMsgUrl: string;
59+
private baseDlobUrl: string;
5960
private heartbeatTimeout: NodeJS.Timeout | null = null;
6061
private priorityFeeSubscriber: PriorityFeeSubscriberMap;
6162
private referrerMap: ReferrerMap;
@@ -71,13 +72,18 @@ export class SwiftPlacer {
7172
? 'wss://swift.drift.trade/ws'
7273
: 'wss://master.swift.drift.trade/ws';
7374

75+
this.baseDlobUrl =
76+
runtimeSpec.driftEnv == 'mainnet-beta'
77+
? 'https://dlob.drift.trade'
78+
: 'https://master.dlob.drift.trade';
79+
7480
const perpMarketsToWatchForFees = [0, 1, 2, 3, 4, 5].map((x) => {
7581
return { marketType: 'perp', marketIndex: x };
7682
});
7783

7884
this.priorityFeeSubscriber = new PriorityFeeSubscriberMap({
7985
driftMarkets: perpMarketsToWatchForFees,
80-
driftPriorityFeeEndpoint: 'https://dlob.drift.trade',
86+
driftPriorityFeeEndpoint: this.baseDlobUrl,
8187
});
8288

8389
this.referrerMap = new ReferrerMap(driftClient, true);
@@ -238,7 +244,7 @@ export class SwiftPlacer {
238244

239245
const isOrderLong = isVariant(signedMsgOrderParams.direction, 'long');
240246
const result = await axios.get(
241-
`https://dlob.drift.trade/topMakers?marketType=perp&marketIndex=${
247+
`${this.baseDlobUrl}/topMakers?marketType=perp&marketIndex=${
242248
signedMsgOrderParams.marketIndex
243249
}&side=${isOrderLong ? 'ask' : 'bid'}&limit=2`
244250
);

src/pythLazerSubscriber.ts

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ import { DriftEnv, PerpMarkets } from '@drift-labs/sdk';
33
import { RedisClient } from '@drift/common/clients';
44
import * as axios from 'axios';
55

6+
export type PythLazerPriceFeedArray = {
7+
channel?: Channel;
8+
priceFeedIds: number[];
9+
};
10+
611
export class PythLazerSubscriber {
712
private pythLazerClient?: PythLazerClient;
813
feedIdChunkToPriceMessage: Map<string, string> = new Map();
@@ -22,34 +27,35 @@ export class PythLazerSubscriber {
2227
constructor(
2328
private endpoints: string[],
2429
private token: string,
25-
private priceFeedIdsArrays: number[][],
30+
private priceFeedArrays: PythLazerPriceFeedArray[],
2631
env: DriftEnv = 'devnet',
2732
private redisClient?: RedisClient,
2833
private httpEndpoints: string[] = [],
29-
private resubTimeoutMs: number = 2000,
30-
private subscribeChannel = 'fixed_rate@200ms'
34+
private resubTimeoutMs: number = 2000
3135
) {
3236
const markets = PerpMarkets[env].filter(
3337
(market) => market.pythLazerId !== undefined
3438
);
3539

36-
this.allSubscribedIds = this.priceFeedIdsArrays.flat();
40+
this.allSubscribedIds = this.priceFeedArrays
41+
.map((array) => array.priceFeedIds)
42+
.flat();
3743
if (
38-
priceFeedIdsArrays[0].length === 1 &&
44+
priceFeedArrays[0].priceFeedIds.length === 1 &&
3945
this.allSubscribedIds.length > 3 &&
4046
this.httpEndpoints.length > 0
4147
) {
4248
this.useHttpRequests = true;
4349
}
4450

45-
for (const priceFeedIds of priceFeedIdsArrays) {
51+
for (const priceFeedIds of priceFeedArrays) {
4652
const filteredMarkets = markets.filter((market) =>
47-
priceFeedIds.includes(market.pythLazerId!)
53+
priceFeedIds.priceFeedIds.includes(market.pythLazerId!)
4854
);
4955
for (const market of filteredMarkets) {
5056
this.marketIndextoPriceFeedIdChunk.set(
5157
market.marketIndex,
52-
priceFeedIds
58+
priceFeedIds.priceFeedIds
5359
);
5460
this.marketIndextoPriceFeedId.set(
5561
market.marketIndex,
@@ -70,9 +76,9 @@ export class PythLazerSubscriber {
7076
this.token
7177
);
7278
let subscriptionId = 1;
73-
for (const priceFeedIds of this.priceFeedIdsArrays) {
74-
const feedIdsHash = this.hash(priceFeedIds);
75-
this.feedIdHashToFeedIds.set(feedIdsHash, priceFeedIds);
79+
for (const priceFeedIds of this.priceFeedArrays) {
80+
const feedIdsHash = this.hash(priceFeedIds.priceFeedIds);
81+
this.feedIdHashToFeedIds.set(feedIdsHash, priceFeedIds.priceFeedIds);
7682
this.subscriptionIdsToFeedIdsHash.set(subscriptionId, feedIdsHash);
7783
this.pythLazerClient.addMessageListener((message) => {
7884
this.receivingData = true;
@@ -108,11 +114,11 @@ export class PythLazerSubscriber {
108114
this.pythLazerClient.send({
109115
type: 'subscribe',
110116
subscriptionId,
111-
priceFeedIds,
117+
priceFeedIds: priceFeedIds.priceFeedIds,
112118
properties: ['price', 'bestAskPrice', 'bestBidPrice', 'exponent'],
113119
chains: ['solana'],
114120
deliveryFormat: 'json',
115-
channel: this.subscribeChannel as Channel,
121+
channel: priceFeedIds.channel ?? ('fixed_rate@200ms' as Channel),
116122
jsonBinaryEncoding: 'hex',
117123
});
118124
subscriptionId++;

yarn.lock

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -380,20 +380,20 @@
380380
enabled "2.0.x"
381381
kuler "^2.0.0"
382382

383-
"@drift-labs/[email protected].54":
384-
version "0.17.54"
385-
resolved "https://registry.yarnpkg.com/@drift-labs/jit-proxy/-/jit-proxy-0.17.54.tgz#a2146ffbc18579c89a4efb7fdb6a01d41806364b"
386-
integrity sha512-o1qu2tSmYae4wcnMPD4ifyU+ulPC4omF+WVrW/6aCdcyrqHEqerluYKtnDtucBoCfQJe3WGM5bqaRekL4QClyw==
383+
"@drift-labs/[email protected].57":
384+
version "0.17.57"
385+
resolved "https://registry.yarnpkg.com/@drift-labs/jit-proxy/-/jit-proxy-0.17.57.tgz#518d9d36ec396407c46266d57df71c580b24fe2b"
386+
integrity sha512-igNg3644ZomHkxkVpL7YsYtCXrKEGvIeCPkU+Jq0/KTaB0q/U8KbB/TJmlJ3byZ81K+AmMxCHlbTqqZyqeNaBQ==
387387
dependencies:
388388
"@coral-xyz/anchor" "0.29.0"
389-
"@drift-labs/sdk" "2.124.0-beta.2"
389+
"@drift-labs/sdk" "2.124.0-beta.5"
390390
"@solana/web3.js" "1.91.7"
391391
tweetnacl-util "^0.15.1"
392392

393-
"@drift-labs/[email protected].2":
394-
version "2.124.0-beta.2"
395-
resolved "https://registry.yarnpkg.com/@drift-labs/sdk/-/sdk-2.124.0-beta.2.tgz#843ae7284a13eea4eff3460e60937960e9ae78f0"
396-
integrity sha512-MxA9FICLffttXxUxSl6jpdVlopNxyMnDX+lezVKJ8LqR/l5FSnKLzDkGAMr+1Ro7Nz2uzifVSH6ZbgAzx/myMg==
393+
"@drift-labs/[email protected].5":
394+
version "2.124.0-beta.5"
395+
resolved "https://registry.yarnpkg.com/@drift-labs/sdk/-/sdk-2.124.0-beta.5.tgz#ebd51fc4b5f798d9cf7bd710cc73769e1860c24e"
396+
integrity sha512-WtqmufmwpxARrpHqKEZ6IzawZJjImofaiB8e3j2KoGEGzzKA7zcuM7kmYlkyG3WUBDr8FIPDHZP/InLE4m+wNQ==
397397
dependencies:
398398
"@coral-xyz/anchor" "0.29.0"
399399
"@coral-xyz/anchor-30" "npm:@coral-xyz/[email protected]"
@@ -452,7 +452,7 @@
452452
"@drift/common@file:./drift-common/common-ts":
453453
version "1.0.0"
454454
dependencies:
455-
"@drift-labs/sdk" "file:../../../.cache/yarn/v6/[email protected]a9f2db60-9f18-439d-ada5-a36d34281dad-1749931617585/node_modules/@drift/protocol/sdk"
455+
"@drift-labs/sdk" "file:../../../.cache/yarn/v6/[email protected]493c413e-6aac-48c5-a634-6f605ad648e0-1750104675160/node_modules/@drift/protocol/sdk"
456456
"@jest/globals" "29.3.1"
457457
"@slack/web-api" "6.4.0"
458458
"@solana/spl-token" "0.3.8"

0 commit comments

Comments
 (0)