Skip to content

Commit

Permalink
fix create launch hook
Browse files Browse the repository at this point in the history
  • Loading branch information
MSghais committed Feb 19, 2025
1 parent 17fa19e commit d84f613
Show file tree
Hide file tree
Showing 6 changed files with 283 additions and 21 deletions.
36 changes: 23 additions & 13 deletions apps/mobile/src/hooks/launchpad/useCreateToken.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {LAUNCHPAD_ADDRESS} from 'common';
import {AccountInterface, cairo, CairoCustomEnum, CallData, constants} from 'starknet';
import { LAUNCHPAD_ADDRESS } from 'common';
import { AccountInterface, cairo, CairoCustomEnum, CallData, constants } from 'starknet';

// import { LAUNCHPAD_ADDRESS, UNRUGGABLE_FACTORY_ADDRESS } from "../../constants/contracts";
import {formatFloatToUint256} from '../../utils/format';
import {BondingType} from '../../types/keys';
import { formatFloatToUint256 } from '../../utils/format';
import { BondingType } from '../../types/keys';
import { byteArray } from 'starknet';

export type DeployTokenFormValues = {
Expand All @@ -14,6 +14,8 @@ export type DeployTokenFormValues = {
contract_address_salt: string | undefined;
is_unruggable?: boolean;
bonding_type?: BondingType;
creator_fee_percent?: number;
creator_fee_destination?: string;
};

export const useCreateToken = () => {
Expand All @@ -29,14 +31,14 @@ export const useCreateToken = () => {

let initial_supply = formatFloatToUint256(data?.initialSupply ?? 100_000_000);
console.log('initial supply', initial_supply);

;
// if(Number.isNaN(initial_supply) && Number.isInteger(data?.initialSupply)){
// initial_supply = cairo.uint256(data?.initialSupply)
// }
console.log('initial supply', initial_supply);

const nameByteArray= byteArray.byteArrayFromString(data.name ?? 'LFG')
const symbolByteArray= byteArray.byteArrayFromString(data.symbol ?? 'LFG')
const nameByteArray = byteArray.byteArrayFromString(data.name ?? 'LFG')
const symbolByteArray = byteArray.byteArrayFromString(data.symbol ?? 'LFG')
console.log("byteArray.byteArrayFromString(data.name ?? 'LFG'),", nameByteArray)
console.log("byteArray.byteArrayFromString(data.symbol ?? 'LFG'),", symbolByteArray)
const deployCall = {
Expand All @@ -56,6 +58,7 @@ export const useCreateToken = () => {
// contract_address_salt: new Date().getTime(),
// is_unruggable: false,
is_unruggable: cairo.felt(String(data?.is_unruggable ?? false)),

// bonding_type:bondingEnum
// contract_address_salt:CONTRACT_ADDRESS_SALT_DEFAULT + Math.random() + Math.random() / 1000
// contract_address_salt:cairo.felt(Math.random())
Expand Down Expand Up @@ -86,7 +89,7 @@ export const useCreateToken = () => {
const initial_supply = formatFloatToUint256(data?.initialSupply ?? 100_000_000);

// let bondingEnum = new CairoCustomEnum({Exponential: 1});
let bondingEnum = new CairoCustomEnum({Linear: {}});
let bondingEnum = new CairoCustomEnum({ Linear: {} });
// let bondingEnum = new CairoCustomEnum({Linear: 0});
// let bondingEnum = new CairoCustomEnum({Exponential: {}});
console.log('[DEBUG] bondingEnum', bondingEnum);
Expand All @@ -96,19 +99,24 @@ export const useCreateToken = () => {
if (data.bonding_type === BondingType.Linear) {
console.log('[DEBUG] bondingEnum linear', data.bonding_type);
// bondingEnum = new CairoCustomEnum({Linear: 0});
bondingEnum = new CairoCustomEnum({Linear: {}});
bondingEnum = new CairoCustomEnum({ Linear: {} });
} else if (data.bonding_type === BondingType.Exponential) {
console.log('[DEBUG] bondingEnum exp', data.bonding_type);
// bondingEnum = new CairoCustomEnum({Exponential: 1});
// bondingEnum = new CairoCustomEnum({Exponential: 3});
bondingEnum = new CairoCustomEnum({Exponential: {}});
bondingEnum = new CairoCustomEnum({ Exponential: {} });
}
}
console.log('[DEBUG] bondingEnum updt', bondingEnum);

const nameByteArray= byteArray.byteArrayFromString(data.name ?? 'LFG')
const symbolByteArray= byteArray.byteArrayFromString(data.symbol ?? 'LFG')

let creator_fee_percent = formatFloatToUint256(data?.creator_fee_percent ?? 0);
console.log('creator fee percent', creator_fee_percent);

let creator_fee_destination = cairo.felt(data?.creator_fee_destination ?? account?.address)

const nameByteArray = byteArray.byteArrayFromString(data.name ?? 'LFG')
const symbolByteArray = byteArray.byteArrayFromString(data.symbol ?? 'LFG')

console.log("byteArray.byteArrayFromString(data.name ?? 'LFG'),", nameByteArray)
console.log("byteArray.byteArrayFromString(data.symbol ?? 'LFG'),", symbolByteArray)
console.log('initial supply', initial_supply);
Expand All @@ -128,6 +136,8 @@ export const useCreateToken = () => {
// is_unruggable: data?.is_unruggable
is_unruggable: cairo.felt(String(data?.is_unruggable ?? false)),
bonding_type: bondingEnum,
creator_fee_percent: creator_fee_percent,
creator_fee_destination: creator_fee_destination,
}),
};

Expand Down
248 changes: 248 additions & 0 deletions apps/mobile/src/modules/LaunchTokenPump/FormLaunchToken copy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
import { NDKEvent } from '@nostr-dev-kit/ndk';
import { useAccount } from '@starknet-react/core';
import { useQueryClient } from '@tanstack/react-query';
import { useProfile } from 'afk_nostr_sdk';
// import { useAuth } from '../../store/auth';
import { useAuth } from 'afk_nostr_sdk';
import { Formik, FormikProps } from 'formik';
import { useMemo, useRef, useState } from 'react';
import { ScrollView, TextInput, View } from 'react-native';

import { Button, SquareInput, Text } from '../../components';
import { useStyles, useWaitConnection, useWindowDimensions } from '../../hooks';
import { DeployTokenFormValues, useCreateToken } from '../../hooks/launchpad/useCreateToken';
import { useToast, useWalletModal } from '../../hooks/modals';
import stylesheet from '../../screens/CreateChannel/styles';
import { TipSuccessModalProps } from '../TipSuccessModal';
import { Picker } from '@react-native-picker/picker';
import { BondingType } from '../../types/keys';
import { numericValue } from '../../utils/format';
import { useTokenCreatedModal } from '../../hooks/modals/useTokenCreateModal';
import { LoadingSpinner } from '../../components/Loading';
import { byteArray } from 'starknet';
enum TypeCreate {
LAUNCH,
CREATE,
CREATE_AND_LAUNCH,
}
export type FormTokenCreatedProps = {
event?: NDKEvent;
starknetAddress?: string;
hide?: () => void;
showSuccess?: (props: TipSuccessModalProps) => void;
hideSuccess?: () => void;
};

type FormValues = DeployTokenFormValues;
export const FormLaunchToken: React.FC<FormTokenCreatedProps> = () => {
const [loading, setLoading] = useState(false)
const formikRef = useRef<FormikProps<FormValues>>(null);
const { hide: hideTokenCreateModal } = useTokenCreatedModal();
const walletModal = useWalletModal();
const styles = useStyles(stylesheet);
const publicKey = useAuth((state) => state.publicKey);
const profile = useProfile({ publicKey });
const queryClient = useQueryClient();
const { showToast } = useToast();
const account = useAccount();
const waitConnection = useWaitConnection();
const { deployToken, deployTokenAndLaunch } = useCreateToken();

const [type, setType] = useState(TypeCreate.CREATE);
const initialFormValues: FormValues = {
name: '',
symbol: '',
bonding_type: BondingType.Linear,
// ticker: '',
initialSupply: undefined,
contract_address_salt: new Date().getTime()?.toString(),
recipient: account?.address,
is_unruggable:false
};

const onSubmitPress = (type: TypeCreate) => {
setType(type);
formikRef.current?.handleSubmit();
};

const validateForm = (values: FormValues) => {
const errors = {} as Partial<FormValues>;
// TODO: Do validation

return errors;
};

const onFormSubmit = async (values: FormValues) => {
try {
console.log('onFormSubmit deploy');
if (!account.address) {
walletModal.show();
const result = await waitConnection();
if (!result) return;
}

if (!account || !account?.account) return;
console.log('test deploy');

if (!values?.symbol) {
return showToast({ type: 'info', title: 'Add symbol' });
} else if (!values?.name) {
return showToast({ type: 'info', title: 'Add name' });
}
else if (!values?.initialSupply) {
return showToast({ type: 'info', title: 'Initial supply required' });
}

let tx;
setLoading(true)
if (type == TypeCreate.CREATE) {
const data: DeployTokenFormValues = {
recipient: account?.address,
// name: byteArray.byteArrayFromString(values.name),
name:values.name,
symbol: values.symbol,
initialSupply: values?.initialSupply,
contract_address_salt: values.contract_address_salt,
is_unruggable: values.is_unruggable ?? false,
};

tx = await deployToken(account?.account, data).catch(err => {
showToast({ type: 'error', title: err?.message || "Something went wrong" });
setLoading(false)
});


} else {
const data: DeployTokenFormValues = {
recipient: account?.address,
name: values.name,
symbol: values.symbol,
initialSupply: values?.initialSupply,
contract_address_salt: values.contract_address_salt,
is_unruggable: values.is_unruggable ?? false,
bonding_type: values.bonding_type,
};
tx = await deployTokenAndLaunch(account?.account, data).catch(err => {
// showToast({ type: 'error', title: err?.message || "Something went wrong" });
showToast({ type: 'error', title: "Something went wrong when deploy token and launch", description: err?.message || "Something went wrong" });

setLoading(false)
});
}

if (tx) {
showToast({ type: 'success', title: 'Token launch created successfully' });
hideTokenCreateModal?.()
setLoading(false)
}
} catch (error) {

showToast({ type: 'error', title: 'Failed to create token and launch' });
setLoading(false)
}

};

if (profile.isLoading) return null;

const dimensions = useWindowDimensions();
const isDesktop = useMemo(() => {
return dimensions.width >= 1024;
}, [dimensions]);

return (
<ScrollView
automaticallyAdjustKeyboardInsets
style={styles.container}
contentContainerStyle={
isDesktop ? styles.contentContainerDesktop : styles.contentContainerMobile
}
>
<Formik
innerRef={formikRef}
initialValues={initialFormValues}
onSubmit={onFormSubmit}
validate={validateForm}
>
{({ handleChange, handleBlur, values, errors, setFieldValue }) => (
<View style={styles.form}>
<View style={styles.inputContainer}>
<Text style={styles.inputLabel}>Name</Text>
<TextInput
value={values.name}
onChangeText={handleChange('name')}
onBlur={handleBlur('name')}
placeholder="AFK Token"
style={styles.input}
/>
</View>

<View style={styles.inputContainer}>
<Text style={styles.inputLabel}>Symbol</Text>
<TextInput
value={values.symbol}
onChangeText={handleChange('symbol')}
onBlur={handleBlur('symbol')}
placeholder="AFK"
style={styles.input}
/>
</View>

<View style={styles.inputContainer}>
<Text style={styles.inputLabel}>Total Supply</Text>
<TextInput
// type="number"
value={values.initialSupply?.toString()}
onChangeText={(text) => setFieldValue("initialSupply", numericValue(text))}
onBlur={handleBlur('initialSupply')}
placeholder="100000"
inputMode="numeric"
keyboardType="numeric"
style={styles.input}


/>
</View>

<View style={styles.inputContainer}>
<Text style={styles.inputLabel}>Bonding Type</Text>
<Picker
selectedValue={values.bonding_type}
onValueChange={(itemValue) => {
formikRef.current?.setFieldValue('bonding_type', Number(itemValue));
}}
style={styles.input}
>
{Object.keys(BondingType)
.filter((key) => isNaN(Number(key)))
.map((bonding) => (
<Picker.Item
key={bonding}
label={bonding}
value={BondingType[bonding as keyof typeof BondingType]}
/>
))}
</Picker>
</View>

<Button disabled={loading} variant="primary" onPress={() => onSubmitPress(TypeCreate.CREATE)}>
Create
{loading && type == TypeCreate.CREATE &&
<LoadingSpinner size={14} />
}
</Button>

<Button disabled={loading} variant="primary" onPress={() => onSubmitPress(TypeCreate.CREATE_AND_LAUNCH)}>
Create & Launch
{loading && type !== TypeCreate.CREATE &&
<LoadingSpinner size={14} />
}
</Button>

<View style={styles.gap} />
</View>
)}
</Formik>
</ScrollView>
);
};
5 changes: 4 additions & 1 deletion apps/mobile/src/modules/LaunchTokenPump/FormLaunchToken.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ export const FormLaunchToken: React.FC<FormTokenCreatedProps> = () => {
initialSupply: undefined,
contract_address_salt: new Date().getTime()?.toString(),
recipient: account?.address,
is_unruggable:false
is_unruggable:false,
creator_fee_percent: 0,
creator_fee_destination: account?.address,

};

const onSubmitPress = (type: TypeCreate) => {
Expand Down
3 changes: 2 additions & 1 deletion onchain/cairo/launchpad/src/launchpad/launchpad.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ pub mod LaunchpadMarketplace {
const SLIPPAGE_THRESHOLD: u256 = 100; //1%

// TODO Used in V2 and be choose by user
const ZERO_FEE_AMOUNT: u256 = 0; //1%
const MIN_FEE_CREATOR: u256 = 100; //1%
const MID_FEE_CREATOR: u256 = 1000; //10%
const MAX_FEE_CREATOR: u256 = 5000; //50%
Expand Down Expand Up @@ -1390,7 +1391,7 @@ pub mod LaunchpadMarketplace {
// let creator_fee_percent = self.creator_fee_percent.read();

assert(
creator_fee_percent <= MAX_FEE_CREATOR && creator_fee_percent >= MIN_FEE_CREATOR,
creator_fee_percent <= MAX_FEE_CREATOR && creator_fee_percent >= ZERO_FEE_AMOUNT,
errors::CREATOR_FEE_OUT_OF_BOUNDS
);

Expand Down
3 changes: 2 additions & 1 deletion packages/common/src/contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,9 @@ export const LAUNCHPAD_ADDRESS = {

// [constants.StarknetChainId.SN_SEPOLIA]:
// "0x2b4d93fc565381d1911f3f449f615de050b72d297fc95d89dda0301d7d35a37",
// [constants.StarknetChainId.SN_SEPOLIA]: "0x7fbf067657772a454c302354a19e07ce0a920736e2e3b7ca605d813723db883"
[constants.StarknetChainId.SN_SEPOLIA]: "0x7fbf067657772a454c302354a19e07ce0a920736e2e3b7ca605d813723db883"

// [constants.StarknetChainId.SN_SEPOLIA]: "0x1001bff43b6e171161be4d6c9025d0839caa745e199ccf720449cc5bf89166"
};

export const ESCROW_ADDRESS = {
Expand Down
Loading

0 comments on commit d84f613

Please sign in to comment.