well, a lot of stuff.
This commit is contained in:
parent
b6ac259413
commit
ff339ed482
|
@ -3,7 +3,7 @@ import * as fs from 'fs';
|
||||||
import { program } from 'commander';
|
import { program } from 'commander';
|
||||||
import * as anchor from '@project-serum/anchor';
|
import * as anchor from '@project-serum/anchor';
|
||||||
import { LAMPORTS_PER_SOL } from '@solana/web3.js';
|
import { LAMPORTS_PER_SOL } from '@solana/web3.js';
|
||||||
|
import { Token } from '@solana/spl-token';
|
||||||
import { CACHE_PATH, TOKEN_PROGRAM_ID } from './helpers/constants';
|
import { CACHE_PATH, TOKEN_PROGRAM_ID } from './helpers/constants';
|
||||||
import {
|
import {
|
||||||
loadFairLaunchProgram,
|
loadFairLaunchProgram,
|
||||||
|
@ -11,7 +11,11 @@ import {
|
||||||
getTokenMint,
|
getTokenMint,
|
||||||
getFairLaunch,
|
getFairLaunch,
|
||||||
getTreasury,
|
getTreasury,
|
||||||
|
getFairLaunchTicket,
|
||||||
|
getAtaForMint,
|
||||||
|
getFairLaunchTicketSeqLookup,
|
||||||
} from './helpers/accounts';
|
} from './helpers/accounts';
|
||||||
|
import { sleep } from './helpers/various';
|
||||||
program.version('0.0.1');
|
program.version('0.0.1');
|
||||||
|
|
||||||
if (!fs.existsSync(CACHE_PATH)) {
|
if (!fs.existsSync(CACHE_PATH)) {
|
||||||
|
@ -145,6 +149,137 @@ program
|
||||||
console.log(`create fair launch Done: ${fairLaunch.toBase58()}`);
|
console.log(`create fair launch Done: ${fairLaunch.toBase58()}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
program
|
||||||
|
.command('purchase_ticket')
|
||||||
|
.option(
|
||||||
|
'-e, --env <string>',
|
||||||
|
'Solana cluster env name',
|
||||||
|
'devnet', //mainnet-beta, testnet, devnet
|
||||||
|
)
|
||||||
|
.option(
|
||||||
|
'-k, --keypair <path>',
|
||||||
|
`Solana wallet location`,
|
||||||
|
'--keypair not provided',
|
||||||
|
)
|
||||||
|
.option('-f, --fair-launch <string>', 'fair launch id')
|
||||||
|
.option('-a, --amount <string>', 'amount')
|
||||||
|
.action(async (_, cmd) => {
|
||||||
|
const { env, keypair, fairLaunch, amount } = cmd.opts();
|
||||||
|
let amountNumber = parseFloat(amount);
|
||||||
|
|
||||||
|
const walletKeyPair = loadWalletKey(keypair);
|
||||||
|
const anchorProgram = await loadFairLaunchProgram(walletKeyPair, env);
|
||||||
|
|
||||||
|
const fairLaunchKey = new anchor.web3.PublicKey(fairLaunch);
|
||||||
|
const fairLaunchObj = await anchorProgram.account.fairLaunch.fetch(
|
||||||
|
fairLaunchKey,
|
||||||
|
);
|
||||||
|
const [fairLaunchTicket, bump] = await getFairLaunchTicket(
|
||||||
|
//@ts-ignore
|
||||||
|
fairLaunchObj.tokenMint,
|
||||||
|
walletKeyPair.publicKey,
|
||||||
|
);
|
||||||
|
|
||||||
|
const remainingAccounts = [];
|
||||||
|
const instructions = [];
|
||||||
|
const signers = [];
|
||||||
|
|
||||||
|
//@ts-ignore
|
||||||
|
if (!fairLaunchObj.treasuryMint) {
|
||||||
|
amountNumber = Math.ceil(amountNumber * LAMPORTS_PER_SOL);
|
||||||
|
} else {
|
||||||
|
const transferAuthority = anchor.web3.Keypair.generate();
|
||||||
|
signers.push(transferAuthority);
|
||||||
|
|
||||||
|
instructions.push(
|
||||||
|
Token.createApproveInstruction(
|
||||||
|
TOKEN_PROGRAM_ID,
|
||||||
|
//@ts-ignore
|
||||||
|
fairLaunchObj.treasuryMint,
|
||||||
|
transferAuthority.publicKey,
|
||||||
|
walletKeyPair.publicKey,
|
||||||
|
[],
|
||||||
|
//@ts-ignore
|
||||||
|
amountNumber + fairLaunchObj.data.fees.toNumber(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
remainingAccounts.push({
|
||||||
|
//@ts-ignore
|
||||||
|
pubkey: fairLaunchObj.treasuryMint,
|
||||||
|
isWritable: true,
|
||||||
|
isSigner: false,
|
||||||
|
});
|
||||||
|
remainingAccounts.push({
|
||||||
|
pubkey: (
|
||||||
|
await getAtaForMint(
|
||||||
|
//@ts-ignore
|
||||||
|
fairLaunchObj.treasuryMint,
|
||||||
|
walletKeyPair.publicKey,
|
||||||
|
)
|
||||||
|
)[0],
|
||||||
|
isWritable: true,
|
||||||
|
isSigner: false,
|
||||||
|
});
|
||||||
|
remainingAccounts.push({
|
||||||
|
pubkey: transferAuthority.publicKey,
|
||||||
|
isWritable: false,
|
||||||
|
isSigner: true,
|
||||||
|
});
|
||||||
|
remainingAccounts.push({
|
||||||
|
pubkey: TOKEN_PROGRAM_ID,
|
||||||
|
isWritable: false,
|
||||||
|
isSigner: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await anchorProgram.rpc.purchaseTicket(bump, new anchor.BN(amountNumber), {
|
||||||
|
accounts: {
|
||||||
|
fairLaunchTicket,
|
||||||
|
fairLaunch,
|
||||||
|
//@ts-ignore
|
||||||
|
treasury: fairLaunchObj.treasury,
|
||||||
|
buyer: walletKeyPair.publicKey,
|
||||||
|
payer: walletKeyPair.publicKey,
|
||||||
|
systemProgram: anchor.web3.SystemProgram.programId,
|
||||||
|
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
||||||
|
clock: anchor.web3.SYSVAR_CLOCK_PUBKEY,
|
||||||
|
},
|
||||||
|
//__private: { logAccounts: true },
|
||||||
|
remainingAccounts,
|
||||||
|
signers,
|
||||||
|
instructions: instructions.length > 0 ? instructions : undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`create fair launch ticket Done: ${fairLaunchTicket.toBase58()}. Trying to create seq now...we may or may not get a validator with data on chain. Either way, your ticket is secure.`,
|
||||||
|
);
|
||||||
|
|
||||||
|
await sleep(5000);
|
||||||
|
const fairLaunchTicketObj =
|
||||||
|
await anchorProgram.account.fairLaunchTicket.fetch(fairLaunchTicket);
|
||||||
|
|
||||||
|
const [fairLaunchTicketSeqLookup, seqBump] =
|
||||||
|
await getFairLaunchTicketSeqLookup(
|
||||||
|
//@ts-ignore
|
||||||
|
fairLaunchObj.tokenMint,
|
||||||
|
//@ts-ignore
|
||||||
|
fairLaunchTicketObj.seq,
|
||||||
|
);
|
||||||
|
|
||||||
|
await anchorProgram.rpc.createTicketSeq(seqBump, {
|
||||||
|
accounts: {
|
||||||
|
fairLaunchTicketSeqLookup,
|
||||||
|
fairLaunch,
|
||||||
|
fairLaunchTicket,
|
||||||
|
payer: walletKeyPair.publicKey,
|
||||||
|
systemProgram: anchor.web3.SystemProgram.programId,
|
||||||
|
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
|
||||||
|
},
|
||||||
|
signers: [],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
program
|
program
|
||||||
.command('show')
|
.command('show')
|
||||||
.option(
|
.option(
|
||||||
|
@ -290,4 +425,51 @@ program
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
program
|
||||||
|
.command('show_ticket')
|
||||||
|
.option(
|
||||||
|
'-e, --env <string>',
|
||||||
|
'Solana cluster env name',
|
||||||
|
'devnet', //mainnet-beta, testnet, devnet
|
||||||
|
)
|
||||||
|
.option(
|
||||||
|
'-k, --keypair <path>',
|
||||||
|
`Solana wallet location`,
|
||||||
|
'--keypair not provided',
|
||||||
|
)
|
||||||
|
.option('-f, --fair-launch <string>', 'fair launch id')
|
||||||
|
.action(async (options, cmd) => {
|
||||||
|
const { env, fairLaunch, keypair } = cmd.opts();
|
||||||
|
|
||||||
|
const walletKeyPair = loadWalletKey(keypair);
|
||||||
|
const anchorProgram = await loadFairLaunchProgram(walletKeyPair, env);
|
||||||
|
|
||||||
|
const fairLaunchObj = await anchorProgram.account.fairLaunch.fetch(
|
||||||
|
fairLaunch,
|
||||||
|
);
|
||||||
|
|
||||||
|
const fairLaunchTicket = (
|
||||||
|
await getFairLaunchTicket(
|
||||||
|
//@ts-ignore
|
||||||
|
fairLaunchObj.tokenMint,
|
||||||
|
walletKeyPair.publicKey,
|
||||||
|
)
|
||||||
|
)[0];
|
||||||
|
|
||||||
|
const fairLaunchTicketObj =
|
||||||
|
await anchorProgram.account.fairLaunchTicket.fetch(fairLaunchTicket);
|
||||||
|
|
||||||
|
//@ts-ignore
|
||||||
|
console.log('Buyer', fairLaunchTicketObj.buyer.toBase58());
|
||||||
|
//@ts-ignore
|
||||||
|
console.log('Fair Launch', fairLaunchTicketObj.fairLaunch.toBase58());
|
||||||
|
//@ts-ignore
|
||||||
|
console.log('Current Amount', fairLaunchTicketObj.amount.toNumber());
|
||||||
|
//@ts-ignore
|
||||||
|
console.log('State', fairLaunchTicketObj.state);
|
||||||
|
//@ts-ignore
|
||||||
|
console.log('Bump', fairLaunchTicketObj.bump);
|
||||||
|
//@ts-ignore
|
||||||
|
console.log('Sequence', fairLaunchTicketObj.seq.toNumber());
|
||||||
|
});
|
||||||
program.parse(process.argv);
|
program.parse(process.argv);
|
||||||
|
|
|
@ -118,6 +118,36 @@ export const getFairLaunch = async (
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getFairLaunchTicket = async (
|
||||||
|
tokenMint: anchor.web3.PublicKey,
|
||||||
|
buyer: anchor.web3.PublicKey,
|
||||||
|
): Promise<[anchor.web3.PublicKey, number]> => {
|
||||||
|
return await anchor.web3.PublicKey.findProgramAddress(
|
||||||
|
[Buffer.from('fair_launch'), tokenMint.toBuffer(), buyer.toBuffer()],
|
||||||
|
FAIR_LAUNCH_PROGRAM_ID,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getFairLaunchTicketSeqLookup = async (
|
||||||
|
tokenMint: anchor.web3.PublicKey,
|
||||||
|
seq: anchor.BN,
|
||||||
|
): Promise<[anchor.web3.PublicKey, number]> => {
|
||||||
|
return await anchor.web3.PublicKey.findProgramAddress(
|
||||||
|
[Buffer.from('fair_launch'), tokenMint.toBuffer(), seq.toBuffer()],
|
||||||
|
FAIR_LAUNCH_PROGRAM_ID,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getAtaForMint = async (
|
||||||
|
mint: anchor.web3.PublicKey,
|
||||||
|
buyer: anchor.web3.PublicKey,
|
||||||
|
): Promise<[anchor.web3.PublicKey, number]> => {
|
||||||
|
return await anchor.web3.PublicKey.findProgramAddress(
|
||||||
|
[buyer.toBuffer(), TOKEN_PROGRAM_ID.toBuffer(), mint.toBuffer()],
|
||||||
|
SPL_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM_ID,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export const getTreasury = async (
|
export const getTreasury = async (
|
||||||
tokenMint: anchor.web3.PublicKey,
|
tokenMint: anchor.web3.PublicKey,
|
||||||
): Promise<[anchor.web3.PublicKey, number]> => {
|
): Promise<[anchor.web3.PublicKey, number]> => {
|
||||||
|
|
|
@ -799,13 +799,13 @@ pub struct UpdateFairLaunchLotteryBitmap<'info> {
|
||||||
#[derive(Accounts)]
|
#[derive(Accounts)]
|
||||||
#[instruction(bump: u8, amount: u64)]
|
#[instruction(bump: u8, amount: u64)]
|
||||||
pub struct PurchaseTicket<'info> {
|
pub struct PurchaseTicket<'info> {
|
||||||
|
#[account(init, seeds=[PREFIX.as_bytes(), fair_launch.token_mint.as_ref(), buyer.key.as_ref()], payer=payer, bump=bump, space=FAIR_LAUNCH_TICKET_SIZE)]
|
||||||
|
fair_launch_ticket: ProgramAccount<'info, FairLaunchTicket>,
|
||||||
#[account(mut, seeds=[PREFIX.as_bytes(), fair_launch.token_mint.as_ref()], bump=fair_launch.bump, has_one=treasury)]
|
#[account(mut, seeds=[PREFIX.as_bytes(), fair_launch.token_mint.as_ref()], bump=fair_launch.bump, has_one=treasury)]
|
||||||
fair_launch: ProgramAccount<'info, FairLaunch>,
|
fair_launch: ProgramAccount<'info, FairLaunch>,
|
||||||
#[account(mut)]
|
#[account(mut)]
|
||||||
treasury: AccountInfo<'info>,
|
treasury: AccountInfo<'info>,
|
||||||
#[account(init, seeds=[PREFIX.as_bytes(), fair_launch.token_mint.as_ref(), buyer.key.as_ref()], payer=payer, bump=bump, space=FAIR_LAUNCH_TICKET_SIZE)]
|
#[account(mut, signer, constraint= buyer.data_is_empty() && buyer.lamports() > 0)]
|
||||||
fair_launch_ticket: ProgramAccount<'info, FairLaunchTicket>,
|
|
||||||
#[account(mut, signer, constraint= (treasury.owner == &spl_token::id() && buyer.owner == &spl_token::id()) || (treasury.owner != &spl_token::id() && buyer.data_is_empty() && buyer.lamports() > 0) )]
|
|
||||||
buyer: AccountInfo<'info>,
|
buyer: AccountInfo<'info>,
|
||||||
#[account(mut, signer)]
|
#[account(mut, signer)]
|
||||||
payer: AccountInfo<'info>,
|
payer: AccountInfo<'info>,
|
||||||
|
@ -824,12 +824,12 @@ pub struct PurchaseTicket<'info> {
|
||||||
#[derive(Accounts)]
|
#[derive(Accounts)]
|
||||||
#[instruction(bump: u8)]
|
#[instruction(bump: u8)]
|
||||||
pub struct CreateTicketSeq<'info> {
|
pub struct CreateTicketSeq<'info> {
|
||||||
|
#[account(init, seeds=[PREFIX.as_bytes(), fair_launch.token_mint.as_ref(), &fair_launch_ticket.seq.to_le_bytes()], payer=payer, bump=bump, space=FAIR_LAUNCH_TICKET_SEQ_SIZE)]
|
||||||
|
fair_launch_ticket_seq_lookup: ProgramAccount<'info, FairLaunchTicketSeqLookup>,
|
||||||
#[account(mut, seeds=[PREFIX.as_bytes(), fair_launch.token_mint.as_ref()], bump=fair_launch.bump)]
|
#[account(mut, seeds=[PREFIX.as_bytes(), fair_launch.token_mint.as_ref()], bump=fair_launch.bump)]
|
||||||
fair_launch: ProgramAccount<'info, FairLaunch>,
|
fair_launch: ProgramAccount<'info, FairLaunch>,
|
||||||
#[account(mut, seeds=[PREFIX.as_bytes(), fair_launch.token_mint.as_ref(), fair_launch_ticket.buyer.as_ref()], bump=fair_launch_ticket.bump, has_one=fair_launch)]
|
#[account(mut, seeds=[PREFIX.as_bytes(), fair_launch.token_mint.as_ref(), fair_launch_ticket.buyer.as_ref()], bump=fair_launch_ticket.bump, has_one=fair_launch)]
|
||||||
fair_launch_ticket: ProgramAccount<'info, FairLaunchTicket>,
|
fair_launch_ticket: ProgramAccount<'info, FairLaunchTicket>,
|
||||||
#[account(init, seeds=[PREFIX.as_bytes(), fair_launch.token_mint.as_ref(), &fair_launch_ticket.seq.to_le_bytes()], payer=payer, bump=bump, space=FAIR_LAUNCH_TICKET_SEQ_SIZE)]
|
|
||||||
fair_launch_ticket_seq_lookup: ProgramAccount<'info, FairLaunchTicketSeqLookup>,
|
|
||||||
#[account(mut, signer)]
|
#[account(mut, signer)]
|
||||||
payer: AccountInfo<'info>,
|
payer: AccountInfo<'info>,
|
||||||
#[account(address = system_program::ID)]
|
#[account(address = system_program::ID)]
|
||||||
|
|
|
@ -209,8 +209,10 @@ pub fn assert_valid_amount(data: &FairLaunchData, amount: u64) -> ProgramResult
|
||||||
return Err(ErrorCode::InvalidPurchaseAmount.into());
|
return Err(ErrorCode::InvalidPurchaseAmount.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
if amount.checked_rem(data.tick_size).is_some() {
|
if let Some(val) = amount.checked_rem(data.tick_size) {
|
||||||
return Err(ErrorCode::InvalidPurchaseAmount.into());
|
if val > 0 {
|
||||||
|
return Err(ErrorCode::InvalidPurchaseAmount.into());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -299,4 +301,4 @@ pub fn spl_token_mint_to<'a: 'b, 'b>(
|
||||||
&[authority_signer_seeds],
|
&[authority_signer_seeds],
|
||||||
);
|
);
|
||||||
result.map_err(|_| ErrorCode::TokenMintToFailed.into())
|
result.map_err(|_| ErrorCode::TokenMintToFailed.into())
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue