proof-of-take-sdk 3.1.3 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/getters/getSeasonLaunchpadPool.d.ts +31 -0
  2. package/dist/getters/getSeasonLaunchpadPool.js +49 -0
  3. package/dist/getters/index.d.ts +1 -0
  4. package/dist/getters/index.js +1 -0
  5. package/dist/idl/proof_of_take.json +4548 -1670
  6. package/dist/index.d.ts +14 -7
  7. package/dist/index.js +20 -3
  8. package/dist/instructions/buyMizd.d.ts +19 -0
  9. package/dist/instructions/buyMizd.js +41 -0
  10. package/dist/instructions/claimReferralPenaltyForWindow.d.ts +53 -2
  11. package/dist/instructions/claimReferralPenaltyForWindow.js +45 -3
  12. package/dist/instructions/claimSignupRewards.d.ts +30 -0
  13. package/dist/instructions/claimSignupRewards.js +37 -3
  14. package/dist/instructions/claimWindowRewards.d.ts +42 -1
  15. package/dist/instructions/claimWindowRewards.js +47 -3
  16. package/dist/instructions/confirmedPostOnX.d.ts +2 -0
  17. package/dist/instructions/confirmedPostOnX.js +4 -0
  18. package/dist/instructions/createMiztake.d.ts +2 -0
  19. package/dist/instructions/createMiztake.js +4 -0
  20. package/dist/instructions/initializeBondingCurve.d.ts +24 -0
  21. package/dist/instructions/initializeBondingCurve.js +37 -0
  22. package/dist/instructions/initializeRewardWindow.d.ts +2 -0
  23. package/dist/instructions/initializeRewardWindow.js +5 -2
  24. package/dist/instructions/initializeSeasonVault.d.ts +1 -1
  25. package/dist/instructions/initializeSeasonVault.js +3 -2
  26. package/dist/instructions/joinSeason.d.ts +102 -3
  27. package/dist/instructions/joinSeason.js +117 -40
  28. package/dist/instructions/sellMizd.d.ts +19 -0
  29. package/dist/instructions/sellMizd.js +41 -0
  30. package/dist/instructions/viewSeasonMembershipStatus.d.ts +1 -1
  31. package/dist/instructions/viewSeasonMembershipStatus.js +13 -8
  32. package/dist/instructions/withdrawSeasonDeposit.d.ts +2 -0
  33. package/dist/instructions/withdrawSeasonDeposit.js +6 -1
  34. package/dist/optimistic/index.d.ts +1 -0
  35. package/dist/optimistic/index.js +5 -1
  36. package/dist/optimistic/joinSeasonOptimistic.d.ts +31 -0
  37. package/dist/optimistic/joinSeasonOptimistic.js +55 -0
  38. package/dist/types/accountTypes.d.ts +72 -18
  39. package/dist/types/anchorAccounts.d.ts +2 -0
  40. package/dist/types/proof_of_take.d.ts +4530 -1652
  41. package/dist/types.d.ts +15 -2
  42. package/dist/types.js +7 -1
  43. package/dist/utils/accountConverters.js +6 -1
  44. package/dist/utils/accountUpdates.d.ts +38 -8
  45. package/dist/utils/accountUpdates.js +108 -19
  46. package/dist/utils/constants.d.ts +11 -0
  47. package/dist/utils/constants.js +14 -1
  48. package/dist/utils/pdaManager.d.ts +42 -2
  49. package/dist/utils/pdaManager.js +70 -28
  50. package/dist/utils/pdas.d.ts +46 -8
  51. package/dist/utils/pdas.js +111 -11
  52. package/dist/utils/remainingAccounts.d.ts +1 -0
  53. package/dist/utils/remainingAccounts.js +3 -2
  54. package/dist/utils/seedRegistry.d.ts +10 -0
  55. package/dist/utils/seedRegistry.js +10 -0
  56. package/package.json +1 -1
  57. package/dist/instructions/initializeEscrowVault.d.ts +0 -12
  58. package/dist/instructions/initializeEscrowVault.js +0 -37
@@ -11,6 +11,8 @@ export interface CreateMiztakeOptions {
11
11
  user: PublicKey;
12
12
  admin: PublicKey;
13
13
  seasonNumber: BN;
14
+ /** Token mint this season is scoped to (used for PDA derivation). Defaults to MIZD_TOKEN_MINT. */
15
+ tokenMint?: PublicKey;
14
16
  windowNumber: WindowNumberLike;
15
17
  /** Tier number: 0=copper, 1=silver, 2=gold, 3=platinum, 4=mithril */
16
18
  tier: TierNumber;
@@ -7,6 +7,7 @@ const web3_js_1 = require("@solana/web3.js");
7
7
  const types_1 = require("../types");
8
8
  const pdaManager_1 = require("../utils/pdaManager");
9
9
  const programHelpers_1 = require("../utils/programHelpers");
10
+ const constants_1 = require("../utils/constants");
10
11
  const signerHelpers_1 = require("../utils/signerHelpers");
11
12
  const conversions_1 = require("../utils/conversions");
12
13
  const optimistic_1 = require("../optimistic");
@@ -41,6 +42,7 @@ const enumHelpers_1 = require("../utils/enumHelpers");
41
42
  */
42
43
  async function createMiztake(options) {
43
44
  const program = (0, programHelpers_1.getProgram)(options.connection);
45
+ const tokenMint = options.tokenMint ?? constants_1.MIZD_TOKEN_MINT;
44
46
  // Guardrail: this program uses a 21-window schedule (0..20).
45
47
  const windowNumber = (0, conversions_1.toWindowNumberBn)(options.windowNumber);
46
48
  const shaHash = (0, conversions_1.toSha256HexString)(options.params.shaHash);
@@ -52,6 +54,7 @@ async function createMiztake(options) {
52
54
  windowNumber,
53
55
  user: options.user,
54
56
  tier: options.tier,
57
+ tokenMint,
55
58
  });
56
59
  // Build typed accounts object
57
60
  const accounts = {
@@ -63,6 +66,7 @@ async function createMiztake(options) {
63
66
  seasonMembership: pdas.seasonMembership,
64
67
  rewardWindow: pdas.rewardWindow,
65
68
  userWindowParticipation: pdas.userWindowParticipation,
69
+ tokenMint,
66
70
  user: options.user,
67
71
  admin: options.admin,
68
72
  systemProgram: web3_js_1.SystemProgram.programId,
@@ -0,0 +1,24 @@
1
+ import { BN } from "@coral-xyz/anchor";
2
+ import { Connection, PublicKey } from "@solana/web3.js";
3
+ import { StandardInstructionResultWithPdas } from "../types/instructionResults";
4
+ export interface InitializeBondingCurveOptions {
5
+ connection: Connection;
6
+ /** Must be the on-chain root admin (ADMIN_PUBLIC_KEY). */
7
+ admin?: PublicKey;
8
+ /** Initial MIZD inventory deposited into the vault (base units). */
9
+ initialMizdDepositUnits: BN;
10
+ /** Initial SOL reserve deposited into the curve PDA (lamports). */
11
+ initialSolDepositLamports: BN;
12
+ /** Virtual SOL reserve (lamports). */
13
+ virtualSolReserveLamports?: BN;
14
+ /** Virtual MIZD reserve (base units). */
15
+ virtualMizdReserveUnits?: BN;
16
+ /** Fee in bps (0..=10000). Default 0. */
17
+ feeBps?: number;
18
+ feePayer?: PublicKey;
19
+ }
20
+ export declare function initializeBondingCurve(opts: InitializeBondingCurveOptions): Promise<StandardInstructionResultWithPdas<{
21
+ bondingCurve: PublicKey;
22
+ mizdVault: PublicKey;
23
+ adminMizdAta: PublicKey;
24
+ }>>;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.initializeBondingCurve = initializeBondingCurve;
4
+ const anchor_1 = require("@coral-xyz/anchor");
5
+ const web3_js_1 = require("@solana/web3.js");
6
+ const spl_token_1 = require("@solana/spl-token");
7
+ const instructionResultHelpers_1 = require("../utils/instructionResultHelpers");
8
+ const constants_1 = require("../utils/constants");
9
+ const pdaManager_1 = require("../utils/pdaManager");
10
+ const programHelpers_1 = require("../utils/programHelpers");
11
+ const signerHelpers_1 = require("../utils/signerHelpers");
12
+ async function initializeBondingCurve(opts) {
13
+ const program = (0, programHelpers_1.getProgram)(opts.connection);
14
+ const admin = opts.admin ?? constants_1.ADMIN_PUBLIC_KEY;
15
+ const pdas = pdaManager_1.PDAManager.deriveBondingCurvePdas();
16
+ const adminMizdAta = (0, spl_token_1.getAssociatedTokenAddressSync)(constants_1.MIZD_TOKEN_MINT, admin);
17
+ const accounts = {
18
+ bondingCurve: pdas.bondingCurve,
19
+ mizdVault: pdas.mizdVault,
20
+ mizdMint: constants_1.MIZD_TOKEN_MINT,
21
+ admin,
22
+ adminMizdAta,
23
+ associatedTokenProgram: spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID,
24
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
25
+ systemProgram: web3_js_1.SystemProgram.programId,
26
+ };
27
+ const instruction = await program.methods
28
+ .initializeBondingCurve(opts.initialMizdDepositUnits, opts.initialSolDepositLamports, opts.virtualSolReserveLamports ?? new anchor_1.BN(0), opts.virtualMizdReserveUnits ?? new anchor_1.BN(0), opts.feeBps ?? 0)
29
+ .accounts(accounts)
30
+ .instruction();
31
+ const feePayer = (0, signerHelpers_1.resolveFeePayer)({ feePayer: opts.feePayer, admin });
32
+ const signers = (0, signerHelpers_1.buildSigners)([(0, signerHelpers_1.asAdminSigner)(admin)], feePayer);
33
+ return (0, instructionResultHelpers_1.singleInstruction)(instruction, {
34
+ signers,
35
+ pdas: { bondingCurve: pdas.bondingCurve, mizdVault: pdas.mizdVault, adminMizdAta },
36
+ });
37
+ }
@@ -12,6 +12,8 @@ export interface InitializeRewardWindowOptions {
12
12
  admin: PublicKey;
13
13
  seasonNumber: SeasonNumberLike;
14
14
  windowNumber: WindowNumberLike;
15
+ /** Token mint this season is scoped to (used for PDA derivation). Defaults to MIZD_TOKEN_MINT. */
16
+ tokenMint?: PublicKey;
15
17
  feePayer?: PublicKey;
16
18
  }
17
19
  /**
@@ -7,6 +7,7 @@ const programHelpers_1 = require("../utils/programHelpers");
7
7
  const signerHelpers_1 = require("../utils/signerHelpers");
8
8
  const instructionResultHelpers_1 = require("../utils/instructionResultHelpers");
9
9
  const conversions_1 = require("../utils/conversions");
10
+ const constants_1 = require("../utils/constants");
10
11
  /**
11
12
  * Initialize (materialize) a missing RewardWindow PDA (root-admin only).
12
13
  *
@@ -17,13 +18,15 @@ async function initializeRewardWindow(options) {
17
18
  const program = (0, programHelpers_1.getProgram)(options.connection);
18
19
  const seasonNumberBn = (0, conversions_1.toSeasonNumberBn)(options.seasonNumber);
19
20
  const windowNumberBn = (0, conversions_1.toWindowNumberBn)(options.windowNumber);
21
+ const tokenMint = options.tokenMint ?? constants_1.MIZD_TOKEN_MINT;
20
22
  const [seasonSettings] = (0, pdas_1.getSeasonSettingsPda)();
21
- const [season] = (0, pdas_1.getSeasonPda)(seasonNumberBn);
22
- const [rewardWindow] = (0, pdas_1.getRewardWindowPda)(seasonNumberBn, windowNumberBn);
23
+ const [season] = (0, pdas_1.getSeasonPda)(seasonNumberBn, tokenMint);
24
+ const [rewardWindow] = (0, pdas_1.getRewardWindowPda)(seasonNumberBn, windowNumberBn, tokenMint);
23
25
  const accounts = {
24
26
  seasonSettings,
25
27
  season,
26
28
  rewardWindow,
29
+ tokenMint,
27
30
  admin: options.admin,
28
31
  systemProgram: web3_js_1.SystemProgram.programId,
29
32
  };
@@ -12,6 +12,6 @@ import { StandardInstructionResultWithPdas } from "../types/instructionResults";
12
12
  * @param feePayer - Optional separate fee payer for transaction fees
13
13
  * @returns Instructions, signers array, and vault PDA
14
14
  */
15
- export declare function initializeSeasonVault(connection: Connection, admin: PublicKey, seasonNumber: BN, feePayer?: PublicKey): Promise<StandardInstructionResultWithPdas<{
15
+ export declare function initializeSeasonVault(connection: Connection, admin: PublicKey, seasonNumber: BN, tokenMint?: PublicKey, feePayer?: PublicKey): Promise<StandardInstructionResultWithPdas<{
16
16
  vault: PublicKey;
17
17
  }>>;
@@ -19,12 +19,13 @@ const instructionResultHelpers_1 = require("../utils/instructionResultHelpers");
19
19
  * @param feePayer - Optional separate fee payer for transaction fees
20
20
  * @returns Instructions, signers array, and vault PDA
21
21
  */
22
- async function initializeSeasonVault(connection, admin, seasonNumber, feePayer) {
22
+ async function initializeSeasonVault(connection, admin, seasonNumber, tokenMint = constants_1.MIZD_TOKEN_MINT, feePayer) {
23
23
  const program = (0, programHelpers_1.getProgram)(connection);
24
- const [vaultPda] = (0, pdas_1.getSeasonDepositVaultPda)(seasonNumber);
24
+ const [vaultPda] = (0, pdas_1.getSeasonDepositVaultPda)(seasonNumber, tokenMint);
25
25
  const accounts = {
26
26
  seasonDepositVault: vaultPda,
27
27
  mizdMint: constants_1.MIZD_TOKEN_MINT,
28
+ tokenMint,
28
29
  admin: admin,
29
30
  tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
30
31
  systemProgram: web3_js_1.SystemProgram.programId,
@@ -3,12 +3,14 @@ import { Connection, PublicKey } from "@solana/web3.js";
3
3
  import { Season, SeasonMembership, SeasonSettings, TierNumber } from "../types";
4
4
  import { StandardInstructionResultWithPdas } from "../types/instructionResults";
5
5
  /**
6
- * Options for joinSeason instruction
6
+ * Options for joinSeason instruction (joining an existing season)
7
7
  */
8
8
  export interface JoinSeasonOptions {
9
9
  connection: Connection;
10
10
  user: PublicKey;
11
11
  seasonNumber: BN;
12
+ /** Token mint this season is scoped to (used for PDA derivation). Defaults to MIZD_TOKEN_MINT. */
13
+ tokenMint?: PublicKey;
12
14
  /** Tier number: 0=copper, 1=silver, 2=gold, 3=platinum, 4=mithril */
13
15
  tier: TierNumber;
14
16
  /** Optional referrer (PublicKey.default means no referrer) */
@@ -17,6 +19,29 @@ export interface JoinSeasonOptions {
17
19
  referrerTier?: TierNumber;
18
20
  /** If true, root admin funds join fee + deposit (currently only allowed for tier=0 on-chain). */
19
21
  star?: boolean;
22
+ /** If true, join uses launchpad mode (SOL in, virtual tokens escrowed; no SPL token accounts needed). */
23
+ launchpad?: boolean;
24
+ /** Launchpad slippage cap (lamports). Only used when launchpad=true. Defaults to u64::MAX. */
25
+ maxSolInLamports?: BN;
26
+ /**
27
+ * Launchpad slippage ergonomics:
28
+ * - Provide `expectedSolInLamports` (your quote) and `maxSlippageBps` and the program will enforce
29
+ * `sol_required <= expected * (1 + bps/10_000)`.
30
+ * - If both this and `maxSolInLamports` are provided, the program uses the tighter cap.
31
+ */
32
+ expectedSolInLamports?: BN;
33
+ /** Max slippage in basis points (0..=10_000). Used only when expectedSolInLamports > 0. */
34
+ maxSlippageBps?: number;
35
+ /**
36
+ * Star flag prompt: a short message (max 33 chars) displayed when users raise their flag.
37
+ * Only used when initializing a new pool (first join). Ignored when joining existing season.
38
+ */
39
+ starFlagPrompt?: string;
40
+ /**
41
+ * Token symbol (max 4 chars, e.g., "MIZD", "USDT", "MOON").
42
+ * Only used when initializing a new pool (first join). Ignored when joining existing season.
43
+ */
44
+ symbol?: string;
20
45
  /** Optional injected timestamp (seconds) for optimistic state calculation */
21
46
  now?: BN;
22
47
  feePayer?: PublicKey;
@@ -25,12 +50,56 @@ export interface JoinSeasonOptions {
25
50
  season?: Season;
26
51
  };
27
52
  }
53
+ /**
54
+ * Options for initializing a new season (first joiner).
55
+ * Requires starFlagPrompt and symbol since they will be stored in the pool accounts.
56
+ */
57
+ export type JoinSeasonAndInitializeOptions = Omit<JoinSeasonOptions, "starFlagPrompt" | "symbol"> & {
58
+ /**
59
+ * Star flag prompt: a short message (max 33 chars) displayed when users raise their flag.
60
+ * REQUIRED when initializing a new pool.
61
+ */
62
+ starFlagPrompt: string;
63
+ /**
64
+ * Token symbol (max 4 chars, e.g., "MIZD", "USDT", "MOON").
65
+ * REQUIRED when initializing a new pool.
66
+ */
67
+ symbol: string;
68
+ };
69
+ /**
70
+ * Options for the classic (non-launchpad) joinSeason wrapper.
71
+ * This avoids exposing nullable optional accounts to app code.
72
+ */
73
+ export type JoinSeasonClassicOptions = Omit<JoinSeasonOptions, "launchpad" | "maxSolInLamports" | "expectedSolInLamports" | "maxSlippageBps"> & {
74
+ launchpad?: never;
75
+ maxSolInLamports?: never;
76
+ expectedSolInLamports?: never;
77
+ maxSlippageBps?: never;
78
+ };
79
+ /**
80
+ * Options for the launchpad joinSeason wrapper.
81
+ * (No SPL token accounts needed; user pays SOL to the pool PDA.)
82
+ */
83
+ export type JoinSeasonLaunchpadOptions = Omit<JoinSeasonOptions, "launchpad" | "maxSolInLamports" | "expectedSolInLamports" | "maxSlippageBps"> & {
84
+ launchpad?: never;
85
+ /** Optional hard cap in lamports (0 disables this cap on-chain). */
86
+ maxSolInLamports?: BN;
87
+ /** Optional expected SOL in lamports for bps slippage protection (0 disables on-chain). */
88
+ expectedSolInLamports?: BN;
89
+ /** Optional max slippage bps (0 disables on-chain). */
90
+ maxSlippageBps?: number;
91
+ };
28
92
  type JoinSeasonPdas = {
29
93
  seasonSettings: PublicKey;
30
94
  season: PublicKey;
31
95
  seasonMembership: PublicKey;
96
+ moonpool: PublicKey;
97
+ moonpoolTreasury: PublicKey;
98
+ launchpadTokenMint: PublicKey;
99
+ sunpool: PublicKey;
32
100
  seasonDepositVault: PublicKey;
33
- seasonEscrowVault: PublicKey;
101
+ userJoinCredit: PublicKey;
102
+ userJoinCreditVault: PublicKey;
34
103
  };
35
104
  type JoinSeasonUpdatedAccounts = {
36
105
  seasonSettings?: SeasonSettings;
@@ -42,7 +111,7 @@ type JoinSeasonUpdatedAccounts = {
42
111
  *
43
112
  * Signers: user + root admin (root admin pays for signup-rewards vault ATA creation when a referrer is present)
44
113
  * User pays for season (if needed) and membership accounts
45
- * Transfers full tier deposit from user to vault, then escrows the pre-join portion
114
+ * Transfers active deposit into the season vault; the late-join escrow portion is converted into non-withdrawable join credit
46
115
  *
47
116
  * IMPORTANT: If providing a referrer, you MUST also provide referrerTier.
48
117
  * The referrerTier must match the tier the referrer actually joined the season with.
@@ -52,4 +121,34 @@ type JoinSeasonUpdatedAccounts = {
52
121
  * @returns Instructions, signers, PDAs, and optimistically created/updated accounts
53
122
  */
54
123
  export declare function joinSeason(options: JoinSeasonOptions): Promise<StandardInstructionResultWithPdas<JoinSeasonPdas, JoinSeasonUpdatedAccounts>>;
124
+ /**
125
+ * Convenience wrapper: classic (non-launchpad) joinSeason.
126
+ * - Keeps the existing MIZD-based join behavior.
127
+ * - App code never passes nullable optional accounts.
128
+ */
129
+ export declare function joinSeasonClassic(options: JoinSeasonClassicOptions): Promise<StandardInstructionResultWithPdas<JoinSeasonPdas, JoinSeasonUpdatedAccounts>>;
130
+ /**
131
+ * Convenience wrapper: launchpad joinSeason.
132
+ * - Uses SOL in + virtual token escrow.
133
+ * - App code never passes nullable optional accounts.
134
+ */
135
+ export declare function joinSeasonLaunchpad(options: JoinSeasonLaunchpadOptions): Promise<StandardInstructionResultWithPdas<JoinSeasonPdas, JoinSeasonUpdatedAccounts>>;
136
+ /**
137
+ * Join season AND initialize it (first joiner).
138
+ * Use this when you know the season doesn't exist yet.
139
+ *
140
+ * @param options - Options with REQUIRED starFlagPrompt
141
+ * @throws Error if starFlagPrompt is empty or exceeds 33 characters
142
+ */
143
+ export declare function joinSeasonAndInitialize(options: JoinSeasonAndInitializeOptions): Promise<StandardInstructionResultWithPdas<JoinSeasonPdas, JoinSeasonUpdatedAccounts>>;
144
+ /**
145
+ * Join season AND initialize it in launchpad mode (first joiner).
146
+ * Use this when you know the season doesn't exist yet and want launchpad mode.
147
+ *
148
+ * @param options - Options with REQUIRED starFlagPrompt
149
+ * @throws Error if starFlagPrompt is empty or exceeds 33 characters
150
+ */
151
+ export declare function joinSeasonLaunchpadAndInitialize(options: Omit<JoinSeasonLaunchpadOptions, "starFlagPrompt"> & {
152
+ starFlagPrompt: string;
153
+ }): Promise<StandardInstructionResultWithPdas<JoinSeasonPdas, JoinSeasonUpdatedAccounts>>;
55
154
  export {};
@@ -1,25 +1,25 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.joinSeason = joinSeason;
4
+ exports.joinSeasonClassic = joinSeasonClassic;
5
+ exports.joinSeasonLaunchpad = joinSeasonLaunchpad;
6
+ exports.joinSeasonAndInitialize = joinSeasonAndInitialize;
7
+ exports.joinSeasonLaunchpadAndInitialize = joinSeasonLaunchpadAndInitialize;
4
8
  const anchor_1 = require("@coral-xyz/anchor");
5
9
  const web3_js_1 = require("@solana/web3.js");
6
10
  const spl_token_1 = require("@solana/spl-token");
7
- const types_1 = require("../types");
8
11
  const pdaManager_1 = require("../utils/pdaManager");
9
12
  const constants_1 = require("../utils/constants");
10
13
  const programHelpers_1 = require("../utils/programHelpers");
11
14
  const signerHelpers_1 = require("../utils/signerHelpers");
12
15
  const optimistic_1 = require("../optimistic");
13
- const pdas_1 = require("../utils/pdas");
14
- const tierPenalty_1 = require("../utils/tierPenalty");
15
- const enumHelpers_1 = require("../utils/enumHelpers");
16
16
  const remainingAccounts_1 = require("../utils/remainingAccounts");
17
17
  /**
18
18
  * Join a season
19
19
  *
20
20
  * Signers: user + root admin (root admin pays for signup-rewards vault ATA creation when a referrer is present)
21
21
  * User pays for season (if needed) and membership accounts
22
- * Transfers full tier deposit from user to vault, then escrows the pre-join portion
22
+ * Transfers active deposit into the season vault; the late-join escrow portion is converted into non-withdrawable join credit
23
23
  *
24
24
  * IMPORTANT: If providing a referrer, you MUST also provide referrerTier.
25
25
  * The referrerTier must match the tier the referrer actually joined the season with.
@@ -30,20 +30,44 @@ const remainingAccounts_1 = require("../utils/remainingAccounts");
30
30
  */
31
31
  async function joinSeason(options) {
32
32
  const program = (0, programHelpers_1.getProgram)(options.connection);
33
- const pdas = pdaManager_1.PDAManager.deriveJoinSeasonPdas({
33
+ const tokenMint = options.tokenMint ?? constants_1.MIZD_TOKEN_MINT;
34
+ const launchpad = options.launchpad ?? false;
35
+ const pdasBase = pdaManager_1.PDAManager.deriveJoinSeasonPdas({
34
36
  user: options.user,
35
37
  seasonNumber: options.seasonNumber,
36
38
  tier: options.tier,
39
+ tokenMint,
37
40
  });
38
- const rootAdminTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(constants_1.MIZD_TOKEN_MINT, constants_1.ADMIN_PUBLIC_KEY);
39
- const userMizdAta = (0, spl_token_1.getAssociatedTokenAddressSync)(constants_1.MIZD_TOKEN_MINT, options.user);
41
+ const rootAdminTokenAccount = launchpad
42
+ ? null
43
+ : (0, spl_token_1.getAssociatedTokenAddressSync)(constants_1.MIZD_TOKEN_MINT, constants_1.ADMIN_PUBLIC_KEY);
44
+ const userMizdAta = launchpad
45
+ ? null
46
+ : (0, spl_token_1.getAssociatedTokenAddressSync)(constants_1.MIZD_TOKEN_MINT, options.user);
47
+ // Join credit PDA + its vault ATA (owner is off-curve PDA, so allowOwnerOffCurve=true).
48
+ const userJoinCreditVault = launchpad
49
+ ? null
50
+ : (0, spl_token_1.getAssociatedTokenAddressSync)(constants_1.MIZD_TOKEN_MINT, pdasBase.userJoinCredit, true);
51
+ const pdas = {
52
+ ...pdasBase,
53
+ userJoinCreditVault: userJoinCreditVault ?? web3_js_1.PublicKey.default,
54
+ };
40
55
  const accounts = {
41
56
  seasonSettings: pdas.seasonSettings,
42
57
  season: pdas.season,
43
58
  seasonMembership: pdas.seasonMembership,
44
- seasonDepositVault: pdas.seasonDepositVault,
45
- seasonEscrowVault: pdas.seasonEscrowVault,
59
+ // SECURITY: Pool accounts are now MANDATORY (non-optional) to prevent bypassing
60
+ // the mode check. The on-chain program validates pool state to ensure
61
+ // subsequent seasons use the same mode (launchpad/classic) as the first season.
62
+ moonpool: pdas.moonpool,
63
+ moonpoolTreasury: pdas.moonpoolTreasury,
64
+ launchpadTokenMint: pdas.launchpadTokenMint,
65
+ sunpool: pdas.sunpool,
66
+ seasonDepositVault: launchpad ? null : pdas.seasonDepositVault,
67
+ userJoinCredit: launchpad ? null : pdas.userJoinCredit,
68
+ userJoinCreditVault: launchpad ? null : userJoinCreditVault,
46
69
  mizdMint: constants_1.MIZD_TOKEN_MINT,
70
+ tokenMint,
47
71
  rootAdmin: constants_1.ADMIN_PUBLIC_KEY,
48
72
  rootAdminTokenAccount,
49
73
  // Always pass the canonical ATA; it may not exist yet (created on-chain with root admin as payer).
@@ -51,6 +75,7 @@ async function joinSeason(options) {
51
75
  user: options.user,
52
76
  associatedTokenProgram: spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID,
53
77
  tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
78
+ token2022Program: spl_token_1.TOKEN_2022_PROGRAM_ID,
54
79
  systemProgram: web3_js_1.SystemProgram.programId,
55
80
  };
56
81
  const referrer = options.referrer ?? web3_js_1.PublicKey.default;
@@ -65,12 +90,13 @@ async function joinSeason(options) {
65
90
  tier: options.tier,
66
91
  referrer,
67
92
  referrerTier: options.referrerTier,
93
+ tokenMint,
68
94
  })
69
95
  : [];
70
96
  const methodBuilder = program.methods
71
97
  // Anchor expects BN for u64 args.
72
98
  // referrerTier defaults to 0 if no referrer (ignored on-chain)
73
- .joinSeason(options.seasonNumber, options.tier, referrer, options.referrerTier ?? 0, options.star ?? false)
99
+ .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 ?? "")
74
100
  .accounts(accounts);
75
101
  if (remainingAccounts.length > 0) {
76
102
  methodBuilder.remainingAccounts(remainingAccounts);
@@ -86,41 +112,26 @@ async function joinSeason(options) {
86
112
  let newSeasonMembership;
87
113
  let updatedSeason;
88
114
  if (curr.seasonSettings) {
89
- const [, bump] = (0, pdas_1.getSeasonMembershipPda)(options.seasonNumber, options.user, options.tier);
90
- // Mirror on-chain join_season.rs:
91
- // current_window = (now - season.started_at) / window_duration (integer division)
92
- // joined_window_number = current_window (after bounds checks)
93
- const totalWindows = curr.seasonSettings.totalWindowsPerSeason;
94
- const depositTier = (0, tierPenalty_1.tierNumberToDepositTier)(options.tier);
95
- const perWindowPenalty = (0, tierPenalty_1.getTierPenaltyPerWindow)(depositTier);
96
- const depositFull = perWindowPenalty.muln(totalWindows);
97
- let joinedWindowNumber = new anchor_1.BN(0);
98
- if (curr.season) {
99
- if ((0, enumHelpers_1.isSeasonState)(curr.season.seasonState, types_1.SeasonState.Uninitialized)) {
100
- // On-chain: season is initialized with started_at = now, so elapsed = 0 -> current_window = 0
101
- joinedWindowNumber = new anchor_1.BN(0);
102
- }
103
- else if (curr.seasonSettings.windowDuration &&
104
- !curr.seasonSettings.windowDuration.isZero()) {
105
- const startedAt = curr.season.startedAt;
106
- const elapsed = now.gte(startedAt) ? now.sub(startedAt) : new anchor_1.BN(0);
107
- joinedWindowNumber = elapsed.div(curr.seasonSettings.windowDuration);
108
- }
109
- }
110
- // If this would fail on-chain (current_window >= total_windows), skip optimistic updates.
111
- if (joinedWindowNumber.gte(new anchor_1.BN(totalWindows))) {
115
+ const optimistic = (0, optimistic_1.computeJoinSeasonOptimistic)({
116
+ user: options.user,
117
+ seasonNumber: options.seasonNumber,
118
+ tier: options.tier,
119
+ referrer: options.referrer ?? web3_js_1.PublicKey.default,
120
+ tokenMint,
121
+ now,
122
+ star: options.star ?? false,
123
+ seasonSettings: curr.seasonSettings,
124
+ ...(curr.season ? { season: curr.season } : {}),
125
+ });
126
+ if (optimistic.kind === "skip") {
112
127
  return {
113
128
  instructions: [instruction],
114
129
  signers,
115
130
  pdas,
116
131
  };
117
132
  }
118
- const depositEscrowed = perWindowPenalty.mul(joinedWindowNumber);
119
- const depositActive = depositFull.sub(depositEscrowed);
120
- newSeasonMembership = (0, optimistic_1.initializeSeasonMembership)(options.user, options.seasonNumber, depositTier, options.referrer ?? web3_js_1.PublicKey.default, depositActive, depositEscrowed, now, joinedWindowNumber, bump, options.star ?? false);
121
- if (curr.season) {
122
- updatedSeason = (0, optimistic_1.updateSeasonForJoin)(curr.season, depositActive, depositTier, joinedWindowNumber, totalWindows);
123
- }
133
+ newSeasonMembership = optimistic.newSeasonMembership;
134
+ updatedSeason = optimistic.updatedSeason;
124
135
  }
125
136
  return {
126
137
  instructions: [instruction],
@@ -139,4 +150,70 @@ async function joinSeason(options) {
139
150
  : {}),
140
151
  };
141
152
  }
153
+ /**
154
+ * Convenience wrapper: classic (non-launchpad) joinSeason.
155
+ * - Keeps the existing MIZD-based join behavior.
156
+ * - App code never passes nullable optional accounts.
157
+ */
158
+ async function joinSeasonClassic(options) {
159
+ // IMPORTANT: With `exactOptionalPropertyTypes`, we must OMIT optional props (not set them to `undefined`).
160
+ return joinSeason({ ...options, launchpad: false });
161
+ }
162
+ /**
163
+ * Convenience wrapper: launchpad joinSeason.
164
+ * - Uses SOL in + virtual token escrow.
165
+ * - App code never passes nullable optional accounts.
166
+ */
167
+ async function joinSeasonLaunchpad(options) {
168
+ // IMPORTANT: With `exactOptionalPropertyTypes`, we must OMIT optional props (not set them to `undefined`).
169
+ const { maxSolInLamports, expectedSolInLamports, maxSlippageBps, ...rest } = options;
170
+ return joinSeason({
171
+ ...rest,
172
+ launchpad: true,
173
+ ...(maxSolInLamports ? { maxSolInLamports } : {}),
174
+ ...(expectedSolInLamports ? { expectedSolInLamports } : {}),
175
+ ...(typeof maxSlippageBps === "number" ? { maxSlippageBps } : {}),
176
+ });
177
+ }
178
+ /**
179
+ * Join season AND initialize it (first joiner).
180
+ * Use this when you know the season doesn't exist yet.
181
+ *
182
+ * @param options - Options with REQUIRED starFlagPrompt
183
+ * @throws Error if starFlagPrompt is empty or exceeds 33 characters
184
+ */
185
+ async function joinSeasonAndInitialize(options) {
186
+ // Validate starFlagPrompt
187
+ if (!options.starFlagPrompt || options.starFlagPrompt.length === 0) {
188
+ throw new Error("starFlagPrompt is required when initializing a new season");
189
+ }
190
+ if (options.starFlagPrompt.length > 33) {
191
+ throw new Error("starFlagPrompt cannot exceed 33 characters");
192
+ }
193
+ return joinSeason(options);
194
+ }
195
+ /**
196
+ * Join season AND initialize it in launchpad mode (first joiner).
197
+ * Use this when you know the season doesn't exist yet and want launchpad mode.
198
+ *
199
+ * @param options - Options with REQUIRED starFlagPrompt
200
+ * @throws Error if starFlagPrompt is empty or exceeds 33 characters
201
+ */
202
+ async function joinSeasonLaunchpadAndInitialize(options) {
203
+ // Validate starFlagPrompt
204
+ if (!options.starFlagPrompt || options.starFlagPrompt.length === 0) {
205
+ throw new Error("starFlagPrompt is required when initializing a new season");
206
+ }
207
+ if (options.starFlagPrompt.length > 33) {
208
+ throw new Error("starFlagPrompt cannot exceed 33 characters");
209
+ }
210
+ const { maxSolInLamports, expectedSolInLamports, maxSlippageBps, ...rest } = options;
211
+ return joinSeason({
212
+ ...rest,
213
+ launchpad: true,
214
+ ...(maxSolInLamports ? { maxSolInLamports } : {}),
215
+ ...(expectedSolInLamports ? { expectedSolInLamports } : {}),
216
+ ...(typeof maxSlippageBps === "number" ? { maxSlippageBps } : {}),
217
+ });
218
+ }
142
219
  // getTierPenaltyPerWindow imported from ../utils/tierPenalty
@@ -0,0 +1,19 @@
1
+ import { BN } from "@coral-xyz/anchor";
2
+ import { Connection, PublicKey } from "@solana/web3.js";
3
+ import { StandardInstructionResultWithPdas } from "../types/instructionResults";
4
+ export interface SellMizdOptions {
5
+ connection: Connection;
6
+ user: PublicKey;
7
+ /** MIZD input (base units). */
8
+ mizdInUnits: BN;
9
+ /** Slippage protection: minimum SOL out (lamports). */
10
+ minSolOutLamports: BN;
11
+ /** Must be the on-chain root admin (ADMIN_PUBLIC_KEY); required signer on-chain. */
12
+ admin?: PublicKey;
13
+ feePayer?: PublicKey;
14
+ }
15
+ export declare function sellMizd(opts: SellMizdOptions): Promise<StandardInstructionResultWithPdas<{
16
+ bondingCurve: PublicKey;
17
+ mizdVault: PublicKey;
18
+ userMizdAta: PublicKey;
19
+ }>>;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sellMizd = sellMizd;
4
+ const web3_js_1 = require("@solana/web3.js");
5
+ const spl_token_1 = require("@solana/spl-token");
6
+ const instructionResultHelpers_1 = require("../utils/instructionResultHelpers");
7
+ const constants_1 = require("../utils/constants");
8
+ const pdaManager_1 = require("../utils/pdaManager");
9
+ const programHelpers_1 = require("../utils/programHelpers");
10
+ const signerHelpers_1 = require("../utils/signerHelpers");
11
+ async function sellMizd(opts) {
12
+ const program = (0, programHelpers_1.getProgram)(opts.connection);
13
+ const admin = opts.admin ?? constants_1.ADMIN_PUBLIC_KEY;
14
+ const pdas = pdaManager_1.PDAManager.deriveBondingCurvePdas();
15
+ const userMizdAta = (0, spl_token_1.getAssociatedTokenAddressSync)(constants_1.MIZD_TOKEN_MINT, opts.user);
16
+ const accounts = {
17
+ bondingCurve: pdas.bondingCurve,
18
+ mizdVault: pdas.mizdVault,
19
+ mizdMint: constants_1.MIZD_TOKEN_MINT,
20
+ admin,
21
+ user: opts.user,
22
+ userMizdAta,
23
+ associatedTokenProgram: spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID,
24
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
25
+ systemProgram: web3_js_1.SystemProgram.programId,
26
+ };
27
+ const instruction = await program.methods
28
+ .sellMizd(opts.mizdInUnits, opts.minSolOutLamports)
29
+ .accounts(accounts)
30
+ .instruction();
31
+ const feePayer = (0, signerHelpers_1.resolveFeePayer)({ feePayer: opts.feePayer, admin });
32
+ const signers = (0, signerHelpers_1.buildSigners)([(0, signerHelpers_1.asAdminSigner)(admin), (0, signerHelpers_1.asUserSigner)(opts.user)], feePayer);
33
+ return (0, instructionResultHelpers_1.singleInstruction)(instruction, {
34
+ signers,
35
+ pdas: {
36
+ bondingCurve: pdas.bondingCurve,
37
+ mizdVault: pdas.mizdVault,
38
+ userMizdAta,
39
+ },
40
+ });
41
+ }
@@ -13,4 +13,4 @@ import { SeasonMembershipStatusView, TierNumber } from "../types";
13
13
  * @param tier - Tier number: 0=copper, 1=silver, 2=gold, 3=platinum, 4=mithril
14
14
  * @returns View data with membership status
15
15
  */
16
- export declare function viewSeasonMembershipStatus(connection: Connection, user: PublicKey, seasonNumber: BN, tier: TierNumber): Promise<SeasonMembershipStatusView>;
16
+ export declare function viewSeasonMembershipStatus(connection: Connection, user: PublicKey, seasonNumber: BN, tier: TierNumber, tokenMint?: PublicKey): Promise<SeasonMembershipStatusView>;
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.viewSeasonMembershipStatus = viewSeasonMembershipStatus;
4
- const pdas_1 = require("../utils/pdas");
5
4
  const programHelpers_1 = require("../utils/programHelpers");
5
+ const constants_1 = require("../utils/constants");
6
+ const pdaManager_1 = require("../utils/pdaManager");
6
7
  /**
7
8
  * View season membership status (read-only)
8
9
  *
@@ -15,15 +16,19 @@ const programHelpers_1 = require("../utils/programHelpers");
15
16
  * @param tier - Tier number: 0=copper, 1=silver, 2=gold, 3=platinum, 4=mithril
16
17
  * @returns View data with membership status
17
18
  */
18
- async function viewSeasonMembershipStatus(connection, user, seasonNumber, tier) {
19
+ async function viewSeasonMembershipStatus(connection, user, seasonNumber, tier, tokenMint = constants_1.MIZD_TOKEN_MINT) {
19
20
  const program = (0, programHelpers_1.getProgram)(connection);
20
- const [seasonSettingsPda] = (0, pdas_1.getSeasonSettingsPda)();
21
- const [seasonMembershipPda] = (0, pdas_1.getSeasonMembershipPda)(seasonNumber, user, tier);
22
- const [seasonPda] = (0, pdas_1.getSeasonPda)(seasonNumber);
21
+ const pdas = pdaManager_1.PDAManager.deriveViewSeasonMembershipStatusPdas({
22
+ user,
23
+ seasonNumber,
24
+ tier,
25
+ tokenMint,
26
+ });
23
27
  const accounts = {
24
- seasonSettings: seasonSettingsPda,
25
- seasonMembership: seasonMembershipPda,
26
- season: seasonPda,
28
+ seasonSettings: pdas.seasonSettings,
29
+ seasonMembership: pdas.seasonMembership,
30
+ season: pdas.season,
31
+ tokenMint,
27
32
  };
28
33
  const result = await program.methods
29
34
  .viewSeasonMembershipStatus()