Skip to content

Commit

Permalink
fix: complete launchpad create collection
Browse files Browse the repository at this point in the history
  • Loading branch information
WaDadidou committed Mar 27, 2024
1 parent a5f84c5 commit c396913
Show file tree
Hide file tree
Showing 26 changed files with 808 additions and 570 deletions.
2 changes: 1 addition & 1 deletion packages/components/inputs/SelectInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import { SpacerColumn, SpacerRow } from "../spacer";

export type SelectInputItem = {
label: string;
value: string;
value: string | boolean;
iconComponent?: ReactElement;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { LocalFileData } from "../../utils/types/files";

export interface SelectFileUploaderProps {
onUpload: (files: LocalFileData[]) => void;
files?: LocalFileData[];
label?: string;
style?: StyleProp<ViewStyle>;
isImageCover?: boolean;
Expand Down
24 changes: 14 additions & 10 deletions packages/components/selectFileUploader/SelectFileUploader.web.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const SelectFileUploader: FC<SelectFileUploaderProps> = ({
label,
style,
onUpload,
files,
// multiple is not used at true for now, needs to refactor in parents
multiple,
mimeTypes,
Expand All @@ -37,7 +38,8 @@ export const SelectFileUploader: FC<SelectFileUploaderProps> = ({
}) => {
const { setToastError } = useFeedbacks();
const hiddenFileInput = useRef<HTMLInputElement>(null);
const [files, setFiles] = useState<LocalFileData[]>([]);
const [localFiles, setLocalFiles] = useState<LocalFileData[]>([]);
const filesToUse = (!localFiles.length ? files : localFiles) || [];

const handleFiles = async (files: File[]) => {
const _files = multiple ? files : [files[0]];
Expand All @@ -64,7 +66,7 @@ export const SelectFileUploader: FC<SelectFileUploaderProps> = ({

const formattedFiles = await Promise.all(supportedFiles.map(formatFile));

setFiles(formattedFiles);
setLocalFiles(formattedFiles);
onUpload(formattedFiles);
};

Expand Down Expand Up @@ -142,21 +144,23 @@ export const SelectFileUploader: FC<SelectFileUploaderProps> = ({
alignItems: "center",
justifyContent: "center",
height:
files.length > 0 && !multiple ? fileHeight : containerHeight,
filesToUse.length > 0 && !multiple
? fileHeight
: containerHeight,
borderRadius: 12,
}}
>
{files.length > 0 && !multiple ? (
{filesToUse.length > 0 && !multiple ? (
<>
<DeleteButton
onPress={() => {
setFiles([]);
setLocalFiles([]);
onUpload([]);
}}
style={{ top: 12, right: 12 }}
/>
<Image
source={{ uri: URL.createObjectURL(files[0].file) }}
source={{ uri: URL.createObjectURL(filesToUse[0].file) }}
style={{
overflow: "hidden",
height: fileHeight,
Expand All @@ -171,7 +175,7 @@ export const SelectFileUploader: FC<SelectFileUploaderProps> = ({
flex: 1,
width: "100%",
height:
files.length > 0 && !multiple
filesToUse.length > 0 && !multiple
? fileHeight
: containerHeight,
alignItems: "center",
Expand All @@ -180,7 +184,7 @@ export const SelectFileUploader: FC<SelectFileUploaderProps> = ({
borderWidth: 1,
}}
>
{files.length > 0 && multiple ? (
{filesToUse.length > 0 && multiple ? (
<View
style={{
height: "100%",
Expand All @@ -206,7 +210,7 @@ export const SelectFileUploader: FC<SelectFileUploaderProps> = ({
<BrandText
style={[fontSemibold14, { color: secondaryColor }]}
>
{files.length} files selected
{filesToUse.length} files selected
</BrandText>
</View>
<input
Expand Down Expand Up @@ -249,7 +253,7 @@ export const SelectFileUploader: FC<SelectFileUploaderProps> = ({
<BrandText
style={[fontSemibold14, { color: primaryColor }]}
>
Select files
{`Select file${multiple ? "s" : ""}`}
</BrandText>
</View>
<input
Expand Down
141 changes: 141 additions & 0 deletions packages/hooks/launchpad/useCreateCollection.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import { useCallback } from "react";
import { useSelector } from "react-redux";

import { NftLaunchpadClient } from "@/contracts-clients/nft-launchpad";
import { PinataFileProps, useIpfs } from "@/hooks/useIpfs";
import useSelectedWallet from "@/hooks/useSelectedWallet";
import {
getNetworkFeature,
mustGetCosmosNetwork,
NetworkFeature,
} from "@/networks";
import { getKeplrSigningCosmWasmClient } from "@/networks/signer";
import { CreateCollectionFormValues } from "@/screens/Launchpad/CreateCollection.type";

Check failure on line 13 in packages/hooks/launchpad/useCreateCollection.ts

View workflow job for this annotation

GitHub Actions / lint-and-build

'@/screens/Launchpad/CreateCollection.type' import is restricted from being used by a pattern. Screens imports are only allowed in navigation and other screens
import { selectNFTStorageAPI } from "@/store/slices/settings";
import { generateIpfsKey } from "@/utils/ipfs";

export const useCreateCollection = () => {
const selectedWallet = useSelectedWallet();
const userIPFSKey = useSelector(selectNFTStorageAPI);
const { pinataPinFileToIPFS } = useIpfs();

return useCallback(
async (collectionFormValues: CreateCollectionFormValues) => {
if (!selectedWallet) return;

const network = mustGetCosmosNetwork(selectedWallet.networkId);

const signingComswasmClient = await getKeplrSigningCosmWasmClient(
network.id,
);
const cosmwasmLaunchpadFeature = getNetworkFeature(
network.id,
NetworkFeature.NFTLaunchpad,
);

if (!cosmwasmLaunchpadFeature) return;

const client = new NftLaunchpadClient(
signingComswasmClient,
selectedWallet.address,
cosmwasmLaunchpadFeature.launchpadContractAddress,
);

try {
const pinataJWTKey =
userIPFSKey ||
(await generateIpfsKey(network.id, selectedWallet.userId));
if (!pinataJWTKey) {
console.error("upload file err : No Pinata JWT");
// setToastError({
// title: "File upload failed",
// message: "No Pinata JWT",
// });
return;
}
const fileIpfsHash = await pinataPinFileToIPFS({
pinataJWTKey,
file: collectionFormValues.coverImage,
} as PinataFileProps);

client.submitCollection({
collection: {
name: collectionFormValues.name || "",
desc: collectionFormValues.description || "",
symbol: collectionFormValues.symbol || "",
external_link: collectionFormValues.externalLink || "",

website_link: collectionFormValues.websiteLink || "",
twitter_profile: collectionFormValues.twitterProfileUrl || "",
twitter_followers_count:
collectionFormValues.nbTwitterFollowers || 0,
contact_discord_name: collectionFormValues.discordName || "",
contact_email: collectionFormValues.email || "",
project_type: collectionFormValues.projectTypes?.join() || "",
project_desc: collectionFormValues.projectDescription || "",

tokens_count: collectionFormValues.nbTokens || 0,
unit_price: collectionFormValues.unitPrice || "",
limit_per_address: collectionFormValues.perAddressLimit || 0,
start_time: collectionFormValues.startTime || 0,

team_desc: collectionFormValues.teamDescription || "",
team_link: collectionFormValues.teamLink || "",
partners: collectionFormValues.partnersDescription || "",

investment_desc: collectionFormValues.investDescription || "",
investment_link: collectionFormValues.investLink || "",
roadmap_link: collectionFormValues.roadmapLink || "",

artwork_desc: collectionFormValues.artworkDescription || "",
expected_supply: collectionFormValues.expectedSupply || 0,
expected_public_mint_price:
collectionFormValues.expectedPublicMintPrice || 0,
expected_mint_date: collectionFormValues.expectedMintDate || 0,

// TODO:
// nftApiKey: collectionFormValues.nftApiKey || "",

cover_img_uri: fileIpfsHash || "",
is_applied_previously:
collectionFormValues.isPreviouslyApplied || false,
is_project_derivative:
collectionFormValues.isDerivativeProject || false,
is_ready_for_mint: collectionFormValues.isReadyForMint || false,
is_dox: collectionFormValues.isDox || false,
escrow_mint_proceeds_period:
collectionFormValues.escrowMintProceedsPeriod || 0,
dao_whitelist_count: collectionFormValues.daoWhitelistCount || 0,

// TODO: collection of whitelists

whitelist_mint_infos: [],

royalty_address: collectionFormValues.royaltyAddress || "",
royalty_percentage: collectionFormValues.royaltyPercentage || 0,

target_network: network.id,
denom: cosmwasmLaunchpadFeature.defaultMintDenom,
deployed_address: "None",
merkle_root: "None",
whitepaper_link: "None",
base_token_uri: "None",
},
});

// const amount = await tnsClient.mintPrice({ tokenId });
// return {
// denom: info.native_denom,
// amount: amount?.toString() || "0",
// invalid: false,
// };
} catch (e) {

Check failure on line 132 in packages/hooks/launchpad/useCreateCollection.ts

View workflow job for this annotation

GitHub Actions / lint-and-build

'e' is defined but never used
// if (e instanceof Error && e.message.includes("Token Name Invalid")) {
// return { denom: info.native_denom, amount: "0", invalid: true };
// }
// throw e;
}
},
[],

Check failure on line 139 in packages/hooks/launchpad/useCreateCollection.ts

View workflow job for this annotation

GitHub Actions / lint-and-build

React Hook useCallback has missing dependencies: 'pinataPinFileToIPFS', 'selectedWallet', and 'userIPFSKey'. Either include them or remove the dependency array
);
};
16 changes: 14 additions & 2 deletions packages/networks/features.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,18 @@ type CosmWasmSocialFeed = {
feedContractAddress: string;
};

export const allFeatureObjects = [zodCosmWasmPremiumFeed];
const zodCosmWasmLaunchpad = z.object({
type: z.literal(NetworkFeature.NFTLaunchpad),
launchpadContractAddress: z.string(),
defaultMintDenom: z.string(),
// allowedMintDenoms: z.array(z.string()), // for future
});

export type CosmWasmLaunchpad = z.infer<typeof zodCosmWasmLaunchpad>;

export const allFeatureObjects = [zodCosmWasmPremiumFeed, zodCosmWasmLaunchpad];

export type NetworkFeatureObject = CosmWasmPremiumFeed | CosmWasmSocialFeed;
export type NetworkFeatureObject =
| CosmWasmPremiumFeed
| CosmWasmSocialFeed
| CosmWasmLaunchpad;
15 changes: 12 additions & 3 deletions packages/networks/teritori-testnet/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { teritoriTestnetCurrencies } from "./currencies";
import { CosmWasmPremiumFeed, NetworkFeature } from "../features";
import {
CosmWasmLaunchpad,
CosmWasmPremiumFeed,
NetworkFeature,
} from "../features";
import { NetworkInfo, NetworkKind } from "../types";

const nameServiceContractAddress =
Expand All @@ -12,7 +16,12 @@ const premiumFeedFeature: CosmWasmPremiumFeed = {
mintDenom: "utori",
};

const launchpadContractAddress = "tori164jjtp4c032arq30dzpgn2uujwavm777ug7we5evlvf0c26007jqetqdv3";
const cosmwasmLaunchpadFeature: CosmWasmLaunchpad = {
type: NetworkFeature.NFTLaunchpad,
launchpadContractAddress:
"tori164jjtp4c032arq30dzpgn2uujwavm777ug7we5evlvf0c26007jqetqdv3",
defaultMintDenom: "utori",
};

const riotContractAddressGen0 =
"tori1hzz0s0ucrhdp6tue2lxk3c03nj6f60qy463we7lgx0wudd72ctmstg4wkc";
Expand All @@ -37,7 +46,7 @@ export const teritoriTestnetNetwork: NetworkInfo = {
NetworkFeature.CosmWasmPremiumFeed,
NetworkFeature.NFTMarketplaceLeaderboard,
],
featureObjects: [premiumFeedFeature],
featureObjects: [premiumFeedFeature, cosmwasmLaunchpadFeature],
currencies: teritoriTestnetCurrencies,
txExplorer: "https://explorer.teritori.com/teritori-testnet/tx/$hash",
accountExplorer:
Expand Down
1 change: 1 addition & 0 deletions packages/networks/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export type CosmosNetworkInfo = NetworkInfoBase & {
daoVotingCw4CodeId?: number;
daoFactoryContractAddress?: string;
coreDAOAddress?: string;
launchpadContractAddress?: string;
};

export type EthereumNetworkInfo = NetworkInfoBase & {
Expand Down
Loading

0 comments on commit c396913

Please sign in to comment.