1+ import { PublicKey } from "@solana/web3.js" ;
2+ import { assert } from "chai" ;
3+ import {
4+ AutocratClient ,
5+ getLaunchAddr ,
6+ LaunchpadClient ,
7+ } from "@metadaoproject/futarchy/v0.4" ;
8+ import { createMint } from "spl-token-bankrun" ;
9+ import { BN } from "bn.js" ;
10+ import { createSetAuthorityInstruction , AuthorityType , getAssociatedTokenAddressSync } from "@solana/spl-token" ;
11+
12+ export default function suite ( ) {
13+ let autocratClient : AutocratClient ;
14+ let launchpadClient : LaunchpadClient ;
15+ let dao : PublicKey ;
16+ let daoTreasury : PublicKey ;
17+ let META : PublicKey ;
18+ let USDC : PublicKey ;
19+ let launch : PublicKey ;
20+ let usdcVault : PublicKey ;
21+ let treasuryUsdcAccount : PublicKey ;
22+
23+ const minRaise = new BN ( 1000_000000 ) ; // 1000 USDC
24+
25+ before ( async function ( ) {
26+ autocratClient = this . autocratClient ;
27+ launchpadClient = this . launchpadClient ;
28+ } ) ;
29+
30+ beforeEach ( async function ( ) {
31+ // Create test tokens
32+ META = await createMint ( this . banksClient , this . payer , this . payer . publicKey , null , 6 ) ;
33+ USDC = await createMint ( this . banksClient , this . payer , this . payer . publicKey , null , 6 ) ;
34+
35+ // Initialize DAO
36+ dao = await autocratClient . initializeDao ( META , 400 , 5 , 5000 , USDC ) ;
37+ [ daoTreasury ] = PublicKey . findProgramAddressSync (
38+ [ dao . toBuffer ( ) ] ,
39+ autocratClient . autocrat . programId
40+ ) ;
41+
42+ // Get accounts
43+ [ launch ] = getLaunchAddr ( launchpadClient . getProgramId ( ) , dao ) ;
44+ usdcVault = getAssociatedTokenAddressSync ( USDC , launch , true ) ;
45+ treasuryUsdcAccount = getAssociatedTokenAddressSync ( USDC , daoTreasury , true ) ;
46+
47+ // Initialize launch
48+ await launchpadClient . initializeLaunchIx (
49+ dao ,
50+ minRaise ,
51+ new BN ( 5000_000000 ) ,
52+ USDC ,
53+ META
54+ ) . preInstructions ( [
55+ createSetAuthorityInstruction (
56+ META ,
57+ this . payer . publicKey ,
58+ AuthorityType . MintTokens ,
59+ launch
60+ )
61+ ] ) . rpc ( ) ;
62+ } ) ;
63+
64+ it ( "completes launch successfully when minimum raise is met" , async function ( ) {
65+ // Fund the launch with exactly minimum raise
66+ const userUsdcAccount = await this . createTokenAccount ( USDC , this . payer . publicKey ) ;
67+ const userTokenAccount = await this . createTokenAccount ( META , this . payer . publicKey ) ;
68+ // await this.mintTo(USDC, userUsdcAccount, this.payer, minRaise.toNumber());
69+ await this . mintTo ( USDC , this . payer . publicKey , this . payer , minRaise . toNumber ( ) ) ;
70+
71+ await launchpadClient . fundIx (
72+ launch ,
73+ minRaise ,
74+ USDC ,
75+ META
76+ ) . rpc ( ) ;
77+
78+ // Complete the launch
79+ await launchpadClient . completeLaunchIx ( launch , USDC , daoTreasury ) . rpc ( ) ;
80+
81+ const launchAccount = await launchpadClient . fetchLaunch ( launch ) ;
82+ const treasuryBalance = await this . getTokenBalance ( USDC , daoTreasury ) ;
83+
84+ assert . exists ( launchAccount . state . complete ) ;
85+ assert . equal ( treasuryBalance . toString ( ) , minRaise . toString ( ) ) ;
86+ } ) ;
87+
88+ it ( "moves to refunding state when minimum raise is not met" , async function ( ) {
89+ // Fund the launch with less than minimum raise
90+ const userUsdcAccount = await this . createTokenAccount ( USDC , this . payer . publicKey ) ;
91+ const userTokenAccount = await this . createTokenAccount ( META , this . payer . publicKey ) ;
92+ const partialAmount = minRaise . divn ( 2 ) ;
93+ await this . mintTo ( USDC , this . payer . publicKey , this . payer , partialAmount . toNumber ( ) ) ;
94+
95+ await launchpadClient . fundIx (
96+ launch ,
97+ partialAmount ,
98+ USDC ,
99+ META
100+ ) . rpc ( ) ;
101+
102+ // Complete the launch
103+ await launchpadClient . completeLaunchIx ( launch , USDC , daoTreasury ) . rpc ( ) ;
104+
105+ const launchAccount = await launchpadClient . fetchLaunch ( launch ) ;
106+ const treasuryBalance = await this . getTokenBalance ( USDC , daoTreasury ) ;
107+
108+ assert . exists ( launchAccount . state . refunding ) ;
109+ assert . equal ( treasuryBalance . toString ( ) , "0" ) ;
110+ } ) ;
111+
112+ it ( "fails when launch is not in live state" , async function ( ) {
113+ // Complete launch first time
114+ await launchpadClient . completeLaunchIx ( launch , USDC , daoTreasury ) . rpc ( ) ;
115+
116+ // Try to complete again
117+ try {
118+ await launchpadClient . completeLaunchIx ( launch , USDC , daoTreasury ) . rpc ( ) ;
119+ assert . fail ( "Should have thrown error" ) ;
120+ } catch ( e ) {
121+ assert . include ( e . message , "InvalidLaunchState" ) ;
122+ }
123+ } ) ;
124+ }
0 commit comments