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

Refactor: Cancel STX transactions #5533

Closed
wants to merge 1 commit into from
Closed
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
13 changes: 13 additions & 0 deletions src/app/common/utils/get-burn-address.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { StacksNetwork } from '@stacks/network';
import { ChainID } from '@stacks/transactions';

export function getBurnAddress(network: StacksNetwork): string {
switch (network.chainId) {
case ChainID.Mainnet:
return 'SP00000000000003SCNSJTCSE62ZF4MSE';
case ChainID.Testnet:
return 'ST000000000000000000002AMW42H';
default:
return 'ST000000000000000000002AMW42H';
Comment on lines +10 to +11
Copy link

Choose a reason for hiding this comment

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

Clarify the default case in getBurnAddress.

The function returns the Testnet burn address as the default. It might be clearer to either handle this explicitly or add a comment explaining why this is the default behavior, to avoid confusion in environments where the chain ID might not be explicitly set.

-      return 'ST000000000000000000002AMW42H';
+      // Default to Testnet burn address unless specified otherwise
+      return 'ST000000000000000000002AMW42H'; 
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
default:
return 'ST000000000000000000002AMW42H';
default:
// Default to Testnet burn address unless specified otherwise
return 'ST000000000000000000002AMW42H';

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { HStack } from 'leather-styles/jsx';

import type { BitcoinTx } from '@leather.io/models';
import { useInscriptionByOutput } from '@leather.io/query';
import { BtcAvatarIcon, BulletSeparator, Caption } from '@leather.io/ui';
import { BtcAvatarIcon, BulletSeparator, Caption, ChevronsRightIcon } from '@leather.io/ui';

import { RouteUrls } from '@shared/route-urls';
import { analytics } from '@shared/utils/analytics';
Expand All @@ -18,10 +18,10 @@ import {
isBitcoinTxInbound,
} from '@app/common/transactions/bitcoin/utils';
import { openInNewTab } from '@app/common/utils/open-in-new-tab';
import { IncreaseFeeButton } from '@app/components/stacks-transaction-item/increase-fee-button';
import { TransactionTitle } from '@app/components/transaction/transaction-title';
import { useCurrentAccountNativeSegwitAddressIndexZero } from '@app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks';

import { TransactionActionIconButton } from '../stacks-transaction-item/transaction-action-button';
import { TransactionItemLayout } from '../transaction-item/transaction-item.layout';
import { BitcoinTransactionIcon } from './bitcoin-transaction-icon';
import { InscriptionIcon } from './bitcoin-transaction-inscription-icon';
Expand Down Expand Up @@ -74,10 +74,12 @@ export function BitcoinTransactionItem({ transaction }: BitcoinTransactionItemPr

const title = inscriptionData ? `Ordinal inscription #${inscriptionData.number}` : 'Bitcoin';
const increaseFeeButton = (
<IncreaseFeeButton
<TransactionActionIconButton
icon={<ChevronsRightIcon />}
label="Increase fee"
isEnabled={isEnabled}
isSelected={pathname === RouteUrls.IncreaseBtcFee}
onIncreaseFee={onIncreaseFee}
onButtonClick={onIncreaseFee}
/>
);

Expand Down
38 changes: 0 additions & 38 deletions src/app/components/stacks-transaction-item/increase-fee-button.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { useLocation, useNavigate } from 'react-router-dom';
import { useMatch, useNavigate } from 'react-router-dom';

import { HStack } from 'leather-styles/jsx';

import { StacksTx } from '@leather.io/models';
import { ChevronsRightIcon, CloseIcon } from '@leather.io/ui';

import { RouteUrls } from '@shared/route-urls';
import { analytics } from '@shared/utils/analytics';
Expand All @@ -19,9 +22,21 @@ import { TransactionTitle } from '@app/components/transaction/transaction-title'
import { useCurrentStacksAccount } from '@app/store/accounts/blockchain/stacks/stacks-account.hooks';

import { TransactionItemLayout } from '../transaction-item/transaction-item.layout';
import { IncreaseFeeButton } from './increase-fee-button';
import { StacksTransactionIcon } from './stacks-transaction-icon';
import { StacksTransactionStatus } from './stacks-transaction-status';
import { TransactionActionIconButton } from './transaction-action-button';

type TransactionAction = 'increaseFee' | 'cancel';

interface ActionRouteMap {
increaseFee: keyof typeof RouteUrls;
cancel: keyof typeof RouteUrls;
}

const actionRouteMap: ActionRouteMap = {
increaseFee: 'IncreaseStxFee',
cancel: 'CancelStxTransaction',
};

interface StacksTransactionItemProps {
caption?: string;
Expand All @@ -42,10 +57,13 @@ export function StacksTransactionItem({
const { handleOpenStacksTxLink } = useStacksExplorerLink();
const currentAccount = useCurrentStacksAccount();

const { pathname } = useLocation();
const navigate = useNavigate();
const { whenWallet } = useWalletType();

const cancelTransactionMatch = useMatch('/cancel-transaction/stx/:txid');
const increaseFeeMatch = useMatch('/increase-fee/stx/:txid');
const isTransactionActionRoute = !!cancelTransactionMatch || !!increaseFeeMatch;

const hasTransferDetailsData = !!caption && !!title && !!value && !!link;
if (!transaction && !hasTransferDetailsData) return null;

Expand All @@ -56,10 +74,11 @@ export function StacksTransactionItem({
});
};

const onIncreaseFee = () => {
const handleTransactionAction = (action: TransactionAction): void => {
if (!transaction) return;

const routeUrl = RouteUrls.IncreaseStxFee.replace(':txid', transaction.tx_id);
const routeKey = actionRouteMap[action];
const routeUrl = RouteUrls[routeKey].replace(':txid', transaction.tx_id);

whenWallet({
ledger: () =>
Expand All @@ -78,22 +97,36 @@ export function StacksTransactionItem({
const txIcon = transaction ? <StacksTransactionIcon transaction={transaction} /> : icon;
const txTitle = transaction ? getTxTitle(transaction) : title || '';
const txValue = transaction ? getTxValue(transaction, isOriginator) : value;
const increaseFeeButton = (
<IncreaseFeeButton
isEnabled={isOriginator && isPending}
isSelected={pathname === RouteUrls.IncreaseStxFee}
onIncreaseFee={onIncreaseFee}
/>

const actionButtonGroup = (
<HStack alignItems="center">
<TransactionActionIconButton
icon={<CloseIcon />}
isEnabled={isOriginator && isPending}
isSelected={isTransactionActionRoute}
label="Cancel"
onButtonClick={() => handleTransactionAction('cancel')}
/>
<TransactionActionIconButton
icon={<ChevronsRightIcon />}
isEnabled={isOriginator && isPending}
isSelected={isTransactionActionRoute}
label="Increase Fee"
onButtonClick={() => handleTransactionAction('increaseFee')}
/>
</HStack>
);

const txIsPending = transaction && transaction.tx_status == 'pending';
const txStatus = transaction && <StacksTransactionStatus transaction={transaction} />;

return (
<TransactionItemLayout
openTxLink={openTxLink}
rightElement={isOriginator && isPending ? increaseFeeButton : undefined}
rightElement={isOriginator && isPending ? actionButtonGroup : undefined}
txCaption={txCaption}
txIcon={txIcon}
txStatus={txStatus}
txStatus={!txIsPending && txStatus}
txTitle={<TransactionTitle title={txTitle} />}
txValue={txValue}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { IconButton } from '@leather.io/ui';

import { BasicTooltip } from '@app/ui/components/tooltip/basic-tooltip';

interface ActionButtonProps {
icon: React.ReactElement;
isEnabled?: boolean;
isSelected: boolean;
label: string;
onButtonClick(): void;
}

export function TransactionActionIconButton(props: ActionButtonProps) {
const { isEnabled, isSelected, onButtonClick, label, icon } = props;
const isActive = isEnabled && !isSelected;

if (!isActive) return null;

return (
<BasicTooltip label={label} side="top">
<IconButton
icon={icon}
backgroundColor={'ink.background-primary'}
onClick={e => {
e.stopPropagation();
onButtonClick();
}}
></IconButton>
</BasicTooltip>
);
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { RouteUrls } from '@shared/route-urls';

import { IncreaseFeeField } from './components/increase-fee-field';
import { useStxCancelTransaction } from './hooks/use-stx-cancel-transaction';
import { StxTransactionActionDialog } from './stx-transaction-action-dialog';

export function CancelStxTransactionDialog() {
return (
<StxTransactionActionDialog
title="Cancel transaction"
description="Cancelling a transaction isn't guaranteed to work. A higher fee can help replace the old transaction."
routeUrl={RouteUrls.CancelStxTransaction}
useActionHook={useStxCancelTransaction}
FeeComponent={IncreaseFeeField}
isCancel={true}
/>
);
}
Loading