Mostly working now
This commit is contained in:
parent
8916935b22
commit
f3020bc926
|
@ -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(
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue