@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.
- package/README.md +11 -9
- package/dist/accounts/index.cjs +531 -3
- package/dist/accounts/index.cjs.map +1 -1
- package/dist/accounts/index.d.cts +307 -2
- package/dist/accounts/index.d.ts +307 -2
- package/dist/accounts/index.js +503 -4
- package/dist/accounts/index.js.map +1 -1
- package/dist/constants/index.cjs +41 -3
- package/dist/constants/index.cjs.map +1 -1
- package/dist/constants/index.d.cts +38 -3
- package/dist/constants/index.d.ts +38 -3
- package/dist/constants/index.js +40 -4
- package/dist/constants/index.js.map +1 -1
- package/dist/index.cjs +2297 -361
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +566 -7
- package/dist/index.d.ts +566 -7
- package/dist/index.js +2279 -379
- package/dist/index.js.map +1 -1
- package/dist/instructions/index.cjs +783 -40
- package/dist/instructions/index.cjs.map +1 -1
- package/dist/instructions/index.d.cts +492 -6
- package/dist/instructions/index.d.ts +492 -6
- package/dist/instructions/index.js +762 -42
- package/dist/instructions/index.js.map +1 -1
- package/dist/pdas/index.cjs +163 -1
- package/dist/pdas/index.cjs.map +1 -1
- package/dist/pdas/index.d.cts +131 -1
- package/dist/pdas/index.d.ts +131 -1
- package/dist/pdas/index.js +151 -2
- package/dist/pdas/index.js.map +1 -1
- package/dist/types/index.cjs +9 -0
- package/dist/types/index.cjs.map +1 -1
- package/dist/types/index.d.cts +586 -3
- package/dist/types/index.d.ts +586 -3
- package/dist/types/index.js +9 -1
- package/dist/types/index.js.map +1 -1
- package/package.json +5 -3
- package/src/__tests__/dynamic-tokenomics.test.ts +358 -0
- package/src/accounts/index.ts +852 -1
- package/src/client.ts +1130 -1
- package/src/constants/index.ts +48 -2
- package/src/index.ts +58 -0
- package/src/instructions/index.ts +1383 -40
- package/src/pdas/index.ts +346 -0
- package/src/types/index.ts +698 -2
- package/src/utils/index.ts +90 -0
package/dist/index.cjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var web3_js = require('@solana/web3.js');
|
|
4
3
|
var anchor = require('@coral-xyz/anchor');
|
|
4
|
+
var web3_js = require('@solana/web3.js');
|
|
5
5
|
var splToken = require('@solana/spl-token');
|
|
6
6
|
|
|
7
|
-
// src/
|
|
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: "
|
|
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
|
-
|
|
382
|
+
function getAllocationProposalPDA(projectPda, proposalIndex, programId) {
|
|
383
|
+
const [pda] = web3_js.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] = web3_js.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] = web3_js.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] = web3_js.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] = web3_js.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] = web3_js.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] = web3_js.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] = web3_js.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] = web3_js.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] = web3_js.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 web3_js.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] = web3_js.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] = web3_js.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
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
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 web3_js.PublicKey(String(value));
|
|
517
|
-
}
|
|
518
|
-
function getMethods(program) {
|
|
519
|
-
return program.methods;
|
|
520
701
|
}
|
|
521
|
-
function
|
|
522
|
-
|
|
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
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
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
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
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
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
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
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
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
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
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
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
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
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
const
|
|
570
|
-
const
|
|
571
|
-
if (
|
|
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
|
-
|
|
575
|
-
|
|
815
|
+
canClaim: false,
|
|
816
|
+
reason: `Project must be in Funded, InProgress, or Completed state. Current state: ${stateStr}`
|
|
576
817
|
};
|
|
577
818
|
}
|
|
578
|
-
|
|
819
|
+
return { canClaim: true };
|
|
820
|
+
}
|
|
821
|
+
function canClaimFounderMilestoneTokens(milestone) {
|
|
822
|
+
const stateStr = getMilestoneStateString(milestone.state);
|
|
823
|
+
if (stateStr !== "unlocked") {
|
|
579
824
|
return {
|
|
580
|
-
|
|
581
|
-
|
|
825
|
+
canClaim: false,
|
|
826
|
+
reason: `Milestone must be in Unlocked state. Current state: ${stateStr}`
|
|
582
827
|
};
|
|
583
828
|
}
|
|
584
|
-
return {
|
|
829
|
+
return { canClaim: true };
|
|
585
830
|
}
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
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 anchor.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 anchor.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 anchor.BN(project.totalRaised) : project.totalRaised;
|
|
965
|
+
const goal = typeof project.fundingGoal === "number" ? new anchor.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 web3_js.PublicKey("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s");
|
|
1048
|
+
function ensurePublicKey(value) {
|
|
1049
|
+
if (value instanceof web3_js.PublicKey) {
|
|
1050
|
+
return value;
|
|
1051
|
+
}
|
|
1052
|
+
return new web3_js.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 anchor.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 anchor.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
|
-
|
|
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().
|
|
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
|
-
|
|
1167
|
+
const futureRoundTokenVaultPda = getFutureRoundTokenVaultPDA(projectPda, program.programId);
|
|
1168
|
+
const futureRoundVaultPda = getFutureRoundVaultPDA(projectPda, program.programId);
|
|
1169
|
+
const computeBudgetIx = web3_js.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
|
-
|
|
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().
|
|
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
|
splToken.TOKEN_PROGRAM_ID
|
|
679
1229
|
);
|
|
680
|
-
return getMethods(program).voteOnMilestone({ choice: args.choice }).
|
|
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().
|
|
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 anchor.BN(0)) ? getMilestonePDA(projectPda, args.milestoneIndex + 1, program.programId) : null);
|
|
706
|
-
return getMethods(program).claimMilestoneFunds({ nextMilestoneDeadline: args.nextMilestoneDeadline }).
|
|
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().
|
|
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
|
-
}).
|
|
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
|
-
}).
|
|
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 }).
|
|
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().
|
|
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
|
-
}).
|
|
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().
|
|
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().
|
|
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().
|
|
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
|
-
}).
|
|
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 }).
|
|
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().
|
|
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().
|
|
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().
|
|
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().
|
|
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().
|
|
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
|
splToken.TOKEN_PROGRAM_ID
|
|
998
1548
|
);
|
|
999
|
-
return getMethods(program).claimInvestorTokens({ milestoneIndex: args.milestoneIndex }).
|
|
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 }).
|
|
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 }).
|
|
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().
|
|
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().
|
|
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().
|
|
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
|
splToken.TOKEN_PROGRAM_ID
|
|
1113
1663
|
);
|
|
1114
|
-
return getMethods(program).claimMissedUnlock({ milestoneIndex: args.milestoneIndex }).
|
|
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: splToken.TOKEN_PROGRAM_ID
|
|
1125
1675
|
}).rpc();
|
|
1126
1676
|
}
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
}
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
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: web3_js.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 = splToken.getAssociatedTokenAddressSync(
|
|
1719
|
+
nftMintPubkey,
|
|
1720
|
+
voter,
|
|
1721
|
+
false,
|
|
1722
|
+
splToken.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: web3_js.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 = splToken.getAssociatedTokenAddressSync(
|
|
1754
|
+
nftMintPubkey,
|
|
1755
|
+
investor,
|
|
1756
|
+
false,
|
|
1757
|
+
splToken.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: splToken.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: splToken.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: splToken.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: web3_js.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: splToken.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 = splToken.getAssociatedTokenAddressSync(
|
|
1851
|
+
nftMintPubkey,
|
|
1852
|
+
investor,
|
|
1853
|
+
false,
|
|
1854
|
+
splToken.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: splToken.TOKEN_PROGRAM_ID,
|
|
1869
|
+
systemProgram: web3_js.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 = splToken.getAssociatedTokenAddressSync(
|
|
1882
|
+
nftMintPubkey,
|
|
1883
|
+
investor,
|
|
1884
|
+
false,
|
|
1885
|
+
splToken.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: splToken.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: splToken.TOKEN_PROGRAM_ID,
|
|
1921
|
+
systemProgram: web3_js.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: splToken.TOKEN_PROGRAM_ID
|
|
1939
|
+
}).rpc();
|
|
1940
|
+
}
|
|
1941
|
+
function getRoundEscrowAuthorityPDA(projectPda, roundNumber, programId) {
|
|
1942
|
+
return web3_js.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: splToken.TOKEN_PROGRAM_ID,
|
|
1990
|
+
systemProgram: web3_js.SystemProgram.programId,
|
|
1991
|
+
rent: web3_js.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 = splToken.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: splToken.TOKEN_PROGRAM_ID,
|
|
2019
|
+
associatedTokenProgram: splToken.ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
2020
|
+
systemProgram: web3_js.SystemProgram.programId,
|
|
2021
|
+
rent: web3_js.SYSVAR_RENT_PUBKEY,
|
|
2022
|
+
tokenMetadataProgram: TOKEN_METADATA_PROGRAM_ID,
|
|
2023
|
+
sysvarInstructions: web3_js.SYSVAR_INSTRUCTIONS_PUBKEY
|
|
2024
|
+
}).preInstructions([
|
|
2025
|
+
web3_js.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: splToken.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: web3_js.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 = splToken.getAssociatedTokenAddressSync(
|
|
2075
|
+
nftMintPubkey,
|
|
2076
|
+
voter,
|
|
2077
|
+
false,
|
|
2078
|
+
splToken.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: web3_js.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: web3_js.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 anchor.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: web3_js.SystemProgram.programId,
|
|
2120
|
+
tokenProgram: splToken.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 = splToken.getAssociatedTokenAddressSync(
|
|
2141
|
+
nftMintPubkey,
|
|
2142
|
+
investor,
|
|
2143
|
+
false,
|
|
2144
|
+
splToken.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: splToken.TOKEN_PROGRAM_ID,
|
|
2161
|
+
systemProgram: web3_js.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 = splToken.getAssociatedTokenAddressSync(
|
|
2182
|
+
nftMintPubkey,
|
|
2183
|
+
investor,
|
|
2184
|
+
false,
|
|
2185
|
+
splToken.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: splToken.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 = splToken.getAssociatedTokenAddressSync(
|
|
2214
|
+
nftMintPubkey,
|
|
2215
|
+
investor,
|
|
2216
|
+
false,
|
|
2217
|
+
splToken.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: splToken.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
|
+
);
|
|
1219
2552
|
}
|
|
1220
2553
|
// ===========================================================================
|
|
1221
|
-
//
|
|
2554
|
+
// Pivot Instructions
|
|
1222
2555
|
// ===========================================================================
|
|
1223
|
-
async
|
|
1224
|
-
return
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
2556
|
+
async proposePivot(args) {
|
|
2557
|
+
return proposePivot(
|
|
2558
|
+
this.program,
|
|
2559
|
+
args,
|
|
2560
|
+
this.walletPublicKey
|
|
2561
|
+
);
|
|
1228
2562
|
}
|
|
1229
|
-
async
|
|
1230
|
-
return
|
|
2563
|
+
async approvePivot(projectId, adminKeypair) {
|
|
2564
|
+
return approvePivot(
|
|
2565
|
+
this.program,
|
|
2566
|
+
projectId,
|
|
2567
|
+
adminKeypair
|
|
2568
|
+
);
|
|
1231
2569
|
}
|
|
1232
|
-
async
|
|
1233
|
-
return
|
|
2570
|
+
async withdrawFromPivot(args) {
|
|
2571
|
+
return withdrawFromPivot(
|
|
2572
|
+
this.program,
|
|
2573
|
+
args,
|
|
2574
|
+
this.walletPublicKey
|
|
2575
|
+
);
|
|
1234
2576
|
}
|
|
1235
|
-
async
|
|
1236
|
-
return
|
|
2577
|
+
async finalizePivot(args) {
|
|
2578
|
+
return finalizePivot(
|
|
2579
|
+
this.program,
|
|
2580
|
+
args,
|
|
2581
|
+
this.walletPublicKey
|
|
2582
|
+
);
|
|
1237
2583
|
}
|
|
1238
|
-
|
|
1239
|
-
|
|
2584
|
+
// ===========================================================================
|
|
2585
|
+
// TGE Instructions
|
|
2586
|
+
// ===========================================================================
|
|
2587
|
+
async setTgeDate(args) {
|
|
2588
|
+
return setTgeDate(
|
|
2589
|
+
this.program,
|
|
2590
|
+
args,
|
|
2591
|
+
this.walletPublicKey
|
|
2592
|
+
);
|
|
1240
2593
|
}
|
|
1241
|
-
async
|
|
1242
|
-
return
|
|
2594
|
+
async depositTokens(args) {
|
|
2595
|
+
return depositTokens(
|
|
2596
|
+
this.program,
|
|
2597
|
+
args,
|
|
2598
|
+
this.walletPublicKey
|
|
2599
|
+
);
|
|
1243
2600
|
}
|
|
1244
|
-
async
|
|
1245
|
-
return
|
|
2601
|
+
async claimTokens(args) {
|
|
2602
|
+
return claimTokens(
|
|
2603
|
+
this.program,
|
|
2604
|
+
args,
|
|
2605
|
+
this.walletPublicKey
|
|
2606
|
+
);
|
|
1246
2607
|
}
|
|
1247
|
-
async
|
|
1248
|
-
return
|
|
2608
|
+
async reportScam(args) {
|
|
2609
|
+
return reportScam(
|
|
2610
|
+
this.program,
|
|
2611
|
+
args,
|
|
2612
|
+
this.walletPublicKey
|
|
2613
|
+
);
|
|
1249
2614
|
}
|
|
1250
|
-
async
|
|
1251
|
-
return
|
|
2615
|
+
async releaseHoldback(args) {
|
|
2616
|
+
return releaseHoldback(
|
|
2617
|
+
this.program,
|
|
2618
|
+
args
|
|
2619
|
+
);
|
|
1252
2620
|
}
|
|
1253
2621
|
// ===========================================================================
|
|
1254
|
-
//
|
|
2622
|
+
// ZTM v2.0 Token Distribution Instructions
|
|
1255
2623
|
// ===========================================================================
|
|
1256
|
-
|
|
1257
|
-
|
|
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(
|
|
1258
2632
|
this.program,
|
|
1259
|
-
|
|
2633
|
+
args,
|
|
1260
2634
|
this.walletPublicKey
|
|
1261
2635
|
);
|
|
1262
2636
|
}
|
|
1263
|
-
|
|
1264
|
-
|
|
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(
|
|
1265
2648
|
this.program,
|
|
1266
|
-
|
|
1267
|
-
|
|
2649
|
+
args,
|
|
2650
|
+
this.walletPublicKey
|
|
1268
2651
|
);
|
|
1269
2652
|
}
|
|
1270
|
-
|
|
1271
|
-
|
|
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(
|
|
1272
2661
|
this.program,
|
|
2662
|
+
args,
|
|
1273
2663
|
this.walletPublicKey
|
|
1274
2664
|
);
|
|
1275
2665
|
}
|
|
1276
2666
|
// ===========================================================================
|
|
1277
|
-
//
|
|
2667
|
+
// ZTM v2.0: Founder Vesting Instructions
|
|
1278
2668
|
// ===========================================================================
|
|
1279
|
-
|
|
1280
|
-
|
|
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(
|
|
1281
2678
|
this.program,
|
|
1282
2679
|
args,
|
|
1283
2680
|
this.walletPublicKey
|
|
1284
2681
|
);
|
|
1285
2682
|
}
|
|
1286
|
-
|
|
1287
|
-
|
|
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(
|
|
1288
2691
|
this.program,
|
|
1289
|
-
|
|
2692
|
+
args,
|
|
1290
2693
|
this.walletPublicKey
|
|
1291
2694
|
);
|
|
1292
2695
|
}
|
|
1293
|
-
|
|
1294
|
-
|
|
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(
|
|
1295
2708
|
this.program,
|
|
1296
2709
|
args,
|
|
1297
2710
|
adminKeypair
|
|
1298
2711
|
);
|
|
1299
2712
|
}
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
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(
|
|
1305
2721
|
this.program,
|
|
1306
2722
|
args,
|
|
1307
2723
|
this.walletPublicKey
|
|
1308
2724
|
);
|
|
1309
2725
|
}
|
|
1310
|
-
|
|
1311
|
-
|
|
2726
|
+
// ===========================================================================
|
|
2727
|
+
// Early Token Release Instructions
|
|
2728
|
+
// ===========================================================================
|
|
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(
|
|
1312
2742
|
this.program,
|
|
1313
|
-
|
|
1314
|
-
milestoneIndex,
|
|
2743
|
+
args,
|
|
1315
2744
|
this.walletPublicKey
|
|
1316
2745
|
);
|
|
1317
2746
|
}
|
|
1318
|
-
|
|
1319
|
-
|
|
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(
|
|
1320
2759
|
this.program,
|
|
1321
2760
|
args,
|
|
1322
2761
|
this.walletPublicKey
|
|
1323
2762
|
);
|
|
1324
2763
|
}
|
|
1325
|
-
|
|
1326
|
-
|
|
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(
|
|
1327
2776
|
this.program,
|
|
1328
|
-
|
|
1329
|
-
|
|
2777
|
+
args,
|
|
2778
|
+
this.walletPublicKey
|
|
1330
2779
|
);
|
|
1331
2780
|
}
|
|
2781
|
+
// ===========================================================================
|
|
2782
|
+
// Per-Milestone Vesting Instructions (add-per-milestone-vesting)
|
|
2783
|
+
// ===========================================================================
|
|
1332
2784
|
/**
|
|
1333
|
-
* Claim milestone
|
|
1334
|
-
* - Regular milestones: Full payout to founder
|
|
1335
|
-
* - Final milestone: LP USDC reserved for PCL, triggers MAE
|
|
2785
|
+
* Claim instant tokens for a passed milestone (investor)
|
|
1336
2786
|
*
|
|
1337
|
-
*
|
|
1338
|
-
*
|
|
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
|
|
1339
2793
|
*/
|
|
1340
|
-
async
|
|
1341
|
-
return
|
|
2794
|
+
async claimMilestoneInstantTokens(args) {
|
|
2795
|
+
return claimMilestoneInstantTokens(
|
|
1342
2796
|
this.program,
|
|
1343
2797
|
args,
|
|
1344
2798
|
this.walletPublicKey
|
|
1345
2799
|
);
|
|
1346
2800
|
}
|
|
1347
2801
|
/**
|
|
1348
|
-
*
|
|
2802
|
+
* Claim vested tokens for a milestone after cliff period (investor)
|
|
1349
2803
|
*
|
|
1350
|
-
*
|
|
1351
|
-
*
|
|
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
|
|
1352
2811
|
*/
|
|
1353
|
-
async
|
|
1354
|
-
return
|
|
2812
|
+
async claimMilestoneVestedTokens(args) {
|
|
2813
|
+
return claimMilestoneVestedTokens(
|
|
1355
2814
|
this.program,
|
|
1356
2815
|
args,
|
|
1357
2816
|
this.walletPublicKey
|
|
1358
2817
|
);
|
|
1359
2818
|
}
|
|
1360
2819
|
/**
|
|
1361
|
-
*
|
|
2820
|
+
* Claim instant tokens for a passed milestone (founder)
|
|
1362
2821
|
*
|
|
1363
|
-
*
|
|
1364
|
-
*
|
|
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
|
|
1365
2827
|
*/
|
|
1366
|
-
async
|
|
1367
|
-
return
|
|
2828
|
+
async claimFounderMsInstantTokens(args) {
|
|
2829
|
+
return claimFounderMsInstantTokens(
|
|
1368
2830
|
this.program,
|
|
1369
2831
|
args,
|
|
1370
2832
|
this.walletPublicKey
|
|
1371
2833
|
);
|
|
1372
2834
|
}
|
|
1373
2835
|
/**
|
|
1374
|
-
*
|
|
2836
|
+
* Claim vested tokens for a milestone after cliff period (founder)
|
|
1375
2837
|
*
|
|
1376
|
-
*
|
|
1377
|
-
*
|
|
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
|
|
1378
2844
|
*/
|
|
1379
|
-
async
|
|
1380
|
-
return
|
|
2845
|
+
async claimFounderMsVestedTokens(args) {
|
|
2846
|
+
return claimFounderMsVestedTokens(
|
|
1381
2847
|
this.program,
|
|
1382
2848
|
args,
|
|
1383
2849
|
this.walletPublicKey
|
|
1384
2850
|
);
|
|
1385
2851
|
}
|
|
1386
2852
|
// ===========================================================================
|
|
1387
|
-
//
|
|
2853
|
+
// Abandonment Instructions
|
|
2854
|
+
// ===========================================================================
|
|
2855
|
+
async checkAbandonment(projectId, milestoneIndex = 0) {
|
|
2856
|
+
return checkAbandonment(
|
|
2857
|
+
this.program,
|
|
2858
|
+
projectId,
|
|
2859
|
+
milestoneIndex
|
|
2860
|
+
);
|
|
2861
|
+
}
|
|
2862
|
+
async claimRefund(args) {
|
|
2863
|
+
return claimRefund(
|
|
2864
|
+
this.program,
|
|
2865
|
+
args,
|
|
2866
|
+
this.walletPublicKey
|
|
2867
|
+
);
|
|
2868
|
+
}
|
|
2869
|
+
// ===========================================================================
|
|
2870
|
+
// Sub-Allocation Vesting Instructions
|
|
1388
2871
|
// ===========================================================================
|
|
1389
|
-
|
|
1390
|
-
|
|
2872
|
+
/**
|
|
2873
|
+
* Initialize sub-allocation vesting after MAE (Market Access Event)
|
|
2874
|
+
*
|
|
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.
|
|
2878
|
+
*/
|
|
2879
|
+
async initializeSubAllocationVesting(args) {
|
|
2880
|
+
return initializeSubAllocationVesting(
|
|
1391
2881
|
this.program,
|
|
1392
2882
|
args,
|
|
1393
2883
|
this.walletPublicKey
|
|
1394
2884
|
);
|
|
1395
2885
|
}
|
|
1396
|
-
|
|
1397
|
-
|
|
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(
|
|
1398
2894
|
this.program,
|
|
1399
2895
|
args,
|
|
1400
2896
|
this.walletPublicKey
|
|
1401
2897
|
);
|
|
1402
2898
|
}
|
|
1403
2899
|
// ===========================================================================
|
|
1404
|
-
//
|
|
2900
|
+
// Dynamic Tokenomics Instructions
|
|
1405
2901
|
// ===========================================================================
|
|
1406
|
-
|
|
1407
|
-
|
|
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(
|
|
1408
2910
|
this.program,
|
|
1409
2911
|
args,
|
|
1410
2912
|
this.walletPublicKey
|
|
1411
2913
|
);
|
|
1412
2914
|
}
|
|
1413
|
-
|
|
1414
|
-
|
|
2915
|
+
/**
|
|
2916
|
+
* Propose an allocation change via governance (post-Draft states)
|
|
2917
|
+
*
|
|
2918
|
+
* Creates a 7-day voting period for investors to approve/reject
|
|
2919
|
+
* a new sub-allocation from the reserve pool.
|
|
2920
|
+
*/
|
|
2921
|
+
async proposeAllocationChange(args) {
|
|
2922
|
+
return proposeAllocationChange(
|
|
1415
2923
|
this.program,
|
|
1416
|
-
|
|
1417
|
-
|
|
2924
|
+
args,
|
|
2925
|
+
this.walletPublicKey
|
|
1418
2926
|
);
|
|
1419
2927
|
}
|
|
1420
|
-
|
|
1421
|
-
|
|
2928
|
+
/**
|
|
2929
|
+
* Vote on an allocation change proposal
|
|
2930
|
+
*
|
|
2931
|
+
* Investors can vote for/against using their Investment NFT.
|
|
2932
|
+
* Must meet 7-day hold period for voting eligibility.
|
|
2933
|
+
*/
|
|
2934
|
+
async voteAllocationChange(args) {
|
|
2935
|
+
return voteAllocationChange(
|
|
1422
2936
|
this.program,
|
|
1423
2937
|
args,
|
|
1424
2938
|
this.walletPublicKey
|
|
1425
2939
|
);
|
|
1426
2940
|
}
|
|
1427
|
-
|
|
1428
|
-
|
|
2941
|
+
/**
|
|
2942
|
+
* Execute an approved allocation change proposal
|
|
2943
|
+
*
|
|
2944
|
+
* Permissionless - anyone can call after voting ends.
|
|
2945
|
+
* Proposal must have passed (>51% approval).
|
|
2946
|
+
*/
|
|
2947
|
+
async executeAllocationChange(args) {
|
|
2948
|
+
return executeAllocationChange(
|
|
1429
2949
|
this.program,
|
|
1430
2950
|
args,
|
|
1431
2951
|
this.walletPublicKey
|
|
1432
2952
|
);
|
|
1433
2953
|
}
|
|
1434
2954
|
// ===========================================================================
|
|
1435
|
-
//
|
|
2955
|
+
// Dynamic Tokenomics Helpers
|
|
1436
2956
|
// ===========================================================================
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
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;
|
|
2971
|
+
}
|
|
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
|
+
};
|
|
3032
|
+
}
|
|
3033
|
+
// ===========================================================================
|
|
3034
|
+
// Milestone Price Increase Helpers
|
|
3035
|
+
// ===========================================================================
|
|
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;
|
|
3059
|
+
}
|
|
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;
|
|
3069
|
+
}
|
|
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 anchor.BN(multiplier)).div(new anchor.BN(_RaiseClient.PRICE_MULTIPLIER_BASE)),
|
|
3087
|
+
multiplierBps: multiplier
|
|
3088
|
+
}));
|
|
3089
|
+
}
|
|
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;
|
|
3148
|
+
}
|
|
3149
|
+
// ===========================================================================
|
|
3150
|
+
// Linear Progressive Pricing Helpers (add-linear-progressive-pricing)
|
|
3151
|
+
// ===========================================================================
|
|
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 anchor.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 anchor.BN(multiplier)).div(new anchor.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
|
-
|
|
1445
|
-
return
|
|
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
|
-
|
|
1452
|
-
|
|
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
|
-
|
|
1459
|
-
|
|
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
|
-
*
|
|
3343
|
+
* Submit round milestone for investor review
|
|
1476
3344
|
*
|
|
1477
|
-
*
|
|
1478
|
-
*
|
|
3345
|
+
* Multi-Round Fundraising: Transitions milestone to UnderReview,
|
|
3346
|
+
* sets voting deadline.
|
|
1479
3347
|
*/
|
|
1480
|
-
async
|
|
1481
|
-
return
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
|
1497
|
-
return
|
|
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
|
-
*
|
|
3369
|
+
* Finalize voting on a round milestone
|
|
1505
3370
|
*
|
|
1506
|
-
*
|
|
1507
|
-
*
|
|
3371
|
+
* Multi-Round Fundraising: Processes vote results, transitions
|
|
3372
|
+
* milestone to Passed or Failed state.
|
|
1508
3373
|
*/
|
|
1509
|
-
async
|
|
1510
|
-
return
|
|
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
|
-
*
|
|
3381
|
+
* Claim milestone funds from a round (founder)
|
|
1521
3382
|
*
|
|
1522
|
-
*
|
|
1523
|
-
*
|
|
1524
|
-
*
|
|
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
|
|
1527
|
-
return
|
|
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
|
|
3397
|
+
* Claim instant tokens for a round milestone (investor)
|
|
1535
3398
|
*
|
|
1536
|
-
*
|
|
1537
|
-
*
|
|
3399
|
+
* Multi-Round Fundraising: R2+ investors claim instant portion
|
|
3400
|
+
* when milestone passes. Tokens come from FutureRoundVault.
|
|
1538
3401
|
*/
|
|
1539
|
-
async
|
|
1540
|
-
return
|
|
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
|
-
*
|
|
3410
|
+
* Claim vested tokens for a round milestone (investor)
|
|
1551
3411
|
*
|
|
1552
|
-
*
|
|
1553
|
-
*
|
|
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
|
|
1557
|
-
return
|
|
3415
|
+
async claimRoundVestedTokens(args) {
|
|
3416
|
+
return claimRoundVestedTokens(
|
|
1558
3417
|
this.program,
|
|
1559
3418
|
args,
|
|
1560
|
-
|
|
3419
|
+
this.walletPublicKey
|
|
1561
3420
|
);
|
|
1562
3421
|
}
|
|
1563
3422
|
/**
|
|
1564
|
-
* Claim
|
|
3423
|
+
* Claim early tokens for a round investment (5% after 24h)
|
|
1565
3424
|
*
|
|
1566
|
-
*
|
|
1567
|
-
*
|
|
3425
|
+
* Multi-Round Fundraising: R2+ investors claim 5% of token allocation
|
|
3426
|
+
* 24 hours after investing. Tokens come from FutureRoundVault.
|
|
1568
3427
|
*/
|
|
1569
|
-
async
|
|
1570
|
-
return
|
|
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
|
-
//
|
|
3436
|
+
// Multi-Round Fundraising Helpers
|
|
1578
3437
|
// ===========================================================================
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
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
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
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,10 @@ function shortenPublicKey(pubkey, chars = 4) {
|
|
|
1921
3821
|
return `${str.slice(0, chars)}...${str.slice(-chars)}`;
|
|
1922
3822
|
}
|
|
1923
3823
|
|
|
3824
|
+
Object.defineProperty(exports, "BN", {
|
|
3825
|
+
enumerable: true,
|
|
3826
|
+
get: function () { return anchor.BN; }
|
|
3827
|
+
});
|
|
1924
3828
|
Object.defineProperty(exports, "Connection", {
|
|
1925
3829
|
enumerable: true,
|
|
1926
3830
|
get: function () { return web3_js.Connection; }
|
|
@@ -1933,13 +3837,13 @@ Object.defineProperty(exports, "PublicKey", {
|
|
|
1933
3837
|
enumerable: true,
|
|
1934
3838
|
get: function () { return web3_js.PublicKey; }
|
|
1935
3839
|
});
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
});
|
|
3840
|
+
exports.EARLY_TOKEN_COOLING_PERIOD_SECONDS = EARLY_TOKEN_COOLING_PERIOD_SECONDS;
|
|
3841
|
+
exports.EARLY_TOKEN_COOLING_PERIOD_SECONDS_DEV = EARLY_TOKEN_COOLING_PERIOD_SECONDS_DEV;
|
|
3842
|
+
exports.EARLY_TOKEN_RELEASE_BPS = EARLY_TOKEN_RELEASE_BPS;
|
|
1940
3843
|
exports.ERROR_CODES = ERROR_CODES;
|
|
1941
3844
|
exports.ERROR_MESSAGES = ERROR_MESSAGES;
|
|
1942
3845
|
exports.EVENT_NAMES = EVENT_NAMES;
|
|
3846
|
+
exports.FundingRoundState = FundingRoundState;
|
|
1943
3847
|
exports.GOVERNANCE = GOVERNANCE;
|
|
1944
3848
|
exports.InvestmentTier = InvestmentTier;
|
|
1945
3849
|
exports.MAX_DEADLINE_DURATION_SECONDS = MAX_DEADLINE_DURATION_SECONDS;
|
|
@@ -1957,6 +3861,7 @@ exports.TIER_MINIMUMS = TIER_MINIMUMS;
|
|
|
1957
3861
|
exports.TIER_TOKEN_MULTIPLIERS = TIER_TOKEN_MULTIPLIERS;
|
|
1958
3862
|
exports.TIER_VOTE_MULTIPLIERS = TIER_VOTE_MULTIPLIERS;
|
|
1959
3863
|
exports.TIMING = TIMING;
|
|
3864
|
+
exports.TOKENOMICS = TOKENOMICS;
|
|
1960
3865
|
exports.USDC = USDC;
|
|
1961
3866
|
exports.VALIDATION = VALIDATION;
|
|
1962
3867
|
exports.VoteChoice = VoteChoice;
|
|
@@ -1969,13 +3874,24 @@ exports.bnToBigInt = bnToBigInt;
|
|
|
1969
3874
|
exports.bnToNumber = bnToNumber;
|
|
1970
3875
|
exports.bpsToPercent = bpsToPercent;
|
|
1971
3876
|
exports.calculateDeadline = calculateDeadline;
|
|
3877
|
+
exports.calculateEarlyTokenAmount = calculateEarlyTokenAmount;
|
|
3878
|
+
exports.calculateRemainingAllocation = calculateRemainingAllocation;
|
|
3879
|
+
exports.canClaimEarlyTokens = canClaimEarlyTokens;
|
|
3880
|
+
exports.canClaimFounderEarlyTokens = canClaimFounderEarlyTokens;
|
|
3881
|
+
exports.canClaimFounderMilestoneTokens = canClaimFounderMilestoneTokens;
|
|
3882
|
+
exports.canClaimRoundEarlyTokens = canClaimRoundEarlyTokens;
|
|
1972
3883
|
exports.cancelInvestment = cancelInvestment;
|
|
3884
|
+
exports.cancelRoundInvestment = cancelRoundInvestment;
|
|
1973
3885
|
exports.checkAbandonment = checkAbandonment;
|
|
1974
3886
|
exports.claimExitWindowRefund = claimExitWindowRefund;
|
|
1975
3887
|
exports.claimInvestorTokens = claimInvestorTokens;
|
|
1976
3888
|
exports.claimMilestoneFunds = claimMilestoneFunds;
|
|
1977
3889
|
exports.claimMissedUnlock = claimMissedUnlock;
|
|
1978
3890
|
exports.claimRefund = claimRefund;
|
|
3891
|
+
exports.claimRoundEarlyTokens = claimRoundEarlyTokens;
|
|
3892
|
+
exports.claimRoundInstantTokens = claimRoundInstantTokens;
|
|
3893
|
+
exports.claimRoundMilestoneFunds = claimRoundMilestoneFunds;
|
|
3894
|
+
exports.claimRoundVestedTokens = claimRoundVestedTokens;
|
|
1979
3895
|
exports.claimTokens = claimTokens;
|
|
1980
3896
|
exports.claimVestedTokens = claimVestedTokens;
|
|
1981
3897
|
exports.completeDistribution = completeDistribution;
|
|
@@ -1985,18 +3901,25 @@ exports.depositTokens = depositTokens;
|
|
|
1985
3901
|
exports.distributeTokens = distributeTokens;
|
|
1986
3902
|
exports.extendMilestoneDeadline = extendMilestoneDeadline;
|
|
1987
3903
|
exports.fetchAdminConfig = fetchAdminConfig;
|
|
3904
|
+
exports.fetchAllFundingRounds = fetchAllFundingRounds;
|
|
1988
3905
|
exports.fetchAllInvestments = fetchAllInvestments;
|
|
1989
3906
|
exports.fetchAllMilestones = fetchAllMilestones;
|
|
1990
3907
|
exports.fetchAllVotes = fetchAllVotes;
|
|
3908
|
+
exports.fetchFundingRound = fetchFundingRound;
|
|
3909
|
+
exports.fetchFutureRoundVault = fetchFutureRoundVault;
|
|
1991
3910
|
exports.fetchInvestment = fetchInvestment;
|
|
1992
3911
|
exports.fetchMilestone = fetchMilestone;
|
|
1993
3912
|
exports.fetchPivotProposal = fetchPivotProposal;
|
|
1994
3913
|
exports.fetchProject = fetchProject;
|
|
1995
3914
|
exports.fetchProjectByPda = fetchProjectByPda;
|
|
3915
|
+
exports.fetchRoundInvestment = fetchRoundInvestment;
|
|
3916
|
+
exports.fetchRoundInvestorMilestoneVesting = fetchRoundInvestorMilestoneVesting;
|
|
3917
|
+
exports.fetchRoundMilestone = fetchRoundMilestone;
|
|
1996
3918
|
exports.fetchTgeEscrow = fetchTgeEscrow;
|
|
1997
3919
|
exports.fetchVote = fetchVote;
|
|
1998
3920
|
exports.filterEventsByName = filterEventsByName;
|
|
1999
3921
|
exports.finalizePivot = finalizePivot;
|
|
3922
|
+
exports.finalizeRoundVoting = finalizeRoundVoting;
|
|
2000
3923
|
exports.finalizeVoting = finalizeVoting;
|
|
2001
3924
|
exports.findEvent = findEvent;
|
|
2002
3925
|
exports.findTierIndex = findTierIndex;
|
|
@@ -2008,6 +3931,9 @@ exports.getErrorMessage = getErrorMessage;
|
|
|
2008
3931
|
exports.getEscrowPDA = getEscrowPDA;
|
|
2009
3932
|
exports.getFounderVaultPDA = getFounderVaultPDA;
|
|
2010
3933
|
exports.getFounderVestingPDA = getFounderVestingPDA;
|
|
3934
|
+
exports.getFundingRoundPDA = getFundingRoundPDA;
|
|
3935
|
+
exports.getFutureRoundTokenVaultPDA = getFutureRoundTokenVaultPDA;
|
|
3936
|
+
exports.getFutureRoundVaultPDA = getFutureRoundVaultPDA;
|
|
2011
3937
|
exports.getInvestmentPDA = getInvestmentPDA;
|
|
2012
3938
|
exports.getInvestorVaultPDA = getInvestorVaultPDA;
|
|
2013
3939
|
exports.getLpTokenVaultPDA = getLpTokenVaultPDA;
|
|
@@ -2018,6 +3944,11 @@ exports.getPivotProposalPDA = getPivotProposalPDA;
|
|
|
2018
3944
|
exports.getProgramAuthorityPDA = getProgramAuthorityPDA;
|
|
2019
3945
|
exports.getProjectPDA = getProjectPDA;
|
|
2020
3946
|
exports.getProjectPDAs = getProjectPDAs;
|
|
3947
|
+
exports.getRoundEscrowPDA = getRoundEscrowPDA;
|
|
3948
|
+
exports.getRoundInvestmentPDA = getRoundInvestmentPDA;
|
|
3949
|
+
exports.getRoundInvestorMilestoneVestingPDA = getRoundInvestorMilestoneVestingPDA;
|
|
3950
|
+
exports.getRoundMilestonePDA = getRoundMilestonePDA;
|
|
3951
|
+
exports.getRoundNftMintPDA = getRoundNftMintPDA;
|
|
2021
3952
|
exports.getScamReportPDA = getScamReportPDA;
|
|
2022
3953
|
exports.getTgeEscrowPDA = getTgeEscrowPDA;
|
|
2023
3954
|
exports.getTierFromAmount = getTierFromAmount;
|
|
@@ -2035,21 +3966,25 @@ exports.initializeAdmin = initializeAdmin;
|
|
|
2035
3966
|
exports.initializeFounderVesting = initializeFounderVesting;
|
|
2036
3967
|
exports.initializeProject = initializeProject;
|
|
2037
3968
|
exports.invest = invest;
|
|
3969
|
+
exports.investInRound = investInRound;
|
|
2038
3970
|
exports.isRaiseError = isRaiseError;
|
|
2039
3971
|
exports.isValidPublicKey = isValidPublicKey;
|
|
2040
3972
|
exports.minDeadline = minDeadline;
|
|
3973
|
+
exports.openFundingRound = openFundingRound;
|
|
2041
3974
|
exports.parseError = parseError;
|
|
2042
3975
|
exports.percentToBps = percentToBps;
|
|
2043
3976
|
exports.percentageOf = percentageOf;
|
|
2044
3977
|
exports.proposePivot = proposePivot;
|
|
2045
3978
|
exports.releaseHoldback = releaseHoldback;
|
|
2046
3979
|
exports.reportScam = reportScam;
|
|
3980
|
+
exports.requiresBurnForRefund = requiresBurnForRefund;
|
|
2047
3981
|
exports.resubmitMilestone = resubmitMilestone;
|
|
2048
3982
|
exports.setMilestoneDeadline = setMilestoneDeadline;
|
|
2049
3983
|
exports.setTgeDate = setTgeDate;
|
|
2050
3984
|
exports.shortenPublicKey = shortenPublicKey;
|
|
2051
3985
|
exports.submitForApproval = submitForApproval;
|
|
2052
3986
|
exports.submitMilestone = submitMilestone;
|
|
3987
|
+
exports.submitRoundMilestone = submitRoundMilestone;
|
|
2053
3988
|
exports.symbolToBytes = symbolToBytes;
|
|
2054
3989
|
exports.timeRemaining = timeRemaining;
|
|
2055
3990
|
exports.timestampToDate = timestampToDate;
|
|
@@ -2058,6 +3993,7 @@ exports.validateDeadline = validateDeadline;
|
|
|
2058
3993
|
exports.validateMetadataUri = validateMetadataUri;
|
|
2059
3994
|
exports.validateMilestonePercentages = validateMilestonePercentages;
|
|
2060
3995
|
exports.voteOnMilestone = voteOnMilestone;
|
|
3996
|
+
exports.voteOnRoundMilestone = voteOnRoundMilestone;
|
|
2061
3997
|
exports.withdrawFromPivot = withdrawFromPivot;
|
|
2062
3998
|
//# sourceMappingURL=index.cjs.map
|
|
2063
3999
|
//# sourceMappingURL=index.cjs.map
|