Mostly working now

This commit is contained in:
Jordan Prince 2021-09-13 18:31:18 -05:00
parent 8916935b22
commit f3020bc926
3 changed files with 257 additions and 135 deletions

View File

@ -604,9 +604,8 @@ program
)
)[0];
const fairLaunchLotteryBitmap = ( //@ts-ignore
await getFairLaunchLotteryBitmap(fairLaunchObj.tokenMint)
)[0];
const fairLaunchLotteryBitmap = //@ts-ignore
(await getFairLaunchLotteryBitmap(fairLaunchObj.tokenMint))[0];
await adjustTicket({
amountNumber,
@ -649,6 +648,11 @@ program
)
)[0];
const fairLaunchLotteryBitmapObj =
await anchorProgram.provider.connection.getAccountInfo(
fairLaunchLotteryBitmap,
);
const seqKeys = [];
//@ts-ignore
for (let i = 0; i < fairLaunchObj.numberTicketsSold; i++) {
@ -758,23 +762,63 @@ program
anchorProgram,
});
} else {
console.log(
'Punching ticket for buyer',
ticket.model.buyer.toBase58(),
);
const diff =
ticket.model.amount.toNumber() -
//@ts-ignore
fairLaunchObj.currentMedian.toNumber();
if (diff > 0) {
const myByte =
fairLaunchLotteryBitmapObj.data[
FAIR_LAUNCH_LOTTERY_SIZE +
Math.floor(ticket.model.seq.toNumber() / 8)
];
const positionFromRight = 7 - (ticket.model.seq.toNumber() % 8);
const mask = Math.pow(2, positionFromRight);
const isWinner = myByte & mask;
if (isWinner > 0) {
console.log(
'Refunding first',
diff,
'to buyer before punching',
'Punching ticket for buyer',
ticket.model.buyer.toBase58(),
);
const diff =
ticket.model.amount.toNumber() -
//@ts-ignore
fairLaunchObj.currentMedian.toNumber();
if (diff > 0) {
console.log(
'Refunding first',
diff,
'to buyer before punching',
);
await adjustTicket({
//@ts-ignore
amountNumber: fairLaunchObj.currentMedian.toNumber,
fairLaunchObj,
adjuster: ticket.model.buyer,
fairLaunch,
fairLaunchTicket: ticket.key,
fairLaunchLotteryBitmap,
anchorProgram,
});
}
const buyerTokenAccount = await punchTicket({
payer: walletKeyPair,
puncher: ticket.model.buyer,
anchorProgram,
fairLaunchTicket: ticket.key,
fairLaunch,
fairLaunchLotteryBitmap,
fairLaunchObj,
});
console.log(
`Punched ticket and placed token in new account ${buyerTokenAccount.toBase58()}.`,
);
} else {
console.log(
'Buyer ',
ticket.model.buyer.toBase58(),
'was eligible but lost lottery, refunding',
);
await adjustTicket({
//@ts-ignore
amountNumber: fairLaunchObj.currentMedian.toNumber,
amountNumber: 0,
fairLaunchObj,
adjuster: ticket.model.buyer,
fairLaunch,
@ -782,20 +826,8 @@ program
fairLaunchLotteryBitmap,
anchorProgram,
});
console.log('Refunded.');
}
const buyerTokenAccount = await punchTicket({
payer: walletKeyPair,
puncher: ticket.model.buyer,
anchorProgram,
fairLaunchTicket: ticket.key,
fairLaunch,
fairLaunchLotteryBitmap,
fairLaunchObj,
});
console.log(
`Punched ticket and placed token in new account ${buyerTokenAccount.toBase58()}.`,
);
}
} else if (ticket.model.state.withdrawn) {
console.log(
@ -898,9 +930,8 @@ program
)
)[0];
const fairLaunchLotteryBitmap = ( //@ts-ignore
await getFairLaunchLotteryBitmap(fairLaunchObj.tokenMint)
)[0];
const fairLaunchLotteryBitmap = //@ts-ignore
(await getFairLaunchLotteryBitmap(fairLaunchObj.tokenMint))[0];
const ticket = await anchorProgram.account.fairLaunchTicket.fetch(
fairLaunchTicket,
@ -1022,9 +1053,8 @@ program
const fairLaunchObj = await anchorProgram.account.fairLaunch.fetch(
fairLaunchKey,
);
const fairLaunchLotteryBitmap = ( //@ts-ignore
await getFairLaunchLotteryBitmap(fairLaunchObj.tokenMint)
)[0];
const fairLaunchLotteryBitmap = //@ts-ignore
(await getFairLaunchLotteryBitmap(fairLaunchObj.tokenMint))[0];
await anchorProgram.rpc.startPhaseThree({
accounts: {
@ -1105,6 +1135,99 @@ program
console.log(`Now you rich, give me some.`);
});
program
.command('receive_refund')
.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 (_, cmd) => {
const { env, keypair, fairLaunch } = cmd.opts();
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 buyerTokenAccount = (
await getAtaForMint(
//@ts-ignore
fairLaunchObj.tokenMint,
walletKeyPair.publicKey,
)
)[0];
const transferAuthority = anchor.web3.Keypair.generate();
const signers = [transferAuthority];
const instructions = [
Token.createApproveInstruction(
TOKEN_PROGRAM_ID,
//@ts-ignore
fairLaunchObj.tokenMint,
transferAuthority.publicKey,
walletKeyPair.publicKey,
[],
//@ts-ignore
1,
),
];
const remainingAccounts = [];
//@ts-ignore
if (fairLaunchObj.treasuryMint) {
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,
});
}
const txid = await anchorProgram.rpc.receiveRefund({
accounts: {
fairLaunch,
// @ts-ignore
treasury: fairLaunchObj.treasury,
buyer: walletKeyPair.publicKey,
buyerTokenAccount,
transferAuthority: transferAuthority.publicKey,
// @ts-ignore
tokenMint: fairLaunchObj.tokenMint,
tokenProgram: TOKEN_PROGRAM_ID,
systemProgram: anchor.web3.SystemProgram.programId,
clock: anchor.web3.SYSVAR_CLOCK_PUBKEY,
},
remainingAccounts,
instructions,
signers,
});
console.log(`You received a refund, traitor. ${txid}`);
});
program
.command('create_fair_launch_lottery')
.option(

View File

@ -783,119 +783,118 @@ pub mod fair_launch {
Ok(())
}
}
pub fn receive_refund<'info>(
ctx: Context<'_, '_, '_, 'info, ReceiveRefund<'info>>,
) -> ProgramResult {
let fair_launch = &mut ctx.accounts.fair_launch;
let treasury = &mut ctx.accounts.treasury;
let buyer = &mut ctx.accounts.buyer;
let token_mint = &ctx.accounts.token_mint;
let token_program = &ctx.accounts.token_program;
let clock = &ctx.accounts.clock;
let buyer_token_account = &mut ctx.accounts.buyer_token_account;
let transfer_authority = &mut ctx.accounts.transfer_authority;
pub fn receive_refund<'info>(
ctx: Context<'_, '_, '_, 'info, ReceiveRefund<'info>>,
) -> ProgramResult {
let fair_launch = &mut ctx.accounts.fair_launch;
let treasury = &mut ctx.accounts.treasury;
let buyer = &mut ctx.accounts.buyer;
let token_mint = &ctx.accounts.token_mint;
let token_program = &ctx.accounts.token_program;
let clock = &ctx.accounts.clock;
let buyer_token_account = &mut ctx.accounts.buyer_token_account;
let transfer_authority = &mut ctx.accounts.transfer_authority;
let signer_seeds = [
PREFIX.as_bytes(),
&token_mint.key.as_ref(),
&[fair_launch.bump],
];
let signer_seeds = [
PREFIX.as_bytes(),
&token_mint.key.as_ref(),
&[fair_launch.bump],
];
if fair_launch.number_tickets_sold
> fair_launch.number_tickets_dropped + fair_launch.number_tickets_punched
{
return Err(ErrorCode::CannotRefundUntilAllTicketsHaveBeenPunchedOrDropped.into());
}
if !fair_launch.phase_three_started {
return Err(ErrorCode::CannotRefundUntilPhaseThree.into());
}
fair_launch.number_tokens_burned_for_refunds = fair_launch
.number_tokens_burned_for_refunds
.checked_add(1)
.ok_or(ErrorCode::NumericalOverflowError)?;
spl_token_burn(TokenBurnParams {
mint: token_mint.clone(),
source: buyer_token_account.clone(),
amount: 1,
authority: transfer_authority.clone(),
authority_signer_seeds: None,
token_program: token_program.clone(),
})?;
if let Some(treasury_mint) = fair_launch.treasury_mint {
let treasury_mint_info = &ctx.remaining_accounts[0];
let _treasury_mint: spl_token::state::Mint = assert_initialized(&treasury_mint_info)?;
let buyer_payment_account_info = &ctx.remaining_accounts[1];
let buyer_payment_account: Account = assert_initialized(&buyer_payment_account_info)?;
let treasury_account: Account = assert_initialized(treasury)?;
if *treasury_mint_info.key != treasury_mint {
return Err(ErrorCode::TreasuryMintMismatch.into());
if fair_launch.number_tickets_sold
> fair_launch.number_tickets_dropped + fair_launch.number_tickets_punched
{
return Err(ErrorCode::CannotRefundUntilAllTicketsHaveBeenPunchedOrDropped.into());
}
assert_owned_by(treasury_mint_info, &token_program.key)?;
assert_owned_by(buyer_payment_account_info, &token_program.key)?;
assert_owned_by(treasury, &token_program.key)?;
if buyer_payment_account.mint != *treasury_mint_info.key {
return Err(ErrorCode::TreasuryMintMismatch.into());
if !fair_launch.phase_three_started {
return Err(ErrorCode::CannotRefundUntilPhaseThree.into());
}
// assert is an ATA
assert_derivation(
&Pubkey::from_str(ASSOCIATED_TOKEN_PROGRAM_ID).unwrap(),
buyer_payment_account_info,
&[
buyer.key.as_ref(),
token_program.key.as_ref(),
&treasury_mint_info.key.as_ref(),
],
)?;
fair_launch.number_tokens_burned_for_refunds = fair_launch
.number_tokens_burned_for_refunds
.checked_add(1)
.ok_or(ErrorCode::NumericalOverflowError)?;
if buyer_payment_account.delegate.is_some() {
return Err(ErrorCode::AccountShouldHaveNoDelegates.into());
}
if fair_launch.treasury_snapshot.is_none() {
fair_launch.treasury_snapshot = Some(treasury_account.amount)
}
let amount = calculate_refund_amount(fair_launch, clock.unix_timestamp)?;
spl_token_transfer(TokenTransferParams {
source: treasury.to_account_info(),
destination: buyer_payment_account_info.clone(),
authority: fair_launch.to_account_info(),
authority_signer_seeds: &signer_seeds,
spl_token_burn(TokenBurnParams {
mint: token_mint.clone(),
source: buyer_token_account.clone(),
amount: 1,
authority: transfer_authority.clone(),
authority_signer_seeds: None,
token_program: token_program.clone(),
amount,
})?;
} else {
if fair_launch.treasury_snapshot.is_none() {
fair_launch.treasury_snapshot = Some(treasury.lamports())
if let Some(treasury_mint) = fair_launch.treasury_mint {
let treasury_mint_info = &ctx.remaining_accounts[0];
let _treasury_mint: spl_token::state::Mint = assert_initialized(&treasury_mint_info)?;
let buyer_payment_account_info = &ctx.remaining_accounts[1];
let buyer_payment_account: Account = assert_initialized(&buyer_payment_account_info)?;
let treasury_account: Account = assert_initialized(treasury)?;
if *treasury_mint_info.key != treasury_mint {
return Err(ErrorCode::TreasuryMintMismatch.into());
}
assert_owned_by(treasury_mint_info, &token_program.key)?;
assert_owned_by(buyer_payment_account_info, &token_program.key)?;
assert_owned_by(treasury, &token_program.key)?;
if buyer_payment_account.mint != *treasury_mint_info.key {
return Err(ErrorCode::TreasuryMintMismatch.into());
}
// assert is an ATA
assert_derivation(
&Pubkey::from_str(ASSOCIATED_TOKEN_PROGRAM_ID).unwrap(),
buyer_payment_account_info,
&[
buyer.key.as_ref(),
token_program.key.as_ref(),
&treasury_mint_info.key.as_ref(),
],
)?;
if buyer_payment_account.delegate.is_some() {
return Err(ErrorCode::AccountShouldHaveNoDelegates.into());
}
if fair_launch.treasury_snapshot.is_none() {
fair_launch.treasury_snapshot = Some(treasury_account.amount)
}
let amount = calculate_refund_amount(fair_launch, clock.unix_timestamp)?;
spl_token_transfer(TokenTransferParams {
source: treasury.to_account_info(),
destination: buyer_payment_account_info.clone(),
authority: fair_launch.to_account_info(),
authority_signer_seeds: &signer_seeds,
token_program: token_program.clone(),
amount,
})?;
} else {
if fair_launch.treasury_snapshot.is_none() {
fair_launch.treasury_snapshot = Some(treasury.lamports())
}
let amount = calculate_refund_amount(fair_launch, clock.unix_timestamp)?;
invoke(
&system_instruction::transfer(treasury.key, buyer.key, amount),
&[
treasury.to_account_info(),
buyer.clone(),
ctx.accounts.system_program.clone(),
],
)?;
}
let amount = calculate_refund_amount(fair_launch, clock.unix_timestamp)?;
invoke(
&system_instruction::transfer(treasury.key, buyer.key, amount),
&[
treasury.to_account_info(),
buyer.clone(),
ctx.accounts.system_program.clone(),
],
)?;
Ok(())
}
Ok(())
}
#[derive(Accounts)]
#[instruction(bump: u8, treasury_bump: u8, token_mint_bump: u8, data: FairLaunchData)]
pub struct InitializeFairLaunch<'info> {

File diff suppressed because one or more lines are too long