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: add hook for confirmed btc balance, inscription callouts #711

Merged
merged 12 commits into from
Dec 28, 2023
Merged
14 changes: 7 additions & 7 deletions package-lock.json
Copy link
Contributor

Choose a reason for hiding this comment

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

@abdulhaseeb4239 we should revert the package-lock.json changes as they're not needed and they also cause the build failure in this PR

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"@ledgerhq/hw-transport-webusb": "^6.27.13",
"@phosphor-icons/react": "^2.0.10",
"@react-spring/web": "^9.6.1",
"@secretkeylabs/xverse-core": "5.3.0",
"@secretkeylabs/xverse-core": "5.3.0-1be3831",
"@stacks/connect": "^6.10.2",
"@stacks/encryption": "4.3.5",
"@stacks/stacks-blockchain-api-types": "6.1.1",
Expand Down
30 changes: 30 additions & 0 deletions src/app/hooks/queries/useConfirmedBtcBalance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import useBtcClient from '@hooks/useBtcClient';
import { useQuery } from '@tanstack/react-query';
import useWalletSelector from '../useWalletSelector';

const useConfirmBtcBalance = () => {
const { btcAddress } = useWalletSelector();
const btcClient = useBtcClient();

const fetchBtcAddressData = async () => btcClient.getAddressData(btcAddress);

let confirmedBalance: number = 0;
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
let confirmedBalance: number = 0;
let confirmedBalance = 0;

Copy link
Contributor

Choose a reason for hiding this comment

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

nit: do we need to explicitly set the type here? I think we can rely on type inference here https://www.typescriptlang.org/docs/handbook/type-inference.html


const response = useQuery({
queryKey: ['btc-address-data'],
queryFn: fetchBtcAddressData,
});

const chainStats = response.data?.chain_stats;
const mempoolStats = response.data?.mempool_stats;
if (chainStats && mempoolStats) {
confirmedBalance =
chainStats.funded_txo_sum - chainStats.spent_txo_sum - mempoolStats.spent_txo_sum;
}

return {
confirmedBalance,
};
};

export default useConfirmBtcBalance;
48 changes: 41 additions & 7 deletions src/app/screens/createInscription/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
currencySymbolMap,
fetchBtcFeeRate,
getNonOrdinalUtxo,
InscriptionErrorCode,
useInscriptionExecute,
useInscriptionFees,
UTXO,
Expand All @@ -25,8 +26,9 @@ import { ExternalSatsMethods, MESSAGE_SOURCE } from '@common/types/message-types
import AccountHeaderComponent from '@components/accountHeader';
import ConfirmScreen from '@components/confirmScreen';
import useWalletSelector from '@hooks/useWalletSelector';
import { getShortTruncatedAddress } from '@utils/helper';
import { getShortTruncatedAddress, isLedgerAccount } from '@utils/helper';

import useConfirmedBtcBalance from '@hooks/queries/useConfirmedBtcBalance';
import useBtcClient from '@hooks/useBtcClient';
import useSeedVault from '@hooks/useSeedVault';
import Callout from '@ui-library/callout';
Expand Down Expand Up @@ -265,13 +267,21 @@ function CreateInscription() {

const [utxos, setUtxos] = useState<UTXO[] | undefined>();
const [showFeeSettings, setShowFeeSettings] = useState(false);
const [showConfirmedBalanceError, setShowConfirmedBalanceError] = useState(false);
const [feeRate, setFeeRate] = useState(suggestedMinerFeeRate ?? DEFAULT_FEE_RATE);
const [feeRates, setFeeRates] = useState<BtcFeeResponse>();
const { getSeed } = useSeedVault();
const btcClient = useBtcClient();

const { ordinalsAddress, network, btcAddress, selectedAccount, btcFiatRate, fiatCurrency } =
useWalletSelector();
const {
ordinalsAddress,
network,
btcAddress,
selectedAccount,
btcFiatRate,
fiatCurrency,
btcBalance,
} = useWalletSelector();

useEffect(() => {
getNonOrdinalUtxo(btcAddress, btcClient, requestedNetwork.type).then(setUtxos);
Expand Down Expand Up @@ -381,8 +391,11 @@ function CreateInscription() {
inscriptionValue,
} = commitValueBreakdown ?? {};

const { confirmedBalance } = useConfirmedBtcBalance();

const chainFee = (revealChainFee ?? 0) + (commitChainFee ?? 0);
const totalFee = (revealServiceFee ?? 0) + (externalServiceFee ?? 0) + chainFee;

const showTotalFee = totalFee !== chainFee;

const toFiat = (value: number | string = 0) =>
Expand All @@ -392,6 +405,18 @@ function CreateInscription() {
.plus(new BigNumber(totalInscriptionValue ?? 0))
.toString();

const errorCode = feeErrorCode || executeErrorCode;

const isLoading = utxos === undefined || inscriptionFeesLoading;

useEffect(() => {
const showConfirmError =
!isLoading &&
errorCode !== InscriptionErrorCode.INSUFFICIENT_FUNDS &&
Number(bundlePlusFees) > confirmedBalance;
setShowConfirmedBalanceError(!!showConfirmError);
}, [confirmedBalance, errorCode, bundlePlusFees, isLoading]);

if (complete && revealTransactionId) {
const onClose = () => {
const response = {
Expand Down Expand Up @@ -420,9 +445,12 @@ function CreateInscription() {
return <CompleteScreen txId={revealTransactionId} onClose={onClose} network={network} />;
}

const errorCode = feeErrorCode || executeErrorCode;

const isLoading = utxos === undefined || inscriptionFeesLoading;
const disableConfirmButton =
!!errorCode ||
isExecuting ||
showOver24RepeatsError ||
showConfirmedBalanceError ||
isLedgerAccount(selectedAccount);

return (
<ConfirmScreen
Expand All @@ -431,7 +459,7 @@ function CreateInscription() {
cancelText={t('CANCEL_BUTTON')}
confirmText={!errorCode ? t('CONFIRM_BUTTON') : t(`ERRORS.SHORT.${errorCode}`)}
loading={isExecuting || isLoading}
disabled={!!errorCode || isExecuting || showOver24RepeatsError}
disabled={disableConfirmButton}
isError={!!errorCode || showOver24RepeatsError}
>
<OuterContainer>
Expand All @@ -442,6 +470,12 @@ function CreateInscription() {
{showOver24RepeatsError && (
<StyledCallout variant="danger" bodyText={t('ERRORS.TOO_MANY_REPEATS')} />
)}
{showConfirmedBalanceError && (
<StyledCallout variant="danger" bodyText={t('ERRORS.UNCONFIRMED_UTXO')} />
)}
{isLedgerAccount(selectedAccount) && (
<StyledCallout variant="danger" bodyText={t('ERRORS.LEDGER_INSCRIPTION')} />
)}
<CardContainer bottomPadding>
<CardRow>
<StyledPillLabel>
Expand Down
4 changes: 3 additions & 1 deletion src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -982,7 +982,9 @@
"FAILED_TO_FINALIZE": "The inscription transaction failed to finalize. Please try again or contact support.",
"SERVER_ERROR": "An unknown server error occurred. Please try again or contact support."
},
"TOO_MANY_REPEATS": "You can only create up to 24 inscriptions in a single request"
"TOO_MANY_REPEATS": "You can only create up to 24 inscriptions in a single request",
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it would be good to move the 24 number to some constant (in a shared file or the component where it's used) to not change the translations in case the number needs to be changed, right? We can then pass it like this:
Monosnap index tsx β€” xverse-web-extension 2023-12-14 14-30-53

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's a valid point. Although this wasn't included in the current pull request, I've addressed it anyway πŸ˜„

"UNCONFIRMED_UTXO": "Some of your balance consists of unconfirmed outputs. You don't have enough confirmed funds to proceed with this transaction",
"LEDGER_INSCRIPTION": "This inscription service is not compatible with Ledger accounts. Please switch to a standard account to inscribe."
}
},
"ERROR_SCREEN": {
Expand Down
Loading