@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/src/client.ts ADDED
@@ -0,0 +1,715 @@
1
+ /**
2
+ * Raise Client
3
+ *
4
+ * Main client class for interacting with the Raise program.
5
+ * Provides a high-level API that wraps the instruction and account modules.
6
+ */
7
+
8
+ import { Program, AnchorProvider, BN } from '@coral-xyz/anchor';
9
+ import { Connection, PublicKey, Keypair } from '@solana/web3.js';
10
+
11
+ // Import all modules
12
+ import * as pdas from './pdas/index.js';
13
+ import * as accounts from './accounts/index.js';
14
+ import * as instructions from './instructions/index.js';
15
+ import type { TierConfig } from './types/index.js';
16
+
17
+ /**
18
+ * Wallet interface required by the client
19
+ */
20
+ export interface Wallet {
21
+ publicKey: PublicKey;
22
+ signTransaction: <T>(tx: T) => Promise<T>;
23
+ signAllTransactions: <T>(txs: T[]) => Promise<T[]>;
24
+ }
25
+
26
+ /**
27
+ * Main client for interacting with the Raise program
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * import { RaiseClient } from '@raise/sdk';
32
+ *
33
+ * const client = RaiseClient.load(connection, wallet);
34
+ *
35
+ * // Create a project
36
+ * const tx = await client.initializeProject({
37
+ * projectId: new BN(1),
38
+ * fundingGoal: new BN(100000000000), // 100,000 USDC
39
+ * metadataUri: 'https://example.com/project.json',
40
+ * });
41
+ *
42
+ * // Fetch project data
43
+ * const project = await client.fetchProject(new BN(1));
44
+ * ```
45
+ */
46
+ export class RaiseClient {
47
+ /**
48
+ * Create a new RaiseClient
49
+ *
50
+ * @param program - Anchor program instance
51
+ * @param provider - Anchor provider
52
+ */
53
+ constructor(
54
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
55
+ public readonly program: Program<any>,
56
+ public readonly provider: AnchorProvider
57
+ ) {}
58
+
59
+ /**
60
+ * Load a new RaiseClient instance
61
+ *
62
+ * @param connection - Solana connection
63
+ * @param wallet - Wallet instance
64
+ * @param programId - Optional program ID override
65
+ * @returns Initialized RaiseClient
66
+ *
67
+ * @example
68
+ * ```typescript
69
+ * const client = RaiseClient.load(connection, wallet);
70
+ * ```
71
+ */
72
+ static load(
73
+ _connection: Connection,
74
+ _wallet: Wallet,
75
+ _programId?: PublicKey
76
+ ): RaiseClient {
77
+ // Note: In production, you would import the IDL from a generated file
78
+ // For now, we'll need the IDL to be provided or loaded separately
79
+ // This is a placeholder that assumes IDL is available
80
+ throw new Error(
81
+ 'RaiseClient.load requires IDL. Use RaiseClient.fromProgram instead, ' +
82
+ 'or ensure the IDL is bundled with your application.'
83
+ );
84
+ }
85
+
86
+ /**
87
+ * Create client from an existing program instance
88
+ *
89
+ * @param program - Anchor program instance
90
+ * @returns Initialized RaiseClient
91
+ *
92
+ * @example
93
+ * ```typescript
94
+ * import idl from './idl/raise.json';
95
+ *
96
+ * const provider = new AnchorProvider(connection, wallet, {});
97
+ * const program = new Program(idl, provider);
98
+ * const client = RaiseClient.fromProgram(program);
99
+ * ```
100
+ */
101
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
102
+ static fromProgram(program: Program<any>): RaiseClient {
103
+ const provider = program.provider as AnchorProvider;
104
+ return new RaiseClient(program, provider);
105
+ }
106
+
107
+ /**
108
+ * Get the program ID
109
+ */
110
+ get programId(): PublicKey {
111
+ return this.program.programId;
112
+ }
113
+
114
+ /**
115
+ * Get the connected wallet public key
116
+ */
117
+ get walletPublicKey(): PublicKey {
118
+ return this.provider.wallet.publicKey;
119
+ }
120
+
121
+ // ===========================================================================
122
+ // PDA Helpers
123
+ // ===========================================================================
124
+
125
+ getProjectPDA(projectId: BN): PublicKey {
126
+ return pdas.getProjectPDA(projectId, this.programId);
127
+ }
128
+
129
+ getEscrowPDA(projectId: BN): PublicKey {
130
+ return pdas.getEscrowPDA(projectId, this.programId);
131
+ }
132
+
133
+ getMilestonePDA(projectPda: PublicKey, milestoneIndex: number): PublicKey {
134
+ return pdas.getMilestonePDA(projectPda, milestoneIndex, this.programId);
135
+ }
136
+
137
+ getInvestmentPDA(projectPda: PublicKey, nftMint: PublicKey): PublicKey {
138
+ return pdas.getInvestmentPDA(projectPda, nftMint, this.programId);
139
+ }
140
+
141
+ getVotePDA(milestonePda: PublicKey, voterKey: PublicKey, votingRound: number): PublicKey {
142
+ return pdas.getVotePDA(milestonePda, voterKey, votingRound, this.programId);
143
+ }
144
+
145
+ getPivotProposalPDA(projectPda: PublicKey, pivotCount: number): PublicKey {
146
+ return pdas.getPivotProposalPDA(projectPda, pivotCount, this.programId);
147
+ }
148
+
149
+ getTgeEscrowPDA(projectPda: PublicKey): PublicKey {
150
+ return pdas.getTgeEscrowPDA(projectPda, this.programId);
151
+ }
152
+
153
+ getTgeEscrowVaultPDA(projectPda: PublicKey): PublicKey {
154
+ return pdas.getTgeEscrowVaultPDA(projectPda, this.programId);
155
+ }
156
+
157
+ getAdminConfigPDA(): PublicKey {
158
+ return pdas.getAdminConfigPDA(this.programId);
159
+ }
160
+
161
+ // ===========================================================================
162
+ // Account Fetchers
163
+ // ===========================================================================
164
+
165
+ async fetchProject(projectId: BN) {
166
+ return accounts.fetchProject(this.program, projectId);
167
+ }
168
+
169
+ async fetchMilestone(projectId: BN, milestoneIndex: number) {
170
+ return accounts.fetchMilestone(this.program, projectId, milestoneIndex);
171
+ }
172
+
173
+ async fetchAllMilestones(projectId: BN) {
174
+ return accounts.fetchAllMilestones(this.program, projectId);
175
+ }
176
+
177
+ async fetchInvestment(projectId: BN, nftMint: PublicKey) {
178
+ return accounts.fetchInvestment(this.program, projectId, nftMint);
179
+ }
180
+
181
+ async fetchAllInvestments(projectId: BN) {
182
+ return accounts.fetchAllInvestments(this.program, projectId);
183
+ }
184
+
185
+ async fetchVote(projectId: BN, milestoneIndex: number, voterKey: PublicKey, votingRound: number) {
186
+ return accounts.fetchVote(this.program, projectId, milestoneIndex, voterKey, votingRound);
187
+ }
188
+
189
+ async fetchAllVotes(projectId: BN, milestoneIndex: number) {
190
+ return accounts.fetchAllVotes(this.program, projectId, milestoneIndex);
191
+ }
192
+
193
+ async fetchPivotProposal(projectId: BN) {
194
+ return accounts.fetchPivotProposal(this.program, projectId);
195
+ }
196
+
197
+ async fetchTgeEscrow(projectId: BN) {
198
+ return accounts.fetchTgeEscrow(this.program, projectId);
199
+ }
200
+
201
+ async fetchAdminConfig() {
202
+ return accounts.fetchAdminConfig(this.program);
203
+ }
204
+
205
+ // ===========================================================================
206
+ // Admin Instructions
207
+ // ===========================================================================
208
+
209
+ async initializeAdmin(admin: PublicKey): Promise<string> {
210
+ return instructions.initializeAdmin(
211
+ this.program,
212
+ admin,
213
+ this.walletPublicKey
214
+ );
215
+ }
216
+
217
+ async transferAdmin(newAdmin: PublicKey, adminKeypair: Keypair): Promise<string> {
218
+ return instructions.transferAdmin(
219
+ this.program,
220
+ adminKeypair,
221
+ newAdmin
222
+ );
223
+ }
224
+
225
+ async acceptAdmin(): Promise<string> {
226
+ return instructions.acceptAdmin(
227
+ this.program,
228
+ this.walletPublicKey
229
+ );
230
+ }
231
+
232
+ // ===========================================================================
233
+ // Project Instructions
234
+ // ===========================================================================
235
+
236
+ async initializeProject(args: {
237
+ projectId: BN;
238
+ fundingGoal: BN;
239
+ metadataUri: string;
240
+ tiers: TierConfig[];
241
+ /** ZTM v2.0: Tokenomics configuration */
242
+ tokenomics: instructions.TokenomicsInput;
243
+ /** Milestone 1 deadline - Unix timestamp (required) */
244
+ milestone1Deadline: BN;
245
+ }): Promise<string> {
246
+ return instructions.initializeProject(
247
+ this.program,
248
+ args,
249
+ this.walletPublicKey
250
+ );
251
+ }
252
+
253
+ async submitForApproval(projectId: BN): Promise<string> {
254
+ return instructions.submitForApproval(
255
+ this.program,
256
+ projectId,
257
+ this.walletPublicKey
258
+ );
259
+ }
260
+
261
+ async approveProject(
262
+ args: { projectId: BN; usdcMint: PublicKey },
263
+ adminKeypair: Keypair
264
+ ): Promise<string> {
265
+ return instructions.approveProject(
266
+ this.program,
267
+ args,
268
+ adminKeypair
269
+ );
270
+ }
271
+
272
+ // ===========================================================================
273
+ // Milestone Instructions
274
+ // ===========================================================================
275
+
276
+ async createMilestone(args: {
277
+ projectId: BN;
278
+ milestoneIndex: number;
279
+ percentage: number;
280
+ description: string;
281
+ }): Promise<string> {
282
+ return instructions.createMilestone(
283
+ this.program,
284
+ args,
285
+ this.walletPublicKey
286
+ );
287
+ }
288
+
289
+ async submitMilestone(projectId: BN, milestoneIndex: number): Promise<string> {
290
+ return instructions.submitMilestone(
291
+ this.program,
292
+ projectId,
293
+ milestoneIndex,
294
+ this.walletPublicKey
295
+ );
296
+ }
297
+
298
+ async voteOnMilestone(args: {
299
+ projectId: BN;
300
+ milestoneIndex: number;
301
+ nftMint: PublicKey | string;
302
+ choice: { good: object } | { bad: object };
303
+ }): Promise<string> {
304
+ return instructions.voteOnMilestone(
305
+ this.program,
306
+ args,
307
+ this.walletPublicKey
308
+ );
309
+ }
310
+
311
+ async finalizeVoting(projectId: BN, milestoneIndex: number): Promise<string> {
312
+ return instructions.finalizeVoting(
313
+ this.program,
314
+ projectId,
315
+ milestoneIndex
316
+ );
317
+ }
318
+
319
+ /**
320
+ * Claim milestone funds (ZTM v2.0)
321
+ * - Regular milestones: Full payout to founder
322
+ * - Final milestone: LP USDC reserved for PCL, triggers MAE
323
+ *
324
+ * @param nextMilestoneDeadline - Deadline for next milestone (required for non-final milestones)
325
+ * Set to BN(0) for final milestone claims (no next milestone exists)
326
+ */
327
+ async claimMilestoneFunds(args: {
328
+ projectId: BN;
329
+ milestoneIndex: number;
330
+ founderUsdcAccount: PublicKey;
331
+ escrowTokenAccount: PublicKey;
332
+ /** Deadline for next milestone - required for non-final milestones, use BN(0) for final */
333
+ nextMilestoneDeadline: BN;
334
+ /** Next milestone PDA - optional, auto-derived if not provided */
335
+ nextMilestonePda?: PublicKey;
336
+ }): Promise<string> {
337
+ return instructions.claimMilestoneFunds(
338
+ this.program,
339
+ args,
340
+ this.walletPublicKey
341
+ );
342
+ }
343
+
344
+ /**
345
+ * Resubmit a failed milestone for rework (Failed → InProgress)
346
+ *
347
+ * Allows founders to iterate on failed milestones. Clears voting state
348
+ * for a fresh voting cycle. consecutive_failures is NOT reset.
349
+ */
350
+ async resubmitMilestone(args: {
351
+ projectId: BN;
352
+ milestoneIndex: number;
353
+ }): Promise<string> {
354
+ return instructions.resubmitMilestone(
355
+ this.program,
356
+ args,
357
+ this.walletPublicKey
358
+ );
359
+ }
360
+
361
+ /**
362
+ * Set milestone deadline for founder to commit submission date
363
+ *
364
+ * Founders must set deadlines for milestones to provide visibility to investors.
365
+ * Deadline must be at least 7 days from now and at most 1 year from now.
366
+ */
367
+ async setMilestoneDeadline(args: {
368
+ projectId: BN;
369
+ milestoneIndex: number;
370
+ /** Unix timestamp for the deadline */
371
+ deadline: BN;
372
+ }): Promise<string> {
373
+ return instructions.setMilestoneDeadline(
374
+ this.program,
375
+ args,
376
+ this.walletPublicKey
377
+ );
378
+ }
379
+
380
+ /**
381
+ * Extend milestone deadline (max 3 extensions per milestone)
382
+ *
383
+ * Founders can extend a deadline up to 3 times before it passes.
384
+ * Must be called BEFORE the current deadline passes.
385
+ */
386
+ async extendMilestoneDeadline(args: {
387
+ projectId: BN;
388
+ milestoneIndex: number;
389
+ /** New deadline timestamp (must be > current deadline) */
390
+ newDeadline: BN;
391
+ }): Promise<string> {
392
+ return instructions.extendMilestoneDeadline(
393
+ this.program,
394
+ args,
395
+ this.walletPublicKey
396
+ );
397
+ }
398
+
399
+ // ===========================================================================
400
+ // Investment Instructions
401
+ // ===========================================================================
402
+
403
+ async invest(args: {
404
+ projectId: BN;
405
+ amount: BN;
406
+ investorTokenAccount: PublicKey;
407
+ escrowTokenAccount: PublicKey;
408
+ investmentCount: number; // Must be fetched from project.investmentCount
409
+ }): Promise<string> {
410
+ return instructions.invest(
411
+ this.program,
412
+ args,
413
+ this.walletPublicKey
414
+ );
415
+ }
416
+
417
+ async cancelInvestment(args: {
418
+ projectId: BN;
419
+ nftMint: PublicKey;
420
+ investorNftAccount: PublicKey;
421
+ investorUsdcAccount: PublicKey;
422
+ escrowTokenAccount: PublicKey;
423
+ }): Promise<string> {
424
+ return instructions.cancelInvestment(
425
+ this.program,
426
+ args,
427
+ this.walletPublicKey
428
+ );
429
+ }
430
+
431
+ // ===========================================================================
432
+ // Pivot Instructions
433
+ // ===========================================================================
434
+
435
+ async proposePivot(args: {
436
+ projectId: BN;
437
+ newMetadataUri: string;
438
+ newMilestones: Array<{ percentage: number; description: string }>;
439
+ }): Promise<string> {
440
+ return instructions.proposePivot(
441
+ this.program,
442
+ args,
443
+ this.walletPublicKey
444
+ );
445
+ }
446
+
447
+ async approvePivot(projectId: BN, adminKeypair: Keypair): Promise<string> {
448
+ return instructions.approvePivot(
449
+ this.program,
450
+ projectId,
451
+ adminKeypair
452
+ );
453
+ }
454
+
455
+ async withdrawFromPivot(args: {
456
+ projectId: BN;
457
+ pivotCount: number;
458
+ nftMint: PublicKey;
459
+ investorTokenAccount: PublicKey;
460
+ escrowTokenAccount: PublicKey;
461
+ milestoneAccounts: PublicKey[]; // All milestone PDAs for calculating unreleased funds
462
+ }): Promise<string> {
463
+ return instructions.withdrawFromPivot(
464
+ this.program,
465
+ args,
466
+ this.walletPublicKey
467
+ );
468
+ }
469
+
470
+ async finalizePivot(args: {
471
+ projectId: BN;
472
+ pivotCount: number;
473
+ milestoneAccounts: PublicKey[]; // All milestone PDAs (reused when old_count == new_count)
474
+ }): Promise<string> {
475
+ return instructions.finalizePivot(
476
+ this.program,
477
+ args,
478
+ this.walletPublicKey
479
+ );
480
+ }
481
+
482
+ // ===========================================================================
483
+ // TGE Instructions
484
+ // ===========================================================================
485
+
486
+ async setTgeDate(args: {
487
+ projectId: BN;
488
+ tgeDate: BN;
489
+ tokenMint: PublicKey;
490
+ }): Promise<string> {
491
+ return instructions.setTgeDate(
492
+ this.program,
493
+ args,
494
+ this.walletPublicKey
495
+ );
496
+ }
497
+
498
+ async depositTokens(args: {
499
+ projectId: BN;
500
+ amount: BN;
501
+ tokenMint: PublicKey;
502
+ founderTokenAccount: PublicKey;
503
+ }): Promise<string> {
504
+ return instructions.depositTokens(
505
+ this.program,
506
+ args,
507
+ this.walletPublicKey
508
+ );
509
+ }
510
+
511
+ async claimTokens(args: {
512
+ projectId: BN;
513
+ nftMint: PublicKey;
514
+ investorNftAccount: PublicKey;
515
+ investorTokenAccount: PublicKey;
516
+ projectTokenVault: PublicKey;
517
+ }): Promise<string> {
518
+ return instructions.claimTokens(
519
+ this.program,
520
+ args,
521
+ this.walletPublicKey
522
+ );
523
+ }
524
+
525
+ async reportScam(args: {
526
+ projectId: BN;
527
+ nftMint: PublicKey;
528
+ }): Promise<string> {
529
+ return instructions.reportScam(
530
+ this.program,
531
+ args,
532
+ this.walletPublicKey
533
+ );
534
+ }
535
+
536
+ async releaseHoldback(args: {
537
+ projectId: BN;
538
+ founderTokenAccount: PublicKey;
539
+ }): Promise<string> {
540
+ return instructions.releaseHoldback(
541
+ this.program,
542
+ args
543
+ );
544
+ }
545
+
546
+ // ===========================================================================
547
+ // ZTM v2.0 Token Distribution Instructions
548
+ // ===========================================================================
549
+
550
+ /**
551
+ * Claim investor tokens from a passed milestone (whitepaper: manual claim model)
552
+ *
553
+ * ZTM v2.0: Per whitepaper, investors manually claim their tokens after a milestone passes.
554
+ * This replaces the batch distribution model with investor-initiated per-NFT claims.
555
+ */
556
+ async claimInvestorTokens(args: {
557
+ projectId: BN;
558
+ milestoneIndex: number;
559
+ nftMint: PublicKey;
560
+ investorTokenAccount: PublicKey;
561
+ }): Promise<string> {
562
+ return instructions.claimInvestorTokens(
563
+ this.program,
564
+ args,
565
+ this.walletPublicKey
566
+ );
567
+ }
568
+
569
+ /**
570
+ * Distribute tokens to NFT holders for a milestone
571
+ *
572
+ * ZTM v2.0: Called by cranker after finalize_voting sets distribution_pending = true.
573
+ * Processes batch of investments, transferring unlocked tokens to NFT holders.
574
+ * Max batch size: 10 investments per call.
575
+ *
576
+ * @deprecated Use claimInvestorTokens instead (whitepaper manual claim model)
577
+ */
578
+ async distributeTokens(args: {
579
+ projectId: BN;
580
+ milestoneIndex: number;
581
+ investments: Array<{
582
+ investmentPda: PublicKey;
583
+ investorTokenAccount: PublicKey;
584
+ }>;
585
+ }): Promise<string> {
586
+ return instructions.distributeTokens(
587
+ this.program,
588
+ args,
589
+ this.walletPublicKey
590
+ );
591
+ }
592
+
593
+ /**
594
+ * Complete token distribution for a milestone
595
+ *
596
+ * ZTM v2.0: Marks distribution as complete after all batches have been processed.
597
+ * Permissionless - anyone can call this to finalize a distribution.
598
+ */
599
+ async completeDistribution(args: {
600
+ projectId: BN;
601
+ milestoneIndex: number;
602
+ }): Promise<string> {
603
+ return instructions.completeDistribution(
604
+ this.program,
605
+ args,
606
+ this.walletPublicKey
607
+ );
608
+ }
609
+
610
+ // ===========================================================================
611
+ // ZTM v2.0: Founder Vesting Instructions
612
+ // ===========================================================================
613
+
614
+ /**
615
+ * Initialize founder vesting after MAE (Market Access Event)
616
+ *
617
+ * ZTM v2.0: Creates FounderVesting PDA with vesting schedule from Tokenomics.
618
+ * Must be called after project reaches Completed state (all milestones done).
619
+ * Permissionless - anyone can pay to initialize.
620
+ */
621
+ async initializeFounderVesting(args: {
622
+ projectId: BN;
623
+ }): Promise<string> {
624
+ return instructions.initializeFounderVesting(
625
+ this.program,
626
+ args,
627
+ this.walletPublicKey
628
+ );
629
+ }
630
+
631
+ /**
632
+ * Claim vested tokens from founder vault
633
+ *
634
+ * ZTM v2.0: Founder claims tokens based on linear vesting schedule.
635
+ * Requires cliff period to pass before any tokens can be claimed.
636
+ */
637
+ async claimVestedTokens(args: {
638
+ projectId: BN;
639
+ founderTokenAccount: PublicKey;
640
+ }): Promise<string> {
641
+ return instructions.claimVestedTokens(
642
+ this.program,
643
+ args,
644
+ this.walletPublicKey
645
+ );
646
+ }
647
+
648
+ // ===========================================================================
649
+ // ZTM v2.0: Circuit Breaker Instructions
650
+ // ===========================================================================
651
+
652
+ /**
653
+ * Force complete a stuck distribution (admin only)
654
+ *
655
+ * ZTM v2.0: Circuit breaker for when token distribution is stuck for >7 days.
656
+ * Marks distribution as complete so project can continue.
657
+ * Affected investors can use claimMissedUnlock to get their tokens.
658
+ */
659
+ async forceCompleteDistribution(
660
+ args: { projectId: BN },
661
+ adminKeypair: Keypair
662
+ ): Promise<string> {
663
+ return instructions.forceCompleteDistribution(
664
+ this.program,
665
+ args,
666
+ adminKeypair
667
+ );
668
+ }
669
+
670
+ /**
671
+ * Claim missed token unlock after force-complete distribution
672
+ *
673
+ * ZTM v2.0: Allows investors to claim tokens they missed during a stuck
674
+ * distribution that was force-completed by admin.
675
+ */
676
+ async claimMissedUnlock(args: {
677
+ projectId: BN;
678
+ nftMint: PublicKey;
679
+ milestoneIndex: number;
680
+ claimerTokenAccount: PublicKey;
681
+ }): Promise<string> {
682
+ return instructions.claimMissedUnlock(
683
+ this.program,
684
+ args,
685
+ this.walletPublicKey
686
+ );
687
+ }
688
+
689
+ // ===========================================================================
690
+ // Abandonment Instructions
691
+ // ===========================================================================
692
+
693
+ async checkAbandonment(projectId: BN, milestoneIndex: number = 0): Promise<string> {
694
+ return instructions.checkAbandonment(
695
+ this.program,
696
+ projectId,
697
+ milestoneIndex
698
+ );
699
+ }
700
+
701
+ async claimRefund(args: {
702
+ projectId: BN;
703
+ nftMint: PublicKey;
704
+ investorNftAccount: PublicKey;
705
+ investorUsdcAccount: PublicKey;
706
+ escrowTokenAccount: PublicKey;
707
+ milestoneCount?: number;
708
+ }): Promise<string> {
709
+ return instructions.claimRefund(
710
+ this.program,
711
+ args,
712
+ this.walletPublicKey
713
+ );
714
+ }
715
+ }