sol-parser-sdk 0.5.9

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.
Files changed (190) hide show
  1. package/.env.example +24 -0
  2. package/LICENSE +21 -0
  3. package/README.md +236 -0
  4. package/README_CN.md +236 -0
  5. package/dist/accounts/mod.d.ts +15 -0
  6. package/dist/accounts/mod.js +173 -0
  7. package/dist/accounts/nonce.d.ts +5 -0
  8. package/dist/accounts/nonce.js +32 -0
  9. package/dist/accounts/pumpfun.d.ts +16 -0
  10. package/dist/accounts/pumpfun.js +538 -0
  11. package/dist/accounts/pumpswap.d.ts +8 -0
  12. package/dist/accounts/pumpswap.js +192 -0
  13. package/dist/accounts/raydium_orca.d.ts +26 -0
  14. package/dist/accounts/raydium_orca.js +453 -0
  15. package/dist/accounts/rpc_wallet.d.ts +5 -0
  16. package/dist/accounts/rpc_wallet.js +18 -0
  17. package/dist/accounts/rust_aliases.d.ts +10 -0
  18. package/dist/accounts/rust_aliases.js +21 -0
  19. package/dist/accounts/token.d.ts +5 -0
  20. package/dist/accounts/token.js +98 -0
  21. package/dist/accounts/types.d.ts +9 -0
  22. package/dist/accounts/types.js +2 -0
  23. package/dist/accounts/utils.d.ts +1 -0
  24. package/dist/accounts/utils.js +12 -0
  25. package/dist/accounts/wallet_resolve.d.ts +1 -0
  26. package/dist/accounts/wallet_resolve.js +28 -0
  27. package/dist/common/constants.d.ts +10 -0
  28. package/dist/common/constants.js +13 -0
  29. package/dist/core/account_dispatcher_rpc.d.ts +11 -0
  30. package/dist/core/account_dispatcher_rpc.js +155 -0
  31. package/dist/core/account_fill_bonk.d.ts +4 -0
  32. package/dist/core/account_fill_bonk.js +20 -0
  33. package/dist/core/account_fill_meteora.d.ts +15 -0
  34. package/dist/core/account_fill_meteora.js +27 -0
  35. package/dist/core/account_fill_orca.d.ts +5 -0
  36. package/dist/core/account_fill_orca.js +18 -0
  37. package/dist/core/account_fill_pumpfun.d.ts +7 -0
  38. package/dist/core/account_fill_pumpfun.js +167 -0
  39. package/dist/core/account_fill_pumpswap.d.ts +10 -0
  40. package/dist/core/account_fill_pumpswap.js +128 -0
  41. package/dist/core/account_fill_raydium.d.ts +20 -0
  42. package/dist/core/account_fill_raydium.js +104 -0
  43. package/dist/core/account_fill_raydium_launchlab.d.ts +4 -0
  44. package/dist/core/account_fill_raydium_launchlab.js +20 -0
  45. package/dist/core/account_pubkey_cache.d.ts +12 -0
  46. package/dist/core/account_pubkey_cache.js +26 -0
  47. package/dist/core/clock.d.ts +8 -0
  48. package/dist/core/clock.js +20 -0
  49. package/dist/core/common_filler_rpc.d.ts +6 -0
  50. package/dist/core/common_filler_rpc.js +21 -0
  51. package/dist/core/dex_event.d.ts +1704 -0
  52. package/dist/core/dex_event.js +14 -0
  53. package/dist/core/error.d.ts +43 -0
  54. package/dist/core/error.js +16 -0
  55. package/dist/core/json_utils.d.ts +8 -0
  56. package/dist/core/json_utils.js +18 -0
  57. package/dist/core/metadata.d.ts +11 -0
  58. package/dist/core/metadata.js +13 -0
  59. package/dist/core/pumpfun_fee_enrich.d.ts +6 -0
  60. package/dist/core/pumpfun_fee_enrich.js +159 -0
  61. package/dist/core/rpc_invoke_map.d.ts +23 -0
  62. package/dist/core/rpc_invoke_map.js +157 -0
  63. package/dist/core/unified_parser.d.ts +19 -0
  64. package/dist/core/unified_parser.js +50 -0
  65. package/dist/grpc/client.d.ts +83 -0
  66. package/dist/grpc/client.js +645 -0
  67. package/dist/grpc/client_stub.d.ts +5 -0
  68. package/dist/grpc/client_stub.js +5 -0
  69. package/dist/grpc/event_parser.d.ts +6 -0
  70. package/dist/grpc/event_parser.js +15 -0
  71. package/dist/grpc/geyser_connect.d.ts +30 -0
  72. package/dist/grpc/geyser_connect.js +40 -0
  73. package/dist/grpc/log_instr_dedup.d.ts +2 -0
  74. package/dist/grpc/log_instr_dedup.js +402 -0
  75. package/dist/grpc/order_buffer.d.ts +27 -0
  76. package/dist/grpc/order_buffer.js +166 -0
  77. package/dist/grpc/program_ids.d.ts +27 -0
  78. package/dist/grpc/program_ids.js +61 -0
  79. package/dist/grpc/rpc_to_grpc.d.ts +18 -0
  80. package/dist/grpc/rpc_to_grpc.js +127 -0
  81. package/dist/grpc/subscribe_builder.d.ts +13 -0
  82. package/dist/grpc/subscribe_builder.js +66 -0
  83. package/dist/grpc/transaction_meta.d.ts +29 -0
  84. package/dist/grpc/transaction_meta.js +208 -0
  85. package/dist/grpc/types.d.ts +195 -0
  86. package/dist/grpc/types.js +551 -0
  87. package/dist/grpc/yellowstone_parse.d.ts +16 -0
  88. package/dist/grpc/yellowstone_parse.js +62 -0
  89. package/dist/index.d.ts +50 -0
  90. package/dist/index.js +298 -0
  91. package/dist/instr/bonk_ix.d.ts +8 -0
  92. package/dist/instr/bonk_ix.js +131 -0
  93. package/dist/instr/inner.d.ts +4 -0
  94. package/dist/instr/inner.js +453 -0
  95. package/dist/instr/meteora_damm_ix.d.ts +8 -0
  96. package/dist/instr/meteora_damm_ix.js +601 -0
  97. package/dist/instr/meteora_dlmm_ix.d.ts +2 -0
  98. package/dist/instr/meteora_dlmm_ix.js +134 -0
  99. package/dist/instr/meteora_pools_ix.d.ts +2 -0
  100. package/dist/instr/meteora_pools_ix.js +78 -0
  101. package/dist/instr/mod.d.ts +18 -0
  102. package/dist/instr/mod.js +129 -0
  103. package/dist/instr/orca_whirlpool_ix.d.ts +8 -0
  104. package/dist/instr/orca_whirlpool_ix.js +119 -0
  105. package/dist/instr/program_ids.d.ts +4 -0
  106. package/dist/instr/program_ids.js +20 -0
  107. package/dist/instr/pump_fees_ix.d.ts +2 -0
  108. package/dist/instr/pump_fees_ix.js +168 -0
  109. package/dist/instr/pumpfun_ix.d.ts +6 -0
  110. package/dist/instr/pumpfun_ix.js +448 -0
  111. package/dist/instr/pumpswap_ix.d.ts +5 -0
  112. package/dist/instr/pumpswap_ix.js +270 -0
  113. package/dist/instr/raydium_amm_v4_ix.d.ts +6 -0
  114. package/dist/instr/raydium_amm_v4_ix.js +112 -0
  115. package/dist/instr/raydium_clmm_ix.d.ts +5 -0
  116. package/dist/instr/raydium_clmm_ix.js +184 -0
  117. package/dist/instr/raydium_cpmm_ix.d.ts +5 -0
  118. package/dist/instr/raydium_cpmm_ix.js +109 -0
  119. package/dist/instr/raydium_launchlab_ix.d.ts +8 -0
  120. package/dist/instr/raydium_launchlab_ix.js +125 -0
  121. package/dist/instr/rust_aliases.d.ts +10 -0
  122. package/dist/instr/rust_aliases.js +20 -0
  123. package/dist/instr/utils.d.ts +10 -0
  124. package/dist/instr/utils.js +35 -0
  125. package/dist/logs/discriminator_lut.d.ts +19 -0
  126. package/dist/logs/discriminator_lut.js +62 -0
  127. package/dist/logs/meteora_amm.d.ts +8 -0
  128. package/dist/logs/meteora_amm.js +113 -0
  129. package/dist/logs/meteora_damm.d.ts +5 -0
  130. package/dist/logs/meteora_damm.js +367 -0
  131. package/dist/logs/meteora_dbc.d.ts +11 -0
  132. package/dist/logs/meteora_dbc.js +142 -0
  133. package/dist/logs/meteora_dlmm.d.ts +6 -0
  134. package/dist/logs/meteora_dlmm.js +201 -0
  135. package/dist/logs/optimized_matcher.d.ts +11 -0
  136. package/dist/logs/optimized_matcher.js +941 -0
  137. package/dist/logs/orca.d.ts +6 -0
  138. package/dist/logs/orca.js +148 -0
  139. package/dist/logs/program_data.d.ts +2 -0
  140. package/dist/logs/program_data.js +20 -0
  141. package/dist/logs/program_log_discriminators.d.ts +80 -0
  142. package/dist/logs/program_log_discriminators.js +88 -0
  143. package/dist/logs/pump.d.ts +14 -0
  144. package/dist/logs/pump.js +378 -0
  145. package/dist/logs/pump_amm.d.ts +9 -0
  146. package/dist/logs/pump_amm.js +418 -0
  147. package/dist/logs/pump_fees.d.ts +23 -0
  148. package/dist/logs/pump_fees.js +364 -0
  149. package/dist/logs/raydium_amm.d.ts +9 -0
  150. package/dist/logs/raydium_amm.js +224 -0
  151. package/dist/logs/raydium_clmm.d.ts +17 -0
  152. package/dist/logs/raydium_clmm.js +624 -0
  153. package/dist/logs/raydium_cpmm.d.ts +7 -0
  154. package/dist/logs/raydium_cpmm.js +121 -0
  155. package/dist/logs/raydium_launchlab.d.ts +10 -0
  156. package/dist/logs/raydium_launchlab.js +84 -0
  157. package/dist/logs/raydium_launchpad.d.ts +12 -0
  158. package/dist/logs/raydium_launchpad.js +92 -0
  159. package/dist/logs/rust_aliases.d.ts +7 -0
  160. package/dist/logs/rust_aliases.js +16 -0
  161. package/dist/parser_alias.d.ts +3 -0
  162. package/dist/parser_alias.js +2 -0
  163. package/dist/rpc_parser.d.ts +17 -0
  164. package/dist/rpc_parser.js +39 -0
  165. package/dist/rpc_transaction.d.ts +27 -0
  166. package/dist/rpc_transaction.js +416 -0
  167. package/dist/shredstream/alt_lookup.d.ts +9 -0
  168. package/dist/shredstream/alt_lookup.js +70 -0
  169. package/dist/shredstream/client.d.ts +65 -0
  170. package/dist/shredstream/client.js +403 -0
  171. package/dist/shredstream/config.d.ts +30 -0
  172. package/dist/shredstream/config.js +34 -0
  173. package/dist/shredstream/entries_decode.d.ts +28 -0
  174. package/dist/shredstream/entries_decode.js +251 -0
  175. package/dist/shredstream/index.d.ts +17 -0
  176. package/dist/shredstream/index.js +33 -0
  177. package/dist/shredstream/instruction_parse.d.ts +34 -0
  178. package/dist/shredstream/instruction_parse.js +79 -0
  179. package/dist/shredstream/proto_types.d.ts +9 -0
  180. package/dist/shredstream/proto_types.js +2 -0
  181. package/dist/shredstream/shredstream.proto +15 -0
  182. package/dist/shredstream/wire_to_shred_tx.d.ts +2 -0
  183. package/dist/shredstream/wire_to_shred_tx.js +59 -0
  184. package/dist/util/binary.d.ts +14 -0
  185. package/dist/util/binary.js +82 -0
  186. package/dist/util/market.d.ts +18 -0
  187. package/dist/util/market.js +54 -0
  188. package/dist/warmup.d.ts +3 -0
  189. package/dist/warmup.js +23 -0
  190. package/package.json +61 -0
@@ -0,0 +1,30 @@
1
+ /**
2
+ * 与 Rust `sol-parser-sdk/src/grpc/geyser_connect.rs` 对齐:Yellowstone Geyser gRPC 连接选项。
3
+ *
4
+ * `@triton-one/yellowstone-grpc` 的 `Client` 通过构造函数第三参传入 `ChannelOptions`;
5
+ * `connectTimeoutMs` 无与 tonic 完全一一对应的项,仅作文档与默认值对齐(可配合环境网络调优)。
6
+ */
7
+ import type { ChannelOptions } from "@grpc/grpc-js";
8
+ import Client from "@triton-one/yellowstone-grpc";
9
+ /** 与 Rust `GeyserConnectConfig` 字段对应(毫秒 / 字节) */
10
+ export interface GeyserConnectConfig {
11
+ /** 对应 Rust `connect_timeout`(毫秒) */
12
+ connectTimeoutMs: number;
13
+ /** 对应 Rust `max_decoding_message_size` */
14
+ maxDecodingMessageSize: number;
15
+ /** 对应 Rust `x_token` */
16
+ xToken?: string;
17
+ /** gRPC 通道 HTTP/2 keepalive 间隔(毫秒),与 Rust `ClientConfig.keep_alive_interval_ms` 默认对齐 */
18
+ keepAliveIntervalMs?: number;
19
+ /** gRPC keepalive 应答超时(毫秒) */
20
+ keepAliveTimeoutMs?: number;
21
+ }
22
+ /** 与 Rust `GeyserConnectConfig::default` 一致 */
23
+ export declare function defaultGeyserConnectConfig(): GeyserConnectConfig;
24
+ /** 与 `ClientConfig` / `grpc.keepalive_*` 对齐,用于长连接抗 NAT/负载均衡 idle 断开 */
25
+ export declare function geyserGrpcChannelOptions(config?: GeyserConnectConfig): ChannelOptions;
26
+ /**
27
+ * 建立 Yellowstone Geyser 客户端(与 Rust `connect_yellowstone_geyser` 一致)。
28
+ * Rust 为 async;此处构造同步完成,返回 `Promise` 以保持 `await connectYellowstoneGeyser(...)` 写法。
29
+ */
30
+ export declare function connectYellowstoneGeyser(endpoint: string, config?: GeyserConnectConfig): Promise<Client>;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.defaultGeyserConnectConfig = defaultGeyserConnectConfig;
7
+ exports.geyserGrpcChannelOptions = geyserGrpcChannelOptions;
8
+ exports.connectYellowstoneGeyser = connectYellowstoneGeyser;
9
+ const yellowstone_grpc_1 = __importDefault(require("@triton-one/yellowstone-grpc"));
10
+ /** 与 Rust `GeyserConnectConfig::default` 一致 */
11
+ function defaultGeyserConnectConfig() {
12
+ return {
13
+ connectTimeoutMs: 8000,
14
+ maxDecodingMessageSize: 1024 * 1024 * 1024,
15
+ xToken: undefined,
16
+ keepAliveIntervalMs: 30_000,
17
+ keepAliveTimeoutMs: 5000,
18
+ };
19
+ }
20
+ /** 与 `ClientConfig` / `grpc.keepalive_*` 对齐,用于长连接抗 NAT/负载均衡 idle 断开 */
21
+ function geyserGrpcChannelOptions(config = defaultGeyserConnectConfig()) {
22
+ const max = config.maxDecodingMessageSize;
23
+ const interval = config.keepAliveIntervalMs ?? 30_000;
24
+ const timeout = config.keepAliveTimeoutMs ?? 5000;
25
+ return {
26
+ "grpc.max_receive_message_length": max,
27
+ "grpc.max_send_message_length": max,
28
+ "grpc.keepalive_time_ms": interval,
29
+ "grpc.keepalive_timeout_ms": timeout,
30
+ /** 无活跃 RPC 时仍发 keepalive,避免长时间仅订阅时被中间设备掐断 */
31
+ "grpc.keepalive_permit_without_calls": 1,
32
+ };
33
+ }
34
+ /**
35
+ * 建立 Yellowstone Geyser 客户端(与 Rust `connect_yellowstone_geyser` 一致)。
36
+ * Rust 为 async;此处构造同步完成,返回 `Promise` 以保持 `await connectYellowstoneGeyser(...)` 写法。
37
+ */
38
+ async function connectYellowstoneGeyser(endpoint, config = defaultGeyserConnectConfig()) {
39
+ return new yellowstone_grpc_1.default(endpoint, config.xToken, geyserGrpcChannelOptions(config));
40
+ }
@@ -0,0 +1,2 @@
1
+ import type { DexEvent } from "../core/dex_event.js";
2
+ export declare function dedupeLogInstructionEvents(logEvents: DexEvent[], instructionEvents: DexEvent[]): DexEvent[];
@@ -0,0 +1,402 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.dedupeLogInstructionEvents = dedupeLogInstructionEvents;
4
+ const dex_event_js_1 = require("../core/dex_event.js");
5
+ const ZERO = (0, dex_event_js_1.defaultPubkey)();
6
+ const PUMPFUN_TRADE_NAMES = new Set([
7
+ "PumpFunTrade",
8
+ "PumpFunBuy",
9
+ "PumpFunSell",
10
+ "PumpFunBuyExactSolIn",
11
+ ]);
12
+ function eventName(ev) {
13
+ return Object.keys(ev)[0] ?? "";
14
+ }
15
+ function payload(ev) {
16
+ const key = eventName(ev);
17
+ return key ? ev[key] : null;
18
+ }
19
+ function isDefaultPubkey(v) {
20
+ return v === "" || v === ZERO || v == null;
21
+ }
22
+ function fillString(to, key, from) {
23
+ const value = from[key];
24
+ if (isDefaultPubkey(to[key]) && !isDefaultPubkey(value)) {
25
+ to[key] = value;
26
+ }
27
+ }
28
+ function fillNonZero(to, key, from) {
29
+ const value = from[key];
30
+ if ((to[key] == null || to[key] === 0n || to[key] === 0) && value != null && value !== 0n && value !== 0) {
31
+ to[key] = value;
32
+ }
33
+ }
34
+ function fillNestedString(to, parent, key, from) {
35
+ const srcParent = from[parent];
36
+ if (!srcParent || typeof srcParent !== "object")
37
+ return;
38
+ if (!to[parent] || typeof to[parent] !== "object")
39
+ to[parent] = {};
40
+ fillString(to[parent], key, srcParent);
41
+ }
42
+ function fillIxName(to, from) {
43
+ if ((to.ix_name ?? "") === "" && (from.ix_name ?? "") !== "") {
44
+ to.ix_name = from.ix_name;
45
+ }
46
+ }
47
+ function ixLane(ixName) {
48
+ switch (ixName) {
49
+ case "sell":
50
+ case "sell_v2":
51
+ return 1;
52
+ case "buy_exact_sol_in":
53
+ case "buy_exact_quote_in":
54
+ case "buy_exact_quote_in_v2":
55
+ return 2;
56
+ default:
57
+ return 0;
58
+ }
59
+ }
60
+ function nextOccurrence(base, counts) {
61
+ const current = counts.get(base) ?? 0;
62
+ counts.set(base, current + 1);
63
+ return current;
64
+ }
65
+ function dedupeKey(ev, pumpfunLaneCounts) {
66
+ const name = eventName(ev);
67
+ const data = payload(ev);
68
+ if (!data)
69
+ return null;
70
+ if (PUMPFUN_TRADE_NAMES.has(name)) {
71
+ const lane = ixLane(data.ix_name);
72
+ const base = `${data.mint}|${data.user}|${Boolean(data.is_buy)}|${lane}`;
73
+ const occurrence = nextOccurrence(base, pumpfunLaneCounts);
74
+ return `PumpFunTrade|${base}|${occurrence}`;
75
+ }
76
+ switch (name) {
77
+ case "PumpFunCreate":
78
+ return `PumpFunCreate|${data.mint}`;
79
+ case "PumpFunCreateV2":
80
+ return `PumpFunCreate|${data.mint}`;
81
+ case "PumpFunMigrate":
82
+ return `PumpFunMigrate|${data.mint}|${data.pool}|${data.user}`;
83
+ case "RaydiumLaunchlabTrade":
84
+ return `RaydiumLaunchlabTrade|${data.pool_state}|${data.user}|${Boolean(data.is_buy)}`;
85
+ case "RaydiumLaunchlabPoolCreate":
86
+ return `RaydiumLaunchlabPoolCreate|${data.pool_state}`;
87
+ case "RaydiumLaunchlabMigrateAmm":
88
+ return `RaydiumLaunchlabMigrateAmm|${data.old_pool}|${data.new_pool}|${data.user}`;
89
+ case "PumpSwapTrade":
90
+ return `PumpSwapTrade|${data.mint}|${data.user}|${Boolean(data.is_buy)}|${ixLane(data.ix_name)}`;
91
+ case "PumpSwapBuy":
92
+ return `PumpSwapBuy|${data.pool}|${data.user}`;
93
+ case "PumpSwapSell":
94
+ return `PumpSwapSell|${data.pool}|${data.user}`;
95
+ case "PumpSwapCreatePool":
96
+ return `PumpSwapCreatePool|${data.pool}|${data.base_mint}|${data.quote_mint}`;
97
+ case "PumpSwapLiquidityAdded":
98
+ return `PumpSwapLiquidityAdded|${data.pool}|${data.user}`;
99
+ case "PumpSwapLiquidityRemoved":
100
+ return `PumpSwapLiquidityRemoved|${data.pool}|${data.user}`;
101
+ case "RaydiumClmmSwap":
102
+ return `RaydiumClmmSwap|${data.pool_state}|${Boolean(data.zero_for_one)}`;
103
+ case "RaydiumAmmV4Swap":
104
+ return `RaydiumAmmV4Swap|${data.amm}`;
105
+ case "MeteoraDlmmSwap":
106
+ return `MeteoraDlmmSwap|${data.pool}|${data.from}|${Boolean(data.swap_for_y)}`;
107
+ default:
108
+ return null;
109
+ }
110
+ }
111
+ function mergePumpfunTrade(log, ix) {
112
+ for (const key of [
113
+ "bonding_curve",
114
+ "bonding_curve_v2",
115
+ "associated_bonding_curve",
116
+ "associated_user",
117
+ "system_program",
118
+ "token_program",
119
+ "quote_token_program",
120
+ "associated_token_program",
121
+ "creator_vault",
122
+ "fee_recipient",
123
+ "associated_quote_fee_recipient",
124
+ "buyback_fee_recipient",
125
+ "associated_quote_buyback_fee_recipient",
126
+ "associated_quote_bonding_curve",
127
+ "associated_quote_user",
128
+ "associated_creator_vault",
129
+ "sharing_config",
130
+ "event_authority",
131
+ "program",
132
+ "global_volume_accumulator",
133
+ "user_volume_accumulator",
134
+ "associated_user_volume_accumulator",
135
+ "fee_config",
136
+ "fee_program",
137
+ "global",
138
+ "quote_mint",
139
+ "creator",
140
+ ]) {
141
+ fillString(log, key, ix);
142
+ }
143
+ if (log.account == null && ix.account != null)
144
+ log.account = ix.account;
145
+ for (const key of [
146
+ "amount",
147
+ "max_sol_cost",
148
+ "min_sol_output",
149
+ "spendable_sol_in",
150
+ "spendable_quote_in",
151
+ "min_tokens_out",
152
+ "quote_amount",
153
+ "virtual_quote_reserves",
154
+ "real_quote_reserves",
155
+ ]) {
156
+ fillNonZero(log, key, ix);
157
+ }
158
+ fillIxName(log, ix);
159
+ log.is_created_buy = Boolean(log.is_created_buy) || Boolean(ix.is_created_buy);
160
+ }
161
+ function mergePumpfunCreate(log, ix) {
162
+ for (const key of [
163
+ "name",
164
+ "symbol",
165
+ "uri",
166
+ "mint",
167
+ "bonding_curve",
168
+ "user",
169
+ "creator",
170
+ "token_program",
171
+ "quote_mint",
172
+ "quote_vault",
173
+ "quote_token_program",
174
+ ]) {
175
+ fillString(log, key, ix);
176
+ }
177
+ for (const key of [
178
+ "timestamp",
179
+ "virtual_token_reserves",
180
+ "virtual_sol_reserves",
181
+ "real_token_reserves",
182
+ "token_total_supply",
183
+ "virtual_quote_reserves",
184
+ ]) {
185
+ fillNonZero(log, key, ix);
186
+ }
187
+ fillIxName(log, ix);
188
+ log.is_mayhem_mode = Boolean(log.is_mayhem_mode) || Boolean(ix.is_mayhem_mode);
189
+ log.is_cashback_enabled =
190
+ Boolean(log.is_cashback_enabled) || Boolean(ix.is_cashback_enabled);
191
+ }
192
+ function mergePumpfunCreateV2(log, ix) {
193
+ mergePumpfunCreate(log, ix);
194
+ for (const key of [
195
+ "mint_authority",
196
+ "associated_bonding_curve",
197
+ "global",
198
+ "system_program",
199
+ "associated_token_program",
200
+ "mayhem_program_id",
201
+ "global_params",
202
+ "sol_vault",
203
+ "mayhem_state",
204
+ "mayhem_token_vault",
205
+ "event_authority",
206
+ "program",
207
+ "observed_fee_recipient",
208
+ ]) {
209
+ fillString(log, key, ix);
210
+ }
211
+ }
212
+ function mergePumpfunMigrate(log, ix) {
213
+ for (const key of ["bonding_curve", "pool", "user"]) {
214
+ fillString(log, key, ix);
215
+ }
216
+ }
217
+ function mergePumpSwapBuySell(log, ix, includeIxName) {
218
+ for (const key of [
219
+ "user_base_token_account",
220
+ "user_quote_token_account",
221
+ "protocol_fee_recipient",
222
+ "protocol_fee_recipient_token_account",
223
+ "coin_creator",
224
+ "base_mint",
225
+ "quote_mint",
226
+ "pool_base_token_account",
227
+ "pool_quote_token_account",
228
+ "coin_creator_vault_ata",
229
+ "coin_creator_vault_authority",
230
+ "base_token_program",
231
+ "quote_token_program",
232
+ "pool_v2",
233
+ "fee_recipient",
234
+ "fee_recipient_quote_token_account",
235
+ ]) {
236
+ fillString(log, key, ix);
237
+ }
238
+ if (includeIxName)
239
+ fillIxName(log, ix);
240
+ }
241
+ function mergePumpSwapCreatePool(log, ix) {
242
+ for (const key of [
243
+ "creator",
244
+ "pool",
245
+ "lp_mint",
246
+ "user_base_token_account",
247
+ "user_quote_token_account",
248
+ "coin_creator",
249
+ ]) {
250
+ fillString(log, key, ix);
251
+ }
252
+ }
253
+ function mergePumpSwapLiquidity(log, ix) {
254
+ for (const key of [
255
+ "user_base_token_account",
256
+ "user_quote_token_account",
257
+ "user_pool_token_account",
258
+ ]) {
259
+ fillString(log, key, ix);
260
+ }
261
+ }
262
+ function mergeRaydiumClmmSwap(log, ix) {
263
+ for (const key of ["token_account_0", "token_account_1", "sender"]) {
264
+ fillString(log, key, ix);
265
+ }
266
+ }
267
+ function mergeRaydiumAmmV4Swap(log, ix) {
268
+ for (const key of [
269
+ "token_program",
270
+ "amm_authority",
271
+ "amm_open_orders",
272
+ "amm_target_orders",
273
+ "pool_coin_token_account",
274
+ "pool_pc_token_account",
275
+ "serum_program",
276
+ "serum_market",
277
+ "serum_bids",
278
+ "serum_asks",
279
+ "serum_event_queue",
280
+ "serum_coin_vault_account",
281
+ "serum_pc_vault_account",
282
+ "serum_vault_signer",
283
+ "user_source_token_account",
284
+ "user_destination_token_account",
285
+ ]) {
286
+ fillString(log, key, ix);
287
+ }
288
+ }
289
+ function mergeRaydiumLaunchlabPoolCreate(log, ix) {
290
+ fillString(log, "creator", ix);
291
+ for (const key of ["name", "symbol", "uri"]) {
292
+ fillNestedString(log, "base_mint_param", key, ix);
293
+ }
294
+ }
295
+ function mergeRaydiumLaunchlabMigrateAmm(log, ix) {
296
+ for (const key of ["old_pool", "new_pool", "user"]) {
297
+ fillString(log, key, ix);
298
+ }
299
+ }
300
+ function mergeGrpcInstructionIntoLog(logEvent, ixEvent) {
301
+ const logName = eventName(logEvent);
302
+ const ixName = eventName(ixEvent);
303
+ const log = payload(logEvent);
304
+ const ix = payload(ixEvent);
305
+ if (!log || !ix)
306
+ return;
307
+ if (PUMPFUN_TRADE_NAMES.has(logName) && PUMPFUN_TRADE_NAMES.has(ixName)) {
308
+ mergePumpfunTrade(log, ix);
309
+ return;
310
+ }
311
+ if (logName === "PumpFunCreate" && ixName === "PumpFunCreateV2") {
312
+ mergePumpfunCreate(log, ix);
313
+ return;
314
+ }
315
+ if (logName === "PumpFunCreateV2" && ixName === "PumpFunCreate") {
316
+ mergePumpfunCreateV2(log, ix);
317
+ return;
318
+ }
319
+ switch (logName) {
320
+ case "PumpFunCreate":
321
+ if (ixName === "PumpFunCreate")
322
+ mergePumpfunCreate(log, ix);
323
+ break;
324
+ case "PumpFunCreateV2":
325
+ if (ixName === "PumpFunCreateV2")
326
+ mergePumpfunCreateV2(log, ix);
327
+ break;
328
+ case "PumpFunMigrate":
329
+ if (ixName === "PumpFunMigrate")
330
+ mergePumpfunMigrate(log, ix);
331
+ break;
332
+ case "PumpSwapTrade":
333
+ if (ixName === "PumpSwapTrade")
334
+ fillIxName(log, ix);
335
+ break;
336
+ case "PumpSwapBuy":
337
+ if (ixName === "PumpSwapBuy")
338
+ mergePumpSwapBuySell(log, ix, true);
339
+ break;
340
+ case "PumpSwapSell":
341
+ if (ixName === "PumpSwapSell")
342
+ mergePumpSwapBuySell(log, ix, false);
343
+ break;
344
+ case "PumpSwapCreatePool":
345
+ if (ixName === "PumpSwapCreatePool")
346
+ mergePumpSwapCreatePool(log, ix);
347
+ break;
348
+ case "PumpSwapLiquidityAdded":
349
+ if (ixName === "PumpSwapLiquidityAdded")
350
+ mergePumpSwapLiquidity(log, ix);
351
+ break;
352
+ case "PumpSwapLiquidityRemoved":
353
+ if (ixName === "PumpSwapLiquidityRemoved")
354
+ mergePumpSwapLiquidity(log, ix);
355
+ break;
356
+ case "RaydiumClmmSwap":
357
+ if (ixName === "RaydiumClmmSwap")
358
+ mergeRaydiumClmmSwap(log, ix);
359
+ break;
360
+ case "RaydiumAmmV4Swap":
361
+ if (ixName === "RaydiumAmmV4Swap")
362
+ mergeRaydiumAmmV4Swap(log, ix);
363
+ break;
364
+ case "RaydiumLaunchlabPoolCreate":
365
+ if (ixName === "RaydiumLaunchlabPoolCreate")
366
+ mergeRaydiumLaunchlabPoolCreate(log, ix);
367
+ break;
368
+ case "RaydiumLaunchlabMigrateAmm":
369
+ if (ixName === "RaydiumLaunchlabMigrateAmm")
370
+ mergeRaydiumLaunchlabMigrateAmm(log, ix);
371
+ break;
372
+ default:
373
+ break;
374
+ }
375
+ }
376
+ function dedupeLogInstructionEvents(logEvents, instructionEvents) {
377
+ const out = [];
378
+ const indexByKey = new Map();
379
+ const logPumpfunLaneCounts = new Map();
380
+ const ixPumpfunLaneCounts = new Map();
381
+ for (const ev of logEvents) {
382
+ const key = dedupeKey(ev, logPumpfunLaneCounts);
383
+ if (key)
384
+ indexByKey.set(key, out.length);
385
+ out.push(ev);
386
+ }
387
+ for (const ev of instructionEvents) {
388
+ const key = dedupeKey(ev, ixPumpfunLaneCounts);
389
+ if (!key) {
390
+ out.push(ev);
391
+ continue;
392
+ }
393
+ const existing = indexByKey.get(key);
394
+ if (existing === undefined) {
395
+ indexByKey.set(key, out.length);
396
+ out.push(ev);
397
+ continue;
398
+ }
399
+ mergeGrpcInstructionIntoLog(out[existing], ev);
400
+ }
401
+ return out;
402
+ }
@@ -0,0 +1,27 @@
1
+ import type { DexEvent } from "../core/dex_event.js";
2
+ import type { ClientConfig } from "./types.js";
3
+ export declare class OrderDispatcher {
4
+ private readonly mode;
5
+ private readonly timeoutMs;
6
+ private readonly microBatchUs;
7
+ private readonly slots;
8
+ private readonly streamingWatermarks;
9
+ private microBatch;
10
+ private microBatchStartUs;
11
+ private lastFlushMs;
12
+ private currentSlot;
13
+ private seq;
14
+ constructor(config: ClientConfig);
15
+ get needsTimer(): boolean;
16
+ pushTransactionEvents(events: DexEvent[], fallbackSlot: number, fallbackTxIndex: number, emit: (event: DexEvent) => void): void;
17
+ flushDue(emit: (event: DexEvent) => void): void;
18
+ flushAll(emit: (event: DexEvent) => void): void;
19
+ private pushOrdered;
20
+ private pushStreaming;
21
+ private pushMicroBatch;
22
+ private pushSlotBatch;
23
+ private flushBefore;
24
+ private flushAllSlots;
25
+ private flushMicroBatch;
26
+ private emitBatch;
27
+ }
@@ -0,0 +1,166 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OrderDispatcher = void 0;
4
+ const dex_event_js_1 = require("../core/dex_event.js");
5
+ function eventSlotAndIndex(events, fallbackSlot, fallbackTxIndex) {
6
+ const meta = events.length > 0 ? (0, dex_event_js_1.metadataForDexEvent)(events[0]) : null;
7
+ return {
8
+ slot: Number.isFinite(meta?.slot) ? meta.slot : fallbackSlot,
9
+ txIndex: Number.isFinite(meta?.tx_index) ? meta.tx_index : fallbackTxIndex,
10
+ };
11
+ }
12
+ class OrderDispatcher {
13
+ mode;
14
+ timeoutMs;
15
+ microBatchUs;
16
+ slots = new Map();
17
+ streamingWatermarks = new Map();
18
+ microBatch = [];
19
+ microBatchStartUs = 0;
20
+ lastFlushMs = Date.now();
21
+ currentSlot = 0;
22
+ seq = 0;
23
+ constructor(config) {
24
+ this.mode = config.order_mode;
25
+ this.timeoutMs = Math.max(1, config.order_timeout_ms || 100);
26
+ this.microBatchUs = Math.max(1, config.micro_batch_us || 100);
27
+ }
28
+ get needsTimer() {
29
+ return this.mode !== "Unordered";
30
+ }
31
+ pushTransactionEvents(events, fallbackSlot, fallbackTxIndex, emit) {
32
+ if (events.length === 0)
33
+ return;
34
+ const { slot, txIndex } = eventSlotAndIndex(events, fallbackSlot, fallbackTxIndex);
35
+ const batch = { slot, txIndex, seq: this.seq++, events };
36
+ switch (this.mode) {
37
+ case "Unordered":
38
+ this.emitBatch(batch, emit);
39
+ return;
40
+ case "Ordered":
41
+ this.pushOrdered(batch, emit);
42
+ return;
43
+ case "StreamingOrdered":
44
+ this.pushStreaming(batch, emit);
45
+ return;
46
+ case "MicroBatch":
47
+ this.pushMicroBatch(batch, emit);
48
+ return;
49
+ }
50
+ }
51
+ flushDue(emit) {
52
+ const nowMs = Date.now();
53
+ if ((this.mode === "Ordered" || this.mode === "StreamingOrdered") && nowMs - this.lastFlushMs > this.timeoutMs) {
54
+ this.flushAllSlots(emit);
55
+ }
56
+ if (this.mode === "MicroBatch") {
57
+ const nowUs = Math.floor(nowMs * 1000);
58
+ if (this.microBatch.length > 0 && nowUs - this.microBatchStartUs >= this.microBatchUs) {
59
+ this.flushMicroBatch(emit);
60
+ }
61
+ }
62
+ }
63
+ flushAll(emit) {
64
+ this.flushAllSlots(emit);
65
+ this.flushMicroBatch(emit);
66
+ }
67
+ pushOrdered(batch, emit) {
68
+ if (batch.slot > this.currentSlot && this.currentSlot > 0) {
69
+ this.flushBefore(batch.slot, emit);
70
+ }
71
+ if (batch.slot > this.currentSlot)
72
+ this.currentSlot = batch.slot;
73
+ this.pushSlotBatch(batch);
74
+ }
75
+ pushStreaming(batch, emit) {
76
+ if (batch.slot > this.currentSlot && this.currentSlot > 0) {
77
+ this.flushBefore(batch.slot, emit);
78
+ for (const slot of [...this.streamingWatermarks.keys()]) {
79
+ if (slot < batch.slot)
80
+ this.streamingWatermarks.delete(slot);
81
+ }
82
+ }
83
+ if (batch.slot > this.currentSlot)
84
+ this.currentSlot = batch.slot;
85
+ const expected = this.streamingWatermarks.get(batch.slot) ?? 0;
86
+ if (batch.txIndex === expected) {
87
+ this.emitBatch(batch, emit);
88
+ let watermark = expected + 1;
89
+ const buffered = this.slots.get(batch.slot);
90
+ if (buffered) {
91
+ buffered.sort(compareBatch);
92
+ let pos = buffered.findIndex((b) => b.txIndex === watermark);
93
+ while (pos >= 0) {
94
+ const [next] = buffered.splice(pos, 1);
95
+ this.emitBatch(next, emit);
96
+ watermark += 1;
97
+ pos = buffered.findIndex((b) => b.txIndex === watermark);
98
+ }
99
+ if (buffered.length === 0)
100
+ this.slots.delete(batch.slot);
101
+ }
102
+ this.streamingWatermarks.set(batch.slot, watermark);
103
+ }
104
+ else if (batch.txIndex > expected) {
105
+ this.pushSlotBatch(batch);
106
+ }
107
+ }
108
+ pushMicroBatch(batch, emit) {
109
+ const nowUs = Math.floor(Date.now() * 1000);
110
+ if (this.microBatch.length === 0)
111
+ this.microBatchStartUs = nowUs;
112
+ this.microBatch.push(batch);
113
+ if (nowUs - this.microBatchStartUs >= this.microBatchUs) {
114
+ this.flushMicroBatch(emit);
115
+ }
116
+ }
117
+ pushSlotBatch(batch) {
118
+ const list = this.slots.get(batch.slot);
119
+ if (list)
120
+ list.push(batch);
121
+ else
122
+ this.slots.set(batch.slot, [batch]);
123
+ }
124
+ flushBefore(slot, emit) {
125
+ for (const s of [...this.slots.keys()].sort((a, b) => a - b)) {
126
+ if (s >= slot)
127
+ continue;
128
+ const batches = this.slots.get(s) ?? [];
129
+ batches.sort(compareBatch);
130
+ for (const batch of batches)
131
+ this.emitBatch(batch, emit);
132
+ this.slots.delete(s);
133
+ this.streamingWatermarks.delete(s);
134
+ }
135
+ this.lastFlushMs = Date.now();
136
+ }
137
+ flushAllSlots(emit) {
138
+ for (const s of [...this.slots.keys()].sort((a, b) => a - b)) {
139
+ const batches = this.slots.get(s) ?? [];
140
+ batches.sort(compareBatch);
141
+ for (const batch of batches)
142
+ this.emitBatch(batch, emit);
143
+ this.slots.delete(s);
144
+ this.streamingWatermarks.delete(s);
145
+ }
146
+ this.lastFlushMs = Date.now();
147
+ }
148
+ flushMicroBatch(emit) {
149
+ if (this.microBatch.length === 0)
150
+ return;
151
+ this.microBatch.sort(compareBatch);
152
+ for (const batch of this.microBatch)
153
+ this.emitBatch(batch, emit);
154
+ this.microBatch = [];
155
+ this.microBatchStartUs = 0;
156
+ this.lastFlushMs = Date.now();
157
+ }
158
+ emitBatch(batch, emit) {
159
+ for (const event of batch.events)
160
+ emit(event);
161
+ }
162
+ }
163
+ exports.OrderDispatcher = OrderDispatcher;
164
+ function compareBatch(a, b) {
165
+ return a.slot - b.slot || a.txIndex - b.txIndex || a.seq - b.seq;
166
+ }