@gabox-labs/sdk 0.1.1 → 0.6.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.
@@ -0,0 +1,2604 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
+ import { AccountRole, Endian, addEncoderSizePrefix, appendTransactionMessageInstructions, compileTransaction, compressTransactionMessageUsingAddressLookupTables, createTransactionMessage, fixDecoderSize, getAddressDecoder, getAddressEncoder, getBase64Encoder, getBooleanDecoder, getBytesDecoder, getProgramDerivedAddress, getStructDecoder, getStructEncoder, getTransactionEncoder, getU16Decoder, getU16Encoder, getU32Encoder, getU64Decoder, getU64Encoder, getU8Decoder, getU8Encoder, getUtf8Encoder, pipe, setTransactionMessageFeePayerSigner, setTransactionMessageLifetimeUsingBlockhash } from "@solana/kit";
3
+ import { getCloseAccountInstruction, getCreateAssociatedTokenIdempotentInstruction } from "@solana-program/token";
4
+ //#region src/raydium/abi.ts
5
+ const RAYDIUM_MAINNET_IDS = {
6
+ launchlab: "LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj",
7
+ launchlabAuthority: "WLHv2UAZm6z4KyaaELi5pjdbJh6RESMva1Rnn8pJVVh",
8
+ launchlabEventAuthority: "2DPAtwB8L12vrMRExbLuyGnC7n2J5LNoZQSejeQGpwkr",
9
+ solGlobalConfig: "6s1xP3hpbAfFoNtUNF8mfHsjr2Bd97JxFJRWLbL6aHuX",
10
+ gaboxPlatform: "8tXUG97CEpSKTNXdGtanYyC33RWmTTuSin4VdaWwNj8q",
11
+ cpmm: "CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C",
12
+ cpmmAuthority: "GpMZbSM2GgvTKHJirzeGfMFoaZ8UR2X7F4v8vHTvxFbL",
13
+ launchQuoteRaise: 85000000000n
14
+ };
15
+ const RAYDIUM_DEVNET_IDS = {
16
+ launchlab: "DRay6fNdQ5J82H7xV6uq2aV3mNrUZ1J4PgSKsWgptcm6",
17
+ launchlabAuthority: "5xqNaZXX5eUi4p5HU4oz9i5QnwRNT2y6oN7yyn4qENeq",
18
+ launchlabEventAuthority: "4uAB7seenFJKPUXqYewAdfra2u6baBgjiXU8x1SC7Ycz",
19
+ solGlobalConfig: "7ZR4zD7PYfY2XxoG1Gxcy2EgEeGYrpxrwzPuwdUBssEt",
20
+ gaboxPlatform: "DdEeCPXbCAzHE2PZSoR3RZng4WA4bSztrezQznrJ4ooB",
21
+ cpmm: "DRaycpLY18LhpbydsBWbVJtxpNv9oXPgjRSfpF2bWpYb",
22
+ cpmmAuthority: "CXniRufdq5xL8t8jZAPxsPZDpuudwuJSPWnbcD5Y5Nxq",
23
+ launchQuoteRaise: 3000000000n
24
+ };
25
+ /** Wrapped SOL. The only quote Gabox accepts today, on both venues. */
26
+ const WSOL_MINT = "So11111111111111111111111111111111111111112";
27
+ /** Metaplex Token Metadata, which LaunchLab's create instruction writes to. */
28
+ const METAPLEX_PROGRAM_ADDRESS = "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s";
29
+ /**
30
+ * `PLATFORM_ADMIN` in the program's constants.rs. The Gabox platform config PDA derives from this
31
+ * wallet, and LaunchLab pays the platform share of every curve trade to it.
32
+ */
33
+ const PLATFORM_ADMIN = "5WcPTEQ59UqpQzjZUPbU8QRGCbj7NeQNLDa7DbsLkLKT";
34
+ /** The coin supply every Gabox launch mints: 1,000,000,000 coins at 6 decimals. */
35
+ const LAUNCH_SUPPLY = 1000000000000000n;
36
+ /** The part of the supply the LaunchLab curve sells: 793,100,000 coins. */
37
+ const LAUNCH_TOTAL_BASE_SELL = 793100000000000n;
38
+ /** Classic SPL Token. LaunchLab pins it on both sides of every Gabox launch and trade. */
39
+ const TOKEN_PROGRAM_ADDRESS = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
40
+ const ASSOCIATED_TOKEN_PROGRAM_ADDRESS = "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL";
41
+ const SYSTEM_PROGRAM_ADDRESS = "11111111111111111111111111111111";
42
+ /** The rent sysvar. LaunchLab's create instruction still takes it. */
43
+ const RENT_SYSVAR_ADDRESS = "SysvarRent111111111111111111111111111111111";
44
+ /**
45
+ * The first eight bytes of each Raydium account this SDK decodes. `adapter.ts` checks them before
46
+ * it reads a field, so an account of the wrong type fails loudly instead of decoding as rubbish.
47
+ *
48
+ * LaunchLab and CPMM give their pool account the same eight bytes, because Anchor derives a
49
+ * discriminator from the struct name alone and both are called `PoolState`. The two programs own
50
+ * different accounts, so the pair never collides in practice.
51
+ */
52
+ const LAUNCHLAB_POOL_STATE_DISCRIMINATOR = new Uint8Array([
53
+ 247,
54
+ 237,
55
+ 227,
56
+ 245,
57
+ 215,
58
+ 195,
59
+ 222,
60
+ 70
61
+ ]);
62
+ const LAUNCHLAB_GLOBAL_CONFIG_DISCRIMINATOR = new Uint8Array([
63
+ 149,
64
+ 8,
65
+ 156,
66
+ 202,
67
+ 160,
68
+ 252,
69
+ 176,
70
+ 217
71
+ ]);
72
+ const LAUNCHLAB_PLATFORM_CONFIG_DISCRIMINATOR = new Uint8Array([
73
+ 160,
74
+ 78,
75
+ 128,
76
+ 0,
77
+ 248,
78
+ 83,
79
+ 230,
80
+ 160
81
+ ]);
82
+ const CPMM_POOL_STATE_DISCRIMINATOR = new Uint8Array([
83
+ 247,
84
+ 237,
85
+ 227,
86
+ 245,
87
+ 215,
88
+ 195,
89
+ 222,
90
+ 70
91
+ ]);
92
+ const CPMM_AMM_CONFIG_DISCRIMINATOR = new Uint8Array([
93
+ 218,
94
+ 244,
95
+ 33,
96
+ 104,
97
+ 203,
98
+ 203,
99
+ 43,
100
+ 111
101
+ ]);
102
+ /**
103
+ * `initialize_v2` on `LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj` — cross-checked against interfaces.json.
104
+ */
105
+ const LAUNCHLAB_INITIALIZE = {
106
+ name: "initialize_v2",
107
+ discriminator: new Uint8Array([
108
+ 67,
109
+ 153,
110
+ 175,
111
+ 39,
112
+ 218,
113
+ 16,
114
+ 38,
115
+ 32
116
+ ]),
117
+ accounts: [
118
+ {
119
+ name: "payer",
120
+ writable: true,
121
+ signer: true
122
+ },
123
+ {
124
+ name: "creator",
125
+ writable: false,
126
+ signer: false
127
+ },
128
+ {
129
+ name: "global_config",
130
+ writable: false,
131
+ signer: false
132
+ },
133
+ {
134
+ name: "platform_config",
135
+ writable: false,
136
+ signer: false
137
+ },
138
+ {
139
+ name: "authority",
140
+ writable: false,
141
+ signer: false
142
+ },
143
+ {
144
+ name: "pool_state",
145
+ writable: true,
146
+ signer: false
147
+ },
148
+ {
149
+ name: "base_mint",
150
+ writable: true,
151
+ signer: true
152
+ },
153
+ {
154
+ name: "quote_mint",
155
+ writable: false,
156
+ signer: false
157
+ },
158
+ {
159
+ name: "base_vault",
160
+ writable: true,
161
+ signer: false
162
+ },
163
+ {
164
+ name: "quote_vault",
165
+ writable: true,
166
+ signer: false
167
+ },
168
+ {
169
+ name: "metadata_account",
170
+ writable: true,
171
+ signer: false
172
+ },
173
+ {
174
+ name: "base_token_program",
175
+ writable: false,
176
+ signer: false
177
+ },
178
+ {
179
+ name: "quote_token_program",
180
+ writable: false,
181
+ signer: false
182
+ },
183
+ {
184
+ name: "metadata_program",
185
+ writable: false,
186
+ signer: false
187
+ },
188
+ {
189
+ name: "system_program",
190
+ writable: false,
191
+ signer: false
192
+ },
193
+ {
194
+ name: "rent_program",
195
+ writable: false,
196
+ signer: false
197
+ },
198
+ {
199
+ name: "event_authority",
200
+ writable: false,
201
+ signer: false
202
+ },
203
+ {
204
+ name: "program",
205
+ writable: false,
206
+ signer: false
207
+ }
208
+ ]
209
+ };
210
+ /**
211
+ * `buy_exact_in` on `LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj` — not in interfaces.json (the program never builds it).
212
+ * The last three accounts are not in the IDL. LaunchLab reads them from the remaining
213
+ * accounts, in this order.
214
+ */
215
+ const LAUNCHLAB_BUY_EXACT_IN = {
216
+ name: "buy_exact_in",
217
+ discriminator: new Uint8Array([
218
+ 250,
219
+ 234,
220
+ 13,
221
+ 123,
222
+ 213,
223
+ 156,
224
+ 19,
225
+ 236
226
+ ]),
227
+ accounts: [
228
+ {
229
+ name: "payer",
230
+ writable: true,
231
+ signer: true
232
+ },
233
+ {
234
+ name: "authority",
235
+ writable: false,
236
+ signer: false
237
+ },
238
+ {
239
+ name: "global_config",
240
+ writable: false,
241
+ signer: false
242
+ },
243
+ {
244
+ name: "platform_config",
245
+ writable: false,
246
+ signer: false
247
+ },
248
+ {
249
+ name: "pool_state",
250
+ writable: true,
251
+ signer: false
252
+ },
253
+ {
254
+ name: "user_base_token",
255
+ writable: true,
256
+ signer: false
257
+ },
258
+ {
259
+ name: "user_quote_token",
260
+ writable: true,
261
+ signer: false
262
+ },
263
+ {
264
+ name: "base_vault",
265
+ writable: true,
266
+ signer: false
267
+ },
268
+ {
269
+ name: "quote_vault",
270
+ writable: true,
271
+ signer: false
272
+ },
273
+ {
274
+ name: "base_token_mint",
275
+ writable: false,
276
+ signer: false
277
+ },
278
+ {
279
+ name: "quote_token_mint",
280
+ writable: false,
281
+ signer: false
282
+ },
283
+ {
284
+ name: "base_token_program",
285
+ writable: false,
286
+ signer: false
287
+ },
288
+ {
289
+ name: "quote_token_program",
290
+ writable: false,
291
+ signer: false
292
+ },
293
+ {
294
+ name: "event_authority",
295
+ writable: false,
296
+ signer: false
297
+ },
298
+ {
299
+ name: "program",
300
+ writable: false,
301
+ signer: false
302
+ },
303
+ {
304
+ name: "system_program",
305
+ writable: false,
306
+ signer: false
307
+ },
308
+ {
309
+ name: "platform_fee_vault",
310
+ writable: true,
311
+ signer: false
312
+ },
313
+ {
314
+ name: "creator_fee_vault",
315
+ writable: true,
316
+ signer: false
317
+ }
318
+ ]
319
+ };
320
+ /**
321
+ * `buy_exact_out` on `LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj` — cross-checked against interfaces.json.
322
+ * The last three accounts are not in the IDL. LaunchLab reads them from the remaining
323
+ * accounts, in this order.
324
+ */
325
+ const LAUNCHLAB_BUY_EXACT_OUT = {
326
+ name: "buy_exact_out",
327
+ discriminator: new Uint8Array([
328
+ 24,
329
+ 211,
330
+ 116,
331
+ 40,
332
+ 105,
333
+ 3,
334
+ 153,
335
+ 56
336
+ ]),
337
+ accounts: [
338
+ {
339
+ name: "payer",
340
+ writable: true,
341
+ signer: true
342
+ },
343
+ {
344
+ name: "authority",
345
+ writable: false,
346
+ signer: false
347
+ },
348
+ {
349
+ name: "global_config",
350
+ writable: false,
351
+ signer: false
352
+ },
353
+ {
354
+ name: "platform_config",
355
+ writable: false,
356
+ signer: false
357
+ },
358
+ {
359
+ name: "pool_state",
360
+ writable: true,
361
+ signer: false
362
+ },
363
+ {
364
+ name: "user_base_token",
365
+ writable: true,
366
+ signer: false
367
+ },
368
+ {
369
+ name: "user_quote_token",
370
+ writable: true,
371
+ signer: false
372
+ },
373
+ {
374
+ name: "base_vault",
375
+ writable: true,
376
+ signer: false
377
+ },
378
+ {
379
+ name: "quote_vault",
380
+ writable: true,
381
+ signer: false
382
+ },
383
+ {
384
+ name: "base_token_mint",
385
+ writable: false,
386
+ signer: false
387
+ },
388
+ {
389
+ name: "quote_token_mint",
390
+ writable: false,
391
+ signer: false
392
+ },
393
+ {
394
+ name: "base_token_program",
395
+ writable: false,
396
+ signer: false
397
+ },
398
+ {
399
+ name: "quote_token_program",
400
+ writable: false,
401
+ signer: false
402
+ },
403
+ {
404
+ name: "event_authority",
405
+ writable: false,
406
+ signer: false
407
+ },
408
+ {
409
+ name: "program",
410
+ writable: false,
411
+ signer: false
412
+ },
413
+ {
414
+ name: "system_program",
415
+ writable: false,
416
+ signer: false
417
+ },
418
+ {
419
+ name: "platform_fee_vault",
420
+ writable: true,
421
+ signer: false
422
+ },
423
+ {
424
+ name: "creator_fee_vault",
425
+ writable: true,
426
+ signer: false
427
+ }
428
+ ]
429
+ };
430
+ /**
431
+ * `sell_exact_in` on `LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj` — cross-checked against interfaces.json.
432
+ * The last three accounts are not in the IDL. LaunchLab reads them from the remaining
433
+ * accounts, in this order.
434
+ */
435
+ const LAUNCHLAB_SELL_EXACT_IN = {
436
+ name: "sell_exact_in",
437
+ discriminator: new Uint8Array([
438
+ 149,
439
+ 39,
440
+ 222,
441
+ 155,
442
+ 211,
443
+ 124,
444
+ 152,
445
+ 26
446
+ ]),
447
+ accounts: [
448
+ {
449
+ name: "payer",
450
+ writable: true,
451
+ signer: true
452
+ },
453
+ {
454
+ name: "authority",
455
+ writable: false,
456
+ signer: false
457
+ },
458
+ {
459
+ name: "global_config",
460
+ writable: false,
461
+ signer: false
462
+ },
463
+ {
464
+ name: "platform_config",
465
+ writable: false,
466
+ signer: false
467
+ },
468
+ {
469
+ name: "pool_state",
470
+ writable: true,
471
+ signer: false
472
+ },
473
+ {
474
+ name: "user_base_token",
475
+ writable: true,
476
+ signer: false
477
+ },
478
+ {
479
+ name: "user_quote_token",
480
+ writable: true,
481
+ signer: false
482
+ },
483
+ {
484
+ name: "base_vault",
485
+ writable: true,
486
+ signer: false
487
+ },
488
+ {
489
+ name: "quote_vault",
490
+ writable: true,
491
+ signer: false
492
+ },
493
+ {
494
+ name: "base_token_mint",
495
+ writable: false,
496
+ signer: false
497
+ },
498
+ {
499
+ name: "quote_token_mint",
500
+ writable: false,
501
+ signer: false
502
+ },
503
+ {
504
+ name: "base_token_program",
505
+ writable: false,
506
+ signer: false
507
+ },
508
+ {
509
+ name: "quote_token_program",
510
+ writable: false,
511
+ signer: false
512
+ },
513
+ {
514
+ name: "event_authority",
515
+ writable: false,
516
+ signer: false
517
+ },
518
+ {
519
+ name: "program",
520
+ writable: false,
521
+ signer: false
522
+ },
523
+ {
524
+ name: "system_program",
525
+ writable: false,
526
+ signer: false
527
+ },
528
+ {
529
+ name: "platform_fee_vault",
530
+ writable: true,
531
+ signer: false
532
+ },
533
+ {
534
+ name: "creator_fee_vault",
535
+ writable: true,
536
+ signer: false
537
+ }
538
+ ]
539
+ };
540
+ /**
541
+ * `claim_creator_fee` on `LanMV9sAd7wArD4vJFi2qDdfnVhFxYSUg6eADduJ3uj` — not in interfaces.json (the program never builds it).
542
+ */
543
+ const LAUNCHLAB_CLAIM_CREATOR_FEE = {
544
+ name: "claim_creator_fee",
545
+ discriminator: new Uint8Array([
546
+ 26,
547
+ 97,
548
+ 138,
549
+ 203,
550
+ 132,
551
+ 171,
552
+ 141,
553
+ 252
554
+ ]),
555
+ accounts: [
556
+ {
557
+ name: "creator",
558
+ writable: true,
559
+ signer: true
560
+ },
561
+ {
562
+ name: "fee_vault_authority",
563
+ writable: false,
564
+ signer: false
565
+ },
566
+ {
567
+ name: "creator_fee_vault",
568
+ writable: true,
569
+ signer: false
570
+ },
571
+ {
572
+ name: "recipient_token_account",
573
+ writable: true,
574
+ signer: false
575
+ },
576
+ {
577
+ name: "quote_mint",
578
+ writable: false,
579
+ signer: false
580
+ },
581
+ {
582
+ name: "token_program",
583
+ writable: false,
584
+ signer: false
585
+ },
586
+ {
587
+ name: "system_program",
588
+ writable: false,
589
+ signer: false
590
+ },
591
+ {
592
+ name: "associated_token_program",
593
+ writable: false,
594
+ signer: false
595
+ }
596
+ ]
597
+ };
598
+ /**
599
+ * `swap_base_output` on `CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C` — cross-checked against interfaces.json.
600
+ */
601
+ const CPMM_SWAP_BASE_OUTPUT = {
602
+ name: "swap_base_output",
603
+ discriminator: new Uint8Array([
604
+ 55,
605
+ 217,
606
+ 98,
607
+ 86,
608
+ 163,
609
+ 74,
610
+ 180,
611
+ 173
612
+ ]),
613
+ accounts: [
614
+ {
615
+ name: "payer",
616
+ writable: false,
617
+ signer: true
618
+ },
619
+ {
620
+ name: "authority",
621
+ writable: false,
622
+ signer: false
623
+ },
624
+ {
625
+ name: "amm_config",
626
+ writable: false,
627
+ signer: false
628
+ },
629
+ {
630
+ name: "pool_state",
631
+ writable: true,
632
+ signer: false
633
+ },
634
+ {
635
+ name: "input_token_account",
636
+ writable: true,
637
+ signer: false
638
+ },
639
+ {
640
+ name: "output_token_account",
641
+ writable: true,
642
+ signer: false
643
+ },
644
+ {
645
+ name: "input_vault",
646
+ writable: true,
647
+ signer: false
648
+ },
649
+ {
650
+ name: "output_vault",
651
+ writable: true,
652
+ signer: false
653
+ },
654
+ {
655
+ name: "input_token_program",
656
+ writable: false,
657
+ signer: false
658
+ },
659
+ {
660
+ name: "output_token_program",
661
+ writable: false,
662
+ signer: false
663
+ },
664
+ {
665
+ name: "input_token_mint",
666
+ writable: false,
667
+ signer: false
668
+ },
669
+ {
670
+ name: "output_token_mint",
671
+ writable: false,
672
+ signer: false
673
+ },
674
+ {
675
+ name: "observation_state",
676
+ writable: true,
677
+ signer: false
678
+ }
679
+ ]
680
+ };
681
+ /**
682
+ * `swap_base_input` on `CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C` — cross-checked against interfaces.json.
683
+ */
684
+ const CPMM_SWAP_BASE_INPUT = {
685
+ name: "swap_base_input",
686
+ discriminator: new Uint8Array([
687
+ 143,
688
+ 190,
689
+ 90,
690
+ 218,
691
+ 196,
692
+ 30,
693
+ 51,
694
+ 222
695
+ ]),
696
+ accounts: [
697
+ {
698
+ name: "payer",
699
+ writable: false,
700
+ signer: true
701
+ },
702
+ {
703
+ name: "authority",
704
+ writable: false,
705
+ signer: false
706
+ },
707
+ {
708
+ name: "amm_config",
709
+ writable: false,
710
+ signer: false
711
+ },
712
+ {
713
+ name: "pool_state",
714
+ writable: true,
715
+ signer: false
716
+ },
717
+ {
718
+ name: "input_token_account",
719
+ writable: true,
720
+ signer: false
721
+ },
722
+ {
723
+ name: "output_token_account",
724
+ writable: true,
725
+ signer: false
726
+ },
727
+ {
728
+ name: "input_vault",
729
+ writable: true,
730
+ signer: false
731
+ },
732
+ {
733
+ name: "output_vault",
734
+ writable: true,
735
+ signer: false
736
+ },
737
+ {
738
+ name: "input_token_program",
739
+ writable: false,
740
+ signer: false
741
+ },
742
+ {
743
+ name: "output_token_program",
744
+ writable: false,
745
+ signer: false
746
+ },
747
+ {
748
+ name: "input_token_mint",
749
+ writable: false,
750
+ signer: false
751
+ },
752
+ {
753
+ name: "output_token_mint",
754
+ writable: false,
755
+ signer: false
756
+ },
757
+ {
758
+ name: "observation_state",
759
+ writable: true,
760
+ signer: false
761
+ }
762
+ ]
763
+ };
764
+ /**
765
+ * `collect_creator_fee` on `CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C` — not in interfaces.json (the program never builds it).
766
+ * The last account is not in the IDL snapshot; see `CPMM_CREATOR_FEE_SHARE_ACCOUNT` in
767
+ * scripts/codegen.mjs. Derive it as PDA(["creator_fee_share", creator, amm_config]).
768
+ */
769
+ const CPMM_COLLECT_CREATOR_FEE = {
770
+ name: "collect_creator_fee",
771
+ discriminator: new Uint8Array([
772
+ 20,
773
+ 22,
774
+ 86,
775
+ 123,
776
+ 198,
777
+ 28,
778
+ 219,
779
+ 132
780
+ ]),
781
+ accounts: [
782
+ {
783
+ name: "creator",
784
+ writable: true,
785
+ signer: true
786
+ },
787
+ {
788
+ name: "authority",
789
+ writable: false,
790
+ signer: false
791
+ },
792
+ {
793
+ name: "pool_state",
794
+ writable: true,
795
+ signer: false
796
+ },
797
+ {
798
+ name: "amm_config",
799
+ writable: false,
800
+ signer: false
801
+ },
802
+ {
803
+ name: "token_0_vault",
804
+ writable: true,
805
+ signer: false
806
+ },
807
+ {
808
+ name: "token_1_vault",
809
+ writable: true,
810
+ signer: false
811
+ },
812
+ {
813
+ name: "vault_0_mint",
814
+ writable: false,
815
+ signer: false
816
+ },
817
+ {
818
+ name: "vault_1_mint",
819
+ writable: false,
820
+ signer: false
821
+ },
822
+ {
823
+ name: "creator_token_0",
824
+ writable: true,
825
+ signer: false
826
+ },
827
+ {
828
+ name: "creator_token_1",
829
+ writable: true,
830
+ signer: false
831
+ },
832
+ {
833
+ name: "token_0_program",
834
+ writable: false,
835
+ signer: false
836
+ },
837
+ {
838
+ name: "token_1_program",
839
+ writable: false,
840
+ signer: false
841
+ },
842
+ {
843
+ name: "associated_token_program",
844
+ writable: false,
845
+ signer: false
846
+ },
847
+ {
848
+ name: "system_program",
849
+ writable: false,
850
+ signer: false
851
+ },
852
+ {
853
+ name: "creator_fee_share",
854
+ writable: false,
855
+ signer: false
856
+ }
857
+ ]
858
+ };
859
+ //#endregion
860
+ //#region src/raydium/ids.ts
861
+ /**
862
+ * The Raydium addresses and launch numbers Gabox pins, per cluster.
863
+ *
864
+ * Mainnet and devnet run different Raydium deployments. Every program id and every PDA differs, and
865
+ * so does the quote the curve must raise before a coin graduates. So nothing here is a global: a
866
+ * caller passes the cluster, which comes from `createClient({ cluster })`.
867
+ *
868
+ * None of these strings is typed in this file. `scripts/codegen.mjs` reads them out of the Rust
869
+ * program's `programs/gabox/src/venue/ids.rs` and writes `abi.ts`. The Rust file is the source of
870
+ * truth, because the program checks every one of these addresses on chain.
871
+ * `test/raydium-pdas.test.ts` derives each PDA again and compares.
872
+ */
873
+ const ADDRESS_ENCODER = getAddressEncoder();
874
+ /**
875
+ * The decimals every Gabox coin is launched with. `venue/launch.rs` refuses any other value, and
876
+ * `tokens.rs` refuses a pool mint that does not have exactly this many.
877
+ */
878
+ const LAUNCH_DECIMALS = 6;
879
+ /**
880
+ * The Raydium deployment of each cluster.
881
+ *
882
+ * `localnet` uses the mainnet set. A local validator normally clones the mainnet Raydium programs,
883
+ * and the program's own default `anchor build` pins the mainnet addresses too; the `devnet` cargo
884
+ * feature is what swaps them. Pass your own ids to a builder if your validator clones devnet.
885
+ */
886
+ const RAYDIUM_IDS = {
887
+ "mainnet-beta": RAYDIUM_MAINNET_IDS,
888
+ devnet: RAYDIUM_DEVNET_IDS,
889
+ localnet: RAYDIUM_MAINNET_IDS
890
+ };
891
+ /** The Raydium deployment one cluster trades on. Throws for a cluster this SDK does not know. */
892
+ function raydiumIds(cluster) {
893
+ const ids = RAYDIUM_IDS[cluster];
894
+ if (!ids) throw new Error(`unknown cluster ${JSON.stringify(cluster)}; expected 'devnet', 'mainnet-beta' or 'localnet'`);
895
+ return ids;
896
+ }
897
+ /** LaunchLab's PDA seeds, and the two Gabox coins are always sorted against. */
898
+ const LAUNCHLAB_SEEDS = {
899
+ /** `["vault_auth_seed"]`. */
900
+ authority: "vault_auth_seed",
901
+ /** `["__event_authority"]`. */
902
+ eventAuthority: "__event_authority",
903
+ /** `["global_config", quote_mint, u8 curve_type, u16 big-endian index]`. */
904
+ globalConfig: "global_config",
905
+ /** `["platform_config", platform_admin]`. */
906
+ platformConfig: "platform_config",
907
+ /** `["pool", base_mint, quote_mint]`. */
908
+ pool: "pool",
909
+ /** `["pool_vault", pool_state, mint]`. */
910
+ vault: "pool_vault",
911
+ /** `["creator_fee_vault_auth_seed"]`, the authority over every creator fee vault. */
912
+ creatorFeeVaultAuthority: "creator_fee_vault_auth_seed"
913
+ };
914
+ /** CPMM's PDA seeds. */
915
+ const CPMM_SEEDS = {
916
+ /** `["vault_and_lp_mint_auth_seed"]`. */
917
+ authority: "vault_and_lp_mint_auth_seed",
918
+ /** `["pool", amm_config, token_0_mint, token_1_mint]`, the mints sorted by byte order. */
919
+ pool: "pool",
920
+ /** `["pool_vault", pool_state, mint]`. */
921
+ vault: "pool_vault",
922
+ /** `["observation", pool_state]`. */
923
+ observation: "observation",
924
+ /** `["creator_fee_share", creator, amm_config]`. */
925
+ creatorFeeShare: "creator_fee_share"
926
+ };
927
+ /** Metaplex's metadata PDA seed: `["metadata", metaplex, mint]`. */
928
+ const METADATA_SEED = "metadata";
929
+ /**
930
+ * Every rate LaunchLab and CPMM state is out of 1,000,000, not out of 10,000. A `trade_fee_rate`
931
+ * of 5,000 is 0.5%.
932
+ */
933
+ const RATE_DENOMINATOR = 1000000n;
934
+ /** The share-fee receiver Gabox never passes, so its rate is always zero on every trade. */
935
+ const SHARE_FEE_RATE = 0n;
936
+ /** `CurveParams::Constant`, the only curve shape Gabox launches. */
937
+ const CONSTANT_CURVE_TAG = 0;
938
+ /** `migrate_type` 1: the coin graduates into a CPMM pool, not into an AMM pool. */
939
+ const MIGRATE_TO_CPMM = 1;
940
+ /** `AmmCreatorFeeOn::QuoteToken`, so the CPMM creator fee is paid in WSOL. */
941
+ const CREATOR_FEE_ON_QUOTE = 0;
942
+ /** LaunchLab pool `status`: still selling on the curve. */
943
+ const LAUNCHLAB_STATUS_FUND = 0;
944
+ /** LaunchLab pool `status`: the raise is complete and Raydium's bot is migrating the coin. */
945
+ const LAUNCHLAB_STATUS_MIGRATE = 1;
946
+ /** LaunchLab pool `status`: the coin has graduated and trades on its CPMM pool. */
947
+ const LAUNCHLAB_STATUS_TRADE = 2;
948
+ /** Metaplex's own limits on the three strings a creator picks, in UTF-8 bytes. */
949
+ const METADATA_LIMITS = {
950
+ name: 32,
951
+ symbol: 10,
952
+ uri: 200
953
+ };
954
+ /** Raydium sorts a CPMM pair by raw address byte order. */
955
+ function sortedMints(a, b) {
956
+ return compareAddresses(a, b) <= 0 ? [a, b] : [b, a];
957
+ }
958
+ /** Compare two addresses the way the runtime does: by their 32 raw bytes, not by base58 text. */
959
+ function compareAddresses(a, b) {
960
+ const left = ADDRESS_ENCODER.encode(a);
961
+ const right = ADDRESS_ENCODER.encode(b);
962
+ for (let i = 0; i < 32; i++) {
963
+ const difference = (left[i] ?? 0) - (right[i] ?? 0);
964
+ if (difference !== 0) return difference;
965
+ }
966
+ return 0;
967
+ }
968
+ //#endregion
969
+ //#region src/raydium/pdas.ts
970
+ /**
971
+ * Every Raydium address a Gabox transaction derives.
972
+ *
973
+ * All of them are program-derived, so each one takes the program it lives under. Mainnet and devnet
974
+ * run different Raydium programs, so the same seeds give different addresses on the two clusters.
975
+ * Pass `raydiumIds(client.cluster)` and read the program out of it.
976
+ *
977
+ * `venue/trade.rs` and `venue/launch.rs` derive the same addresses on chain and refuse any account
978
+ * that does not match. `test/raydium-pdas.test.ts` checks every one of these against the pinned
979
+ * table in `abi.ts`, for both clusters.
980
+ */
981
+ const address$1 = getAddressEncoder();
982
+ const utf8 = getUtf8Encoder();
983
+ const u8$1 = getU8Encoder();
984
+ const u16be = getU16Encoder({ endian: Endian.Big });
985
+ const derive = async (programAddress, seeds) => (await getProgramDerivedAddress({
986
+ programAddress,
987
+ seeds
988
+ }))[0];
989
+ /** `["vault_auth_seed"]`. LaunchLab signs its own vault transfers with this PDA. */
990
+ const launchlabAuthority = async (launchlab) => await derive(launchlab, [utf8.encode(LAUNCHLAB_SEEDS.authority)]);
991
+ /** `["__event_authority"]`. */
992
+ const launchlabEventAuthority = async (launchlab) => await derive(launchlab, [utf8.encode(LAUNCHLAB_SEEDS.eventAuthority)]);
993
+ /**
994
+ * `["global_config", quote_mint, u8 curve_type, u16 big-endian index]`. The curve settings for one
995
+ * quote asset. Gabox uses curve type 0 (constant product) and index 0.
996
+ */
997
+ const launchlabGlobalConfig = async (launchlab, quoteMint, curveType = 0, index = 0) => await derive(launchlab, [
998
+ utf8.encode(LAUNCHLAB_SEEDS.globalConfig),
999
+ address$1.encode(quoteMint),
1000
+ u8$1.encode(curveType),
1001
+ u16be.encode(index)
1002
+ ]);
1003
+ /** `["platform_config", platform_admin]`. The Gabox platform on LaunchLab. */
1004
+ const launchlabPlatformConfig = async (launchlab, platformAdmin) => await derive(launchlab, [utf8.encode(LAUNCHLAB_SEEDS.platformConfig), address$1.encode(platformAdmin)]);
1005
+ /** `["pool", base_mint, quote_mint]`. The curve pool of one coin. */
1006
+ const launchlabPoolAddress = async (launchlab, baseMint, quoteMint) => await derive(launchlab, [
1007
+ utf8.encode(LAUNCHLAB_SEEDS.pool),
1008
+ address$1.encode(baseMint),
1009
+ address$1.encode(quoteMint)
1010
+ ]);
1011
+ /** `["pool_vault", pool_state, mint]`. One side of a curve pool's reserves. */
1012
+ const launchlabVaultAddress = async (launchlab, poolState, mint) => await derive(launchlab, [
1013
+ utf8.encode(LAUNCHLAB_SEEDS.vault),
1014
+ address$1.encode(poolState),
1015
+ address$1.encode(mint)
1016
+ ]);
1017
+ /**
1018
+ * `[platform_config, quote_mint]`. LaunchLab pays the platform share of every curve trade here.
1019
+ *
1020
+ * The seeds carry no text prefix. That is Raydium's own derivation, not a mistake.
1021
+ */
1022
+ const platformFeeVaultAddress = async (launchlab, platformConfig, quoteMint) => await derive(launchlab, [address$1.encode(platformConfig), address$1.encode(quoteMint)]);
1023
+ /**
1024
+ * `[creator, quote_mint]`. LaunchLab pays the creator share of every curve trade here.
1025
+ *
1026
+ * One vault per wallet per quote asset, not one per coin. A creator with several coins collects
1027
+ * all of them with a single `claim_creator_fee`.
1028
+ */
1029
+ const creatorFeeVaultAddress = async (launchlab, creator, quoteMint) => await derive(launchlab, [address$1.encode(creator), address$1.encode(quoteMint)]);
1030
+ /** `["creator_fee_vault_auth_seed"]`. The authority `claim_creator_fee` signs the payout with. */
1031
+ const creatorFeeVaultAuthority = async (launchlab) => await derive(launchlab, [utf8.encode(LAUNCHLAB_SEEDS.creatorFeeVaultAuthority)]);
1032
+ /** `["metadata", metaplex, mint]` under Metaplex. LaunchLab's create instruction writes it. */
1033
+ const metadataAddress = async (mint) => await derive(METAPLEX_PROGRAM_ADDRESS, [
1034
+ utf8.encode(METADATA_SEED),
1035
+ address$1.encode(METAPLEX_PROGRAM_ADDRESS),
1036
+ address$1.encode(mint)
1037
+ ]);
1038
+ /** `["vault_and_lp_mint_auth_seed"]`. */
1039
+ const cpmmAuthority = async (cpmm) => await derive(cpmm, [utf8.encode(CPMM_SEEDS.authority)]);
1040
+ /**
1041
+ * `["pool", amm_config, token_0, token_1]`, with the two mints sorted by raw byte order.
1042
+ *
1043
+ * This is where Raydium migrates a coin when the address is free. It is only a first guess: when the
1044
+ * account is taken, the migration lands somewhere else entirely. And the address alone proves
1045
+ * nothing, because anyone can open a CPMM pool for any pair under any config. `findCpmmPool` tries
1046
+ * this address, checks the account data, and scans for the real pool when it does not match.
1047
+ *
1048
+ * There are no vault or observation derivations here on purpose. `venue/trade.rs` reads those three
1049
+ * addresses out of the pool account, and so does this SDK: a migrated pool names its own vaults and
1050
+ * its own oracle, wherever it sits.
1051
+ */
1052
+ const cpmmPoolAddress = async (cpmm, ammConfig, mintA, mintB) => {
1053
+ const [token0, token1] = sortedMints(mintA, mintB);
1054
+ return await derive(cpmm, [
1055
+ utf8.encode(CPMM_SEEDS.pool),
1056
+ address$1.encode(ammConfig),
1057
+ address$1.encode(token0),
1058
+ address$1.encode(token1)
1059
+ ]);
1060
+ };
1061
+ /**
1062
+ * `["creator_fee_share", creator, amm_config]`. Where CPMM tracks what one creator is owed under
1063
+ * one fee tier.
1064
+ *
1065
+ * `collect_creator_fee` takes this account after the fourteen the mainnet IDL lists. That snapshot
1066
+ * predates the account; Raydium's devnet build declares it and stops with `AccountNotEnoughKeys`
1067
+ * (3005) when it is missing. One account per creator per fee tier, not one per pool.
1068
+ */
1069
+ const cpmmCreatorFeeShare = async (cpmm, creator, ammConfig) => await derive(cpmm, [
1070
+ utf8.encode(CPMM_SEEDS.creatorFeeShare),
1071
+ address$1.encode(creator),
1072
+ address$1.encode(ammConfig)
1073
+ ]);
1074
+ /** An associated token account. Off-curve owners are allowed: pool PDAs are all off-curve. */
1075
+ const ata = async (owner, mint, tokenProgram = TOKEN_PROGRAM_ADDRESS) => await derive(ASSOCIATED_TOKEN_PROGRAM_ADDRESS, [
1076
+ address$1.encode(owner),
1077
+ address$1.encode(tokenProgram),
1078
+ address$1.encode(mint)
1079
+ ]);
1080
+ //#endregion
1081
+ //#region src/raydium/adapter.ts
1082
+ /**
1083
+ * Reading Raydium's accounts.
1084
+ *
1085
+ * Every decoder here is written from the field list in the two IDL snapshots under `idl/`. Nothing
1086
+ * is guessed: each struct is laid out in Borsh order with no padding between fields, so the offsets
1087
+ * follow from the field sizes alone. Each decoder checks the account's eight-byte discriminator
1088
+ * first, so a wrong account fails loudly instead of decoding as plausible rubbish.
1089
+ *
1090
+ * `test/raydium-decode.test.ts` builds one byte array per decoder by hand and reads it back.
1091
+ *
1092
+ * Only the fields Gabox needs are decoded. The trailing padding of each account is skipped, which
1093
+ * is also why a longer account than the one recorded here still decodes: Raydium only ever appends
1094
+ * into its own padding.
1095
+ *
1096
+ * Kit's codecs, never `Buffer`. This module is vendored into a Next.js app, and `Buffer` does not
1097
+ * exist in a browser.
1098
+ */
1099
+ const DISCRIMINATOR = 8;
1100
+ const u8 = getU8Decoder();
1101
+ const u16 = getU16Decoder();
1102
+ const u64$1 = getU64Decoder();
1103
+ const addressAt = getAddressDecoder();
1104
+ const bool = getBooleanDecoder();
1105
+ /** Refuse an account that is too short or carries another type's discriminator. */
1106
+ function checked(data, discriminator, what) {
1107
+ if (data.length < discriminator.length) throw new Error(`not a ${what}: ${data.length} bytes is shorter than a discriminator`);
1108
+ for (const [i, byte] of discriminator.entries()) if (data[i] !== byte) throw new Error(`not a ${what}: the discriminator does not match`);
1109
+ return data;
1110
+ }
1111
+ /** Refuse a truncated account before a decoder reads past its end. */
1112
+ function atLeast(data, size, what) {
1113
+ if (data.length < size) throw new Error(`not a ${what}: ${data.length} bytes, expected at least ${size}`);
1114
+ return data;
1115
+ }
1116
+ /**
1117
+ * The `amount` field of an SPL token account: bytes 64 to 72, little-endian.
1118
+ *
1119
+ * Both venues and every Gabox account use classic SPL Token, whose account is 165 bytes. The
1120
+ * Token-2022 layout shares those first 165 bytes, so this reader covers a Token-2022 account too.
1121
+ */
1122
+ function tokenAccountAmount(data) {
1123
+ if (data.length < 72) throw new Error("not a token account: fewer than 72 bytes");
1124
+ return u64$1.decode(data, 64);
1125
+ }
1126
+ /** The `mint` and `owner` of an SPL token account: bytes 0 to 32 and 32 to 64. */
1127
+ function tokenAccountOwnerAndMint(data) {
1128
+ if (data.length < 64) throw new Error("not a token account: fewer than 64 bytes");
1129
+ return {
1130
+ mint: addressAt.decode(data, 0),
1131
+ owner: addressAt.decode(data, 32)
1132
+ };
1133
+ }
1134
+ /** Offsets follow the `PoolState` field list in `idl/raydium_launchpad.json`. */
1135
+ const LAUNCHLAB_POOL_HEAD = getStructDecoder([
1136
+ ["epoch", u64$1],
1137
+ ["authBump", u8],
1138
+ ["status", u8],
1139
+ ["baseDecimals", u8],
1140
+ ["quoteDecimals", u8],
1141
+ ["migrateType", u8],
1142
+ ["supply", u64$1],
1143
+ ["totalBaseSell", u64$1],
1144
+ ["virtualBase", u64$1],
1145
+ ["virtualQuote", u64$1],
1146
+ ["realBase", u64$1],
1147
+ ["realQuote", u64$1],
1148
+ ["totalQuoteFundRaising", u64$1],
1149
+ ["quoteProtocolFee", u64$1],
1150
+ ["platformFee", u64$1],
1151
+ ["migrateFee", u64$1],
1152
+ ["vestingTotalLockedAmount", u64$1],
1153
+ ["vestingCliffPeriod", u64$1],
1154
+ ["vestingUnlockPeriod", u64$1],
1155
+ ["vestingStartTime", u64$1],
1156
+ ["vestingAllocatedShareAmount", u64$1],
1157
+ ["globalConfig", addressAt],
1158
+ ["platformConfig", addressAt],
1159
+ ["baseMint", addressAt],
1160
+ ["quoteMint", addressAt],
1161
+ ["baseVault", addressAt],
1162
+ ["quoteVault", addressAt],
1163
+ ["creator", addressAt],
1164
+ ["tokenProgramFlag", u8],
1165
+ ["ammCreatorFeeOn", u8]
1166
+ ]);
1167
+ /** The bytes the decoder above reads, discriminator included. The account itself is longer. */
1168
+ const LAUNCHLAB_POOL_STATE_HEAD_SIZE = 367;
1169
+ function decodeLaunchlabPool(data) {
1170
+ checked(data, LAUNCHLAB_POOL_STATE_DISCRIMINATOR, "LaunchLab pool");
1171
+ atLeast(data, 367, "LaunchLab pool");
1172
+ const head = LAUNCHLAB_POOL_HEAD.decode(data, DISCRIMINATOR);
1173
+ return {
1174
+ status: head.status,
1175
+ baseDecimals: head.baseDecimals,
1176
+ quoteDecimals: head.quoteDecimals,
1177
+ migrateType: head.migrateType,
1178
+ supply: head.supply,
1179
+ totalBaseSell: head.totalBaseSell,
1180
+ virtualBase: head.virtualBase,
1181
+ virtualQuote: head.virtualQuote,
1182
+ realBase: head.realBase,
1183
+ realQuote: head.realQuote,
1184
+ totalQuoteFundRaising: head.totalQuoteFundRaising,
1185
+ migrateFee: head.migrateFee,
1186
+ globalConfig: head.globalConfig,
1187
+ platformConfig: head.platformConfig,
1188
+ baseMint: head.baseMint,
1189
+ quoteMint: head.quoteMint,
1190
+ baseVault: head.baseVault,
1191
+ quoteVault: head.quoteVault,
1192
+ creator: head.creator,
1193
+ ammCreatorFeeOn: head.ammCreatorFeeOn
1194
+ };
1195
+ }
1196
+ const LAUNCHLAB_GLOBAL_CONFIG_HEAD = getStructDecoder([
1197
+ ["epoch", u64$1],
1198
+ ["curveType", u8],
1199
+ ["index", u16],
1200
+ ["migrateFee", u64$1],
1201
+ ["tradeFeeRate", u64$1],
1202
+ ["maxShareFeeRate", u64$1],
1203
+ ["minBaseSupply", u64$1],
1204
+ ["maxLockRate", u64$1],
1205
+ ["minBaseSellRate", u64$1],
1206
+ ["minBaseMigrateRate", u64$1],
1207
+ ["minQuoteFundRaising", u64$1],
1208
+ ["quoteMint", addressAt]
1209
+ ]);
1210
+ const LAUNCHLAB_GLOBAL_CONFIG_HEAD_SIZE = 115;
1211
+ function decodeLaunchlabGlobalConfig(data) {
1212
+ checked(data, LAUNCHLAB_GLOBAL_CONFIG_DISCRIMINATOR, "LaunchLab global config");
1213
+ atLeast(data, 115, "LaunchLab global config");
1214
+ const head = LAUNCHLAB_GLOBAL_CONFIG_HEAD.decode(data, DISCRIMINATOR);
1215
+ return {
1216
+ curveType: head.curveType,
1217
+ index: head.index,
1218
+ migrateFee: head.migrateFee,
1219
+ tradeFeeRate: head.tradeFeeRate,
1220
+ quoteMint: head.quoteMint
1221
+ };
1222
+ }
1223
+ /**
1224
+ * The fixed-size head of `PlatformConfig`, before its `curve_params` vector. The three text fields
1225
+ * are fixed byte arrays, so this is the same length for every platform.
1226
+ */
1227
+ const LAUNCHLAB_PLATFORM_CONFIG_HEAD = getStructDecoder([
1228
+ ["epoch", u64$1],
1229
+ ["platformFeeWallet", addressAt],
1230
+ ["platformNftWallet", addressAt],
1231
+ ["platformScale", u64$1],
1232
+ ["creatorScale", u64$1],
1233
+ ["burnScale", u64$1],
1234
+ ["feeRate", u64$1]
1235
+ ]);
1236
+ const PLATFORM_CPSWAP_CONFIG_OFFSET = 688;
1237
+ const PLATFORM_CREATOR_FEE_RATE_OFFSET = 720;
1238
+ const PLATFORM_CP_CREATOR_OFFSET = 800;
1239
+ /** Everything before `curve_params`, discriminator included. */
1240
+ const LAUNCHLAB_PLATFORM_CONFIG_HEAD_SIZE = 940;
1241
+ function decodeLaunchlabPlatformConfig(data) {
1242
+ checked(data, LAUNCHLAB_PLATFORM_CONFIG_DISCRIMINATOR, "LaunchLab platform config");
1243
+ atLeast(data, 940, "LaunchLab platform config");
1244
+ const head = LAUNCHLAB_PLATFORM_CONFIG_HEAD.decode(data, DISCRIMINATOR);
1245
+ return {
1246
+ platformFeeWallet: head.platformFeeWallet,
1247
+ feeRate: head.feeRate,
1248
+ creatorFeeRate: u64$1.decode(data, PLATFORM_CREATOR_FEE_RATE_OFFSET),
1249
+ cpswapConfig: addressAt.decode(data, PLATFORM_CPSWAP_CONFIG_OFFSET),
1250
+ platformCpCreator: addressAt.decode(data, PLATFORM_CP_CREATOR_OFFSET)
1251
+ };
1252
+ }
1253
+ const CPMM_POOL_HEAD = getStructDecoder([
1254
+ ["ammConfig", addressAt],
1255
+ ["poolCreator", addressAt],
1256
+ ["token0Vault", addressAt],
1257
+ ["token1Vault", addressAt],
1258
+ ["lpMint", addressAt],
1259
+ ["token0Mint", addressAt],
1260
+ ["token1Mint", addressAt],
1261
+ ["token0Program", addressAt],
1262
+ ["token1Program", addressAt],
1263
+ ["observationKey", addressAt],
1264
+ ["authBump", u8],
1265
+ ["status", u8],
1266
+ ["lpMintDecimals", u8],
1267
+ ["mint0Decimals", u8],
1268
+ ["mint1Decimals", u8],
1269
+ ["lpSupply", u64$1],
1270
+ ["protocolFeesToken0", u64$1],
1271
+ ["protocolFeesToken1", u64$1],
1272
+ ["fundFeesToken0", u64$1],
1273
+ ["fundFeesToken1", u64$1],
1274
+ ["openTime", u64$1],
1275
+ ["recentEpoch", u64$1],
1276
+ ["creatorFeeOn", u8],
1277
+ ["enableCreatorFee", bool],
1278
+ ["padding1", fixDecoderSize(getBytesDecoder(), 6)],
1279
+ ["creatorFeesToken0", u64$1],
1280
+ ["creatorFeesToken1", u64$1]
1281
+ ]);
1282
+ const CPMM_POOL_STATE_HEAD_SIZE = 413;
1283
+ /**
1284
+ * The full byte length of a CPMM `PoolState`, trailing padding included. A `getProgramAccounts`
1285
+ * scan filters on it, so it has to be the whole account and not only the part decoded above.
1286
+ */
1287
+ const CPMM_POOL_STATE_SIZE = 637;
1288
+ /**
1289
+ * Byte offsets a `getProgramAccounts` scan matches on. They are the same offsets `venue/trade.rs`
1290
+ * reads the fields at, so a pool that passes the scan passes the program's own check.
1291
+ */
1292
+ const CPMM_POOL_OFFSETS = {
1293
+ ammConfig: 8,
1294
+ poolCreator: 40,
1295
+ token0Mint: 168,
1296
+ token1Mint: 200,
1297
+ enableCreatorFee: 390
1298
+ };
1299
+ function decodeCpmmPool(data) {
1300
+ checked(data, CPMM_POOL_STATE_DISCRIMINATOR, "CPMM pool");
1301
+ atLeast(data, 413, "CPMM pool");
1302
+ const head = CPMM_POOL_HEAD.decode(data, DISCRIMINATOR);
1303
+ return {
1304
+ ammConfig: head.ammConfig,
1305
+ poolCreator: head.poolCreator,
1306
+ token0Vault: head.token0Vault,
1307
+ token1Vault: head.token1Vault,
1308
+ token0Mint: head.token0Mint,
1309
+ token1Mint: head.token1Mint,
1310
+ token0Program: head.token0Program,
1311
+ token1Program: head.token1Program,
1312
+ observationKey: head.observationKey,
1313
+ status: head.status,
1314
+ mint0Decimals: head.mint0Decimals,
1315
+ mint1Decimals: head.mint1Decimals,
1316
+ protocolFeesToken0: head.protocolFeesToken0,
1317
+ protocolFeesToken1: head.protocolFeesToken1,
1318
+ fundFeesToken0: head.fundFeesToken0,
1319
+ fundFeesToken1: head.fundFeesToken1,
1320
+ creatorFeesToken0: head.creatorFeesToken0,
1321
+ creatorFeesToken1: head.creatorFeesToken1,
1322
+ openTime: head.openTime,
1323
+ creatorFeeOn: head.creatorFeeOn,
1324
+ enableCreatorFee: head.enableCreatorFee
1325
+ };
1326
+ }
1327
+ const CPMM_AMM_CONFIG_HEAD = getStructDecoder([
1328
+ ["bump", u8],
1329
+ ["disableCreatePool", bool],
1330
+ ["index", u16],
1331
+ ["tradeFeeRate", u64$1],
1332
+ ["protocolFeeRate", u64$1],
1333
+ ["fundFeeRate", u64$1],
1334
+ ["createPoolFee", u64$1],
1335
+ ["protocolOwner", addressAt],
1336
+ ["fundOwner", addressAt],
1337
+ ["creatorFeeRate", u64$1]
1338
+ ]);
1339
+ const CPMM_AMM_CONFIG_HEAD_SIZE = 116;
1340
+ function decodeCpmmAmmConfig(data) {
1341
+ checked(data, CPMM_AMM_CONFIG_DISCRIMINATOR, "CPMM amm config");
1342
+ atLeast(data, 116, "CPMM amm config");
1343
+ const head = CPMM_AMM_CONFIG_HEAD.decode(data, DISCRIMINATOR);
1344
+ return {
1345
+ index: head.index,
1346
+ disableCreatePool: head.disableCreatePool,
1347
+ tradeFeeRate: head.tradeFeeRate,
1348
+ protocolFeeRate: head.protocolFeeRate,
1349
+ fundFeeRate: head.fundFeeRate,
1350
+ creatorFeeRate: head.creatorFeeRate
1351
+ };
1352
+ }
1353
+ //#endregion
1354
+ //#region src/compute.ts
1355
+ /**
1356
+ * The two `ComputeBudget` instructions the transaction builders prepend.
1357
+ *
1358
+ * # Why every gabox transaction needs one
1359
+ *
1360
+ * The default budget is 200,000 compute units for the whole transaction. `buy_pack` alone does a
1361
+ * CPI into Raydium (which does its own CPIs into the token program and may create two fee vaults),
1362
+ * a `transfer_checked`, an account init, and a CPI into MagicBlock's VRF program that allocates a
1363
+ * request account. `createMachine` adds LaunchLab's `initialize_v2` to that, which mints the coin
1364
+ * and writes its Metaplex metadata. Neither fits in the default, and nothing on chain can raise its
1365
+ * own budget.
1366
+ *
1367
+ * # The numbers are measured
1368
+ *
1369
+ * Each figure below is about 1.3x the largest `computeUnitsConsumed` the devnet end-to-end test saw
1370
+ * over three runs on 2026-09-18, across both venues. That matters because the prioritisation fee is
1371
+ * `price x requested limit`: a request three times too large costs three times too much on every
1372
+ * pack. A caller may still override any of them.
1373
+ *
1374
+ * The three runs did not agree. A curve pack cost 164,717, then 167,723, then 181,225 units for the
1375
+ * same work, so the venue's own cost moves with state this SDK does not control. The 1.3x margin is
1376
+ * there to absorb that, and the largest of the three is always the basis.
1377
+ *
1378
+ * Re-measure after a change to a builder or to a Raydium program. `test/devnet.e2e.test.ts` prints
1379
+ * `CU <label>: <units> | <signature>` for every transaction it sends, which is where these came
1380
+ * from.
1381
+ */
1382
+ const COMPUTE_BUDGET_PROGRAM_ADDRESS = "ComputeBudget111111111111111111111111111111";
1383
+ /** The runtime's per-transaction ceiling. A larger request is rejected outright. */
1384
+ const MAX_COMPUTE_UNIT_LIMIT = 14e5;
1385
+ /** What an instruction gets when no `SetComputeUnitLimit` is present. */
1386
+ const DEFAULT_COMPUTE_UNIT_LIMIT = 2e5;
1387
+ /**
1388
+ * LaunchLab `initialize_v2`, the WSOL wrap, pool initialization with a seed buy, and the WSOL
1389
+ * close, in one transaction. Measured at `293,004`, `264,249` and `268,749`. The first run is the
1390
+ * worst case: that creator had no LaunchLab fee vault yet, so the transaction created one.
1391
+ */
1392
+ const CREATE_MACHINE_COMPUTE_UNITS = 385e3;
1393
+ /**
1394
+ * A WSOL wrap, a venue buy, an escrow transfer, a draw init, a VRF request and the WSOL close.
1395
+ * Measured at `164,717`, `167,723` and `181,225` on the curve, and `116,332`, `113,342` and
1396
+ * `119,334` on CPMM. The curve buy is dearer because a coin's first trade also creates the platform
1397
+ * and creator fee vaults.
1398
+ */
1399
+ const BUY_PACK_COMPUTE_UNITS = 24e4;
1400
+ /**
1401
+ * A WSOL wrap, a venue sale, and the WSOL close. Measured at `93,827`, `93,827` and `101,327` on
1402
+ * the curve, and `61,041`, `64,041` and `67,041` on CPMM.
1403
+ */
1404
+ const REDEEM_COMPUTE_UNITS = 135e3;
1405
+ /**
1406
+ * A creator fee claim: create the WSOL account, claim or collect, close it again. Measured at
1407
+ * `31,319` every run for the LaunchLab claim, and `40,959` every run for the CPMM collect.
1408
+ */
1409
+ const CLAIM_COMPUTE_UNITS = 55e3;
1410
+ /** `ComputeBudgetInstruction`'s discriminants. Positional and append-only upstream. */
1411
+ const SET_COMPUTE_UNIT_LIMIT = 2;
1412
+ const SET_COMPUTE_UNIT_PRICE = 3;
1413
+ /** `[u8 discriminant, u32 units]` — five bytes. */
1414
+ const LIMIT_ENCODER = getStructEncoder([["discriminant", getU8Encoder()], ["units", getU32Encoder()]]);
1415
+ /** `[u8 discriminant, u64 microLamports]` — nine bytes. */
1416
+ const PRICE_ENCODER = getStructEncoder([["discriminant", getU8Encoder()], ["microLamports", getU64Encoder()]]);
1417
+ function getSetComputeUnitLimitInstruction(units) {
1418
+ if (!Number.isInteger(units) || units < 0 || units > 14e5) throw new Error(`compute unit limit must be an integer in 0..=${MAX_COMPUTE_UNIT_LIMIT}, got ${units}`);
1419
+ return {
1420
+ programAddress: COMPUTE_BUDGET_PROGRAM_ADDRESS,
1421
+ accounts: [],
1422
+ data: LIMIT_ENCODER.encode({
1423
+ discriminant: SET_COMPUTE_UNIT_LIMIT,
1424
+ units
1425
+ })
1426
+ };
1427
+ }
1428
+ /**
1429
+ * `SetComputeUnitPrice(microLamports)` — the priority fee, per compute unit.
1430
+ *
1431
+ * No default, deliberately. The fee that lands a transaction is a property of the network at the
1432
+ * moment you send it. A hardcoded price is either money burnt on an idle chain or a transaction
1433
+ * that quietly stops landing under load. Sample `getRecentPrioritizationFees`, or take it from
1434
+ * config.
1435
+ */
1436
+ function getSetComputeUnitPriceInstruction(microLamports) {
1437
+ const price = BigInt(microLamports);
1438
+ if (price < 0n) throw new Error(`compute unit price must not be negative, got ${price}`);
1439
+ return {
1440
+ programAddress: COMPUTE_BUDGET_PROGRAM_ADDRESS,
1441
+ accounts: [],
1442
+ data: PRICE_ENCODER.encode({
1443
+ discriminant: SET_COMPUTE_UNIT_PRICE,
1444
+ microLamports: price
1445
+ })
1446
+ };
1447
+ }
1448
+ /** The compute budget prefix a builder prepends: a limit, and a price only when one is asked for. */
1449
+ function computeBudgetInstructions(units, microLamports) {
1450
+ const instructions = [getSetComputeUnitLimitInstruction(units)];
1451
+ if (microLamports !== void 0) instructions.push(getSetComputeUnitPriceInstruction(microLamports));
1452
+ return instructions;
1453
+ }
1454
+ //#endregion
1455
+ //#region src/raydium/accounts.ts
1456
+ /**
1457
+ * The ordered account list of every Raydium trade Gabox forwards.
1458
+ *
1459
+ * # Why these are built here
1460
+ *
1461
+ * `venue/trade.rs` accepts four trade instructions and no others: LaunchLab's `buy_exact_out` and
1462
+ * `sell_exact_in`, CPMM's `swap_base_output` and `swap_base_input`. It takes the venue's own
1463
+ * account list as `remaining_accounts` and walks it position by position. So the lists are
1464
+ * assembled here, from `abi.ts`, which codegen generated from the same Raydium IDLs the program's
1465
+ * `venue/abi.rs` came from.
1466
+ *
1467
+ * # How to read the output
1468
+ *
1469
+ * Each function returns `AccountMeta[]` in ABI order, with the role each slot's own ABI gives it.
1470
+ * That list goes into `initialize_pool`, `buy_pack` or `sell_tokens` as `remainingAccounts`,
1471
+ * unchanged. The program then requires every writable slot to be writable in the outer transaction,
1472
+ * requires the one signer slot to be the purchaser, and checks every address by name.
1473
+ *
1474
+ * # CPMM names its accounts by direction
1475
+ *
1476
+ * CPMM calls its four pairs `input_*` and `output_*`. A buy sends quote and receives the coin; a
1477
+ * sell is the other way round. So the two builders below fill the same four names with opposite
1478
+ * addresses. LaunchLab names its accounts by role instead, and uses one list for both sides.
1479
+ */
1480
+ /**
1481
+ * Turn `{name -> address}` into the ABI's ordered `AccountMeta[]`.
1482
+ *
1483
+ * The map is keyed by the IDL's own account names, so a missing entry names the slot it belongs to
1484
+ * rather than failing as an off-by-one further down. The role comes from the ABI table alone, never
1485
+ * from the caller, which is what keeps this list in step with `venue/abi.rs`.
1486
+ */
1487
+ function order(abi, byName) {
1488
+ return abi.accounts.map((spec) => {
1489
+ const address = byName[spec.name];
1490
+ if (address === void 0) throw new Error(`${abi.name}: no address given for the "${spec.name}" account`);
1491
+ return {
1492
+ address,
1493
+ role: spec.signer ? spec.writable ? AccountRole.WRITABLE_SIGNER : AccountRole.READONLY_SIGNER : spec.writable ? AccountRole.WRITABLE : AccountRole.READONLY
1494
+ };
1495
+ });
1496
+ }
1497
+ function launchlabTradeAccounts(abi, input) {
1498
+ return order(abi, {
1499
+ payer: input.user,
1500
+ authority: input.launchlabAuthority,
1501
+ global_config: input.globalConfig,
1502
+ platform_config: input.platformConfig,
1503
+ pool_state: input.poolState,
1504
+ user_base_token: input.userBaseToken,
1505
+ user_quote_token: input.userQuoteToken,
1506
+ base_vault: input.baseVault,
1507
+ quote_vault: input.quoteVault,
1508
+ base_token_mint: input.mint,
1509
+ quote_token_mint: input.quoteMint,
1510
+ base_token_program: TOKEN_PROGRAM_ADDRESS,
1511
+ quote_token_program: TOKEN_PROGRAM_ADDRESS,
1512
+ event_authority: input.launchlabEventAuthority,
1513
+ program: input.launchlab,
1514
+ system_program: SYSTEM_PROGRAM_ADDRESS,
1515
+ platform_fee_vault: input.platformFeeVault,
1516
+ creator_fee_vault: input.creatorFeeVault
1517
+ });
1518
+ }
1519
+ /** `buy_exact_out`: 18 accounts. The first argument is the coins wanted, the second the cost cap. */
1520
+ const launchlabBuyAccounts = (input) => launchlabTradeAccounts(LAUNCHLAB_BUY_EXACT_OUT, input);
1521
+ /** `sell_exact_in`: the same 18 accounts. `venue/trade.rs` uses one table for both sides. */
1522
+ const launchlabSellAccounts = (input) => launchlabTradeAccounts(LAUNCHLAB_SELL_EXACT_IN, input);
1523
+ /**
1524
+ * `buy_exact_in`: the same 18 accounts again. Gabox never forwards this instruction; a wallet sends
1525
+ * it on its own, to buy the curve out with a fixed spend.
1526
+ */
1527
+ const launchlabBuyExactInAccounts = (input) => launchlabTradeAccounts(LAUNCHLAB_BUY_EXACT_IN, input);
1528
+ /** A buy sends the quote and receives the coin. A sell is the other way round. */
1529
+ function cpmmTradeAccounts(abi, input, side) {
1530
+ const buying = side === "buy";
1531
+ return order(abi, {
1532
+ payer: input.user,
1533
+ authority: input.cpmmAuthority,
1534
+ amm_config: input.ammConfig,
1535
+ pool_state: input.poolState,
1536
+ input_token_account: buying ? input.userQuoteToken : input.userBaseToken,
1537
+ output_token_account: buying ? input.userBaseToken : input.userQuoteToken,
1538
+ input_vault: buying ? input.quoteVault : input.baseVault,
1539
+ output_vault: buying ? input.baseVault : input.quoteVault,
1540
+ input_token_program: TOKEN_PROGRAM_ADDRESS,
1541
+ output_token_program: TOKEN_PROGRAM_ADDRESS,
1542
+ input_token_mint: buying ? input.quoteMint : input.mint,
1543
+ output_token_mint: buying ? input.mint : input.quoteMint,
1544
+ observation_state: input.observationState
1545
+ });
1546
+ }
1547
+ /** `swap_base_output`: 13 accounts. Note the argument order is `(max_amount_in, amount_out)`. */
1548
+ const cpmmBuyAccounts = (input) => cpmmTradeAccounts(CPMM_SWAP_BASE_OUTPUT, input, "buy");
1549
+ /** `swap_base_input`: 13 accounts, with the four pairs swapped. */
1550
+ const cpmmSellAccounts = (input) => cpmmTradeAccounts(CPMM_SWAP_BASE_INPUT, input, "sell");
1551
+ //#endregion
1552
+ //#region src/raydium/curve.ts
1553
+ /**
1554
+ * Raydium's own price math, ported to bigint.
1555
+ *
1556
+ * Every function here is a line-by-line port of Raydium's TypeScript, which is itself the same math
1557
+ * their on-chain programs run. The point is that a buyer sees the exact number the venue will
1558
+ * charge, not an estimate: `buy_pack` passes the pack size as an exact-tokens-out amount, and the
1559
+ * program then requires the token delta to equal one pack.
1560
+ *
1561
+ * Sources, read on 2026-09-18:
1562
+ *
1563
+ * - `raydium/launchpad/curve/constantProductCurve.ts` and `curve.ts` (LaunchLab)
1564
+ * - `raydium/cpmm/curve/calculator.ts`, `constantProduct.ts` and `fee.ts` (CPMM)
1565
+ *
1566
+ * Raydium uses `BN`, which truncates toward zero on division. Every value here is a non-negative
1567
+ * bigint, where `/` truncates the same way, so a plain `/` is the faithful port of their `.div()`.
1568
+ * Where they round up they call a ceiling helper, and so does this file. Nothing is approximated
1569
+ * and no step is reordered: a division that happens before a subtraction there happens before it
1570
+ * here, because the two orders give different answers.
1571
+ *
1572
+ * Every rate is out of 1,000,000, not out of 10,000.
1573
+ */
1574
+ /** `ceilDiv(a, b, denominator)` in Raydium's code: `ceil(a * b / denominator)`. */
1575
+ function ceilDivRate(amount, rate, denominator = RATE_DENOMINATOR) {
1576
+ if (rate === 0n) return 0n;
1577
+ return ceilDiv(amount * rate, denominator);
1578
+ }
1579
+ /** `ceil(numerator / denominator)` for non-negative values. */
1580
+ function ceilDiv(numerator, denominator) {
1581
+ if (denominator === 0n) throw new Error("divide by zero");
1582
+ return (numerator + denominator - 1n) / denominator;
1583
+ }
1584
+ /**
1585
+ * The amount before a fee was taken, given the amount after it: `ceil(post * 1e6 / (1e6 - rate))`.
1586
+ *
1587
+ * Raydium calls this `calculatePreFee` on the curve and `calculatePreFeeAmount` on CPMM. Both are
1588
+ * the same expression.
1589
+ */
1590
+ function preFeeAmount(postFeeAmount, rate) {
1591
+ if (rate === 0n) return postFeeAmount;
1592
+ if (rate >= 1000000n) throw new Error("a fee rate of 100% or more has no pre-fee amount");
1593
+ return ceilDiv(postFeeAmount * RATE_DENOMINATOR, RATE_DENOMINATOR - rate);
1594
+ }
1595
+ /**
1596
+ * The whole fee a curve trade pays. Gabox never passes a share-fee receiver, so the fourth rate
1597
+ * Raydium supports is always zero and is left out here.
1598
+ */
1599
+ function totalCurveFeeRate(rates) {
1600
+ const total = rates.tradeFeeRate + rates.platformFeeRate + rates.creatorFeeRate;
1601
+ if (total > 1000000n) throw new Error("the total curve fee rate exceeds 1,000,000");
1602
+ return total;
1603
+ }
1604
+ /** Coins the curve still has to sell. A buy cannot take more than this. */
1605
+ function remainingBase(pool) {
1606
+ return pool.totalBaseSell > pool.realBase ? pool.totalBaseSell - pool.realBase : 0n;
1607
+ }
1608
+ /** The two sides of the constant product, as the curve sees them right now. */
1609
+ const quoteSide = (pool) => pool.virtualQuote + pool.realQuote;
1610
+ const baseSide = (pool) => pool.virtualBase - pool.realBase;
1611
+ /**
1612
+ * Quote needed to buy exactly `tokens` coins on the curve, fees included.
1613
+ *
1614
+ * This is `Curve.buyExactOut` with no token transfer fee, which is always the case for Gabox: both
1615
+ * mints are classic SPL Token and carry no transfer-fee extension.
1616
+ *
1617
+ * Raydium caps the amount at what the curve has left to sell and still returns a price, so this
1618
+ * does the same. A caller that needs the whole `tokens` must check `remainingBase` first;
1619
+ * `resolveVenue` does.
1620
+ */
1621
+ function curveBuyExactOut(pool, rates, tokens) {
1622
+ if (tokens <= 0n) throw new Error("tokens must be positive");
1623
+ const remaining = remainingBase(pool);
1624
+ const amount = tokens > remaining ? remaining : tokens;
1625
+ if (amount === 0n) throw new Error("the curve has no coins left to sell");
1626
+ return preFeeAmount(curveQuoteInForBaseOut(pool, amount), totalCurveFeeRate(rates));
1627
+ }
1628
+ /**
1629
+ * Coins `quote` buys on the curve right now, fees already taken off the spend.
1630
+ *
1631
+ * This is `Curve.buyExactIn`. It is what a raw `buy_exact_in` pays out, which the devnet end-to-end
1632
+ * test uses to push a curve to graduation.
1633
+ */
1634
+ function curveBuyExactIn(pool, rates, quote) {
1635
+ if (quote <= 0n) throw new Error("quote must be positive");
1636
+ const spend = quote - ceilDivRate(quote, totalCurveFeeRate(rates));
1637
+ if (spend <= 0n) throw new Error("the whole spend would go to fees");
1638
+ const tokens = curveBaseOutForQuoteIn(pool, spend);
1639
+ const remaining = remainingBase(pool);
1640
+ return tokens > remaining ? remaining : tokens;
1641
+ }
1642
+ /**
1643
+ * Quote a sale of exactly `tokens` coins returns, net of fees. This is `Curve.sellExactIn`.
1644
+ */
1645
+ function curveSellExactIn(pool, rates, tokens) {
1646
+ if (tokens <= 0n) throw new Error("tokens must be positive");
1647
+ const gross = curveQuoteOutForBaseIn(pool, tokens);
1648
+ const fee = ceilDivRate(gross, totalCurveFeeRate(rates));
1649
+ return gross > fee ? gross - fee : 0n;
1650
+ }
1651
+ /** `getAmountIn` on the buy side: `ceil(quoteSide * out / (baseSide - out))`. */
1652
+ function curveQuoteInForBaseOut(pool, tokens) {
1653
+ const output = baseSide(pool);
1654
+ if (tokens >= output) throw new Error("the curve does not hold that many coins");
1655
+ return ceilDiv(quoteSide(pool) * tokens, output - tokens);
1656
+ }
1657
+ /** `getAmountOut` on the buy side: `floor(in * baseSide / (quoteSide + in))`. */
1658
+ function curveBaseOutForQuoteIn(pool, quote) {
1659
+ return quote * baseSide(pool) / (quoteSide(pool) + quote);
1660
+ }
1661
+ /** `getAmountOut` on the sell side: `floor(in * quoteSide / (baseSide + in))`. */
1662
+ function curveQuoteOutForBaseIn(pool, tokens) {
1663
+ return tokens * quoteSide(pool) / (baseSide(pool) + tokens);
1664
+ }
1665
+ /**
1666
+ * The virtual reserves LaunchLab gives a coin that does not exist yet.
1667
+ *
1668
+ * This is `LaunchConstantProductCurve.getInitParam`. `createMachine` needs it because the seed buy
1669
+ * runs in the same transaction that creates the coin: there is no pool account to read yet, and the
1670
+ * reserves follow from the pinned launch shape alone.
1671
+ *
1672
+ * Checked against Raydium's own published numbers for the mainnet Gabox launch shape (supply
1673
+ * 1,000,000,000 coins, 793,100,000 sold on the curve, 85 SOL raised, no migrate fee):
1674
+ * `virtualBase` 1,073,025,605,596,382 and `virtualQuote` 30,000,852,951.
1675
+ */
1676
+ function initialCurve(params) {
1677
+ const { supply, totalBaseSell, quoteRaise } = params;
1678
+ const locked = params.totalLockedAmount ?? 0n;
1679
+ const migrateFee = params.migrateFee ?? 0n;
1680
+ if (supply <= totalBaseSell) throw new Error("the supply must be larger than the curve sells");
1681
+ const migrateBase = supply - totalBaseSell - locked;
1682
+ if (migrateBase <= 0n) throw new Error("nothing would be left to seed the pool at graduation");
1683
+ const raiseLessMigrateFee = quoteRaise - migrateFee;
1684
+ if (raiseLessMigrateFee <= 0n) throw new Error("the migrate fee eats the whole raise");
1685
+ const numerator = raiseLessMigrateFee * totalBaseSell * totalBaseSell / migrateBase;
1686
+ const denominator = raiseLessMigrateFee * totalBaseSell / migrateBase - quoteRaise;
1687
+ if (denominator <= 0n) throw new Error("these launch parameters have no valid starting price");
1688
+ return {
1689
+ virtualBase: numerator / denominator,
1690
+ virtualQuote: quoteRaise * quoteRaise / denominator,
1691
+ realBase: 0n,
1692
+ realQuote: 0n,
1693
+ totalBaseSell
1694
+ };
1695
+ }
1696
+ /**
1697
+ * Quote a CPMM buy of exactly `tokens` coins costs, both fees included.
1698
+ *
1699
+ * This is `CurveCalculator.swapBaseOutput`, which is what `swap_base_output` charges.
1700
+ */
1701
+ function cpmmSwapBaseOutput(sides, rates, amountOut) {
1702
+ if (amountOut <= 0n) throw new Error("amountOut must be positive");
1703
+ const actualOut = rates.creatorFeeOnInput ? amountOut : preFeeAmount(amountOut, rates.creatorFeeRate);
1704
+ if (actualOut >= sides.outputReserve) throw new Error("the pool does not hold that much of the output token");
1705
+ return preFeeAmount(ceilDiv(sides.inputReserve * actualOut, sides.outputReserve - actualOut), rates.creatorFeeOnInput ? rates.tradeFeeRate + rates.creatorFeeRate : rates.tradeFeeRate);
1706
+ }
1707
+ /**
1708
+ * What a CPMM swap of exactly `amountIn` returns, net of both fees.
1709
+ *
1710
+ * This is `CurveCalculator.swapBaseInput`, which is what `swap_base_input` pays out.
1711
+ */
1712
+ function cpmmSwapBaseInput(sides, rates, amountIn) {
1713
+ if (amountIn <= 0n) throw new Error("amountIn must be positive");
1714
+ const tradeFee = ceilDivRate(amountIn, rates.tradeFeeRate);
1715
+ const creatorFeeIn = rates.creatorFeeOnInput ? ceilDivRate(amountIn, rates.creatorFeeRate) : 0n;
1716
+ const lessFees = amountIn - tradeFee - creatorFeeIn;
1717
+ if (lessFees <= 0n) throw new Error("the whole input would go to fees");
1718
+ const swapped = lessFees * sides.outputReserve / (sides.inputReserve + lessFees);
1719
+ if (rates.creatorFeeOnInput) return swapped;
1720
+ const creatorFeeOut = ceilDivRate(swapped, rates.creatorFeeRate);
1721
+ return swapped > creatorFeeOut ? swapped - creatorFeeOut : 0n;
1722
+ }
1723
+ //#endregion
1724
+ //#region src/raydium/venue.ts
1725
+ /**
1726
+ * Reading the venue: which one a coin trades on right now, what a pack costs there, and the account
1727
+ * list for the trade.
1728
+ *
1729
+ * `resolveVenue` reads every account the answer depends on, decodes them, and hands back a plain
1730
+ * object whose methods are pure. A caller that wants to re-price a different token count calls
1731
+ * `quoteBuy` again with no further reads.
1732
+ *
1733
+ * # Choosing the venue
1734
+ *
1735
+ * The LaunchLab pool's `status` is the whole rule:
1736
+ *
1737
+ * - `0`: the curve is still selling, so trade LaunchLab.
1738
+ * - `1`: the raise is finished and Raydium's own bot is moving the coin into a CPMM pool. Nothing
1739
+ * trades. This throws, and the message says to retry in a moment. On devnet the move usually
1740
+ * finishes within a minute.
1741
+ * - `2`: the coin graduated, so trade its CPMM pool.
1742
+ *
1743
+ * A coin can graduate between the read and the send. A pack buy then fails and no draw is created,
1744
+ * which is the intended outcome: refresh and retry.
1745
+ *
1746
+ * # Finding the migrated CPMM pool
1747
+ *
1748
+ * The pool is normally at `["pool", cpswap_config, token_0, token_1]` under CPMM, where
1749
+ * `cpswap_config` is the fee tier the Gabox platform config names. It is not always: when that
1750
+ * address is already taken, Raydium migrates into a random account instead. So this module tries
1751
+ * the derived address first and falls back to a filtered `getProgramAccounts` scan.
1752
+ *
1753
+ * Either way the pool has to prove itself from its own data, which is what `venue/trade.rs` checks
1754
+ * on chain as well: CPMM owns it, it carries the `PoolState` discriminator, its `pool_creator` is
1755
+ * the coin creator, its two mints are the sorted pair, and `enable_creator_fee` is true. That last
1756
+ * flag is the one that cannot be forged. A plain CPMM `initialize` always leaves it false; only a
1757
+ * creator Raydium has permissioned, such as LaunchLab's migration, can set it.
1758
+ */
1759
+ const base64$1 = getBase64Encoder();
1760
+ async function readAccounts(rpc, addresses) {
1761
+ const { value } = await rpc.getMultipleAccounts(addresses, {
1762
+ encoding: "base64",
1763
+ commitment: "confirmed"
1764
+ }).send();
1765
+ return value.map((account) => {
1766
+ if (!account) return null;
1767
+ const [encoded] = account.data;
1768
+ return {
1769
+ data: new Uint8Array(base64$1.encode(encoded)),
1770
+ owner: account.owner
1771
+ };
1772
+ });
1773
+ }
1774
+ /**
1775
+ * The user's WSOL associated token account.
1776
+ *
1777
+ * Both venues settle in WSOL, never in native SOL. This account must exist and hold enough before a
1778
+ * pack is bought, and sale proceeds land in it. Every builder in `tx/` wraps the SOL it needs into
1779
+ * this account and closes it again in the same transaction.
1780
+ */
1781
+ async function wsolAccountFor(user) {
1782
+ return await ata(user, WSOL_MINT);
1783
+ }
1784
+ /** Read the two pinned config accounts and take the four numbers a quote needs out of them. */
1785
+ async function fetchCurveSettings(client, ids = raydiumIds(client.cluster)) {
1786
+ const [globalAccount, platformAccount] = await readAccounts(client.rpc, [ids.solGlobalConfig, ids.gaboxPlatform]);
1787
+ if (!globalAccount) throw new Error(`LaunchLab's WSOL global config is missing at ${ids.solGlobalConfig}`);
1788
+ if (!platformAccount) throw new Error(`the Gabox platform config is missing at ${ids.gaboxPlatform}`);
1789
+ return settingsFrom(globalAccount.data, platformAccount.data);
1790
+ }
1791
+ function settingsFrom(globalData, platformData) {
1792
+ const global = decodeLaunchlabGlobalConfig(globalData);
1793
+ const platform = decodeLaunchlabPlatformConfig(platformData);
1794
+ return {
1795
+ rates: {
1796
+ tradeFeeRate: global.tradeFeeRate,
1797
+ platformFeeRate: platform.feeRate,
1798
+ creatorFeeRate: platform.creatorFeeRate
1799
+ },
1800
+ migrateFee: global.migrateFee,
1801
+ cpswapConfig: platform.cpswapConfig
1802
+ };
1803
+ }
1804
+ async function resolveVenue(client, options) {
1805
+ const ids = raydiumIds(client.cluster);
1806
+ const { mint, user } = options;
1807
+ const quoteMint = WSOL_MINT;
1808
+ const curvePool = await launchlabPoolAddress(ids.launchlab, mint, quoteMint);
1809
+ const [poolAccount, globalAccount, platformAccount] = await readAccounts(client.rpc, [
1810
+ curvePool,
1811
+ ids.solGlobalConfig,
1812
+ ids.gaboxPlatform
1813
+ ]);
1814
+ if (!poolAccount) throw new Error(`no LaunchLab pool at ${curvePool}. The coin was not launched on LaunchLab with WSOL as its quote, so it has no Gabox venue.`);
1815
+ if (!globalAccount) throw new Error(`LaunchLab's WSOL global config is missing at ${ids.solGlobalConfig}`);
1816
+ if (!platformAccount) throw new Error(`the Gabox platform config is missing at ${ids.gaboxPlatform}`);
1817
+ const pool = decodeLaunchlabPool(poolAccount.data);
1818
+ if (pool.baseMint !== mint || pool.quoteMint !== quoteMint) throw new Error(`the LaunchLab pool at ${curvePool} is not the pool of ${mint}`);
1819
+ const settings = settingsFrom(globalAccount.data, platformAccount.data);
1820
+ const kind = options.venue ?? (pool.status === 2 ? "cpmm" : "launchlab");
1821
+ if (options.venue === void 0 && pool.status === 1) throw new Error(`${mint} is graduating: its LaunchLab curve is sold out and Raydium is moving it into a CPMM pool. Retry in a moment; the move usually finishes within a minute.`);
1822
+ if (kind === "launchlab") {
1823
+ if (pool.status !== 0) throw new Error(`${mint} no longer trades on its LaunchLab curve (status ${pool.status}). Use the CPMM venue.`);
1824
+ return await launchlabVenue(ids, pool, settings.rates, {
1825
+ mint,
1826
+ quoteMint,
1827
+ user,
1828
+ poolState: curvePool
1829
+ });
1830
+ }
1831
+ return await cpmmVenue(client, ids, pool, settings.cpswapConfig, {
1832
+ mint,
1833
+ quoteMint,
1834
+ user
1835
+ });
1836
+ }
1837
+ async function launchlabVenue(ids, pool, rates, where) {
1838
+ const { mint, quoteMint, user, poolState } = where;
1839
+ const shared = {
1840
+ launchlab: ids.launchlab,
1841
+ launchlabAuthority: ids.launchlabAuthority,
1842
+ launchlabEventAuthority: ids.launchlabEventAuthority,
1843
+ globalConfig: ids.solGlobalConfig,
1844
+ platformConfig: ids.gaboxPlatform,
1845
+ poolState,
1846
+ mint,
1847
+ quoteMint,
1848
+ baseVault: await launchlabVaultAddress(ids.launchlab, poolState, mint),
1849
+ quoteVault: await launchlabVaultAddress(ids.launchlab, poolState, quoteMint),
1850
+ user,
1851
+ userBaseToken: await ata(user, mint),
1852
+ userQuoteToken: await ata(user, quoteMint),
1853
+ platformFeeVault: await platformFeeVaultAddress(ids.launchlab, ids.gaboxPlatform, quoteMint),
1854
+ creatorFeeVault: await creatorFeeVaultAddress(ids.launchlab, pool.creator, quoteMint)
1855
+ };
1856
+ const reserves = {
1857
+ virtualBase: pool.virtualBase,
1858
+ virtualQuote: pool.virtualQuote,
1859
+ realBase: pool.realBase,
1860
+ realQuote: pool.realQuote,
1861
+ totalBaseSell: pool.totalBaseSell
1862
+ };
1863
+ const remaining = remainingBase(reserves);
1864
+ return {
1865
+ kind: "launchlab",
1866
+ program: ids.launchlab,
1867
+ mint,
1868
+ quoteMint,
1869
+ poolState,
1870
+ status: pool.status,
1871
+ creator: pool.creator,
1872
+ ammConfig: null,
1873
+ remainingCurveBase: remaining,
1874
+ buyAccounts: launchlabBuyAccounts(shared),
1875
+ sellAccounts: launchlabSellAccounts(shared),
1876
+ quoteBuy: (tokens) => {
1877
+ if (tokens > remaining) throw new Error(`the curve has ${remaining} base units left and cannot sell ${tokens}. Wait for the coin to graduate, then buy on its CPMM pool.`);
1878
+ return curveBuyExactOut(reserves, rates, tokens);
1879
+ },
1880
+ quoteSell: (tokens) => curveSellExactIn(reserves, rates, tokens)
1881
+ };
1882
+ }
1883
+ /**
1884
+ * Every check the program makes on a CPMM pool account, in one place.
1885
+ *
1886
+ * `enable_creator_fee` is the one that identifies the migrated pool. Anyone can call CPMM's own
1887
+ * `initialize` and open a pool for the same pair with the same creator, but that pool always has
1888
+ * the flag false. Only a creator Raydium has permissioned can set it, and LaunchLab's migration is
1889
+ * one of those.
1890
+ */
1891
+ function cpmmPoolMatches(pool, expect) {
1892
+ return pool.enableCreatorFee && pool.poolCreator === expect.creator && pool.token0Mint === expect.token0 && pool.token1Mint === expect.token1;
1893
+ }
1894
+ /**
1895
+ * The CPMM pool LaunchLab migrated a coin into.
1896
+ *
1897
+ * Two steps, because the pool is not always at a derived address. Raydium migrates into
1898
+ * `["pool", cpswap_config, token_0, token_1]` when that account is free, and into a random account
1899
+ * when it is not. So: try the derived address, and scan for the pool when it does not hold one.
1900
+ *
1901
+ * The scan filters on the account length and on the three fields at their fixed offsets, so the
1902
+ * RPC does the work and returns at most a handful of accounts. Every candidate still has to pass
1903
+ * `cpmmPoolMatches`, and more than one match is an error rather than a guess.
1904
+ */
1905
+ async function findCpmmPool(client, options) {
1906
+ const ids = raydiumIds(client.cluster);
1907
+ const { mint, creator, cpswapConfig } = options;
1908
+ const quoteMint = options.quoteMint ?? "So11111111111111111111111111111111111111112";
1909
+ const [token0, token1] = sortedMints(mint, quoteMint);
1910
+ const expect = {
1911
+ creator,
1912
+ token0,
1913
+ token1
1914
+ };
1915
+ const derived = await cpmmPoolAddress(ids.cpmm, cpswapConfig, mint, quoteMint);
1916
+ const [account] = await readAccounts(client.rpc, [derived]);
1917
+ if (account && account.owner === ids.cpmm) {
1918
+ const pool = decodeCpmmPoolOrNull(account.data);
1919
+ if (pool && cpmmPoolMatches(pool, expect)) return {
1920
+ address: derived,
1921
+ pool
1922
+ };
1923
+ }
1924
+ const rows = await client.rpc.getProgramAccounts(ids.cpmm, {
1925
+ encoding: "base64",
1926
+ commitment: "confirmed",
1927
+ filters: [
1928
+ { dataSize: BigInt(637) },
1929
+ memcmp(CPMM_POOL_OFFSETS.poolCreator, creator),
1930
+ memcmp(CPMM_POOL_OFFSETS.token0Mint, token0),
1931
+ memcmp(CPMM_POOL_OFFSETS.token1Mint, token1)
1932
+ ]
1933
+ }).send();
1934
+ const matches = [];
1935
+ for (const { pubkey, account: row } of rows) {
1936
+ const pool = decodeCpmmPoolOrNull(new Uint8Array(base64$1.encode(row.data[0])));
1937
+ if (pool && cpmmPoolMatches(pool, expect)) matches.push({
1938
+ address: pubkey,
1939
+ pool
1940
+ });
1941
+ }
1942
+ const [only] = matches;
1943
+ if (!only) throw new Error(`no migrated CPMM pool for ${mint}. The derived address ${derived} holds no matching pool, and no other CPMM pool has this coin, this creator and a creator fee enabled.`);
1944
+ if (matches.length > 1) throw new Error(`${matches.length} CPMM pools match ${mint}: ${matches.map((m) => m.address).join(", ")}. Pass the one you mean rather than letting this choose.`);
1945
+ return only;
1946
+ }
1947
+ /** A `getProgramAccounts` byte filter. The bytes of an address are its own base58 text. */
1948
+ function memcmp(offset, value) {
1949
+ return { memcmp: {
1950
+ offset: BigInt(offset),
1951
+ bytes: value,
1952
+ encoding: "base58"
1953
+ } };
1954
+ }
1955
+ /** Decode a candidate account, or give up quietly. A scan row that is not a pool is not an error. */
1956
+ function decodeCpmmPoolOrNull(data) {
1957
+ try {
1958
+ return decodeCpmmPool(data);
1959
+ } catch {
1960
+ return null;
1961
+ }
1962
+ }
1963
+ async function cpmmVenue(client, ids, curve, cpswapConfig, where) {
1964
+ const { mint, quoteMint, user } = where;
1965
+ const { address: poolState, pool } = await findCpmmPool(client, {
1966
+ mint,
1967
+ quoteMint,
1968
+ creator: curve.creator,
1969
+ cpswapConfig
1970
+ });
1971
+ const baseIsToken0 = pool.token0Mint === mint;
1972
+ const baseVault = baseIsToken0 ? pool.token0Vault : pool.token1Vault;
1973
+ const quoteVault = baseIsToken0 ? pool.token1Vault : pool.token0Vault;
1974
+ const [configAccount, baseVaultAccount, quoteVaultAccount] = await readAccounts(client.rpc, [
1975
+ pool.ammConfig,
1976
+ baseVault,
1977
+ quoteVault
1978
+ ]);
1979
+ if (!configAccount) throw new Error(`the CPMM pool at ${poolState} names a fee tier that is not on chain`);
1980
+ if (!baseVaultAccount || !quoteVaultAccount) throw new Error(`the CPMM pool at ${poolState} has no reserve accounts`);
1981
+ const config = decodeCpmmAmmConfig(configAccount.data);
1982
+ const owedBase = baseIsToken0 ? pool.protocolFeesToken0 + pool.fundFeesToken0 + pool.creatorFeesToken0 : pool.protocolFeesToken1 + pool.fundFeesToken1 + pool.creatorFeesToken1;
1983
+ const owedQuote = baseIsToken0 ? pool.protocolFeesToken1 + pool.fundFeesToken1 + pool.creatorFeesToken1 : pool.protocolFeesToken0 + pool.fundFeesToken0 + pool.creatorFeesToken0;
1984
+ const baseReserve = tokenAccountAmount(baseVaultAccount.data) - owedBase;
1985
+ const quoteReserve = tokenAccountAmount(quoteVaultAccount.data) - owedQuote;
1986
+ if (baseReserve <= 0n || quoteReserve <= 0n) throw new Error(`the CPMM pool at ${poolState} has no tradable reserves`);
1987
+ const shared = {
1988
+ cpmmAuthority: ids.cpmmAuthority,
1989
+ ammConfig: pool.ammConfig,
1990
+ poolState,
1991
+ mint,
1992
+ quoteMint,
1993
+ baseVault,
1994
+ quoteVault,
1995
+ observationState: pool.observationKey,
1996
+ user,
1997
+ userBaseToken: await ata(user, mint),
1998
+ userQuoteToken: await ata(user, quoteMint)
1999
+ };
2000
+ const creatorFeeRate = pool.enableCreatorFee ? config.creatorFeeRate : 0n;
2001
+ const buySides = {
2002
+ inputReserve: quoteReserve,
2003
+ outputReserve: baseReserve
2004
+ };
2005
+ const sellSides = {
2006
+ inputReserve: baseReserve,
2007
+ outputReserve: quoteReserve
2008
+ };
2009
+ const buyRates = {
2010
+ tradeFeeRate: config.tradeFeeRate,
2011
+ creatorFeeRate,
2012
+ creatorFeeOnInput: creatorFeeOnInput(pool, quoteMint)
2013
+ };
2014
+ const sellRates = {
2015
+ tradeFeeRate: config.tradeFeeRate,
2016
+ creatorFeeRate,
2017
+ creatorFeeOnInput: creatorFeeOnInput(pool, mint)
2018
+ };
2019
+ return {
2020
+ kind: "cpmm",
2021
+ program: ids.cpmm,
2022
+ mint,
2023
+ quoteMint,
2024
+ poolState,
2025
+ status: curve.status,
2026
+ creator: pool.poolCreator,
2027
+ ammConfig: pool.ammConfig,
2028
+ remainingCurveBase: 0n,
2029
+ buyAccounts: cpmmBuyAccounts(shared),
2030
+ sellAccounts: cpmmSellAccounts(shared),
2031
+ quoteBuy: (tokens) => cpmmSwapBaseOutput(buySides, buyRates, tokens),
2032
+ quoteSell: (tokens) => cpmmSwapBaseInput(sellSides, sellRates, tokens)
2033
+ };
2034
+ }
2035
+ /**
2036
+ * Does this side's creator fee come off the token going in?
2037
+ *
2038
+ * `creator_fee_on` is 0 when the fee follows the input token, 1 when it is always token 0, and 2
2039
+ * when it is always token 1. LaunchLab migrates a Gabox coin with `AmmCreatorFeeOn::QuoteToken`, so
2040
+ * the pool charges the creator fee in WSOL only: on the input of a buy, on the output of a sale.
2041
+ */
2042
+ function creatorFeeOnInput(pool, inputMint) {
2043
+ if (pool.creatorFeeOn === 0) return true;
2044
+ const inputIsToken0 = pool.token0Mint === inputMint;
2045
+ return pool.creatorFeeOn === 1 ? inputIsToken0 : !inputIsToken0;
2046
+ }
2047
+ /**
2048
+ * WSOL an exact-coins-out buy of `tokens` costs right now, on whichever venue the coin trades.
2049
+ * Pass `pool.packTokens` for the pack price.
2050
+ *
2051
+ * Use `resolveVenue` when you also need the account list, which every transaction builder does.
2052
+ * This is for a price display.
2053
+ */
2054
+ async function curveQuote(client, mint, tokens, options = {}) {
2055
+ return (await resolveVenue(client, {
2056
+ mint,
2057
+ user: options.user ?? mint,
2058
+ ...options.venue ? { venue: options.venue } : {}
2059
+ })).quoteBuy(tokens);
2060
+ }
2061
+ /** WSOL a sale of `tokens` returns right now, net of the venue's fees. */
2062
+ async function sellQuote(client, mint, tokens, options = {}) {
2063
+ return (await resolveVenue(client, {
2064
+ mint,
2065
+ user: options.user ?? mint,
2066
+ ...options.venue ? { venue: options.venue } : {}
2067
+ })).quoteSell(tokens);
2068
+ }
2069
+ /**
2070
+ * WSOL an exact-coins-out buy of `tokens` would cost on a curve that does not exist yet, fees
2071
+ * included.
2072
+ *
2073
+ * This is what the seed costs. `initialize_pool` buys it in the same transaction that creates the
2074
+ * coin, so the curve is a brand-new LaunchLab curve with the pinned Gabox launch shape at that
2075
+ * moment. Exact, unless Raydium changes a fee rate between this read and the send.
2076
+ */
2077
+ async function newCurveBuyCost(client, tokens) {
2078
+ if (tokens <= 0n) return 0n;
2079
+ const ids = raydiumIds(client.cluster);
2080
+ const settings = await fetchCurveSettings(client, ids);
2081
+ return curveBuyExactOut(newCurveReserves(ids, settings.migrateFee), settings.rates, tokens);
2082
+ }
2083
+ /** The starting reserves of a brand-new Gabox curve on this cluster. */
2084
+ function newCurveReserves(ids, migrateFee) {
2085
+ return initialCurve({
2086
+ supply: LAUNCH_SUPPLY,
2087
+ totalBaseSell: LAUNCH_TOTAL_BASE_SELL,
2088
+ quoteRaise: ids.launchQuoteRaise,
2089
+ migrateFee
2090
+ });
2091
+ }
2092
+ //#endregion
2093
+ //#region src/tx/message.ts
2094
+ /**
2095
+ * Assembling a transaction message.
2096
+ *
2097
+ * Every builder in this directory ends here: compute budget first, then the program instructions,
2098
+ * with a fee payer and a blockhash lifetime. The result is a message a wallet can sign and send —
2099
+ * nothing in this SDK signs or sends anything itself.
2100
+ */
2101
+ /**
2102
+ * Build the message. One RPC read, for the blockhash.
2103
+ *
2104
+ * The blockhash expires in about a minute, so build the message when the user is ready to sign
2105
+ * rather than when the page loads.
2106
+ */
2107
+ async function buildMessage(client, feePayer, instructions, options) {
2108
+ const { value: latestBlockhash } = await client.rpc.getLatestBlockhash({ commitment: "confirmed" }).send();
2109
+ const budget = computeBudgetInstructions(options.computeUnitLimit, options.computeUnitPrice);
2110
+ const message = pipe(createTransactionMessage({ version: 0 }), (m) => setTransactionMessageFeePayerSigner(feePayer, m), (m) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, m), (m) => appendTransactionMessageInstructions([...budget, ...instructions], m), (m) => compressTransactionMessageUsingAddressLookupTables(m, options.addressLookupTables ?? client.addressLookupTables));
2111
+ const size = getTransactionEncoder().encode(compileTransaction(message)).length;
2112
+ if (size > 1232) throw new Error(`Transaction is ${size} bytes; Solana allows 1232. Shorten metadata or supply additional address lookup tables.`);
2113
+ return message;
2114
+ }
2115
+ /** Append `remainingAccounts` to a generated instruction, which is how a venue's list is passed. */
2116
+ function withRemainingAccounts(instruction, remaining) {
2117
+ return {
2118
+ ...instruction,
2119
+ accounts: [...instruction.accounts ?? [], ...remaining]
2120
+ };
2121
+ }
2122
+ //#endregion
2123
+ //#region src/raydium/launch.ts
2124
+ /**
2125
+ * LaunchLab's `initialize_v2`, built by hand.
2126
+ *
2127
+ * Put it **before** `initialize_pool` in the transaction. `venue/launch.rs` reads the Instructions
2128
+ * sysvar and looks for this instruction by discriminator, then checks all 18 of its accounts and
2129
+ * every one of its arguments. The order matters for a second reason too: the mint account has to
2130
+ * exist and deserialize before Anchor validates the Gabox accounts.
2131
+ *
2132
+ * # The launch shape is pinned
2133
+ *
2134
+ * A creator picks the name, the symbol and the metadata URI. Nothing else. Every other argument is
2135
+ * fixed, and the program refuses any other value:
2136
+ *
2137
+ * | Argument | Value |
2138
+ * | --- | --- |
2139
+ * | `decimals` | 6 |
2140
+ * | curve | `Constant` |
2141
+ * | `supply` | 1,000,000,000 coins |
2142
+ * | `total_base_sell` | 793,100,000 coins |
2143
+ * | `total_quote_fund_raising` | 85 SOL on mainnet, 3 SOL on devnet |
2144
+ * | `migrate_type` | 1, which means graduate into a CPMM pool |
2145
+ * | `VestingParams` | all three fields 0 |
2146
+ * | `AmmCreatorFeeOn` | `QuoteToken` |
2147
+ *
2148
+ * The instruction data must end exactly after the last argument. Trailing bytes are refused.
2149
+ *
2150
+ * # The argument layout
2151
+ *
2152
+ * Borsh, in IDL order: `MintParams { decimals, name, symbol, uri }`, then the `CurveParams` enum
2153
+ * tag and its `ConstantCurve` fields, then `VestingParams`, then the `AmmCreatorFeeOn` enum tag.
2154
+ * An Anchor enum tag is one byte.
2155
+ */
2156
+ const borshString = () => addEncoderSizePrefix(getUtf8Encoder(), getU32Encoder());
2157
+ const ARGS_ENCODER = getStructEncoder([
2158
+ ["decimals", getU8Encoder()],
2159
+ ["name", borshString()],
2160
+ ["symbol", borshString()],
2161
+ ["uri", borshString()],
2162
+ ["curveTag", getU8Encoder()],
2163
+ ["supply", getU64Encoder()],
2164
+ ["totalBaseSell", getU64Encoder()],
2165
+ ["totalQuoteFundRaising", getU64Encoder()],
2166
+ ["migrateType", getU8Encoder()],
2167
+ ["totalLockedAmount", getU64Encoder()],
2168
+ ["cliffPeriod", getU64Encoder()],
2169
+ ["unlockPeriod", getU64Encoder()],
2170
+ ["ammFeeOn", getU8Encoder()]
2171
+ ]);
2172
+ /** Metaplex refuses a longer string, so refuse it here rather than on chain. */
2173
+ function bounded(value, limit, what) {
2174
+ const bytes = new TextEncoder().encode(value).length;
2175
+ if (bytes === 0) throw new Error(`${what} must not be empty`);
2176
+ if (bytes > limit) throw new Error(`${what} is ${bytes} UTF-8 bytes; Metaplex allows at most ${limit}`);
2177
+ return value;
2178
+ }
2179
+ /**
2180
+ * Build `initialize_v2` for one cluster's LaunchLab. `ids` is `raydiumIds(client.cluster)`.
2181
+ *
2182
+ * Two slots sign: the mint keypair, which LaunchLab takes as a signer rather than deriving, and the
2183
+ * creator, who pays for everything.
2184
+ */
2185
+ async function getLaunchInstruction(input, ids) {
2186
+ const { mint, creator } = input;
2187
+ const name = bounded(input.name, METADATA_LIMITS.name, "name");
2188
+ const symbol = bounded(input.symbol, METADATA_LIMITS.symbol, "symbol");
2189
+ const uri = bounded(input.uri, METADATA_LIMITS.uri, "uri");
2190
+ const quoteMint = WSOL_MINT;
2191
+ const poolState = await launchlabPoolAddress(ids.launchlab, mint.address, quoteMint);
2192
+ const metas = order(LAUNCHLAB_INITIALIZE, {
2193
+ payer: creator.address,
2194
+ creator: creator.address,
2195
+ global_config: ids.solGlobalConfig,
2196
+ platform_config: ids.gaboxPlatform,
2197
+ authority: ids.launchlabAuthority,
2198
+ pool_state: poolState,
2199
+ base_mint: mint.address,
2200
+ quote_mint: quoteMint,
2201
+ base_vault: await launchlabVaultAddress(ids.launchlab, poolState, mint.address),
2202
+ quote_vault: await launchlabVaultAddress(ids.launchlab, poolState, quoteMint),
2203
+ metadata_account: await metadataAddress(mint.address),
2204
+ base_token_program: TOKEN_PROGRAM_ADDRESS,
2205
+ quote_token_program: TOKEN_PROGRAM_ADDRESS,
2206
+ metadata_program: METAPLEX_PROGRAM_ADDRESS,
2207
+ system_program: SYSTEM_PROGRAM_ADDRESS,
2208
+ rent_program: RENT_SYSVAR_ADDRESS,
2209
+ event_authority: ids.launchlabEventAuthority,
2210
+ program: ids.launchlab
2211
+ });
2212
+ const signerFor = /* @__PURE__ */ new Map([[mint.address, mint], [creator.address, creator]]);
2213
+ const accounts = metas.map((meta) => {
2214
+ const signs = meta.role === 2 || meta.role === 3;
2215
+ const signer = signerFor.get(meta.address);
2216
+ return signs && signer ? {
2217
+ ...meta,
2218
+ signer
2219
+ } : meta;
2220
+ });
2221
+ const data = new Uint8Array([...LAUNCHLAB_INITIALIZE.discriminator, ...ARGS_ENCODER.encode({
2222
+ decimals: 6,
2223
+ name,
2224
+ symbol,
2225
+ uri,
2226
+ curveTag: 0,
2227
+ supply: LAUNCH_SUPPLY,
2228
+ totalBaseSell: LAUNCH_TOTAL_BASE_SELL,
2229
+ totalQuoteFundRaising: ids.launchQuoteRaise,
2230
+ migrateType: 1,
2231
+ totalLockedAmount: 0n,
2232
+ cliffPeriod: 0n,
2233
+ unlockPeriod: 0n,
2234
+ ammFeeOn: 0
2235
+ })]);
2236
+ return {
2237
+ programAddress: ids.launchlab,
2238
+ accounts,
2239
+ data
2240
+ };
2241
+ }
2242
+ //#endregion
2243
+ //#region src/raydium/claim.ts
2244
+ /**
2245
+ * Collecting the creator's share of trading.
2246
+ *
2247
+ * Gabox charges no fee at all. The creator's income is the share Raydium pays out of its own
2248
+ * revenue, and it sits in two different places depending on where the coin trades:
2249
+ *
2250
+ * - **On the curve.** LaunchLab pays 0.5% of every trade into `[creator, WSOL]` under LaunchLab.
2251
+ * One vault per wallet, not one per coin, so a single `claim_creator_fee` sweeps every coin
2252
+ * that creator launched.
2253
+ * - **After graduation.** The CPMM pool keeps the creator's fee inside the pool account, and
2254
+ * `collect_creator_fee` pays it out. That is per pool, so it takes one call per coin.
2255
+ *
2256
+ * Both instructions pay into the creator's WSOL associated token account. Every builder here closes
2257
+ * that account afterwards, so the creator ends up with plain SOL in their wallet.
2258
+ *
2259
+ * **Closing unwraps everything.** If the creator already held WSOL in that account before the
2260
+ * claim, closing turns that into SOL too. Nothing is lost, but the balance moves.
2261
+ */
2262
+ const base64 = getBase64Encoder();
2263
+ /**
2264
+ * Create the creator's WSOL account, if it is missing, and close it again at the end.
2265
+ *
2266
+ * Raydium's own instructions create the account when they need to, but an idempotent create here
2267
+ * costs nothing and makes the flow the same whichever instruction runs. The close is what turns the
2268
+ * WSOL into SOL.
2269
+ */
2270
+ async function wrapAround(creator, middle) {
2271
+ const account = await ata(creator.address, WSOL_MINT);
2272
+ return [
2273
+ getCreateAssociatedTokenIdempotentInstruction({
2274
+ payer: creator,
2275
+ ata: account,
2276
+ owner: creator.address,
2277
+ mint: WSOL_MINT,
2278
+ tokenProgram: TOKEN_PROGRAM_ADDRESS
2279
+ }),
2280
+ ...middle,
2281
+ getCloseAccountInstruction({
2282
+ account,
2283
+ destination: creator.address,
2284
+ owner: creator
2285
+ })
2286
+ ];
2287
+ }
2288
+ /** Attach a signer to the one slot the ABI marks as signing. Roles never change here. */
2289
+ function withSigner(accounts, signer) {
2290
+ return accounts.map((meta) => (meta.role === AccountRole.READONLY_SIGNER || meta.role === AccountRole.WRITABLE_SIGNER) && meta.address === signer.address ? {
2291
+ ...meta,
2292
+ signer
2293
+ } : meta);
2294
+ }
2295
+ /**
2296
+ * The instructions of a curve fee claim: create the WSOL account, claim, close it.
2297
+ *
2298
+ * This sweeps **every** coin this wallet launched, because LaunchLab keeps one vault per wallet per
2299
+ * quote asset. There is no per-coin version.
2300
+ */
2301
+ async function getClaimCreatorFeeInstructions(creator, ids) {
2302
+ const quoteMint = WSOL_MINT;
2303
+ return await wrapAround(creator, [{
2304
+ programAddress: ids.launchlab,
2305
+ accounts: withSigner(order(LAUNCHLAB_CLAIM_CREATOR_FEE, {
2306
+ creator: creator.address,
2307
+ fee_vault_authority: await creatorFeeVaultAuthority(ids.launchlab),
2308
+ creator_fee_vault: await creatorFeeVaultAddress(ids.launchlab, creator.address, quoteMint),
2309
+ recipient_token_account: await ata(creator.address, quoteMint),
2310
+ quote_mint: quoteMint,
2311
+ token_program: TOKEN_PROGRAM_ADDRESS,
2312
+ system_program: SYSTEM_PROGRAM_ADDRESS,
2313
+ associated_token_program: ASSOCIATED_TOKEN_PROGRAM_ADDRESS
2314
+ }), creator),
2315
+ data: new Uint8Array(LAUNCHLAB_CLAIM_CREATOR_FEE.discriminator)
2316
+ }]);
2317
+ }
2318
+ /**
2319
+ * Claim the curve creator fee and receive it as SOL.
2320
+ *
2321
+ * One transaction, three instructions. It sweeps every coin this wallet launched on LaunchLab.
2322
+ */
2323
+ async function claimCreatorFee(client, input) {
2324
+ const ids = raydiumIds(client.cluster);
2325
+ const instructions = await getClaimCreatorFeeInstructions(input.creator, ids);
2326
+ return await buildMessage(client, input.creator, instructions, {
2327
+ addressLookupTables: input.addressLookupTables,
2328
+ computeUnitLimit: input.computeUnitLimit ?? 55e3,
2329
+ ...input.computeUnitPrice === void 0 ? {} : { computeUnitPrice: input.computeUnitPrice }
2330
+ });
2331
+ }
2332
+ /**
2333
+ * The instructions of a graduated coin's fee collection: create the WSOL account, collect, close.
2334
+ *
2335
+ * This is per coin. `collect_creator_fee` pays out both sides of the pair, so anything owed in the
2336
+ * coin itself lands in the creator's coin account and stays there.
2337
+ */
2338
+ async function getCollectCreatorFeeInstructions(client, input, ids = raydiumIds(client.cluster)) {
2339
+ const { mint, creator } = input;
2340
+ const quoteMint = WSOL_MINT;
2341
+ const settings = await fetchCurveSettings(client, ids);
2342
+ const { address: poolState, pool } = await findCpmmPool(client, {
2343
+ mint,
2344
+ quoteMint,
2345
+ creator: creator.address,
2346
+ cpswapConfig: settings.cpswapConfig
2347
+ });
2348
+ return await wrapAround(creator, [{
2349
+ programAddress: ids.cpmm,
2350
+ accounts: withSigner(order(CPMM_COLLECT_CREATOR_FEE, {
2351
+ creator: creator.address,
2352
+ authority: ids.cpmmAuthority,
2353
+ pool_state: poolState,
2354
+ amm_config: pool.ammConfig,
2355
+ token_0_vault: pool.token0Vault,
2356
+ token_1_vault: pool.token1Vault,
2357
+ vault_0_mint: pool.token0Mint,
2358
+ vault_1_mint: pool.token1Mint,
2359
+ creator_token_0: await ata(creator.address, pool.token0Mint, pool.token0Program),
2360
+ creator_token_1: await ata(creator.address, pool.token1Mint, pool.token1Program),
2361
+ token_0_program: pool.token0Program,
2362
+ token_1_program: pool.token1Program,
2363
+ associated_token_program: ASSOCIATED_TOKEN_PROGRAM_ADDRESS,
2364
+ system_program: SYSTEM_PROGRAM_ADDRESS,
2365
+ creator_fee_share: await cpmmCreatorFeeShare(ids.cpmm, creator.address, pool.ammConfig)
2366
+ }), creator),
2367
+ data: new Uint8Array(CPMM_COLLECT_CREATOR_FEE.discriminator)
2368
+ }]);
2369
+ }
2370
+ /** Collect one graduated coin's CPMM creator fee and receive the WSOL side as SOL. */
2371
+ async function collectCreatorFee(client, input) {
2372
+ const instructions = await getCollectCreatorFeeInstructions(client, {
2373
+ mint: input.mint,
2374
+ creator: input.creator
2375
+ });
2376
+ return await buildMessage(client, input.creator, instructions, {
2377
+ addressLookupTables: input.addressLookupTables,
2378
+ computeUnitLimit: input.computeUnitLimit ?? 55e3,
2379
+ ...input.computeUnitPrice === void 0 ? {} : { computeUnitPrice: input.computeUnitPrice }
2380
+ });
2381
+ }
2382
+ /**
2383
+ * Read both places a creator's fees can sit.
2384
+ *
2385
+ * `mint` is optional. Without it only the curve vault is read, which is the one number that covers
2386
+ * every coin at once. With it the coin's CPMM pool is read too, and a coin that has not graduated
2387
+ * reports zeros rather than failing.
2388
+ */
2389
+ async function fetchCreatorFees(client, input) {
2390
+ const ids = raydiumIds(client.cluster);
2391
+ const quoteMint = WSOL_MINT;
2392
+ const vault = await creatorFeeVaultAddress(ids.launchlab, input.creator, quoteMint);
2393
+ const { value } = await client.rpc.getAccountInfo(vault, {
2394
+ encoding: "base64",
2395
+ commitment: "confirmed"
2396
+ }).send();
2397
+ const curveLamports = value ? tokenAccountAmount(new Uint8Array(base64.encode(value.data[0]))) : 0n;
2398
+ if (!input.mint) return {
2399
+ curveLamports,
2400
+ cpmmLamports: 0n,
2401
+ cpmmTokens: 0n
2402
+ };
2403
+ const settings = await fetchCurveSettings(client, ids);
2404
+ try {
2405
+ const { pool } = await findCpmmPool(client, {
2406
+ mint: input.mint,
2407
+ quoteMint,
2408
+ creator: input.creator,
2409
+ cpswapConfig: settings.cpswapConfig
2410
+ });
2411
+ const [token0] = sortedMints(input.mint, quoteMint);
2412
+ const baseIsToken0 = token0 === input.mint;
2413
+ return {
2414
+ curveLamports,
2415
+ cpmmLamports: baseIsToken0 ? pool.creatorFeesToken1 : pool.creatorFeesToken0,
2416
+ cpmmTokens: baseIsToken0 ? pool.creatorFeesToken0 : pool.creatorFeesToken1
2417
+ };
2418
+ } catch {
2419
+ return {
2420
+ curveLamports,
2421
+ cpmmLamports: 0n,
2422
+ cpmmTokens: 0n
2423
+ };
2424
+ }
2425
+ }
2426
+ //#endregion
2427
+ //#region src/raydium/trade.ts
2428
+ /**
2429
+ * A venue trade a wallet sends on its own, outside any Gabox instruction.
2430
+ *
2431
+ * Pack buys and token sales go through `buy_pack` and `sell_tokens`: they take the venue's account
2432
+ * list as `remainingAccounts` and the Gabox program does the call. This file is for the one trade
2433
+ * Gabox never makes, a plain `buy_exact_in` on the curve. Anyone may trade a Gabox coin directly,
2434
+ * and the devnet end-to-end test uses this to buy the rest of the curve and force graduation.
2435
+ *
2436
+ * The account list and the discriminator both come from `abi.ts`, which codegen took from
2437
+ * Raydium's IDL. Nothing here retypes either.
2438
+ */
2439
+ const u64 = getU64Encoder();
2440
+ /**
2441
+ * `buy_exact_in` on the curve: spend exactly `quoteIn` WSOL and take whatever coins it buys.
2442
+ *
2443
+ * LaunchLab caps the trade at what the curve has left to sell, so a spend larger than the rest of
2444
+ * the raise still succeeds and graduates the coin. Wrap the SOL into the user's WSOL ATA first and
2445
+ * close it afterwards, the same way the Gabox builders do.
2446
+ */
2447
+ async function getCurveBuyExactInInstruction(client, input, ids = raydiumIds(client.cluster)) {
2448
+ if (input.quoteIn <= 0n) throw new Error("quoteIn must be positive");
2449
+ if (input.minTokensOut < 0n) throw new Error("minTokensOut must not be negative");
2450
+ const quoteMint = WSOL_MINT;
2451
+ const poolState = await launchlabPoolAddress(ids.launchlab, input.mint, quoteMint);
2452
+ const accounts = launchlabBuyExactInAccounts({
2453
+ launchlab: ids.launchlab,
2454
+ launchlabAuthority: ids.launchlabAuthority,
2455
+ launchlabEventAuthority: ids.launchlabEventAuthority,
2456
+ globalConfig: ids.solGlobalConfig,
2457
+ platformConfig: ids.gaboxPlatform,
2458
+ poolState,
2459
+ mint: input.mint,
2460
+ quoteMint,
2461
+ baseVault: await launchlabVaultAddress(ids.launchlab, poolState, input.mint),
2462
+ quoteVault: await launchlabVaultAddress(ids.launchlab, poolState, quoteMint),
2463
+ user: input.user.address,
2464
+ userBaseToken: await ata(input.user.address, input.mint),
2465
+ userQuoteToken: await ata(input.user.address, quoteMint),
2466
+ platformFeeVault: await platformFeeVaultAddress(ids.launchlab, ids.gaboxPlatform, quoteMint),
2467
+ creatorFeeVault: await creatorFeeVaultAddress(ids.launchlab, input.creator, quoteMint)
2468
+ });
2469
+ return {
2470
+ programAddress: ids.launchlab,
2471
+ accounts: attachSigner(accounts, input.user),
2472
+ data: new Uint8Array([
2473
+ ...LAUNCHLAB_BUY_EXACT_IN.discriminator,
2474
+ ...u64.encode(input.quoteIn),
2475
+ ...u64.encode(input.minTokensOut),
2476
+ ...u64.encode(SHARE_FEE_RATE)
2477
+ ])
2478
+ };
2479
+ }
2480
+ /** Give the signer to the slot the ABI already marks as signing. Roles never change here. */
2481
+ function attachSigner(accounts, signer) {
2482
+ let matched = false;
2483
+ const withSigner = accounts.map((meta) => {
2484
+ if (!(meta.role === 2 || meta.role === 3) || meta.address !== signer.address) return meta;
2485
+ matched = true;
2486
+ return {
2487
+ ...meta,
2488
+ signer
2489
+ };
2490
+ });
2491
+ if (!matched) throw new Error(`${signer.address} is not the signing account of this trade. Build the account list with the same wallet you are going to sign with.`);
2492
+ return withSigner;
2493
+ }
2494
+ //#endregion
2495
+ //#region src/raydium/index.ts
2496
+ var raydium_exports = /* @__PURE__ */ __exportAll({
2497
+ ASSOCIATED_TOKEN_PROGRAM_ADDRESS: () => ASSOCIATED_TOKEN_PROGRAM_ADDRESS,
2498
+ CONSTANT_CURVE_TAG: () => 0,
2499
+ CPMM_AMM_CONFIG_DISCRIMINATOR: () => CPMM_AMM_CONFIG_DISCRIMINATOR,
2500
+ CPMM_AMM_CONFIG_HEAD_SIZE: () => 116,
2501
+ CPMM_COLLECT_CREATOR_FEE: () => CPMM_COLLECT_CREATOR_FEE,
2502
+ CPMM_POOL_OFFSETS: () => CPMM_POOL_OFFSETS,
2503
+ CPMM_POOL_STATE_DISCRIMINATOR: () => CPMM_POOL_STATE_DISCRIMINATOR,
2504
+ CPMM_POOL_STATE_HEAD_SIZE: () => 413,
2505
+ CPMM_POOL_STATE_SIZE: () => 637,
2506
+ CPMM_SEEDS: () => CPMM_SEEDS,
2507
+ CPMM_SWAP_BASE_INPUT: () => CPMM_SWAP_BASE_INPUT,
2508
+ CPMM_SWAP_BASE_OUTPUT: () => CPMM_SWAP_BASE_OUTPUT,
2509
+ CREATOR_FEE_ON_QUOTE: () => 0,
2510
+ LAUNCHLAB_BUY_EXACT_IN: () => LAUNCHLAB_BUY_EXACT_IN,
2511
+ LAUNCHLAB_BUY_EXACT_OUT: () => LAUNCHLAB_BUY_EXACT_OUT,
2512
+ LAUNCHLAB_CLAIM_CREATOR_FEE: () => LAUNCHLAB_CLAIM_CREATOR_FEE,
2513
+ LAUNCHLAB_GLOBAL_CONFIG_DISCRIMINATOR: () => LAUNCHLAB_GLOBAL_CONFIG_DISCRIMINATOR,
2514
+ LAUNCHLAB_GLOBAL_CONFIG_HEAD_SIZE: () => 115,
2515
+ LAUNCHLAB_INITIALIZE: () => LAUNCHLAB_INITIALIZE,
2516
+ LAUNCHLAB_PLATFORM_CONFIG_DISCRIMINATOR: () => LAUNCHLAB_PLATFORM_CONFIG_DISCRIMINATOR,
2517
+ LAUNCHLAB_PLATFORM_CONFIG_HEAD_SIZE: () => 940,
2518
+ LAUNCHLAB_POOL_STATE_DISCRIMINATOR: () => LAUNCHLAB_POOL_STATE_DISCRIMINATOR,
2519
+ LAUNCHLAB_POOL_STATE_HEAD_SIZE: () => 367,
2520
+ LAUNCHLAB_SEEDS: () => LAUNCHLAB_SEEDS,
2521
+ LAUNCHLAB_SELL_EXACT_IN: () => LAUNCHLAB_SELL_EXACT_IN,
2522
+ LAUNCHLAB_STATUS_FUND: () => 0,
2523
+ LAUNCHLAB_STATUS_MIGRATE: () => 1,
2524
+ LAUNCHLAB_STATUS_TRADE: () => 2,
2525
+ LAUNCH_DECIMALS: () => 6,
2526
+ LAUNCH_SUPPLY: () => LAUNCH_SUPPLY,
2527
+ LAUNCH_TOTAL_BASE_SELL: () => LAUNCH_TOTAL_BASE_SELL,
2528
+ METADATA_LIMITS: () => METADATA_LIMITS,
2529
+ METADATA_SEED: () => METADATA_SEED,
2530
+ METAPLEX_PROGRAM_ADDRESS: () => METAPLEX_PROGRAM_ADDRESS,
2531
+ MIGRATE_TO_CPMM: () => 1,
2532
+ PLATFORM_ADMIN: () => PLATFORM_ADMIN,
2533
+ RATE_DENOMINATOR: () => RATE_DENOMINATOR,
2534
+ RAYDIUM_DEVNET_IDS: () => RAYDIUM_DEVNET_IDS,
2535
+ RAYDIUM_IDS: () => RAYDIUM_IDS,
2536
+ RAYDIUM_MAINNET_IDS: () => RAYDIUM_MAINNET_IDS,
2537
+ RENT_SYSVAR_ADDRESS: () => RENT_SYSVAR_ADDRESS,
2538
+ SHARE_FEE_RATE: () => SHARE_FEE_RATE,
2539
+ SYSTEM_PROGRAM_ADDRESS: () => SYSTEM_PROGRAM_ADDRESS,
2540
+ TOKEN_PROGRAM_ADDRESS: () => TOKEN_PROGRAM_ADDRESS,
2541
+ WSOL_MINT: () => WSOL_MINT,
2542
+ ata: () => ata,
2543
+ ceilDiv: () => ceilDiv,
2544
+ ceilDivRate: () => ceilDivRate,
2545
+ claimCreatorFee: () => claimCreatorFee,
2546
+ collectCreatorFee: () => collectCreatorFee,
2547
+ compareAddresses: () => compareAddresses,
2548
+ cpmmAuthority: () => cpmmAuthority,
2549
+ cpmmBuyAccounts: () => cpmmBuyAccounts,
2550
+ cpmmCreatorFeeShare: () => cpmmCreatorFeeShare,
2551
+ cpmmPoolAddress: () => cpmmPoolAddress,
2552
+ cpmmPoolMatches: () => cpmmPoolMatches,
2553
+ cpmmSellAccounts: () => cpmmSellAccounts,
2554
+ cpmmSwapBaseInput: () => cpmmSwapBaseInput,
2555
+ cpmmSwapBaseOutput: () => cpmmSwapBaseOutput,
2556
+ creatorFeeOnInput: () => creatorFeeOnInput,
2557
+ creatorFeeVaultAddress: () => creatorFeeVaultAddress,
2558
+ creatorFeeVaultAuthority: () => creatorFeeVaultAuthority,
2559
+ curveBuyExactIn: () => curveBuyExactIn,
2560
+ curveBuyExactOut: () => curveBuyExactOut,
2561
+ curveQuote: () => curveQuote,
2562
+ curveSellExactIn: () => curveSellExactIn,
2563
+ decodeCpmmAmmConfig: () => decodeCpmmAmmConfig,
2564
+ decodeCpmmPool: () => decodeCpmmPool,
2565
+ decodeLaunchlabGlobalConfig: () => decodeLaunchlabGlobalConfig,
2566
+ decodeLaunchlabPlatformConfig: () => decodeLaunchlabPlatformConfig,
2567
+ decodeLaunchlabPool: () => decodeLaunchlabPool,
2568
+ fetchCreatorFees: () => fetchCreatorFees,
2569
+ fetchCurveSettings: () => fetchCurveSettings,
2570
+ findCpmmPool: () => findCpmmPool,
2571
+ getClaimCreatorFeeInstructions: () => getClaimCreatorFeeInstructions,
2572
+ getCollectCreatorFeeInstructions: () => getCollectCreatorFeeInstructions,
2573
+ getCurveBuyExactInInstruction: () => getCurveBuyExactInInstruction,
2574
+ getLaunchInstruction: () => getLaunchInstruction,
2575
+ initialCurve: () => initialCurve,
2576
+ launchlabAuthority: () => launchlabAuthority,
2577
+ launchlabBuyAccounts: () => launchlabBuyAccounts,
2578
+ launchlabBuyExactInAccounts: () => launchlabBuyExactInAccounts,
2579
+ launchlabEventAuthority: () => launchlabEventAuthority,
2580
+ launchlabGlobalConfig: () => launchlabGlobalConfig,
2581
+ launchlabPlatformConfig: () => launchlabPlatformConfig,
2582
+ launchlabPoolAddress: () => launchlabPoolAddress,
2583
+ launchlabSellAccounts: () => launchlabSellAccounts,
2584
+ launchlabVaultAddress: () => launchlabVaultAddress,
2585
+ metadataAddress: () => metadataAddress,
2586
+ newCurveBuyCost: () => newCurveBuyCost,
2587
+ newCurveReserves: () => newCurveReserves,
2588
+ order: () => order,
2589
+ platformFeeVaultAddress: () => platformFeeVaultAddress,
2590
+ preFeeAmount: () => preFeeAmount,
2591
+ raydiumIds: () => raydiumIds,
2592
+ remainingBase: () => remainingBase,
2593
+ resolveVenue: () => resolveVenue,
2594
+ sellQuote: () => sellQuote,
2595
+ sortedMints: () => sortedMints,
2596
+ tokenAccountAmount: () => tokenAccountAmount,
2597
+ tokenAccountOwnerAndMint: () => tokenAccountOwnerAndMint,
2598
+ totalCurveFeeRate: () => totalCurveFeeRate,
2599
+ wsolAccountFor: () => wsolAccountFor
2600
+ });
2601
+ //#endregion
2602
+ export { LAUNCHLAB_PLATFORM_CONFIG_HEAD_SIZE as $, LAUNCH_SUPPLY as $t, remainingBase as A, METADATA_LIMITS as At, COMPUTE_BUDGET_PROGRAM_ADDRESS as B, CPMM_AMM_CONFIG_DISCRIMINATOR as Bt, cpmmSwapBaseInput as C, CPMM_SEEDS as Ct, curveSellExactIn as D, LAUNCHLAB_STATUS_MIGRATE as Dt, curveBuyExactOut as E, LAUNCHLAB_STATUS_FUND as Et, launchlabBuyExactInAccounts as F, SHARE_FEE_RATE as Ft, computeBudgetInstructions as G, LAUNCHLAB_BUY_EXACT_IN as Gt, DEFAULT_COMPUTE_UNIT_LIMIT as H, CPMM_POOL_STATE_DISCRIMINATOR as Ht, launchlabSellAccounts as I, compareAddresses as It, CPMM_AMM_CONFIG_HEAD_SIZE as J, LAUNCHLAB_GLOBAL_CONFIG_DISCRIMINATOR as Jt, getSetComputeUnitLimitInstruction as K, LAUNCHLAB_BUY_EXACT_OUT as Kt, order as L, raydiumIds as Lt, cpmmBuyAccounts as M, MIGRATE_TO_CPMM as Mt, cpmmSellAccounts as N, RATE_DENOMINATOR as Nt, initialCurve as O, LAUNCHLAB_STATUS_TRADE as Ot, launchlabBuyAccounts as P, RAYDIUM_IDS as Pt, LAUNCHLAB_GLOBAL_CONFIG_HEAD_SIZE as Q, LAUNCHLAB_SELL_EXACT_IN as Qt, BUY_PACK_COMPUTE_UNITS as R, sortedMints as Rt, ceilDivRate as S, CONSTANT_CURVE_TAG as St, curveBuyExactIn as T, LAUNCHLAB_SEEDS as Tt, MAX_COMPUTE_UNIT_LIMIT as U, CPMM_SWAP_BASE_INPUT as Ut, CREATE_MACHINE_COMPUTE_UNITS as V, CPMM_COLLECT_CREATOR_FEE as Vt, REDEEM_COMPUTE_UNITS as W, CPMM_SWAP_BASE_OUTPUT as Wt, CPMM_POOL_STATE_HEAD_SIZE as X, LAUNCHLAB_PLATFORM_CONFIG_DISCRIMINATOR as Xt, CPMM_POOL_OFFSETS as Y, LAUNCHLAB_INITIALIZE as Yt, CPMM_POOL_STATE_SIZE as Z, LAUNCHLAB_POOL_STATE_DISCRIMINATOR as Zt, newCurveReserves as _, launchlabPlatformConfig as _t, fetchCreatorFees as a, RENT_SYSVAR_ADDRESS as an, decodeLaunchlabPool as at, wsolAccountFor as b, metadataAddress as bt, getLaunchInstruction as c, WSOL_MINT as cn, ata as ct, cpmmPoolMatches as d, cpmmPoolAddress as dt, LAUNCH_TOTAL_BASE_SELL as en, LAUNCHLAB_POOL_STATE_HEAD_SIZE as et, creatorFeeOnInput as f, creatorFeeVaultAddress as ft, newCurveBuyCost as g, launchlabGlobalConfig as gt, findCpmmPool as h, launchlabEventAuthority as ht, collectCreatorFee as i, RAYDIUM_MAINNET_IDS as in, decodeLaunchlabPlatformConfig as it, totalCurveFeeRate as j, METADATA_SEED as jt, preFeeAmount as k, LAUNCH_DECIMALS as kt, buildMessage as l, cpmmAuthority as lt, fetchCurveSettings as m, launchlabAuthority as mt, getCurveBuyExactInInstruction as n, PLATFORM_ADMIN as nn, decodeCpmmPool as nt, getClaimCreatorFeeInstructions as o, SYSTEM_PROGRAM_ADDRESS as on, tokenAccountAmount as ot, curveQuote as p, creatorFeeVaultAuthority as pt, getSetComputeUnitPriceInstruction as q, LAUNCHLAB_CLAIM_CREATOR_FEE as qt, claimCreatorFee as r, RAYDIUM_DEVNET_IDS as rn, decodeLaunchlabGlobalConfig as rt, getCollectCreatorFeeInstructions as s, TOKEN_PROGRAM_ADDRESS as sn, tokenAccountOwnerAndMint as st, raydium_exports as t, METAPLEX_PROGRAM_ADDRESS as tn, decodeCpmmAmmConfig as tt, withRemainingAccounts as u, cpmmCreatorFeeShare as ut, resolveVenue as v, launchlabPoolAddress as vt, cpmmSwapBaseOutput as w, CREATOR_FEE_ON_QUOTE as wt, ceilDiv as x, platformFeeVaultAddress as xt, sellQuote as y, launchlabVaultAddress as yt, CLAIM_COMPUTE_UNITS as z, ASSOCIATED_TOKEN_PROGRAM_ADDRESS as zt };
2603
+
2604
+ //# sourceMappingURL=raydium-B-l9V3O-.js.map