@zemyth/raise-sdk 0.1.6 → 0.2.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.
@@ -15,6 +15,7 @@ export const SEEDS = {
15
15
  INVESTMENT: 'investment',
16
16
  VOTE: 'vote',
17
17
  ESCROW: 'escrow',
18
+ ESCROW_TOKEN: 'escrow_token',
18
19
  PIVOT: 'pivot',
19
20
  PIVOT_PROPOSAL: 'pivot_proposal',
20
21
  TGE_ESCROW: 'tge_escrow',
@@ -58,10 +59,11 @@ export const VALIDATION = {
58
59
  // Timing Constants (in seconds)
59
60
  // =============================================================================
60
61
 
61
- export const TIMING = {
62
- /** Production voting period (14 days) */
62
+ /** Production timing constants (mainnet) */
63
+ export const TIMING_PRODUCTION = {
64
+ /** Voting period (14 days) */
63
65
  VOTING_PERIOD_SECONDS: 1_209_600,
64
- /** Production hold period (7 days) */
66
+ /** Hold period (7 days) */
65
67
  HOLD_PERIOD_SECONDS: 604_800,
66
68
  /** Inactivity timeout (90 days) */
67
69
  INACTIVITY_TIMEOUT_SECONDS: 7_776_000,
@@ -71,14 +73,59 @@ export const TIMING = {
71
73
  REFUND_WINDOW_SECONDS: 1_209_600,
72
74
  /** Pivot withdrawal window (7 days) */
73
75
  PIVOT_WITHDRAWAL_WINDOW_SECONDS: 604_800,
74
- /** Minimum TGE date (15 days from now) */
75
- TGE_MIN_DAYS: 1_296_000,
76
- /** Maximum TGE date (90 days from now) */
77
- TGE_MAX_DAYS: 7_776_000,
78
- /** Post-TGE holdback period (30 days) */
79
- POST_TGE_HOLDBACK_DAYS: 2_592_000,
76
+ /** Early token cooling period (24 hours) */
77
+ EARLY_TOKEN_COOLING_PERIOD: 86_400,
78
+ /** Exit window period (7 days) */
79
+ EXIT_WINDOW_PERIOD: 604_800,
80
+ /** Wallet update timelock (7 days) */
81
+ WALLET_UPDATE_TIMELOCK: 604_800,
82
+ /** Minimum deadline duration (7 days) */
83
+ MIN_DEADLINE_DURATION_SECONDS: 604_800,
84
+ /** Maximum deadline duration (90 days) */
85
+ MAX_DEADLINE_DURATION_SECONDS: 90 * 24 * 60 * 60,
86
+ /** Deadline grace period (90 days) */
87
+ DEADLINE_GRACE_PERIOD_SECONDS: 7_776_000,
80
88
  } as const;
81
89
 
90
+ /** Dev timing constants (localnet/devnet) - matches Solana program dev mode */
91
+ export const TIMING_DEV = {
92
+ /** Voting period (60 seconds) */
93
+ VOTING_PERIOD_SECONDS: 60,
94
+ /** Hold period (1 second) */
95
+ HOLD_PERIOD_SECONDS: 1,
96
+ /** Inactivity timeout (10 seconds) */
97
+ INACTIVITY_TIMEOUT_SECONDS: 10,
98
+ /** Abandonment timeout (60 seconds) */
99
+ ABANDONMENT_TIMEOUT_SECONDS: 60,
100
+ /** Refund window (2 minutes) */
101
+ REFUND_WINDOW_SECONDS: 120,
102
+ /** Pivot withdrawal window (10 seconds) */
103
+ PIVOT_WITHDRAWAL_WINDOW_SECONDS: 10,
104
+ /** Early token cooling period (10 seconds) */
105
+ EARLY_TOKEN_COOLING_PERIOD: 10,
106
+ /** Exit window period (20 seconds) */
107
+ EXIT_WINDOW_PERIOD: 20,
108
+ /** Wallet update timelock (60 seconds) */
109
+ WALLET_UPDATE_TIMELOCK: 60,
110
+ /** Minimum deadline duration (60 seconds) */
111
+ MIN_DEADLINE_DURATION_SECONDS: 60,
112
+ /** Maximum deadline duration (90 days) */
113
+ MAX_DEADLINE_DURATION_SECONDS: 90 * 24 * 60 * 60,
114
+ /** Deadline grace period (5 seconds) */
115
+ DEADLINE_GRACE_PERIOD_SECONDS: 5,
116
+ } as const;
117
+
118
+ /**
119
+ * Get timing constants based on environment
120
+ * @param isDev - Whether to use dev mode constants (localnet/devnet)
121
+ */
122
+ export function getTimingConstants(isDev: boolean = false) {
123
+ return isDev ? TIMING_DEV : TIMING_PRODUCTION;
124
+ }
125
+
126
+ /** @deprecated Use TIMING_PRODUCTION or TIMING_DEV instead */
127
+ export const TIMING = TIMING_PRODUCTION;
128
+
82
129
  // =============================================================================
83
130
  // Tier Configuration Constraints
84
131
  // =============================================================================
package/src/index.ts CHANGED
@@ -22,6 +22,9 @@ export {
22
22
  SEEDS,
23
23
  VALIDATION,
24
24
  TIMING,
25
+ TIMING_PRODUCTION,
26
+ TIMING_DEV,
27
+ getTimingConstants,
25
28
  TIER_CONSTRAINTS,
26
29
  InvestmentTier,
27
30
  TIER_MINIMUMS,
@@ -44,6 +47,7 @@ export {
44
47
  export {
45
48
  getProjectPDA,
46
49
  getEscrowPDA,
50
+ getEscrowTokenAccountPDA,
47
51
  getMilestonePDA,
48
52
  getInvestmentPDA,
49
53
  getVotePDA,
@@ -10,6 +10,7 @@ import { PublicKey, Keypair, SYSVAR_INSTRUCTIONS_PUBKEY, SYSVAR_RENT_PUBKEY, SYS
10
10
  import {
11
11
  getProjectPDA,
12
12
  getEscrowPDA,
13
+ getEscrowTokenAccountPDA,
13
14
  getMilestonePDA,
14
15
  getInvestmentPDA,
15
16
  getVotePDA,
@@ -364,8 +365,9 @@ export async function approveProject(
364
365
  /** USDC mint address (for creating lp_usdc_vault) */
365
366
  usdcMint: PublicKey;
366
367
  },
367
- adminKeypair: Keypair
368
+ admin: PublicKey | Keypair
368
369
  ): Promise<string> {
370
+ const adminPubkey = admin instanceof Keypair ? admin.publicKey : admin;
369
371
  const projectPda = getProjectPDA(args.projectId, program.programId);
370
372
  const tokenomicsPda = getTokenomicsPDA(projectPda, program.programId);
371
373
  const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
@@ -378,13 +380,15 @@ export async function approveProject(
378
380
  const lpUsdcVaultPda = getLpUsdcVaultPDA(projectPda, program.programId);
379
381
  const futureRoundTokenVaultPda = getFutureRoundTokenVaultPDA(projectPda, program.programId);
380
382
  const futureRoundVaultPda = getFutureRoundVaultPDA(projectPda, program.programId);
383
+ const escrowPda = getEscrowPDA(args.projectId, program.programId);
384
+ const escrowTokenAccountPda = getEscrowTokenAccountPDA(projectPda, program.programId);
381
385
 
382
- // Request 400k CUs - this instruction creates 10 accounts + 7 CPIs + 5 events
386
+ // Request 400k CUs - this instruction creates 11 accounts + 7 CPIs + 5 events
383
387
  const computeBudgetIx = ComputeBudgetProgram.setComputeUnitLimit({
384
388
  units: 400_000,
385
389
  });
386
390
 
387
- return getMethods(program)
391
+ let builder = getMethods(program)
388
392
  .approveProject()
389
393
  .accountsPartial({
390
394
  project: projectPda,
@@ -400,12 +404,18 @@ export async function approveProject(
400
404
  futureRoundTokenVault: futureRoundTokenVaultPda,
401
405
  futureRoundVault: futureRoundVaultPda,
402
406
  usdcMint: args.usdcMint,
403
- authority: adminKeypair.publicKey,
404
- payer: adminKeypair.publicKey,
407
+ escrowPda,
408
+ escrowTokenAccount: escrowTokenAccountPda,
409
+ authority: adminPubkey,
410
+ payer: adminPubkey,
405
411
  })
406
- .preInstructions([computeBudgetIx])
407
- .signers([adminKeypair])
408
- .rpc();
412
+ .preInstructions([computeBudgetIx]);
413
+
414
+ if (admin instanceof Keypair) {
415
+ builder = builder.signers([admin]);
416
+ }
417
+
418
+ return builder.rpc();
409
419
  }
410
420
 
411
421
  // =============================================================================
@@ -579,11 +589,14 @@ export async function claimMilestoneFunds(
579
589
  const lpUsdcVaultPda = getLpUsdcVaultPDA(projectPda, program.programId);
580
590
 
581
591
  // For non-final milestones, derive next milestone PDA if not provided
592
+ const isFinal = args.nextMilestoneDeadline.eq(new BN(0));
582
593
  const nextMilestonePda = args.nextMilestonePda ??
583
- (args.nextMilestoneDeadline.gt(new BN(0))
594
+ (!isFinal
584
595
  ? getMilestonePDA(projectPda, args.milestoneIndex + 1, program.programId)
585
596
  : null);
586
597
 
598
+ // Pass null for optional next_milestone on final milestone —
599
+ // Anchor's resolveOptionals converts null → programId sentinel for Option<Account> = None
587
600
  return getMethods(program)
588
601
  .claimMilestoneFunds({ nextMilestoneDeadline: args.nextMilestoneDeadline })
589
602
  .accountsPartial({
@@ -596,7 +609,7 @@ export async function claimMilestoneFunds(
596
609
  tokenVault: tokenVaultPda,
597
610
  tokenomics: tokenomicsPda,
598
611
  lpUsdcVault: lpUsdcVaultPda,
599
- nextMilestone: nextMilestonePda,
612
+ nextMilestone: nextMilestonePda, // null for final → Anchor uses programId sentinel
600
613
  systemProgram: SystemProgram.programId,
601
614
  tokenProgram: TOKEN_PROGRAM_ID,
602
615
  })
package/src/pdas/index.ts CHANGED
@@ -57,6 +57,24 @@ export function getEscrowPDA(projectId: BN | number | string, programId: PublicK
57
57
  return pda;
58
58
  }
59
59
 
60
+ /**
61
+ * Derive Escrow Token Account PDA from project PDA
62
+ *
63
+ * This is the USDC token account owned by the escrow PDA,
64
+ * created during approveProject.
65
+ *
66
+ * @param projectPda - Project account PDA
67
+ * @param programId - Raise program ID
68
+ * @returns Escrow token account PDA
69
+ */
70
+ export function getEscrowTokenAccountPDA(projectPda: PublicKey, programId: PublicKey): PublicKey {
71
+ const [pda] = PublicKey.findProgramAddressSync(
72
+ [Buffer.from(SEEDS.ESCROW_TOKEN), projectPda.toBuffer()],
73
+ programId
74
+ );
75
+ return pda;
76
+ }
77
+
60
78
  /**
61
79
  * Derive Milestone PDA from project PDA and milestone index
62
80
  *