123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334 |
- const anchor = require("@project-serum/anchor");
- const assert = require("assert");
- const {
- TOKEN_PROGRAM_ID,
- sleep,
- getTokenAccount,
- createMint,
- createTokenAccount,
- mintToAccount,
- } = require("./utils");
- describe("ido-pool", () => {
- const provider = anchor.Provider.local();
- // Configure the client to use the local cluster.
- anchor.setProvider(provider);
- const program = anchor.workspace.IdoPool;
- // All mints default to 6 decimal places.
- const watermelonIdoAmount = new anchor.BN(5000000);
- // These are all of the variables we assume exist in the world already and
- // are available to the client.
- let usdcMint = null;
- let watermelonMint = null;
- let creatorUsdc = null;
- let creatorWatermelon = null;
- it("Initializes the state-of-the-world", async () => {
- usdcMint = await createMint(provider);
- watermelonMint = await createMint(provider);
- creatorUsdc = await createTokenAccount(
- provider,
- usdcMint,
- provider.wallet.publicKey
- );
- creatorWatermelon = await createTokenAccount(
- provider,
- watermelonMint,
- provider.wallet.publicKey
- );
- // Mint Watermelon tokens the will be distributed from the IDO pool.
- await mintToAccount(
- provider,
- watermelonMint,
- creatorWatermelon,
- watermelonIdoAmount,
- provider.wallet.publicKey
- );
- creator_watermelon_account = await getTokenAccount(
- provider,
- creatorWatermelon
- );
- assert.ok(creator_watermelon_account.amount.eq(watermelonIdoAmount));
- });
- // These are all variables the client will have to create to initialize the
- // IDO pool
- let poolSigner = null;
- let redeemableMint = null;
- let poolWatermelon = null;
- let poolUsdc = null;
- let poolAccount = null;
- let startIdoTs = null;
- let endDepositsTs = null;
- let endIdoTs = null;
- it("Initializes the IDO pool", async () => {
- // We use the watermelon mint address as the seed, could use something else though.
- const [_poolSigner, nonce] = await anchor.web3.PublicKey.findProgramAddress(
- [watermelonMint.toBuffer()],
- program.programId
- );
- poolSigner = _poolSigner;
- // Pool doesn't need a Redeemable SPL token account because it only
- // burns and mints redeemable tokens, it never stores them.
- redeemableMint = await createMint(provider, poolSigner);
- poolWatermelon = await createTokenAccount(
- provider,
- watermelonMint,
- poolSigner
- );
- poolUsdc = await createTokenAccount(provider, usdcMint, poolSigner);
- poolAccount = new anchor.web3.Account();
- const nowBn = new anchor.BN(Date.now() / 1000);
- startIdoTs = nowBn.add(new anchor.BN(5));
- endDepositsTs = nowBn.add(new anchor.BN(10));
- endIdoTs = nowBn.add(new anchor.BN(15));
- // Atomically create the new account and initialize it with the program.
- await program.rpc.initializePool(
- watermelonIdoAmount,
- nonce,
- startIdoTs,
- endDepositsTs,
- endIdoTs,
- {
- accounts: {
- poolAccount: poolAccount.publicKey,
- poolSigner,
- distributionAuthority: provider.wallet.publicKey,
- creatorWatermelon,
- redeemableMint,
- usdcMint,
- poolWatermelon,
- poolUsdc,
- tokenProgram: TOKEN_PROGRAM_ID,
- rent: anchor.web3.SYSVAR_RENT_PUBKEY,
- clock: anchor.web3.SYSVAR_CLOCK_PUBKEY,
- },
- signers: [poolAccount],
- instructions: [
- await program.account.poolAccount.createInstruction(poolAccount),
- ],
- }
- );
- creators_watermelon_account = await getTokenAccount(
- provider,
- creatorWatermelon
- );
- assert.ok(creators_watermelon_account.amount.eq(new anchor.BN(0)));
- });
- // We're going to need to start using the associated program account for creating token accounts
- // if not in testing, then definitely in production.
- let userUsdc = null;
- let userRedeemable = null;
- // 10 usdc
- const firstDeposit = new anchor.BN(10_000_349);
- it("Exchanges user USDC for redeemable tokens", async () => {
- // Wait until the IDO has opened.
- if (Date.now() < startIdoTs.toNumber() * 1000) {
- await sleep(startIdoTs.toNumber() * 1000 - Date.now() + 1000);
- }
- userUsdc = await createTokenAccount(
- provider,
- usdcMint,
- provider.wallet.publicKey
- );
- await mintToAccount(
- provider,
- usdcMint,
- userUsdc,
- firstDeposit,
- provider.wallet.publicKey
- );
- userRedeemable = await createTokenAccount(
- provider,
- redeemableMint,
- provider.wallet.publicKey
- );
- try {
- const tx = await program.rpc.exchangeUsdcForRedeemable(firstDeposit, {
- accounts: {
- poolAccount: poolAccount.publicKey,
- poolSigner,
- redeemableMint,
- poolUsdc,
- userAuthority: provider.wallet.publicKey,
- userUsdc,
- userRedeemable,
- tokenProgram: TOKEN_PROGRAM_ID,
- clock: anchor.web3.SYSVAR_CLOCK_PUBKEY,
- },
- });
- } catch (err) {
- console.log("This is the error message", err.toString());
- }
- poolUsdcAccount = await getTokenAccount(provider, poolUsdc);
- assert.ok(poolUsdcAccount.amount.eq(firstDeposit));
- userRedeemableAccount = await getTokenAccount(provider, userRedeemable);
- assert.ok(userRedeemableAccount.amount.eq(firstDeposit));
- });
- // 23 usdc
- const secondDeposit = new anchor.BN(23_000_672);
- let totalPoolUsdc = null;
- it("Exchanges a second users USDC for redeemable tokens", async () => {
- secondUserUsdc = await createTokenAccount(
- provider,
- usdcMint,
- provider.wallet.publicKey
- );
- await mintToAccount(
- provider,
- usdcMint,
- secondUserUsdc,
- secondDeposit,
- provider.wallet.publicKey
- );
- secondUserRedeemable = await createTokenAccount(
- provider,
- redeemableMint,
- provider.wallet.publicKey
- );
- await program.rpc.exchangeUsdcForRedeemable(secondDeposit, {
- accounts: {
- poolAccount: poolAccount.publicKey,
- poolSigner,
- redeemableMint,
- poolUsdc,
- userAuthority: provider.wallet.publicKey,
- userUsdc: secondUserUsdc,
- userRedeemable: secondUserRedeemable,
- tokenProgram: TOKEN_PROGRAM_ID,
- clock: anchor.web3.SYSVAR_CLOCK_PUBKEY,
- },
- });
- totalPoolUsdc = firstDeposit.add(secondDeposit);
- poolUsdcAccount = await getTokenAccount(provider, poolUsdc);
- assert.ok(poolUsdcAccount.amount.eq(totalPoolUsdc));
- secondUserRedeemableAccount = await getTokenAccount(
- provider,
- secondUserRedeemable
- );
- assert.ok(secondUserRedeemableAccount.amount.eq(secondDeposit));
- });
- const firstWithdrawal = new anchor.BN(2_000_000);
- it("Exchanges user Redeemable tokens for USDC", async () => {
- await program.rpc.exchangeRedeemableForUsdc(firstWithdrawal, {
- accounts: {
- poolAccount: poolAccount.publicKey,
- poolSigner,
- redeemableMint,
- poolUsdc,
- userAuthority: provider.wallet.publicKey,
- userUsdc,
- userRedeemable,
- tokenProgram: TOKEN_PROGRAM_ID,
- clock: anchor.web3.SYSVAR_CLOCK_PUBKEY,
- },
- });
- totalPoolUsdc = totalPoolUsdc.sub(firstWithdrawal);
- poolUsdcAccount = await getTokenAccount(provider, poolUsdc);
- assert.ok(poolUsdcAccount.amount.eq(totalPoolUsdc));
- userUsdcAccount = await getTokenAccount(provider, userUsdc);
- assert.ok(userUsdcAccount.amount.eq(firstWithdrawal));
- });
- it("Exchanges user Redeemable tokens for watermelon", async () => {
- // Wait until the IDO has opened.
- if (Date.now() < endIdoTs.toNumber() * 1000) {
- await sleep(endIdoTs.toNumber() * 1000 - Date.now() + 2000);
- }
- let firstUserRedeemable = firstDeposit.sub(firstWithdrawal);
- userWatermelon = await createTokenAccount(
- provider,
- watermelonMint,
- provider.wallet.publicKey
- );
- await program.rpc.exchangeRedeemableForWatermelon(firstUserRedeemable, {
- accounts: {
- poolAccount: poolAccount.publicKey,
- poolSigner,
- redeemableMint,
- poolWatermelon,
- userAuthority: provider.wallet.publicKey,
- userWatermelon,
- userRedeemable,
- tokenProgram: TOKEN_PROGRAM_ID,
- clock: anchor.web3.SYSVAR_CLOCK_PUBKEY,
- },
- });
- poolWatermelonAccount = await getTokenAccount(provider, poolWatermelon);
- let redeemedWatermelon = firstUserRedeemable
- .mul(watermelonIdoAmount)
- .div(totalPoolUsdc);
- let remainingWatermelon = watermelonIdoAmount.sub(redeemedWatermelon);
- assert.ok(poolWatermelonAccount.amount.eq(remainingWatermelon));
- userWatermelonAccount = await getTokenAccount(provider, userWatermelon);
- assert.ok(userWatermelonAccount.amount.eq(redeemedWatermelon));
- });
- it("Exchanges second users Redeemable tokens for watermelon", async () => {
- secondUserWatermelon = await createTokenAccount(
- provider,
- watermelonMint,
- provider.wallet.publicKey
- );
- await program.rpc.exchangeRedeemableForWatermelon(secondDeposit, {
- accounts: {
- poolAccount: poolAccount.publicKey,
- poolSigner,
- redeemableMint,
- poolWatermelon,
- userAuthority: provider.wallet.publicKey,
- userWatermelon: secondUserWatermelon,
- userRedeemable: secondUserRedeemable,
- tokenProgram: TOKEN_PROGRAM_ID,
- clock: anchor.web3.SYSVAR_CLOCK_PUBKEY,
- },
- });
- poolWatermelonAccount = await getTokenAccount(provider, poolWatermelon);
- assert.ok(poolWatermelonAccount.amount.eq(new anchor.BN(0)));
- });
- it("Withdraws total USDC from pool account", async () => {
- await program.rpc.withdrawPoolUsdc({
- accounts: {
- poolAccount: poolAccount.publicKey,
- poolSigner,
- distributionAuthority: provider.wallet.publicKey,
- creatorUsdc,
- poolUsdc,
- tokenProgram: TOKEN_PROGRAM_ID,
- clock: anchor.web3.SYSVAR_CLOCK_PUBKEY,
- },
- });
- poolUsdcAccount = await getTokenAccount(provider, poolUsdc);
- assert.ok(poolUsdcAccount.amount.eq(new anchor.BN(0)));
- creatorUsdcAccount = await getTokenAccount(provider, creatorUsdc);
- assert.ok(creatorUsdcAccount.amount.eq(totalPoolUsdc));
- });
- });
|