@zemyth/raise-sdk 0.1.1 → 0.1.3

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 (47) hide show
  1. package/README.md +11 -9
  2. package/dist/accounts/index.cjs +531 -3
  3. package/dist/accounts/index.cjs.map +1 -1
  4. package/dist/accounts/index.d.cts +307 -2
  5. package/dist/accounts/index.d.ts +307 -2
  6. package/dist/accounts/index.js +503 -4
  7. package/dist/accounts/index.js.map +1 -1
  8. package/dist/constants/index.cjs +41 -3
  9. package/dist/constants/index.cjs.map +1 -1
  10. package/dist/constants/index.d.cts +38 -3
  11. package/dist/constants/index.d.ts +38 -3
  12. package/dist/constants/index.js +40 -4
  13. package/dist/constants/index.js.map +1 -1
  14. package/dist/index.cjs +2297 -361
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +566 -7
  17. package/dist/index.d.ts +566 -7
  18. package/dist/index.js +2279 -379
  19. package/dist/index.js.map +1 -1
  20. package/dist/instructions/index.cjs +783 -40
  21. package/dist/instructions/index.cjs.map +1 -1
  22. package/dist/instructions/index.d.cts +492 -6
  23. package/dist/instructions/index.d.ts +492 -6
  24. package/dist/instructions/index.js +762 -42
  25. package/dist/instructions/index.js.map +1 -1
  26. package/dist/pdas/index.cjs +163 -1
  27. package/dist/pdas/index.cjs.map +1 -1
  28. package/dist/pdas/index.d.cts +131 -1
  29. package/dist/pdas/index.d.ts +131 -1
  30. package/dist/pdas/index.js +151 -2
  31. package/dist/pdas/index.js.map +1 -1
  32. package/dist/types/index.cjs +9 -0
  33. package/dist/types/index.cjs.map +1 -1
  34. package/dist/types/index.d.cts +586 -3
  35. package/dist/types/index.d.ts +586 -3
  36. package/dist/types/index.js +9 -1
  37. package/dist/types/index.js.map +1 -1
  38. package/package.json +5 -3
  39. package/src/__tests__/dynamic-tokenomics.test.ts +358 -0
  40. package/src/accounts/index.ts +852 -1
  41. package/src/client.ts +1130 -1
  42. package/src/constants/index.ts +48 -2
  43. package/src/index.ts +58 -0
  44. package/src/instructions/index.ts +1383 -40
  45. package/src/pdas/index.ts +346 -0
  46. package/src/types/index.ts +698 -2
  47. package/src/utils/index.ts +90 -0
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
- import { PublicKey, SystemProgram, SYSVAR_INSTRUCTIONS_PUBKEY, SYSVAR_RENT_PUBKEY, ComputeBudgetProgram, SYSVAR_CLOCK_PUBKEY } from '@solana/web3.js';
2
- export { Connection, Keypair, PublicKey } from '@solana/web3.js';
3
1
  import { BN, AnchorError } from '@coral-xyz/anchor';
4
2
  export { BN } from '@coral-xyz/anchor';
3
+ import { PublicKey, ComputeBudgetProgram, SystemProgram, SYSVAR_INSTRUCTIONS_PUBKEY, SYSVAR_RENT_PUBKEY, SYSVAR_CLOCK_PUBKEY } from '@solana/web3.js';
4
+ export { Connection, Keypair, PublicKey } from '@solana/web3.js';
5
5
  import { getAssociatedTokenAddressSync, TOKEN_PROGRAM_ID, ASSOCIATED_TOKEN_PROGRAM_ID } from '@solana/spl-token';
6
6
 
7
- // src/pdas/index.ts
7
+ // src/client.ts
8
8
 
9
9
  // src/constants/index.ts
10
10
  var SEEDS = {
@@ -20,7 +20,13 @@ var SEEDS = {
20
20
  SCAM_REPORT: "scam_report",
21
21
  ADMIN_CONFIG: "admin-config",
22
22
  NFT_MINT: "nft_mint",
23
- AUTHORITY: "authority"
23
+ AUTHORITY: "authority",
24
+ FUTURE_ROUND_VAULT: "future_round_vault",
25
+ FUTURE_ROUND_STATE: "future_round_state",
26
+ // Multi-Round Fundraising seeds
27
+ FUNDING_ROUND: "funding_round",
28
+ ROUND_ESCROW: "round_escrow",
29
+ INVESTOR_MS_VESTING: "investor_ms_vesting"
24
30
  };
25
31
  var VALIDATION = {
26
32
  /** Minimum number of milestones per project */
@@ -146,9 +152,9 @@ var GOVERNANCE = {
146
152
  };
147
153
  var NFT = {
148
154
  /** NFT symbol */
149
- SYMBOL: "SNI",
155
+ SYMBOL: "ZRI",
150
156
  /** NFT name prefix */
151
- NAME_PREFIX: "Raise Investment #",
157
+ NAME_PREFIX: "Zemyth Raise Investment #",
152
158
  /** Royalty basis points (2%) */
153
159
  ROYALTY_BASIS_POINTS: 200
154
160
  };
@@ -160,6 +166,26 @@ var USDC = {
160
166
  /** Convert lamports to USDC */
161
167
  fromAmount: (lamports) => Number(lamports) / 10 ** 6
162
168
  };
169
+ var TOKENOMICS = {
170
+ /** Minimum investor allocation (20%) */
171
+ MIN_INVESTOR_ALLOCATION_BPS: 2e3,
172
+ /** Minimum founder allocation (5%) if > 0 */
173
+ MIN_FOUNDER_ALLOCATION_BPS: 500,
174
+ /** Minimum LP token allocation (5%) */
175
+ MIN_LP_TOKEN_ALLOCATION_BPS: 500,
176
+ /** Minimum LP USDC allocation (5%) */
177
+ MIN_LP_USDC_BPS: 500,
178
+ /** Minimum Zemyth allocation (1%) */
179
+ MIN_ZEMYTH_ALLOCATION_BPS: 100,
180
+ /** Default Zemyth allocation (1%) */
181
+ DEFAULT_ZEMYTH_ALLOCATION_BPS: 100,
182
+ /** Minimum future round allocation (10%) if > 0 */
183
+ MIN_FUTURE_ROUND_ALLOCATION_BPS: 1e3,
184
+ /** Maximum token symbol length */
185
+ MAX_TOKEN_SYMBOL_LEN: 8,
186
+ /** Total allocation must sum to this (100% = 10000 bps) */
187
+ TOTAL_ALLOCATION_BPS: 1e4
188
+ };
163
189
 
164
190
  // src/pdas/index.ts
165
191
  function ensureBN(value) {
@@ -353,8 +379,149 @@ function getFounderVestingPDA(projectPda, programId) {
353
379
  );
354
380
  return pda;
355
381
  }
356
-
357
- // src/accounts/index.ts
382
+ function getAllocationProposalPDA(projectPda, proposalIndex, programId) {
383
+ const [pda] = PublicKey.findProgramAddressSync(
384
+ [
385
+ Buffer.from("allocation_proposal"),
386
+ projectPda.toBuffer(),
387
+ Buffer.from([proposalIndex])
388
+ ],
389
+ programId
390
+ );
391
+ return pda;
392
+ }
393
+ function getAllocationVotePDA(proposalPda, nftMint, programId) {
394
+ const [pda] = PublicKey.findProgramAddressSync(
395
+ [
396
+ Buffer.from("allocation_vote"),
397
+ proposalPda.toBuffer(),
398
+ nftMint.toBuffer()
399
+ ],
400
+ programId
401
+ );
402
+ return pda;
403
+ }
404
+ function getSubAllocationVestingPDA(projectPda, subAllocationId, programId) {
405
+ const [pda] = PublicKey.findProgramAddressSync(
406
+ [
407
+ Buffer.from("sub_allocation_vesting"),
408
+ projectPda.toBuffer(),
409
+ Buffer.from([subAllocationId])
410
+ ],
411
+ programId
412
+ );
413
+ return pda;
414
+ }
415
+ function getInvestorMilestoneVestingPDA(projectPda, milestoneIndex, investmentPda, programId) {
416
+ const [pda] = PublicKey.findProgramAddressSync(
417
+ [
418
+ Buffer.from("investor_ms_vesting"),
419
+ projectPda.toBuffer(),
420
+ Buffer.from([milestoneIndex]),
421
+ investmentPda.toBuffer()
422
+ ],
423
+ programId
424
+ );
425
+ return pda;
426
+ }
427
+ function getFounderMilestoneVestingPDA(projectPda, milestoneIndex, programId) {
428
+ const [pda] = PublicKey.findProgramAddressSync(
429
+ [
430
+ Buffer.from("founder_ms_vesting"),
431
+ projectPda.toBuffer(),
432
+ Buffer.from([milestoneIndex])
433
+ ],
434
+ programId
435
+ );
436
+ return pda;
437
+ }
438
+ function getFutureRoundTokenVaultPDA(projectPda, programId) {
439
+ const [pda] = PublicKey.findProgramAddressSync(
440
+ [Buffer.from(SEEDS.FUTURE_ROUND_VAULT), projectPda.toBuffer()],
441
+ programId
442
+ );
443
+ return pda;
444
+ }
445
+ function getFutureRoundVaultPDA(projectPda, programId) {
446
+ const [pda] = PublicKey.findProgramAddressSync(
447
+ [Buffer.from(SEEDS.FUTURE_ROUND_STATE), projectPda.toBuffer()],
448
+ programId
449
+ );
450
+ return pda;
451
+ }
452
+ function getFundingRoundPDA(projectPda, roundNumber, programId) {
453
+ const [pda] = PublicKey.findProgramAddressSync(
454
+ [
455
+ Buffer.from(SEEDS.FUNDING_ROUND),
456
+ projectPda.toBuffer(),
457
+ Buffer.from([roundNumber])
458
+ ],
459
+ programId
460
+ );
461
+ return pda;
462
+ }
463
+ function getRoundEscrowPDA(projectPda, roundNumber, programId) {
464
+ const [pda] = PublicKey.findProgramAddressSync(
465
+ [
466
+ Buffer.from(SEEDS.ROUND_ESCROW),
467
+ projectPda.toBuffer(),
468
+ Buffer.from([roundNumber])
469
+ ],
470
+ programId
471
+ );
472
+ return pda;
473
+ }
474
+ function getRoundMilestonePDA(projectPda, roundNumber, milestoneIndex, programId) {
475
+ const [pda] = PublicKey.findProgramAddressSync(
476
+ [
477
+ Buffer.from(SEEDS.MILESTONE),
478
+ projectPda.toBuffer(),
479
+ Buffer.from([roundNumber]),
480
+ Buffer.from([milestoneIndex])
481
+ ],
482
+ programId
483
+ );
484
+ return pda;
485
+ }
486
+ function getRoundNftMintPDA(projectId, roundNumber, investor, investmentCount, programId) {
487
+ const projectIdBN = ensureBN(projectId);
488
+ const countBN = ensureBN(investmentCount);
489
+ return PublicKey.findProgramAddressSync(
490
+ [
491
+ Buffer.from(SEEDS.NFT_MINT),
492
+ projectIdBN.toArrayLike(Buffer, "le", 8),
493
+ Buffer.from([roundNumber]),
494
+ investor.toBuffer(),
495
+ countBN.toArrayLike(Buffer, "le", 8)
496
+ ],
497
+ programId
498
+ );
499
+ }
500
+ function getRoundInvestmentPDA(projectPda, roundNumber, nftMint, programId) {
501
+ const [pda] = PublicKey.findProgramAddressSync(
502
+ [
503
+ Buffer.from(SEEDS.INVESTMENT),
504
+ projectPda.toBuffer(),
505
+ Buffer.from([roundNumber]),
506
+ nftMint.toBuffer()
507
+ ],
508
+ programId
509
+ );
510
+ return pda;
511
+ }
512
+ function getRoundInvestorMilestoneVestingPDA(projectPda, roundNumber, milestoneIndex, investmentPda, programId) {
513
+ const [pda] = PublicKey.findProgramAddressSync(
514
+ [
515
+ Buffer.from(SEEDS.INVESTOR_MS_VESTING),
516
+ projectPda.toBuffer(),
517
+ Buffer.from([roundNumber]),
518
+ Buffer.from([milestoneIndex]),
519
+ investmentPda.toBuffer()
520
+ ],
521
+ programId
522
+ );
523
+ return pda;
524
+ }
358
525
  function getAccountNamespace(program) {
359
526
  return program.account;
360
527
  }
@@ -500,6 +667,18 @@ async function fetchAdminConfig(program) {
500
667
  const adminConfigPda = getAdminConfigPDA(program.programId);
501
668
  return await getAccountNamespace(program).adminConfig.fetch(adminConfigPda);
502
669
  }
670
+ async function fetchTokenVault(program, projectId) {
671
+ try {
672
+ const projectPda = getProjectPDA(projectId, program.programId);
673
+ const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
674
+ return await getAccountNamespace(program).tokenVault.fetch(tokenVaultPda);
675
+ } catch (error) {
676
+ if (error instanceof Error && error.message?.includes("Account does not exist")) {
677
+ return null;
678
+ }
679
+ throw error;
680
+ }
681
+ }
503
682
  async function accountExists(program, accountType, pda) {
504
683
  try {
505
684
  await program.account[accountType].fetch(pda);
@@ -508,107 +687,468 @@ async function accountExists(program, accountType, pda) {
508
687
  return false;
509
688
  }
510
689
  }
511
- var TOKEN_METADATA_PROGRAM_ID = new PublicKey("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s");
512
- function ensurePublicKey(value) {
513
- if (value instanceof PublicKey) {
514
- return value;
690
+ async function fetchTokenomics(program, projectId) {
691
+ try {
692
+ const projectPda = getProjectPDA(projectId, program.programId);
693
+ const tokenomicsPda = getTokenomicsPDA(projectPda, program.programId);
694
+ return await getAccountNamespace(program).tokenomics.fetch(tokenomicsPda);
695
+ } catch (error) {
696
+ if (error instanceof Error && error.message?.includes("Account does not exist")) {
697
+ return null;
698
+ }
699
+ throw error;
515
700
  }
516
- return new PublicKey(String(value));
517
- }
518
- function getMethods(program) {
519
- return program.methods;
520
701
  }
521
- function getAccountNamespace2(program) {
522
- return program.account;
702
+ async function fetchAllocationProposal(program, projectId, proposalIndex) {
703
+ try {
704
+ const projectPda = getProjectPDA(projectId, program.programId);
705
+ const proposalPda = getAllocationProposalPDA(projectPda, proposalIndex, program.programId);
706
+ return await getAccountNamespace(program).allocationProposal.fetch(proposalPda);
707
+ } catch (error) {
708
+ if (error instanceof Error && error.message?.includes("Account does not exist")) {
709
+ return null;
710
+ }
711
+ throw error;
712
+ }
523
713
  }
524
- async function initializeAdmin(program, admin, payer) {
525
- return getMethods(program).initializeAdmin().accounts({
526
- admin,
527
- payer
528
- }).rpc();
714
+ async function fetchAllAllocationProposals(program, projectId) {
715
+ const projectPda = getProjectPDA(projectId, program.programId);
716
+ const proposals = await getAccountNamespace(program).allocationProposal.all([
717
+ {
718
+ memcmp: {
719
+ offset: 8,
720
+ // Skip discriminator
721
+ bytes: projectPda.toBase58()
722
+ }
723
+ }
724
+ ]);
725
+ return proposals.map((p) => ({
726
+ publicKey: p.publicKey,
727
+ account: p.account
728
+ }));
529
729
  }
530
- async function transferAdmin(program, adminKeypair, newAdmin) {
531
- return getMethods(program).transferAdmin().accounts({
532
- authority: adminKeypair.publicKey,
533
- newAdmin
534
- }).signers([adminKeypair]).rpc();
730
+ async function fetchAllocationVote(program, projectId, proposalIndex, nftMint) {
731
+ try {
732
+ const projectPda = getProjectPDA(projectId, program.programId);
733
+ const proposalPda = getAllocationProposalPDA(projectPda, proposalIndex, program.programId);
734
+ const votePda = getAllocationVotePDA(proposalPda, nftMint, program.programId);
735
+ return await getAccountNamespace(program).allocationVote.fetch(votePda);
736
+ } catch (error) {
737
+ if (error instanceof Error && error.message?.includes("Account does not exist")) {
738
+ return null;
739
+ }
740
+ throw error;
741
+ }
535
742
  }
536
- async function acceptAdmin(program, newAuthority) {
537
- return getMethods(program).acceptAdmin().accounts({
538
- newAuthority
539
- }).rpc();
743
+ async function fetchSubAllocationVesting(program, projectId, subAllocationId) {
744
+ try {
745
+ const projectPda = getProjectPDA(projectId, program.programId);
746
+ const vestingPda = getSubAllocationVestingPDA(projectPda, subAllocationId, program.programId);
747
+ return await getAccountNamespace(program).subAllocationVesting.fetch(vestingPda);
748
+ } catch (error) {
749
+ if (error instanceof Error && error.message?.includes("Account does not exist")) {
750
+ return null;
751
+ }
752
+ throw error;
753
+ }
540
754
  }
541
- function symbolToBytes(symbol) {
542
- const bytes = new Array(8).fill(0);
543
- const chars = symbol.toUpperCase().slice(0, 8);
544
- for (let i = 0; i < chars.length; i++) {
545
- bytes[i] = chars.charCodeAt(i);
755
+ async function fetchInvestorMilestoneVesting(program, projectId, milestoneIndex, nftMint) {
756
+ try {
757
+ const projectPda = getProjectPDA(projectId, program.programId);
758
+ const investmentPda = getInvestmentPDA(projectPda, nftMint, program.programId);
759
+ const vestingPda = getInvestorMilestoneVestingPDA(projectPda, milestoneIndex, investmentPda, program.programId);
760
+ return await getAccountNamespace(program).investorMilestoneVesting.fetch(vestingPda);
761
+ } catch (error) {
762
+ if (error instanceof Error && error.message?.includes("Account does not exist")) {
763
+ return null;
764
+ }
765
+ throw error;
546
766
  }
547
- return bytes;
548
767
  }
549
- var MIN_DEADLINE_DURATION_SECONDS_PROD = 604800;
550
- var MIN_DEADLINE_DURATION_SECONDS_DEV = 60;
551
- var MAX_DEADLINE_DURATION_SECONDS = 31536e3;
552
- function calculateDeadline(daysFromNow, isDev = false) {
553
- const nowSeconds = Math.floor(Date.now() / 1e3);
554
- const minDuration = isDev ? MIN_DEADLINE_DURATION_SECONDS_DEV : MIN_DEADLINE_DURATION_SECONDS_PROD;
555
- const daysInSeconds = daysFromNow * 24 * 60 * 60;
556
- const deadlineSeconds = nowSeconds + Math.max(daysInSeconds, minDuration);
557
- const maxDeadline = nowSeconds + MAX_DEADLINE_DURATION_SECONDS;
558
- return new BN(Math.min(deadlineSeconds, maxDeadline));
768
+ async function fetchFounderMilestoneVesting(program, projectId, milestoneIndex) {
769
+ try {
770
+ const projectPda = getProjectPDA(projectId, program.programId);
771
+ const vestingPda = getFounderMilestoneVestingPDA(projectPda, milestoneIndex, program.programId);
772
+ return await getAccountNamespace(program).founderMilestoneVesting.fetch(vestingPda);
773
+ } catch (error) {
774
+ if (error instanceof Error && error.message?.includes("Account does not exist")) {
775
+ return null;
776
+ }
777
+ throw error;
778
+ }
559
779
  }
560
- function minDeadline(isDev = false) {
561
- const nowSeconds = Math.floor(Date.now() / 1e3);
562
- const minDuration = isDev ? MIN_DEADLINE_DURATION_SECONDS_DEV : MIN_DEADLINE_DURATION_SECONDS_PROD;
563
- return new BN(nowSeconds + minDuration + 1);
780
+ var EARLY_TOKEN_COOLING_PERIOD_SECONDS = 86400;
781
+ var EARLY_TOKEN_COOLING_PERIOD_SECONDS_DEV = 10;
782
+ var EARLY_TOKEN_RELEASE_BPS = 500;
783
+ function canClaimEarlyTokens(investment, currentTimestamp, isDev = false) {
784
+ const now = currentTimestamp ?? Math.floor(Date.now() / 1e3);
785
+ const coolingPeriod = isDev ? EARLY_TOKEN_COOLING_PERIOD_SECONDS_DEV : EARLY_TOKEN_COOLING_PERIOD_SECONDS;
786
+ if (investment.earlyTokensClaimed) {
787
+ return { canClaim: false, reason: "Early tokens already claimed" };
788
+ }
789
+ if (investment.votingRightsActive === false) {
790
+ return { canClaim: false, reason: "Voting rights have been revoked" };
791
+ }
792
+ if (investment.withdrawnFromPivot === true) {
793
+ return { canClaim: false, reason: "Investment has been withdrawn from pivot" };
794
+ }
795
+ const investedAt = typeof investment.investedAt === "number" ? investment.investedAt : investment.investedAt.toNumber();
796
+ const coolingEndTime = investedAt + coolingPeriod;
797
+ if (now < coolingEndTime) {
798
+ const timeRemaining2 = coolingEndTime - now;
799
+ return {
800
+ canClaim: false,
801
+ reason: `Cooling period not expired. ${formatTimeRemaining(timeRemaining2)} remaining.`,
802
+ timeRemainingSeconds: timeRemaining2
803
+ };
804
+ }
805
+ return { canClaim: true };
564
806
  }
565
- function validateDeadline(deadline, isDev = false) {
566
- const nowSeconds = Math.floor(Date.now() / 1e3);
567
- const deadlineSeconds = deadline.toNumber();
568
- const minDuration = isDev ? MIN_DEADLINE_DURATION_SECONDS_DEV : MIN_DEADLINE_DURATION_SECONDS_PROD;
569
- const minDeadline2 = nowSeconds + minDuration;
570
- const maxDeadline = nowSeconds + MAX_DEADLINE_DURATION_SECONDS;
571
- if (deadlineSeconds < minDeadline2) {
572
- const minDays = isDev ? "60 seconds" : "7 days";
807
+ function canClaimFounderEarlyTokens(project) {
808
+ if (project.founderEarlyTokensClaimed) {
809
+ return { canClaim: false, reason: "Founder early tokens already claimed" };
810
+ }
811
+ const stateStr = getProjectStateString(project.state);
812
+ const validStates = ["funded", "inProgress", "completed"];
813
+ if (!validStates.includes(stateStr)) {
573
814
  return {
574
- valid: false,
575
- error: `Deadline must be at least ${minDays} from now`
815
+ canClaim: false,
816
+ reason: `Project must be in Funded, InProgress, or Completed state. Current state: ${stateStr}`
576
817
  };
577
818
  }
578
- if (deadlineSeconds > maxDeadline) {
819
+ return { canClaim: true };
820
+ }
821
+ function canClaimFounderMilestoneTokens(milestone) {
822
+ const stateStr = getMilestoneStateString(milestone.state);
823
+ if (stateStr !== "unlocked") {
579
824
  return {
580
- valid: false,
581
- error: "Deadline must be within 1 year from now"
825
+ canClaim: false,
826
+ reason: `Milestone must be in Unlocked state. Current state: ${stateStr}`
582
827
  };
583
828
  }
584
- return { valid: true };
829
+ return { canClaim: true };
585
830
  }
586
- async function initializeProject(program, args, founder) {
587
- return getMethods(program).initializeProject({
588
- projectId: args.projectId,
589
- fundingGoal: args.fundingGoal,
590
- metadataUri: args.metadataUri,
591
- tiers: args.tiers,
592
- tokenomics: {
593
- tokenSymbol: args.tokenomics.tokenSymbol,
594
- totalSupply: args.tokenomics.totalSupply,
595
- investorAllocationBps: args.tokenomics.investorAllocationBps,
596
- lpTokenAllocationBps: args.tokenomics.lpTokenAllocationBps,
597
- lpUsdcAllocationBps: args.tokenomics.lpUsdcAllocationBps,
598
- founderAllocationBps: args.tokenomics.founderAllocationBps ?? null,
599
- treasuryAllocationBps: args.tokenomics.treasuryAllocationBps ?? null,
600
- founderWallet: args.tokenomics.founderWallet ?? null,
831
+ function requiresBurnForRefund(project, investment) {
832
+ const isFullRefund = project.cumulativePercentage === 0;
833
+ const requiresBurn = isFullRefund && investment.earlyTokensClaimed;
834
+ if (!requiresBurn) {
835
+ return { requiresBurn: false, burnAmount: 0 };
836
+ }
837
+ const burnAmount = typeof investment.earlyTokensAmount === "number" ? investment.earlyTokensAmount : investment.earlyTokensAmount.toNumber();
838
+ return { requiresBurn: true, burnAmount };
839
+ }
840
+ function calculateEarlyTokenAmount(tokensAllocated) {
841
+ const allocated = typeof tokensAllocated === "number" ? new BN(tokensAllocated) : tokensAllocated;
842
+ return allocated.muln(EARLY_TOKEN_RELEASE_BPS).divn(1e4);
843
+ }
844
+ function calculateRemainingAllocation(tokensAllocated) {
845
+ const allocated = typeof tokensAllocated === "number" ? new BN(tokensAllocated) : tokensAllocated;
846
+ const remainingBps = 1e4 - EARLY_TOKEN_RELEASE_BPS;
847
+ return allocated.muln(remainingBps).divn(1e4);
848
+ }
849
+ function formatTimeRemaining(seconds) {
850
+ if (seconds <= 0) return "0 seconds";
851
+ const hours = Math.floor(seconds / 3600);
852
+ const minutes = Math.floor(seconds % 3600 / 60);
853
+ const secs = seconds % 60;
854
+ const parts = [];
855
+ if (hours > 0) parts.push(`${hours}h`);
856
+ if (minutes > 0) parts.push(`${minutes}m`);
857
+ if (secs > 0 && hours === 0) parts.push(`${secs}s`);
858
+ return parts.join(" ") || "0 seconds";
859
+ }
860
+ function getProjectStateString(state) {
861
+ if (typeof state === "object" && state !== null) {
862
+ const keys = Object.keys(state);
863
+ return keys[0]?.toLowerCase() ?? "unknown";
864
+ }
865
+ return "unknown";
866
+ }
867
+ function getMilestoneStateString(state) {
868
+ if (typeof state === "object" && state !== null) {
869
+ const keys = Object.keys(state);
870
+ return keys[0]?.toLowerCase() ?? "unknown";
871
+ }
872
+ return "unknown";
873
+ }
874
+ async function fetchFundingRound(program, projectId, roundNumber) {
875
+ try {
876
+ const projectPda = getProjectPDA(projectId, program.programId);
877
+ const fundingRoundPda = getFundingRoundPDA(projectPda, roundNumber, program.programId);
878
+ return await getAccountNamespace(program).fundingRound.fetch(fundingRoundPda);
879
+ } catch (error) {
880
+ if (error instanceof Error && error.message?.includes("Account does not exist")) {
881
+ return null;
882
+ }
883
+ throw error;
884
+ }
885
+ }
886
+ async function fetchAllFundingRounds(program, projectId) {
887
+ const projectPda = getProjectPDA(projectId, program.programId);
888
+ const rounds = await getAccountNamespace(program).fundingRound.all([
889
+ {
890
+ memcmp: {
891
+ offset: 8,
892
+ // Skip discriminator
893
+ bytes: projectPda.toBase58()
894
+ }
895
+ }
896
+ ]);
897
+ return rounds.map((r) => ({
898
+ publicKey: r.publicKey,
899
+ account: r.account
900
+ }));
901
+ }
902
+ async function fetchRoundMilestone(program, projectId, roundNumber, milestoneIndex) {
903
+ try {
904
+ const projectPda = getProjectPDA(projectId, program.programId);
905
+ const milestonePda = getRoundMilestonePDA(projectPda, roundNumber, milestoneIndex, program.programId);
906
+ return await getAccountNamespace(program).milestone.fetch(milestonePda);
907
+ } catch (error) {
908
+ if (error instanceof Error && error.message?.includes("Account does not exist")) {
909
+ return null;
910
+ }
911
+ throw error;
912
+ }
913
+ }
914
+ async function fetchRoundInvestment(program, projectId, roundNumber, nftMint) {
915
+ try {
916
+ const projectPda = getProjectPDA(projectId, program.programId);
917
+ const investmentPda = getRoundInvestmentPDA(projectPda, roundNumber, nftMint, program.programId);
918
+ return await getAccountNamespace(program).investment.fetch(investmentPda);
919
+ } catch (error) {
920
+ if (error instanceof Error && error.message?.includes("Account does not exist")) {
921
+ return null;
922
+ }
923
+ throw error;
924
+ }
925
+ }
926
+ async function fetchRoundInvestorMilestoneVesting(program, projectId, roundNumber, milestoneIndex, nftMint) {
927
+ try {
928
+ const projectPda = getProjectPDA(projectId, program.programId);
929
+ const investmentPda = getRoundInvestmentPDA(projectPda, roundNumber, nftMint, program.programId);
930
+ const vestingPda = getRoundInvestorMilestoneVestingPDA(
931
+ projectPda,
932
+ roundNumber,
933
+ milestoneIndex,
934
+ investmentPda,
935
+ program.programId
936
+ );
937
+ return await getAccountNamespace(program).investorMilestoneVesting.fetch(vestingPda);
938
+ } catch (error) {
939
+ if (error instanceof Error && error.message?.includes("Account does not exist")) {
940
+ return null;
941
+ }
942
+ throw error;
943
+ }
944
+ }
945
+ async function fetchFutureRoundVault(program, projectId) {
946
+ try {
947
+ const projectPda = getProjectPDA(projectId, program.programId);
948
+ const vaultPda = getFutureRoundVaultPDA(projectPda, program.programId);
949
+ return await getAccountNamespace(program).futureRoundVault.fetch(vaultPda);
950
+ } catch (error) {
951
+ if (error instanceof Error && error.message?.includes("Account does not exist")) {
952
+ return null;
953
+ }
954
+ throw error;
955
+ }
956
+ }
957
+ function canClaimRoundEarlyTokens(investment, currentTimestamp, isDev = false) {
958
+ if (investment.roundNumber < 2) {
959
+ return { canClaim: false, reason: "R1 investments use claim_investor_early_tokens instruction" };
960
+ }
961
+ return canClaimEarlyTokens(investment, currentTimestamp, isDev);
962
+ }
963
+ function isR1FullyFunded(project) {
964
+ const raised = typeof project.totalRaised === "number" ? new BN(project.totalRaised) : project.totalRaised;
965
+ const goal = typeof project.fundingGoal === "number" ? new BN(project.fundingGoal) : project.fundingGoal;
966
+ return raised.gte(goal);
967
+ }
968
+ function isFundingRoundFullyFunded(fundingRound) {
969
+ const stateStr = getRoundStateString(fundingRound.state);
970
+ return ["funded", "inProgress", "inprogress", "completed"].includes(stateStr);
971
+ }
972
+ async function isRoundFullyFunded(program, projectId, roundNumber) {
973
+ if (roundNumber === 1) {
974
+ const project = await fetchProject(program, projectId);
975
+ if (!project) return false;
976
+ return isR1FullyFunded(project);
977
+ } else {
978
+ const fundingRound = await fetchFundingRound(program, projectId, roundNumber);
979
+ if (!fundingRound) return false;
980
+ return isFundingRoundFullyFunded(fundingRound);
981
+ }
982
+ }
983
+ async function canOpenNextRound(program, projectId) {
984
+ const project = await fetchProject(program, projectId);
985
+ if (!project) {
986
+ return { canOpen: false, reason: "Project not found" };
987
+ }
988
+ const projectState = getProjectStateString(project.state);
989
+ if (!["inProgress", "inprogress", "completed"].includes(projectState)) {
990
+ return {
991
+ canOpen: false,
992
+ reason: `Project must be in InProgress or Completed state. Current: ${projectState}`
993
+ };
994
+ }
995
+ if (projectState !== "completed" && project.milestonesPassed === 0) {
996
+ return {
997
+ canOpen: false,
998
+ reason: "At least one milestone must pass before opening next round"
999
+ };
1000
+ }
1001
+ if (project.activeRound !== 0) {
1002
+ return {
1003
+ canOpen: false,
1004
+ reason: `Round ${project.activeRound} is already active`
1005
+ };
1006
+ }
1007
+ const currentRound = project.roundCount;
1008
+ const isCurrentFunded = await isRoundFullyFunded(program, projectId, currentRound);
1009
+ if (!isCurrentFunded) {
1010
+ return {
1011
+ canOpen: false,
1012
+ reason: `Current round ${currentRound} must be fully funded before opening next round`
1013
+ };
1014
+ }
1015
+ const tokenomics = await fetchTokenomics(program, projectId);
1016
+ if (!tokenomics) {
1017
+ return { canOpen: false, reason: "Tokenomics not found" };
1018
+ }
1019
+ if (tokenomics.futureRoundAllocationBps === 0) {
1020
+ return {
1021
+ canOpen: false,
1022
+ reason: "No future round allocation configured"
1023
+ };
1024
+ }
1025
+ const remainingAllocation = tokenomics.futureRoundAllocationBps - (tokenomics.usedFutureRoundBps || 0);
1026
+ if (remainingAllocation <= 0) {
1027
+ return {
1028
+ canOpen: false,
1029
+ reason: "Future round allocation pool exhausted"
1030
+ };
1031
+ }
1032
+ return {
1033
+ canOpen: true,
1034
+ nextRoundNumber: currentRound + 1
1035
+ };
1036
+ }
1037
+ function getRemainingFutureRoundAllocation(tokenomics) {
1038
+ return tokenomics.futureRoundAllocationBps - (tokenomics.usedFutureRoundBps || 0);
1039
+ }
1040
+ function getRoundStateString(state) {
1041
+ if (typeof state === "object" && state !== null) {
1042
+ const keys = Object.keys(state);
1043
+ return keys[0]?.toLowerCase() ?? "unknown";
1044
+ }
1045
+ return "unknown";
1046
+ }
1047
+ var TOKEN_METADATA_PROGRAM_ID = new PublicKey("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s");
1048
+ function ensurePublicKey(value) {
1049
+ if (value instanceof PublicKey) {
1050
+ return value;
1051
+ }
1052
+ return new PublicKey(String(value));
1053
+ }
1054
+ function getMethods(program) {
1055
+ return program.methods;
1056
+ }
1057
+ function getAccountNamespace2(program) {
1058
+ return program.account;
1059
+ }
1060
+ async function initializeAdmin(program, admin, payer) {
1061
+ return getMethods(program).initializeAdmin().accountsPartial({
1062
+ admin,
1063
+ payer
1064
+ }).rpc();
1065
+ }
1066
+ async function transferAdmin(program, adminKeypair, newAdmin) {
1067
+ return getMethods(program).transferAdmin().accountsPartial({
1068
+ authority: adminKeypair.publicKey,
1069
+ newAdmin
1070
+ }).signers([adminKeypair]).rpc();
1071
+ }
1072
+ async function acceptAdmin(program, newAuthority) {
1073
+ return getMethods(program).acceptAdmin().accountsPartial({
1074
+ newAuthority
1075
+ }).rpc();
1076
+ }
1077
+ function symbolToBytes(symbol) {
1078
+ const bytes = new Array(8).fill(0);
1079
+ const chars = symbol.toUpperCase().slice(0, 8);
1080
+ for (let i = 0; i < chars.length; i++) {
1081
+ bytes[i] = chars.charCodeAt(i);
1082
+ }
1083
+ return bytes;
1084
+ }
1085
+ var MIN_DEADLINE_DURATION_SECONDS_PROD = 604800;
1086
+ var MIN_DEADLINE_DURATION_SECONDS_DEV = 60;
1087
+ var MAX_DEADLINE_DURATION_SECONDS = 31536e3;
1088
+ function calculateDeadline(daysFromNow, isDev = false) {
1089
+ const nowSeconds = Math.floor(Date.now() / 1e3);
1090
+ const minDuration = isDev ? MIN_DEADLINE_DURATION_SECONDS_DEV : MIN_DEADLINE_DURATION_SECONDS_PROD;
1091
+ const daysInSeconds = daysFromNow * 24 * 60 * 60;
1092
+ const deadlineSeconds = nowSeconds + Math.max(daysInSeconds, minDuration);
1093
+ const maxDeadline = nowSeconds + MAX_DEADLINE_DURATION_SECONDS;
1094
+ return new BN(Math.min(deadlineSeconds, maxDeadline));
1095
+ }
1096
+ function minDeadline(isDev = false) {
1097
+ const nowSeconds = Math.floor(Date.now() / 1e3);
1098
+ const minDuration = isDev ? MIN_DEADLINE_DURATION_SECONDS_DEV : MIN_DEADLINE_DURATION_SECONDS_PROD;
1099
+ return new BN(nowSeconds + minDuration + 1);
1100
+ }
1101
+ function validateDeadline(deadline, isDev = false) {
1102
+ const nowSeconds = Math.floor(Date.now() / 1e3);
1103
+ const deadlineSeconds = deadline.toNumber();
1104
+ const minDuration = isDev ? MIN_DEADLINE_DURATION_SECONDS_DEV : MIN_DEADLINE_DURATION_SECONDS_PROD;
1105
+ const minDeadline2 = nowSeconds + minDuration;
1106
+ const maxDeadline = nowSeconds + MAX_DEADLINE_DURATION_SECONDS;
1107
+ if (deadlineSeconds < minDeadline2) {
1108
+ const minDays = isDev ? "60 seconds" : "7 days";
1109
+ return {
1110
+ valid: false,
1111
+ error: `Deadline must be at least ${minDays} from now`
1112
+ };
1113
+ }
1114
+ if (deadlineSeconds > maxDeadline) {
1115
+ return {
1116
+ valid: false,
1117
+ error: "Deadline must be within 1 year from now"
1118
+ };
1119
+ }
1120
+ return { valid: true };
1121
+ }
1122
+ async function initializeProject(program, args, founder) {
1123
+ return getMethods(program).initializeProject({
1124
+ projectId: args.projectId,
1125
+ fundingGoal: args.fundingGoal,
1126
+ metadataUri: args.metadataUri,
1127
+ tiers: args.tiers,
1128
+ tokenomics: {
1129
+ tokenSymbol: args.tokenomics.tokenSymbol,
1130
+ totalSupply: args.tokenomics.totalSupply,
1131
+ investorAllocationBps: args.tokenomics.investorAllocationBps,
1132
+ lpTokenAllocationBps: args.tokenomics.lpTokenAllocationBps,
1133
+ lpUsdcAllocationBps: args.tokenomics.lpUsdcAllocationBps,
1134
+ founderAllocationBps: args.tokenomics.founderAllocationBps ?? null,
1135
+ zemythAllocationBps: args.tokenomics.zemythAllocationBps ?? null,
1136
+ founderWallet: args.tokenomics.founderWallet ?? null,
601
1137
  vestingDurationMonths: args.tokenomics.vestingDurationMonths ?? null,
602
- cliffMonths: args.tokenomics.cliffMonths ?? null
1138
+ cliffMonths: args.tokenomics.cliffMonths ?? null,
1139
+ founderMilestoneVestingBps: args.tokenomics.founderMilestoneVestingBps ?? null,
1140
+ founderTimeVestingBps: args.tokenomics.founderTimeVestingBps ?? null,
1141
+ futureRoundAllocationBps: args.tokenomics.futureRoundAllocationBps ?? null
603
1142
  },
604
- milestone1Deadline: args.milestone1Deadline
605
- }).accounts({
1143
+ milestone1Deadline: args.milestone1Deadline,
1144
+ priceMultipliers: args.priceMultipliers ?? null
1145
+ }).accountsPartial({
606
1146
  founder
607
1147
  }).rpc();
608
1148
  }
609
1149
  async function submitForApproval(program, projectId, founder) {
610
1150
  const projectPda = getProjectPDA(projectId, program.programId);
611
- return getMethods(program).submitForApproval().accounts({
1151
+ return getMethods(program).submitForApproval().accountsPartial({
612
1152
  project: projectPda,
613
1153
  founder
614
1154
  }).rpc();
@@ -624,7 +1164,12 @@ async function approveProject(program, args, adminKeypair) {
624
1164
  const lpTokenVaultPda = getLpTokenVaultPDA(projectPda, program.programId);
625
1165
  const treasuryVaultPda = getTreasuryVaultPDA(projectPda, program.programId);
626
1166
  const lpUsdcVaultPda = getLpUsdcVaultPDA(projectPda, program.programId);
627
- return getMethods(program).approveProject().accounts({
1167
+ const futureRoundTokenVaultPda = getFutureRoundTokenVaultPDA(projectPda, program.programId);
1168
+ const futureRoundVaultPda = getFutureRoundVaultPDA(projectPda, program.programId);
1169
+ const computeBudgetIx = ComputeBudgetProgram.setComputeUnitLimit({
1170
+ units: 4e5
1171
+ });
1172
+ return getMethods(program).approveProject().accountsPartial({
628
1173
  project: projectPda,
629
1174
  tokenomics: tokenomicsPda,
630
1175
  tokenVault: tokenVaultPda,
@@ -635,10 +1180,12 @@ async function approveProject(program, args, adminKeypair) {
635
1180
  lpTokenVault: lpTokenVaultPda,
636
1181
  treasuryVault: treasuryVaultPda,
637
1182
  lpUsdcVault: lpUsdcVaultPda,
1183
+ futureRoundTokenVault: futureRoundTokenVaultPda,
1184
+ futureRoundVault: futureRoundVaultPda,
638
1185
  usdcMint: args.usdcMint,
639
1186
  authority: adminKeypair.publicKey,
640
1187
  payer: adminKeypair.publicKey
641
- }).signers([adminKeypair]).rpc();
1188
+ }).preInstructions([computeBudgetIx]).signers([adminKeypair]).rpc();
642
1189
  }
643
1190
  async function createMilestone(program, args, founder) {
644
1191
  const projectPda = getProjectPDA(args.projectId, program.programId);
@@ -646,8 +1193,11 @@ async function createMilestone(program, args, founder) {
646
1193
  return getMethods(program).createMilestone({
647
1194
  milestoneIndex: args.milestoneIndex,
648
1195
  percentage: args.percentage,
649
- description: args.description
650
- }).accounts({
1196
+ description: args.description,
1197
+ vestingDurationMonths: args.vestingDurationMonths ?? null,
1198
+ cliffMonths: args.cliffMonths ?? null,
1199
+ instantReleaseBps: args.instantReleaseBps ?? null
1200
+ }).accountsPartial({
651
1201
  project: projectPda,
652
1202
  milestone: milestonePda,
653
1203
  founder
@@ -656,7 +1206,7 @@ async function createMilestone(program, args, founder) {
656
1206
  async function submitMilestone(program, projectId, milestoneIndex, founder) {
657
1207
  const projectPda = getProjectPDA(projectId, program.programId);
658
1208
  const milestonePda = getMilestonePDA(projectPda, milestoneIndex, program.programId);
659
- return getMethods(program).submitMilestone().accounts({
1209
+ return getMethods(program).submitMilestone().accountsPartial({
660
1210
  project: projectPda,
661
1211
  milestone: milestonePda,
662
1212
  founder
@@ -677,7 +1227,7 @@ async function voteOnMilestone(program, args, voter) {
677
1227
  // allowOwnerOffCurve
678
1228
  TOKEN_PROGRAM_ID
679
1229
  );
680
- return getMethods(program).voteOnMilestone({ choice: args.choice }).accounts({
1230
+ return getMethods(program).voteOnMilestone({ choice: args.choice }).accountsPartial({
681
1231
  milestone: milestonePda,
682
1232
  project: projectPda,
683
1233
  investment: investmentPda,
@@ -690,7 +1240,7 @@ async function voteOnMilestone(program, args, voter) {
690
1240
  async function finalizeVoting(program, projectId, milestoneIndex) {
691
1241
  const projectPda = getProjectPDA(projectId, program.programId);
692
1242
  const milestonePda = getMilestonePDA(projectPda, milestoneIndex, program.programId);
693
- return getMethods(program).finalizeVoting().accounts({
1243
+ return getMethods(program).finalizeVoting().accountsPartial({
694
1244
  project: projectPda,
695
1245
  milestone: milestonePda
696
1246
  }).rpc();
@@ -703,7 +1253,7 @@ async function claimMilestoneFunds(program, args, founder) {
703
1253
  const tokenomicsPda = getTokenomicsPDA(projectPda, program.programId);
704
1254
  const lpUsdcVaultPda = getLpUsdcVaultPDA(projectPda, program.programId);
705
1255
  const nextMilestonePda = args.nextMilestonePda ?? (args.nextMilestoneDeadline.gt(new BN(0)) ? getMilestonePDA(projectPda, args.milestoneIndex + 1, program.programId) : null);
706
- return getMethods(program).claimMilestoneFunds({ nextMilestoneDeadline: args.nextMilestoneDeadline }).accounts({
1256
+ return getMethods(program).claimMilestoneFunds({ nextMilestoneDeadline: args.nextMilestoneDeadline }).accountsPartial({
707
1257
  milestone: milestonePda,
708
1258
  project: projectPda,
709
1259
  founder,
@@ -721,7 +1271,7 @@ async function claimMilestoneFunds(program, args, founder) {
721
1271
  async function resubmitMilestone(program, args, founder) {
722
1272
  const projectPda = getProjectPDA(args.projectId, program.programId);
723
1273
  const milestonePda = getMilestonePDA(projectPda, args.milestoneIndex, program.programId);
724
- return getMethods(program).resubmitMilestone().accounts({
1274
+ return getMethods(program).resubmitMilestone().accountsPartial({
725
1275
  project: projectPda,
726
1276
  milestone: milestonePda,
727
1277
  founder
@@ -733,7 +1283,7 @@ async function setMilestoneDeadline(program, args, founder) {
733
1283
  return getMethods(program).setMilestoneDeadline({
734
1284
  milestoneIndex: args.milestoneIndex,
735
1285
  deadline: args.deadline
736
- }).accounts({
1286
+ }).accountsPartial({
737
1287
  project: projectPda,
738
1288
  milestone: milestonePda,
739
1289
  founder
@@ -745,7 +1295,7 @@ async function extendMilestoneDeadline(program, args, founder) {
745
1295
  return getMethods(program).extendMilestoneDeadline({
746
1296
  milestoneIndex: args.milestoneIndex,
747
1297
  newDeadline: args.newDeadline
748
- }).accounts({
1298
+ }).accountsPartial({
749
1299
  project: projectPda,
750
1300
  milestone: milestonePda,
751
1301
  founder
@@ -783,7 +1333,7 @@ async function invest(program, args, investor) {
783
1333
  const masterEdition = getMasterEditionPDA(nftMint);
784
1334
  const [programAuthority] = getProgramAuthorityPDA(program.programId);
785
1335
  const firstMilestonePda = getMilestonePDA(projectPda, 0, program.programId);
786
- return getMethods(program).invest({ amount: args.amount }).accounts({
1336
+ return getMethods(program).invest({ amount: args.amount }).accountsPartial({
787
1337
  project: projectPda,
788
1338
  firstMilestone: firstMilestonePda,
789
1339
  nftMint,
@@ -810,7 +1360,7 @@ async function cancelInvestment(program, args, investor) {
810
1360
  const projectPda = getProjectPDA(args.projectId, program.programId);
811
1361
  const investmentPda = getInvestmentPDA(projectPda, nftMintPubkey, program.programId);
812
1362
  const escrowPda = getEscrowPDA(args.projectId, program.programId);
813
- return getMethods(program).cancelInvestment().accounts({
1363
+ return getMethods(program).cancelInvestment().accountsPartial({
814
1364
  investor,
815
1365
  project: projectPda,
816
1366
  investment: investmentPda,
@@ -829,7 +1379,7 @@ async function proposePivot(program, args, founder) {
829
1379
  return getMethods(program).proposePivot({
830
1380
  newMetadataUri: args.newMetadataUri,
831
1381
  newMilestones: args.newMilestones
832
- }).accounts({
1382
+ }).accountsPartial({
833
1383
  project: projectPda,
834
1384
  founder,
835
1385
  pivotProposal: pivotProposalPda,
@@ -847,7 +1397,7 @@ async function approvePivot(program, projectId, adminKeypair) {
847
1397
  const pivotCount = projectAccount.pivotCount || 0;
848
1398
  pivotProposalPda = getPivotProposalPDA(projectPda, pivotCount, program.programId);
849
1399
  }
850
- return getMethods(program).approvePivot().accounts({
1400
+ return getMethods(program).approvePivot().accountsPartial({
851
1401
  moderator: adminKeypair.publicKey,
852
1402
  project: projectPda,
853
1403
  pivotProposal: pivotProposalPda
@@ -870,7 +1420,7 @@ async function withdrawFromPivot(program, args, investor) {
870
1420
  isSigner: false,
871
1421
  isWritable: false
872
1422
  }));
873
- return getMethods(program).withdrawFromPivot().accounts({
1423
+ return getMethods(program).withdrawFromPivot().accountsPartial({
874
1424
  investor,
875
1425
  project: projectPda,
876
1426
  pivotProposal: pivotProposalPda,
@@ -890,7 +1440,7 @@ async function finalizePivot(program, args, authority) {
890
1440
  isSigner: false,
891
1441
  isWritable: true
892
1442
  }));
893
- return getMethods(program).finalizePivot().accounts({
1443
+ return getMethods(program).finalizePivot().accountsPartial({
894
1444
  authority,
895
1445
  project: projectPda,
896
1446
  pivotProposal: pivotProposalPda
@@ -901,14 +1451,14 @@ async function setTgeDate(program, args, founder) {
901
1451
  return getMethods(program).setTgeDate({
902
1452
  tgeDate: args.tgeDate,
903
1453
  tokenMint: args.tokenMint
904
- }).accounts({
1454
+ }).accountsPartial({
905
1455
  project: projectPda,
906
1456
  founder
907
1457
  }).rpc();
908
1458
  }
909
1459
  async function depositTokens(program, args, founder) {
910
1460
  const projectPda = getProjectPDA(args.projectId, program.programId);
911
- return getMethods(program).depositTokens({ amount: args.amount }).accounts({
1461
+ return getMethods(program).depositTokens({ amount: args.amount }).accountsPartial({
912
1462
  project: projectPda,
913
1463
  tokenMint: args.tokenMint,
914
1464
  founderTokenAccount: args.founderTokenAccount,
@@ -919,7 +1469,7 @@ async function claimTokens(program, args, investor) {
919
1469
  const projectPda = getProjectPDA(args.projectId, program.programId);
920
1470
  const investmentPda = getInvestmentPDA(projectPda, args.nftMint, program.programId);
921
1471
  const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
922
- return getMethods(program).claimTokens().accounts({
1472
+ return getMethods(program).claimTokens().accountsPartial({
923
1473
  investor,
924
1474
  project: projectPda,
925
1475
  investment: investmentPda,
@@ -934,7 +1484,7 @@ async function reportScam(program, args, reporter) {
934
1484
  const projectPda = getProjectPDA(args.projectId, program.programId);
935
1485
  const tgeEscrowPda = getTgeEscrowPDA(projectPda, program.programId);
936
1486
  const investmentPda = getInvestmentPDA(projectPda, args.nftMint, program.programId);
937
- return getMethods(program).reportScam().accounts({
1487
+ return getMethods(program).reportScam().accountsPartial({
938
1488
  tgeEscrow: tgeEscrowPda,
939
1489
  project: projectPda,
940
1490
  investment: investmentPda,
@@ -945,7 +1495,7 @@ async function reportScam(program, args, reporter) {
945
1495
  async function releaseHoldback(program, args) {
946
1496
  const projectPda = getProjectPDA(args.projectId, program.programId);
947
1497
  const tgeEscrowPda = getTgeEscrowPDA(projectPda, program.programId);
948
- return getMethods(program).releaseHoldback().accounts({
1498
+ return getMethods(program).releaseHoldback().accountsPartial({
949
1499
  tgeEscrow: tgeEscrowPda,
950
1500
  project: projectPda,
951
1501
  founderTokenAccount: args.founderTokenAccount
@@ -954,7 +1504,7 @@ async function releaseHoldback(program, args) {
954
1504
  async function checkAbandonment(program, projectId, milestoneIndex = 0) {
955
1505
  const projectPda = getProjectPDA(projectId, program.programId);
956
1506
  const milestonePda = getMilestonePDA(projectPda, milestoneIndex, program.programId);
957
- return getMethods(program).checkAbandonment().accounts({
1507
+ return getMethods(program).checkAbandonment().accountsPartial({
958
1508
  project: projectPda,
959
1509
  milestone: milestonePda
960
1510
  }).rpc();
@@ -973,7 +1523,7 @@ async function claimRefund(program, args, investor) {
973
1523
  isSigner: false
974
1524
  });
975
1525
  }
976
- return getMethods(program).claimRefund().accounts({
1526
+ return getMethods(program).claimRefund().accountsPartial({
977
1527
  project: projectPda,
978
1528
  investment: investmentPda,
979
1529
  nftMint: nftMintPubkey,
@@ -996,7 +1546,7 @@ async function claimInvestorTokens(program, args, investor) {
996
1546
  false,
997
1547
  TOKEN_PROGRAM_ID
998
1548
  );
999
- return getMethods(program).claimInvestorTokens({ milestoneIndex: args.milestoneIndex }).accounts({
1549
+ return getMethods(program).claimInvestorTokens({ milestoneIndex: args.milestoneIndex }).accountsPartial({
1000
1550
  investor,
1001
1551
  project: projectPda,
1002
1552
  tokenVault: tokenVaultPda,
@@ -1018,7 +1568,7 @@ async function distributeTokens(program, args, payer) {
1018
1568
  { pubkey: inv.investmentPda, isSigner: false, isWritable: true },
1019
1569
  { pubkey: inv.investorTokenAccount, isSigner: false, isWritable: true }
1020
1570
  ]);
1021
- return getMethods(program).distributeTokens({ milestoneIndex: args.milestoneIndex }).accounts({
1571
+ return getMethods(program).distributeTokens({ milestoneIndex: args.milestoneIndex }).accountsPartial({
1022
1572
  project: projectPda,
1023
1573
  tokenVault: tokenVaultPda,
1024
1574
  investorVault: investorVaultPda,
@@ -1030,7 +1580,7 @@ async function distributeTokens(program, args, payer) {
1030
1580
  async function completeDistribution(program, args, payer) {
1031
1581
  const projectPda = getProjectPDA(args.projectId, program.programId);
1032
1582
  const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
1033
- return getMethods(program).completeDistribution({ milestoneIndex: args.milestoneIndex }).accounts({
1583
+ return getMethods(program).completeDistribution({ milestoneIndex: args.milestoneIndex }).accountsPartial({
1034
1584
  project: projectPda,
1035
1585
  tokenVault: tokenVaultPda,
1036
1586
  payer
@@ -1061,7 +1611,7 @@ async function initializeFounderVesting(program, args, payer) {
1061
1611
  const tokenomicsPda = getTokenomicsPDA(projectPda, program.programId);
1062
1612
  const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
1063
1613
  const founderVestingPda = getFounderVestingPDA(projectPda, program.programId);
1064
- return getMethods(program).initializeFounderVesting().accounts({
1614
+ return getMethods(program).initializeFounderVesting().accountsPartial({
1065
1615
  project: projectPda,
1066
1616
  tokenomics: tokenomicsPda,
1067
1617
  tokenVault: tokenVaultPda,
@@ -1076,7 +1626,7 @@ async function claimVestedTokens(program, args, founder) {
1076
1626
  const founderVestingPda = getFounderVestingPDA(projectPda, program.programId);
1077
1627
  const founderVaultPda = getFounderVaultPDA(projectPda, program.programId);
1078
1628
  const vaultAuthorityPda = getVaultAuthorityPDA(projectPda, program.programId);
1079
- return getMethods(program).claimVestedTokens().accounts({
1629
+ return getMethods(program).claimVestedTokens().accountsPartial({
1080
1630
  project: projectPda,
1081
1631
  tokenVault: tokenVaultPda,
1082
1632
  founderVesting: founderVestingPda,
@@ -1091,7 +1641,7 @@ async function forceCompleteDistribution(program, args, adminKeypair) {
1091
1641
  const projectPda = getProjectPDA(args.projectId, program.programId);
1092
1642
  const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
1093
1643
  const adminConfigPda = getAdminConfigPDA(program.programId);
1094
- return getMethods(program).forceCompleteDistribution().accounts({
1644
+ return getMethods(program).forceCompleteDistribution().accountsPartial({
1095
1645
  admin: adminKeypair.publicKey,
1096
1646
  adminConfig: adminConfigPda,
1097
1647
  project: projectPda,
@@ -1111,7 +1661,7 @@ async function claimMissedUnlock(program, args, claimer) {
1111
1661
  false,
1112
1662
  TOKEN_PROGRAM_ID
1113
1663
  );
1114
- return getMethods(program).claimMissedUnlock({ milestoneIndex: args.milestoneIndex }).accounts({
1664
+ return getMethods(program).claimMissedUnlock({ milestoneIndex: args.milestoneIndex }).accountsPartial({
1115
1665
  claimer,
1116
1666
  project: projectPda,
1117
1667
  tokenVault: tokenVaultPda,
@@ -1124,70 +1674,627 @@ async function claimMissedUnlock(program, args, claimer) {
1124
1674
  tokenProgram: TOKEN_PROGRAM_ID
1125
1675
  }).rpc();
1126
1676
  }
1127
-
1128
- // src/client.ts
1129
- var RaiseClient = class _RaiseClient {
1130
- /**
1131
- * Create a new RaiseClient
1132
- *
1133
- * @param program - Anchor program instance
1134
- * @param provider - Anchor provider
1135
- */
1136
- constructor(program, provider) {
1137
- this.program = program;
1138
- this.provider = provider;
1139
- }
1140
- /**
1141
- * Load a new RaiseClient instance
1142
- *
1143
- * @param connection - Solana connection
1144
- * @param wallet - Wallet instance
1145
- * @param programId - Optional program ID override
1146
- * @returns Initialized RaiseClient
1147
- *
1148
- * @example
1149
- * ```typescript
1150
- * const client = RaiseClient.load(connection, wallet);
1151
- * ```
1152
- */
1153
- static load(_connection, _wallet, _programId) {
1154
- throw new Error(
1155
- "RaiseClient.load requires IDL. Use RaiseClient.fromProgram instead, or ensure the IDL is bundled with your application."
1156
- );
1157
- }
1158
- /**
1159
- * Create client from an existing program instance
1160
- *
1161
- * @param program - Anchor program instance
1162
- * @returns Initialized RaiseClient
1163
- *
1164
- * @example
1165
- * ```typescript
1166
- * import idl from './idl/raise.json';
1167
- *
1168
- * const provider = new AnchorProvider(connection, wallet, {});
1169
- * const program = new Program(idl, provider);
1170
- * const client = RaiseClient.fromProgram(program);
1171
- * ```
1172
- */
1173
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1174
- static fromProgram(program) {
1175
- const provider = program.provider;
1176
- return new _RaiseClient(program, provider);
1177
- }
1178
- /**
1179
- * Get the program ID
1180
- */
1181
- get programId() {
1182
- return this.program.programId;
1183
- }
1184
- /**
1185
- * Get the connected wallet public key
1186
- */
1187
- get walletPublicKey() {
1188
- return this.provider.wallet.publicKey;
1189
- }
1190
- // ===========================================================================
1677
+ async function addSubAllocation(program, args, founder) {
1678
+ const projectPda = getProjectPDA(args.projectId, program.programId);
1679
+ const tokenomicsPda = getTokenomicsPDA(projectPda, program.programId);
1680
+ return getMethods(program).addSubAllocation({
1681
+ name: args.name,
1682
+ bps: args.bps,
1683
+ recipient: args.recipient,
1684
+ vestingMonths: args.vestingMonths,
1685
+ cliffMonths: args.cliffMonths
1686
+ }).accountsPartial({
1687
+ project: projectPda,
1688
+ tokenomics: tokenomicsPda,
1689
+ founder
1690
+ }).rpc();
1691
+ }
1692
+ async function proposeAllocationChange(program, args, founder) {
1693
+ const projectPda = getProjectPDA(args.projectId, program.programId);
1694
+ const tokenomicsPda = getTokenomicsPDA(projectPda, program.programId);
1695
+ const tokenomics = await getAccountNamespace2(program).tokenomics.fetch(tokenomicsPda);
1696
+ const proposalIndex = tokenomics.proposalCount || 0;
1697
+ const proposalPda = getAllocationProposalPDA(projectPda, proposalIndex, program.programId);
1698
+ return getMethods(program).proposeAllocationChange({
1699
+ name: args.name,
1700
+ bps: args.bps,
1701
+ recipient: args.recipient,
1702
+ vestingMonths: args.vestingMonths,
1703
+ cliffMonths: args.cliffMonths
1704
+ }).accountsPartial({
1705
+ project: projectPda,
1706
+ tokenomics: tokenomicsPda,
1707
+ proposal: proposalPda,
1708
+ founder,
1709
+ systemProgram: SystemProgram.programId
1710
+ }).rpc();
1711
+ }
1712
+ async function voteAllocationChange(program, args, voter) {
1713
+ const nftMintPubkey = ensurePublicKey(args.nftMint);
1714
+ const projectPda = getProjectPDA(args.projectId, program.programId);
1715
+ const proposalPda = getAllocationProposalPDA(projectPda, args.proposalIndex, program.programId);
1716
+ const investmentPda = getInvestmentPDA(projectPda, nftMintPubkey, program.programId);
1717
+ const votePda = getAllocationVotePDA(proposalPda, nftMintPubkey, program.programId);
1718
+ const investorNftAccount = getAssociatedTokenAddressSync(
1719
+ nftMintPubkey,
1720
+ voter,
1721
+ false,
1722
+ TOKEN_PROGRAM_ID
1723
+ );
1724
+ return getMethods(program).voteAllocationChange({ voteFor: args.voteFor }).accountsPartial({
1725
+ project: projectPda,
1726
+ proposal: proposalPda,
1727
+ investment: investmentPda,
1728
+ nftMint: nftMintPubkey,
1729
+ investorNftAccount,
1730
+ voteRecord: votePda,
1731
+ voter,
1732
+ systemProgram: SystemProgram.programId
1733
+ }).rpc();
1734
+ }
1735
+ async function executeAllocationChange(program, args, executor) {
1736
+ const projectPda = getProjectPDA(args.projectId, program.programId);
1737
+ const tokenomicsPda = getTokenomicsPDA(projectPda, program.programId);
1738
+ const proposalPda = getAllocationProposalPDA(projectPda, args.proposalIndex, program.programId);
1739
+ return getMethods(program).executeAllocationChange().accountsPartial({
1740
+ project: projectPda,
1741
+ tokenomics: tokenomicsPda,
1742
+ proposal: proposalPda,
1743
+ executor
1744
+ }).rpc();
1745
+ }
1746
+ async function claimEarlyTokens(program, args, investor) {
1747
+ const nftMintPubkey = ensurePublicKey(args.nftMint);
1748
+ const projectPda = getProjectPDA(args.projectId, program.programId);
1749
+ const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
1750
+ const investmentPda = getInvestmentPDA(projectPda, nftMintPubkey, program.programId);
1751
+ const investorVaultPda = getInvestorVaultPDA(projectPda, program.programId);
1752
+ const vaultAuthorityPda = getVaultAuthorityPDA(projectPda, program.programId);
1753
+ const investorNftAccount = getAssociatedTokenAddressSync(
1754
+ nftMintPubkey,
1755
+ investor,
1756
+ false,
1757
+ TOKEN_PROGRAM_ID
1758
+ );
1759
+ return getMethods(program).claimEarlyTokens().accountsPartial({
1760
+ investor,
1761
+ project: projectPda,
1762
+ tokenVault: tokenVaultPda,
1763
+ investment: investmentPda,
1764
+ nftMint: nftMintPubkey,
1765
+ investorNftAccount,
1766
+ investorVault: investorVaultPda,
1767
+ investorTokenAccount: args.investorTokenAccount,
1768
+ vaultAuthority: vaultAuthorityPda,
1769
+ tokenProgram: TOKEN_PROGRAM_ID
1770
+ }).rpc();
1771
+ }
1772
+ async function claimFounderEarlyTokens(program, args, founder) {
1773
+ const projectPda = getProjectPDA(args.projectId, program.programId);
1774
+ const tokenomicsPda = getTokenomicsPDA(projectPda, program.programId);
1775
+ const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
1776
+ const founderVaultPda = getFounderVaultPDA(projectPda, program.programId);
1777
+ const vaultAuthorityPda = getVaultAuthorityPDA(projectPda, program.programId);
1778
+ return getMethods(program).claimFounderEarlyTokens().accountsPartial({
1779
+ founder,
1780
+ project: projectPda,
1781
+ tokenomics: tokenomicsPda,
1782
+ tokenVault: tokenVaultPda,
1783
+ founderVault: founderVaultPda,
1784
+ founderTokenAccount: args.founderTokenAccount,
1785
+ vaultAuthority: vaultAuthorityPda,
1786
+ tokenProgram: TOKEN_PROGRAM_ID
1787
+ }).rpc();
1788
+ }
1789
+ async function claimFounderMilestoneTokens(program, args, founder) {
1790
+ const projectPda = getProjectPDA(args.projectId, program.programId);
1791
+ const milestonePda = getMilestonePDA(projectPda, args.milestoneIndex, program.programId);
1792
+ const tokenomicsPda = getTokenomicsPDA(projectPda, program.programId);
1793
+ const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
1794
+ const founderVaultPda = getFounderVaultPDA(projectPda, program.programId);
1795
+ const vaultAuthorityPda = getVaultAuthorityPDA(projectPda, program.programId);
1796
+ return getMethods(program).claimFounderMilestoneTokens({ milestoneIndex: args.milestoneIndex }).accountsPartial({
1797
+ founder,
1798
+ project: projectPda,
1799
+ milestone: milestonePda,
1800
+ tokenomics: tokenomicsPda,
1801
+ tokenVault: tokenVaultPda,
1802
+ founderVault: founderVaultPda,
1803
+ founderTokenAccount: args.founderTokenAccount,
1804
+ vaultAuthority: vaultAuthorityPda,
1805
+ tokenProgram: TOKEN_PROGRAM_ID
1806
+ }).rpc();
1807
+ }
1808
+ async function initializeSubAllocationVesting(program, args, payer) {
1809
+ const projectPda = getProjectPDA(args.projectId, program.programId);
1810
+ const tokenomicsPda = getTokenomicsPDA(projectPda, program.programId);
1811
+ const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
1812
+ const subAllocationVestingPda = getSubAllocationVestingPDA(projectPda, args.subAllocationId, program.programId);
1813
+ return getMethods(program).initializeSubAllocationVesting({ subAllocationId: args.subAllocationId }).accountsPartial({
1814
+ project: projectPda,
1815
+ tokenomics: tokenomicsPda,
1816
+ tokenVault: tokenVaultPda,
1817
+ subAllocationVesting: subAllocationVestingPda,
1818
+ payer,
1819
+ systemProgram: SystemProgram.programId
1820
+ }).rpc();
1821
+ }
1822
+ async function claimSubAllocationTokens(program, args, recipient) {
1823
+ const projectPda = getProjectPDA(args.projectId, program.programId);
1824
+ const tokenomicsPda = getTokenomicsPDA(projectPda, program.programId);
1825
+ const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
1826
+ const subAllocationVestingPda = getSubAllocationVestingPDA(projectPda, args.subAllocationId, program.programId);
1827
+ const treasuryVaultPda = getTreasuryVaultPDA(projectPda, program.programId);
1828
+ const vaultAuthorityPda = getVaultAuthorityPDA(projectPda, program.programId);
1829
+ return getMethods(program).claimSubAllocationTokens({ subAllocationId: args.subAllocationId }).accountsPartial({
1830
+ project: projectPda,
1831
+ tokenomics: tokenomicsPda,
1832
+ tokenVault: tokenVaultPda,
1833
+ subAllocationVesting: subAllocationVestingPda,
1834
+ reserveVault: treasuryVaultPda,
1835
+ vaultAuthority: vaultAuthorityPda,
1836
+ recipientTokenAccount: args.recipientTokenAccount,
1837
+ recipient,
1838
+ tokenProgram: TOKEN_PROGRAM_ID
1839
+ }).rpc();
1840
+ }
1841
+ async function claimMilestoneInstantTokens(program, args, investor) {
1842
+ const nftMintPubkey = ensurePublicKey(args.nftMint);
1843
+ const projectPda = getProjectPDA(args.projectId, program.programId);
1844
+ const milestonePda = getMilestonePDA(projectPda, args.milestoneIndex, program.programId);
1845
+ const investmentPda = getInvestmentPDA(projectPda, nftMintPubkey, program.programId);
1846
+ const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
1847
+ const vestingPda = getInvestorMilestoneVestingPDA(projectPda, args.milestoneIndex, investmentPda, program.programId);
1848
+ const investorVaultPda = getInvestorVaultPDA(projectPda, program.programId);
1849
+ const vaultAuthorityPda = getVaultAuthorityPDA(projectPda, program.programId);
1850
+ const investorNftAccount = getAssociatedTokenAddressSync(
1851
+ nftMintPubkey,
1852
+ investor,
1853
+ false,
1854
+ TOKEN_PROGRAM_ID
1855
+ );
1856
+ return getMethods(program).claimMilestoneInstantTokens({ milestoneIndex: args.milestoneIndex }).accountsPartial({
1857
+ investor,
1858
+ project: projectPda,
1859
+ milestone: milestonePda,
1860
+ investment: investmentPda,
1861
+ tokenVault: tokenVaultPda,
1862
+ vesting: vestingPda,
1863
+ nftMint: nftMintPubkey,
1864
+ investorNftAccount,
1865
+ investorVault: investorVaultPda,
1866
+ investorTokenAccount: args.investorTokenAccount,
1867
+ vaultAuthority: vaultAuthorityPda,
1868
+ tokenProgram: TOKEN_PROGRAM_ID,
1869
+ systemProgram: SystemProgram.programId
1870
+ }).rpc();
1871
+ }
1872
+ async function claimMilestoneVestedTokens(program, args, investor) {
1873
+ const nftMintPubkey = ensurePublicKey(args.nftMint);
1874
+ const projectPda = getProjectPDA(args.projectId, program.programId);
1875
+ const milestonePda = getMilestonePDA(projectPda, args.milestoneIndex, program.programId);
1876
+ const investmentPda = getInvestmentPDA(projectPda, nftMintPubkey, program.programId);
1877
+ const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
1878
+ const vestingPda = getInvestorMilestoneVestingPDA(projectPda, args.milestoneIndex, investmentPda, program.programId);
1879
+ const investorVaultPda = getInvestorVaultPDA(projectPda, program.programId);
1880
+ const vaultAuthorityPda = getVaultAuthorityPDA(projectPda, program.programId);
1881
+ const investorNftAccount = getAssociatedTokenAddressSync(
1882
+ nftMintPubkey,
1883
+ investor,
1884
+ false,
1885
+ TOKEN_PROGRAM_ID
1886
+ );
1887
+ return getMethods(program).claimMilestoneVestedTokens({ milestoneIndex: args.milestoneIndex }).accountsPartial({
1888
+ investor,
1889
+ project: projectPda,
1890
+ milestone: milestonePda,
1891
+ investment: investmentPda,
1892
+ tokenVault: tokenVaultPda,
1893
+ vesting: vestingPda,
1894
+ nftMint: nftMintPubkey,
1895
+ investorNftAccount,
1896
+ investorVault: investorVaultPda,
1897
+ investorTokenAccount: args.investorTokenAccount,
1898
+ vaultAuthority: vaultAuthorityPda,
1899
+ tokenProgram: TOKEN_PROGRAM_ID
1900
+ }).rpc();
1901
+ }
1902
+ async function claimFounderMsInstantTokens(program, args, founder) {
1903
+ const projectPda = getProjectPDA(args.projectId, program.programId);
1904
+ const milestonePda = getMilestonePDA(projectPda, args.milestoneIndex, program.programId);
1905
+ const tokenomicsPda = getTokenomicsPDA(projectPda, program.programId);
1906
+ const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
1907
+ const vestingPda = getFounderMilestoneVestingPDA(projectPda, args.milestoneIndex, program.programId);
1908
+ const founderVaultPda = getFounderVaultPDA(projectPda, program.programId);
1909
+ const vaultAuthorityPda = getVaultAuthorityPDA(projectPda, program.programId);
1910
+ return getMethods(program).claimFounderMsInstantTokens({ milestoneIndex: args.milestoneIndex }).accountsPartial({
1911
+ founder,
1912
+ project: projectPda,
1913
+ tokenomics: tokenomicsPda,
1914
+ milestone: milestonePda,
1915
+ tokenVault: tokenVaultPda,
1916
+ vesting: vestingPda,
1917
+ founderVault: founderVaultPda,
1918
+ founderTokenAccount: args.founderTokenAccount,
1919
+ vaultAuthority: vaultAuthorityPda,
1920
+ tokenProgram: TOKEN_PROGRAM_ID,
1921
+ systemProgram: SystemProgram.programId
1922
+ }).rpc();
1923
+ }
1924
+ async function claimFounderMsVestedTokens(program, args, founder) {
1925
+ const projectPda = getProjectPDA(args.projectId, program.programId);
1926
+ const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
1927
+ const vestingPda = getFounderMilestoneVestingPDA(projectPda, args.milestoneIndex, program.programId);
1928
+ const founderVaultPda = getFounderVaultPDA(projectPda, program.programId);
1929
+ const vaultAuthorityPda = getVaultAuthorityPDA(projectPda, program.programId);
1930
+ return getMethods(program).claimFounderMsVestedTokens({ milestoneIndex: args.milestoneIndex }).accountsPartial({
1931
+ founder,
1932
+ project: projectPda,
1933
+ tokenVault: tokenVaultPda,
1934
+ vesting: vestingPda,
1935
+ founderVault: founderVaultPda,
1936
+ founderTokenAccount: args.founderTokenAccount,
1937
+ vaultAuthority: vaultAuthorityPda,
1938
+ tokenProgram: TOKEN_PROGRAM_ID
1939
+ }).rpc();
1940
+ }
1941
+ function getRoundEscrowAuthorityPDA(projectPda, roundNumber, programId) {
1942
+ return PublicKey.findProgramAddressSync(
1943
+ [
1944
+ Buffer.from("round_escrow"),
1945
+ projectPda.toBuffer(),
1946
+ Buffer.from([roundNumber]),
1947
+ Buffer.from("authority")
1948
+ ],
1949
+ programId
1950
+ );
1951
+ }
1952
+ async function openFundingRound(program, args, founder) {
1953
+ const projectPda = getProjectPDA(args.projectId, program.programId);
1954
+ const tokenomicsPda = getTokenomicsPDA(projectPda, program.programId);
1955
+ const project = await getAccountNamespace2(program).project.fetch(projectPda);
1956
+ const newRoundNumber = (project.roundCount || 1) + 1;
1957
+ const fundingRoundPda = getFundingRoundPDA(projectPda, newRoundNumber, program.programId);
1958
+ const roundEscrowPda = getRoundEscrowPDA(projectPda, newRoundNumber, program.programId);
1959
+ const [roundEscrowAuthorityPda] = getRoundEscrowAuthorityPDA(projectPda, newRoundNumber, program.programId);
1960
+ const remainingAccounts = args.milestones.map((_, i) => {
1961
+ const milestonePda = getRoundMilestonePDA(projectPda, newRoundNumber, i, program.programId);
1962
+ return {
1963
+ pubkey: milestonePda,
1964
+ isSigner: false,
1965
+ isWritable: true
1966
+ };
1967
+ });
1968
+ const milestonesParam = args.milestones.map((m) => ({
1969
+ percentage: m.percentage,
1970
+ description: m.description,
1971
+ vestingDurationMonths: m.vestingDurationMonths ?? null,
1972
+ cliffMonths: m.cliffMonths ?? null,
1973
+ instantReleaseBps: m.instantReleaseBps ?? null
1974
+ }));
1975
+ return getMethods(program).openFundingRound({
1976
+ roundAllocationBps: args.roundAllocationBps,
1977
+ fundingGoal: args.fundingGoal,
1978
+ tiers: args.tiers,
1979
+ milestones: milestonesParam
1980
+ }).accountsPartial({
1981
+ project: projectPda,
1982
+ tokenomics: tokenomicsPda,
1983
+ fundingRound: fundingRoundPda,
1984
+ roundEscrow: roundEscrowPda,
1985
+ roundEscrowAuthority: roundEscrowAuthorityPda,
1986
+ usdcMint: args.usdcMint,
1987
+ previousFundingRound: args.previousFundingRoundPda ?? null,
1988
+ founder,
1989
+ tokenProgram: TOKEN_PROGRAM_ID,
1990
+ systemProgram: SystemProgram.programId,
1991
+ rent: SYSVAR_RENT_PUBKEY
1992
+ }).remainingAccounts(remainingAccounts).rpc();
1993
+ }
1994
+ async function investInRound(program, args, investor) {
1995
+ const projectPda = getProjectPDA(args.projectId, program.programId);
1996
+ const fundingRoundPda = getFundingRoundPDA(projectPda, args.roundNumber, program.programId);
1997
+ const roundEscrowPda = getRoundEscrowPDA(projectPda, args.roundNumber, program.programId);
1998
+ const firstRoundMilestonePda = getRoundMilestonePDA(projectPda, args.roundNumber, 0, program.programId);
1999
+ const [nftMint] = getRoundNftMintPDA(args.projectId, args.roundNumber, investor, args.investmentCount, program.programId);
2000
+ const investmentPda = getRoundInvestmentPDA(projectPda, args.roundNumber, nftMint, program.programId);
2001
+ const investorNftAccount = getAssociatedTokenAddressSync(nftMint, investor);
2002
+ const metadataAccount = getMetadataPDA(nftMint);
2003
+ const masterEdition = getMasterEditionPDA(nftMint);
2004
+ const [programAuthority] = getProgramAuthorityPDA(program.programId);
2005
+ return getMethods(program).investInRound({ amount: args.amount }).accountsPartial({
2006
+ project: projectPda,
2007
+ fundingRound: fundingRoundPda,
2008
+ firstRoundMilestone: firstRoundMilestonePda,
2009
+ nftMint,
2010
+ investment: investmentPda,
2011
+ investorNftAccount,
2012
+ metadataAccount,
2013
+ masterEdition,
2014
+ roundEscrow: roundEscrowPda,
2015
+ investorTokenAccount: args.investorTokenAccount,
2016
+ programAuthority,
2017
+ investor,
2018
+ tokenProgram: TOKEN_PROGRAM_ID,
2019
+ associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID,
2020
+ systemProgram: SystemProgram.programId,
2021
+ rent: SYSVAR_RENT_PUBKEY,
2022
+ tokenMetadataProgram: TOKEN_METADATA_PROGRAM_ID,
2023
+ sysvarInstructions: SYSVAR_INSTRUCTIONS_PUBKEY
2024
+ }).preInstructions([
2025
+ ComputeBudgetProgram.setComputeUnitLimit({ units: 4e5 })
2026
+ ]).rpc();
2027
+ }
2028
+ async function cancelRoundInvestment(program, args, investor) {
2029
+ const nftMintPubkey = ensurePublicKey(args.nftMint);
2030
+ const projectPda = getProjectPDA(args.projectId, program.programId);
2031
+ const fundingRoundPda = getFundingRoundPDA(projectPda, args.roundNumber, program.programId);
2032
+ const investmentPda = getRoundInvestmentPDA(projectPda, args.roundNumber, nftMintPubkey, program.programId);
2033
+ const roundEscrowPda = getRoundEscrowPDA(projectPda, args.roundNumber, program.programId);
2034
+ const [roundEscrowAuthorityPda] = getRoundEscrowAuthorityPDA(projectPda, args.roundNumber, program.programId);
2035
+ return getMethods(program).cancelRoundInvestment().accountsPartial({
2036
+ investor,
2037
+ project: projectPda,
2038
+ fundingRound: fundingRoundPda,
2039
+ investment: investmentPda,
2040
+ nftMint: nftMintPubkey,
2041
+ investorNftAccount: args.investorNftAccount,
2042
+ roundEscrow: roundEscrowPda,
2043
+ roundEscrowAuthority: roundEscrowAuthorityPda,
2044
+ investorUsdcAccount: args.investorUsdcAccount,
2045
+ tokenProgram: TOKEN_PROGRAM_ID
2046
+ }).rpc();
2047
+ }
2048
+ async function submitRoundMilestone(program, args, founder) {
2049
+ const projectPda = getProjectPDA(args.projectId, program.programId);
2050
+ const fundingRoundPda = getFundingRoundPDA(projectPda, args.roundNumber, program.programId);
2051
+ const milestonePda = getRoundMilestonePDA(projectPda, args.roundNumber, args.milestoneIndex, program.programId);
2052
+ return getMethods(program).submitRoundMilestone().accountsPartial({
2053
+ founder,
2054
+ project: projectPda,
2055
+ fundingRound: fundingRoundPda,
2056
+ milestone: milestonePda,
2057
+ clock: SYSVAR_CLOCK_PUBKEY
2058
+ }).rpc();
2059
+ }
2060
+ async function voteOnRoundMilestone(program, args, voter) {
2061
+ const nftMintPubkey = ensurePublicKey(args.nftMint);
2062
+ const projectPda = getProjectPDA(args.projectId, program.programId);
2063
+ const fundingRoundPda = getFundingRoundPDA(projectPda, args.roundNumber, program.programId);
2064
+ const milestonePda = getRoundMilestonePDA(projectPda, args.roundNumber, args.milestoneIndex, program.programId);
2065
+ let investmentPda;
2066
+ if (args.investmentRoundNumber === 1) {
2067
+ investmentPda = getInvestmentPDA(projectPda, nftMintPubkey, program.programId);
2068
+ } else {
2069
+ investmentPda = getRoundInvestmentPDA(projectPda, args.investmentRoundNumber, nftMintPubkey, program.programId);
2070
+ }
2071
+ const milestone = await getAccountNamespace2(program).milestone.fetch(milestonePda);
2072
+ const votingRound = milestone.votingRound ?? 0;
2073
+ const votePda = getVotePDA(milestonePda, voter, votingRound, program.programId);
2074
+ const voterNftAccount = getAssociatedTokenAddressSync(
2075
+ nftMintPubkey,
2076
+ voter,
2077
+ false,
2078
+ TOKEN_PROGRAM_ID
2079
+ );
2080
+ return getMethods(program).voteOnRoundMilestone({ choice: args.choice }).accountsPartial({
2081
+ vote: votePda,
2082
+ project: projectPda,
2083
+ fundingRound: fundingRoundPda,
2084
+ milestone: milestonePda,
2085
+ investment: investmentPda,
2086
+ nftMint: nftMintPubkey,
2087
+ voterNftAccount,
2088
+ voter,
2089
+ systemProgram: SystemProgram.programId
2090
+ }).rpc();
2091
+ }
2092
+ async function finalizeRoundVoting(program, args) {
2093
+ const projectPda = getProjectPDA(args.projectId, program.programId);
2094
+ const fundingRoundPda = getFundingRoundPDA(projectPda, args.roundNumber, program.programId);
2095
+ const milestonePda = getRoundMilestonePDA(projectPda, args.roundNumber, args.milestoneIndex, program.programId);
2096
+ return getMethods(program).finalizeRoundVoting().accountsPartial({
2097
+ project: projectPda,
2098
+ fundingRound: fundingRoundPda,
2099
+ milestone: milestonePda,
2100
+ clock: SYSVAR_CLOCK_PUBKEY
2101
+ }).rpc();
2102
+ }
2103
+ async function claimRoundMilestoneFunds(program, args, founder) {
2104
+ const projectPda = getProjectPDA(args.projectId, program.programId);
2105
+ const fundingRoundPda = getFundingRoundPDA(projectPda, args.roundNumber, program.programId);
2106
+ const milestonePda = getRoundMilestonePDA(projectPda, args.roundNumber, args.milestoneIndex, program.programId);
2107
+ const roundEscrowPda = getRoundEscrowPDA(projectPda, args.roundNumber, program.programId);
2108
+ const [roundEscrowAuthorityPda] = getRoundEscrowAuthorityPDA(projectPda, args.roundNumber, program.programId);
2109
+ const nextMilestonePda = args.nextMilestoneDeadline.gt(new BN(0)) ? getRoundMilestonePDA(projectPda, args.roundNumber, args.milestoneIndex + 1, program.programId) : null;
2110
+ return getMethods(program).claimRoundMilestoneFunds({ nextMilestoneDeadline: args.nextMilestoneDeadline }).accountsPartial({
2111
+ project: projectPda,
2112
+ fundingRound: fundingRoundPda,
2113
+ milestone: milestonePda,
2114
+ founder,
2115
+ roundEscrow: roundEscrowPda,
2116
+ roundEscrowAuthority: roundEscrowAuthorityPda,
2117
+ founderUsdcAccount: args.founderUsdcAccount,
2118
+ nextMilestone: nextMilestonePda,
2119
+ systemProgram: SystemProgram.programId,
2120
+ tokenProgram: TOKEN_PROGRAM_ID
2121
+ }).rpc();
2122
+ }
2123
+ async function claimRoundInstantTokens(program, args, investor) {
2124
+ const nftMintPubkey = ensurePublicKey(args.nftMint);
2125
+ const projectPda = getProjectPDA(args.projectId, program.programId);
2126
+ const fundingRoundPda = getFundingRoundPDA(projectPda, args.roundNumber, program.programId);
2127
+ const milestonePda = getRoundMilestonePDA(projectPda, args.roundNumber, args.milestoneIndex, program.programId);
2128
+ const investmentPda = getRoundInvestmentPDA(projectPda, args.roundNumber, nftMintPubkey, program.programId);
2129
+ const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
2130
+ const futureRoundVaultPda = getFutureRoundVaultPDA(projectPda, program.programId);
2131
+ const futureRoundTokenVaultPda = getFutureRoundTokenVaultPDA(projectPda, program.programId);
2132
+ const vaultAuthorityPda = getVaultAuthorityPDA(projectPda, program.programId);
2133
+ const vestingPda = getRoundInvestorMilestoneVestingPDA(
2134
+ projectPda,
2135
+ args.roundNumber,
2136
+ args.milestoneIndex,
2137
+ investmentPda,
2138
+ program.programId
2139
+ );
2140
+ const investorNftAccount = getAssociatedTokenAddressSync(
2141
+ nftMintPubkey,
2142
+ investor,
2143
+ false,
2144
+ TOKEN_PROGRAM_ID
2145
+ );
2146
+ return getMethods(program).claimRoundInstantTokens({ milestoneIndex: args.milestoneIndex }).accountsPartial({
2147
+ investor,
2148
+ project: projectPda,
2149
+ fundingRound: fundingRoundPda,
2150
+ milestone: milestonePda,
2151
+ investment: investmentPda,
2152
+ tokenVault: tokenVaultPda,
2153
+ futureRoundVault: futureRoundVaultPda,
2154
+ vesting: vestingPda,
2155
+ nftMint: nftMintPubkey,
2156
+ investorNftAccount,
2157
+ futureRoundTokenVault: futureRoundTokenVaultPda,
2158
+ investorTokenAccount: args.investorTokenAccount,
2159
+ vaultAuthority: vaultAuthorityPda,
2160
+ tokenProgram: TOKEN_PROGRAM_ID,
2161
+ systemProgram: SystemProgram.programId
2162
+ }).rpc();
2163
+ }
2164
+ async function claimRoundVestedTokens(program, args, investor) {
2165
+ const nftMintPubkey = ensurePublicKey(args.nftMint);
2166
+ const projectPda = getProjectPDA(args.projectId, program.programId);
2167
+ const fundingRoundPda = getFundingRoundPDA(projectPda, args.roundNumber, program.programId);
2168
+ const milestonePda = getRoundMilestonePDA(projectPda, args.roundNumber, args.milestoneIndex, program.programId);
2169
+ const investmentPda = getRoundInvestmentPDA(projectPda, args.roundNumber, nftMintPubkey, program.programId);
2170
+ const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
2171
+ const futureRoundVaultPda = getFutureRoundVaultPDA(projectPda, program.programId);
2172
+ const futureRoundTokenVaultPda = getFutureRoundTokenVaultPDA(projectPda, program.programId);
2173
+ const vaultAuthorityPda = getVaultAuthorityPDA(projectPda, program.programId);
2174
+ const vestingPda = getRoundInvestorMilestoneVestingPDA(
2175
+ projectPda,
2176
+ args.roundNumber,
2177
+ args.milestoneIndex,
2178
+ investmentPda,
2179
+ program.programId
2180
+ );
2181
+ const investorNftAccount = getAssociatedTokenAddressSync(
2182
+ nftMintPubkey,
2183
+ investor,
2184
+ false,
2185
+ TOKEN_PROGRAM_ID
2186
+ );
2187
+ return getMethods(program).claimRoundVestedTokens({ milestoneIndex: args.milestoneIndex }).accountsPartial({
2188
+ investor,
2189
+ project: projectPda,
2190
+ fundingRound: fundingRoundPda,
2191
+ milestone: milestonePda,
2192
+ investment: investmentPda,
2193
+ tokenVault: tokenVaultPda,
2194
+ futureRoundVault: futureRoundVaultPda,
2195
+ vesting: vestingPda,
2196
+ nftMint: nftMintPubkey,
2197
+ investorNftAccount,
2198
+ futureRoundTokenVault: futureRoundTokenVaultPda,
2199
+ investorTokenAccount: args.investorTokenAccount,
2200
+ vaultAuthority: vaultAuthorityPda,
2201
+ tokenProgram: TOKEN_PROGRAM_ID
2202
+ }).rpc();
2203
+ }
2204
+ async function claimRoundEarlyTokens(program, args, investor) {
2205
+ const nftMintPubkey = ensurePublicKey(args.nftMint);
2206
+ const projectPda = getProjectPDA(args.projectId, program.programId);
2207
+ const fundingRoundPda = getFundingRoundPDA(projectPda, args.roundNumber, program.programId);
2208
+ const investmentPda = getRoundInvestmentPDA(projectPda, args.roundNumber, nftMintPubkey, program.programId);
2209
+ const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
2210
+ const futureRoundVaultPda = getFutureRoundVaultPDA(projectPda, program.programId);
2211
+ const futureRoundTokenVaultPda = getFutureRoundTokenVaultPDA(projectPda, program.programId);
2212
+ const vaultAuthorityPda = getVaultAuthorityPDA(projectPda, program.programId);
2213
+ const investorNftAccount = getAssociatedTokenAddressSync(
2214
+ nftMintPubkey,
2215
+ investor,
2216
+ false,
2217
+ TOKEN_PROGRAM_ID
2218
+ );
2219
+ return getMethods(program).claimRoundEarlyTokens().accountsPartial({
2220
+ investor,
2221
+ project: projectPda,
2222
+ fundingRound: fundingRoundPda,
2223
+ investment: investmentPda,
2224
+ tokenVault: tokenVaultPda,
2225
+ futureRoundVault: futureRoundVaultPda,
2226
+ nftMint: nftMintPubkey,
2227
+ investorNftAccount,
2228
+ futureRoundTokenVault: futureRoundTokenVaultPda,
2229
+ investorTokenAccount: args.investorTokenAccount,
2230
+ vaultAuthority: vaultAuthorityPda,
2231
+ tokenProgram: TOKEN_PROGRAM_ID
2232
+ }).rpc();
2233
+ }
2234
+
2235
+ // src/client.ts
2236
+ var RaiseClient = class _RaiseClient {
2237
+ /**
2238
+ * Create a new RaiseClient
2239
+ *
2240
+ * @param program - Anchor program instance
2241
+ * @param provider - Anchor provider
2242
+ */
2243
+ constructor(program, provider) {
2244
+ this.program = program;
2245
+ this.provider = provider;
2246
+ }
2247
+ /**
2248
+ * Load a new RaiseClient instance
2249
+ *
2250
+ * @param connection - Solana connection
2251
+ * @param wallet - Wallet instance
2252
+ * @param programId - Optional program ID override
2253
+ * @returns Initialized RaiseClient
2254
+ *
2255
+ * @example
2256
+ * ```typescript
2257
+ * const client = RaiseClient.load(connection, wallet);
2258
+ * ```
2259
+ */
2260
+ static load(_connection, _wallet, _programId) {
2261
+ throw new Error(
2262
+ "RaiseClient.load requires IDL. Use RaiseClient.fromProgram instead, or ensure the IDL is bundled with your application."
2263
+ );
2264
+ }
2265
+ /**
2266
+ * Create client from an existing program instance
2267
+ *
2268
+ * @param program - Anchor program instance
2269
+ * @returns Initialized RaiseClient
2270
+ *
2271
+ * @example
2272
+ * ```typescript
2273
+ * import idl from './idl/raise.json';
2274
+ *
2275
+ * const provider = new AnchorProvider(connection, wallet, {});
2276
+ * const program = new Program(idl, provider);
2277
+ * const client = RaiseClient.fromProgram(program);
2278
+ * ```
2279
+ */
2280
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2281
+ static fromProgram(program) {
2282
+ const provider = program.provider;
2283
+ return new _RaiseClient(program, provider);
2284
+ }
2285
+ /**
2286
+ * Get the program ID
2287
+ */
2288
+ get programId() {
2289
+ return this.program.programId;
2290
+ }
2291
+ /**
2292
+ * Get the connected wallet public key
2293
+ */
2294
+ get walletPublicKey() {
2295
+ return this.provider.wallet.publicKey;
2296
+ }
2297
+ // ===========================================================================
1191
2298
  // PDA Helpers
1192
2299
  // ===========================================================================
1193
2300
  getProjectPDA(projectId) {
@@ -1214,381 +2321,1166 @@ var RaiseClient = class _RaiseClient {
1214
2321
  getTgeEscrowVaultPDA(projectPda) {
1215
2322
  return getTgeEscrowVaultPDA(projectPda, this.programId);
1216
2323
  }
1217
- getAdminConfigPDA() {
1218
- return getAdminConfigPDA(this.programId);
2324
+ getAdminConfigPDA() {
2325
+ return getAdminConfigPDA(this.programId);
2326
+ }
2327
+ getAllocationProposalPDA(projectPda, proposalIndex) {
2328
+ return getAllocationProposalPDA(projectPda, proposalIndex, this.programId);
2329
+ }
2330
+ getAllocationVotePDA(proposalPda, nftMint) {
2331
+ return getAllocationVotePDA(proposalPda, nftMint, this.programId);
2332
+ }
2333
+ getSubAllocationVestingPDA(projectPda, subAllocationId) {
2334
+ return getSubAllocationVestingPDA(projectPda, subAllocationId, this.programId);
2335
+ }
2336
+ getTokenomicsPDA(projectPda) {
2337
+ return getTokenomicsPDA(projectPda, this.programId);
2338
+ }
2339
+ // Per-Milestone Vesting PDAs
2340
+ getInvestorMilestoneVestingPDA(projectPda, milestoneIndex, investmentPda) {
2341
+ return getInvestorMilestoneVestingPDA(projectPda, milestoneIndex, investmentPda, this.programId);
2342
+ }
2343
+ getFounderMilestoneVestingPDA(projectPda, milestoneIndex) {
2344
+ return getFounderMilestoneVestingPDA(projectPda, milestoneIndex, this.programId);
2345
+ }
2346
+ // ===========================================================================
2347
+ // Account Fetchers
2348
+ // ===========================================================================
2349
+ async fetchProject(projectId) {
2350
+ return fetchProject(this.program, projectId);
2351
+ }
2352
+ async fetchMilestone(projectId, milestoneIndex) {
2353
+ return fetchMilestone(this.program, projectId, milestoneIndex);
2354
+ }
2355
+ async fetchAllMilestones(projectId) {
2356
+ return fetchAllMilestones(this.program, projectId);
2357
+ }
2358
+ async fetchInvestment(projectId, nftMint) {
2359
+ return fetchInvestment(this.program, projectId, nftMint);
2360
+ }
2361
+ async fetchAllInvestments(projectId) {
2362
+ return fetchAllInvestments(this.program, projectId);
2363
+ }
2364
+ async fetchVote(projectId, milestoneIndex, voterKey, votingRound) {
2365
+ return fetchVote(this.program, projectId, milestoneIndex, voterKey, votingRound);
2366
+ }
2367
+ async fetchAllVotes(projectId, milestoneIndex) {
2368
+ return fetchAllVotes(this.program, projectId, milestoneIndex);
2369
+ }
2370
+ async fetchPivotProposal(projectId) {
2371
+ return fetchPivotProposal(this.program, projectId);
2372
+ }
2373
+ async fetchTgeEscrow(projectId) {
2374
+ return fetchTgeEscrow(this.program, projectId);
2375
+ }
2376
+ async fetchAdminConfig() {
2377
+ return fetchAdminConfig(this.program);
2378
+ }
2379
+ async fetchTokenVault(projectId) {
2380
+ return fetchTokenVault(this.program, projectId);
2381
+ }
2382
+ async fetchTokenomics(projectId) {
2383
+ return fetchTokenomics(this.program, projectId);
2384
+ }
2385
+ async fetchAllocationProposal(projectId, proposalIndex) {
2386
+ return fetchAllocationProposal(this.program, projectId, proposalIndex);
2387
+ }
2388
+ async fetchAllAllocationProposals(projectId) {
2389
+ return fetchAllAllocationProposals(this.program, projectId);
2390
+ }
2391
+ async fetchAllocationVote(projectId, proposalIndex, nftMint) {
2392
+ return fetchAllocationVote(this.program, projectId, proposalIndex, nftMint);
2393
+ }
2394
+ async fetchSubAllocationVesting(projectId, subAllocationId) {
2395
+ return fetchSubAllocationVesting(this.program, projectId, subAllocationId);
2396
+ }
2397
+ async fetchInvestorMilestoneVesting(projectId, milestoneIndex, nftMint) {
2398
+ return fetchInvestorMilestoneVesting(this.program, projectId, milestoneIndex, nftMint);
2399
+ }
2400
+ async fetchFounderMilestoneVesting(projectId, milestoneIndex) {
2401
+ return fetchFounderMilestoneVesting(this.program, projectId, milestoneIndex);
2402
+ }
2403
+ // ===========================================================================
2404
+ // Admin Instructions
2405
+ // ===========================================================================
2406
+ async initializeAdmin(admin) {
2407
+ return initializeAdmin(
2408
+ this.program,
2409
+ admin,
2410
+ this.walletPublicKey
2411
+ );
2412
+ }
2413
+ async transferAdmin(newAdmin, adminKeypair) {
2414
+ return transferAdmin(
2415
+ this.program,
2416
+ adminKeypair,
2417
+ newAdmin
2418
+ );
2419
+ }
2420
+ async acceptAdmin() {
2421
+ return acceptAdmin(
2422
+ this.program,
2423
+ this.walletPublicKey
2424
+ );
2425
+ }
2426
+ // ===========================================================================
2427
+ // Project Instructions
2428
+ // ===========================================================================
2429
+ async initializeProject(args) {
2430
+ return initializeProject(
2431
+ this.program,
2432
+ args,
2433
+ this.walletPublicKey
2434
+ );
2435
+ }
2436
+ async submitForApproval(projectId) {
2437
+ return submitForApproval(
2438
+ this.program,
2439
+ projectId,
2440
+ this.walletPublicKey
2441
+ );
2442
+ }
2443
+ async approveProject(args, adminKeypair) {
2444
+ return approveProject(
2445
+ this.program,
2446
+ args,
2447
+ adminKeypair
2448
+ );
2449
+ }
2450
+ // ===========================================================================
2451
+ // Milestone Instructions
2452
+ // ===========================================================================
2453
+ async createMilestone(args) {
2454
+ return createMilestone(
2455
+ this.program,
2456
+ args,
2457
+ this.walletPublicKey
2458
+ );
2459
+ }
2460
+ async submitMilestone(projectId, milestoneIndex) {
2461
+ return submitMilestone(
2462
+ this.program,
2463
+ projectId,
2464
+ milestoneIndex,
2465
+ this.walletPublicKey
2466
+ );
2467
+ }
2468
+ async voteOnMilestone(args) {
2469
+ return voteOnMilestone(
2470
+ this.program,
2471
+ args,
2472
+ this.walletPublicKey
2473
+ );
2474
+ }
2475
+ async finalizeVoting(projectId, milestoneIndex) {
2476
+ return finalizeVoting(
2477
+ this.program,
2478
+ projectId,
2479
+ milestoneIndex
2480
+ );
2481
+ }
2482
+ /**
2483
+ * Claim milestone funds (ZTM v2.0)
2484
+ * - Regular milestones: Full payout to founder
2485
+ * - Final milestone: LP USDC reserved for PCL, triggers MAE
2486
+ *
2487
+ * @param nextMilestoneDeadline - Deadline for next milestone (required for non-final milestones)
2488
+ * Set to BN(0) for final milestone claims (no next milestone exists)
2489
+ */
2490
+ async claimMilestoneFunds(args) {
2491
+ return claimMilestoneFunds(
2492
+ this.program,
2493
+ args,
2494
+ this.walletPublicKey
2495
+ );
2496
+ }
2497
+ /**
2498
+ * Resubmit a failed milestone for rework (Failed → InProgress)
2499
+ *
2500
+ * Allows founders to iterate on failed milestones. Clears voting state
2501
+ * for a fresh voting cycle. consecutive_failures is NOT reset.
2502
+ */
2503
+ async resubmitMilestone(args) {
2504
+ return resubmitMilestone(
2505
+ this.program,
2506
+ args,
2507
+ this.walletPublicKey
2508
+ );
2509
+ }
2510
+ /**
2511
+ * Set milestone deadline for founder to commit submission date
2512
+ *
2513
+ * Founders must set deadlines for milestones to provide visibility to investors.
2514
+ * Deadline must be at least 7 days from now and at most 1 year from now.
2515
+ */
2516
+ async setMilestoneDeadline(args) {
2517
+ return setMilestoneDeadline(
2518
+ this.program,
2519
+ args,
2520
+ this.walletPublicKey
2521
+ );
2522
+ }
2523
+ /**
2524
+ * Extend milestone deadline (max 3 extensions per milestone)
2525
+ *
2526
+ * Founders can extend a deadline up to 3 times before it passes.
2527
+ * Must be called BEFORE the current deadline passes.
2528
+ */
2529
+ async extendMilestoneDeadline(args) {
2530
+ return extendMilestoneDeadline(
2531
+ this.program,
2532
+ args,
2533
+ this.walletPublicKey
2534
+ );
2535
+ }
2536
+ // ===========================================================================
2537
+ // Investment Instructions
2538
+ // ===========================================================================
2539
+ async invest(args) {
2540
+ return invest(
2541
+ this.program,
2542
+ args,
2543
+ this.walletPublicKey
2544
+ );
2545
+ }
2546
+ async cancelInvestment(args) {
2547
+ return cancelInvestment(
2548
+ this.program,
2549
+ args,
2550
+ this.walletPublicKey
2551
+ );
2552
+ }
2553
+ // ===========================================================================
2554
+ // Pivot Instructions
2555
+ // ===========================================================================
2556
+ async proposePivot(args) {
2557
+ return proposePivot(
2558
+ this.program,
2559
+ args,
2560
+ this.walletPublicKey
2561
+ );
2562
+ }
2563
+ async approvePivot(projectId, adminKeypair) {
2564
+ return approvePivot(
2565
+ this.program,
2566
+ projectId,
2567
+ adminKeypair
2568
+ );
2569
+ }
2570
+ async withdrawFromPivot(args) {
2571
+ return withdrawFromPivot(
2572
+ this.program,
2573
+ args,
2574
+ this.walletPublicKey
2575
+ );
2576
+ }
2577
+ async finalizePivot(args) {
2578
+ return finalizePivot(
2579
+ this.program,
2580
+ args,
2581
+ this.walletPublicKey
2582
+ );
1219
2583
  }
1220
2584
  // ===========================================================================
1221
- // Account Fetchers
2585
+ // TGE Instructions
1222
2586
  // ===========================================================================
1223
- async fetchProject(projectId) {
1224
- return fetchProject(this.program, projectId);
1225
- }
1226
- async fetchMilestone(projectId, milestoneIndex) {
1227
- return fetchMilestone(this.program, projectId, milestoneIndex);
1228
- }
1229
- async fetchAllMilestones(projectId) {
1230
- return fetchAllMilestones(this.program, projectId);
2587
+ async setTgeDate(args) {
2588
+ return setTgeDate(
2589
+ this.program,
2590
+ args,
2591
+ this.walletPublicKey
2592
+ );
1231
2593
  }
1232
- async fetchInvestment(projectId, nftMint) {
1233
- return fetchInvestment(this.program, projectId, nftMint);
2594
+ async depositTokens(args) {
2595
+ return depositTokens(
2596
+ this.program,
2597
+ args,
2598
+ this.walletPublicKey
2599
+ );
1234
2600
  }
1235
- async fetchAllInvestments(projectId) {
1236
- return fetchAllInvestments(this.program, projectId);
2601
+ async claimTokens(args) {
2602
+ return claimTokens(
2603
+ this.program,
2604
+ args,
2605
+ this.walletPublicKey
2606
+ );
1237
2607
  }
1238
- async fetchVote(projectId, milestoneIndex, voterKey, votingRound) {
1239
- return fetchVote(this.program, projectId, milestoneIndex, voterKey, votingRound);
2608
+ async reportScam(args) {
2609
+ return reportScam(
2610
+ this.program,
2611
+ args,
2612
+ this.walletPublicKey
2613
+ );
1240
2614
  }
1241
- async fetchAllVotes(projectId, milestoneIndex) {
1242
- return fetchAllVotes(this.program, projectId, milestoneIndex);
2615
+ async releaseHoldback(args) {
2616
+ return releaseHoldback(
2617
+ this.program,
2618
+ args
2619
+ );
1243
2620
  }
1244
- async fetchPivotProposal(projectId) {
1245
- return fetchPivotProposal(this.program, projectId);
2621
+ // ===========================================================================
2622
+ // ZTM v2.0 Token Distribution Instructions
2623
+ // ===========================================================================
2624
+ /**
2625
+ * Claim investor tokens from a passed milestone (whitepaper: manual claim model)
2626
+ *
2627
+ * ZTM v2.0: Per whitepaper, investors manually claim their tokens after a milestone passes.
2628
+ * This replaces the batch distribution model with investor-initiated per-NFT claims.
2629
+ */
2630
+ async claimInvestorTokens(args) {
2631
+ return claimInvestorTokens(
2632
+ this.program,
2633
+ args,
2634
+ this.walletPublicKey
2635
+ );
1246
2636
  }
1247
- async fetchTgeEscrow(projectId) {
1248
- return fetchTgeEscrow(this.program, projectId);
2637
+ /**
2638
+ * Distribute tokens to NFT holders for a milestone
2639
+ *
2640
+ * ZTM v2.0: Called by cranker after finalize_voting sets distribution_pending = true.
2641
+ * Processes batch of investments, transferring unlocked tokens to NFT holders.
2642
+ * Max batch size: 10 investments per call.
2643
+ *
2644
+ * @deprecated Use claimInvestorTokens instead (whitepaper manual claim model)
2645
+ */
2646
+ async distributeTokens(args) {
2647
+ return distributeTokens(
2648
+ this.program,
2649
+ args,
2650
+ this.walletPublicKey
2651
+ );
1249
2652
  }
1250
- async fetchAdminConfig() {
1251
- return fetchAdminConfig(this.program);
2653
+ /**
2654
+ * Complete token distribution for a milestone
2655
+ *
2656
+ * ZTM v2.0: Marks distribution as complete after all batches have been processed.
2657
+ * Permissionless - anyone can call this to finalize a distribution.
2658
+ */
2659
+ async completeDistribution(args) {
2660
+ return completeDistribution(
2661
+ this.program,
2662
+ args,
2663
+ this.walletPublicKey
2664
+ );
1252
2665
  }
1253
2666
  // ===========================================================================
1254
- // Admin Instructions
2667
+ // ZTM v2.0: Founder Vesting Instructions
1255
2668
  // ===========================================================================
1256
- async initializeAdmin(admin) {
1257
- return initializeAdmin(
2669
+ /**
2670
+ * Initialize founder vesting after MAE (Market Access Event)
2671
+ *
2672
+ * ZTM v2.0: Creates FounderVesting PDA with vesting schedule from Tokenomics.
2673
+ * Must be called after project reaches Completed state (all milestones done).
2674
+ * Permissionless - anyone can pay to initialize.
2675
+ */
2676
+ async initializeFounderVesting(args) {
2677
+ return initializeFounderVesting(
1258
2678
  this.program,
1259
- admin,
2679
+ args,
1260
2680
  this.walletPublicKey
1261
2681
  );
1262
2682
  }
1263
- async transferAdmin(newAdmin, adminKeypair) {
1264
- return transferAdmin(
2683
+ /**
2684
+ * Claim vested tokens from founder vault
2685
+ *
2686
+ * ZTM v2.0: Founder claims tokens based on linear vesting schedule.
2687
+ * Requires cliff period to pass before any tokens can be claimed.
2688
+ */
2689
+ async claimVestedTokens(args) {
2690
+ return claimVestedTokens(
1265
2691
  this.program,
1266
- adminKeypair,
1267
- newAdmin
2692
+ args,
2693
+ this.walletPublicKey
1268
2694
  );
1269
2695
  }
1270
- async acceptAdmin() {
1271
- return acceptAdmin(
2696
+ // ===========================================================================
2697
+ // ZTM v2.0: Circuit Breaker Instructions
2698
+ // ===========================================================================
2699
+ /**
2700
+ * Force complete a stuck distribution (admin only)
2701
+ *
2702
+ * ZTM v2.0: Circuit breaker for when token distribution is stuck for >7 days.
2703
+ * Marks distribution as complete so project can continue.
2704
+ * Affected investors can use claimMissedUnlock to get their tokens.
2705
+ */
2706
+ async forceCompleteDistribution(args, adminKeypair) {
2707
+ return forceCompleteDistribution(
2708
+ this.program,
2709
+ args,
2710
+ adminKeypair
2711
+ );
2712
+ }
2713
+ /**
2714
+ * Claim missed token unlock after force-complete distribution
2715
+ *
2716
+ * ZTM v2.0: Allows investors to claim tokens they missed during a stuck
2717
+ * distribution that was force-completed by admin.
2718
+ */
2719
+ async claimMissedUnlock(args) {
2720
+ return claimMissedUnlock(
1272
2721
  this.program,
2722
+ args,
1273
2723
  this.walletPublicKey
1274
2724
  );
1275
2725
  }
1276
2726
  // ===========================================================================
1277
- // Project Instructions
2727
+ // Early Token Release Instructions
1278
2728
  // ===========================================================================
1279
- async initializeProject(args) {
1280
- return initializeProject(
2729
+ /**
2730
+ * Claim early tokens as an investor (5% of token allocation)
2731
+ *
2732
+ * Early Token Release: Investors can claim 5% of their token allocation
2733
+ * 24 hours after investing. These tokens are fully liquid immediately.
2734
+ *
2735
+ * Prerequisites:
2736
+ * - 24h cooling period must have passed since investment
2737
+ * - Investment must not have already claimed early tokens
2738
+ * - Investment must have active voting rights
2739
+ */
2740
+ async claimEarlyTokens(args) {
2741
+ return claimEarlyTokens(
1281
2742
  this.program,
1282
2743
  args,
1283
2744
  this.walletPublicKey
1284
2745
  );
1285
2746
  }
1286
- async submitForApproval(projectId) {
1287
- return submitForApproval(
2747
+ /**
2748
+ * Claim early tokens as a founder (5% of founder allocation)
2749
+ *
2750
+ * Early Token Release: Founders can claim 5% of their token allocation
2751
+ * when the project becomes Funded. These tokens are fully liquid immediately.
2752
+ *
2753
+ * Prerequisites:
2754
+ * - Project must be in Funded, InProgress, or Completed state
2755
+ * - Founder must not have already claimed early tokens
2756
+ */
2757
+ async claimFounderEarlyTokens(args) {
2758
+ return claimFounderEarlyTokens(
1288
2759
  this.program,
1289
- projectId,
2760
+ args,
1290
2761
  this.walletPublicKey
1291
2762
  );
1292
2763
  }
1293
- async approveProject(args, adminKeypair) {
1294
- return approveProject(
2764
+ /**
2765
+ * Claim founder milestone-based tokens for a specific milestone
2766
+ *
2767
+ * Early Token Release: Founders can claim their milestone-based portion
2768
+ * (default 47.5% of founder allocation) when milestones are unlocked.
2769
+ *
2770
+ * Prerequisites:
2771
+ * - Milestone must be in Unlocked state
2772
+ * - Founder must not have already claimed tokens for this milestone
2773
+ */
2774
+ async claimFounderMilestoneTokens(args) {
2775
+ return claimFounderMilestoneTokens(
1295
2776
  this.program,
1296
2777
  args,
1297
- adminKeypair
2778
+ this.walletPublicKey
1298
2779
  );
1299
2780
  }
1300
2781
  // ===========================================================================
1301
- // Milestone Instructions
2782
+ // Per-Milestone Vesting Instructions (add-per-milestone-vesting)
1302
2783
  // ===========================================================================
1303
- async createMilestone(args) {
1304
- return createMilestone(
2784
+ /**
2785
+ * Claim instant tokens for a passed milestone (investor)
2786
+ *
2787
+ * Per-milestone vesting: Investors claim the instant portion (e.g., 5-50%)
2788
+ * immediately when a milestone passes. Creates vesting PDA on first claim.
2789
+ *
2790
+ * @param milestoneIndex - The milestone index to claim tokens from
2791
+ * @param nftMint - The NFT mint proving investment ownership
2792
+ * @param investorTokenAccount - Investor's token account to receive claimed tokens
2793
+ */
2794
+ async claimMilestoneInstantTokens(args) {
2795
+ return claimMilestoneInstantTokens(
1305
2796
  this.program,
1306
2797
  args,
1307
2798
  this.walletPublicKey
1308
2799
  );
1309
2800
  }
1310
- async submitMilestone(projectId, milestoneIndex) {
1311
- return submitMilestone(
2801
+ /**
2802
+ * Claim vested tokens for a milestone after cliff period (investor)
2803
+ *
2804
+ * Per-milestone vesting: Investors claim vested tokens linearly after
2805
+ * the cliff period passes. Must have already claimed instant tokens
2806
+ * to initialize the vesting PDA.
2807
+ *
2808
+ * @param milestoneIndex - The milestone index to claim vested tokens from
2809
+ * @param nftMint - The NFT mint proving investment ownership
2810
+ * @param investorTokenAccount - Investor's token account to receive claimed tokens
2811
+ */
2812
+ async claimMilestoneVestedTokens(args) {
2813
+ return claimMilestoneVestedTokens(
1312
2814
  this.program,
1313
- projectId,
1314
- milestoneIndex,
2815
+ args,
1315
2816
  this.walletPublicKey
1316
2817
  );
1317
2818
  }
1318
- async voteOnMilestone(args) {
1319
- return voteOnMilestone(
2819
+ /**
2820
+ * Claim instant tokens for a passed milestone (founder)
2821
+ *
2822
+ * Per-milestone vesting: Founders claim the instant portion (e.g., 5-50%)
2823
+ * of their milestone-based allocation when a milestone passes.
2824
+ *
2825
+ * @param milestoneIndex - The milestone index to claim tokens from
2826
+ * @param founderTokenAccount - Founder's token account to receive claimed tokens
2827
+ */
2828
+ async claimFounderMsInstantTokens(args) {
2829
+ return claimFounderMsInstantTokens(
1320
2830
  this.program,
1321
2831
  args,
1322
2832
  this.walletPublicKey
1323
2833
  );
1324
2834
  }
1325
- async finalizeVoting(projectId, milestoneIndex) {
1326
- return finalizeVoting(
2835
+ /**
2836
+ * Claim vested tokens for a milestone after cliff period (founder)
2837
+ *
2838
+ * Per-milestone vesting: Founders claim vested tokens linearly after
2839
+ * the cliff period passes. Must have already claimed instant tokens
2840
+ * to initialize the vesting PDA.
2841
+ *
2842
+ * @param milestoneIndex - The milestone index to claim vested tokens from
2843
+ * @param founderTokenAccount - Founder's token account to receive claimed tokens
2844
+ */
2845
+ async claimFounderMsVestedTokens(args) {
2846
+ return claimFounderMsVestedTokens(
2847
+ this.program,
2848
+ args,
2849
+ this.walletPublicKey
2850
+ );
2851
+ }
2852
+ // ===========================================================================
2853
+ // Abandonment Instructions
2854
+ // ===========================================================================
2855
+ async checkAbandonment(projectId, milestoneIndex = 0) {
2856
+ return checkAbandonment(
1327
2857
  this.program,
1328
2858
  projectId,
1329
2859
  milestoneIndex
1330
2860
  );
1331
2861
  }
2862
+ async claimRefund(args) {
2863
+ return claimRefund(
2864
+ this.program,
2865
+ args,
2866
+ this.walletPublicKey
2867
+ );
2868
+ }
2869
+ // ===========================================================================
2870
+ // Sub-Allocation Vesting Instructions
2871
+ // ===========================================================================
1332
2872
  /**
1333
- * Claim milestone funds (ZTM v2.0)
1334
- * - Regular milestones: Full payout to founder
1335
- * - Final milestone: LP USDC reserved for PCL, triggers MAE
2873
+ * Initialize sub-allocation vesting after MAE (Market Access Event)
1336
2874
  *
1337
- * @param nextMilestoneDeadline - Deadline for next milestone (required for non-final milestones)
1338
- * Set to BN(0) for final milestone claims (no next milestone exists)
2875
+ * Creates SubAllocationVesting PDA for a specific sub-allocation ID.
2876
+ * Project must be in Completed state with MAE completed.
2877
+ * Permissionless - anyone can pay to initialize.
1339
2878
  */
1340
- async claimMilestoneFunds(args) {
1341
- return claimMilestoneFunds(
2879
+ async initializeSubAllocationVesting(args) {
2880
+ return initializeSubAllocationVesting(
2881
+ this.program,
2882
+ args,
2883
+ this.walletPublicKey
2884
+ );
2885
+ }
2886
+ /**
2887
+ * Claim vested tokens from a sub-allocation
2888
+ *
2889
+ * Only the designated recipient wallet can claim tokens.
2890
+ * Project must be Completed and MAE must be completed.
2891
+ */
2892
+ async claimSubAllocationTokens(args) {
2893
+ return claimSubAllocationTokens(
2894
+ this.program,
2895
+ args,
2896
+ this.walletPublicKey
2897
+ );
2898
+ }
2899
+ // ===========================================================================
2900
+ // Dynamic Tokenomics Instructions
2901
+ // ===========================================================================
2902
+ /**
2903
+ * Add a sub-allocation from the reserve pool (Draft state only)
2904
+ *
2905
+ * Allows founders to add named allocations (advisors, marketing, etc.)
2906
+ * from their reserve pool before submitting for approval.
2907
+ */
2908
+ async addSubAllocation(args) {
2909
+ return addSubAllocation(
1342
2910
  this.program,
1343
2911
  args,
1344
2912
  this.walletPublicKey
1345
2913
  );
1346
2914
  }
1347
2915
  /**
1348
- * Resubmit a failed milestone for rework (Failed → InProgress)
2916
+ * Propose an allocation change via governance (post-Draft states)
1349
2917
  *
1350
- * Allows founders to iterate on failed milestones. Clears voting state
1351
- * for a fresh voting cycle. consecutive_failures is NOT reset.
2918
+ * Creates a 7-day voting period for investors to approve/reject
2919
+ * a new sub-allocation from the reserve pool.
1352
2920
  */
1353
- async resubmitMilestone(args) {
1354
- return resubmitMilestone(
2921
+ async proposeAllocationChange(args) {
2922
+ return proposeAllocationChange(
1355
2923
  this.program,
1356
2924
  args,
1357
2925
  this.walletPublicKey
1358
2926
  );
1359
2927
  }
1360
2928
  /**
1361
- * Set milestone deadline for founder to commit submission date
2929
+ * Vote on an allocation change proposal
1362
2930
  *
1363
- * Founders must set deadlines for milestones to provide visibility to investors.
1364
- * Deadline must be at least 7 days from now and at most 1 year from now.
2931
+ * Investors can vote for/against using their Investment NFT.
2932
+ * Must meet 7-day hold period for voting eligibility.
1365
2933
  */
1366
- async setMilestoneDeadline(args) {
1367
- return setMilestoneDeadline(
2934
+ async voteAllocationChange(args) {
2935
+ return voteAllocationChange(
1368
2936
  this.program,
1369
2937
  args,
1370
2938
  this.walletPublicKey
1371
2939
  );
1372
2940
  }
1373
2941
  /**
1374
- * Extend milestone deadline (max 3 extensions per milestone)
2942
+ * Execute an approved allocation change proposal
1375
2943
  *
1376
- * Founders can extend a deadline up to 3 times before it passes.
1377
- * Must be called BEFORE the current deadline passes.
2944
+ * Permissionless - anyone can call after voting ends.
2945
+ * Proposal must have passed (>51% approval).
1378
2946
  */
1379
- async extendMilestoneDeadline(args) {
1380
- return extendMilestoneDeadline(
2947
+ async executeAllocationChange(args) {
2948
+ return executeAllocationChange(
1381
2949
  this.program,
1382
2950
  args,
1383
2951
  this.walletPublicKey
1384
2952
  );
1385
2953
  }
1386
2954
  // ===========================================================================
1387
- // Investment Instructions
2955
+ // Dynamic Tokenomics Helpers
1388
2956
  // ===========================================================================
1389
- async invest(args) {
1390
- return invest(
1391
- this.program,
1392
- args,
1393
- this.walletPublicKey
1394
- );
2957
+ /**
2958
+ * Get remaining founder pool capacity for sub-allocations in basis points
2959
+ *
2960
+ * Calculates: founder_allocation_bps - sum(sub_allocations.bps)
2961
+ * Sub-allocations (treasury, advisors, marketing) draw from founder's allocation pool.
2962
+ */
2963
+ async getRemainingFounderPool(projectId) {
2964
+ const tokenomics = await this.fetchTokenomics(projectId);
2965
+ if (!tokenomics) {
2966
+ throw new Error("Tokenomics account not found");
2967
+ }
2968
+ const founderBps = tokenomics.founderAllocationBps || 0;
2969
+ const usedBps = (tokenomics.subAllocations || []).filter((sa) => sa.bps > 0).reduce((sum, sa) => sum + sa.bps, 0);
2970
+ return founderBps - usedBps;
1395
2971
  }
1396
- async cancelInvestment(args) {
1397
- return cancelInvestment(
1398
- this.program,
1399
- args,
1400
- this.walletPublicKey
1401
- );
2972
+ /**
2973
+ * Get all active (non-executed, non-expired) allocation proposals
2974
+ */
2975
+ async getActiveProposals(projectId) {
2976
+ const proposals = await this.fetchAllAllocationProposals(projectId);
2977
+ const now = Math.floor(Date.now() / 1e3);
2978
+ return proposals.filter((p) => {
2979
+ const account = p.account;
2980
+ return !account.executed && account.votingEndsAt.toNumber() > now;
2981
+ });
2982
+ }
2983
+ /**
2984
+ * Get vesting status for a sub-allocation
2985
+ *
2986
+ * Returns claimable amount, total vested, and remaining locked tokens.
2987
+ */
2988
+ async getSubAllocationVestingStatus(projectId, subAllocationId) {
2989
+ const vesting = await this.fetchSubAllocationVesting(projectId, subAllocationId);
2990
+ if (!vesting) {
2991
+ return null;
2992
+ }
2993
+ const now = Math.floor(Date.now() / 1e3);
2994
+ const cliffEnd = vesting.cliffEnd.toNumber();
2995
+ const vestingEnd = vesting.vestingEnd.toNumber();
2996
+ const totalAmount = vesting.totalAmount.toNumber();
2997
+ const claimedAmount = vesting.claimedAmount.toNumber();
2998
+ if (now < cliffEnd) {
2999
+ return {
3000
+ totalAmount,
3001
+ vestedAmount: 0,
3002
+ claimedAmount,
3003
+ claimableAmount: 0,
3004
+ lockedAmount: totalAmount - claimedAmount,
3005
+ vestingProgress: 0,
3006
+ cliffPassed: false
3007
+ };
3008
+ }
3009
+ if (now >= vestingEnd) {
3010
+ return {
3011
+ totalAmount,
3012
+ vestedAmount: totalAmount,
3013
+ claimedAmount,
3014
+ claimableAmount: totalAmount - claimedAmount,
3015
+ lockedAmount: 0,
3016
+ vestingProgress: 100,
3017
+ cliffPassed: true
3018
+ };
3019
+ }
3020
+ const vestingDuration = vestingEnd - cliffEnd;
3021
+ const elapsed = now - cliffEnd;
3022
+ const vestedAmount = Math.floor(totalAmount * elapsed / vestingDuration);
3023
+ return {
3024
+ totalAmount,
3025
+ vestedAmount,
3026
+ claimedAmount,
3027
+ claimableAmount: vestedAmount - claimedAmount,
3028
+ lockedAmount: totalAmount - vestedAmount,
3029
+ vestingProgress: Math.floor(elapsed / vestingDuration * 100),
3030
+ cliffPassed: true
3031
+ };
1402
3032
  }
1403
3033
  // ===========================================================================
1404
- // Pivot Instructions
3034
+ // Milestone Price Increase Helpers
1405
3035
  // ===========================================================================
1406
- async proposePivot(args) {
1407
- return proposePivot(
1408
- this.program,
1409
- args,
1410
- this.walletPublicKey
1411
- );
3036
+ /** Base price multiplier constant (10000 BPS = 1.0x) */
3037
+ static PRICE_MULTIPLIER_BASE = 1e4;
3038
+ /**
3039
+ * Get the current price multiplier for a project
3040
+ *
3041
+ * Returns the multiplier in BPS (10000 = 1.0x, 15000 = 1.5x)
3042
+ *
3043
+ * Supports two modes:
3044
+ * - Dynamic mode (priceMultipliers[0] === 0): Uses currentPriceMultiplierBps
3045
+ * calculated dynamically via ZEMYTH formula at each milestone claim
3046
+ * - Static mode (legacy): Uses pre-configured priceMultipliers array lookup
3047
+ */
3048
+ async getCurrentMultiplier(projectId) {
3049
+ const project = await this.fetchProject(projectId);
3050
+ if (!project) {
3051
+ throw new Error("Project account not found");
3052
+ }
3053
+ const { priceMultipliers, milestonesPassed, milestoneCount, currentPriceMultiplierBps } = project;
3054
+ if (priceMultipliers[0] === 0) {
3055
+ return currentPriceMultiplierBps || _RaiseClient.PRICE_MULTIPLIER_BASE;
3056
+ }
3057
+ const index = milestoneCount === 0 ? 0 : Math.min(milestonesPassed, milestoneCount - 1);
3058
+ return priceMultipliers[index] || _RaiseClient.PRICE_MULTIPLIER_BASE;
1412
3059
  }
1413
- async approvePivot(projectId, adminKeypair) {
1414
- return approvePivot(
1415
- this.program,
1416
- projectId,
1417
- adminKeypair
1418
- );
3060
+ /**
3061
+ * Check if a project uses dynamic price multiplier mode
3062
+ */
3063
+ async isDynamicMultiplierMode(projectId) {
3064
+ const project = await this.fetchProject(projectId);
3065
+ if (!project) {
3066
+ throw new Error("Project account not found");
3067
+ }
3068
+ return project.priceMultipliers[0] === 0;
1419
3069
  }
1420
- async withdrawFromPivot(args) {
1421
- return withdrawFromPivot(
1422
- this.program,
1423
- args,
1424
- this.walletPublicKey
1425
- );
3070
+ /**
3071
+ * Calculate effective tier prices with current multiplier
3072
+ *
3073
+ * Returns array of tiers with their effective prices after applying
3074
+ * the current milestone multiplier.
3075
+ */
3076
+ async getEffectiveTierPrices(projectId) {
3077
+ const project = await this.fetchProject(projectId);
3078
+ if (!project) {
3079
+ throw new Error("Project account not found");
3080
+ }
3081
+ const multiplier = await this.getCurrentMultiplier(projectId);
3082
+ const tiers = project.tiers.slice(0, project.tierCount);
3083
+ return tiers.map((tier, index) => ({
3084
+ tierIndex: index,
3085
+ baseAmount: tier.amount,
3086
+ effectiveAmount: tier.amount.mul(new BN(multiplier)).div(new BN(_RaiseClient.PRICE_MULTIPLIER_BASE)),
3087
+ multiplierBps: multiplier
3088
+ }));
1426
3089
  }
1427
- async finalizePivot(args) {
1428
- return finalizePivot(
1429
- this.program,
1430
- args,
1431
- this.walletPublicKey
1432
- );
3090
+ /**
3091
+ * Get price schedule showing multipliers after each milestone
3092
+ *
3093
+ * Returns array showing what the price multiplier will be
3094
+ * after each milestone passes.
3095
+ *
3096
+ * For dynamic mode projects (priceMultipliers[0] === 0), returns null
3097
+ * as multipliers are calculated dynamically based on deadline timing.
3098
+ */
3099
+ async getPriceSchedule(projectId) {
3100
+ const project = await this.fetchProject(projectId);
3101
+ if (!project) {
3102
+ throw new Error("Project account not found");
3103
+ }
3104
+ const { priceMultipliers, milestoneCount } = project;
3105
+ if (priceMultipliers[0] === 0) {
3106
+ return null;
3107
+ }
3108
+ return priceMultipliers.slice(0, milestoneCount).map((multiplier, index) => ({
3109
+ afterMilestone: index,
3110
+ multiplierBps: multiplier,
3111
+ multiplierPercent: multiplier / 100
3112
+ // 10000 -> 100%
3113
+ }));
3114
+ }
3115
+ /**
3116
+ * Preview multiplier calculation for dynamic mode projects
3117
+ *
3118
+ * Uses the ZEMYTH formula to calculate what the multiplier would be
3119
+ * given a specific number of remaining milestones and days to deadline.
3120
+ *
3121
+ * Formula: totalMultiplier = 1 + (sqrt(n) / sqrt(15)) × (1 / ln(d/7 + e))
3122
+ *
3123
+ * @param remainingMilestones Number of milestones left (1-10)
3124
+ * @param daysToDeadline Days until next milestone deadline (1-365)
3125
+ * @returns Preview of the multiplier in BPS (10000 = 1.0x, max 20000 = 2.0x)
3126
+ */
3127
+ previewDynamicMultiplier(remainingMilestones, daysToDeadline) {
3128
+ if (remainingMilestones === 0) {
3129
+ return _RaiseClient.PRICE_MULTIPLIER_BASE;
3130
+ }
3131
+ const days = Math.max(1, Math.min(365, daysToDeadline));
3132
+ const sqrtN = Math.sqrt(remainingMilestones) * 1e3;
3133
+ const milestoneFactor = sqrtN / 3.873;
3134
+ const timeFactor = this.timeFactorLookup(days);
3135
+ const combined = milestoneFactor * timeFactor / 1e3;
3136
+ const bonusBps = Math.min(combined, 1e4);
3137
+ return Math.min(2e4, Math.max(1e4, Math.round(1e4 + bonusBps)));
3138
+ }
3139
+ /** Time factor lookup for dynamic multiplier preview (approximates 1/ln(d/7 + e) × 1000) */
3140
+ timeFactorLookup(days) {
3141
+ if (days <= 7) return 950 - days * 25;
3142
+ if (days <= 14) return 775 - (days - 7) * 20;
3143
+ if (days <= 30) return 635 - (days - 14) * 8;
3144
+ if (days <= 60) return 507 - (days - 30) * 4;
3145
+ if (days <= 90) return 387 - (days - 60) * 3;
3146
+ if (days <= 180) return 297 - (days - 90) * 1;
3147
+ return 250;
1433
3148
  }
1434
3149
  // ===========================================================================
1435
- // TGE Instructions
3150
+ // Linear Progressive Pricing Helpers (add-linear-progressive-pricing)
1436
3151
  // ===========================================================================
1437
- async setTgeDate(args) {
1438
- return setTgeDate(
1439
- this.program,
1440
- args,
1441
- this.walletPublicKey
3152
+ /** Constants for progressive pricing */
3153
+ static TIME_ALLOCATION_PERCENT = 50;
3154
+ static MILESTONE_ALLOCATION_PERCENT = 50;
3155
+ /** DEV MODE: Time acceleration multiplier (10 real seconds = 1 simulated day) */
3156
+ static PROGRESSIVE_TIME_MULTIPLIER = 8640;
3157
+ /**
3158
+ * Check if progressive pricing is active for a project
3159
+ *
3160
+ * Progressive pricing is active when milestonePeriodStartedAt > 0,
3161
+ * meaning the first milestone period has been initialized.
3162
+ */
3163
+ isProgressivePricingActive(project) {
3164
+ return project.milestonePeriodStartedAt.gt(new BN(0));
3165
+ }
3166
+ /**
3167
+ * Calculate time progress for a milestone period
3168
+ *
3169
+ * @param project Project account with progressive pricing fields
3170
+ * @param currentTime Current unix timestamp (seconds)
3171
+ * @returns Progress as ratio 0-1 (capped at 1.0)
3172
+ */
3173
+ getTimeProgress(project, currentTime) {
3174
+ const startedAt = project.milestonePeriodStartedAt.toNumber();
3175
+ const deadline = project.expectedMilestoneDeadlineTs.toNumber();
3176
+ if (startedAt === 0 || deadline <= startedAt) {
3177
+ return 0;
3178
+ }
3179
+ const rawElapsed = Math.max(0, currentTime - startedAt);
3180
+ const elapsed = rawElapsed * _RaiseClient.PROGRESSIVE_TIME_MULTIPLIER;
3181
+ const expectedDuration = Math.max(1, deadline - startedAt);
3182
+ return Math.min(1, elapsed / expectedDuration);
3183
+ }
3184
+ /**
3185
+ * Calculate the effective multiplier including time-based component
3186
+ *
3187
+ * @param project Project account with progressive pricing fields
3188
+ * @param currentTime Current unix timestamp (seconds)
3189
+ * @returns Effective multiplier in BPS (10000 = 1.0x)
3190
+ */
3191
+ calculateEffectiveMultiplier(project, currentTime) {
3192
+ if (!this.isProgressivePricingActive(project)) {
3193
+ if (project.priceMultipliers[0] === 0) {
3194
+ return project.currentPriceMultiplierBps || _RaiseClient.PRICE_MULTIPLIER_BASE;
3195
+ }
3196
+ return project.currentPriceMultiplierBps || _RaiseClient.PRICE_MULTIPLIER_BASE;
3197
+ }
3198
+ const timeProgress = this.getTimeProgress(project, currentTime);
3199
+ const timeIncrement = Math.floor(project.timeAllocationBps * timeProgress);
3200
+ return project.milestoneBaseMultiplierBps + timeIncrement;
3201
+ }
3202
+ /**
3203
+ * Preview what the milestone spike will be at a given claim time
3204
+ *
3205
+ * If founder claims early, unused time allocation accumulates to spike.
3206
+ *
3207
+ * @param project Project account with progressive pricing fields
3208
+ * @param claimTime Unix timestamp when claim will happen
3209
+ * @returns Object with spike details
3210
+ */
3211
+ previewMilestoneSpike(project, claimTime) {
3212
+ const timeProgress = this.getTimeProgress(project, claimTime);
3213
+ const consumedTimeBps = Math.floor(project.timeAllocationBps * timeProgress);
3214
+ const unusedTimeBps = project.timeAllocationBps - consumedTimeBps;
3215
+ const milestoneSpikeBps = project.milestoneAllocationBps + unusedTimeBps;
3216
+ const effectiveMultiplierBps = project.milestoneBaseMultiplierBps + consumedTimeBps;
3217
+ const newBaseBps = effectiveMultiplierBps + milestoneSpikeBps;
3218
+ return {
3219
+ timeProgress,
3220
+ consumedTimeBps,
3221
+ unusedTimeBps,
3222
+ milestoneSpikeBps,
3223
+ effectiveMultiplierBps,
3224
+ newBaseBps
3225
+ };
3226
+ }
3227
+ /**
3228
+ * Get effective tier prices with time-based progressive pricing
3229
+ *
3230
+ * Unlike getEffectiveTierPrices which fetches the project, this takes
3231
+ * the project and current time to calculate prices including time component.
3232
+ */
3233
+ getProgressiveTierPrices(project, currentTime) {
3234
+ const multiplier = this.calculateEffectiveMultiplier(project, currentTime);
3235
+ const timeProgress = this.getTimeProgress(project, currentTime);
3236
+ const tiers = project.tiers.slice(0, project.tierCount);
3237
+ return tiers.map((tier, index) => ({
3238
+ tierIndex: index,
3239
+ baseAmount: tier.amount,
3240
+ effectiveAmount: tier.amount.mul(new BN(multiplier)).div(new BN(_RaiseClient.PRICE_MULTIPLIER_BASE)),
3241
+ multiplierBps: multiplier,
3242
+ timeProgressPercent: Math.round(timeProgress * 100)
3243
+ }));
3244
+ }
3245
+ // ===========================================================================
3246
+ // Multi-Round Fundraising PDAs
3247
+ // ===========================================================================
3248
+ getFundingRoundPDA(projectPda, roundNumber) {
3249
+ return getFundingRoundPDA(projectPda, roundNumber, this.programId);
3250
+ }
3251
+ getRoundEscrowPDA(projectPda, roundNumber) {
3252
+ return getRoundEscrowPDA(projectPda, roundNumber, this.programId);
3253
+ }
3254
+ getRoundMilestonePDA(projectPda, roundNumber, milestoneIndex) {
3255
+ return getRoundMilestonePDA(projectPda, roundNumber, milestoneIndex, this.programId);
3256
+ }
3257
+ getRoundInvestmentPDA(projectPda, roundNumber, nftMint) {
3258
+ return getRoundInvestmentPDA(projectPda, roundNumber, nftMint, this.programId);
3259
+ }
3260
+ getRoundInvestorMilestoneVestingPDA(projectPda, roundNumber, milestoneIndex, investmentPda) {
3261
+ return getRoundInvestorMilestoneVestingPDA(
3262
+ projectPda,
3263
+ roundNumber,
3264
+ milestoneIndex,
3265
+ investmentPda,
3266
+ this.programId
1442
3267
  );
1443
3268
  }
1444
- async depositTokens(args) {
1445
- return depositTokens(
3269
+ getFutureRoundVaultPDA(projectPda) {
3270
+ return getFutureRoundVaultPDA(projectPda, this.programId);
3271
+ }
3272
+ getFutureRoundTokenVaultPDA(projectPda) {
3273
+ return getFutureRoundTokenVaultPDA(projectPda, this.programId);
3274
+ }
3275
+ // ===========================================================================
3276
+ // Multi-Round Fundraising Account Fetchers
3277
+ // ===========================================================================
3278
+ async fetchFundingRound(projectId, roundNumber) {
3279
+ return fetchFundingRound(this.program, projectId, roundNumber);
3280
+ }
3281
+ async fetchAllFundingRounds(projectId) {
3282
+ return fetchAllFundingRounds(this.program, projectId);
3283
+ }
3284
+ async fetchRoundMilestone(projectId, roundNumber, milestoneIndex) {
3285
+ return fetchRoundMilestone(this.program, projectId, roundNumber, milestoneIndex);
3286
+ }
3287
+ async fetchRoundInvestment(projectId, roundNumber, nftMint) {
3288
+ return fetchRoundInvestment(this.program, projectId, roundNumber, nftMint);
3289
+ }
3290
+ async fetchFutureRoundVault(projectId) {
3291
+ return fetchFutureRoundVault(this.program, projectId);
3292
+ }
3293
+ // ===========================================================================
3294
+ // Multi-Round Fundraising Instructions
3295
+ // ===========================================================================
3296
+ /**
3297
+ * Open a new funding round (R2, R3, R4...)
3298
+ *
3299
+ * Multi-Round Fundraising: Creates FundingRound PDA, round escrow,
3300
+ * and milestone PDAs for the new round. Tokens come from FutureRoundVault.
3301
+ *
3302
+ * Prerequisites:
3303
+ * - Project must be InProgress or Completed state
3304
+ * - At least 1 milestone must have passed (for InProgress projects)
3305
+ * - No other round currently Open
3306
+ * - Current round must be fully funded before opening next
3307
+ * - Must have future_round_allocation configured in tokenomics
3308
+ */
3309
+ async openFundingRound(args) {
3310
+ return openFundingRound(
1446
3311
  this.program,
1447
3312
  args,
1448
3313
  this.walletPublicKey
1449
3314
  );
1450
3315
  }
1451
- async claimTokens(args) {
1452
- return claimTokens(
3316
+ /**
3317
+ * Invest in a funding round (R2, R3, R4...)
3318
+ *
3319
+ * Multi-Round Fundraising: Creates investment NFT and deposits USDC
3320
+ * to the round-specific escrow. Tokens come from FutureRoundVault.
3321
+ */
3322
+ async investInRound(args) {
3323
+ return investInRound(
1453
3324
  this.program,
1454
3325
  args,
1455
3326
  this.walletPublicKey
1456
3327
  );
1457
3328
  }
1458
- async reportScam(args) {
1459
- return reportScam(
3329
+ /**
3330
+ * Cancel round investment within 24-hour cooling-off period
3331
+ *
3332
+ * Multi-Round Fundraising: Returns USDC from round escrow,
3333
+ * closes investment account.
3334
+ */
3335
+ async cancelRoundInvestment(args) {
3336
+ return cancelRoundInvestment(
1460
3337
  this.program,
1461
3338
  args,
1462
3339
  this.walletPublicKey
1463
3340
  );
1464
3341
  }
1465
- async releaseHoldback(args) {
1466
- return releaseHoldback(
1467
- this.program,
1468
- args
1469
- );
1470
- }
1471
- // ===========================================================================
1472
- // ZTM v2.0 Token Distribution Instructions
1473
- // ===========================================================================
1474
3342
  /**
1475
- * Claim investor tokens from a passed milestone (whitepaper: manual claim model)
3343
+ * Submit round milestone for investor review
1476
3344
  *
1477
- * ZTM v2.0: Per whitepaper, investors manually claim their tokens after a milestone passes.
1478
- * This replaces the batch distribution model with investor-initiated per-NFT claims.
3345
+ * Multi-Round Fundraising: Transitions milestone to UnderReview,
3346
+ * sets voting deadline.
1479
3347
  */
1480
- async claimInvestorTokens(args) {
1481
- return claimInvestorTokens(
3348
+ async submitRoundMilestone(args) {
3349
+ return submitRoundMilestone(
1482
3350
  this.program,
1483
3351
  args,
1484
3352
  this.walletPublicKey
1485
3353
  );
1486
3354
  }
1487
3355
  /**
1488
- * Distribute tokens to NFT holders for a milestone
1489
- *
1490
- * ZTM v2.0: Called by cranker after finalize_voting sets distribution_pending = true.
1491
- * Processes batch of investments, transferring unlocked tokens to NFT holders.
1492
- * Max batch size: 10 investments per call.
3356
+ * Vote on a round milestone (unified voting - ANY investor can vote)
1493
3357
  *
1494
- * @deprecated Use claimInvestorTokens instead (whitepaper manual claim model)
3358
+ * Multi-Round Fundraising: R1, R2, R3... investors can all vote
3359
+ * on any round's milestones. Investment can be from any round.
1495
3360
  */
1496
- async distributeTokens(args) {
1497
- return distributeTokens(
3361
+ async voteOnRoundMilestone(args) {
3362
+ return voteOnRoundMilestone(
1498
3363
  this.program,
1499
3364
  args,
1500
3365
  this.walletPublicKey
1501
3366
  );
1502
3367
  }
1503
3368
  /**
1504
- * Complete token distribution for a milestone
3369
+ * Finalize voting on a round milestone
1505
3370
  *
1506
- * ZTM v2.0: Marks distribution as complete after all batches have been processed.
1507
- * Permissionless - anyone can call this to finalize a distribution.
3371
+ * Multi-Round Fundraising: Processes vote results, transitions
3372
+ * milestone to Passed or Failed state.
1508
3373
  */
1509
- async completeDistribution(args) {
1510
- return completeDistribution(
3374
+ async finalizeRoundVoting(args) {
3375
+ return finalizeRoundVoting(
1511
3376
  this.program,
1512
- args,
1513
- this.walletPublicKey
3377
+ args
1514
3378
  );
1515
3379
  }
1516
- // ===========================================================================
1517
- // ZTM v2.0: Founder Vesting Instructions
1518
- // ===========================================================================
1519
3380
  /**
1520
- * Initialize founder vesting after MAE (Market Access Event)
3381
+ * Claim milestone funds from a round (founder)
1521
3382
  *
1522
- * ZTM v2.0: Creates FounderVesting PDA with vesting schedule from Tokenomics.
1523
- * Must be called after project reaches Completed state (all milestones done).
1524
- * Permissionless - anyone can pay to initialize.
3383
+ * Multi-Round Fundraising: Transfers USDC from round escrow
3384
+ * to founder's account.
3385
+ *
3386
+ * @param nextMilestoneDeadline - Deadline for next milestone (required for non-final)
3387
+ * Set to BN(0) for final milestone claims
1525
3388
  */
1526
- async initializeFounderVesting(args) {
1527
- return initializeFounderVesting(
3389
+ async claimRoundMilestoneFunds(args) {
3390
+ return claimRoundMilestoneFunds(
1528
3391
  this.program,
1529
3392
  args,
1530
3393
  this.walletPublicKey
1531
3394
  );
1532
3395
  }
1533
3396
  /**
1534
- * Claim vested tokens from founder vault
3397
+ * Claim instant tokens for a round milestone (investor)
1535
3398
  *
1536
- * ZTM v2.0: Founder claims tokens based on linear vesting schedule.
1537
- * Requires cliff period to pass before any tokens can be claimed.
3399
+ * Multi-Round Fundraising: R2+ investors claim instant portion
3400
+ * when milestone passes. Tokens come from FutureRoundVault.
1538
3401
  */
1539
- async claimVestedTokens(args) {
1540
- return claimVestedTokens(
3402
+ async claimRoundInstantTokens(args) {
3403
+ return claimRoundInstantTokens(
1541
3404
  this.program,
1542
3405
  args,
1543
3406
  this.walletPublicKey
1544
3407
  );
1545
3408
  }
1546
- // ===========================================================================
1547
- // ZTM v2.0: Circuit Breaker Instructions
1548
- // ===========================================================================
1549
3409
  /**
1550
- * Force complete a stuck distribution (admin only)
3410
+ * Claim vested tokens for a round milestone (investor)
1551
3411
  *
1552
- * ZTM v2.0: Circuit breaker for when token distribution is stuck for >7 days.
1553
- * Marks distribution as complete so project can continue.
1554
- * Affected investors can use claimMissedUnlock to get their tokens.
3412
+ * Multi-Round Fundraising: R2+ investors claim vested portion
3413
+ * after cliff period. Tokens come from FutureRoundVault.
1555
3414
  */
1556
- async forceCompleteDistribution(args, adminKeypair) {
1557
- return forceCompleteDistribution(
3415
+ async claimRoundVestedTokens(args) {
3416
+ return claimRoundVestedTokens(
1558
3417
  this.program,
1559
3418
  args,
1560
- adminKeypair
3419
+ this.walletPublicKey
1561
3420
  );
1562
3421
  }
1563
3422
  /**
1564
- * Claim missed token unlock after force-complete distribution
3423
+ * Claim early tokens for a round investment (5% after 24h)
1565
3424
  *
1566
- * ZTM v2.0: Allows investors to claim tokens they missed during a stuck
1567
- * distribution that was force-completed by admin.
3425
+ * Multi-Round Fundraising: R2+ investors claim 5% of token allocation
3426
+ * 24 hours after investing. Tokens come from FutureRoundVault.
1568
3427
  */
1569
- async claimMissedUnlock(args) {
1570
- return claimMissedUnlock(
3428
+ async claimRoundEarlyTokens(args) {
3429
+ return claimRoundEarlyTokens(
1571
3430
  this.program,
1572
3431
  args,
1573
3432
  this.walletPublicKey
1574
3433
  );
1575
3434
  }
1576
3435
  // ===========================================================================
1577
- // Abandonment Instructions
3436
+ // Multi-Round Fundraising Helpers
1578
3437
  // ===========================================================================
1579
- async checkAbandonment(projectId, milestoneIndex = 0) {
1580
- return checkAbandonment(
1581
- this.program,
1582
- projectId,
1583
- milestoneIndex
1584
- );
3438
+ /**
3439
+ * Check if the next funding round can be opened
3440
+ *
3441
+ * Returns eligibility status with reason and next round number.
3442
+ */
3443
+ async canOpenNextRound(projectId) {
3444
+ return canOpenNextRound(this.program, projectId);
1585
3445
  }
1586
- async claimRefund(args) {
1587
- return claimRefund(
1588
- this.program,
1589
- args,
1590
- this.walletPublicKey
1591
- );
3446
+ /**
3447
+ * Get remaining future round allocation in BPS
3448
+ */
3449
+ getRemainingFutureRoundAllocation(tokenomics) {
3450
+ return getRemainingFutureRoundAllocation(tokenomics);
3451
+ }
3452
+ /**
3453
+ * Check if a specific round is fully funded
3454
+ */
3455
+ async isRoundFullyFunded(projectId, roundNumber) {
3456
+ return isRoundFullyFunded(this.program, projectId, roundNumber);
3457
+ }
3458
+ /**
3459
+ * Get round details with computed state
3460
+ *
3461
+ * Returns funding round data with additional computed fields.
3462
+ */
3463
+ async getRoundDetails(projectId, roundNumber) {
3464
+ const fundingRound = await this.fetchFundingRound(projectId, roundNumber);
3465
+ if (!fundingRound) {
3466
+ return null;
3467
+ }
3468
+ const milestones = [];
3469
+ for (let i = 0; i < fundingRound.milestoneCount; i++) {
3470
+ const milestone = await this.fetchRoundMilestone(projectId, roundNumber, i);
3471
+ if (milestone) {
3472
+ milestones.push(milestone);
3473
+ }
3474
+ }
3475
+ const totalRaised = fundingRound.totalRaised.toNumber();
3476
+ const fundingGoal = fundingRound.fundingGoal.toNumber();
3477
+ const fundingProgress = fundingGoal > 0 ? totalRaised / fundingGoal * 100 : 0;
3478
+ return {
3479
+ ...fundingRound,
3480
+ milestones,
3481
+ fundingProgress,
3482
+ isFullyFunded: totalRaised >= fundingGoal
3483
+ };
1592
3484
  }
1593
3485
  };
1594
3486
 
@@ -1627,6 +3519,14 @@ var PivotState = /* @__PURE__ */ ((PivotState2) => {
1627
3519
  PivotState2["Finalized"] = "finalized";
1628
3520
  return PivotState2;
1629
3521
  })(PivotState || {});
3522
+ var FundingRoundState = /* @__PURE__ */ ((FundingRoundState2) => {
3523
+ FundingRoundState2["Open"] = "open";
3524
+ FundingRoundState2["Funded"] = "funded";
3525
+ FundingRoundState2["InProgress"] = "inProgress";
3526
+ FundingRoundState2["Completed"] = "completed";
3527
+ FundingRoundState2["Failed"] = "failed";
3528
+ return FundingRoundState2;
3529
+ })(FundingRoundState || {});
1630
3530
  var ERROR_CODES = {
1631
3531
  // State Transition Errors (6000-6099)
1632
3532
  InvalidStateTransition: 6e3,
@@ -1921,6 +3821,6 @@ function shortenPublicKey(pubkey, chars = 4) {
1921
3821
  return `${str.slice(0, chars)}...${str.slice(-chars)}`;
1922
3822
  }
1923
3823
 
1924
- export { ERROR_CODES, ERROR_MESSAGES, EVENT_NAMES, GOVERNANCE, InvestmentTier, MAX_DEADLINE_DURATION_SECONDS, MIN_DEADLINE_DURATION_SECONDS_DEV, MIN_DEADLINE_DURATION_SECONDS_PROD, MilestoneState, NFT, PivotState, ProjectState, RaiseClient, RaiseError, SEEDS, TIER_CONSTRAINTS, TIER_MINIMUMS, TIER_TOKEN_MULTIPLIERS, TIER_VOTE_MULTIPLIERS, TIMING, USDC, VALIDATION, VoteChoice, acceptAdmin, accountExists, approvePivot, approveProject, bigIntToBN, bnToBigInt, bnToNumber, bpsToPercent, calculateDeadline, cancelInvestment, checkAbandonment, claimExitWindowRefund, claimInvestorTokens, claimMilestoneFunds, claimMissedUnlock, claimRefund, claimTokens, claimVestedTokens, completeDistribution, confirmTransaction, createMilestone, depositTokens, distributeTokens, extendMilestoneDeadline, fetchAdminConfig, fetchAllInvestments, fetchAllMilestones, fetchAllVotes, fetchInvestment, fetchMilestone, fetchPivotProposal, fetchProject, fetchProjectByPda, fetchTgeEscrow, fetchVote, filterEventsByName, finalizePivot, finalizeVoting, findEvent, findTierIndex, forceCompleteDistribution, formatDuration, getAdminConfigPDA, getCurrentTimestamp, getErrorMessage, getEscrowPDA, getFounderVaultPDA, getFounderVestingPDA, getInvestmentPDA, getInvestorVaultPDA, getLpTokenVaultPDA, getLpUsdcVaultPDA, getMilestonePDA, getNftMintPDA, getPivotProposalPDA, getProgramAuthorityPDA, getProjectPDA, getProjectPDAs, getScamReportPDA, getTgeEscrowPDA, getTierFromAmount, getTokenMintPDA, getTokenMultiplier, getTokenVaultPDA, getTokenomicsPDA, getTransactionWithRetry, getTreasuryVaultPDA, getVaultAuthorityPDA, getVoteMultiplier, getVotePDA, hasTimestampPassed, initializeAdmin, initializeFounderVesting, initializeProject, invest, isRaiseError, isValidPublicKey, minDeadline, parseError, percentToBps, percentageOf, proposePivot, releaseHoldback, reportScam, resubmitMilestone, setMilestoneDeadline, setTgeDate, shortenPublicKey, submitForApproval, submitMilestone, symbolToBytes, timeRemaining, timestampToDate, transferAdmin, validateDeadline, validateMetadataUri, validateMilestonePercentages, voteOnMilestone, withdrawFromPivot };
3824
+ export { EARLY_TOKEN_COOLING_PERIOD_SECONDS, EARLY_TOKEN_COOLING_PERIOD_SECONDS_DEV, EARLY_TOKEN_RELEASE_BPS, ERROR_CODES, ERROR_MESSAGES, EVENT_NAMES, FundingRoundState, GOVERNANCE, InvestmentTier, MAX_DEADLINE_DURATION_SECONDS, MIN_DEADLINE_DURATION_SECONDS_DEV, MIN_DEADLINE_DURATION_SECONDS_PROD, MilestoneState, NFT, PivotState, ProjectState, RaiseClient, RaiseError, SEEDS, TIER_CONSTRAINTS, TIER_MINIMUMS, TIER_TOKEN_MULTIPLIERS, TIER_VOTE_MULTIPLIERS, TIMING, TOKENOMICS, USDC, VALIDATION, VoteChoice, acceptAdmin, accountExists, approvePivot, approveProject, bigIntToBN, bnToBigInt, bnToNumber, bpsToPercent, calculateDeadline, calculateEarlyTokenAmount, calculateRemainingAllocation, canClaimEarlyTokens, canClaimFounderEarlyTokens, canClaimFounderMilestoneTokens, canClaimRoundEarlyTokens, cancelInvestment, cancelRoundInvestment, checkAbandonment, claimExitWindowRefund, claimInvestorTokens, claimMilestoneFunds, claimMissedUnlock, claimRefund, claimRoundEarlyTokens, claimRoundInstantTokens, claimRoundMilestoneFunds, claimRoundVestedTokens, claimTokens, claimVestedTokens, completeDistribution, confirmTransaction, createMilestone, depositTokens, distributeTokens, extendMilestoneDeadline, fetchAdminConfig, fetchAllFundingRounds, fetchAllInvestments, fetchAllMilestones, fetchAllVotes, fetchFundingRound, fetchFutureRoundVault, fetchInvestment, fetchMilestone, fetchPivotProposal, fetchProject, fetchProjectByPda, fetchRoundInvestment, fetchRoundInvestorMilestoneVesting, fetchRoundMilestone, fetchTgeEscrow, fetchVote, filterEventsByName, finalizePivot, finalizeRoundVoting, finalizeVoting, findEvent, findTierIndex, forceCompleteDistribution, formatDuration, getAdminConfigPDA, getCurrentTimestamp, getErrorMessage, getEscrowPDA, getFounderVaultPDA, getFounderVestingPDA, getFundingRoundPDA, getFutureRoundTokenVaultPDA, getFutureRoundVaultPDA, getInvestmentPDA, getInvestorVaultPDA, getLpTokenVaultPDA, getLpUsdcVaultPDA, getMilestonePDA, getNftMintPDA, getPivotProposalPDA, getProgramAuthorityPDA, getProjectPDA, getProjectPDAs, getRoundEscrowPDA, getRoundInvestmentPDA, getRoundInvestorMilestoneVestingPDA, getRoundMilestonePDA, getRoundNftMintPDA, getScamReportPDA, getTgeEscrowPDA, getTierFromAmount, getTokenMintPDA, getTokenMultiplier, getTokenVaultPDA, getTokenomicsPDA, getTransactionWithRetry, getTreasuryVaultPDA, getVaultAuthorityPDA, getVoteMultiplier, getVotePDA, hasTimestampPassed, initializeAdmin, initializeFounderVesting, initializeProject, invest, investInRound, isRaiseError, isValidPublicKey, minDeadline, openFundingRound, parseError, percentToBps, percentageOf, proposePivot, releaseHoldback, reportScam, requiresBurnForRefund, resubmitMilestone, setMilestoneDeadline, setTgeDate, shortenPublicKey, submitForApproval, submitMilestone, submitRoundMilestone, symbolToBytes, timeRemaining, timestampToDate, transferAdmin, validateDeadline, validateMetadataUri, validateMilestonePercentages, voteOnMilestone, voteOnRoundMilestone, withdrawFromPivot };
1925
3825
  //# sourceMappingURL=index.js.map
1926
3826
  //# sourceMappingURL=index.js.map