Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow aux funds for name registration #1065

Closed
wants to merge 12 commits into from
16 changes: 10 additions & 6 deletions apps/web/src/components/Basenames/RegistrationForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import TransactionError from 'apps/web/src/components/TransactionError';
import TransactionStatus from 'apps/web/src/components/TransactionStatus';
import { usePremiumEndDurationRemaining } from 'apps/web/src/hooks/useActiveEthPremiumAmount';
import useBasenameChain, { supportedChainIds } from 'apps/web/src/hooks/useBasenameChain';
import useCapabilitiesSafe from 'apps/web/src/hooks/useCapabilitiesSafe';
import { useEthPriceFromUniswap } from 'apps/web/src/hooks/useEthPriceFromUniswap';
import {
useDiscountedNameRegistrationPrice,
Expand Down Expand Up @@ -164,12 +165,16 @@ export default function RegistrationForm() {
[setReverseRecord],
);

const { auxiliaryFunds: auxiliaryFundsEnabled } = useCapabilitiesSafe({ chain: connectedChain });
const { data: balance } = useBalance({ address, chainId: connectedChain?.id });
const insufficientBalanceToRegister =
balance?.value !== undefined && price !== undefined && balance?.value < price;
const correctChain = connectedChain?.id === basenameChain.id;
const insufficientFundsAndNoAuxFunds = insufficientBalanceToRegister && !auxiliaryFundsEnabled;
const insufficientBalanceToRegisterAndCorrectChain =
insufficientBalanceToRegister && correctChain;
const insufficientFundsNoAuxFundsAndCorrectChain =
!auxiliaryFundsEnabled && insufficientBalanceToRegisterAndCorrectChain;

const hasResolvedUSDPrice = price !== undefined && ethUsdPrice !== undefined;
const usdPrice = hasResolvedUSDPrice ? formatUsdPrice(price, ethUsdPrice) : '--.--';
Expand Down Expand Up @@ -267,14 +272,14 @@ export default function RegistrationForm() {
<div className="flex flex-row items-baseline justify-around gap-2">
<p
className={classNames('whitespace-nowrap text-3xl text-black line-through', {
'text-state-n-hovered': insufficientBalanceToRegister,
'text-state-n-hovered': insufficientFundsAndNoAuxFunds,
})}
>
{formatEtherPrice(initialPrice)}
</p>
<p
className={classNames('whitespace-nowrap text-3xl font-bold text-green-50', {
'text-state-n-hovered': insufficientBalanceToRegister,
'text-state-n-hovered': insufficientFundsAndNoAuxFunds,
})}
>
{formatEtherPrice(discountedPrice)} ETH
Expand All @@ -283,7 +288,7 @@ export default function RegistrationForm() {
) : (
<p
className={classNames('whitespace-nowrap text-3xl font-bold text-black', {
'text-state-n-hovered': insufficientBalanceToRegister,
'text-state-n-hovered': insufficientFundsAndNoAuxFunds,
})}
>
{formatEtherPrice(price)} ETH
Expand All @@ -293,7 +298,7 @@ export default function RegistrationForm() {
<span className="whitespace-nowrap text-xl text-gray-60">${usdPrice}</span>
)}
</div>
{insufficientBalanceToRegister ? (
{insufficientFundsAndNoAuxFunds ? (
<p className="text-sm text-state-n-hovered">your ETH balance is insufficient</p>
) : Boolean(nameIsFree && IS_EARLY_ACCESS) ? (
<p className="text-sm text-green-50">Discounted during Early Access.</p>
Expand Down Expand Up @@ -337,7 +342,7 @@ export default function RegistrationForm() {
variant={ButtonVariants.Black}
size={ButtonSizes.Medium}
disabled={
insufficientBalanceToRegisterAndCorrectChain ||
insufficientFundsNoAuxFundsAndCorrectChain ||
registerNameTransactionIsPending
}
isLoading={registerNameTransactionIsPending}
Expand Down Expand Up @@ -395,7 +400,6 @@ export default function RegistrationForm() {
baseSingleYearEthCost={singleYearBasePrice}
isOpen={premiumExplainerModalOpen}
toggleModal={togglePremiumExplainerModal}
nameLength={selectedName?.length}
brendan-defi marked this conversation as resolved.
Show resolved Hide resolved
/>
)}
</>
Expand Down
38 changes: 25 additions & 13 deletions apps/web/src/hooks/useCapabilitiesSafe.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
A hook to safely check wallet_getCapabilities support

Responsabilities:
Responsibilities:
- Check for unsupported wallets (e.g: metamask)
- Use experimental useCapabilities
- Check atomicBatch (batchcall) and paymasterService for a given chain
Expand All @@ -12,26 +12,38 @@ import { Chain } from 'viem';
import { useAccount } from 'wagmi';
import { useCapabilities } from 'wagmi/experimental';

// To add a new capability, add it to this list
const capabilitiesList = ['atomicBatch', 'paymasterService', 'auxiliaryFunds'] as const;
This conversation was marked as resolved.
Show resolved Hide resolved

type ListedCapabilities = (typeof capabilitiesList)[number];

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main goal of the refactor is to make this hook more easily updatable. Simply adding the capability name to this string[] is all you need to do to expose the capability through the hook.

export type UseCapabilitiesSafeProps = {
chain: Chain;
chain?: Chain;
};

export default function useCapabilitiesSafe({ chain }: UseCapabilitiesSafeProps) {
const { connector, isConnected } = useAccount();
export default function useCapabilitiesSafe({
chain: paramChain,
}: UseCapabilitiesSafeProps): Record<ListedCapabilities, boolean> {
const { connector, isConnected, chain: accountChain } = useAccount();
const chain = paramChain ?? accountChain;

// Metamask doesn't support wallet_getCapabilities
const isMetamaskWallet = connector?.id === 'io.metamask';
const enabled = isConnected && !isMetamaskWallet;

const { data: capabilities } = useCapabilities({ query: { enabled } });
const { data: rawCapabilities } = useCapabilities({ query: { enabled } });

function isCapabilitySupported(capability: ListedCapabilities) {
return (
(chain && rawCapabilities && rawCapabilities[chain.id]?.[capability]?.supported === true) ??
false
);
}

const atomicBatchEnabled =
(capabilities && capabilities[chain.id]?.atomicBatch?.supported === true) ?? false;
const paymasterServiceEnabled =
(capabilities && capabilities[chain.id]?.paymasterService?.supported === true) ?? false;
const capabilities = capabilitiesList.reduce((acc, capability) => {
acc[capability] = isCapabilitySupported(capability);
return acc;
}, {} as Record<ListedCapabilities, boolean>);

return {
atomicBatchEnabled,
paymasterServiceEnabled,
};
return capabilities;
}
2 changes: 1 addition & 1 deletion apps/web/src/hooks/useWriteContractsWithLogs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export default function useWriteContractsWithLogs({
// Errors & Analytics
const { logEventWithContext } = useAnalytics();
const { logError } = useErrors();
const { atomicBatchEnabled } = useCapabilitiesSafe({ chain });
const { atomicBatch: atomicBatchEnabled } = useCapabilitiesSafe({ chain });
const { chain: connectedChain } = useAccount();

const [batchCallsStatus, setBatchCallsStatus] = useState<BatchCallsStatus>(BatchCallsStatus.Idle);
Expand Down
Loading