@zemyth/raise-sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +416 -0
  2. package/dist/accounts/index.cjs +258 -0
  3. package/dist/accounts/index.cjs.map +1 -0
  4. package/dist/accounts/index.d.cts +115 -0
  5. package/dist/accounts/index.d.ts +115 -0
  6. package/dist/accounts/index.js +245 -0
  7. package/dist/accounts/index.js.map +1 -0
  8. package/dist/constants/index.cjs +174 -0
  9. package/dist/constants/index.cjs.map +1 -0
  10. package/dist/constants/index.d.cts +143 -0
  11. package/dist/constants/index.d.ts +143 -0
  12. package/dist/constants/index.js +158 -0
  13. package/dist/constants/index.js.map +1 -0
  14. package/dist/errors/index.cjs +177 -0
  15. package/dist/errors/index.cjs.map +1 -0
  16. package/dist/errors/index.d.cts +83 -0
  17. package/dist/errors/index.d.ts +83 -0
  18. package/dist/errors/index.js +170 -0
  19. package/dist/errors/index.js.map +1 -0
  20. package/dist/index.cjs +2063 -0
  21. package/dist/index.cjs.map +1 -0
  22. package/dist/index.d.cts +680 -0
  23. package/dist/index.d.ts +680 -0
  24. package/dist/index.js +1926 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/instructions/index.cjs +852 -0
  27. package/dist/instructions/index.cjs.map +1 -0
  28. package/dist/instructions/index.d.cts +452 -0
  29. package/dist/instructions/index.d.ts +452 -0
  30. package/dist/instructions/index.js +809 -0
  31. package/dist/instructions/index.js.map +1 -0
  32. package/dist/pdas/index.cjs +241 -0
  33. package/dist/pdas/index.cjs.map +1 -0
  34. package/dist/pdas/index.d.cts +171 -0
  35. package/dist/pdas/index.d.ts +171 -0
  36. package/dist/pdas/index.js +217 -0
  37. package/dist/pdas/index.js.map +1 -0
  38. package/dist/types/index.cjs +44 -0
  39. package/dist/types/index.cjs.map +1 -0
  40. package/dist/types/index.d.cts +229 -0
  41. package/dist/types/index.d.ts +229 -0
  42. package/dist/types/index.js +39 -0
  43. package/dist/types/index.js.map +1 -0
  44. package/package.json +130 -0
  45. package/src/accounts/index.ts +329 -0
  46. package/src/client.ts +715 -0
  47. package/src/constants/index.ts +205 -0
  48. package/src/errors/index.ts +222 -0
  49. package/src/events/index.ts +256 -0
  50. package/src/index.ts +253 -0
  51. package/src/instructions/index.ts +1504 -0
  52. package/src/pdas/index.ts +404 -0
  53. package/src/types/index.ts +267 -0
  54. package/src/utils/index.ts +277 -0
package/dist/index.js ADDED
@@ -0,0 +1,1926 @@
1
+ import { PublicKey, SystemProgram, SYSVAR_INSTRUCTIONS_PUBKEY, SYSVAR_RENT_PUBKEY, ComputeBudgetProgram, SYSVAR_CLOCK_PUBKEY } from '@solana/web3.js';
2
+ export { Connection, Keypair, PublicKey } from '@solana/web3.js';
3
+ import { BN, AnchorError } from '@coral-xyz/anchor';
4
+ export { BN } from '@coral-xyz/anchor';
5
+ import { getAssociatedTokenAddressSync, TOKEN_PROGRAM_ID, ASSOCIATED_TOKEN_PROGRAM_ID } from '@solana/spl-token';
6
+
7
+ // src/pdas/index.ts
8
+
9
+ // src/constants/index.ts
10
+ var SEEDS = {
11
+ PROJECT: "project",
12
+ MILESTONE: "milestone",
13
+ INVESTMENT: "investment",
14
+ VOTE: "vote",
15
+ ESCROW: "escrow",
16
+ PIVOT: "pivot",
17
+ PIVOT_PROPOSAL: "pivot_proposal",
18
+ TGE_ESCROW: "tge_escrow",
19
+ TGE_ESCROW_VAULT: "tge_escrow_vault",
20
+ SCAM_REPORT: "scam_report",
21
+ ADMIN_CONFIG: "admin-config",
22
+ NFT_MINT: "nft_mint",
23
+ AUTHORITY: "authority"
24
+ };
25
+ var VALIDATION = {
26
+ /** Minimum number of milestones per project */
27
+ MIN_MILESTONES: 2,
28
+ /** Maximum number of milestones per project */
29
+ MAX_MILESTONES: 10,
30
+ /** Milestone percentages must sum to this value */
31
+ MILESTONE_PERCENTAGE_SUM: 100,
32
+ /** Maximum funding buffer (110% of goal) */
33
+ MAX_FUNDING_BUFFER_PERCENT: 110,
34
+ /** Maximum metadata URI length */
35
+ MAX_METADATA_URI_LENGTH: 200,
36
+ /** Maximum pivot description length */
37
+ MAX_PIVOT_DESCRIPTION_LEN: 256,
38
+ /** Maximum pivot vision length */
39
+ MAX_PIVOT_VISION_LEN: 512,
40
+ /** Maximum pivot justification length */
41
+ MAX_PIVOT_JUSTIFICATION_LEN: 512
42
+ };
43
+ var TIMING = {
44
+ /** Production voting period (14 days) */
45
+ VOTING_PERIOD_SECONDS: 1209600,
46
+ /** Production hold period (7 days) */
47
+ HOLD_PERIOD_SECONDS: 604800,
48
+ /** Inactivity timeout (90 days) */
49
+ INACTIVITY_TIMEOUT_SECONDS: 7776e3,
50
+ /** Abandonment timeout (90 days) */
51
+ ABANDONMENT_TIMEOUT_SECONDS: 7776e3,
52
+ /** Refund window (14 days) */
53
+ REFUND_WINDOW_SECONDS: 1209600,
54
+ /** Pivot withdrawal window (7 days) */
55
+ PIVOT_WITHDRAWAL_WINDOW_SECONDS: 604800,
56
+ /** Minimum TGE date (15 days from now) */
57
+ TGE_MIN_DAYS: 1296e3,
58
+ /** Maximum TGE date (90 days from now) */
59
+ TGE_MAX_DAYS: 7776e3,
60
+ /** Post-TGE holdback period (30 days) */
61
+ POST_TGE_HOLDBACK_DAYS: 2592e3
62
+ };
63
+ var TIER_CONSTRAINTS = {
64
+ /** Minimum number of tiers */
65
+ MIN_TIERS: 1,
66
+ /** Maximum number of tiers */
67
+ MAX_TIERS: 10,
68
+ /** Minimum tier amount (10 USDC in lamports) */
69
+ MIN_TIER_AMOUNT: 10000000n,
70
+ /** Minimum max_lots per tier */
71
+ MIN_TIER_MAX_LOTS: 1,
72
+ /** Minimum token ratio */
73
+ MIN_TIER_TOKEN_RATIO: 1n,
74
+ /** Minimum vote multiplier (100 = 1.0x) */
75
+ MIN_TIER_VOTE_MULTIPLIER: 100
76
+ };
77
+ var InvestmentTier = /* @__PURE__ */ ((InvestmentTier2) => {
78
+ InvestmentTier2["Bronze"] = "Bronze";
79
+ InvestmentTier2["Silver"] = "Silver";
80
+ InvestmentTier2["Gold"] = "Gold";
81
+ InvestmentTier2["Platinum"] = "Platinum";
82
+ InvestmentTier2["Diamond"] = "Diamond";
83
+ return InvestmentTier2;
84
+ })(InvestmentTier || {});
85
+ var TIER_MINIMUMS = {
86
+ ["Bronze" /* Bronze */]: 100000000n,
87
+ // 100 USDC
88
+ ["Silver" /* Silver */]: 500000000n,
89
+ // 500 USDC
90
+ ["Gold" /* Gold */]: 1000000000n,
91
+ // 1,000 USDC
92
+ ["Platinum" /* Platinum */]: 5000000000n,
93
+ // 5,000 USDC
94
+ ["Diamond" /* Diamond */]: 10000000000n
95
+ // 10,000 USDC
96
+ };
97
+ var TIER_VOTE_MULTIPLIERS = {
98
+ ["Bronze" /* Bronze */]: 100,
99
+ // 1.0x
100
+ ["Silver" /* Silver */]: 120,
101
+ // 1.2x
102
+ ["Gold" /* Gold */]: 150,
103
+ // 1.5x
104
+ ["Platinum" /* Platinum */]: 200,
105
+ // 2.0x
106
+ ["Diamond" /* Diamond */]: 300
107
+ // 3.0x
108
+ };
109
+ var TIER_TOKEN_MULTIPLIERS = {
110
+ ["Bronze" /* Bronze */]: 100,
111
+ ["Silver" /* Silver */]: 120,
112
+ ["Gold" /* Gold */]: 150,
113
+ ["Platinum" /* Platinum */]: 200,
114
+ ["Diamond" /* Diamond */]: 300
115
+ };
116
+ function getTierFromAmount(amount) {
117
+ if (amount >= TIER_MINIMUMS["Diamond" /* Diamond */]) return "Diamond" /* Diamond */;
118
+ if (amount >= TIER_MINIMUMS["Platinum" /* Platinum */]) return "Platinum" /* Platinum */;
119
+ if (amount >= TIER_MINIMUMS["Gold" /* Gold */]) return "Gold" /* Gold */;
120
+ if (amount >= TIER_MINIMUMS["Silver" /* Silver */]) return "Silver" /* Silver */;
121
+ return "Bronze" /* Bronze */;
122
+ }
123
+ function getVoteMultiplier(amount) {
124
+ const tier = getTierFromAmount(amount);
125
+ return TIER_VOTE_MULTIPLIERS[tier] / 100;
126
+ }
127
+ function getTokenMultiplier(amount) {
128
+ const tier = getTierFromAmount(amount);
129
+ return TIER_TOKEN_MULTIPLIERS[tier] / 100;
130
+ }
131
+ function findTierIndex(tiers, amount) {
132
+ for (let i = tiers.length - 1; i >= 0; i--) {
133
+ if (amount >= tiers[i].amount) {
134
+ return i;
135
+ }
136
+ }
137
+ return null;
138
+ }
139
+ var GOVERNANCE = {
140
+ /** Scam report threshold (30%) */
141
+ SCAM_THRESHOLD_PERCENT: 30,
142
+ /** Consecutive milestone failures before exit window eligible */
143
+ CONSECUTIVE_FAILURES_THRESHOLD: 3,
144
+ /** Milestone approval threshold (>50% weighted approval per whitepaper voting.md:100-101) */
145
+ MILESTONE_APPROVAL_THRESHOLD_PERCENT: 50
146
+ };
147
+ var NFT = {
148
+ /** NFT symbol */
149
+ SYMBOL: "SNI",
150
+ /** NFT name prefix */
151
+ NAME_PREFIX: "Raise Investment #",
152
+ /** Royalty basis points (2%) */
153
+ ROYALTY_BASIS_POINTS: 200
154
+ };
155
+ var USDC = {
156
+ /** USDC decimals */
157
+ DECIMALS: 6,
158
+ /** Convert USDC to lamports */
159
+ toAmount: (usdc) => BigInt(Math.floor(usdc * 10 ** 6)),
160
+ /** Convert lamports to USDC */
161
+ fromAmount: (lamports) => Number(lamports) / 10 ** 6
162
+ };
163
+
164
+ // src/pdas/index.ts
165
+ function ensureBN(value) {
166
+ if (value && typeof value.toArrayLike === "function") {
167
+ return value;
168
+ }
169
+ return new BN(String(value));
170
+ }
171
+ function getProjectPDA(projectId, programId) {
172
+ const projectIdBN = ensureBN(projectId);
173
+ const [pda] = PublicKey.findProgramAddressSync(
174
+ [Buffer.from(SEEDS.PROJECT), projectIdBN.toArrayLike(Buffer, "le", 8)],
175
+ programId
176
+ );
177
+ return pda;
178
+ }
179
+ function getEscrowPDA(projectId, programId) {
180
+ const projectIdBN = ensureBN(projectId);
181
+ const [pda] = PublicKey.findProgramAddressSync(
182
+ [Buffer.from(SEEDS.ESCROW), projectIdBN.toArrayLike(Buffer, "le", 8)],
183
+ programId
184
+ );
185
+ return pda;
186
+ }
187
+ function getMilestonePDA(projectPda, milestoneIndex, programId) {
188
+ const [pda] = PublicKey.findProgramAddressSync(
189
+ [
190
+ Buffer.from(SEEDS.MILESTONE),
191
+ projectPda.toBuffer(),
192
+ Buffer.from([milestoneIndex])
193
+ ],
194
+ programId
195
+ );
196
+ return pda;
197
+ }
198
+ function getInvestmentPDA(projectPda, nftMint, programId) {
199
+ const [pda] = PublicKey.findProgramAddressSync(
200
+ [
201
+ Buffer.from(SEEDS.INVESTMENT),
202
+ projectPda.toBuffer(),
203
+ nftMint.toBuffer()
204
+ ],
205
+ programId
206
+ );
207
+ return pda;
208
+ }
209
+ function getVotePDA(milestonePda, voterKey, votingRound, programId) {
210
+ const [pda] = PublicKey.findProgramAddressSync(
211
+ [Buffer.from(SEEDS.VOTE), milestonePda.toBuffer(), voterKey.toBuffer(), Buffer.from([votingRound])],
212
+ programId
213
+ );
214
+ return pda;
215
+ }
216
+ function getPivotProposalPDA(projectPda, pivotCount, programId) {
217
+ const [pda] = PublicKey.findProgramAddressSync(
218
+ [
219
+ Buffer.from(SEEDS.PIVOT),
220
+ // Use PIVOT seed, not PIVOT_PROPOSAL
221
+ projectPda.toBuffer(),
222
+ Buffer.from([pivotCount])
223
+ // pivot_count is u8 (1 byte) on-chain
224
+ ],
225
+ programId
226
+ );
227
+ return pda;
228
+ }
229
+ function getTgeEscrowPDA(projectPda, programId) {
230
+ const [pda] = PublicKey.findProgramAddressSync(
231
+ [Buffer.from(SEEDS.TGE_ESCROW), projectPda.toBuffer()],
232
+ programId
233
+ );
234
+ return pda;
235
+ }
236
+ function getTgeEscrowVaultPDA(projectPda, programId) {
237
+ const [pda] = PublicKey.findProgramAddressSync(
238
+ [Buffer.from(SEEDS.TGE_ESCROW_VAULT), projectPda.toBuffer()],
239
+ programId
240
+ );
241
+ return pda;
242
+ }
243
+ function getTokenVaultPDA(projectPda, programId) {
244
+ const [pda] = PublicKey.findProgramAddressSync(
245
+ [Buffer.from("token_vault"), projectPda.toBuffer()],
246
+ programId
247
+ );
248
+ return pda;
249
+ }
250
+ function getScamReportPDA(projectPda, nftMint, programId) {
251
+ const [pda] = PublicKey.findProgramAddressSync(
252
+ [
253
+ Buffer.from(SEEDS.SCAM_REPORT),
254
+ projectPda.toBuffer(),
255
+ nftMint.toBuffer()
256
+ ],
257
+ programId
258
+ );
259
+ return pda;
260
+ }
261
+ function getAdminConfigPDA(programId) {
262
+ const [pda] = PublicKey.findProgramAddressSync(
263
+ [Buffer.from(SEEDS.ADMIN_CONFIG)],
264
+ programId
265
+ );
266
+ return pda;
267
+ }
268
+ function getNftMintPDA(projectId, investor, investmentCount, programId) {
269
+ const projectIdBN = ensureBN(projectId);
270
+ const countBN = ensureBN(investmentCount);
271
+ return PublicKey.findProgramAddressSync(
272
+ [
273
+ Buffer.from(SEEDS.NFT_MINT),
274
+ projectIdBN.toArrayLike(Buffer, "le", 8),
275
+ investor.toBuffer(),
276
+ countBN.toArrayLike(Buffer, "le", 8)
277
+ // u64 is 8 bytes LE
278
+ ],
279
+ programId
280
+ );
281
+ }
282
+ function getProgramAuthorityPDA(programId) {
283
+ return PublicKey.findProgramAddressSync(
284
+ [Buffer.from(SEEDS.AUTHORITY)],
285
+ programId
286
+ );
287
+ }
288
+ function getProjectPDAs(projectId, programId) {
289
+ const project = getProjectPDA(projectId, programId);
290
+ const escrow = getEscrowPDA(projectId, programId);
291
+ return { project, escrow };
292
+ }
293
+ function getTokenomicsPDA(projectPda, programId) {
294
+ const [pda] = PublicKey.findProgramAddressSync(
295
+ [Buffer.from("tokenomics"), projectPda.toBuffer()],
296
+ programId
297
+ );
298
+ return pda;
299
+ }
300
+ function getTokenMintPDA(projectPda, programId) {
301
+ const [pda] = PublicKey.findProgramAddressSync(
302
+ [Buffer.from("token_mint"), projectPda.toBuffer()],
303
+ programId
304
+ );
305
+ return pda;
306
+ }
307
+ function getVaultAuthorityPDA(projectPda, programId) {
308
+ const [pda] = PublicKey.findProgramAddressSync(
309
+ [Buffer.from("vault_authority"), projectPda.toBuffer()],
310
+ programId
311
+ );
312
+ return pda;
313
+ }
314
+ function getInvestorVaultPDA(projectPda, programId) {
315
+ const [pda] = PublicKey.findProgramAddressSync(
316
+ [Buffer.from("investor_vault"), projectPda.toBuffer()],
317
+ programId
318
+ );
319
+ return pda;
320
+ }
321
+ function getFounderVaultPDA(projectPda, programId) {
322
+ const [pda] = PublicKey.findProgramAddressSync(
323
+ [Buffer.from("founder_vault"), projectPda.toBuffer()],
324
+ programId
325
+ );
326
+ return pda;
327
+ }
328
+ function getLpTokenVaultPDA(projectPda, programId) {
329
+ const [pda] = PublicKey.findProgramAddressSync(
330
+ [Buffer.from("lp_token_vault"), projectPda.toBuffer()],
331
+ programId
332
+ );
333
+ return pda;
334
+ }
335
+ function getTreasuryVaultPDA(projectPda, programId) {
336
+ const [pda] = PublicKey.findProgramAddressSync(
337
+ [Buffer.from("treasury_vault"), projectPda.toBuffer()],
338
+ programId
339
+ );
340
+ return pda;
341
+ }
342
+ function getLpUsdcVaultPDA(projectPda, programId) {
343
+ const [pda] = PublicKey.findProgramAddressSync(
344
+ [Buffer.from("lp_usdc_vault"), projectPda.toBuffer()],
345
+ programId
346
+ );
347
+ return pda;
348
+ }
349
+ function getFounderVestingPDA(projectPda, programId) {
350
+ const [pda] = PublicKey.findProgramAddressSync(
351
+ [Buffer.from("founder_vesting"), projectPda.toBuffer()],
352
+ programId
353
+ );
354
+ return pda;
355
+ }
356
+
357
+ // src/accounts/index.ts
358
+ function getAccountNamespace(program) {
359
+ return program.account;
360
+ }
361
+ async function fetchProject(program, projectId) {
362
+ try {
363
+ const projectPda = getProjectPDA(projectId, program.programId);
364
+ return await getAccountNamespace(program).project.fetch(projectPda);
365
+ } catch (error) {
366
+ if (error instanceof Error && error.message?.includes("Account does not exist")) {
367
+ return null;
368
+ }
369
+ throw error;
370
+ }
371
+ }
372
+ async function fetchProjectByPda(program, projectPda) {
373
+ try {
374
+ return await getAccountNamespace(program).project.fetch(projectPda);
375
+ } catch (error) {
376
+ if (error instanceof Error && error.message?.includes("Account does not exist")) {
377
+ return null;
378
+ }
379
+ throw error;
380
+ }
381
+ }
382
+ async function fetchMilestone(program, projectId, milestoneIndex) {
383
+ try {
384
+ const projectPda = getProjectPDA(projectId, program.programId);
385
+ const milestonePda = getMilestonePDA(projectPda, milestoneIndex, program.programId);
386
+ return await getAccountNamespace(program).milestone.fetch(milestonePda);
387
+ } catch (error) {
388
+ if (error instanceof Error && error.message?.includes("Account does not exist")) {
389
+ return null;
390
+ }
391
+ throw error;
392
+ }
393
+ }
394
+ async function fetchAllMilestones(program, projectId) {
395
+ const projectPda = getProjectPDA(projectId, program.programId);
396
+ const milestones = await getAccountNamespace(program).milestone.all([
397
+ {
398
+ memcmp: {
399
+ offset: 8,
400
+ // Skip discriminator
401
+ bytes: projectPda.toBase58()
402
+ }
403
+ }
404
+ ]);
405
+ return milestones.map((m) => ({
406
+ publicKey: m.publicKey,
407
+ account: m.account
408
+ }));
409
+ }
410
+ async function fetchInvestment(program, projectId, nftMint) {
411
+ try {
412
+ const projectPda = getProjectPDA(projectId, program.programId);
413
+ const investmentPda = getInvestmentPDA(projectPda, nftMint, program.programId);
414
+ return await getAccountNamespace(program).investment.fetch(investmentPda);
415
+ } catch (error) {
416
+ if (error instanceof Error && error.message?.includes("Account does not exist")) {
417
+ return null;
418
+ }
419
+ throw error;
420
+ }
421
+ }
422
+ async function fetchAllInvestments(program, projectId) {
423
+ const projectPda = getProjectPDA(projectId, program.programId);
424
+ const investments = await getAccountNamespace(program).investment.all([
425
+ {
426
+ memcmp: {
427
+ offset: 8,
428
+ // Skip discriminator
429
+ bytes: projectPda.toBase58()
430
+ }
431
+ }
432
+ ]);
433
+ return investments.map((inv) => ({
434
+ publicKey: inv.publicKey,
435
+ account: inv.account
436
+ }));
437
+ }
438
+ async function fetchVote(program, projectId, milestoneIndex, voterKey, votingRound) {
439
+ try {
440
+ const projectPda = getProjectPDA(projectId, program.programId);
441
+ const milestonePda = getMilestonePDA(projectPda, milestoneIndex, program.programId);
442
+ const votePda = getVotePDA(milestonePda, voterKey, votingRound, program.programId);
443
+ return await getAccountNamespace(program).vote.fetch(votePda);
444
+ } catch (error) {
445
+ if (error instanceof Error && error.message?.includes("Account does not exist")) {
446
+ return null;
447
+ }
448
+ throw error;
449
+ }
450
+ }
451
+ async function fetchAllVotes(program, projectId, milestoneIndex) {
452
+ const projectPda = getProjectPDA(projectId, program.programId);
453
+ const milestonePda = getMilestonePDA(projectPda, milestoneIndex, program.programId);
454
+ const votes = await getAccountNamespace(program).vote.all([
455
+ {
456
+ memcmp: {
457
+ offset: 8,
458
+ // Skip discriminator
459
+ bytes: milestonePda.toBase58()
460
+ }
461
+ }
462
+ ]);
463
+ return votes.map((v) => ({
464
+ publicKey: v.publicKey,
465
+ account: v.account
466
+ }));
467
+ }
468
+ async function fetchPivotProposal(program, projectId) {
469
+ try {
470
+ const projectPda = getProjectPDA(projectId, program.programId);
471
+ const projectAccount = await getAccountNamespace(program).project.fetch(projectPda);
472
+ let pivotPda;
473
+ if (projectAccount.activePivot) {
474
+ pivotPda = projectAccount.activePivot;
475
+ } else {
476
+ const pivotCount = projectAccount.pivotCount || 0;
477
+ pivotPda = getPivotProposalPDA(projectPda, pivotCount, program.programId);
478
+ }
479
+ return await getAccountNamespace(program).pivotProposal.fetch(pivotPda);
480
+ } catch (error) {
481
+ if (error instanceof Error && error.message?.includes("Account does not exist")) {
482
+ return null;
483
+ }
484
+ throw error;
485
+ }
486
+ }
487
+ async function fetchTgeEscrow(program, projectId) {
488
+ try {
489
+ const projectPda = getProjectPDA(projectId, program.programId);
490
+ const tgeEscrowPda = getTgeEscrowPDA(projectPda, program.programId);
491
+ return await getAccountNamespace(program).tgeEscrow.fetch(tgeEscrowPda);
492
+ } catch (error) {
493
+ if (error instanceof Error && error.message?.includes("Account does not exist")) {
494
+ return null;
495
+ }
496
+ throw error;
497
+ }
498
+ }
499
+ async function fetchAdminConfig(program) {
500
+ const adminConfigPda = getAdminConfigPDA(program.programId);
501
+ return await getAccountNamespace(program).adminConfig.fetch(adminConfigPda);
502
+ }
503
+ async function accountExists(program, accountType, pda) {
504
+ try {
505
+ await program.account[accountType].fetch(pda);
506
+ return true;
507
+ } catch {
508
+ return false;
509
+ }
510
+ }
511
+ var TOKEN_METADATA_PROGRAM_ID = new PublicKey("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s");
512
+ function ensurePublicKey(value) {
513
+ if (value instanceof PublicKey) {
514
+ return value;
515
+ }
516
+ return new PublicKey(String(value));
517
+ }
518
+ function getMethods(program) {
519
+ return program.methods;
520
+ }
521
+ function getAccountNamespace2(program) {
522
+ return program.account;
523
+ }
524
+ async function initializeAdmin(program, admin, payer) {
525
+ return getMethods(program).initializeAdmin().accounts({
526
+ admin,
527
+ payer
528
+ }).rpc();
529
+ }
530
+ async function transferAdmin(program, adminKeypair, newAdmin) {
531
+ return getMethods(program).transferAdmin().accounts({
532
+ authority: adminKeypair.publicKey,
533
+ newAdmin
534
+ }).signers([adminKeypair]).rpc();
535
+ }
536
+ async function acceptAdmin(program, newAuthority) {
537
+ return getMethods(program).acceptAdmin().accounts({
538
+ newAuthority
539
+ }).rpc();
540
+ }
541
+ function symbolToBytes(symbol) {
542
+ const bytes = new Array(8).fill(0);
543
+ const chars = symbol.toUpperCase().slice(0, 8);
544
+ for (let i = 0; i < chars.length; i++) {
545
+ bytes[i] = chars.charCodeAt(i);
546
+ }
547
+ return bytes;
548
+ }
549
+ var MIN_DEADLINE_DURATION_SECONDS_PROD = 604800;
550
+ var MIN_DEADLINE_DURATION_SECONDS_DEV = 60;
551
+ var MAX_DEADLINE_DURATION_SECONDS = 31536e3;
552
+ function calculateDeadline(daysFromNow, isDev = false) {
553
+ const nowSeconds = Math.floor(Date.now() / 1e3);
554
+ const minDuration = isDev ? MIN_DEADLINE_DURATION_SECONDS_DEV : MIN_DEADLINE_DURATION_SECONDS_PROD;
555
+ const daysInSeconds = daysFromNow * 24 * 60 * 60;
556
+ const deadlineSeconds = nowSeconds + Math.max(daysInSeconds, minDuration);
557
+ const maxDeadline = nowSeconds + MAX_DEADLINE_DURATION_SECONDS;
558
+ return new BN(Math.min(deadlineSeconds, maxDeadline));
559
+ }
560
+ function minDeadline(isDev = false) {
561
+ const nowSeconds = Math.floor(Date.now() / 1e3);
562
+ const minDuration = isDev ? MIN_DEADLINE_DURATION_SECONDS_DEV : MIN_DEADLINE_DURATION_SECONDS_PROD;
563
+ return new BN(nowSeconds + minDuration + 1);
564
+ }
565
+ function validateDeadline(deadline, isDev = false) {
566
+ const nowSeconds = Math.floor(Date.now() / 1e3);
567
+ const deadlineSeconds = deadline.toNumber();
568
+ const minDuration = isDev ? MIN_DEADLINE_DURATION_SECONDS_DEV : MIN_DEADLINE_DURATION_SECONDS_PROD;
569
+ const minDeadline2 = nowSeconds + minDuration;
570
+ const maxDeadline = nowSeconds + MAX_DEADLINE_DURATION_SECONDS;
571
+ if (deadlineSeconds < minDeadline2) {
572
+ const minDays = isDev ? "60 seconds" : "7 days";
573
+ return {
574
+ valid: false,
575
+ error: `Deadline must be at least ${minDays} from now`
576
+ };
577
+ }
578
+ if (deadlineSeconds > maxDeadline) {
579
+ return {
580
+ valid: false,
581
+ error: "Deadline must be within 1 year from now"
582
+ };
583
+ }
584
+ return { valid: true };
585
+ }
586
+ async function initializeProject(program, args, founder) {
587
+ return getMethods(program).initializeProject({
588
+ projectId: args.projectId,
589
+ fundingGoal: args.fundingGoal,
590
+ metadataUri: args.metadataUri,
591
+ tiers: args.tiers,
592
+ tokenomics: {
593
+ tokenSymbol: args.tokenomics.tokenSymbol,
594
+ totalSupply: args.tokenomics.totalSupply,
595
+ investorAllocationBps: args.tokenomics.investorAllocationBps,
596
+ lpTokenAllocationBps: args.tokenomics.lpTokenAllocationBps,
597
+ lpUsdcAllocationBps: args.tokenomics.lpUsdcAllocationBps,
598
+ founderAllocationBps: args.tokenomics.founderAllocationBps ?? null,
599
+ treasuryAllocationBps: args.tokenomics.treasuryAllocationBps ?? null,
600
+ founderWallet: args.tokenomics.founderWallet ?? null,
601
+ vestingDurationMonths: args.tokenomics.vestingDurationMonths ?? null,
602
+ cliffMonths: args.tokenomics.cliffMonths ?? null
603
+ },
604
+ milestone1Deadline: args.milestone1Deadline
605
+ }).accounts({
606
+ founder
607
+ }).rpc();
608
+ }
609
+ async function submitForApproval(program, projectId, founder) {
610
+ const projectPda = getProjectPDA(projectId, program.programId);
611
+ return getMethods(program).submitForApproval().accounts({
612
+ project: projectPda,
613
+ founder
614
+ }).rpc();
615
+ }
616
+ async function approveProject(program, args, adminKeypair) {
617
+ const projectPda = getProjectPDA(args.projectId, program.programId);
618
+ const tokenomicsPda = getTokenomicsPDA(projectPda, program.programId);
619
+ const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
620
+ const tokenMintPda = getTokenMintPDA(projectPda, program.programId);
621
+ const vaultAuthorityPda = getVaultAuthorityPDA(projectPda, program.programId);
622
+ const investorVaultPda = getInvestorVaultPDA(projectPda, program.programId);
623
+ const founderVaultPda = getFounderVaultPDA(projectPda, program.programId);
624
+ const lpTokenVaultPda = getLpTokenVaultPDA(projectPda, program.programId);
625
+ const treasuryVaultPda = getTreasuryVaultPDA(projectPda, program.programId);
626
+ const lpUsdcVaultPda = getLpUsdcVaultPDA(projectPda, program.programId);
627
+ return getMethods(program).approveProject().accounts({
628
+ project: projectPda,
629
+ tokenomics: tokenomicsPda,
630
+ tokenVault: tokenVaultPda,
631
+ tokenMint: tokenMintPda,
632
+ vaultAuthority: vaultAuthorityPda,
633
+ investorVault: investorVaultPda,
634
+ founderVault: founderVaultPda,
635
+ lpTokenVault: lpTokenVaultPda,
636
+ treasuryVault: treasuryVaultPda,
637
+ lpUsdcVault: lpUsdcVaultPda,
638
+ usdcMint: args.usdcMint,
639
+ authority: adminKeypair.publicKey,
640
+ payer: adminKeypair.publicKey
641
+ }).signers([adminKeypair]).rpc();
642
+ }
643
+ async function createMilestone(program, args, founder) {
644
+ const projectPda = getProjectPDA(args.projectId, program.programId);
645
+ const milestonePda = getMilestonePDA(projectPda, args.milestoneIndex, program.programId);
646
+ return getMethods(program).createMilestone({
647
+ milestoneIndex: args.milestoneIndex,
648
+ percentage: args.percentage,
649
+ description: args.description
650
+ }).accounts({
651
+ project: projectPda,
652
+ milestone: milestonePda,
653
+ founder
654
+ }).rpc();
655
+ }
656
+ async function submitMilestone(program, projectId, milestoneIndex, founder) {
657
+ const projectPda = getProjectPDA(projectId, program.programId);
658
+ const milestonePda = getMilestonePDA(projectPda, milestoneIndex, program.programId);
659
+ return getMethods(program).submitMilestone().accounts({
660
+ project: projectPda,
661
+ milestone: milestonePda,
662
+ founder
663
+ }).rpc();
664
+ }
665
+ async function voteOnMilestone(program, args, voter) {
666
+ const nftMintPubkey = ensurePublicKey(args.nftMint);
667
+ const projectPda = getProjectPDA(args.projectId, program.programId);
668
+ const milestonePda = getMilestonePDA(projectPda, args.milestoneIndex, program.programId);
669
+ const investmentPda = getInvestmentPDA(projectPda, nftMintPubkey, program.programId);
670
+ const milestone = await getAccountNamespace2(program).milestone.fetch(milestonePda);
671
+ const votingRound = milestone.votingRound ?? 0;
672
+ const votePda = getVotePDA(milestonePda, voter, votingRound, program.programId);
673
+ const voterNftAccount = getAssociatedTokenAddressSync(
674
+ nftMintPubkey,
675
+ voter,
676
+ false,
677
+ // allowOwnerOffCurve
678
+ TOKEN_PROGRAM_ID
679
+ );
680
+ return getMethods(program).voteOnMilestone({ choice: args.choice }).accounts({
681
+ milestone: milestonePda,
682
+ project: projectPda,
683
+ investment: investmentPda,
684
+ vote: votePda,
685
+ nftMint: nftMintPubkey,
686
+ voterNftAccount,
687
+ voter
688
+ }).rpc();
689
+ }
690
+ async function finalizeVoting(program, projectId, milestoneIndex) {
691
+ const projectPda = getProjectPDA(projectId, program.programId);
692
+ const milestonePda = getMilestonePDA(projectPda, milestoneIndex, program.programId);
693
+ return getMethods(program).finalizeVoting().accounts({
694
+ project: projectPda,
695
+ milestone: milestonePda
696
+ }).rpc();
697
+ }
698
+ async function claimMilestoneFunds(program, args, founder) {
699
+ const projectPda = getProjectPDA(args.projectId, program.programId);
700
+ const milestonePda = getMilestonePDA(projectPda, args.milestoneIndex, program.programId);
701
+ const escrowPda = getEscrowPDA(args.projectId, program.programId);
702
+ const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
703
+ const tokenomicsPda = getTokenomicsPDA(projectPda, program.programId);
704
+ const lpUsdcVaultPda = getLpUsdcVaultPDA(projectPda, program.programId);
705
+ const nextMilestonePda = args.nextMilestonePda ?? (args.nextMilestoneDeadline.gt(new BN(0)) ? getMilestonePDA(projectPda, args.milestoneIndex + 1, program.programId) : null);
706
+ return getMethods(program).claimMilestoneFunds({ nextMilestoneDeadline: args.nextMilestoneDeadline }).accounts({
707
+ milestone: milestonePda,
708
+ project: projectPda,
709
+ founder,
710
+ projectEscrow: args.escrowTokenAccount,
711
+ founderUsdcAccount: args.founderUsdcAccount,
712
+ escrowPda,
713
+ tokenVault: tokenVaultPda,
714
+ tokenomics: tokenomicsPda,
715
+ lpUsdcVault: lpUsdcVaultPda,
716
+ nextMilestone: nextMilestonePda,
717
+ systemProgram: SystemProgram.programId,
718
+ tokenProgram: TOKEN_PROGRAM_ID
719
+ }).rpc();
720
+ }
721
+ async function resubmitMilestone(program, args, founder) {
722
+ const projectPda = getProjectPDA(args.projectId, program.programId);
723
+ const milestonePda = getMilestonePDA(projectPda, args.milestoneIndex, program.programId);
724
+ return getMethods(program).resubmitMilestone().accounts({
725
+ project: projectPda,
726
+ milestone: milestonePda,
727
+ founder
728
+ }).rpc();
729
+ }
730
+ async function setMilestoneDeadline(program, args, founder) {
731
+ const projectPda = getProjectPDA(args.projectId, program.programId);
732
+ const milestonePda = getMilestonePDA(projectPda, args.milestoneIndex, program.programId);
733
+ return getMethods(program).setMilestoneDeadline({
734
+ milestoneIndex: args.milestoneIndex,
735
+ deadline: args.deadline
736
+ }).accounts({
737
+ project: projectPda,
738
+ milestone: milestonePda,
739
+ founder
740
+ }).rpc();
741
+ }
742
+ async function extendMilestoneDeadline(program, args, founder) {
743
+ const projectPda = getProjectPDA(args.projectId, program.programId);
744
+ const milestonePda = getMilestonePDA(projectPda, args.milestoneIndex, program.programId);
745
+ return getMethods(program).extendMilestoneDeadline({
746
+ milestoneIndex: args.milestoneIndex,
747
+ newDeadline: args.newDeadline
748
+ }).accounts({
749
+ project: projectPda,
750
+ milestone: milestonePda,
751
+ founder
752
+ }).rpc();
753
+ }
754
+ function getMetadataPDA(mint) {
755
+ const [pda] = PublicKey.findProgramAddressSync(
756
+ [
757
+ Buffer.from("metadata"),
758
+ TOKEN_METADATA_PROGRAM_ID.toBuffer(),
759
+ mint.toBuffer()
760
+ ],
761
+ TOKEN_METADATA_PROGRAM_ID
762
+ );
763
+ return pda;
764
+ }
765
+ function getMasterEditionPDA(mint) {
766
+ const [pda] = PublicKey.findProgramAddressSync(
767
+ [
768
+ Buffer.from("metadata"),
769
+ TOKEN_METADATA_PROGRAM_ID.toBuffer(),
770
+ mint.toBuffer(),
771
+ Buffer.from("edition")
772
+ ],
773
+ TOKEN_METADATA_PROGRAM_ID
774
+ );
775
+ return pda;
776
+ }
777
+ async function invest(program, args, investor) {
778
+ const projectPda = getProjectPDA(args.projectId, program.programId);
779
+ const [nftMint] = getNftMintPDA(args.projectId, investor, args.investmentCount, program.programId);
780
+ const investmentPda = getInvestmentPDA(projectPda, nftMint, program.programId);
781
+ const investorNftAccount = getAssociatedTokenAddressSync(nftMint, investor);
782
+ const metadataAccount = getMetadataPDA(nftMint);
783
+ const masterEdition = getMasterEditionPDA(nftMint);
784
+ const [programAuthority] = getProgramAuthorityPDA(program.programId);
785
+ const firstMilestonePda = getMilestonePDA(projectPda, 0, program.programId);
786
+ return getMethods(program).invest({ amount: args.amount }).accounts({
787
+ project: projectPda,
788
+ firstMilestone: firstMilestonePda,
789
+ nftMint,
790
+ investment: investmentPda,
791
+ investorNftAccount,
792
+ metadataAccount,
793
+ masterEdition,
794
+ escrowTokenAccount: args.escrowTokenAccount,
795
+ investorTokenAccount: args.investorTokenAccount,
796
+ programAuthority,
797
+ investor,
798
+ tokenProgram: TOKEN_PROGRAM_ID,
799
+ associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID,
800
+ systemProgram: SystemProgram.programId,
801
+ rent: SYSVAR_RENT_PUBKEY,
802
+ tokenMetadataProgram: TOKEN_METADATA_PROGRAM_ID,
803
+ sysvarInstructions: SYSVAR_INSTRUCTIONS_PUBKEY
804
+ }).preInstructions([
805
+ ComputeBudgetProgram.setComputeUnitLimit({ units: 4e5 })
806
+ ]).rpc();
807
+ }
808
+ async function cancelInvestment(program, args, investor) {
809
+ const nftMintPubkey = ensurePublicKey(args.nftMint);
810
+ const projectPda = getProjectPDA(args.projectId, program.programId);
811
+ const investmentPda = getInvestmentPDA(projectPda, nftMintPubkey, program.programId);
812
+ const escrowPda = getEscrowPDA(args.projectId, program.programId);
813
+ return getMethods(program).cancelInvestment().accounts({
814
+ investor,
815
+ project: projectPda,
816
+ investment: investmentPda,
817
+ nftMint: nftMintPubkey,
818
+ investorNftAccount: args.investorNftAccount,
819
+ projectEscrow: args.escrowTokenAccount,
820
+ investorUsdcAccount: args.investorUsdcAccount,
821
+ escrowPda
822
+ }).rpc();
823
+ }
824
+ async function proposePivot(program, args, founder) {
825
+ const projectPda = getProjectPDA(args.projectId, program.programId);
826
+ const projectAccount = await getAccountNamespace2(program).project.fetch(projectPda);
827
+ const pivotCount = projectAccount.pivotCount || 0;
828
+ const pivotProposalPda = getPivotProposalPDA(projectPda, pivotCount, program.programId);
829
+ return getMethods(program).proposePivot({
830
+ newMetadataUri: args.newMetadataUri,
831
+ newMilestones: args.newMilestones
832
+ }).accounts({
833
+ project: projectPda,
834
+ founder,
835
+ pivotProposal: pivotProposalPda,
836
+ systemProgram: SystemProgram.programId,
837
+ clock: SYSVAR_CLOCK_PUBKEY
838
+ }).rpc();
839
+ }
840
+ async function approvePivot(program, projectId, adminKeypair) {
841
+ const projectPda = getProjectPDA(projectId, program.programId);
842
+ const projectAccount = await getAccountNamespace2(program).project.fetch(projectPda);
843
+ let pivotProposalPda;
844
+ if (projectAccount.activePivot) {
845
+ pivotProposalPda = projectAccount.activePivot;
846
+ } else {
847
+ const pivotCount = projectAccount.pivotCount || 0;
848
+ pivotProposalPda = getPivotProposalPDA(projectPda, pivotCount, program.programId);
849
+ }
850
+ return getMethods(program).approvePivot().accounts({
851
+ moderator: adminKeypair.publicKey,
852
+ project: projectPda,
853
+ pivotProposal: pivotProposalPda
854
+ }).signers([adminKeypair]).rpc();
855
+ }
856
+ async function withdrawFromPivot(program, args, investor) {
857
+ const nftMintPubkey = ensurePublicKey(args.nftMint);
858
+ const projectPda = getProjectPDA(args.projectId, program.programId);
859
+ const investmentPda = getInvestmentPDA(projectPda, nftMintPubkey, program.programId);
860
+ const escrowPda = getEscrowPDA(args.projectId, program.programId);
861
+ const pivotProposalPda = getPivotProposalPDA(projectPda, args.pivotCount, program.programId);
862
+ const investorNftAccount = getAssociatedTokenAddressSync(
863
+ nftMintPubkey,
864
+ investor,
865
+ false,
866
+ TOKEN_PROGRAM_ID
867
+ );
868
+ const remainingAccounts = args.milestoneAccounts.map((pubkey) => ({
869
+ pubkey: ensurePublicKey(pubkey),
870
+ isSigner: false,
871
+ isWritable: false
872
+ }));
873
+ return getMethods(program).withdrawFromPivot().accounts({
874
+ investor,
875
+ project: projectPda,
876
+ pivotProposal: pivotProposalPda,
877
+ investment: investmentPda,
878
+ nftMint: nftMintPubkey,
879
+ investorNftAccount,
880
+ escrowTokenAccount: args.escrowTokenAccount,
881
+ investorTokenAccount: args.investorTokenAccount,
882
+ escrow: escrowPda
883
+ }).remainingAccounts(remainingAccounts).rpc();
884
+ }
885
+ async function finalizePivot(program, args, authority) {
886
+ const projectPda = getProjectPDA(args.projectId, program.programId);
887
+ const pivotProposalPda = getPivotProposalPDA(projectPda, args.pivotCount, program.programId);
888
+ const remainingAccounts = args.milestoneAccounts.map((pubkey) => ({
889
+ pubkey,
890
+ isSigner: false,
891
+ isWritable: true
892
+ }));
893
+ return getMethods(program).finalizePivot().accounts({
894
+ authority,
895
+ project: projectPda,
896
+ pivotProposal: pivotProposalPda
897
+ }).remainingAccounts(remainingAccounts).rpc();
898
+ }
899
+ async function setTgeDate(program, args, founder) {
900
+ const projectPda = getProjectPDA(args.projectId, program.programId);
901
+ return getMethods(program).setTgeDate({
902
+ tgeDate: args.tgeDate,
903
+ tokenMint: args.tokenMint
904
+ }).accounts({
905
+ project: projectPda,
906
+ founder
907
+ }).rpc();
908
+ }
909
+ async function depositTokens(program, args, founder) {
910
+ const projectPda = getProjectPDA(args.projectId, program.programId);
911
+ return getMethods(program).depositTokens({ amount: args.amount }).accounts({
912
+ project: projectPda,
913
+ tokenMint: args.tokenMint,
914
+ founderTokenAccount: args.founderTokenAccount,
915
+ founder
916
+ }).rpc();
917
+ }
918
+ async function claimTokens(program, args, investor) {
919
+ const projectPda = getProjectPDA(args.projectId, program.programId);
920
+ const investmentPda = getInvestmentPDA(projectPda, args.nftMint, program.programId);
921
+ const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
922
+ return getMethods(program).claimTokens().accounts({
923
+ investor,
924
+ project: projectPda,
925
+ investment: investmentPda,
926
+ investorNftAccount: args.investorNftAccount,
927
+ projectTokenVault: args.projectTokenVault,
928
+ investorTokenAccount: args.investorTokenAccount,
929
+ tokenVaultPda,
930
+ tokenProgram: TOKEN_PROGRAM_ID
931
+ }).rpc();
932
+ }
933
+ async function reportScam(program, args, reporter) {
934
+ const projectPda = getProjectPDA(args.projectId, program.programId);
935
+ const tgeEscrowPda = getTgeEscrowPDA(projectPda, program.programId);
936
+ const investmentPda = getInvestmentPDA(projectPda, args.nftMint, program.programId);
937
+ return getMethods(program).reportScam().accounts({
938
+ tgeEscrow: tgeEscrowPda,
939
+ project: projectPda,
940
+ investment: investmentPda,
941
+ nftMint: args.nftMint,
942
+ reporter
943
+ }).rpc();
944
+ }
945
+ async function releaseHoldback(program, args) {
946
+ const projectPda = getProjectPDA(args.projectId, program.programId);
947
+ const tgeEscrowPda = getTgeEscrowPDA(projectPda, program.programId);
948
+ return getMethods(program).releaseHoldback().accounts({
949
+ tgeEscrow: tgeEscrowPda,
950
+ project: projectPda,
951
+ founderTokenAccount: args.founderTokenAccount
952
+ }).rpc();
953
+ }
954
+ async function checkAbandonment(program, projectId, milestoneIndex = 0) {
955
+ const projectPda = getProjectPDA(projectId, program.programId);
956
+ const milestonePda = getMilestonePDA(projectPda, milestoneIndex, program.programId);
957
+ return getMethods(program).checkAbandonment().accounts({
958
+ project: projectPda,
959
+ milestone: milestonePda
960
+ }).rpc();
961
+ }
962
+ async function claimRefund(program, args, investor) {
963
+ const nftMintPubkey = ensurePublicKey(args.nftMint);
964
+ const projectPda = getProjectPDA(args.projectId, program.programId);
965
+ const investmentPda = getInvestmentPDA(projectPda, nftMintPubkey, program.programId);
966
+ const milestoneCount = args.milestoneCount ?? 1;
967
+ const remainingAccounts = [];
968
+ for (let i = 0; i < milestoneCount; i++) {
969
+ const milestonePda = getMilestonePDA(projectPda, i, program.programId);
970
+ remainingAccounts.push({
971
+ pubkey: milestonePda,
972
+ isWritable: false,
973
+ isSigner: false
974
+ });
975
+ }
976
+ return getMethods(program).claimRefund().accounts({
977
+ project: projectPda,
978
+ investment: investmentPda,
979
+ nftMint: nftMintPubkey,
980
+ investorNftAccount: args.investorNftAccount,
981
+ investor,
982
+ investorTokenAccount: args.investorUsdcAccount,
983
+ escrowTokenAccount: args.escrowTokenAccount
984
+ }).remainingAccounts(remainingAccounts).rpc();
985
+ }
986
+ async function claimInvestorTokens(program, args, investor) {
987
+ const nftMintPubkey = ensurePublicKey(args.nftMint);
988
+ const projectPda = getProjectPDA(args.projectId, program.programId);
989
+ const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
990
+ const investmentPda = getInvestmentPDA(projectPda, nftMintPubkey, program.programId);
991
+ const investorVaultPda = getInvestorVaultPDA(projectPda, program.programId);
992
+ const vaultAuthorityPda = getVaultAuthorityPDA(projectPda, program.programId);
993
+ const investorNftAccount = getAssociatedTokenAddressSync(
994
+ nftMintPubkey,
995
+ investor,
996
+ false,
997
+ TOKEN_PROGRAM_ID
998
+ );
999
+ return getMethods(program).claimInvestorTokens({ milestoneIndex: args.milestoneIndex }).accounts({
1000
+ investor,
1001
+ project: projectPda,
1002
+ tokenVault: tokenVaultPda,
1003
+ investment: investmentPda,
1004
+ nftMint: nftMintPubkey,
1005
+ investorNftAccount,
1006
+ investorVault: investorVaultPda,
1007
+ investorTokenAccount: args.investorTokenAccount,
1008
+ vaultAuthority: vaultAuthorityPda,
1009
+ tokenProgram: TOKEN_PROGRAM_ID
1010
+ }).rpc();
1011
+ }
1012
+ async function distributeTokens(program, args, payer) {
1013
+ const projectPda = getProjectPDA(args.projectId, program.programId);
1014
+ const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
1015
+ const investorVaultPda = getInvestorVaultPDA(projectPda, program.programId);
1016
+ const vaultAuthorityPda = getVaultAuthorityPDA(projectPda, program.programId);
1017
+ const remainingAccounts = args.investments.flatMap((inv) => [
1018
+ { pubkey: inv.investmentPda, isSigner: false, isWritable: true },
1019
+ { pubkey: inv.investorTokenAccount, isSigner: false, isWritable: true }
1020
+ ]);
1021
+ return getMethods(program).distributeTokens({ milestoneIndex: args.milestoneIndex }).accounts({
1022
+ project: projectPda,
1023
+ tokenVault: tokenVaultPda,
1024
+ investorVault: investorVaultPda,
1025
+ vaultAuthority: vaultAuthorityPda,
1026
+ payer,
1027
+ tokenProgram: TOKEN_PROGRAM_ID
1028
+ }).remainingAccounts(remainingAccounts).rpc();
1029
+ }
1030
+ async function completeDistribution(program, args, payer) {
1031
+ const projectPda = getProjectPDA(args.projectId, program.programId);
1032
+ const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
1033
+ return getMethods(program).completeDistribution({ milestoneIndex: args.milestoneIndex }).accounts({
1034
+ project: projectPda,
1035
+ tokenVault: tokenVaultPda,
1036
+ payer
1037
+ }).rpc();
1038
+ }
1039
+ async function claimExitWindowRefund(program, args, investor) {
1040
+ const projectPda = getProjectPDA(args.projectId, program.programId);
1041
+ const investmentPda = getInvestmentPDA(projectPda, args.nftMint, program.programId);
1042
+ const escrowPda = getEscrowPDA(args.projectId, program.programId);
1043
+ const remainingAccounts = (args.milestoneAccounts || []).map((pubkey) => ({
1044
+ pubkey,
1045
+ isSigner: false,
1046
+ isWritable: false
1047
+ }));
1048
+ return getMethods(program).claimExitWindowRefund().accountsPartial({
1049
+ project: projectPda,
1050
+ investment: investmentPda,
1051
+ nftMint: args.nftMint,
1052
+ investorNftAccount: args.investorNftAccount,
1053
+ escrowTokenAccount: args.escrowTokenAccount,
1054
+ investorTokenAccount: args.investorTokenAccount,
1055
+ escrowPda,
1056
+ investor
1057
+ }).remainingAccounts(remainingAccounts).rpc();
1058
+ }
1059
+ async function initializeFounderVesting(program, args, payer) {
1060
+ const projectPda = getProjectPDA(args.projectId, program.programId);
1061
+ const tokenomicsPda = getTokenomicsPDA(projectPda, program.programId);
1062
+ const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
1063
+ const founderVestingPda = getFounderVestingPDA(projectPda, program.programId);
1064
+ return getMethods(program).initializeFounderVesting().accounts({
1065
+ project: projectPda,
1066
+ tokenomics: tokenomicsPda,
1067
+ tokenVault: tokenVaultPda,
1068
+ founderVesting: founderVestingPda,
1069
+ payer,
1070
+ systemProgram: SystemProgram.programId
1071
+ }).rpc();
1072
+ }
1073
+ async function claimVestedTokens(program, args, founder) {
1074
+ const projectPda = getProjectPDA(args.projectId, program.programId);
1075
+ const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
1076
+ const founderVestingPda = getFounderVestingPDA(projectPda, program.programId);
1077
+ const founderVaultPda = getFounderVaultPDA(projectPda, program.programId);
1078
+ const vaultAuthorityPda = getVaultAuthorityPDA(projectPda, program.programId);
1079
+ return getMethods(program).claimVestedTokens().accounts({
1080
+ project: projectPda,
1081
+ tokenVault: tokenVaultPda,
1082
+ founderVesting: founderVestingPda,
1083
+ founderVault: founderVaultPda,
1084
+ vaultAuthority: vaultAuthorityPda,
1085
+ founderTokenAccount: args.founderTokenAccount,
1086
+ founder,
1087
+ tokenProgram: TOKEN_PROGRAM_ID
1088
+ }).rpc();
1089
+ }
1090
+ async function forceCompleteDistribution(program, args, adminKeypair) {
1091
+ const projectPda = getProjectPDA(args.projectId, program.programId);
1092
+ const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
1093
+ const adminConfigPda = getAdminConfigPDA(program.programId);
1094
+ return getMethods(program).forceCompleteDistribution().accounts({
1095
+ admin: adminKeypair.publicKey,
1096
+ adminConfig: adminConfigPda,
1097
+ project: projectPda,
1098
+ tokenVault: tokenVaultPda
1099
+ }).signers([adminKeypair]).rpc();
1100
+ }
1101
+ async function claimMissedUnlock(program, args, claimer) {
1102
+ const nftMintPubkey = ensurePublicKey(args.nftMint);
1103
+ const projectPda = getProjectPDA(args.projectId, program.programId);
1104
+ const tokenVaultPda = getTokenVaultPDA(projectPda, program.programId);
1105
+ const investmentPda = getInvestmentPDA(projectPda, nftMintPubkey, program.programId);
1106
+ const investorVaultPda = getInvestorVaultPDA(projectPda, program.programId);
1107
+ const vaultAuthorityPda = getVaultAuthorityPDA(projectPda, program.programId);
1108
+ const claimerNftAccount = getAssociatedTokenAddressSync(
1109
+ nftMintPubkey,
1110
+ claimer,
1111
+ false,
1112
+ TOKEN_PROGRAM_ID
1113
+ );
1114
+ return getMethods(program).claimMissedUnlock({ milestoneIndex: args.milestoneIndex }).accounts({
1115
+ claimer,
1116
+ project: projectPda,
1117
+ tokenVault: tokenVaultPda,
1118
+ investment: investmentPda,
1119
+ nftMint: nftMintPubkey,
1120
+ claimerNftAccount,
1121
+ investorVault: investorVaultPda,
1122
+ claimerTokenAccount: args.claimerTokenAccount,
1123
+ vaultAuthority: vaultAuthorityPda,
1124
+ tokenProgram: TOKEN_PROGRAM_ID
1125
+ }).rpc();
1126
+ }
1127
+
1128
+ // src/client.ts
1129
+ var RaiseClient = class _RaiseClient {
1130
+ /**
1131
+ * Create a new RaiseClient
1132
+ *
1133
+ * @param program - Anchor program instance
1134
+ * @param provider - Anchor provider
1135
+ */
1136
+ constructor(program, provider) {
1137
+ this.program = program;
1138
+ this.provider = provider;
1139
+ }
1140
+ /**
1141
+ * Load a new RaiseClient instance
1142
+ *
1143
+ * @param connection - Solana connection
1144
+ * @param wallet - Wallet instance
1145
+ * @param programId - Optional program ID override
1146
+ * @returns Initialized RaiseClient
1147
+ *
1148
+ * @example
1149
+ * ```typescript
1150
+ * const client = RaiseClient.load(connection, wallet);
1151
+ * ```
1152
+ */
1153
+ static load(_connection, _wallet, _programId) {
1154
+ throw new Error(
1155
+ "RaiseClient.load requires IDL. Use RaiseClient.fromProgram instead, or ensure the IDL is bundled with your application."
1156
+ );
1157
+ }
1158
+ /**
1159
+ * Create client from an existing program instance
1160
+ *
1161
+ * @param program - Anchor program instance
1162
+ * @returns Initialized RaiseClient
1163
+ *
1164
+ * @example
1165
+ * ```typescript
1166
+ * import idl from './idl/raise.json';
1167
+ *
1168
+ * const provider = new AnchorProvider(connection, wallet, {});
1169
+ * const program = new Program(idl, provider);
1170
+ * const client = RaiseClient.fromProgram(program);
1171
+ * ```
1172
+ */
1173
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1174
+ static fromProgram(program) {
1175
+ const provider = program.provider;
1176
+ return new _RaiseClient(program, provider);
1177
+ }
1178
+ /**
1179
+ * Get the program ID
1180
+ */
1181
+ get programId() {
1182
+ return this.program.programId;
1183
+ }
1184
+ /**
1185
+ * Get the connected wallet public key
1186
+ */
1187
+ get walletPublicKey() {
1188
+ return this.provider.wallet.publicKey;
1189
+ }
1190
+ // ===========================================================================
1191
+ // PDA Helpers
1192
+ // ===========================================================================
1193
+ getProjectPDA(projectId) {
1194
+ return getProjectPDA(projectId, this.programId);
1195
+ }
1196
+ getEscrowPDA(projectId) {
1197
+ return getEscrowPDA(projectId, this.programId);
1198
+ }
1199
+ getMilestonePDA(projectPda, milestoneIndex) {
1200
+ return getMilestonePDA(projectPda, milestoneIndex, this.programId);
1201
+ }
1202
+ getInvestmentPDA(projectPda, nftMint) {
1203
+ return getInvestmentPDA(projectPda, nftMint, this.programId);
1204
+ }
1205
+ getVotePDA(milestonePda, voterKey, votingRound) {
1206
+ return getVotePDA(milestonePda, voterKey, votingRound, this.programId);
1207
+ }
1208
+ getPivotProposalPDA(projectPda, pivotCount) {
1209
+ return getPivotProposalPDA(projectPda, pivotCount, this.programId);
1210
+ }
1211
+ getTgeEscrowPDA(projectPda) {
1212
+ return getTgeEscrowPDA(projectPda, this.programId);
1213
+ }
1214
+ getTgeEscrowVaultPDA(projectPda) {
1215
+ return getTgeEscrowVaultPDA(projectPda, this.programId);
1216
+ }
1217
+ getAdminConfigPDA() {
1218
+ return getAdminConfigPDA(this.programId);
1219
+ }
1220
+ // ===========================================================================
1221
+ // Account Fetchers
1222
+ // ===========================================================================
1223
+ async fetchProject(projectId) {
1224
+ return fetchProject(this.program, projectId);
1225
+ }
1226
+ async fetchMilestone(projectId, milestoneIndex) {
1227
+ return fetchMilestone(this.program, projectId, milestoneIndex);
1228
+ }
1229
+ async fetchAllMilestones(projectId) {
1230
+ return fetchAllMilestones(this.program, projectId);
1231
+ }
1232
+ async fetchInvestment(projectId, nftMint) {
1233
+ return fetchInvestment(this.program, projectId, nftMint);
1234
+ }
1235
+ async fetchAllInvestments(projectId) {
1236
+ return fetchAllInvestments(this.program, projectId);
1237
+ }
1238
+ async fetchVote(projectId, milestoneIndex, voterKey, votingRound) {
1239
+ return fetchVote(this.program, projectId, milestoneIndex, voterKey, votingRound);
1240
+ }
1241
+ async fetchAllVotes(projectId, milestoneIndex) {
1242
+ return fetchAllVotes(this.program, projectId, milestoneIndex);
1243
+ }
1244
+ async fetchPivotProposal(projectId) {
1245
+ return fetchPivotProposal(this.program, projectId);
1246
+ }
1247
+ async fetchTgeEscrow(projectId) {
1248
+ return fetchTgeEscrow(this.program, projectId);
1249
+ }
1250
+ async fetchAdminConfig() {
1251
+ return fetchAdminConfig(this.program);
1252
+ }
1253
+ // ===========================================================================
1254
+ // Admin Instructions
1255
+ // ===========================================================================
1256
+ async initializeAdmin(admin) {
1257
+ return initializeAdmin(
1258
+ this.program,
1259
+ admin,
1260
+ this.walletPublicKey
1261
+ );
1262
+ }
1263
+ async transferAdmin(newAdmin, adminKeypair) {
1264
+ return transferAdmin(
1265
+ this.program,
1266
+ adminKeypair,
1267
+ newAdmin
1268
+ );
1269
+ }
1270
+ async acceptAdmin() {
1271
+ return acceptAdmin(
1272
+ this.program,
1273
+ this.walletPublicKey
1274
+ );
1275
+ }
1276
+ // ===========================================================================
1277
+ // Project Instructions
1278
+ // ===========================================================================
1279
+ async initializeProject(args) {
1280
+ return initializeProject(
1281
+ this.program,
1282
+ args,
1283
+ this.walletPublicKey
1284
+ );
1285
+ }
1286
+ async submitForApproval(projectId) {
1287
+ return submitForApproval(
1288
+ this.program,
1289
+ projectId,
1290
+ this.walletPublicKey
1291
+ );
1292
+ }
1293
+ async approveProject(args, adminKeypair) {
1294
+ return approveProject(
1295
+ this.program,
1296
+ args,
1297
+ adminKeypair
1298
+ );
1299
+ }
1300
+ // ===========================================================================
1301
+ // Milestone Instructions
1302
+ // ===========================================================================
1303
+ async createMilestone(args) {
1304
+ return createMilestone(
1305
+ this.program,
1306
+ args,
1307
+ this.walletPublicKey
1308
+ );
1309
+ }
1310
+ async submitMilestone(projectId, milestoneIndex) {
1311
+ return submitMilestone(
1312
+ this.program,
1313
+ projectId,
1314
+ milestoneIndex,
1315
+ this.walletPublicKey
1316
+ );
1317
+ }
1318
+ async voteOnMilestone(args) {
1319
+ return voteOnMilestone(
1320
+ this.program,
1321
+ args,
1322
+ this.walletPublicKey
1323
+ );
1324
+ }
1325
+ async finalizeVoting(projectId, milestoneIndex) {
1326
+ return finalizeVoting(
1327
+ this.program,
1328
+ projectId,
1329
+ milestoneIndex
1330
+ );
1331
+ }
1332
+ /**
1333
+ * Claim milestone funds (ZTM v2.0)
1334
+ * - Regular milestones: Full payout to founder
1335
+ * - Final milestone: LP USDC reserved for PCL, triggers MAE
1336
+ *
1337
+ * @param nextMilestoneDeadline - Deadline for next milestone (required for non-final milestones)
1338
+ * Set to BN(0) for final milestone claims (no next milestone exists)
1339
+ */
1340
+ async claimMilestoneFunds(args) {
1341
+ return claimMilestoneFunds(
1342
+ this.program,
1343
+ args,
1344
+ this.walletPublicKey
1345
+ );
1346
+ }
1347
+ /**
1348
+ * Resubmit a failed milestone for rework (Failed → InProgress)
1349
+ *
1350
+ * Allows founders to iterate on failed milestones. Clears voting state
1351
+ * for a fresh voting cycle. consecutive_failures is NOT reset.
1352
+ */
1353
+ async resubmitMilestone(args) {
1354
+ return resubmitMilestone(
1355
+ this.program,
1356
+ args,
1357
+ this.walletPublicKey
1358
+ );
1359
+ }
1360
+ /**
1361
+ * Set milestone deadline for founder to commit submission date
1362
+ *
1363
+ * Founders must set deadlines for milestones to provide visibility to investors.
1364
+ * Deadline must be at least 7 days from now and at most 1 year from now.
1365
+ */
1366
+ async setMilestoneDeadline(args) {
1367
+ return setMilestoneDeadline(
1368
+ this.program,
1369
+ args,
1370
+ this.walletPublicKey
1371
+ );
1372
+ }
1373
+ /**
1374
+ * Extend milestone deadline (max 3 extensions per milestone)
1375
+ *
1376
+ * Founders can extend a deadline up to 3 times before it passes.
1377
+ * Must be called BEFORE the current deadline passes.
1378
+ */
1379
+ async extendMilestoneDeadline(args) {
1380
+ return extendMilestoneDeadline(
1381
+ this.program,
1382
+ args,
1383
+ this.walletPublicKey
1384
+ );
1385
+ }
1386
+ // ===========================================================================
1387
+ // Investment Instructions
1388
+ // ===========================================================================
1389
+ async invest(args) {
1390
+ return invest(
1391
+ this.program,
1392
+ args,
1393
+ this.walletPublicKey
1394
+ );
1395
+ }
1396
+ async cancelInvestment(args) {
1397
+ return cancelInvestment(
1398
+ this.program,
1399
+ args,
1400
+ this.walletPublicKey
1401
+ );
1402
+ }
1403
+ // ===========================================================================
1404
+ // Pivot Instructions
1405
+ // ===========================================================================
1406
+ async proposePivot(args) {
1407
+ return proposePivot(
1408
+ this.program,
1409
+ args,
1410
+ this.walletPublicKey
1411
+ );
1412
+ }
1413
+ async approvePivot(projectId, adminKeypair) {
1414
+ return approvePivot(
1415
+ this.program,
1416
+ projectId,
1417
+ adminKeypair
1418
+ );
1419
+ }
1420
+ async withdrawFromPivot(args) {
1421
+ return withdrawFromPivot(
1422
+ this.program,
1423
+ args,
1424
+ this.walletPublicKey
1425
+ );
1426
+ }
1427
+ async finalizePivot(args) {
1428
+ return finalizePivot(
1429
+ this.program,
1430
+ args,
1431
+ this.walletPublicKey
1432
+ );
1433
+ }
1434
+ // ===========================================================================
1435
+ // TGE Instructions
1436
+ // ===========================================================================
1437
+ async setTgeDate(args) {
1438
+ return setTgeDate(
1439
+ this.program,
1440
+ args,
1441
+ this.walletPublicKey
1442
+ );
1443
+ }
1444
+ async depositTokens(args) {
1445
+ return depositTokens(
1446
+ this.program,
1447
+ args,
1448
+ this.walletPublicKey
1449
+ );
1450
+ }
1451
+ async claimTokens(args) {
1452
+ return claimTokens(
1453
+ this.program,
1454
+ args,
1455
+ this.walletPublicKey
1456
+ );
1457
+ }
1458
+ async reportScam(args) {
1459
+ return reportScam(
1460
+ this.program,
1461
+ args,
1462
+ this.walletPublicKey
1463
+ );
1464
+ }
1465
+ async releaseHoldback(args) {
1466
+ return releaseHoldback(
1467
+ this.program,
1468
+ args
1469
+ );
1470
+ }
1471
+ // ===========================================================================
1472
+ // ZTM v2.0 Token Distribution Instructions
1473
+ // ===========================================================================
1474
+ /**
1475
+ * Claim investor tokens from a passed milestone (whitepaper: manual claim model)
1476
+ *
1477
+ * ZTM v2.0: Per whitepaper, investors manually claim their tokens after a milestone passes.
1478
+ * This replaces the batch distribution model with investor-initiated per-NFT claims.
1479
+ */
1480
+ async claimInvestorTokens(args) {
1481
+ return claimInvestorTokens(
1482
+ this.program,
1483
+ args,
1484
+ this.walletPublicKey
1485
+ );
1486
+ }
1487
+ /**
1488
+ * Distribute tokens to NFT holders for a milestone
1489
+ *
1490
+ * ZTM v2.0: Called by cranker after finalize_voting sets distribution_pending = true.
1491
+ * Processes batch of investments, transferring unlocked tokens to NFT holders.
1492
+ * Max batch size: 10 investments per call.
1493
+ *
1494
+ * @deprecated Use claimInvestorTokens instead (whitepaper manual claim model)
1495
+ */
1496
+ async distributeTokens(args) {
1497
+ return distributeTokens(
1498
+ this.program,
1499
+ args,
1500
+ this.walletPublicKey
1501
+ );
1502
+ }
1503
+ /**
1504
+ * Complete token distribution for a milestone
1505
+ *
1506
+ * ZTM v2.0: Marks distribution as complete after all batches have been processed.
1507
+ * Permissionless - anyone can call this to finalize a distribution.
1508
+ */
1509
+ async completeDistribution(args) {
1510
+ return completeDistribution(
1511
+ this.program,
1512
+ args,
1513
+ this.walletPublicKey
1514
+ );
1515
+ }
1516
+ // ===========================================================================
1517
+ // ZTM v2.0: Founder Vesting Instructions
1518
+ // ===========================================================================
1519
+ /**
1520
+ * Initialize founder vesting after MAE (Market Access Event)
1521
+ *
1522
+ * ZTM v2.0: Creates FounderVesting PDA with vesting schedule from Tokenomics.
1523
+ * Must be called after project reaches Completed state (all milestones done).
1524
+ * Permissionless - anyone can pay to initialize.
1525
+ */
1526
+ async initializeFounderVesting(args) {
1527
+ return initializeFounderVesting(
1528
+ this.program,
1529
+ args,
1530
+ this.walletPublicKey
1531
+ );
1532
+ }
1533
+ /**
1534
+ * Claim vested tokens from founder vault
1535
+ *
1536
+ * ZTM v2.0: Founder claims tokens based on linear vesting schedule.
1537
+ * Requires cliff period to pass before any tokens can be claimed.
1538
+ */
1539
+ async claimVestedTokens(args) {
1540
+ return claimVestedTokens(
1541
+ this.program,
1542
+ args,
1543
+ this.walletPublicKey
1544
+ );
1545
+ }
1546
+ // ===========================================================================
1547
+ // ZTM v2.0: Circuit Breaker Instructions
1548
+ // ===========================================================================
1549
+ /**
1550
+ * Force complete a stuck distribution (admin only)
1551
+ *
1552
+ * ZTM v2.0: Circuit breaker for when token distribution is stuck for >7 days.
1553
+ * Marks distribution as complete so project can continue.
1554
+ * Affected investors can use claimMissedUnlock to get their tokens.
1555
+ */
1556
+ async forceCompleteDistribution(args, adminKeypair) {
1557
+ return forceCompleteDistribution(
1558
+ this.program,
1559
+ args,
1560
+ adminKeypair
1561
+ );
1562
+ }
1563
+ /**
1564
+ * Claim missed token unlock after force-complete distribution
1565
+ *
1566
+ * ZTM v2.0: Allows investors to claim tokens they missed during a stuck
1567
+ * distribution that was force-completed by admin.
1568
+ */
1569
+ async claimMissedUnlock(args) {
1570
+ return claimMissedUnlock(
1571
+ this.program,
1572
+ args,
1573
+ this.walletPublicKey
1574
+ );
1575
+ }
1576
+ // ===========================================================================
1577
+ // Abandonment Instructions
1578
+ // ===========================================================================
1579
+ async checkAbandonment(projectId, milestoneIndex = 0) {
1580
+ return checkAbandonment(
1581
+ this.program,
1582
+ projectId,
1583
+ milestoneIndex
1584
+ );
1585
+ }
1586
+ async claimRefund(args) {
1587
+ return claimRefund(
1588
+ this.program,
1589
+ args,
1590
+ this.walletPublicKey
1591
+ );
1592
+ }
1593
+ };
1594
+
1595
+ // src/types/index.ts
1596
+ var ProjectState = /* @__PURE__ */ ((ProjectState2) => {
1597
+ ProjectState2["Draft"] = "draft";
1598
+ ProjectState2["PendingApproval"] = "pendingApproval";
1599
+ ProjectState2["Open"] = "open";
1600
+ ProjectState2["Funded"] = "funded";
1601
+ ProjectState2["InProgress"] = "inProgress";
1602
+ ProjectState2["Completed"] = "completed";
1603
+ ProjectState2["Abandoned"] = "abandoned";
1604
+ ProjectState2["Failed"] = "failed";
1605
+ ProjectState2["TGEFailed"] = "tgeFailed";
1606
+ ProjectState2["Cancelled"] = "cancelled";
1607
+ return ProjectState2;
1608
+ })(ProjectState || {});
1609
+ var MilestoneState = /* @__PURE__ */ ((MilestoneState2) => {
1610
+ MilestoneState2["Proposed"] = "proposed";
1611
+ MilestoneState2["Approved"] = "approved";
1612
+ MilestoneState2["InProgress"] = "inProgress";
1613
+ MilestoneState2["UnderReview"] = "underReview";
1614
+ MilestoneState2["Passed"] = "passed";
1615
+ MilestoneState2["Failed"] = "failed";
1616
+ MilestoneState2["Unlocked"] = "unlocked";
1617
+ return MilestoneState2;
1618
+ })(MilestoneState || {});
1619
+ var VoteChoice = /* @__PURE__ */ ((VoteChoice2) => {
1620
+ VoteChoice2["Good"] = "good";
1621
+ VoteChoice2["Bad"] = "bad";
1622
+ return VoteChoice2;
1623
+ })(VoteChoice || {});
1624
+ var PivotState = /* @__PURE__ */ ((PivotState2) => {
1625
+ PivotState2["PendingModeratorApproval"] = "pendingModeratorApproval";
1626
+ PivotState2["ApprovedAwaitingInvestorWindow"] = "approvedAwaitingInvestorWindow";
1627
+ PivotState2["Finalized"] = "finalized";
1628
+ return PivotState2;
1629
+ })(PivotState || {});
1630
+ var ERROR_CODES = {
1631
+ // State Transition Errors (6000-6099)
1632
+ InvalidStateTransition: 6e3,
1633
+ ProjectNotInOpenState: 6001,
1634
+ ProjectNotInProgress: 6002,
1635
+ MilestoneNotUnderReview: 6003,
1636
+ VotingPeriodEnded: 6004,
1637
+ VotingPeriodNotEnded: 6005,
1638
+ MilestoneNotPassed: 6006,
1639
+ MilestoneAlreadyUnlocked: 6007,
1640
+ ProjectAlreadyFunded: 6008,
1641
+ ProjectNotFunded: 6009,
1642
+ // Authorization Errors (6100-6199)
1643
+ UnauthorizedFounder: 6100,
1644
+ UnauthorizedAdmin: 6101,
1645
+ NotInvestor: 6102,
1646
+ AlreadyVoted: 6103,
1647
+ // Investment Errors (6200-6299)
1648
+ InvestmentBelowMinimum: 6200,
1649
+ FundingGoalExceeded: 6201,
1650
+ InvalidTier: 6202,
1651
+ CoolingOffPeriodActive: 6203,
1652
+ CoolingOffPeriodExpired: 6204,
1653
+ // Milestone Errors (6300-6399)
1654
+ InvalidMilestoneIndex: 6300,
1655
+ MilestonePercentageInvalid: 6301,
1656
+ TotalPercentageExceeded: 6302,
1657
+ MilestoneNotInProgress: 6303,
1658
+ MilestoneNotApproved: 6304,
1659
+ // TGE Errors (6400-6499)
1660
+ TgeDateNotSet: 6400,
1661
+ TgeDateAlreadySet: 6401,
1662
+ TgeDateTooSoon: 6402,
1663
+ TgeDateTooLate: 6403,
1664
+ TgeNotReached: 6404,
1665
+ TokensAlreadyClaimed: 6405,
1666
+ InsufficientTokensDeposited: 6406,
1667
+ // Pivot Errors (6500-6599)
1668
+ PivotAlreadyProposed: 6500,
1669
+ NoPivotProposed: 6501,
1670
+ PivotNotApproved: 6502,
1671
+ PivotWindowNotEnded: 6503,
1672
+ PivotWindowEnded: 6504,
1673
+ AlreadyWithdrawnFromPivot: 6505,
1674
+ // Refund Errors (6800-6899)
1675
+ RefundAlreadyClaimed: 6800,
1676
+ RefundNotAvailable: 6801,
1677
+ ProjectNotAbandoned: 6802,
1678
+ // Scam Errors (6900-6999)
1679
+ ScamReportPeriodEnded: 6900,
1680
+ ScamAlreadyReported: 6901,
1681
+ ScamNotConfirmed: 6902,
1682
+ HoldbackAlreadyReleased: 6903,
1683
+ HoldbackPeriodNotEnded: 6904
1684
+ };
1685
+ var ERROR_MESSAGES = {
1686
+ // State Transition Errors
1687
+ [ERROR_CODES.InvalidStateTransition]: "Invalid project state transition",
1688
+ [ERROR_CODES.ProjectNotInOpenState]: "Project must be in Open state to accept investments",
1689
+ [ERROR_CODES.ProjectNotInProgress]: "Project must be InProgress to perform this action",
1690
+ [ERROR_CODES.MilestoneNotUnderReview]: "Milestone must be under review to vote",
1691
+ [ERROR_CODES.VotingPeriodEnded]: "Voting period has ended",
1692
+ [ERROR_CODES.VotingPeriodNotEnded]: "Voting period has not ended yet",
1693
+ [ERROR_CODES.MilestoneNotPassed]: "Milestone did not pass voting",
1694
+ [ERROR_CODES.MilestoneAlreadyUnlocked]: "Milestone funds already unlocked",
1695
+ [ERROR_CODES.ProjectAlreadyFunded]: "Project has already reached funding goal",
1696
+ [ERROR_CODES.ProjectNotFunded]: "Project has not reached funding goal",
1697
+ // Authorization Errors
1698
+ [ERROR_CODES.UnauthorizedFounder]: "Only the project founder can perform this action",
1699
+ [ERROR_CODES.UnauthorizedAdmin]: "Only the admin can perform this action",
1700
+ [ERROR_CODES.NotInvestor]: "You must be an investor to perform this action",
1701
+ [ERROR_CODES.AlreadyVoted]: "You have already voted on this",
1702
+ // Investment Errors
1703
+ [ERROR_CODES.InvestmentBelowMinimum]: "Investment amount below minimum tier requirement",
1704
+ [ERROR_CODES.FundingGoalExceeded]: "Investment would exceed funding goal",
1705
+ [ERROR_CODES.InvalidTier]: "Invalid investment tier",
1706
+ [ERROR_CODES.CoolingOffPeriodActive]: "Investment is within 24-hour cooling-off period",
1707
+ [ERROR_CODES.CoolingOffPeriodExpired]: "Cooling-off period has expired, cannot cancel",
1708
+ // Milestone Errors
1709
+ [ERROR_CODES.InvalidMilestoneIndex]: "Invalid milestone index",
1710
+ [ERROR_CODES.MilestonePercentageInvalid]: "Milestone percentage must be between 1-100",
1711
+ [ERROR_CODES.TotalPercentageExceeded]: "Total milestone percentages exceed 100%",
1712
+ [ERROR_CODES.MilestoneNotInProgress]: "Milestone must be in progress",
1713
+ [ERROR_CODES.MilestoneNotApproved]: "Milestone must be approved first",
1714
+ // TGE Errors
1715
+ [ERROR_CODES.TgeDateNotSet]: "TGE date has not been set",
1716
+ [ERROR_CODES.TgeDateAlreadySet]: "TGE date has already been set",
1717
+ [ERROR_CODES.TgeDateTooSoon]: "TGE date must be at least 15 days in the future",
1718
+ [ERROR_CODES.TgeDateTooLate]: "TGE date must be within 90 days",
1719
+ [ERROR_CODES.TgeNotReached]: "TGE date has not been reached",
1720
+ [ERROR_CODES.TokensAlreadyClaimed]: "Tokens have already been claimed",
1721
+ [ERROR_CODES.InsufficientTokensDeposited]: "Insufficient tokens deposited by founder",
1722
+ // Pivot Errors
1723
+ [ERROR_CODES.PivotAlreadyProposed]: "A pivot is already pending",
1724
+ [ERROR_CODES.NoPivotProposed]: "No pivot has been proposed",
1725
+ [ERROR_CODES.PivotNotApproved]: "Pivot has not been approved by admin",
1726
+ [ERROR_CODES.PivotWindowNotEnded]: "7-day withdrawal window has not ended",
1727
+ [ERROR_CODES.PivotWindowEnded]: "7-day withdrawal window has ended",
1728
+ [ERROR_CODES.AlreadyWithdrawnFromPivot]: "Already withdrawn from this pivot",
1729
+ // Refund Errors
1730
+ [ERROR_CODES.RefundAlreadyClaimed]: "Refund has already been claimed",
1731
+ [ERROR_CODES.RefundNotAvailable]: "Refund is not available",
1732
+ [ERROR_CODES.ProjectNotAbandoned]: "Project has not been abandoned",
1733
+ // Scam Errors
1734
+ [ERROR_CODES.ScamReportPeriodEnded]: "30-day scam report period has ended",
1735
+ [ERROR_CODES.ScamAlreadyReported]: "Already reported this project for scam",
1736
+ [ERROR_CODES.ScamNotConfirmed]: "Scam has not been confirmed",
1737
+ [ERROR_CODES.HoldbackAlreadyReleased]: "Holdback has already been released",
1738
+ [ERROR_CODES.HoldbackPeriodNotEnded]: "30-day holdback period has not ended"
1739
+ };
1740
+ var RaiseError = class _RaiseError extends Error {
1741
+ constructor(code, message, logs) {
1742
+ super(message);
1743
+ this.code = code;
1744
+ this.logs = logs;
1745
+ this.name = "RaiseError";
1746
+ }
1747
+ /**
1748
+ * Create from an Anchor error
1749
+ */
1750
+ static fromAnchorError(error) {
1751
+ const code = error.error.errorCode.number;
1752
+ const message = ERROR_MESSAGES[code] || error.error.errorMessage;
1753
+ return new _RaiseError(code, message, error.logs);
1754
+ }
1755
+ /**
1756
+ * Check if this is a specific error type
1757
+ */
1758
+ is(errorCode) {
1759
+ return this.code === errorCode;
1760
+ }
1761
+ };
1762
+ function parseError(error) {
1763
+ if (error instanceof AnchorError) {
1764
+ return RaiseError.fromAnchorError(error);
1765
+ }
1766
+ if (error instanceof Error) {
1767
+ return error;
1768
+ }
1769
+ return new Error(String(error));
1770
+ }
1771
+ function isRaiseError(error, code) {
1772
+ if (!(error instanceof RaiseError)) {
1773
+ return false;
1774
+ }
1775
+ if (code !== void 0) {
1776
+ return error.code === code;
1777
+ }
1778
+ return true;
1779
+ }
1780
+ function getErrorMessage(error) {
1781
+ if (error instanceof RaiseError) {
1782
+ return error.message;
1783
+ }
1784
+ if (error instanceof AnchorError) {
1785
+ const code = error.error.errorCode.number;
1786
+ return ERROR_MESSAGES[code] || error.error.errorMessage;
1787
+ }
1788
+ if (error instanceof Error) {
1789
+ return error.message;
1790
+ }
1791
+ return "An unknown error occurred";
1792
+ }
1793
+
1794
+ // src/events/index.ts
1795
+ var EVENT_NAMES = {
1796
+ ProjectCreated: "ProjectCreated",
1797
+ ProjectApproved: "ProjectApproved",
1798
+ ProjectFunded: "ProjectFunded",
1799
+ InvestmentMade: "InvestmentMade",
1800
+ InvestmentCancelled: "InvestmentCancelled",
1801
+ MilestoneCreated: "MilestoneCreated",
1802
+ MilestoneSubmitted: "MilestoneSubmitted",
1803
+ VoteCast: "VoteCast",
1804
+ MilestoneVoteFinalized: "MilestoneVoteFinalized",
1805
+ FundsUnlocked: "FundsUnlocked",
1806
+ TgeDateSet: "TgeDateSet",
1807
+ TokensDeposited: "TokensDeposited",
1808
+ TokensClaimed: "TokensClaimed",
1809
+ RefundClaimed: "RefundClaimed",
1810
+ PivotProposed: "PivotProposed",
1811
+ PivotApproved: "PivotApproved",
1812
+ PivotFinalized: "PivotFinalized",
1813
+ MilestoneReworked: "MilestoneReworked"
1814
+ };
1815
+ function filterEventsByName(events, name) {
1816
+ return events.filter((e) => e.name === name);
1817
+ }
1818
+ function findEvent(events, name) {
1819
+ return events.find((e) => e.name === name);
1820
+ }
1821
+ async function confirmTransaction(connection, signature, commitment = "confirmed") {
1822
+ const latestBlockhash = await connection.getLatestBlockhash();
1823
+ return connection.confirmTransaction(
1824
+ {
1825
+ signature,
1826
+ blockhash: latestBlockhash.blockhash,
1827
+ lastValidBlockHeight: latestBlockhash.lastValidBlockHeight
1828
+ },
1829
+ commitment
1830
+ );
1831
+ }
1832
+ async function getTransactionWithRetry(connection, signature, maxRetries = 3) {
1833
+ for (let i = 0; i < maxRetries; i++) {
1834
+ const tx = await connection.getTransaction(signature, {
1835
+ maxSupportedTransactionVersion: 0
1836
+ });
1837
+ if (tx) {
1838
+ return tx;
1839
+ }
1840
+ await new Promise((resolve) => setTimeout(resolve, 1e3 * (i + 1)));
1841
+ }
1842
+ throw new Error(`Transaction ${signature} not found after ${maxRetries} retries`);
1843
+ }
1844
+ function bnToNumber(bn) {
1845
+ const num = bn.toNumber();
1846
+ if (!Number.isSafeInteger(num)) {
1847
+ throw new Error(`BN value ${bn.toString()} is too large to convert to number`);
1848
+ }
1849
+ return num;
1850
+ }
1851
+ function bnToBigInt(bn) {
1852
+ return BigInt(bn.toString());
1853
+ }
1854
+ function bigIntToBN(value) {
1855
+ return new BN(value.toString());
1856
+ }
1857
+ function getCurrentTimestamp() {
1858
+ return Math.floor(Date.now() / 1e3);
1859
+ }
1860
+ function timestampToDate(timestamp) {
1861
+ const ts = typeof timestamp === "number" ? timestamp : timestamp.toNumber();
1862
+ return new Date(ts * 1e3);
1863
+ }
1864
+ function hasTimestampPassed(timestamp) {
1865
+ const ts = typeof timestamp === "number" ? timestamp : timestamp.toNumber();
1866
+ return getCurrentTimestamp() > ts;
1867
+ }
1868
+ function timeRemaining(timestamp) {
1869
+ const ts = typeof timestamp === "number" ? timestamp : timestamp.toNumber();
1870
+ const remaining = ts - getCurrentTimestamp();
1871
+ return remaining > 0 ? remaining : 0;
1872
+ }
1873
+ function formatDuration(seconds) {
1874
+ if (seconds <= 0) return "0s";
1875
+ const days = Math.floor(seconds / 86400);
1876
+ const hours = Math.floor(seconds % 86400 / 3600);
1877
+ const minutes = Math.floor(seconds % 3600 / 60);
1878
+ const secs = seconds % 60;
1879
+ const parts = [];
1880
+ if (days > 0) parts.push(`${days}d`);
1881
+ if (hours > 0) parts.push(`${hours}h`);
1882
+ if (minutes > 0) parts.push(`${minutes}m`);
1883
+ if (secs > 0 && days === 0) parts.push(`${secs}s`);
1884
+ return parts.join(" ") || "0s";
1885
+ }
1886
+ function bpsToPercent(bps) {
1887
+ return bps / 1e4;
1888
+ }
1889
+ function percentToBps(percent) {
1890
+ return Math.floor(percent * 1e4);
1891
+ }
1892
+ function percentageOf(amount, percentage) {
1893
+ return amount * BigInt(Math.floor(percentage * 100)) / 10000n;
1894
+ }
1895
+ function validateMilestonePercentages(percentages) {
1896
+ const sum = percentages.reduce((acc, p) => acc + p, 0);
1897
+ return sum === 100;
1898
+ }
1899
+ function validateMetadataUri(uri, maxLength = 200) {
1900
+ if (uri.length > maxLength) return false;
1901
+ try {
1902
+ new URL(uri);
1903
+ return true;
1904
+ } catch {
1905
+ return false;
1906
+ }
1907
+ }
1908
+ function isValidPublicKey(pubkey) {
1909
+ try {
1910
+ if (typeof pubkey === "string") {
1911
+ new PublicKey(pubkey);
1912
+ }
1913
+ return true;
1914
+ } catch {
1915
+ return false;
1916
+ }
1917
+ }
1918
+ function shortenPublicKey(pubkey, chars = 4) {
1919
+ const str = pubkey.toString();
1920
+ if (str.length <= chars * 2 + 3) return str;
1921
+ return `${str.slice(0, chars)}...${str.slice(-chars)}`;
1922
+ }
1923
+
1924
+ export { ERROR_CODES, ERROR_MESSAGES, EVENT_NAMES, GOVERNANCE, InvestmentTier, MAX_DEADLINE_DURATION_SECONDS, MIN_DEADLINE_DURATION_SECONDS_DEV, MIN_DEADLINE_DURATION_SECONDS_PROD, MilestoneState, NFT, PivotState, ProjectState, RaiseClient, RaiseError, SEEDS, TIER_CONSTRAINTS, TIER_MINIMUMS, TIER_TOKEN_MULTIPLIERS, TIER_VOTE_MULTIPLIERS, TIMING, USDC, VALIDATION, VoteChoice, acceptAdmin, accountExists, approvePivot, approveProject, bigIntToBN, bnToBigInt, bnToNumber, bpsToPercent, calculateDeadline, cancelInvestment, checkAbandonment, claimExitWindowRefund, claimInvestorTokens, claimMilestoneFunds, claimMissedUnlock, claimRefund, claimTokens, claimVestedTokens, completeDistribution, confirmTransaction, createMilestone, depositTokens, distributeTokens, extendMilestoneDeadline, fetchAdminConfig, fetchAllInvestments, fetchAllMilestones, fetchAllVotes, fetchInvestment, fetchMilestone, fetchPivotProposal, fetchProject, fetchProjectByPda, fetchTgeEscrow, fetchVote, filterEventsByName, finalizePivot, finalizeVoting, findEvent, findTierIndex, forceCompleteDistribution, formatDuration, getAdminConfigPDA, getCurrentTimestamp, getErrorMessage, getEscrowPDA, getFounderVaultPDA, getFounderVestingPDA, getInvestmentPDA, getInvestorVaultPDA, getLpTokenVaultPDA, getLpUsdcVaultPDA, getMilestonePDA, getNftMintPDA, getPivotProposalPDA, getProgramAuthorityPDA, getProjectPDA, getProjectPDAs, getScamReportPDA, getTgeEscrowPDA, getTierFromAmount, getTokenMintPDA, getTokenMultiplier, getTokenVaultPDA, getTokenomicsPDA, getTransactionWithRetry, getTreasuryVaultPDA, getVaultAuthorityPDA, getVoteMultiplier, getVotePDA, hasTimestampPassed, initializeAdmin, initializeFounderVesting, initializeProject, invest, isRaiseError, isValidPublicKey, minDeadline, parseError, percentToBps, percentageOf, proposePivot, releaseHoldback, reportScam, resubmitMilestone, setMilestoneDeadline, setTgeDate, shortenPublicKey, submitForApproval, submitMilestone, symbolToBytes, timeRemaining, timestampToDate, transferAdmin, validateDeadline, validateMetadataUri, validateMilestonePercentages, voteOnMilestone, withdrawFromPivot };
1925
+ //# sourceMappingURL=index.js.map
1926
+ //# sourceMappingURL=index.js.map