@lasersell/lasersell-sdk 0.3.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -48,11 +48,31 @@ export interface MarketContextMsg {
48
48
  raydium_cpmm?: RaydiumCpmmContextMsg;
49
49
  }
50
50
 
51
+ export interface TakeProfitLevelMsg {
52
+ profit_pct: number;
53
+ sell_pct: number;
54
+ trailing_stop_pct: number;
55
+ }
56
+
51
57
  export interface StrategyConfigMsg {
52
58
  target_profit_pct: number;
53
59
  stop_loss_pct: number;
54
60
  trailing_stop_pct?: number;
55
61
  sell_on_graduation?: boolean;
62
+ take_profit_levels?: TakeProfitLevelMsg[];
63
+ liquidity_guard?: boolean;
64
+ breakeven_trail_pct?: number;
65
+ }
66
+
67
+ export interface AutoBuyConfigMsg {
68
+ wallet_pubkey: string;
69
+ amount_quote_units: number;
70
+ amount_usd1_units?: number;
71
+ }
72
+
73
+ export interface WatchWalletEntryMsg {
74
+ pubkey: string;
75
+ auto_buy?: AutoBuyConfigMsg;
56
76
  }
57
77
 
58
78
  export interface LimitsMsg {
@@ -62,6 +82,7 @@ export interface LimitsMsg {
62
82
  max_wallets_per_session: number;
63
83
  max_positions_per_wallet: number;
64
84
  max_sessions_per_api_key: number;
85
+ max_watch_wallets_per_session: number;
65
86
  }
66
87
 
67
88
  export interface PingClientMessage {
@@ -75,6 +96,7 @@ export interface ConfigureClientMessage {
75
96
  strategy: StrategyConfigMsg;
76
97
  send_mode?: string;
77
98
  tip_lamports?: number;
99
+ watch_wallets?: WatchWalletEntryMsg[];
78
100
  }
79
101
 
80
102
  export interface UpdateStrategyClientMessage {
@@ -100,13 +122,26 @@ export interface UpdateWalletsClientMessage {
100
122
  wallet_pubkeys: string[];
101
123
  }
102
124
 
125
+ export interface UpdateWatchWalletsClientMessage {
126
+ type: "update_watch_wallets";
127
+ watch_wallets: WatchWalletEntryMsg[];
128
+ }
129
+
130
+ export interface UpdatePositionStrategyClientMessage {
131
+ type: "update_position_strategy";
132
+ position_id: number;
133
+ strategy: StrategyConfigMsg;
134
+ }
135
+
103
136
  export type ClientMessage =
104
137
  | PingClientMessage
105
138
  | ConfigureClientMessage
106
139
  | UpdateStrategyClientMessage
107
140
  | ClosePositionClientMessage
108
141
  | RequestExitSignalClientMessage
109
- | UpdateWalletsClientMessage;
142
+ | UpdateWalletsClientMessage
143
+ | UpdateWatchWalletsClientMessage
144
+ | UpdatePositionStrategyClientMessage;
110
145
 
111
146
  export interface HelloOkServerMessage {
112
147
  type: "hello_ok";
@@ -132,6 +167,9 @@ export interface PnlUpdateServerMessage {
132
167
  profit_units: number;
133
168
  proceeds_units: number;
134
169
  server_time_ms: number;
170
+ token_price_quote?: number;
171
+ market_cap_quote?: number;
172
+ watched: boolean;
135
173
  }
136
174
 
137
175
  export interface SlippageBandMsg {
@@ -146,6 +184,7 @@ export interface LiquiditySnapshotServerMessage {
146
184
  bands: SlippageBandMsg[];
147
185
  liquidity_trend: string;
148
186
  server_time_ms: number;
187
+ watched: boolean;
149
188
  }
150
189
 
151
190
  export interface BalanceUpdateServerMessage {
@@ -169,6 +208,15 @@ export interface PositionOpenedServerMessage {
169
208
  entry_quote_units: number;
170
209
  market_context?: MarketContextMsg;
171
210
  slot: number;
211
+ token_name?: string;
212
+ token_symbol?: string;
213
+ token_decimals?: number;
214
+ token_price_quote?: number;
215
+ market_cap_quote?: number;
216
+ pool_liquidity_quote?: number;
217
+ opened_at_ms?: number;
218
+ mirror_source?: string;
219
+ watched: boolean;
172
220
  }
173
221
 
174
222
  export interface PositionClosedServerMessage {
@@ -179,6 +227,8 @@ export interface PositionClosedServerMessage {
179
227
  token_account?: string;
180
228
  reason: string;
181
229
  slot: number;
230
+ mirror_source?: string;
231
+ watched: boolean;
182
232
  }
183
233
 
184
234
  export interface ExitSignalWithTxServerMessage {
@@ -195,6 +245,23 @@ export interface ExitSignalWithTxServerMessage {
195
245
  triggered_at_ms: number;
196
246
  market_context?: MarketContextMsg;
197
247
  unsigned_tx_b64: string;
248
+ sell_tokens?: number;
249
+ level_index?: number;
250
+ mirror_source?: string;
251
+ watched: boolean;
252
+ }
253
+
254
+ export interface TradeTickServerMessage {
255
+ type: "trade_tick";
256
+ position_id: number;
257
+ time_ms: number;
258
+ side: string;
259
+ token_amount: number;
260
+ quote_amount: number;
261
+ price_quote: number;
262
+ maker?: string;
263
+ tx_signature?: string;
264
+ watched: boolean;
198
265
  }
199
266
 
200
267
  export type ServerMessage =
@@ -206,7 +273,8 @@ export type ServerMessage =
206
273
  | BalanceUpdateServerMessage
207
274
  | PositionOpenedServerMessage
208
275
  | PositionClosedServerMessage
209
- | ExitSignalWithTxServerMessage;
276
+ | ExitSignalWithTxServerMessage
277
+ | TradeTickServerMessage;
210
278
 
211
279
  export function clientMessageFromText(text: string): ClientMessage {
212
280
  let parsed: unknown;
@@ -244,6 +312,10 @@ export function clientMessageFromUnknown(value: unknown): ClientMessage {
244
312
  if (tip_lamports !== undefined) {
245
313
  msg.tip_lamports = tip_lamports;
246
314
  }
315
+ const watch_wallets = optionalWatchWallets(obj.watch_wallets);
316
+ if (watch_wallets !== undefined && watch_wallets.length > 0) {
317
+ msg.watch_wallets = watch_wallets;
318
+ }
247
319
  return msg;
248
320
  }
249
321
  case "update_strategy": {
@@ -287,6 +359,20 @@ export function clientMessageFromUnknown(value: unknown): ClientMessage {
287
359
  wallet_pubkeys,
288
360
  };
289
361
  }
362
+ case "update_watch_wallets": {
363
+ const watch_wallets = parseWatchWallets(obj.watch_wallets);
364
+ return {
365
+ type: "update_watch_wallets",
366
+ watch_wallets,
367
+ };
368
+ }
369
+ case "update_position_strategy": {
370
+ return {
371
+ type: "update_position_strategy",
372
+ position_id: asNumber(obj.position_id, "update_position_strategy.position_id"),
373
+ strategy: parseStrategyConfig(obj.strategy),
374
+ };
375
+ }
290
376
  default:
291
377
  throw new Error(`unsupported client message type: ${type}`);
292
378
  }
@@ -333,13 +419,24 @@ export function serverMessageFromUnknown(value: unknown): ServerMessage {
333
419
  };
334
420
  }
335
421
  case "pnl_update": {
336
- return {
422
+ const msg: PnlUpdateServerMessage = {
337
423
  type: "pnl_update",
338
424
  position_id: asNumber(obj.position_id, "pnl_update.position_id"),
339
425
  profit_units: asNumber(obj.profit_units, "pnl_update.profit_units"),
340
426
  proceeds_units: asNumber(obj.proceeds_units, "pnl_update.proceeds_units"),
341
427
  server_time_ms: asNumber(obj.server_time_ms, "pnl_update.server_time_ms"),
428
+ watched: false,
342
429
  };
430
+ const token_price_quote = optionalNumber(obj.token_price_quote, "pnl_update.token_price_quote");
431
+ if (token_price_quote !== undefined) {
432
+ msg.token_price_quote = token_price_quote;
433
+ }
434
+ const market_cap_quote = optionalNumber(obj.market_cap_quote, "pnl_update.market_cap_quote");
435
+ if (market_cap_quote !== undefined) {
436
+ msg.market_cap_quote = market_cap_quote;
437
+ }
438
+ msg.watched = optionalBoolean(obj.watched, "pnl_update.watched") ?? false;
439
+ return msg;
343
440
  }
344
441
  case "liquidity_snapshot": {
345
442
  const rawBands = obj.bands;
@@ -362,6 +459,7 @@ export function serverMessageFromUnknown(value: unknown): ServerMessage {
362
459
  bands,
363
460
  liquidity_trend: asString(obj.liquidity_trend, "liquidity_snapshot.liquidity_trend"),
364
461
  server_time_ms: asNumber(obj.server_time_ms, "liquidity_snapshot.server_time_ms"),
462
+ watched: optionalBoolean(obj.watched, "liquidity_snapshot.watched") ?? false,
365
463
  };
366
464
  }
367
465
  case "balance_update": {
@@ -382,7 +480,7 @@ export function serverMessageFromUnknown(value: unknown): ServerMessage {
382
480
  };
383
481
  }
384
482
  case "position_opened": {
385
- return {
483
+ const msg: PositionOpenedServerMessage = {
386
484
  type: "position_opened",
387
485
  position_id: asNumber(obj.position_id, "position_opened.position_id"),
388
486
  wallet_pubkey: asString(
@@ -405,10 +503,45 @@ export function serverMessageFromUnknown(value: unknown): ServerMessage {
405
503
  "position_opened.market_context",
406
504
  ),
407
505
  slot: asNumber(obj.slot, "position_opened.slot"),
506
+ watched: false,
408
507
  };
508
+ const token_name = optionalString(obj.token_name, "position_opened.token_name");
509
+ if (token_name !== undefined) {
510
+ msg.token_name = token_name;
511
+ }
512
+ const token_symbol = optionalString(obj.token_symbol, "position_opened.token_symbol");
513
+ if (token_symbol !== undefined) {
514
+ msg.token_symbol = token_symbol;
515
+ }
516
+ const token_decimals = optionalNumber(obj.token_decimals, "position_opened.token_decimals");
517
+ if (token_decimals !== undefined) {
518
+ msg.token_decimals = token_decimals;
519
+ }
520
+ const token_price_quote = optionalNumber(obj.token_price_quote, "position_opened.token_price_quote");
521
+ if (token_price_quote !== undefined) {
522
+ msg.token_price_quote = token_price_quote;
523
+ }
524
+ const market_cap_quote = optionalNumber(obj.market_cap_quote, "position_opened.market_cap_quote");
525
+ if (market_cap_quote !== undefined) {
526
+ msg.market_cap_quote = market_cap_quote;
527
+ }
528
+ const pool_liquidity_quote = optionalNumber(obj.pool_liquidity_quote, "position_opened.pool_liquidity_quote");
529
+ if (pool_liquidity_quote !== undefined) {
530
+ msg.pool_liquidity_quote = pool_liquidity_quote;
531
+ }
532
+ const opened_at_ms = optionalNumber(obj.opened_at_ms, "position_opened.opened_at_ms");
533
+ if (opened_at_ms !== undefined) {
534
+ msg.opened_at_ms = opened_at_ms;
535
+ }
536
+ const mirror_source = optionalString(obj.mirror_source, "position_opened.mirror_source");
537
+ if (mirror_source !== undefined) {
538
+ msg.mirror_source = mirror_source;
539
+ }
540
+ msg.watched = optionalBoolean(obj.watched, "position_opened.watched") ?? false;
541
+ return msg;
409
542
  }
410
543
  case "position_closed": {
411
- return {
544
+ const msg: PositionClosedServerMessage = {
412
545
  type: "position_closed",
413
546
  position_id: asNumber(obj.position_id, "position_closed.position_id"),
414
547
  wallet_pubkey: asString(
@@ -422,10 +555,17 @@ export function serverMessageFromUnknown(value: unknown): ServerMessage {
422
555
  ),
423
556
  reason: asString(obj.reason, "position_closed.reason"),
424
557
  slot: asNumber(obj.slot, "position_closed.slot"),
558
+ watched: false,
425
559
  };
560
+ const mirror_source = optionalString(obj.mirror_source, "position_closed.mirror_source");
561
+ if (mirror_source !== undefined) {
562
+ msg.mirror_source = mirror_source;
563
+ }
564
+ msg.watched = optionalBoolean(obj.watched, "position_closed.watched") ?? false;
565
+ return msg;
426
566
  }
427
567
  case "exit_signal_with_tx": {
428
- return {
568
+ const msg: ExitSignalWithTxServerMessage = {
429
569
  type: "exit_signal_with_tx",
430
570
  session_id: asNumber(obj.session_id, "exit_signal_with_tx.session_id"),
431
571
  position_id: asNumber(obj.position_id, "exit_signal_with_tx.position_id"),
@@ -460,6 +600,35 @@ export function serverMessageFromUnknown(value: unknown): ServerMessage {
460
600
  obj.unsigned_tx_b64,
461
601
  "exit_signal_with_tx.unsigned_tx_b64",
462
602
  ),
603
+ watched: false,
604
+ };
605
+ const sell_tokens = optionalNumber(obj.sell_tokens, "exit_signal_with_tx.sell_tokens");
606
+ if (sell_tokens !== undefined) {
607
+ msg.sell_tokens = sell_tokens;
608
+ }
609
+ const level_index = optionalNumber(obj.level_index, "exit_signal_with_tx.level_index");
610
+ if (level_index !== undefined) {
611
+ msg.level_index = level_index;
612
+ }
613
+ const mirror_source = optionalString(obj.mirror_source, "exit_signal_with_tx.mirror_source");
614
+ if (mirror_source !== undefined) {
615
+ msg.mirror_source = mirror_source;
616
+ }
617
+ msg.watched = optionalBoolean(obj.watched, "exit_signal_with_tx.watched") ?? false;
618
+ return msg;
619
+ }
620
+ case "trade_tick": {
621
+ return {
622
+ type: "trade_tick",
623
+ position_id: asNumber(obj.position_id, "trade_tick.position_id"),
624
+ time_ms: asNumber(obj.time_ms, "trade_tick.time_ms"),
625
+ side: asString(obj.side, "trade_tick.side"),
626
+ token_amount: asNumber(obj.token_amount, "trade_tick.token_amount"),
627
+ quote_amount: asNumber(obj.quote_amount, "trade_tick.quote_amount"),
628
+ price_quote: asNumber(obj.price_quote, "trade_tick.price_quote"),
629
+ maker: optionalString(obj.maker, "trade_tick.maker"),
630
+ tx_signature: optionalString(obj.tx_signature, "trade_tick.tx_signature"),
631
+ watched: optionalBoolean(obj.watched, "trade_tick.watched") ?? false,
463
632
  };
464
633
  }
465
634
  default:
@@ -518,6 +687,34 @@ function parseStrategyConfig(value: unknown): StrategyConfigMsg {
518
687
  result.sell_on_graduation = sellOnGraduation;
519
688
  }
520
689
 
690
+ const rawLevels = obj.take_profit_levels;
691
+ if (Array.isArray(rawLevels)) {
692
+ result.take_profit_levels = rawLevels.map(
693
+ (item: unknown, idx: number) => {
694
+ const level = asRecord(item, `strategy.take_profit_levels[${idx}]`);
695
+ return {
696
+ profit_pct: asNumber(level.profit_pct, `strategy.take_profit_levels[${idx}].profit_pct`),
697
+ sell_pct: asNumber(level.sell_pct, `strategy.take_profit_levels[${idx}].sell_pct`),
698
+ trailing_stop_pct: asNumber(level.trailing_stop_pct, `strategy.take_profit_levels[${idx}].trailing_stop_pct`),
699
+ };
700
+ },
701
+ );
702
+ } else {
703
+ result.take_profit_levels = [];
704
+ }
705
+
706
+ const liquidityGuard = optionalBoolean(
707
+ obj.liquidity_guard,
708
+ "strategy.liquidity_guard",
709
+ );
710
+ result.liquidity_guard = liquidityGuard ?? false;
711
+
712
+ const breakevenTrailPct = optionalNumber(
713
+ obj.breakeven_trail_pct,
714
+ "strategy.breakeven_trail_pct",
715
+ );
716
+ result.breakeven_trail_pct = breakevenTrailPct ?? 0;
717
+
521
718
  return result;
522
719
  }
523
720
 
@@ -545,6 +742,11 @@ function parseLimits(value: unknown): LimitsMsg {
545
742
  obj.max_sessions_per_api_key,
546
743
  "limits.max_sessions_per_api_key",
547
744
  ) ?? 0,
745
+ max_watch_wallets_per_session:
746
+ optionalNumber(
747
+ obj.max_watch_wallets_per_session,
748
+ "limits.max_watch_wallets_per_session",
749
+ ) ?? 0,
548
750
  };
549
751
  }
550
752
 
@@ -594,6 +796,38 @@ function parseMarketType(value: unknown, path: string): MarketTypeMsg {
594
796
  }
595
797
  }
596
798
 
799
+ function parseWatchWallets(value: unknown): WatchWalletEntryMsg[] {
800
+ if (!Array.isArray(value)) {
801
+ throw new Error("watch_wallets must be an array");
802
+ }
803
+ return value.map((item: unknown, idx: number) => {
804
+ const entry = asRecord(item, `watch_wallets[${idx}]`);
805
+ const result: WatchWalletEntryMsg = {
806
+ pubkey: asString(entry.pubkey, `watch_wallets[${idx}].pubkey`),
807
+ };
808
+ if (entry.auto_buy !== undefined && entry.auto_buy !== null) {
809
+ const ab = asRecord(entry.auto_buy, `watch_wallets[${idx}].auto_buy`);
810
+ const autoBuy: AutoBuyConfigMsg = {
811
+ wallet_pubkey: asString(ab.wallet_pubkey, `watch_wallets[${idx}].auto_buy.wallet_pubkey`),
812
+ amount_quote_units: asNumber(ab.amount_quote_units, `watch_wallets[${idx}].auto_buy.amount_quote_units`),
813
+ };
814
+ const usd1 = optionalNumber(ab.amount_usd1_units, `watch_wallets[${idx}].auto_buy.amount_usd1_units`);
815
+ if (usd1 !== undefined) {
816
+ autoBuy.amount_usd1_units = usd1;
817
+ }
818
+ result.auto_buy = autoBuy;
819
+ }
820
+ return result;
821
+ });
822
+ }
823
+
824
+ function optionalWatchWallets(value: unknown): WatchWalletEntryMsg[] | undefined {
825
+ if (value === undefined || value === null) {
826
+ return undefined;
827
+ }
828
+ return parseWatchWallets(value);
829
+ }
830
+
597
831
  function optionalBoolean(value: unknown, path: string): boolean | undefined {
598
832
  if (value === undefined || value === null) {
599
833
  return undefined;
@@ -23,6 +23,15 @@ export interface PositionHandle {
23
23
  token_program?: string;
24
24
  tokens: number;
25
25
  entry_quote_units: number;
26
+ token_name?: string;
27
+ token_symbol?: string;
28
+ token_decimals?: number;
29
+ market_type?: string;
30
+ launch_platform?: string;
31
+ token_price_quote?: number;
32
+ market_cap_quote?: number;
33
+ pool_liquidity_quote?: number;
34
+ opened_at_ms?: number;
26
35
  }
27
36
 
28
37
  export type StreamEvent =
@@ -54,6 +63,11 @@ export type StreamEvent =
54
63
  type: "liquidity_snapshot";
55
64
  handle?: PositionHandle;
56
65
  message: ServerMessage;
66
+ }
67
+ | {
68
+ type: "trade_tick";
69
+ handle?: PositionHandle;
70
+ message: ServerMessage;
57
71
  };
58
72
 
59
73
  export class StreamSession {
@@ -174,14 +188,24 @@ export class StreamSession {
174
188
  private applyMessage(message: ServerMessage): StreamEvent {
175
189
  switch (message.type) {
176
190
  case "position_opened": {
191
+ const msg = message;
177
192
  const handle: PositionHandle = {
178
- position_id: message.position_id,
179
- token_account: message.token_account,
180
- wallet_pubkey: message.wallet_pubkey,
181
- mint: message.mint,
182
- token_program: message.token_program,
183
- tokens: message.tokens,
184
- entry_quote_units: message.entry_quote_units,
193
+ position_id: msg.position_id,
194
+ token_account: msg.token_account,
195
+ wallet_pubkey: msg.wallet_pubkey,
196
+ mint: msg.mint,
197
+ token_program: msg.token_program,
198
+ tokens: msg.tokens,
199
+ entry_quote_units: msg.entry_quote_units,
200
+ token_name: msg.token_name,
201
+ token_symbol: msg.token_symbol,
202
+ token_decimals: msg.token_decimals,
203
+ market_type: msg.market_context?.market_type?.toLowerCase(),
204
+ launch_platform: undefined,
205
+ token_price_quote: msg.token_price_quote,
206
+ market_cap_quote: msg.market_cap_quote,
207
+ pool_liquidity_quote: msg.pool_liquidity_quote,
208
+ opened_at_ms: msg.opened_at_ms,
185
209
  };
186
210
 
187
211
  this.positionsById.set(message.position_id, handle);
@@ -237,6 +261,14 @@ export class StreamSession {
237
261
  message,
238
262
  };
239
263
  }
264
+ case "trade_tick": {
265
+ const handle = this.findPosition(message.position_id);
266
+ return {
267
+ type: "trade_tick",
268
+ handle: handle ? { ...handle } : undefined,
269
+ message,
270
+ };
271
+ }
240
272
  default: {
241
273
  return {
242
274
  type: "message",
@@ -403,5 +435,8 @@ function defaultStrategy(): StrategyConfigMsg {
403
435
  return {
404
436
  target_profit_pct: 0,
405
437
  stop_loss_pct: 0,
438
+ take_profit_levels: [],
439
+ liquidity_guard: false,
440
+ breakeven_trail_pct: 0,
406
441
  };
407
442
  }