sol-trade-sdk 4.0.9

A high-performance Rust SDK for Solana DEX trading.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
use solana_program::pubkey;
use solana_sdk::pubkey::Pubkey;

pub const JITO_TIP_ACCOUNTS: &[Pubkey] = &[
    pubkey!("96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5"),
    pubkey!("HFqU5x63VTqvQss8hp11i4wVV8bD44PvwucfZ2bU7gRe"),
    pubkey!("Cw8CFyM9FkoMi7K7Crf6HNQqf4uEMzpKw6QNghXLvLkY"),
    pubkey!("ADaUMid9yfUytqMBgopwjb2DTLSokTSzL1zt6iGPaS49"),
    pubkey!("DfXygSm4jCyNCybVYYK6DwvWqjKee8pbDmJGcLWNDXjh"),
    pubkey!("ADuUkR4vqLUMWXxW9gh6D6L8pMSawimctcNZ5pGwDcEt"),
    pubkey!("DttWaMuVvTiduZRnguLF7jNxTgiMBZ1hyAumKUiL2KRL"),
    pubkey!("3AVi9Tg9Uo68tJfuvoKvqKNWKkC5wPdSSdeBnizKZ6jT"),
];

/// Helius Sender tip accounts (fee recipient addresses).
pub const HELIUS_TIP_ACCOUNTS: &[Pubkey] = &[
    pubkey!("4ACfpUFoaSD9bfPdeu6DBt89gB6ENTeHBXCAi87NhDEE"),
    pubkey!("D2L6yPZ2FmmmTKPgzaMKdhu6EWZcTpLy1Vhx8uvZe7NZ"),
    pubkey!("9bnz4RShgq1hAnLnZbP8kbgBg1kEmcJBYQq3gQbmnSta"),
    pubkey!("5VY91ws6B2hMmBFRsXkoAAdsPHBJwRfBht4DXox3xkwn"),
    pubkey!("2nyhqdwKcJZR2vcqCyrYsaPVdAnFoJjiksCXJ7hfEYgD"),
    pubkey!("2q5pghRs6arqVjRvT5gfgWfWcHWmw1ZuCzphgd5KfWGJ"),
    pubkey!("wyvPkWjVZz1M8fHQnMMCDTQDbkManefNNhweYk5WkcF"),
    pubkey!("3KCKozbAaF75qEU33jtzozcJ29yJuaLJTy2jFdzUY8bT"),
    pubkey!("4vieeGHPYPG2MmyPRcYjdiDmmhN3ww7hsFNap8pVN3Ey"),
    pubkey!("4TQLFNWK8AovT1gFvda5jfw2oJeRMKEmw7aH6MGBJ3or"),
];

pub const NEXTBLOCK_TIP_ACCOUNTS: &[Pubkey] = &[
    pubkey!("NextbLoCkVtMGcV47JzewQdvBpLqT9TxQFozQkN98pE"),
    pubkey!("NexTbLoCkWykbLuB1NkjXgFWkX9oAtcoagQegygXXA2"),
    pubkey!("NeXTBLoCKs9F1y5PJS9CKrFNNLU1keHW71rfh7KgA1X"),
    pubkey!("NexTBLockJYZ7QD7p2byrUa6df8ndV2WSd8GkbWqfbb"),
    pubkey!("neXtBLock1LeC67jYd1QdAa32kbVeubsfPNTJC1V5At"),
    pubkey!("nEXTBLockYgngeRmRrjDV31mGSekVPqZoMGhQEZtPVG"),
    pubkey!("NEXTbLoCkB51HpLBLojQfpyVAMorm3zzKg7w9NFdqid"),
    pubkey!("nextBLoCkPMgmG8ZgJtABeScP35qLa2AMCNKntAP7Xc"),
];

pub const ZEROSLOT_TIP_ACCOUNTS: &[Pubkey] = &[
    pubkey!("Eb2KpSC8uMt9GmzyAEm5Eb1AAAgTjRaXWFjKyFXHZxF3"),
    pubkey!("FCjUJZ1qozm1e8romw216qyfQMaaWKxWsuySnumVCCNe"),
    pubkey!("ENxTEjSQ1YabmUpXAdCgevnHQ9MHdLv8tzFiuiYJqa13"),
    pubkey!("6rYLG55Q9RpsPGvqdPNJs4z5WTxJVatMB8zV3WJhs5EK"),
    pubkey!("Cix2bHfqPcKcM233mzxbLk14kSggUUiz2A87fJtGivXr"),
];

pub const NOZOMI_TIP_ACCOUNTS: &[Pubkey] = &[
    pubkey!("TEMPaMeCRFAS9EKF53Jd6KpHxgL47uWLcpFArU1Fanq"),
    pubkey!("noz3jAjPiHuBPqiSPkkugaJDkJscPuRhYnSpbi8UvC4"),
    pubkey!("noz3str9KXfpKknefHji8L1mPgimezaiUyCHYMDv1GE"),
    pubkey!("noz6uoYCDijhu1V7cutCpwxNiSovEwLdRHPwmgCGDNo"),
    pubkey!("noz9EPNcT7WH6Sou3sr3GGjHQYVkN3DNirpbvDkv9YJ"),
    pubkey!("nozc5yT15LazbLTFVZzoNZCwjh3yUtW86LoUyqsBu4L"),
    pubkey!("nozFrhfnNGoyqwVuwPAW4aaGqempx4PU6g6D9CJMv7Z"),
    pubkey!("nozievPk7HyK1Rqy1MPJwVQ7qQg2QoJGyP71oeDwbsu"),
    pubkey!("noznbgwYnBLDHu8wcQVCEw6kDrXkPdKkydGJGNXGvL7"),
    pubkey!("nozNVWs5N8mgzuD3qigrCG2UoKxZttxzZ85pvAQVrbP"),
    pubkey!("nozpEGbwx4BcGp6pvEdAh1JoC2CQGZdU6HbNP1v2p6P"),
    pubkey!("nozrhjhkCr3zXT3BiT4WCodYCUFeQvcdUkM7MqhKqge"),
    pubkey!("nozrwQtWhEdrA6W8dkbt9gnUaMs52PdAv5byipnadq3"),
    pubkey!("nozUacTVWub3cL4mJmGCYjKZTnE9RbdY5AP46iQgbPJ"),
    pubkey!("nozWCyTPppJjRuw2fpzDhhWbW355fzosWSzrrMYB1Qk"),
    pubkey!("nozWNju6dY353eMkMqURqwQEoM3SFgEKC6psLCSfUne"),
    pubkey!("nozxNBgWohjR75vdspfxR5H9ceC7XXH99xpxhVGt3Bb"),
];

pub const BLOX_TIP_ACCOUNTS: &[Pubkey] = &[
    pubkey!("HWEoBxYs7ssKuudEjzjmpfJVX7Dvi7wescFsVx2L5yoY"),
    pubkey!("95cfoy472fcQHaw4tPGBTKpn6ZQnfEPfBgDQx6gcRmRg"),
    pubkey!("3UQUKjhMKaY2S6bjcQD6yHB7utcZt5bfarRCmctpRtUd"),
    pubkey!("FogxVNs6Mm2w9rnGL1vkARSwJxvLE8mujTv3LK8RnUhF"),
];

pub const NODE1_TIP_ACCOUNTS: &[Pubkey] = &[
    pubkey!("node1PqAa3BWWzUnTHVbw8NJHC874zn9ngAkXjgWEej"),
    pubkey!("node1UzzTxAAeBTpfZkQPJXBAqixsbdth11ba1NXLBG"),
    pubkey!("node1Qm1bV4fwYnCurP8otJ9s5yrkPq7SPZ5uhj3Tsv"),
    pubkey!("node1PUber6SFmSQgvf2ECmXsHP5o3boRSGhvJyPMX1"),
    pubkey!("node1AyMbeqiVN6eoQzEAwCA6Pk826hrdqdAHR7cdJ3"),
    pubkey!("node1YtWCoTwwVYTFLfS19zquRQzYX332hs1HEuRBjC"),
];

pub const FLASHBLOCK_TIP_ACCOUNTS: &[Pubkey] = &[
    pubkey!("FLaShB3iXXTWE1vu9wQsChUKq3HFtpMAhb8kAh1pf1wi"),
    pubkey!("FLashhsorBmM9dLpuq6qATawcpqk1Y2aqaZfkd48iT3W"),
    pubkey!("FLaSHJNm5dWYzEgnHJWWJP5ccu128Mu61NJLxUf7mUXU"),
    pubkey!("FLaSHR4Vv7sttd6TyDF4yR1bJyAxRwWKbohDytEMu3wL"),
    pubkey!("FLASHRzANfcAKDuQ3RXv9hbkBy4WVEKDzoAgxJ56DiE4"),
    pubkey!("FLasHstqx11M8W56zrSEqkCyhMCCpr6ze6Mjdvqope5s"),
    pubkey!("FLAShWTjcweNT4NSotpjpxAkwxUr2we3eXQGhpTVzRwy"),
    pubkey!("FLasHXTqrbNvpWFB6grN47HGZfK6pze9HLNTgbukfPSk"),
    pubkey!("FLAshyAyBcKb39KPxSzXcepiS8iDYUhDGwJcJDPX4g2B"),
    pubkey!("FLAsHZTRcf3Dy1APaz6j74ebdMC6Xx4g6i9YxjyrDybR"),
];

pub const BLOCKRAZOR_TIP_ACCOUNTS: &[Pubkey] = &[
    pubkey!("FjmZZrFvhnqqb9ThCuMVnENaM3JGVuGWNyCAxRJcFpg9"),
    pubkey!("6No2i3aawzHsjtThw81iq1EXPJN6rh8eSJCLaYZfKDTG"),
    pubkey!("A9cWowVAiHe9pJfKAj3TJiN9VpbzMUq6E4kEvf5mUT22"),
    pubkey!("Gywj98ophM7GmkDdaWs4isqZnDdFCW7B46TXmKfvyqSm"),
    pubkey!("68Pwb4jS7eZATjDfhmTXgRJjCiZmw1L7Huy4HNpnxJ3o"),
    pubkey!("4ABhJh5rZPjv63RBJBuyWzBK3g9gWMUQdTZP2kiW31V9"),
    pubkey!("B2M4NG5eyZp5SBQrSdtemzk5TqVuaWGQnowGaCBt8GyM"),
    pubkey!("5jA59cXMKQqZAVdtopv8q3yyw9SYfiE3vUCbt7p8MfVf"),
    pubkey!("5YktoWygr1Bp9wiS1xtMtUki1PeYuuzuCF98tqwYxf61"),
    pubkey!("295Avbam4qGShBYK7E9H5Ldew4B3WyJGmgmXfiWdeeyV"),
    pubkey!("EDi4rSy2LZgKJX74mbLTFk4mxoTgT6F7HxxzG2HBAFyK"),
    pubkey!("BnGKHAC386n4Qmv9xtpBVbRaUTKixjBe3oagkPFKtoy6"),
    pubkey!("Dd7K2Fp7AtoN8xCghKDRmyqr5U169t48Tw5fEd3wT9mq"),
    pubkey!("AP6qExwrbRgBAVaehg4b5xHENX815sMabtBzUzVB4v8S"),
];

/// Astralane tip wallets. Extended with new addresses for improved routing and reduced write-lock contention (see portal.astralane.io/blockline).
pub const ASTRALANE_TIP_ACCOUNTS: &[Pubkey] = &[
    pubkey!("astrazznxsGUhWShqgNtAdfrzP2G83DzcWVJDxwV9bF"),
    pubkey!("astra4uejePWneqNaJKuFFA8oonqCE1sqF6b45kDMZm"),
    pubkey!("astra9xWY93QyfG6yM8zwsKsRodscjQ2uU2HKNL5prk"),
    pubkey!("astraRVUuTHjpwEVvNBeQEgwYx9w9CFyfxjYoobCZhL"),
    pubkey!("astraEJ2fEj8Xmy6KLG7B3VfbKfsHXhHrNdCQx7iGJK"),
    pubkey!("astraubkDw81n4LuutzSQ8uzHCv4BhPVhfvTcYv8SKC"),
    pubkey!("astraZW5GLFefxNPAatceHhYjfA1ciq9gvfEg2S47xk"),
    pubkey!("astrawVNP4xDBKT7rAdxrLYiTSTdqtUr63fSMduivXK"),
    // New tip wallets (2025) for improved performance and reduced write-lock delays
    pubkey!("AstrA1ejL4UeXC2SBP4cpeEmtcFPZVLxx3XGKXyCW6to"),
    pubkey!("AsTra79FET4aCKWspPqeSFvjJNyp96SvAnrmyAxqg5b7"),
    pubkey!("AstrABAu8CBTyuPXpV4eSCJ5fePEPnxN8NqBaPKQ9fHR"),
    pubkey!("AsTRADtvb6tTmrsqULQ9Wji9PigDMjhfEMza6zkynEvV"),
    pubkey!("AsTRAEoyMofR3vUPpf9k68Gsfb6ymTZttEtsAbv8Bk4d"),
    pubkey!("AStrAJv2RN2hKCHxwUMtqmSxgdcNZbihCwc1mCSnG83W"),
    pubkey!("Astran35aiQUF57XZsmkWMtNCtXGLzs8upfiqXxth2bz"),
    pubkey!("AStRAnpi6kFrKypragExgeRoJ1QnKH7pbSjLAKQVWUum"),
    pubkey!("ASTRaoF93eYt73TYvwtsv6fMWHWbGmMUZfVZPo3CRU9C"),
];

pub const STELLIUM_TIP_ACCOUNTS: &[Pubkey] = &[
    pubkey!("ste11JV3MLMM7x7EJUM2sXcJC1H7F4jBLnP9a9PG8PH"),
    pubkey!("ste11MWPjXCRfQryCshzi86SGhuXjF4Lv6xMXD2AoSt"),
    pubkey!("ste11p5x8tJ53H1NbNQsRBg1YNRd4GcVpxtDw8PBpmb"),
    pubkey!("ste11p7e2KLYou5bwtt35H7BM6uMdo4pvioGjJXKFcN"),
    pubkey!("ste11TMV68LMi1BguM4RQujtbNCZvf1sjsASpqgAvSX"),
];

// Lightspeed (Solana Vibe Station) tip accounts
pub const LIGHTSPEED_TIP_ACCOUNTS: &[Pubkey] = &[
    pubkey!("53PhM3UTdMQWu5t81wcd35AHGc5xpmHoRjem7GQPvXjA"),
    pubkey!("9tYF5yPDC1NP8s6diiB3kAX6ZZnva9DM3iDwJkBRarBB"),
];

pub const SOYAS_TIP_ACCOUNTS: &[Pubkey] = &[
    pubkey!("soyas4s6L8KWZ8rsSk1mF3d1mQScoTGGAgjk98bF8nP"),
    pubkey!("soyascXFW5wEEYiwfEmHy2pNwomqzvggJosGVD6TJdY"),
    pubkey!("soyasDBdKjADwPz3xk82U3TNPRDKEWJj7wWLajNHZ1L"),
    pubkey!("soyasE2abjBAynmHbGWgEwk4ctBy7JMTUCNrMbjcnyH"),
    pubkey!("soyasi59njacMUPvo3TM5paHjeK8pYSdovXgFi32gRt"),
    pubkey!("soyasQYhJxv8uZgWDxhg72td6piAf7XTkoyWHtSATEz"),
    pubkey!("soyastP66xyYC8XADXZjdMM5BAVGD2YRvz8dwtLsqb8"),
    pubkey!("soyasvdgUJWYcUCzDxpmjUnNjH7KamXLXTzLwFvdVPE"),
    pubkey!("soyasvxAunisNxaoRxkKGjNir7KmbwYnr37JmefkX9G"),
    pubkey!("soyas5doVFUwH8s5zK8gEvCL5KR5ogDmf52LsrJEZ9h"),
];

pub const SPEEDLANDING_TIP_ACCOUNTS: &[Pubkey] = &[
    pubkey!("SpEEdz8S1KorkMZqjMUxfxrmWwofmp6ReNP2Nx6CUmq"),
    pubkey!("SpeeDy3GJM4wcrQmk1itRFWgidvxX4rwjTLMv78wwjE"),
    pubkey!("SPeEdva37vW8vRtqgYjprQs1g3965icfVN5Rt7SMAyh"),
    pubkey!("speEdrSEpox5GUfHWcBc7tQjRuSfUin2yvB7qoYvvJh"),
    pubkey!("SPeEDmkHkN3A2roSZf6aZyEMsmrGqTHKqwP51y2Y4rV"),
    pubkey!("SpeedLdTJXh2RKpXEaP8JCxkWoUVXhtdPQ1EnxBJMxc"),
    pubkey!("SpEediGKLbbXndSYTzwmz6Z3NDgHQLDcTDEvGFkSMH9"),
    pubkey!("speede8xCcUq2Tiv1efXeTuE3k9TDNq8TnGKaKSc6J4"),
];

// `SwqosRegion` 与下列各 `SWQOS_ENDPOINTS_*` 下标严格对应(共 10 项):
// 0 NewYork, 1 Frankfurt, 2 Amsterdam, 3 Dublin, 4 SLC, 5 Tokyo, 6 Singapore, 7 London, 8 LosAngeles, 9 Default。
//
// **地理就近(用户语义)**:当某枚举区域没有该服务商**独立公布**的 PoP 时,在**该服务商已出现的端点集合内**,按真实地理位置选**大圆距离最近**的一项作为填充;行尾注释说明依据。
// **例外**:`SwqosRegion::Default`(下标 9)不表示地球上的点,表中为全局 URL 或文档默认枢纽,**不适用**地理就近,仅表示「未指定区域时的回退」。
// 若某区域仅有一种「大区」级入口(例如全美只有一个美东 PoP),则地理上非最优但只能复用,注释会标明「受服务商可用区限制」。

/// Jito mainnet block engines (`https://<region>.mainnet.block-engine.jito.wtf`).
/// There is no Los Angeles engine → use Salt Lake City for `LosAngeles`; `SwqosRegion::Default` uses the global mainnet URL.
pub const SWQOS_ENDPOINTS_JITO: [&str; 10] = [
    "https://ny.mainnet.block-engine.jito.wtf",
    "https://frankfurt.mainnet.block-engine.jito.wtf",
    "https://amsterdam.mainnet.block-engine.jito.wtf",
    "https://dublin.mainnet.block-engine.jito.wtf",
    "https://slc.mainnet.block-engine.jito.wtf",
    "https://tokyo.mainnet.block-engine.jito.wtf",
    "https://singapore.mainnet.block-engine.jito.wtf",
    "https://london.mainnet.block-engine.jito.wtf",
    "https://slc.mainnet.block-engine.jito.wtf", // LosAngeles: no LA PoP; nearest US-West is SLC
    "https://mainnet.block-engine.jito.wtf",
];

/// NextBlock regional HTTP hosts (see provider docs). `SwqosRegion` order; no dedicated LA PoP → SLC as US-West fallback.
pub const SWQOS_ENDPOINTS_NEXTBLOCK: [&str; 10] = [
    "http://ny.nextblock.io",
    "http://fra.nextblock.io",
    "http://ams.nextblock.io",
    "http://dublin.nextblock.io",
    "http://slc.nextblock.io",
    "http://tokyo.nextblock.io",
    "http://sgp.nextblock.io",
    "http://london.nextblock.io",
    "http://slc.nextblock.io",
    "http://fra.nextblock.io", // Default: 非地理区域;服务商无「全局」主机名时用 EU 枢纽作未选区回退
];

pub const SWQOS_ENDPOINTS_ZERO_SLOT: [&str; 10] = [
    "http://ny.0slot.trade",
    "http://de2.0slot.trade", // Use de2 for TSW, and de1 for OVH
    "http://ams.0slot.trade",
    "http://ams.0slot.trade", // Dublin: 无 IE 专用;在已公布 EU 点中选距爱尔兰最近的 ams(相对 de2 等)
    "http://la.0slot.trade",  // SLC: no UT PoP; nearest US-West published host
    "http://jp.0slot.trade",
    "http://jp.0slot.trade", // SG: 无本地 PoP;已公布 APAC 仅 jp,为表中离新加坡最近的大圆距离
    "http://ams.0slot.trade", // London: 无 UK 专用;已公布 EU 点中 ams 距伦敦最近之一
    "http://la.0slot.trade",
    "http://de2.0slot.trade", // Default: 非地理区域;EU 枢纽 de2 作未选区回退
];

/// Nozomi Direct regions: ewr1, fra2, ams1, lon1, lax1, tyo1, sgp1, …
pub const SWQOS_ENDPOINTS_TEMPORAL: [&str; 10] = [
    "http://ewr1.nozomi.temporal.xyz", // NewYork → Newark
    "http://fra2.nozomi.temporal.xyz",
    "http://ams1.nozomi.temporal.xyz",
    "http://lon1.nozomi.temporal.xyz", // Dublin: no IE host; UK nearest Direct PoP
    "http://lax1.nozomi.temporal.xyz", // SLC: US-West
    "http://tyo1.nozomi.temporal.xyz",
    "http://sgp1.nozomi.temporal.xyz",
    "http://lon1.nozomi.temporal.xyz",
    "http://lax1.nozomi.temporal.xyz",
    "http://fra2.nozomi.temporal.xyz", // Default: 非地理区域;EU Direct 枢纽
];

pub const SWQOS_ENDPOINTS_BLOX: [&str; 10] = [
    "https://ny.solana.dex.blxrbdn.com",
    "https://germany.solana.dex.blxrbdn.com",
    "https://amsterdam.solana.dex.blxrbdn.com",
    "https://uk.solana.dex.blxrbdn.com", // Dublin: IE/UK edge
    "https://la.solana.dex.blxrbdn.com", // SLC: no Mountain PoP; US-West LA
    "https://tokyo.solana.dex.blxrbdn.com",
    "https://tokyo.solana.dex.blxrbdn.com", // SG: 文档无 SGP 区域;已公布 APAC 仅 Tokyo,为距 SG 最近选项
    "https://uk.solana.dex.blxrbdn.com",
    "https://la.solana.dex.blxrbdn.com",
    "https://global.solana.dex.blxrbdn.com", // Default: 非地理区域;全球任播
];

pub const SWQOS_ENDPOINTS_NODE1: [&str; 10] = [
    "http://ny.node1.me",
    "http://fra.node1.me",
    "http://ams.node1.me",
    "http://lon.node1.me", // Dublin: 已公布中英爱区域用 lon(地理上近爱尔兰)
    "http://ny.node1.me",  // SLC: 已公布美国仅 ny;美西无 PoP,受可用区限制复用美东
    "http://tk.node1.me",
    "http://tk.node1.me", // SG: 已公布 APAC 仅 tk;地理上为表中离 SG 最近
    "http://lon.node1.me",
    "http://ny.node1.me",  // LosAngeles: 同上,美国仅 ny 入口
    "http://fra.node1.me", // Default: 非地理区域;与 QUIC 对齐为 EU 枢纽
];

/// Node1 QUIC: port 16666. Region order matches [`SwqosRegion`].
/// server_name = host part (e.g. ny.node1.me). Auth: first bi stream = 16-byte UUID; each tx = new bi stream, bincode body.
pub const SWQOS_ENDPOINTS_NODE1_QUIC: [&str; 10] = [
    "ny.node1.me:16666",
    "fra.node1.me:16666",
    "ams.node1.me:16666",
    "lon.node1.me:16666",
    "ny.node1.me:16666",
    "tk.node1.me:16666",
    "tk.node1.me:16666",
    "lon.node1.me:16666",
    "ny.node1.me:16666",
    "fra.node1.me:16666", // Default: 非地理区域;与 HTTP 对齐为 EU 枢纽
];

/// Published: ny, slc, ams, fra, singapore, london, tokyo (no IE/UK split → london for Dublin).
pub const SWQOS_ENDPOINTS_FLASHBLOCK: [&str; 10] = [
    "http://ny.flashblock.trade",
    "http://fra.flashblock.trade",
    "http://ams.flashblock.trade",
    "http://london.flashblock.trade", // Dublin: no IE host; UK nearest
    "http://slc.flashblock.trade",
    "http://tokyo.flashblock.trade",
    "http://singapore.flashblock.trade",
    "http://london.flashblock.trade",
    "http://slc.flashblock.trade",
    "http://fra.flashblock.trade", // Default: 非地理区域;EU 枢纽
];

/// BlockRazor Send Transaction v2: plain-text Base64 body, auth in URI, Content-Type: text/plain. Keep-alive: POST /v2/health.
/// 若 HTTP 返回 500,可尝试 HTTPS:https://<region>.solana.blockrazor.io/v2/sendTransaction(Frankfurt/NewYork/Tokyo),通过 custom_url 覆盖。
pub const SWQOS_ENDPOINTS_BLOCKRAZOR: [&str; 10] = [
    "http://newyork.solana.blockrazor.xyz:443/v2/sendTransaction",
    "http://frankfurt.solana.blockrazor.xyz:443/v2/sendTransaction",
    "http://amsterdam.solana.blockrazor.xyz:443/v2/sendTransaction",
    "http://london.solana.blockrazor.xyz:443/v2/sendTransaction", // Dublin: UK nearest published
    "http://newyork.solana.blockrazor.xyz:443/v2/sendTransaction", // SLC: 文档无美西;美国仅 NY,受可用区限制
    "http://tokyo.solana.blockrazor.xyz:443/v2/sendTransaction",
    "http://tokyo.solana.blockrazor.xyz:443/v2/sendTransaction", // SG: 已公布 APAC 仅 Tokyo,为距 SG 最近
    "http://london.solana.blockrazor.xyz:443/v2/sendTransaction",
    "http://newyork.solana.blockrazor.xyz:443/v2/sendTransaction", // LosAngeles: 无美西入口;美国仅 NY
    "http://frankfurt.solana.blockrazor.xyz:443/v2/sendTransaction", // Default: 非地理区域;EU 枢纽
];

/// BlockRazor gRPC endpoints. Region order matches [`SwqosRegion`].
/// Port 80 for gRPC protocol. Auth: apikey metadata in gRPC headers.
pub const SWQOS_ENDPOINTS_BLOCKRAZOR_GRPC: [&str; 10] = [
    "http://newyork.solana-grpc.blockrazor.xyz:80",
    "http://frankfurt.solana-grpc.blockrazor.xyz:80",
    "http://amsterdam.solana-grpc.blockrazor.xyz:80",
    "http://london.solana-grpc.blockrazor.xyz:80",
    "http://newyork.solana-grpc.blockrazor.xyz:80", // SLC: 与 HTTP 一致;美国仅 NY
    "http://tokyo.solana-grpc.blockrazor.xyz:80",
    "http://tokyo.solana-grpc.blockrazor.xyz:80",
    "http://london.solana-grpc.blockrazor.xyz:80",
    "http://newyork.solana-grpc.blockrazor.xyz:80", // LosAngeles: 与 HTTP 一致
    "http://frankfurt.solana-grpc.blockrazor.xyz:80", // Default: 非地理区域
];

/// Plain HTTP API path (`/iris?api-key=…&method=…`).
pub const ASTRALANE_PATH_IRIS: &str = "iris";
/// Binary HTTP API path (`/irisb?api-key=…&method=sendTransaction`, raw bincode body).
pub const ASTRALANE_PATH_IRISB: &str = "irisb";

/// Astralane **Plain** HTTP gateways (`/iris`). Pair with [`ASTRALANE_PATH_IRIS`].
pub const SWQOS_ENDPOINTS_ASTRALANE_PLAIN: [&str; 10] = [
    "http://ny.gateway.astralane.io/iris",
    "http://fr.gateway.astralane.io/iris",
    "http://ams.gateway.astralane.io/iris",
    "http://ams.gateway.astralane.io/iris", // Dublin: 无 IE 专用;在已公布 EU 点中选距爱尔兰最近的 ams
    "http://la.gateway.astralane.io/iris",
    "http://jp.gateway.astralane.io/iris",
    "http://sg.gateway.astralane.io/iris",
    "http://ams.gateway.astralane.io/iris", // London: 无 UK 专用;在已公布 EU 点中选距英国最近的 ams
    "http://la.gateway.astralane.io/iris",
    "https://edge.astralane.io/iris", // Default: 非地理区域;全局任播边缘
];

/// Astralane **Binary** HTTP gateways (`/irisb`). Pair with [`ASTRALANE_PATH_IRISB`].
pub const SWQOS_ENDPOINTS_ASTRALANE_BINARY: [&str; 10] = [
    "http://ny.gateway.astralane.io/irisb",
    "http://fr.gateway.astralane.io/irisb",
    "http://ams.gateway.astralane.io/irisb",
    "http://ams.gateway.astralane.io/irisb", // Dublin: 同 Plain
    "http://la.gateway.astralane.io/irisb",
    "http://jp.gateway.astralane.io/irisb",
    "http://sg.gateway.astralane.io/irisb",
    "http://ams.gateway.astralane.io/irisb", // London: 同 Plain
    "http://la.gateway.astralane.io/irisb",
    "https://edge.astralane.io/irisb", // Default: 同 Plain
];

/// Astralane QUIC endpoints (port 7000). Region order matches [`SwqosRegion`].
/// See: https://github.com/Astralane/astralane-quic-client.
pub const SWQOS_ENDPOINTS_ASTRALANE_QUIC: [&str; 10] = [
    "ny.gateway.astralane.io:7000",
    "fr.gateway.astralane.io:7000",
    "ams.gateway.astralane.io:7000",
    "ams.gateway.astralane.io:7000", // Dublin: 同 HTTP
    "la.gateway.astralane.io:7000",  // SLC: 美西 la 为最近已公布美区入口
    "jp.gateway.astralane.io:7000",
    "sg.gateway.astralane.io:7000",
    "ams.gateway.astralane.io:7000", // London: 同 HTTP
    "la.gateway.astralane.io:7000",
    "lim.gateway.astralane.io:7000", // Default: 非地理区域;全局边缘
];

/// Astralane QUIC MEV-protected endpoints (port 9000). Same region order as SWQOS_ENDPOINTS_ASTRALANE_QUIC.
pub const SWQOS_ENDPOINTS_ASTRALANE_QUIC_MEV: [&str; 10] = [
    "ny.gateway.astralane.io:9000",
    "fr.gateway.astralane.io:9000",
    "ams.gateway.astralane.io:9000",
    "ams.gateway.astralane.io:9000",
    "la.gateway.astralane.io:9000",
    "jp.gateway.astralane.io:9000",
    "sg.gateway.astralane.io:9000",
    "ams.gateway.astralane.io:9000",
    "la.gateway.astralane.io:9000",
    "lim.gateway.astralane.io:9000",
];

pub const SWQOS_ENDPOINTS_STELLIUM: [&str; 10] = [
    "http://ewr1.flashrpc.com",
    "http://fra1.flashrpc.com",
    "http://ams1.flashrpc.com",
    "http://lhr1.flashrpc.com", // Dublin: 已公布 UK 用 lhr;地理上近爱尔兰
    "http://ewr1.flashrpc.com", // SLC: 已公布美国仅 ewr;无美西 PoP,受可用区限制
    "http://tyo1.flashrpc.com",
    "http://tyo1.flashrpc.com", // SG: 表中无 SGP;APAC 仅 tyo,为距 SG 最近
    "http://lhr1.flashrpc.com",
    "http://ewr1.flashrpc.com", // LosAngeles: 同上,美国仅 ewr
    "http://fra1.flashrpc.com", // Default: 非地理区域;EU 枢纽
];

pub const SWQOS_ENDPOINTS_SOYAS: [&str; 10] = [
    "nyc.landing.soyas.xyz:9000",
    "fra.landing.soyas.xyz:9000",
    "ams.landing.soyas.xyz:9000",
    "lon.landing.soyas.xyz:9000", // Dublin: 已公布用 lon;地理近爱尔兰
    "nyc.landing.soyas.xyz:9000", // SLC: 已公布美国仅 nyc;无美西
    "tyo.landing.soyas.xyz:9000",
    "tyo.landing.soyas.xyz:9000", // SG: 表中 APAC 仅 tyo
    "lon.landing.soyas.xyz:9000",
    "nyc.landing.soyas.xyz:9000", // LosAngeles: 同上
    "fra.landing.soyas.xyz:9000", // Default: 非地理区域;EU 枢纽
];

pub const SWQOS_ENDPOINTS_SPEEDLANDING: [&str; 10] = [
    "nyc.speedlanding.trade:17778",
    "fra.speedlanding.trade:17778",
    "ams.speedlanding.trade:17778",
    "ams.speedlanding.trade:17778", // Dublin: 已公布 EU 点中 ams 地理近爱尔兰
    "nyc.speedlanding.trade:17778", // SLC: 表中美国仅 nyc;无美西 PoP,受可用区限制
    "tyo.speedlanding.trade:17778",
    "sgp.speedlanding.trade:17778",
    "ams.speedlanding.trade:17778", // London: 已公布 EU 中 ams 距英国最近之一
    "nyc.speedlanding.trade:17778", // LosAngeles: 同上,美国仅 nyc
    "fra.speedlanding.trade:17778", // Default: 非地理区域;EU 枢纽
];

/// Helius Sender: POST /fast, dual routing to validators and Jito. API key optional (custom TPS only).
pub const SWQOS_ENDPOINTS_HELIUS: [&str; 10] = [
    "http://ewr-sender.helius-rpc.com/fast",
    "http://fra-sender.helius-rpc.com/fast",
    "http://ams-sender.helius-rpc.com/fast",
    "http://lon-sender.helius-rpc.com/fast", // Dublin: IE → UK/EU routing
    "http://slc-sender.helius-rpc.com/fast",
    "http://tyo-sender.helius-rpc.com/fast",
    "http://sg-sender.helius-rpc.com/fast",
    "http://lon-sender.helius-rpc.com/fast",
    "http://slc-sender.helius-rpc.com/fast",
    "https://sender.helius-rpc.com/fast", // Default: 非地理区域;全局 Sender
];

pub const SWQOS_MIN_TIP_DEFAULT: f64 = 0.00001; // 其它SWQOS默认最低小费
pub const SWQOS_MIN_TIP_JITO: f64 = 0.00001;
pub const SWQOS_MIN_TIP_NEXTBLOCK: f64 = 0.001;
pub const SWQOS_MIN_TIP_ZERO_SLOT: f64 = 0.0001;
pub const SWQOS_MIN_TIP_TEMPORAL: f64 = 0.0001;
pub const SWQOS_MIN_TIP_BLOXROUTE: f64 = 0.0001;
pub const SWQOS_MIN_TIP_NODE1: f64 = 0.0001; // 如需更高阈值可调整
pub const SWQOS_MIN_TIP_FLASHBLOCK: f64 = 0.0001;
pub const SWQOS_MIN_TIP_BLOCKRAZOR: f64 = 0.0001;
pub const SWQOS_MIN_TIP_ASTRALANE: f64 = 0.00001;
pub const SWQOS_MIN_TIP_STELLIUM: f64 = 0.0001; // Stellium requires minimum 0.001 SOL tip
pub const SWQOS_MIN_TIP_LIGHTSPEED: f64 = 0.0001; // Lightspeed requires minimum 0.001 SOL tip
pub const SWQOS_MIN_TIP_SOYAS: f64 = 0.001; // Soyas requires minimum 0.001 SOL tip
pub const SWQOS_MIN_TIP_SPEEDLANDING: f64 = 0.001; // Speedlanding requires minimum 0.001 SOL tip
/// Helius Sender: 0.0002 SOL when not swqos_only; use SWQOS_MIN_TIP_HELIUS_SWQOS_ONLY when swqos_only=true.
pub const SWQOS_MIN_TIP_HELIUS: f64 = 0.0002;
/// Helius Sender with swqos_only: minimum 0.000005 SOL (much lower tip allowed).
pub const SWQOS_MIN_TIP_HELIUS_SWQOS_ONLY: f64 = 0.000005;

#[cfg(test)]
mod tests {
    use super::*;

    const SWQOS_REGION_ENDPOINT_TABLES: &[&[&str]] = &[
        &SWQOS_ENDPOINTS_JITO,
        &SWQOS_ENDPOINTS_NEXTBLOCK,
        &SWQOS_ENDPOINTS_ZERO_SLOT,
        &SWQOS_ENDPOINTS_TEMPORAL,
        &SWQOS_ENDPOINTS_BLOX,
        &SWQOS_ENDPOINTS_NODE1,
        &SWQOS_ENDPOINTS_NODE1_QUIC,
        &SWQOS_ENDPOINTS_FLASHBLOCK,
        &SWQOS_ENDPOINTS_BLOCKRAZOR,
        &SWQOS_ENDPOINTS_BLOCKRAZOR_GRPC,
        &SWQOS_ENDPOINTS_ASTRALANE_PLAIN,
        &SWQOS_ENDPOINTS_ASTRALANE_BINARY,
        &SWQOS_ENDPOINTS_ASTRALANE_QUIC,
        &SWQOS_ENDPOINTS_ASTRALANE_QUIC_MEV,
        &SWQOS_ENDPOINTS_STELLIUM,
        &SWQOS_ENDPOINTS_SOYAS,
        &SWQOS_ENDPOINTS_SPEEDLANDING,
        &SWQOS_ENDPOINTS_HELIUS,
    ];

    #[test]
    fn all_swqos_endpoint_tables_align_with_swqos_region() {
        const EXPECT: usize = 10;
        for (idx, table) in SWQOS_REGION_ENDPOINT_TABLES.iter().enumerate() {
            assert_eq!(
                table.len(),
                EXPECT,
                "SWQOS endpoint table index {} length must match SwqosRegion (10 variants)",
                idx
            );
        }
    }

    #[test]
    fn astralane_quic_hosts_match_mev_row_by_row() {
        for i in 0..10 {
            let base = SWQOS_ENDPOINTS_ASTRALANE_QUIC[i].trim_end_matches(":7000");
            let mev = SWQOS_ENDPOINTS_ASTRALANE_QUIC_MEV[i].trim_end_matches(":9000");
            assert_eq!(base, mev, "Astralane QUIC vs MEV host mismatch at index {}", i);
        }
    }

    #[test]
    fn node1_http_host_matches_quic_without_port() {
        for i in 0..10 {
            let http_host =
                SWQOS_ENDPOINTS_NODE1[i].strip_prefix("http://").expect("NODE1 HTTP URL");
            let quic_host =
                SWQOS_ENDPOINTS_NODE1_QUIC[i].strip_suffix(":16666").expect("NODE1 QUIC endpoint");
            assert_eq!(http_host, quic_host, "Node1 HTTP vs QUIC host mismatch at index {}", i);
        }
    }

    #[test]
    fn astralane_plain_and_binary_same_origin_per_region() {
        for i in 0..10 {
            let plain = SWQOS_ENDPOINTS_ASTRALANE_PLAIN[i].trim_end_matches("/iris");
            let binary = SWQOS_ENDPOINTS_ASTRALANE_BINARY[i].trim_end_matches("/irisb");
            assert_eq!(plain, binary, "Astralane Plain vs Binary base URL mismatch at index {}", i);
        }
    }
}