diff --git a/.gitignore b/.gitignore index da54f5cc..6eebde39 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ /node_modules /.pnp .pnp.js +bun.lockb # testing /coverage diff --git a/components/UI/backButton.tsx b/components/UI/backButton.tsx new file mode 100644 index 00000000..0b91322d --- /dev/null +++ b/components/UI/backButton.tsx @@ -0,0 +1,17 @@ +import React, { FunctionComponent } from "react"; +import styles from "../../styles/components/backButton.module.css"; +import ArrowLeftIcon from "./iconsComponents/icons/arrowLeftIcon"; +import theme from "../../styles/theme"; + +type BackButtonProps = { + onClick: () => void; +}; + +const BackButton: FunctionComponent = ({ onClick }) => ( + +); + +export default BackButton; diff --git a/components/UI/inputHelper.tsx b/components/UI/inputHelper.tsx new file mode 100644 index 00000000..ad69c7fc --- /dev/null +++ b/components/UI/inputHelper.tsx @@ -0,0 +1,45 @@ +import React, { FunctionComponent, ReactNode } from "react"; +import { Tooltip, TooltipProps, styled, tooltipClasses } from "@mui/material"; +import InfoIcon from "./iconsComponents/icons/infoIcon"; + +type InputHelperProps = { + children: ReactNode; + helperText?: string; + error?: boolean; +}; + +const StyledToolTip = styled(({ className, ...props }: TooltipProps) => ( + +))(() => ({ + [`& .${tooltipClasses.arrow}`]: { + color: "#454545", + }, + [`& .${tooltipClasses.tooltip}`]: { + backgroundColor: "#454545", + }, +})); + +const InputHelper: FunctionComponent = ({ + children, + helperText, + error = false, +}) => { + return ( +
+ {children} + {helperText ? ( + +
+ +
+
+ ) : null} +
+ ); +}; + +export default InputHelper; diff --git a/components/UI/navbar.tsx b/components/UI/navbar.tsx index dd49e6f0..a76ccced 100644 --- a/components/UI/navbar.tsx +++ b/components/UI/navbar.tsx @@ -137,7 +137,7 @@ const Navbar: FunctionComponent = () => { return ( <> -
+
diff --git a/components/UI/textField.tsx b/components/UI/textField.tsx index 02eb9da5..1c888445 100644 --- a/components/UI/textField.tsx +++ b/components/UI/textField.tsx @@ -1,8 +1,8 @@ import React, { FunctionComponent } from "react"; import styles from "../../styles/components/textField.module.css"; -import { OutlinedInputProps, Tooltip } from "@mui/material"; -import InfoIcon from "./iconsComponents/icons/infoIcon"; +import { OutlinedInputProps } from "@mui/material"; import { TextField as TextFieldMui } from "@mui/material"; +import InputHelper from "./inputHelper"; type TextFieldProps = { label: string; @@ -32,17 +32,6 @@ const TextField: FunctionComponent = ({ return (
- {helperText ? ( - -
- -
-
- ) : null} {error ? (

{errorMessage}

) : ( @@ -50,23 +39,24 @@ const TextField: FunctionComponent = ({ )} {required ? "*" : ""}
- - + + +
); }; diff --git a/components/discount/discountEndScreen.tsx b/components/discount/discountEndScreen.tsx index 63b03d0b..e2bea967 100644 --- a/components/discount/discountEndScreen.tsx +++ b/components/discount/discountEndScreen.tsx @@ -1,5 +1,6 @@ import React, { FunctionComponent } from "react"; import styles from "../../styles/discount.module.css"; +import homeStyles from "../../styles/Home.module.css"; type DiscountEndScreenProps = { image: string; @@ -11,9 +12,11 @@ const DiscountEndScreen: FunctionComponent = ({ title, }) => { return ( -
- -

{title}

+
+
+ +

{title}

+
); }; diff --git a/components/discount/registerDiscount.tsx b/components/discount/registerDiscount.tsx index f04d237b..f2dc4d23 100644 --- a/components/discount/registerDiscount.tsx +++ b/components/discount/registerDiscount.tsx @@ -27,7 +27,7 @@ import RegisterCheckboxes from "../domains/registerCheckboxes"; import RegisterSummary from "../domains/registerSummary"; import salesTax from "sales-tax"; import Wallets from "../UI/wallets"; -import registerCalls from "../../utils/registerCalls"; +import registrationCalls from "../../utils/callData/registrationCalls"; import UsForm from "../domains/usForm"; import { computeMetadataHash, generateSalt } from "../../utils/userDataService"; import ArrowLeftIcon from "../UI/iconsComponents/icons/arrows/arrowLeftIcon"; @@ -83,7 +83,7 @@ const RegisterDiscount: FunctionComponent = ({ }); const { writeAsync: execute, data: registerData } = useContractWrite({ // calls: renewalBox - // ? callData.concat(registerCalls.renewal(encodedDomain, price)) + // ? callData.concat(registrationCalls.renewal(encodedDomain, price)) // : callData, calls: callData, }); @@ -161,9 +161,9 @@ const RegisterDiscount: FunctionComponent = ({ hexToDecimal(address) === hexToDecimal(targetAddress); // Common calls const calls = [ - registerCalls.mint(newTokenId), - registerCalls.approve(price), - registerCalls.buy_discounted( + registrationCalls.mint(newTokenId), + registrationCalls.approve(price), + registrationCalls.buy_discounted( encodedDomain, newTokenId, targetAddress, @@ -175,12 +175,12 @@ const RegisterDiscount: FunctionComponent = ({ // If the user is a US resident, we add the sales tax if (salesTaxRate) { - calls.unshift(registerCalls.vatTransfer(salesTaxAmount)); // IMPORTANT: We use unshift to put the call at the beginning of the array + calls.unshift(registrationCalls.vatTransfer(salesTaxAmount)); // IMPORTANT: We use unshift to put the call at the beginning of the array } // If the user do not have a main domain and the address match if (addressesMatch && !hasMainDomain) { - calls.push(registerCalls.addressToDomain(encodedDomain)); + calls.push(registrationCalls.addressToDomain(encodedDomain)); } // Merge and set the call data @@ -198,7 +198,7 @@ const RegisterDiscount: FunctionComponent = ({ useEffect(() => { if (!registerData?.transaction_hash) return; - posthog?.capture("register", { onForceEmail }); + posthog?.capture("register"); // register the metadata to the sales manager db fetch(`${process.env.NEXT_PUBLIC_SALES_SERVER_LINK}/add_metadata`, { @@ -236,22 +236,6 @@ const RegisterDiscount: FunctionComponent = ({ } }, [isUsResident, usState, price]); - // AB Testing - const [onForceEmail, setOnForceEmail] = useState(); - useEffect(() => { - posthog.onFeatureFlags(function () { - // feature flags should be available at this point - if ( - posthog.getFeatureFlag("onforceEmail") == "test" || - process.env.NEXT_PUBLIC_IS_TESTNET === "true" - ) { - setOnForceEmail(true); - } else { - setOnForceEmail(false); - } - }); - }, []); - return (
@@ -266,7 +250,7 @@ const RegisterDiscount: FunctionComponent = ({
changeEmail(e.target.value)} diff --git a/components/domains/domainMenu.tsx b/components/domains/domainMenu.tsx deleted file mode 100644 index fcbc27a7..00000000 --- a/components/domains/domainMenu.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import React, { FunctionComponent, useState } from "react"; -import Details from "./details"; -import DomainTabs from "./domainTabs"; -import Register from "./register"; - -type DomainMenuProps = { - domain: string; - isAvailable?: boolean; -}; - -const DomainMenu: FunctionComponent = ({ - domain, - isAvailable, -}) => { - const [tab, setTab] = useState("one"); - - function changeTab(tab: string): void { - setTab(tab); - } - - return ( -
- -
- {tab == "one" && } - {tab == "two" &&
} -
-
- ); -}; - -export default DomainMenu; diff --git a/components/domains/register.tsx b/components/domains/register.tsx deleted file mode 100644 index abce77d5..00000000 --- a/components/domains/register.tsx +++ /dev/null @@ -1,367 +0,0 @@ -import React from "react"; -import { TextField } from "@mui/material"; -import { FunctionComponent, useEffect, useState } from "react"; -import Button from "../UI/button"; -import styles from "../../styles/Home.module.css"; -import { useEtherContract, usePricingContract } from "../../hooks/contracts"; -import { - useAccount, - useContractRead, - useContractWrite, - useTransactionManager, -} from "@starknet-react/core"; -import { utils } from "starknetid.js"; -import { isHexString, numberToString } from "../../utils/stringService"; -import { gweiToEth, hexToDecimal } from "../../utils/feltService"; -import SelectIdentity from "./selectIdentity"; -import { useDisplayName } from "../../hooks/displayName.tsx"; -import { Abi, Call } from "starknet"; -import TxConfirmationModal from "../UI/txConfirmationModal"; - -type RegisterProps = { - domain: string; - isAvailable?: boolean; -}; - -const Register: FunctionComponent = ({ - domain, - isAvailable, -}) => { - const maxYearsToRegister = 25; - const [targetAddress, setTargetAddress] = useState(""); - const [duration, setDuration] = useState(3); - const [tokenId, setTokenId] = useState(0); - const [callData, setCallData] = useState([]); - const [price, setPrice] = useState("0"); - const [balance, setBalance] = useState("0"); - const [invalidBalance, setInvalidBalance] = useState(false); - const { contract } = usePricingContract(); - const { contract: etherContract } = useEtherContract(); - const [isTxModalOpen, setIsTxModalOpen] = useState(false); - const encodedDomain = utils - .encodeDomain(domain) - .map((element) => element.toString())[0]; - const { data: priceData, error: priceError } = useContractRead({ - address: contract?.address as string, - abi: contract?.abi as Abi, - functionName: "compute_buy_price", - args: [encodedDomain, duration * 365], - }); - const { account, address } = useAccount(); - const { data: userBalanceData, error: userBalanceDataError } = - useContractRead({ - address: etherContract?.address as string, - abi: etherContract?.abi as Abi, - functionName: "balanceOf", - args: [address], - }); - const { writeAsync: execute, data: registerData } = useContractWrite({ - calls: callData, - }); - const hasMainDomain = !useDisplayName(address ?? "", false).startsWith("0x"); - const [domainsMinting, setDomainsMinting] = useState>( - new Map() - ); - const { addTransaction } = useTransactionManager(); - const [sponsor, setSponsor] = useState("0"); - - useEffect(() => { - if (priceError || !priceData) setPrice("0"); - else { - const high = priceData?.["price"].high << BigInt(128); - setPrice((priceData?.["price"].low + high).toString(10)); - } - }, [priceData, priceError]); - - useEffect(() => { - if (userBalanceDataError || !userBalanceData) setBalance("0"); - else { - const high = userBalanceData?.["balance"].high << BigInt(128); - setBalance((userBalanceData?.["balance"].low + high).toString(10)); - } - }, [userBalanceData, userBalanceDataError]); - - useEffect(() => { - if (balance && price) { - if (gweiToEth(balance) > gweiToEth(price)) { - setInvalidBalance(false); - } else { - setInvalidBalance(true); - } - } - }, [balance, price]); - - useEffect(() => { - if (address) { - setTargetAddress(address); - } - }, [address]); - - useEffect(() => { - const referralData = localStorage.getItem("referralData"); - if (referralData) { - const data = JSON.parse(referralData); - if (data.sponsor && data?.expiry >= new Date().getTime()) { - setSponsor(data.sponsor); - } else { - setSponsor("0"); - } - } else { - setSponsor("0"); - } - }, [domain]); - - // Set mulitcalls - useEffect(() => { - if (!isAvailable) return; - const newTokenId: number = Math.floor(Math.random() * 1000000000000); - - if ( - tokenId != 0 && - !hasMainDomain && - hexToDecimal(address) === hexToDecimal(targetAddress) - ) { - setCallData([ - { - contractAddress: process.env.NEXT_PUBLIC_ETHER_CONTRACT as string, - entrypoint: "approve", - calldata: [ - process.env.NEXT_PUBLIC_NAMING_CONTRACT as string, - price, - 0, - ], - }, - { - contractAddress: process.env.NEXT_PUBLIC_NAMING_CONTRACT as string, - entrypoint: "buy", - calldata: [ - numberToString(tokenId), - encodedDomain, - numberToString(duration * 365), - 0, - hexToDecimal(targetAddress), - sponsor, - ], - }, - { - contractAddress: process.env.NEXT_PUBLIC_NAMING_CONTRACT as string, - entrypoint: "set_address_to_domain", - calldata: [1, encodedDomain], - }, - ]); - } else if ( - (tokenId != 0 && hasMainDomain) || - (tokenId != 0 && - !hasMainDomain && - hexToDecimal(address) != hexToDecimal(targetAddress)) - ) { - setCallData([ - { - contractAddress: process.env.NEXT_PUBLIC_ETHER_CONTRACT as string, - entrypoint: "approve", - calldata: [ - process.env.NEXT_PUBLIC_NAMING_CONTRACT as string, - price, - 0, - ], - }, - { - contractAddress: process.env.NEXT_PUBLIC_NAMING_CONTRACT as string, - entrypoint: "buy", - calldata: [ - numberToString(tokenId), - encodedDomain, - numberToString(duration * 365), - 0, - hexToDecimal(targetAddress), - sponsor, - ], - }, - ]); - } else if ( - tokenId === 0 && - !hasMainDomain && - hexToDecimal(address) === hexToDecimal(targetAddress) - ) { - setCallData([ - { - contractAddress: process.env.NEXT_PUBLIC_ETHER_CONTRACT as string, - entrypoint: "approve", - calldata: [ - process.env.NEXT_PUBLIC_NAMING_CONTRACT as string, - price, - 0, - ], - }, - { - contractAddress: process.env - .NEXT_PUBLIC_STARKNETID_CONTRACT as string, - entrypoint: "mint", - calldata: [numberToString(newTokenId)], - }, - { - contractAddress: process.env.NEXT_PUBLIC_NAMING_CONTRACT as string, - entrypoint: "buy", - calldata: [ - numberToString(newTokenId), - encodedDomain, - numberToString(duration * 365), - 0, - hexToDecimal(targetAddress), - sponsor, - ], - }, - { - contractAddress: process.env.NEXT_PUBLIC_NAMING_CONTRACT as string, - entrypoint: "set_address_to_domain", - calldata: [1, encodedDomain], - }, - ]); - } else if ( - (tokenId === 0 && hasMainDomain) || - (tokenId === 0 && - !hasMainDomain && - hexToDecimal(address) != hexToDecimal(targetAddress)) - ) { - setCallData([ - { - contractAddress: process.env.NEXT_PUBLIC_ETHER_CONTRACT as string, - entrypoint: "approve", - calldata: [ - process.env.NEXT_PUBLIC_NAMING_CONTRACT as string, - price, - 0, - ], - }, - { - contractAddress: process.env - .NEXT_PUBLIC_STARKNETID_CONTRACT as string, - entrypoint: "mint", - calldata: [numberToString(newTokenId)], - }, - { - contractAddress: process.env.NEXT_PUBLIC_NAMING_CONTRACT as string, - entrypoint: "buy", - calldata: [ - numberToString(newTokenId), - encodedDomain, - numberToString(duration * 365), - 0, - hexToDecimal(targetAddress), - sponsor, - ], - }, - ]); - } - }, [ - tokenId, - duration, - targetAddress, - isAvailable, - price, - domain, - hasMainDomain, - address, - sponsor, - ]); - - useEffect(() => { - if (!registerData?.transaction_hash) return; - addTransaction({ hash: registerData?.transaction_hash ?? "" }); - setIsTxModalOpen(true); - }, [registerData]); - - function changeAddress(value: string): void { - isHexString(value) ? setTargetAddress(value) : null; - } - - function changeDuration(value: number): void { - setDuration(value); - } - - function changeTokenId(value: number): void { - setTokenId(Number(value)); - } - - if (isAvailable) - return ( -
-
-
- changeAddress(e.target.value)} - color="secondary" - required - /> -
-
- changeDuration(Number(e.target.value))} - InputProps={{ - inputProps: { min: 0, max: maxYearsToRegister }, - }} - defaultValue={duration} - color="secondary" - required - /> -
-
- -
-

- Price:  - - {gweiToEth(price)} ETH - -

-
-
-
- -
-
- setIsTxModalOpen(false)} - title="Your domain is on it's way !" - /> -
- ); - - return

This domain is not available you can’t register it

; -}; - -export default Register; diff --git a/components/domains/registerCheckboxes.tsx b/components/domains/registerCheckboxes.tsx index 8d7a809c..028aedf1 100644 --- a/components/domains/registerCheckboxes.tsx +++ b/components/domains/registerCheckboxes.tsx @@ -45,15 +45,17 @@ const RegisterCheckboxes: FunctionComponent = ({

-
- -

- Enable auto-renewal and don't pay gas for your yearly renewal -

-
+ {onChangeRenewalBox ? ( +
+ +

+ Enable auto-renewal and don't pay gas for your yearly renewal +

+
+ ) : null}
); diff --git a/components/domains/registerV2.tsx b/components/domains/registerV2.tsx index 8fd865b3..ab8485e6 100644 --- a/components/domains/registerV2.tsx +++ b/components/domains/registerV2.tsx @@ -33,7 +33,7 @@ import NumberTextField from "../UI/numberTextField"; import RegisterSummary from "./registerSummary"; import salesTax from "sales-tax"; import Wallets from "../UI/wallets"; -import registerCalls from "../../utils/registerCalls"; +import registrationCalls from "../../utils/callData/registrationCalls"; import { computeMetadataHash, generateSalt } from "../../utils/userDataService"; import { getPriceFromDomain } from "../../utils/priceService"; @@ -87,7 +87,7 @@ const RegisterV2: FunctionComponent = ({ domain, groups }) => { }); const { writeAsync: execute, data: registerData } = useContractWrite({ // calls: renewalBox - // ? callData.concat(registerCalls.renewal(encodedDomain, price)) + // ? callData.concat(registrationCalls.renewal(encodedDomain, price)) // : callData, calls: callData, }); @@ -176,8 +176,8 @@ const RegisterV2: FunctionComponent = ({ domain, groups }) => { // Common calls const calls = [ - registerCalls.approve(price), - registerCalls.buy( + registrationCalls.approve(price), + registrationCalls.buy( encodedDomain, tokenId === 0 ? newTokenId : tokenId, targetAddress, @@ -189,17 +189,17 @@ const RegisterV2: FunctionComponent = ({ domain, groups }) => { // If the user is a US resident, we add the sales tax if (salesTaxRate) { - calls.unshift(registerCalls.vatTransfer(salesTaxAmount)); // IMPORTANT: We use unshift to put the call at the beginning of the array + calls.unshift(registrationCalls.vatTransfer(salesTaxAmount)); // IMPORTANT: We use unshift to put the call at the beginning of the array } // If the user choose to mint a new identity if (tokenId === 0) { - calls.unshift(registerCalls.mint(newTokenId)); // IMPORTANT: We use unshift to put the call at the beginning of the array + calls.unshift(registrationCalls.mint(newTokenId)); // IMPORTANT: We use unshift to put the call at the beginning of the array } // If the user do not have a main domain and the address match if (addressesMatch && !hasMainDomain) { - calls.push(registerCalls.addressToDomain(encodedDomain)); + calls.push(registrationCalls.addressToDomain(encodedDomain)); } // Merge and set the call data @@ -219,9 +219,7 @@ const RegisterV2: FunctionComponent = ({ domain, groups }) => { useEffect(() => { if (!registerData?.transaction_hash || !salt) return; - posthog?.capture("register", { - onForceEmail, - }); + posthog?.capture("register"); // register the metadata to the sales manager db fetch(`${process.env.NEXT_PUBLIC_SALES_SERVER_LINK}/add_metadata`, { @@ -272,22 +270,6 @@ const RegisterV2: FunctionComponent = ({ domain, groups }) => { } }, [isUsResident, usState, price]); - // AB Testing - const [onForceEmail, setOnForceEmail] = useState(); - useEffect(() => { - posthog.onFeatureFlags(function () { - // feature flags should be available at this point - if ( - posthog.getFeatureFlag("onforceEmail") == "test" || - process.env.NEXT_PUBLIC_IS_TESTNET === "true" - ) { - setOnForceEmail(true); - } else { - setOnForceEmail(false); - } - }); - }, []); - return (
@@ -297,18 +279,16 @@ const RegisterV2: FunctionComponent = ({ domain, groups }) => {

{getDomainWithStark(domain)}

- {onForceEmail ? ( - changeEmail(e.target.value)} - color="secondary" - error={emailError} - errorMessage={"Please enter a valid email address"} - type="email" - /> - ) : null} + changeEmail(e.target.value)} + color="secondary" + error={emailError} + errorMessage={"Please enter a valid email address"} + type="email" + /> = ({ domain, groups }) => { invalidBalance || !termsBox || (isUsResident && !usState) || - (emailError && onForceEmail) + emailError } > {!termsBox @@ -386,7 +366,7 @@ const RegisterV2: FunctionComponent = ({ domain, groups }) => { ? "We need your US State" : invalidBalance ? "You don't have enough eth" - : emailError && onForceEmail + : emailError ? "Enter a valid Email" : "Register my domain"} diff --git a/components/domains/renewal.tsx b/components/domains/renewal.tsx index 3616865d..a13721ea 100644 --- a/components/domains/renewal.tsx +++ b/components/domains/renewal.tsx @@ -8,8 +8,12 @@ import { useContractWrite, useTransactionManager, } from "@starknet-react/core"; -import { utils } from "starknetid.js"; -import { getDomainWithStark, isValidEmail } from "../../utils/stringService"; +import { + getDomainWithStark, + isStarkRootDomain, + isValidEmail, + selectedDomainsToArray, +} from "../../utils/stringService"; import { gweiToEth, applyRateToBigInt } from "../../utils/feltService"; import { Abi, Call } from "starknet"; import { posthog } from "posthog-js"; @@ -25,6 +29,7 @@ import Wallets from "../UI/wallets"; import { computeMetadataHash, generateSalt } from "../../utils/userDataService"; import { getPriceFromDomains } from "../../utils/priceService"; import RenewalDomainsBox from "./renewalDomainsBox"; +import registrationCalls from "../../utils/callData/registrationCalls"; type RenewalProps = { domain: string; @@ -44,13 +49,9 @@ const Renewal: FunctionComponent = ({ domain, groups }) => { const [invalidBalance, setInvalidBalance] = useState(false); const { contract: etherContract } = useEtherContract(); const [isTxModalOpen, setIsTxModalOpen] = useState(false); - const encodedDomain = utils - .encodeDomain(domain) - .map((element) => element.toString())[0]; const [termsBox, setTermsBox] = useState(true); - const [renewalBox, setRenewalBox] = useState(true); + // const [renewalBox, setRenewalBox] = useState(true); const [walletModalOpen, setWalletModalOpen] = useState(false); - const [sponsor, setSponsor] = useState("0"); const [salt, setSalt] = useState(); const [metadataHash, setMetadataHash] = useState(); const [selectedDomains, setSelectedDomains] = @@ -65,15 +66,14 @@ const Renewal: FunctionComponent = ({ domain, groups }) => { }); const { writeAsync: execute, data: renewData } = useContractWrite({ // calls: renewalBox - // ? callData.concat(registerCalls.renewal(encodedDomain, price)) + // ? callData.concat(registrationCalls.renewal(encodedDomain, price)) // : callData, calls: callData, }); - const [domainsMinting, setDomainsMinting] = useState>( - new Map() - ); - + const [domainsMinting, setDomainsMinting] = + useState>(); const { addTransaction } = useTransactionManager(); + const duration = 1; // on year by default useEffect(() => { if (!renewData?.transaction_hash || !salt) return; @@ -121,7 +121,12 @@ const Renewal: FunctionComponent = ({ domain, groups }) => { useEffect(() => { if (!selectedDomains) return; - setPrice(getPriceFromDomains(selectedDomains, 1).toString()); + setPrice( + getPriceFromDomains( + selectedDomainsToArray(selectedDomains), + duration + ).toString() + ); }, [selectedDomains]); useEffect(() => { @@ -142,20 +147,6 @@ const Renewal: FunctionComponent = ({ domain, groups }) => { } }, [balance, price]); - useEffect(() => { - const referralData = localStorage.getItem("referralData"); - if (referralData) { - const data = JSON.parse(referralData); - if (data.sponsor && data?.expiry >= new Date().getTime()) { - setSponsor(data.sponsor); - } else { - setSponsor("0"); - } - } else { - setSponsor("0"); - } - }, []); - function changeEmail(value: string): void { setEmail(value); setEmailError(isValidEmail(value) ? false : true); @@ -173,13 +164,36 @@ const Renewal: FunctionComponent = ({ domain, groups }) => { } }, [isUsResident, usState, price]); + useEffect(() => { + if (selectedDomains) { + const calls = [ + registrationCalls.approve(price), + ...registrationCalls.multiCallRenewal( + selectedDomainsToArray(selectedDomains), + duration + ), + ]; + + // If the user is a US resident, we add the sales tax + if (salesTaxRate) { + calls.unshift(registrationCalls.vatTransfer(salesTaxAmount)); // IMPORTANT: We use unshift to put the call at the beginning of the array + } + + setCallData(calls); + } + }, [selectedDomains, price, salesTaxRate]); + return (

Your renewal

-

{getDomainWithStark(domain)}

+

+ {isStarkRootDomain(domain) + ? getDomainWithStark(domain) + : "Renew Your domain(s)"} +

= ({ domain, groups }) => { /> setRenewalBox(!renewalBox)} + // onChangeRenewalBox={() => setRenewalBox(!renewalBox)} onChangeTermsBox={() => setTermsBox(!termsBox)} termsBox={termsBox} - renewalBox={renewalBox} + // renewalBox={renewalBox} /> {address ? (