wip on fair launch new fields
This commit is contained in:
parent
3079e62283
commit
d8d9ab6771
|
@ -1617,16 +1617,27 @@ program
|
|||
|
||||
const statesFlat = states.flat();
|
||||
|
||||
//@ts-ignore;
|
||||
let numWinnersRemaining = fairLaunchObj.data.numberOfTokens;
|
||||
let numWinnersRemaining = Math.min(
|
||||
//@ts-ignore;
|
||||
fairLaunchObj.data.numberOfTokens,
|
||||
//@ts-ignore;
|
||||
statesFlat.filter(s => s.eligible).length,
|
||||
);
|
||||
|
||||
console.log(
|
||||
'Dunn',
|
||||
//@ts-ignore;
|
||||
fairLaunchObj.numberTicketsSold - fairLaunchObj.numberTicketsDropped,
|
||||
);
|
||||
|
||||
let chosen: { seq: anchor.BN; eligible: boolean; chosen: boolean }[];
|
||||
if (numWinnersRemaining >= statesFlat.length) {
|
||||
console.log('More or equal nfts than winners, everybody wins.');
|
||||
chosen = statesFlat.map(s => ({ ...s, chosen: true }));
|
||||
} else {
|
||||
console.log('Doing lottery.');
|
||||
chosen = statesFlat.map(s => ({ ...s, chosen: false }));
|
||||
|
||||
console.log('Doing lottery for', numWinnersRemaining);
|
||||
while (numWinnersRemaining > 0) {
|
||||
const rand = Math.round(Math.random() * (chosen.length - 1));
|
||||
if (chosen[rand].chosen != true && chosen[rand].eligible) {
|
||||
|
@ -1960,6 +1971,12 @@ program
|
|||
fairLaunchObj.phaseThreeStarted,
|
||||
);
|
||||
|
||||
console.log(
|
||||
'Current Eligible Holders',
|
||||
//@ts-ignore
|
||||
fairLaunchObj.currentEligibleHolders.toNumber(),
|
||||
);
|
||||
|
||||
console.log(
|
||||
'Current Median',
|
||||
//@ts-ignore
|
||||
|
|
|
@ -41,7 +41,9 @@ import {
|
|||
import {
|
||||
FairLaunchAccount,
|
||||
FairLaunchTicket,
|
||||
getFairLaunchLotteryBitmap,
|
||||
getFairLaunchState,
|
||||
punchTicket,
|
||||
purchaseTicket,
|
||||
withdrawFunds,
|
||||
} from './fair-launch';
|
||||
|
@ -129,6 +131,30 @@ export interface HomeProps {
|
|||
txTimeout: number;
|
||||
}
|
||||
|
||||
const FAIR_LAUNCH_LOTTERY_SIZE =
|
||||
8 + // discriminator
|
||||
32 + // fair launch
|
||||
1 + // bump
|
||||
8; // size of bitmask ones
|
||||
|
||||
const isWinner = (
|
||||
phaseThree: boolean | undefined,
|
||||
lottery: Uint8Array | null,
|
||||
sequence: anchor.BN | undefined,
|
||||
): boolean => {
|
||||
if (!lottery || !lottery.length || !sequence || !phaseThree) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const myByte =
|
||||
lottery[FAIR_LAUNCH_LOTTERY_SIZE + Math.floor(sequence.toNumber() / 8)];
|
||||
|
||||
const positionFromRight = 7 - (sequence.toNumber() % 8);
|
||||
const mask = Math.pow(2, positionFromRight);
|
||||
const isWinner = myByte & mask;
|
||||
return isWinner > 0;
|
||||
};
|
||||
|
||||
const Home = (props: HomeProps) => {
|
||||
const [balance, setBalance] = useState<number>();
|
||||
const [isActive, setIsActive] = useState(false); // true when countdown completes
|
||||
|
@ -138,6 +164,7 @@ const Home = (props: HomeProps) => {
|
|||
const [selectedTab, setSelectedTab] = useState(0);
|
||||
const [ticket, setTicket] = useState<FairLaunchTicket | null>(null);
|
||||
const [treasury, setTreasury] = useState<number | null>(null);
|
||||
const [lottery, setLottery] = useState<Uint8Array | null>(null);
|
||||
|
||||
const wallet = useWallet();
|
||||
|
||||
|
@ -282,6 +309,19 @@ const Home = (props: HomeProps) => {
|
|||
state.state.treasury,
|
||||
);
|
||||
setTreasury(treasury);
|
||||
const fairLaunchLotteryBitmap = (
|
||||
await getFairLaunchLotteryBitmap(
|
||||
//@ts-ignore
|
||||
fairLaunchObj.tokenMint,
|
||||
)
|
||||
)[0];
|
||||
|
||||
const fairLaunchLotteryBitmapObj =
|
||||
await state.program.provider.connection.getAccountInfo(
|
||||
fairLaunchLotteryBitmap,
|
||||
);
|
||||
|
||||
setLottery(new Uint8Array(fairLaunchLotteryBitmapObj?.data || []));
|
||||
|
||||
console.log();
|
||||
} catch {
|
||||
|
@ -339,6 +379,16 @@ const Home = (props: HomeProps) => {
|
|||
purchaseTicket(contributed, anchorWallet, fairLaunch, ticket);
|
||||
};
|
||||
|
||||
const onPunchTicket = () => {
|
||||
if (!anchorWallet || !fairLaunch) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('punch');
|
||||
|
||||
punchTicket(anchorWallet, fairLaunch);
|
||||
};
|
||||
|
||||
const onWithdraw = () => {
|
||||
if (!anchorWallet) {
|
||||
return;
|
||||
|
@ -410,6 +460,16 @@ const Home = (props: HomeProps) => {
|
|||
{!ticket ? 'Place a bid' : 'Adjust your bid'}
|
||||
</MintButton>
|
||||
|
||||
{isWinner(
|
||||
fairLaunch?.state.phaseThreeStarted,
|
||||
lottery,
|
||||
ticket?.seq,
|
||||
) && (
|
||||
<MintButton onClick={onPunchTicket} variant="contained">
|
||||
Punch Ticket
|
||||
</MintButton>
|
||||
)}
|
||||
|
||||
<Grid>
|
||||
<Typography>How raffles works</Typography>
|
||||
</Grid>
|
||||
|
|
|
@ -2,7 +2,10 @@ import * as anchor from '@project-serum/anchor';
|
|||
|
||||
import { TOKEN_PROGRAM_ID, Token } from '@solana/spl-token';
|
||||
import { LAMPORTS_PER_SOL } from '@solana/web3.js';
|
||||
import { getAtaForMint } from './utils';
|
||||
import {
|
||||
createAssociatedTokenAccountInstruction,
|
||||
getAtaForMint,
|
||||
} from './utils';
|
||||
|
||||
export const FAIR_LAUNCH_PROGRAM = new anchor.web3.PublicKey(
|
||||
'7HmfyvWK7LDohUL9TDAuGv9VFZHUce1SgYMkwti1xWwF',
|
||||
|
@ -49,6 +52,7 @@ export interface FairLaunchState {
|
|||
bump: number;
|
||||
|
||||
currentMedian: anchor.BN;
|
||||
currentEligibleHolders: anchor.BN;
|
||||
data: {
|
||||
antiRugSetting?: AntiRugSetting;
|
||||
fee: anchor.BN;
|
||||
|
@ -121,8 +125,8 @@ export const getFairLaunchState = async (
|
|||
},
|
||||
};
|
||||
};
|
||||
/*
|
||||
const punchTicket = async (
|
||||
|
||||
export const punchTicket = async (
|
||||
anchorWallet: anchor.Wallet,
|
||||
fairLaunch: FairLaunchAccount,
|
||||
) => {
|
||||
|
@ -134,9 +138,8 @@ const punchTicket = async (
|
|||
)
|
||||
)[0];
|
||||
|
||||
const fairLaunchLotteryBitmap = ( //@ts-ignore
|
||||
await getFairLaunchLotteryBitmap(fairLaunchObj.tokenMint)
|
||||
)[0];
|
||||
const fairLaunchLotteryBitmap = //@ts-ignore
|
||||
(await getFairLaunchLotteryBitmap(fairLaunchObj.tokenMint))[0];
|
||||
|
||||
const buyerTokenAccount = (
|
||||
await getAtaForMint(
|
||||
|
@ -167,7 +170,7 @@ const punchTicket = async (
|
|||
),
|
||||
],
|
||||
});
|
||||
};*/
|
||||
};
|
||||
|
||||
export const getFairLaunchTicket = async (
|
||||
tokenMint: anchor.web3.PublicKey,
|
||||
|
@ -276,8 +279,9 @@ export const purchaseTicket = async (
|
|||
);
|
||||
|
||||
if (ticket) {
|
||||
const fairLaunchLotteryBitmap = //@ts-ignore
|
||||
(await getFairLaunchLotteryBitmap(fairLaunch.state.tokenMint))[0];
|
||||
const fairLaunchLotteryBitmap = ( //@ts-ignore
|
||||
await getFairLaunchLotteryBitmap(fairLaunch.state.tokenMint)
|
||||
)[0];
|
||||
console.log(
|
||||
'Anchor wallet',
|
||||
anchorWallet.publicKey.toBase58(),
|
||||
|
|
|
@ -157,7 +157,7 @@ pub mod fair_launch {
|
|||
if fair_launch_lottery_bitmap.bitmap_ones
|
||||
!= std::cmp::min(
|
||||
fair_launch.data.number_of_tokens,
|
||||
fair_launch.number_tickets_sold,
|
||||
fair_launch.current_eligible_holders,
|
||||
)
|
||||
{
|
||||
return Err(ErrorCode::LotteryBitmapOnesMustEqualNumberOfTicketsSold.into());
|
||||
|
@ -1195,6 +1195,7 @@ pub const FAIR_LAUNCH_SPACE_VEC_START: usize = 8 + // discriminator
|
|||
8 + // number of tokens preminted
|
||||
1 + // phase three started
|
||||
9 + // treasury snapshot
|
||||
8 + // current_eligible_holders
|
||||
8 + // current median,
|
||||
4 + // u32 representing number of amounts in vec so far
|
||||
100; // padding
|
||||
|
@ -1267,6 +1268,7 @@ pub struct FairLaunch {
|
|||
pub phase_three_started: bool,
|
||||
/// Snapshot of treasury taken on first withdrawal.
|
||||
pub treasury_snapshot: Option<u64>,
|
||||
pub current_eligible_holders: u64,
|
||||
pub current_median: u64,
|
||||
pub counts_at_each_tick: Vec<u64>,
|
||||
}
|
||||
|
|
|
@ -121,15 +121,28 @@ pub fn adjust_counts(
|
|||
}
|
||||
|
||||
let mut total_counts: u64 = 0;
|
||||
let mut ticks: u64 = 0;
|
||||
let mut first_val_seen = false;
|
||||
let mut first_val = 0;
|
||||
for n in &fair_launch.counts_at_each_tick {
|
||||
total_counts = total_counts
|
||||
.checked_add(*n)
|
||||
.ok_or(ErrorCode::NumericalOverflowError)?;
|
||||
if !first_val_seen && n > &0 {
|
||||
first_val = ticks
|
||||
.checked_add(fair_launch.data.price_range_start)
|
||||
.ok_or(ErrorCode::NumericalOverflowError)?;
|
||||
first_val_seen = true;
|
||||
}
|
||||
ticks = ticks
|
||||
.checked_add(fair_launch.data.tick_size)
|
||||
.ok_or(ErrorCode::NumericalOverflowError)?;
|
||||
}
|
||||
|
||||
if total_counts == 1 {
|
||||
// degen case
|
||||
fair_launch.current_median = new_amount;
|
||||
fair_launch.current_median = first_val;
|
||||
fair_launch.current_eligible_holders = 1;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
@ -140,39 +153,49 @@ pub fn adjust_counts(
|
|||
let mut counter: u64 = 0;
|
||||
let mut ticks: u64 = 0;
|
||||
let mut last_seen_tick_value_with_positive_counts: u64 = 0;
|
||||
let mut current_eligible_holders: u64 = 0;
|
||||
let mut done: bool = false;
|
||||
for n in &fair_launch.counts_at_each_tick {
|
||||
let is_possible_perfect_split = counter == median_location;
|
||||
counter = counter
|
||||
.checked_add(*n)
|
||||
.ok_or(ErrorCode::NumericalOverflowError)?;
|
||||
|
||||
if counter > median_location {
|
||||
if let Some(val) = total_counts.checked_rem(2) {
|
||||
if val == 0 && is_possible_perfect_split {
|
||||
let half_way = ticks
|
||||
.checked_sub(last_seen_tick_value_with_positive_counts)
|
||||
.ok_or(ErrorCode::NumericalOverflowError)?;
|
||||
ticks = half_way
|
||||
.checked_div(2)
|
||||
.ok_or(ErrorCode::NumericalOverflowError)?;
|
||||
ticks = last_seen_tick_value_with_positive_counts
|
||||
.checked_add(ticks)
|
||||
.ok_or(ErrorCode::NumericalOverflowError)?;
|
||||
if !done {
|
||||
if let Some(val) = total_counts.checked_rem(2) {
|
||||
if val == 0 && is_possible_perfect_split {
|
||||
let half_way = ticks
|
||||
.checked_sub(last_seen_tick_value_with_positive_counts)
|
||||
.ok_or(ErrorCode::NumericalOverflowError)?;
|
||||
ticks = half_way
|
||||
.checked_div(2)
|
||||
.ok_or(ErrorCode::NumericalOverflowError)?;
|
||||
ticks = last_seen_tick_value_with_positive_counts
|
||||
.checked_add(ticks)
|
||||
.ok_or(ErrorCode::NumericalOverflowError)?;
|
||||
}
|
||||
}
|
||||
done = true;
|
||||
}
|
||||
break;
|
||||
current_eligible_holders += n;
|
||||
}
|
||||
if n > &0 {
|
||||
last_seen_tick_value_with_positive_counts = ticks;
|
||||
if !done {
|
||||
if n > &0 {
|
||||
last_seen_tick_value_with_positive_counts = ticks;
|
||||
}
|
||||
ticks = ticks
|
||||
.checked_add(fair_launch.data.tick_size)
|
||||
.ok_or(ErrorCode::NumericalOverflowError)?;
|
||||
}
|
||||
ticks = ticks
|
||||
.checked_add(fair_launch.data.tick_size)
|
||||
.ok_or(ErrorCode::NumericalOverflowError)?;
|
||||
}
|
||||
|
||||
fair_launch.current_median = ticks
|
||||
.checked_add(fair_launch.data.price_range_start)
|
||||
.ok_or(ErrorCode::NumericalOverflowError)?;
|
||||
|
||||
fair_launch.current_eligible_holders = current_eligible_holders;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue