Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion buffer-shim.js

This file was deleted.

19 changes: 9 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
"version": "2.0.0",
"description": "",
"scripts": {
"build": "rm -rf dist/ && node scripts/build.js",
"build": "rm -rf dist/ && node scripts/build.mjs",
"dev": "parcel serve parcel-build.html",
"gen:theme-typings": "chakra-cli tokens src/shared/theme/index.ts",
"postinstall": "yarn gen:theme-typings",
"deploy": "yarn build && node scripts/deploy.mjs"
"postinstall": "yarn gen:theme-typings"
},
"repository": {
"type": "git",
Expand All @@ -30,7 +29,7 @@
"@typescript-eslint/eslint-plugin": "^5.14.0",
"@typescript-eslint/parser": "^5.14.0",
"assert": "^2.0.0",
"esbuild": "^0.14.2",
"esbuild": "^0.15.6",
"eslint": "^8.9.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-import": "^2.25.2",
Expand All @@ -39,7 +38,7 @@
"eslint-plugin-react": "^7.29.3",
"eslint-plugin-react-hooks": "^4.3.0",
"follow-redirects": "^1.14.6",
"parcel": "^2.6.2",
"parcel": "^2.7.0",
"prettier": "^2.4.1",
"prettier-plugin-organize-imports": "^2.3.4",
"stream": "^0.0.2",
Expand All @@ -50,13 +49,13 @@
"@chakra-ui/react": "^2.1.0",
"@emotion/react": "^11",
"@emotion/styled": "^11",
"@thirdweb-dev/react": "^2.7.3-0",
"@thirdweb-dev/sdk": "^2.3.39",
"@thirdweb-dev/storage": "^0.1.0",
"@thirdweb-dev/react": "^3.0.5-nightly-b54f95d",
"@thirdweb-dev/sdk": "^3.0.5-nightly-b54f95d",
"@thirdweb-dev/storage": "^1.0.2-nightly-b54f95d",
"color": "^4.2.3",
"ethers": "^5.6.7",
"ethers": "^5.7.0",
"flat": "^5.0.2",
"framer-motion": "^6",
"framer-motion": "^7",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"react-icons": "^4.3.1"
Expand Down
13 changes: 8 additions & 5 deletions scripts/build.js → scripts/build.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const path = require("path");
const fs = require("fs");
import path from 'path';
import fs from 'fs';
import esbuild from 'esbuild';

const EMBEDS_SRC_PATH = path.resolve(process.cwd(), "src/embeds");
const DIST_PATH = path.resolve(process.cwd(), "dist/");
Expand All @@ -8,23 +9,25 @@ const files = fs.readdirSync(EMBEDS_SRC_PATH);

fs.rmSync(DIST_PATH, { recursive: true, force: true });

require("esbuild")
esbuild
.build({
jsx: 'automatic',
entryPoints: files.map((f) => path.resolve(EMBEDS_SRC_PATH, f)),
bundle: true,
minify: true,
platform: "browser",
target: "es6",
outdir: "./esout",


splitting: false,
write: false,
sourcemap: false,
define: {
global: "window",
process: JSON.stringify({
env: "production"
})
},
inject: ['./buffer-shim.js']
})
.then((result) => {
for (const file of result.outputFiles) {
Expand Down
144 changes: 61 additions & 83 deletions src/embeds/edition-drop.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {
Button,
Center,
ChakraProvider,
ColorMode,
Flex,
Grid,
Heading,
Expand All @@ -24,21 +24,18 @@ import {
ThirdwebProvider,
useActiveClaimCondition,
useAddress,
useChainId,
useClaimIneligibilityReasons,
useClaimNFT,
useEditionDrop,
useContract,
useNFT,
useTotalCirculatingSupply,
Web3Button,
} from "@thirdweb-dev/react";
import { EditionDrop } from "@thirdweb-dev/sdk";
import { IpfsStorage } from "@thirdweb-dev/storage";
import { SmartContract } from "@thirdweb-dev/sdk/dist/declarations/src/contracts/smart-contract";
import { ThirdwebStorage } from "@thirdweb-dev/storage";
import { BigNumber } from "ethers";
import { formatUnits, parseUnits } from "ethers/lib/utils";
import React, { useEffect, useMemo, useRef, useState } from "react";
import { createRoot } from "react-dom/client";
import { IoDiamondOutline } from "react-icons/io5";
import { ConnectWalletButton } from "../shared/connect-wallet-button";
import { Footer } from "../shared/footer";
import { Header } from "../shared/header";
import { DropSvg } from "../shared/svg/drop";
Expand All @@ -48,22 +45,19 @@ import { parseIneligibility } from "../utils/parseIneligibility";
import { parseIpfsGateway } from "../utils/parseIpfsGateway";

interface ClaimPageProps {
contract?: EditionDrop;
expectedChainId: number;
contract?: SmartContract | null;
tokenId: string;
primaryColor: string;
secondaryColor: string;
colorScheme: ColorMode;
}

const ClaimButton: React.FC<ClaimPageProps> = ({
contract,
expectedChainId,
tokenId,
primaryColor,
secondaryColor,
colorScheme,
}) => {
const address = useAddress();
const chainId = useChainId();
const [quantity, setQuantity] = useState(1);
const loaded = useRef(false);
const { data: totalSupply } = useTotalCirculatingSupply(contract, tokenId);
Expand All @@ -74,10 +68,6 @@ const ClaimButton: React.FC<ClaimPageProps> = ({
{ quantity, walletAddress: address || "" },
tokenId,
);
const claimMutation = useClaimNFT(contract);

const isEnabled = !!contract && !!address && chainId === expectedChainId;

const bnPrice = parseUnits(
activeClaimCondition.data?.currencyMetadata.displayValue || "0",
activeClaimCondition.data?.currencyMetadata.decimals,
Expand Down Expand Up @@ -116,51 +106,29 @@ const ClaimButton: React.FC<ClaimPageProps> = ({
isNaN(Number(availableSupply)) ? 1000 : Number(availableSupply),
);

const claim = async () => {
claimMutation.mutate(
{ to: address as string, tokenId, quantity },
{
onSuccess: () => {
toast({
title: "Successfully claimed.",
status: "success",
duration: 5000,
isClosable: true,
});
},
onError: (err) => {
console.error(err);
toast({
title: "Failed to claim drop.",
status: "error",
duration: 9000,
isClosable: true,
});
},
},
);
};

const isLoading = claimIneligibilityReasons.isLoading && !loaded.current;

const canClaim =
!isSoldOut && !!address && !claimIneligibilityReasons.data?.length;

if (!isEnabled) {
return (
<ConnectWalletButton
expectedChainId={expectedChainId}
primaryColor={primaryColor}
secondaryColor={secondaryColor}
/>
);
if (!contract) {
return null;
}

const maxQuantity = activeClaimCondition.data?.maxQuantity;

const colors = chakraTheme.colors;
const accentColor = colors[primaryColor as keyof typeof colors][500];

return (
<Stack spacing={4} align="center" w="100%">
<Flex w="100%" direction={{ base: "column", sm: "row" }} gap={2}>
<Flex
w="100%"
direction={{ base: "column", sm: "row" }}
gap={2}
justifyContent="center"
alignItems="center"
>
<NumberInput
inputMode="numeric"
value={quantity}
Expand All @@ -183,14 +151,29 @@ const ClaimButton: React.FC<ClaimPageProps> = ({
</NumberInputStepper>
</NumberInput>
<LightMode>
<Button
isLoading={isLoading || claimMutation.isLoading}
isDisabled={!canClaim}
leftIcon={<IoDiamondOutline />}
onClick={claim}
w="full"
colorScheme={primaryColor}
fontSize={{ base: "label.md", md: "label.lg" }}
<Web3Button
colorMode={colorScheme}
contractAddress={contract?.getAddress()}
isDisabled={!canClaim || isLoading}
action={(cntr) => cntr.erc1155.claim(tokenId, quantity)}
accentColor={accentColor}
onError={(err) => {
console.error(err);
toast({
title: "Failed to claim drop.",
status: "error",
duration: 9000,
isClosable: true,
});
}}
onSuccess={() => {
toast({
title: "Successfully claimed.",
status: "success",
duration: 5000,
isClosable: true,
});
}}
>
{isSoldOut
? "Sold out"
Expand All @@ -208,7 +191,7 @@ const ClaimButton: React.FC<ClaimPageProps> = ({
: claimIneligibilityReasons.data?.length
? parseIneligibility(claimIneligibilityReasons.data, quantity)
: "Minting Unavailable"}
</Button>
</Web3Button>
</LightMode>
</Flex>
{activeClaimCondition.data && (
Expand All @@ -228,10 +211,9 @@ const ClaimButton: React.FC<ClaimPageProps> = ({

const ClaimPage: React.FC<ClaimPageProps> = ({
contract,
expectedChainId,
tokenId,
primaryColor,
secondaryColor,
colorScheme,
}) => {
const tokenMetadata = useNFT(contract, tokenId);

Expand Down Expand Up @@ -283,9 +265,8 @@ const ClaimPage: React.FC<ClaimPageProps> = ({
<ClaimButton
contract={contract}
tokenId={tokenId}
expectedChainId={expectedChainId}
primaryColor={primaryColor}
secondaryColor={secondaryColor}
colorScheme={colorScheme}
/>
</Flex>
</Center>
Expand All @@ -307,22 +288,18 @@ const Body: React.FC<BodyProps> = ({ children }) => {
interface EditionDropEmbedProps {
contractAddress: string;
tokenId: string;
expectedChainId: number;
colorScheme: string;
colorScheme: ColorMode;
primaryColor: string;
secondaryColor: string;
}

const EditionDropEmbed: React.FC<EditionDropEmbedProps> = ({
contractAddress,
tokenId,
expectedChainId,
colorScheme,
primaryColor,
secondaryColor,
}) => {
const { setColorMode } = useColorMode();
const editionDrop = useEditionDrop(contractAddress);
const { contract: editionDrop } = useContract(contractAddress);

useEffect(() => {
setColorMode(colorScheme);
Expand All @@ -348,9 +325,8 @@ const EditionDropEmbed: React.FC<EditionDropEmbedProps> = ({
<ClaimPage
contract={editionDrop}
tokenId={tokenId}
expectedChainId={expectedChainId}
primaryColor={primaryColor}
secondaryColor={secondaryColor}
colorScheme={colorScheme}
/>
</Body>
<Footer />
Expand All @@ -361,18 +337,16 @@ const EditionDropEmbed: React.FC<EditionDropEmbedProps> = ({
const urlParams = new URL(window.location.toString()).searchParams;

const App: React.FC = () => {
const expectedChainId = Number(urlParams.get("chainId"));
const chainId = Number(urlParams.get("chainId"));
const contractAddress = urlParams.get("contract") || "";
// default to expectedChainId default
const rpcUrl = urlParams.get("rpcUrl") || "";
const tokenId = urlParams.get("tokenId") || "0";
const relayerUrl = urlParams.get("relayUrl") || "";

const ipfsGateway = parseIpfsGateway(urlParams.get("ipfsGateway") || "");

const colorScheme = urlParams.get("theme") || "light";
const primaryColor = urlParams.get("primaryColor") || "blue";
const secondaryColor = urlParams.get("secondaryColor") || "orange";
const colorScheme = urlParams.get("theme") === "dark" ? "dark" : "light";
const primaryColor = urlParams.get("primaryColor") || "purple";

const sdkOptions = useMemo(
() =>
Expand All @@ -398,20 +372,24 @@ const App: React.FC = () => {
/>
<ChakraProvider theme={chakraTheme}>
<ThirdwebProvider
desiredChainId={expectedChainId}
desiredChainId={chainId}
sdkOptions={sdkOptions}
storageInterface={
ipfsGateway ? new IpfsStorage(ipfsGateway) : undefined
ipfsGateway
? new ThirdwebStorage({
gatewayUrls: {
"ipfs://": [ipfsGateway],
},
})
: undefined
}
chainRpc={{ [expectedChainId]: rpcUrl }}
chainRpc={{ [chainId]: rpcUrl }}
>
<EditionDropEmbed
contractAddress={contractAddress}
tokenId={tokenId}
expectedChainId={expectedChainId}
colorScheme={colorScheme}
primaryColor={primaryColor}
secondaryColor={secondaryColor}
/>
</ThirdwebProvider>
</ChakraProvider>
Expand Down
Loading