proof-of-take-sdk 5.0.11 → 5.0.12

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.
@@ -1,10 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.joinSeason = joinSeason;
4
- exports.joinSeasonClassic = joinSeasonClassic;
3
+ exports.createMoonpool = createMoonpool;
4
+ exports.joinMoonpoolSeason = joinMoonpoolSeason;
5
+ exports.joinSunpool = joinSunpool;
5
6
  exports.joinSeasonLaunchpad = joinSeasonLaunchpad;
6
- exports.joinSeasonAndInitialize = joinSeasonAndInitialize;
7
- exports.joinSeasonLaunchpadAndInitialize = joinSeasonLaunchpadAndInitialize;
7
+ exports.joinSeasonLaunchpadAndInitialize = joinSeasonLaunchpad;
8
+ exports.joinSeasonClassic = joinSeasonClassic;
9
+ exports.joinSeasonAndInitialize = joinSeasonClassic;
8
10
  const anchor_1 = require("@coral-xyz/anchor");
9
11
  const web3_js_1 = require("@solana/web3.js");
10
12
  const spl_token_1 = require("@solana/spl-token");
@@ -13,268 +15,319 @@ const pdas_1 = require("../utils/pdas");
13
15
  const constants_1 = require("../utils/constants");
14
16
  const programHelpers_1 = require("../utils/programHelpers");
15
17
  const signerHelpers_1 = require("../utils/signerHelpers");
16
- const optimistic_1 = require("../optimistic");
17
- const remainingAccounts_1 = require("../utils/remainingAccounts");
18
18
  /**
19
- * Join a season
20
- *
21
- * Signers: user + root admin (root admin pays for signup-rewards vault ATA creation when a referrer is present)
22
- * User pays for season (if needed) and membership accounts
23
- * Transfers active deposit into the season vault; the late-join escrow portion is converted into non-withdrawable join credit
19
+ * Create a new Moonpool and perform the first launchpad join.
24
20
  *
25
- * IMPORTANT: If providing a referrer, you MUST also provide referrerTier.
26
- * The referrerTier must match the tier the referrer actually joined the season with.
27
- * The referrer must have already joined the season before being used as a referrer.
21
+ * This instruction:
22
+ * - Creates a new launchpad_token_mint (SPL Token-2022)
23
+ * - Initializes the Moonpool
24
+ * - Initializes the Season (scoped to launchpad_token_mint)
25
+ * - Creates the first SeasonMembership
28
26
  *
29
- * @param options - Join season options
30
- * @returns Instructions, signers, PDAs, and optimistically created/updated accounts
27
+ * @param options - CreateMoonpool options
28
+ * @returns Instructions, signers, PDAs, and metadata with the generated keypair
31
29
  */
32
- async function joinSeason(options) {
30
+ async function createMoonpool(options) {
33
31
  const program = (0, programHelpers_1.getProgram)(options.connection);
34
- const tokenMint = options.tokenMint ?? constants_1.MIZD_TOKEN_MINT;
35
- const launchpad = options.launchpad ?? false;
36
- // Determine launchpadTokenMint FIRST (before deriving PDAs)
37
- // For BOTH launchpad and classic mode, Season/SeasonMembership PDAs are scoped to launchpadTokenMint
38
- let launchpadTokenMintKeypair;
39
- let launchpadTokenMintPubkey;
40
- if (launchpad) {
41
- // If forceNewLaunchpadMint is set, skip on-chain checks and always generate a new keypair
42
- if (options.forceNewLaunchpadMint) {
43
- launchpadTokenMintKeypair = web3_js_1.Keypair.generate();
44
- launchpadTokenMintPubkey = launchpadTokenMintKeypair.publicKey;
45
- console.log("[joinSeason] forceNewLaunchpadMint=true - generated new launchpad mint keypair:", launchpadTokenMintPubkey.toString());
46
- }
47
- else {
48
- // For non-force mode, we need an existing launchpadTokenMint to find the moonpool
49
- // Check currentAccounts first (for LiteSVM or optimistic updates)
50
- let moonpoolData = options.currentAccounts?.moonpool ?? null;
51
- if (moonpoolData && !moonpoolData.launchpadTokenMint.equals(web3_js_1.PublicKey.default)) {
52
- // Use the launchpadTokenMint from the provided moonpool data
53
- launchpadTokenMintPubkey = moonpoolData.launchpadTokenMint;
54
- console.log("[joinSeason] Using launchpadTokenMint from currentAccounts:", launchpadTokenMintPubkey.toString());
55
- }
56
- else {
57
- // No moonpool data provided - this is a first join scenario
58
- // Generate a keypair for the mint (the mint will be created on-chain)
59
- launchpadTokenMintKeypair = web3_js_1.Keypair.generate();
60
- launchpadTokenMintPubkey = launchpadTokenMintKeypair.publicKey;
61
- console.log("[joinSeason] First join - generated launchpad mint keypair:", launchpadTokenMintPubkey.toString());
62
- }
63
- }
32
+ // Validate required fields
33
+ if (!options.starFlagPrompt || options.starFlagPrompt.length === 0) {
34
+ throw new Error("starFlagPrompt is required when creating a new Moonpool");
64
35
  }
65
- else {
66
- // Classic mode: use the launchpad token mint PDA derived from tokenMint
67
- // The on-chain program expects launchpad_token_mint.key() for Season/SeasonMembership PDAs
68
- const [launchpadMintPda] = (0, pdas_1.getLaunchpadTokenMintPda)(tokenMint);
69
- launchpadTokenMintPubkey = launchpadMintPda;
36
+ if (options.starFlagPrompt.length > 33) {
37
+ throw new Error("starFlagPrompt cannot exceed 33 characters");
38
+ }
39
+ if (!options.symbol || options.symbol.length === 0) {
40
+ throw new Error("symbol is required when creating a new Moonpool");
41
+ }
42
+ if (options.symbol.length > 4) {
43
+ throw new Error("symbol cannot exceed 4 characters");
70
44
  }
71
- // Derive PDAs with launchpadTokenMint for BOTH modes
72
- // Season/SeasonMembership PDAs are always scoped to launchpadTokenMint
45
+ // Generate a new keypair for the launchpad token mint
46
+ const launchpadTokenMintKeypair = web3_js_1.Keypair.generate();
47
+ const launchpadTokenMintPubkey = launchpadTokenMintKeypair.publicKey;
48
+ console.log("[createMoonpool] Generated new launchpad mint keypair:", launchpadTokenMintPubkey.toString());
49
+ // Derive PDAs with the new launchpadTokenMint
73
50
  const pdasBase = pdaManager_1.PDAManager.deriveJoinSeasonPdas({
74
51
  user: options.user,
75
52
  seasonNumber: options.seasonNumber,
76
53
  tier: options.tier,
77
- tokenMint,
54
+ tokenMint: constants_1.MIZD_TOKEN_MINT,
78
55
  launchpadTokenMint: launchpadTokenMintPubkey,
79
56
  });
80
- // Derive Moonpool and Treasury PDAs using the launchpadTokenMint
57
+ // Derive Moonpool and Treasury PDAs
81
58
  const [moonpoolPda] = (0, pdas_1.getMoonpoolPda)(launchpadTokenMintPubkey);
82
59
  const [moonpoolTreasuryPda] = (0, pdas_1.getMoonpoolTreasuryPda)(launchpadTokenMintPubkey);
83
- const rootAdminTokenAccount = launchpad
84
- ? null
85
- : (0, spl_token_1.getAssociatedTokenAddressSync)(constants_1.MIZD_TOKEN_MINT, constants_1.ADMIN_PUBLIC_KEY);
86
- const userMizdAta = launchpad
87
- ? null
88
- : (0, spl_token_1.getAssociatedTokenAddressSync)(constants_1.MIZD_TOKEN_MINT, options.user);
89
- // Join credit PDA + its vault ATA (owner is off-curve PDA, so allowOwnerOffCurve=true).
90
- const userJoinCreditVault = launchpad
91
- ? null
92
- : (0, spl_token_1.getAssociatedTokenAddressSync)(constants_1.MIZD_TOKEN_MINT, pdasBase.userJoinCredit, true);
93
60
  const pdas = {
94
- ...pdasBase,
61
+ seasonSettings: pdasBase.seasonSettings,
62
+ season: pdasBase.season,
63
+ seasonMembership: pdasBase.seasonMembership,
95
64
  moonpool: moonpoolPda,
96
65
  moonpoolTreasury: moonpoolTreasuryPda,
97
66
  launchpadTokenMint: launchpadTokenMintPubkey,
98
- userJoinCreditVault: userJoinCreditVault ?? web3_js_1.PublicKey.default,
99
67
  };
68
+ const referrer = options.referrer ?? web3_js_1.PublicKey.default;
100
69
  const accounts = {
101
70
  seasonSettings: pdas.seasonSettings,
102
71
  season: pdas.season,
103
72
  seasonMembership: pdas.seasonMembership,
104
- // SECURITY: Pool accounts are now MANDATORY (non-optional) to prevent bypassing
105
- // the mode check. The on-chain program validates pool state to ensure
106
- // subsequent seasons use the same mode (launchpad/classic) as the first season.
107
73
  moonpool: moonpoolPda,
108
74
  moonpoolTreasury: moonpoolTreasuryPda,
109
- launchpadTokenMint: pdas.launchpadTokenMint,
110
- sunpool: pdas.sunpool,
111
- seasonDepositVault: launchpad ? null : pdas.seasonDepositVault,
112
- userJoinCredit: launchpad ? null : pdas.userJoinCredit,
113
- userJoinCreditVault: launchpad ? null : userJoinCreditVault,
114
- mizdMint: constants_1.MIZD_TOKEN_MINT,
115
- tokenMint,
75
+ launchpadTokenMint: launchpadTokenMintPubkey,
116
76
  rootAdmin: constants_1.ADMIN_PUBLIC_KEY,
117
- rootAdminTokenAccount,
118
- // Always pass the canonical ATA; it may not exist yet (created on-chain with root admin as payer).
119
- userTokenAccount: userMizdAta,
120
77
  user: options.user,
121
- associatedTokenProgram: spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID,
122
- tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
123
78
  token2022Program: spl_token_1.TOKEN_2022_PROGRAM_ID,
124
79
  systemProgram: web3_js_1.SystemProgram.programId,
125
80
  };
126
- const referrer = options.referrer ?? web3_js_1.PublicKey.default;
127
- const hasReferrer = !referrer.equals(web3_js_1.PublicKey.default);
128
- // Validate: if referrer is provided, referrerTier must also be provided
129
- if (hasReferrer && options.referrerTier === undefined) {
130
- throw new Error("referrerTier is required when referrer is provided");
131
- }
132
- const remainingAccounts = hasReferrer
133
- ? (0, remainingAccounts_1.getJoinSeasonRemainingAccounts)({
134
- seasonNumber: options.seasonNumber,
135
- tier: options.tier,
136
- referrer,
137
- referrerTier: options.referrerTier,
138
- tokenMint,
139
- })
140
- : [];
141
- const methodBuilder = program.methods
142
- // Anchor expects BN for u64 args.
143
- // referrerTier defaults to 0 if no referrer (ignored on-chain)
144
- .joinSeason(options.seasonNumber, options.tier, referrer, options.referrerTier ?? 0, options.star ?? false, launchpad, options.maxSolInLamports ?? new anchor_1.BN(0), options.expectedSolInLamports ?? new anchor_1.BN(0), options.maxSlippageBps ?? 0, options.starFlagPrompt ?? "", options.symbol ?? "", options.forceNewLaunchpadMint ?? false)
145
- .accounts(accounts);
146
- if (remainingAccounts.length > 0) {
147
- methodBuilder.remainingAccounts(remainingAccounts);
148
- }
149
- const instruction = await methodBuilder.instruction();
150
- // For star joins, make the transaction fully sponsored: force the fee payer to be the root admin.
151
- // This prevents clients from accidentally using an unfunded/nonexistent fee payer account.
81
+ const instruction = await program.methods
82
+ .createMoonpool(options.seasonNumber, options.tier, referrer, options.star ?? false, options.maxSolInLamports ?? new anchor_1.BN(0), options.expectedSolInLamports ?? new anchor_1.BN(0), options.maxSlippageBps ?? 0, options.starFlagPrompt, options.symbol)
83
+ .accounts(accounts)
84
+ .instruction();
85
+ // For star joins, root admin pays
152
86
  const feePayer = options.star ? constants_1.ADMIN_PUBLIC_KEY : (0, signerHelpers_1.getDefaultFeePayer)(options.feePayer);
153
- // Build signers array
154
- const signersList = [(0, signerHelpers_1.asAdminSigner)(constants_1.ADMIN_PUBLIC_KEY), (0, signerHelpers_1.asUserSigner)(options.user)];
155
- // Add launchpad token mint keypair as signer if it exists (either provided or auto-generated)
156
- if (launchpad && launchpadTokenMintKeypair) {
157
- signersList.push({
158
- publicKey: launchpadTokenMintKeypair.publicKey,
159
- role: "payer", // Use 'payer' role for the mint keypair
160
- });
161
- }
87
+ // Build signers array - must include the launchpad mint keypair
88
+ const signersList = [
89
+ (0, signerHelpers_1.asAdminSigner)(constants_1.ADMIN_PUBLIC_KEY),
90
+ (0, signerHelpers_1.asUserSigner)(options.user),
91
+ { publicKey: launchpadTokenMintKeypair.publicKey, role: "payer" },
92
+ ];
162
93
  const signers = (0, signerHelpers_1.buildSigners)(signersList, feePayer);
163
- // OPTIMISTIC UPDATES
164
- const curr = options.currentAccounts || {};
165
- const now = (0, optimistic_1.getCurrentTimestamp)(options.now);
166
- let newSeasonMembership;
167
- let updatedSeason;
168
- if (curr.seasonSettings) {
169
- const optimistic = (0, optimistic_1.computeJoinSeasonOptimistic)({
170
- user: options.user,
171
- seasonNumber: options.seasonNumber,
172
- tier: options.tier,
173
- referrer: options.referrer ?? web3_js_1.PublicKey.default,
174
- tokenMint,
175
- now,
176
- star: options.star ?? false,
177
- seasonSettings: curr.seasonSettings,
178
- ...(curr.season ? { season: curr.season } : {}),
179
- });
180
- if (optimistic.kind === "skip") {
181
- return {
182
- instructions: [instruction],
183
- signers,
184
- pdas,
185
- };
186
- }
187
- newSeasonMembership = optimistic.newSeasonMembership;
188
- updatedSeason = optimistic.updatedSeason;
189
- }
190
94
  return {
191
95
  instructions: [instruction],
192
96
  signers,
193
97
  pdas,
194
- ...(curr.seasonSettings || updatedSeason || newSeasonMembership
195
- ? {
196
- updatedAccounts: {
197
- ...(curr.seasonSettings && { seasonSettings: curr.seasonSettings }),
198
- ...(updatedSeason && { season: updatedSeason }),
199
- ...(newSeasonMembership && {
200
- seasonMembership: newSeasonMembership,
201
- }),
202
- },
203
- }
204
- : {}),
205
- ...(launchpadTokenMintKeypair
206
- ? {
207
- meta: {
208
- launchpadTokenMintKeypair,
209
- },
210
- }
211
- : {}),
98
+ metadata: {
99
+ launchpadTokenMintKeypair,
100
+ },
212
101
  };
213
102
  }
214
103
  /**
215
- * Convenience wrapper: classic (non-launchpad) joinSeason.
216
- * - Keeps the existing MIZD-based join behavior.
217
- * - App code never passes nullable optional accounts.
104
+ * Join an existing Moonpool season.
105
+ *
106
+ * This instruction:
107
+ * - Requires Moonpool to already exist
108
+ * - Lazily initializes Season if needed (for new seasons with existing Moonpool)
109
+ * - Creates new SeasonMembership
110
+ *
111
+ * @param options - JoinMoonpoolSeason options
112
+ * @returns Instructions, signers, and PDAs
218
113
  */
219
- async function joinSeasonClassic(options) {
220
- // IMPORTANT: With `exactOptionalPropertyTypes`, we must OMIT optional props (not set them to `undefined`).
221
- return joinSeason({ ...options, launchpad: false });
114
+ async function joinMoonpoolSeason(options) {
115
+ const program = (0, programHelpers_1.getProgram)(options.connection);
116
+ const launchpadTokenMintPubkey = options.launchpadTokenMint;
117
+ console.log("[joinMoonpoolSeason] Using existing launchpadTokenMint:", launchpadTokenMintPubkey.toString());
118
+ // Derive PDAs with the existing launchpadTokenMint
119
+ const pdasBase = pdaManager_1.PDAManager.deriveJoinSeasonPdas({
120
+ user: options.user,
121
+ seasonNumber: options.seasonNumber,
122
+ tier: options.tier,
123
+ tokenMint: constants_1.MIZD_TOKEN_MINT,
124
+ launchpadTokenMint: launchpadTokenMintPubkey,
125
+ });
126
+ // Derive Moonpool and Treasury PDAs
127
+ const [moonpoolPda] = (0, pdas_1.getMoonpoolPda)(launchpadTokenMintPubkey);
128
+ const [moonpoolTreasuryPda] = (0, pdas_1.getMoonpoolTreasuryPda)(launchpadTokenMintPubkey);
129
+ const pdas = {
130
+ seasonSettings: pdasBase.seasonSettings,
131
+ season: pdasBase.season,
132
+ seasonMembership: pdasBase.seasonMembership,
133
+ moonpool: moonpoolPda,
134
+ moonpoolTreasury: moonpoolTreasuryPda,
135
+ launchpadTokenMint: launchpadTokenMintPubkey,
136
+ };
137
+ const referrer = options.referrer ?? web3_js_1.PublicKey.default;
138
+ const accounts = {
139
+ seasonSettings: pdas.seasonSettings,
140
+ season: pdas.season,
141
+ seasonMembership: pdas.seasonMembership,
142
+ moonpool: moonpoolPda,
143
+ moonpoolTreasury: moonpoolTreasuryPda,
144
+ launchpadTokenMint: launchpadTokenMintPubkey,
145
+ rootAdmin: constants_1.ADMIN_PUBLIC_KEY,
146
+ user: options.user,
147
+ token2022Program: spl_token_1.TOKEN_2022_PROGRAM_ID,
148
+ systemProgram: web3_js_1.SystemProgram.programId,
149
+ };
150
+ const instruction = await program.methods
151
+ .joinMoonpoolSeason(options.seasonNumber, options.tier, referrer, options.star ?? false, options.maxSolInLamports ?? new anchor_1.BN(0), options.expectedSolInLamports ?? new anchor_1.BN(0), options.maxSlippageBps ?? 0)
152
+ .accounts(accounts)
153
+ .instruction();
154
+ // For star joins, root admin pays
155
+ const feePayer = options.star ? constants_1.ADMIN_PUBLIC_KEY : (0, signerHelpers_1.getDefaultFeePayer)(options.feePayer);
156
+ // Build signers array
157
+ const signersList = [
158
+ (0, signerHelpers_1.asAdminSigner)(constants_1.ADMIN_PUBLIC_KEY),
159
+ (0, signerHelpers_1.asUserSigner)(options.user),
160
+ ];
161
+ const signers = (0, signerHelpers_1.buildSigners)(signersList, feePayer);
162
+ return {
163
+ instructions: [instruction],
164
+ signers,
165
+ pdas,
166
+ };
222
167
  }
223
168
  /**
224
- * Convenience wrapper: launchpad joinSeason.
225
- * - Uses SOL in + virtual token escrow.
226
- * - App code never passes nullable optional accounts.
169
+ * Join a Sunpool season (classic mode with MIZD).
170
+ *
171
+ * This instruction:
172
+ * - Lazily initializes Sunpool if needed
173
+ * - Lazily initializes Season if needed
174
+ * - Creates SeasonMembership
175
+ * - Handles MIZD token transfers and join credit
176
+ *
177
+ * @param options - JoinSunpool options
178
+ * @returns Instructions, signers, and PDAs
227
179
  */
228
- async function joinSeasonLaunchpad(options) {
229
- // IMPORTANT: With `exactOptionalPropertyTypes`, we must OMIT optional props (not set them to `undefined`).
230
- const { maxSolInLamports, expectedSolInLamports, maxSlippageBps, ...rest } = options;
231
- return joinSeason({
232
- ...rest,
233
- launchpad: true,
234
- ...(maxSolInLamports ? { maxSolInLamports } : {}),
235
- ...(expectedSolInLamports ? { expectedSolInLamports } : {}),
236
- ...(typeof maxSlippageBps === "number" ? { maxSlippageBps } : {}),
180
+ async function joinSunpool(options) {
181
+ const program = (0, programHelpers_1.getProgram)(options.connection);
182
+ const tokenMint = options.tokenMint ?? constants_1.MIZD_TOKEN_MINT;
183
+ console.log("[joinSunpool] Classic mode join with tokenMint:", tokenMint.toString());
184
+ // Derive PDAs - for Sunpool, use tokenMint for PDA derivation
185
+ const pdasBase = pdaManager_1.PDAManager.deriveJoinSeasonPdas({
186
+ user: options.user,
187
+ seasonNumber: options.seasonNumber,
188
+ tier: options.tier,
189
+ tokenMint,
190
+ launchpadTokenMint: tokenMint, // Sunpool uses tokenMint for Season/Membership PDAs
237
191
  });
192
+ // Derive Sunpool PDA
193
+ const [sunpoolPda] = (0, pdas_1.getSunpoolPda)(tokenMint);
194
+ // User join credit vault ATA
195
+ const userJoinCreditVault = (0, spl_token_1.getAssociatedTokenAddressSync)(constants_1.MIZD_TOKEN_MINT, pdasBase.userJoinCredit, true);
196
+ // Token accounts
197
+ const rootAdminTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(constants_1.MIZD_TOKEN_MINT, constants_1.ADMIN_PUBLIC_KEY);
198
+ const userMizdAta = (0, spl_token_1.getAssociatedTokenAddressSync)(constants_1.MIZD_TOKEN_MINT, options.user);
199
+ const pdas = {
200
+ seasonSettings: pdasBase.seasonSettings,
201
+ season: pdasBase.season,
202
+ seasonMembership: pdasBase.seasonMembership,
203
+ sunpool: sunpoolPda,
204
+ seasonDepositVault: pdasBase.seasonDepositVault,
205
+ userJoinCredit: pdasBase.userJoinCredit,
206
+ userJoinCreditVault,
207
+ };
208
+ const referrer = options.referrer ?? web3_js_1.PublicKey.default;
209
+ const hasReferrer = !referrer.equals(web3_js_1.PublicKey.default);
210
+ // Validate referrer tier
211
+ if (hasReferrer && options.referrerTier === undefined) {
212
+ throw new Error("referrerTier is required when referrer is provided");
213
+ }
214
+ const accounts = {
215
+ seasonSettings: pdas.seasonSettings,
216
+ season: pdas.season,
217
+ seasonMembership: pdas.seasonMembership,
218
+ sunpool: sunpoolPda,
219
+ seasonDepositVault: pdas.seasonDepositVault,
220
+ userJoinCredit: pdas.userJoinCredit,
221
+ userJoinCreditVault,
222
+ mizdMint: constants_1.MIZD_TOKEN_MINT,
223
+ tokenMint,
224
+ rootAdmin: constants_1.ADMIN_PUBLIC_KEY,
225
+ rootAdminTokenAccount,
226
+ userTokenAccount: userMizdAta,
227
+ user: options.user,
228
+ associatedTokenProgram: spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID,
229
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
230
+ systemProgram: web3_js_1.SystemProgram.programId,
231
+ };
232
+ const instruction = await program.methods
233
+ .joinSunpool(options.seasonNumber, options.tier, referrer, options.referrerTier ?? 0, options.star ?? false, options.starFlagPrompt ?? "", options.symbol ?? "")
234
+ .accounts(accounts)
235
+ .instruction();
236
+ // For star joins, root admin pays
237
+ const feePayer = options.star ? constants_1.ADMIN_PUBLIC_KEY : (0, signerHelpers_1.getDefaultFeePayer)(options.feePayer);
238
+ // Build signers array
239
+ const signersList = [
240
+ (0, signerHelpers_1.asAdminSigner)(constants_1.ADMIN_PUBLIC_KEY),
241
+ (0, signerHelpers_1.asUserSigner)(options.user),
242
+ ];
243
+ const signers = (0, signerHelpers_1.buildSigners)(signersList, feePayer);
244
+ return {
245
+ instructions: [instruction],
246
+ signers,
247
+ pdas,
248
+ };
238
249
  }
239
250
  /**
240
- * Join season AND initialize it (first joiner).
241
- * Use this when you know the season doesn't exist yet.
251
+ * Convenience wrapper for launchpad mode joins.
252
+ *
253
+ * This function automatically determines whether to call:
254
+ * - createMoonpool (if forceNewLaunchpadMint=true or no existing moonpool)
255
+ * - joinMoonpoolSeason (if joining an existing moonpool)
242
256
  *
243
- * @param options - Options with REQUIRED starFlagPrompt
244
- * @throws Error if starFlagPrompt is empty or exceeds 33 characters
257
+ * @param options - Join options
258
+ * @returns Instructions, signers, PDAs, and metadata
245
259
  */
246
- async function joinSeasonAndInitialize(options) {
247
- // Validate starFlagPrompt
248
- if (!options.starFlagPrompt || options.starFlagPrompt.length === 0) {
249
- throw new Error("starFlagPrompt is required when initializing a new season");
260
+ async function joinSeasonLaunchpad(options) {
261
+ // Determine if we're creating a new Moonpool or joining an existing one
262
+ const shouldCreateNewMoonpool = options.forceNewLaunchpadMint ||
263
+ !options.currentAccounts?.moonpool ||
264
+ options.currentAccounts.moonpool.launchpadTokenMint?.equals(web3_js_1.PublicKey.default);
265
+ if (shouldCreateNewMoonpool) {
266
+ // Creating a new Moonpool - starFlagPrompt and symbol are required
267
+ if (!options.starFlagPrompt) {
268
+ throw new Error("starFlagPrompt is required when creating a new Moonpool");
269
+ }
270
+ if (!options.symbol) {
271
+ throw new Error("symbol is required when creating a new Moonpool");
272
+ }
273
+ return createMoonpool({
274
+ connection: options.connection,
275
+ user: options.user,
276
+ seasonNumber: options.seasonNumber,
277
+ tier: options.tier,
278
+ starFlagPrompt: options.starFlagPrompt,
279
+ symbol: options.symbol,
280
+ ...(options.referrer !== undefined && { referrer: options.referrer }),
281
+ ...(options.star !== undefined && { star: options.star }),
282
+ ...(options.maxSolInLamports !== undefined && { maxSolInLamports: options.maxSolInLamports }),
283
+ ...(options.expectedSolInLamports !== undefined && { expectedSolInLamports: options.expectedSolInLamports }),
284
+ ...(options.maxSlippageBps !== undefined && { maxSlippageBps: options.maxSlippageBps }),
285
+ ...(options.now !== undefined && { now: options.now }),
286
+ ...(options.feePayer !== undefined && { feePayer: options.feePayer }),
287
+ ...(options.currentAccounts !== undefined && { currentAccounts: options.currentAccounts }),
288
+ });
250
289
  }
251
- if (options.starFlagPrompt.length > 33) {
252
- throw new Error("starFlagPrompt cannot exceed 33 characters");
290
+ else {
291
+ // Joining an existing Moonpool
292
+ const launchpadTokenMint = options.currentAccounts.moonpool.launchpadTokenMint;
293
+ return joinMoonpoolSeason({
294
+ connection: options.connection,
295
+ user: options.user,
296
+ seasonNumber: options.seasonNumber,
297
+ launchpadTokenMint,
298
+ tier: options.tier,
299
+ ...(options.referrer !== undefined && { referrer: options.referrer }),
300
+ ...(options.star !== undefined && { star: options.star }),
301
+ ...(options.maxSolInLamports !== undefined && { maxSolInLamports: options.maxSolInLamports }),
302
+ ...(options.expectedSolInLamports !== undefined && { expectedSolInLamports: options.expectedSolInLamports }),
303
+ ...(options.maxSlippageBps !== undefined && { maxSlippageBps: options.maxSlippageBps }),
304
+ ...(options.now !== undefined && { now: options.now }),
305
+ ...(options.feePayer !== undefined && { feePayer: options.feePayer }),
306
+ ...(options.currentAccounts !== undefined && { currentAccounts: options.currentAccounts }),
307
+ });
253
308
  }
254
- return joinSeason(options);
255
309
  }
256
310
  /**
257
- * Join season AND initialize it in launchpad mode (first joiner).
258
- * Use this when you know the season doesn't exist yet and want launchpad mode.
311
+ * Convenience wrapper for classic (non-launchpad) mode joins.
312
+ * Routes to joinSunpool instruction.
259
313
  *
260
- * @param options - Options with REQUIRED starFlagPrompt
261
- * @throws Error if starFlagPrompt is empty or exceeds 33 characters
314
+ * @param options - Join options
315
+ * @returns Instructions, signers, and PDAs
262
316
  */
263
- async function joinSeasonLaunchpadAndInitialize(options) {
264
- // Validate starFlagPrompt
265
- if (!options.starFlagPrompt || options.starFlagPrompt.length === 0) {
266
- throw new Error("starFlagPrompt is required when initializing a new season");
267
- }
268
- if (options.starFlagPrompt.length > 33) {
269
- throw new Error("starFlagPrompt cannot exceed 33 characters");
270
- }
271
- const { maxSolInLamports, expectedSolInLamports, maxSlippageBps, ...rest } = options;
272
- return joinSeason({
273
- ...rest,
274
- launchpad: true,
275
- ...(maxSolInLamports ? { maxSolInLamports } : {}),
276
- ...(expectedSolInLamports ? { expectedSolInLamports } : {}),
277
- ...(typeof maxSlippageBps === "number" ? { maxSlippageBps } : {}),
317
+ async function joinSeasonClassic(options) {
318
+ return joinSunpool({
319
+ connection: options.connection,
320
+ user: options.user,
321
+ seasonNumber: options.seasonNumber,
322
+ tier: options.tier,
323
+ ...(options.tokenMint !== undefined && { tokenMint: options.tokenMint }),
324
+ ...(options.referrer !== undefined && { referrer: options.referrer }),
325
+ ...(options.referrerTier !== undefined && { referrerTier: options.referrerTier }),
326
+ ...(options.star !== undefined && { star: options.star }),
327
+ ...(options.starFlagPrompt !== undefined && { starFlagPrompt: options.starFlagPrompt }),
328
+ ...(options.symbol !== undefined && { symbol: options.symbol }),
329
+ ...(options.now !== undefined && { now: options.now }),
330
+ ...(options.feePayer !== undefined && { feePayer: options.feePayer }),
331
+ ...(options.currentAccounts !== undefined && { currentAccounts: options.currentAccounts }),
278
332
  });
279
333
  }
280
- // getTierPenaltyPerWindow imported from ../utils/tierPenalty