diff --git a/package.json b/package.json
index 8a6a4a3305b..56949477c80 100644
--- a/package.json
+++ b/package.json
@@ -141,7 +141,7 @@
"@leather.io/constants": "0.9.1",
"@leather.io/crypto": "1.4.2",
"@leather.io/models": "0.13.0",
- "@leather.io/query": "2.7.0",
+ "@leather.io/query": "2.7.1",
"@leather.io/stacks": "1.0.2",
"@leather.io/tokens": "0.9.0",
"@leather.io/ui": "1.16.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index babc9272d30..21402e67524 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -47,8 +47,8 @@ importers:
specifier: 0.13.0
version: 0.13.0
'@leather.io/query':
- specifier: 2.7.0
- version: 2.7.0(@stacks/network@6.13.0(encoding@0.1.13))(encoding@0.1.13)(react@18.3.1)
+ specifier: 2.7.1
+ version: 2.7.1(@stacks/network@6.13.0(encoding@0.1.13))(encoding@0.1.13)(react@18.3.1)
'@leather.io/stacks':
specifier: 1.0.2
version: 1.0.2(encoding@0.1.13)
@@ -2551,7 +2551,7 @@ packages:
'@expo/bunyan@4.0.1':
resolution: {integrity: sha512-+Lla7nYSiHZirgK+U/uYzsLv/X+HaJienbD5AKX1UQZHYfWaP+9uuQluRB4GrEVWF0GZ7vEVp/jzaOT9k/SQlg==}
- engines: {node: '>=0.10.0'}
+ engines: {'0': node >=0.10.0}
'@expo/cli@0.18.28':
resolution: {integrity: sha512-fvbVPId6s6etindzP6Nzos/CS1NurMVy4JKozjebArHr63tBid5i/UY5Pp+4wTCAM20gB2SjRdwcwoL6HFC4Iw==}
@@ -2779,8 +2779,8 @@ packages:
'@leather.io/prettier-config@0.6.0':
resolution: {integrity: sha512-QBKtLanfxFxXBlR58U/j8a6lBI0xzJzqqi36fXpGVp+9mJoEf6Ro6xrtFrixjW6seY6EOva4OApVnnPBsvOC/w==}
- '@leather.io/query@2.7.0':
- resolution: {integrity: sha512-IWPJ+nYH2OR7Eb2WZ9Dkvs98/ffdJ1aXyIEomExuOLkTEmsxQvdZe4Bm0MtBwqFdzzmM1C7PSmbPuR521rpkHA==}
+ '@leather.io/query@2.7.1':
+ resolution: {integrity: sha512-TIew8kDeYGUbFOBVcWeFZuYCaSa2Pp2xfDUPxf/BicIsyYqXxFGoB5fclDqugratAWw9aZTTqsYcbMzg/+pwew==}
peerDependencies:
react: '*'
@@ -17635,7 +17635,7 @@ snapshots:
- '@vue/compiler-sfc'
- supports-color
- '@leather.io/query@2.7.0(@stacks/network@6.13.0(encoding@0.1.13))(encoding@0.1.13)(react@18.3.1)':
+ '@leather.io/query@2.7.1(@stacks/network@6.13.0(encoding@0.1.13))(encoding@0.1.13)(react@18.3.1)':
dependencies:
'@fungible-systems/zone-file': 2.0.0
'@hirosystems/token-metadata-api-client': 1.2.0(encoding@0.1.13)
diff --git a/src/app/common/hooks/use-stacks-explorer-link.ts b/src/app/common/hooks/use-stacks-explorer-link.ts
index 059eeb6f001..df8f86ddfed 100644
--- a/src/app/common/hooks/use-stacks-explorer-link.ts
+++ b/src/app/common/hooks/use-stacks-explorer-link.ts
@@ -5,7 +5,7 @@ import { useCurrentNetworkState } from '@app/store/networks/networks.hooks';
import { openInNewTab } from '../utils/open-in-new-tab';
-export interface HandleOpenStacksTxLinkArgs {
+interface HandleOpenStacksTxLinkArgs {
searchParams?: URLSearchParams;
txid: string;
}
diff --git a/src/app/common/validation/forms/amount-validators.ts b/src/app/common/validation/forms/amount-validators.ts
index 65453e84b23..5f8221dbadd 100644
--- a/src/app/common/validation/forms/amount-validators.ts
+++ b/src/app/common/validation/forms/amount-validators.ts
@@ -131,14 +131,3 @@ export function stacksFungibleTokenAmountValidator(balance: Money) {
},
});
}
-
-export function tokenAmountValidator(balance: Money) {
- const { amount } = balance;
- return amountValidator().test({
- message: formatInsufficientBalanceError(balance, sum => sum.amount.toString()),
- test(value) {
- if (!isNumber(value) || !amount) return false;
- return new BigNumber(value).isLessThanOrEqualTo(amount);
- },
- });
-}
diff --git a/src/app/components/status-pending.tsx b/src/app/components/status-pending.tsx
deleted file mode 100644
index be34c834425..00000000000
--- a/src/app/components/status-pending.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-export function StatusPending() {
- return (
-
- );
-}
diff --git a/src/app/components/status-ready.tsx b/src/app/components/status-ready.tsx
deleted file mode 100644
index d0aabde4d7d..00000000000
--- a/src/app/components/status-ready.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-export function StatusReady() {
- return (
-
- );
-}
diff --git a/src/app/features/asset-list/bitcoin/brc20-token-asset-list/brc20-token-asset-list.tsx b/src/app/features/asset-list/bitcoin/brc20-token-asset-list/brc20-token-asset-list.tsx
index 6a239cf408d..bec2a7ad5c8 100644
--- a/src/app/features/asset-list/bitcoin/brc20-token-asset-list/brc20-token-asset-list.tsx
+++ b/src/app/features/asset-list/bitcoin/brc20-token-asset-list/brc20-token-asset-list.tsx
@@ -1,13 +1,9 @@
-import { useNavigate } from 'react-router-dom';
-
import { CryptoAssetSelectors } from '@tests/selectors/crypto-asset.selectors';
import { Stack } from 'leather-styles/jsx';
import type { Brc20CryptoAssetInfo, CryptoAssetBalance, MarketData } from '@leather.io/models';
import { Brc20AvatarIcon } from '@leather.io/ui';
-import { RouteUrls } from '@shared/route-urls';
-
import { convertAssetBalanceToFiat } from '@app/common/asset-utils';
import { CryptoAssetItemLayout } from '@app/components/crypto-asset-item/crypto-asset-item.layout';
import type { AssetListVariant } from '@app/features/asset-list/asset-list';
@@ -32,24 +28,8 @@ function getBrc20TokenFiatBalance(token: Brc20TokenAssetDetails) {
});
}
-export function Brc20TokenAssetList({ tokens, variant }: Brc20TokenAssetListProps) {
- const navigate = useNavigate();
- const { balance, isLoading } = useCurrentBtcCryptoAssetBalanceNativeSegwit();
-
- const hasPositiveBtcBalanceForFees =
- variant === 'interactive' && balance.availableBalance.amount.isGreaterThan(0);
-
- function navigateToBrc20SendForm(token: Brc20TokenAssetDetails) {
- const { balance, holderAddress, info, marketData } = token;
- navigate(RouteUrls.SendBrc20SendForm.replace(':ticker', info.symbol), {
- state: {
- balance: balance.availableBalance,
- holderAddress,
- marketData,
- ticker: info.symbol,
- },
- });
- }
+export function Brc20TokenAssetList({ tokens }: Brc20TokenAssetListProps) {
+ const { isLoading } = useCurrentBtcCryptoAssetBalanceNativeSegwit();
if (!tokens.length) return null;
return (
@@ -61,9 +41,6 @@ export function Brc20TokenAssetList({ tokens, variant }: Brc20TokenAssetListProp
icon={}
isLoading={isLoading}
key={token.info.symbol}
- onSelectAsset={
- hasPositiveBtcBalanceForFees ? () => navigateToBrc20SendForm(token) : undefined
- }
titleLeft={token.info.symbol}
fiatBalance={getBrc20TokenFiatBalance(token)}
/>
diff --git a/src/app/features/pending-brc-20-transfers/pending-brc-20-transfers.tsx b/src/app/features/pending-brc-20-transfers/pending-brc-20-transfers.tsx
deleted file mode 100644
index 8e4c10f6831..00000000000
--- a/src/app/features/pending-brc-20-transfers/pending-brc-20-transfers.tsx
+++ /dev/null
@@ -1,133 +0,0 @@
-import { useNavigate } from 'react-router-dom';
-
-import { Box, Flex, HStack, Stack } from 'leather-styles/jsx';
-
-import { fetchInscripionById, useOrdinalsbotClient } from '@leather.io/query';
-import { BulletSeparator, Caption, Flag } from '@leather.io/ui';
-import { noop } from '@leather.io/utils';
-
-import { RouteUrls } from '@shared/route-urls';
-
-import { usePressable } from '@app/components/item-hover';
-import { StatusPending } from '@app/components/status-pending';
-import { StatusReady } from '@app/components/status-ready';
-import { useCurrentBtcCryptoAssetBalanceNativeSegwit } from '@app/query/bitcoin/balance/btc-balance-native-segwit.hooks';
-import { useCheckOrderStatuses } from '@app/query/bitcoin/ordinals/brc20/use-check-order-status';
-import {
- OrdinalsbotInscriptionStatus,
- PendingBrc20Transfer,
- usePendingBrc20Transfers,
-} from '@app/store/ordinals/ordinals.slice';
-import { BasicTooltip } from '@app/ui/components/tooltip/basic-tooltip';
-
-function StatusIcon({ status }: { status: OrdinalsbotInscriptionStatus }) {
- switch (status) {
- case 'pending':
- return ;
- case 'paid':
- return ;
- case 'waiting-for-indexer':
- return ;
- case 'ready':
- return ;
- default:
- return null;
- }
-}
-function StatusLabel({ status }: { status: OrdinalsbotInscriptionStatus }) {
- switch (status) {
- case 'pending':
- return <>Paying for transfer inscription…>;
- case 'paid':
- return (
-
- <>Creating transfer inscription…>
-
- );
- case 'waiting-for-indexer':
- return (
-
- <>Receiving transfer inscription…>
-
- );
- case 'ready':
- return <>Ready to transfer>;
- default:
- return null;
- }
-}
-
-export function PendingBrc20TransferList() {
- const transferOrders = usePendingBrc20Transfers();
-
- useCheckOrderStatuses(
- transferOrders.filter(order => order.status !== 'ready').map(order => order.id)
- );
-
- if (!transferOrders.length) return null;
-
- return (
-
-
- Pending BRC-20 transfers
-
-
- {transferOrders.map(order => (
-
- ))}
-
-
- );
-}
-
-interface PendingBrcTransferProps {
- order: PendingBrc20Transfer;
-}
-function PendingBrcTransfer({ order }: PendingBrcTransferProps) {
- const [component, bind] = usePressable(order.status === 'ready');
- const navigate = useNavigate();
- const ordinalsbotClient = useOrdinalsbotClient();
- const { balance } = useCurrentBtcCryptoAssetBalanceNativeSegwit();
-
- const hasPositiveBtcBalanceForFees = balance.availableBalance.amount.isGreaterThan(0);
-
- return (
- {
- // Really inefficient, find way to not have to refetch data
- const { data: orderInfo } = await ordinalsbotClient.orderStatus(order.id);
- const { data: inscription } = await fetchInscripionById(
- (orderInfo as any).files[0].tx?.inscription
- );
- navigate(RouteUrls.SendOrdinalInscription, {
- state: {
- inscription,
- },
- });
- }
- : noop
- : noop
- }
- {...(order.status === 'ready' ? bind : {})}
- >
- <>
- {order.amount} {order.tick}
- >
-
-
-
- }>
-
-
-
-
-
- {component}
-
- );
-}
diff --git a/src/app/pages/home/components/assets.tsx b/src/app/pages/home/components/assets.tsx
index 2568d5e08f0..fad7b948377 100644
--- a/src/app/pages/home/components/assets.tsx
+++ b/src/app/pages/home/components/assets.tsx
@@ -5,13 +5,11 @@ import { Stack } from 'leather-styles/jsx';
import { AssetList } from '@app/features/asset-list/asset-list';
import { Collectibles } from '@app/features/collectibles/collectibles';
-import { PendingBrc20TransferList } from '@app/features/pending-brc-20-transfers/pending-brc-20-transfers';
export function Assets() {
return (
-
diff --git a/src/app/pages/send/ordinal-inscription/send-inscription-review.tsx b/src/app/pages/send/ordinal-inscription/send-inscription-review.tsx
index 7a4bd5aaa36..858ea1c5f64 100644
--- a/src/app/pages/send/ordinal-inscription/send-inscription-review.tsx
+++ b/src/app/pages/send/ordinal-inscription/send-inscription-review.tsx
@@ -15,8 +15,6 @@ import { InfoCardRow, InfoCardSeparator } from '@app/components/info-card/info-c
import { InscriptionPreview } from '@app/components/inscription-preview-card/components/inscription-preview';
import { Card } from '@app/components/layout';
import { useCurrentNativeSegwitUtxos } from '@app/query/bitcoin/address/utxos-by-address.hooks';
-import { useAppDispatch } from '@app/store';
-import { inscriptionSent } from '@app/store/ordinals/ordinals.slice';
import { InscriptionPreviewCard } from '../../../components/inscription-preview-card/inscription-preview-card';
import { useSendInscriptionState } from './components/send-inscription-container';
@@ -33,7 +31,6 @@ function useSendInscriptionReviewState() {
export function SendInscriptionReview() {
const navigate = useNavigate();
- const dispatch = useAppDispatch();
const { arrivesIn, signedTx, recipient, feeRowValue } = useSendInscriptionReviewState();
const { inscription } = useSendInscriptionState();
@@ -47,8 +44,6 @@ export function SendInscriptionReview() {
async onSuccess(txid: string) {
void analytics.track('broadcast_ordinal_transaction');
await filteredUtxosQuery.refetch();
- // Might be a BRC-20 transfer, so we want to remove it from the pending
- dispatch(inscriptionSent({ inscriptionId: inscription.id }));
navigate(`/${RouteUrls.SendOrdinalInscription}/${RouteUrls.SendOrdinalInscriptionSent}`, {
state: {
inscription,
diff --git a/src/app/pages/send/send-crypto-asset-form/form/brc20/brc20-choose-fee.tsx b/src/app/pages/send/send-crypto-asset-form/form/brc20/brc20-choose-fee.tsx
deleted file mode 100644
index fd4b702e5a6..00000000000
--- a/src/app/pages/send/send-crypto-asset-form/form/brc20/brc20-choose-fee.tsx
+++ /dev/null
@@ -1,177 +0,0 @@
-import { useState } from 'react';
-import { Outlet, useLocation, useNavigate } from 'react-router-dom';
-
-import { Stack } from 'leather-styles/jsx';
-import get from 'lodash.get';
-
-import type { BtcFeeType } from '@leather.io/models';
-import type { UtxoResponseItem } from '@leather.io/query';
-import { createMoney } from '@leather.io/utils';
-
-import { logger } from '@shared/logger';
-import { RouteUrls } from '@shared/route-urls';
-
-import { formFeeRowValue } from '@app/common/send/utils';
-import { useGenerateUnsignedNativeSegwitTx } from '@app/common/transactions/bitcoin/use-generate-bitcoin-tx';
-import {
- BitcoinFeesList,
- OnChooseFeeArgs,
-} from '@app/components/bitcoin-fees-list/bitcoin-fees-list';
-import { useBitcoinFeesList } from '@app/components/bitcoin-fees-list/use-bitcoin-fees-list';
-import { Content, Page } from '@app/components/layout';
-import { LoadingSpinner } from '@app/components/loading-spinner';
-import { BitcoinChooseFee } from '@app/features/bitcoin-choose-fee/bitcoin-choose-fee';
-import { useValidateBitcoinSpend } from '@app/features/bitcoin-choose-fee/hooks/use-validate-bitcoin-spend';
-import { PageHeader } from '@app/features/container/headers/page.header';
-import { useToast } from '@app/features/toasts/use-toast';
-import { useBrc20Transfers } from '@app/query/bitcoin/ordinals/brc20/brc20-tokens.hooks';
-import { useSignBitcoinTx } from '@app/store/accounts/blockchain/bitcoin/bitcoin.hooks';
-
-import { useSendBitcoinAssetContextState } from '../../family/bitcoin/components/send-bitcoin-asset-container';
-
-function useBrc20ChooseFeeState() {
- const location = useLocation();
- return {
- ticker: get(location.state, 'ticker') as string,
- amount: get(location.state, 'amount') as string,
- recipient: get(location.state, 'recipient') as string,
- utxos: get(location.state, 'utxos') as UtxoResponseItem[],
- holderAddress: get(location.state, 'holderAddress') as string,
- };
-}
-
-export function BrcChooseFee() {
- const toast = useToast();
- const navigate = useNavigate();
- const { amount, recipient, ticker, utxos, holderAddress } = useBrc20ChooseFeeState();
- const generateTx = useGenerateUnsignedNativeSegwitTx();
- const signTx = useSignBitcoinTx();
- const { selectedFeeType, setSelectedFeeType } = useSendBitcoinAssetContextState();
- const { initiateTransfer } = useBrc20Transfers(holderAddress);
- const amountAsMoney = createMoney(Number(amount), ticker, 0);
- const { feesList, isLoading } = useBitcoinFeesList({
- amount: amountAsMoney,
- recipient,
- utxos,
- });
- const recipients = [
- {
- address: recipient,
- amount: amountAsMoney,
- },
- ];
- const recommendedFeeRate = feesList[1]?.feeRate.toString() || '';
-
- const { showInsufficientBalanceError, onValidateBitcoinFeeSpend } =
- useValidateBitcoinSpend(amountAsMoney);
-
- const [isLoadingOrder, setIsLoadingOrder] = useState(false);
-
- async function previewTransaction({ feeRate, feeValue, isCustomFee }: OnChooseFeeArgs) {
- setIsLoadingOrder(true);
- try {
- const { order, id } = await initiateTransfer(ticker, amount);
- setIsLoadingOrder(false);
-
- const { charge } = order.data;
-
- const serviceFeeRecipient = charge.address;
- const serviceFee = charge.amount;
-
- const serviceFeeAsMoney = createMoney(serviceFee, 'BTC');
-
- const resp = await generateTx(
- {
- amount: serviceFeeAsMoney,
- recipients: [
- {
- address: serviceFeeRecipient,
- amount: serviceFeeAsMoney,
- },
- ],
- },
- feeRate,
- utxos
- );
-
- if (!resp) return logger.error('Attempted to generate raw tx, but no tx exists');
- const signedTx = await signTx(resp.psbt);
-
- if (!signedTx) return logger.error('Attempted to sign tx, but no tx exists');
- signedTx.finalize();
-
- const feeRowValue = formFeeRowValue(feeRate, isCustomFee);
- navigate(RouteUrls.SendBrc20Confirmation.replace(':ticker', ticker), {
- state: {
- tx: signedTx.hex,
- orderId: id,
- fee: feeValue,
- serviceFee: charge.amount,
- serviceFeeRecipient,
- recipient,
- feeRowValue,
- ticker,
- amount,
- holderAddress,
- hasHeaderTitle: true,
- },
- });
- } catch (err) {
- const errorMessage = (err as Error).message || 'Failed to create transaction';
- logger.error('Failed to create transaction', err);
- toast.error(errorMessage);
- navigate('..');
- } finally {
- setIsLoadingOrder(false);
- }
- }
-
- return (
- <>
-
-
-
- {isLoadingOrder && (
-
-
-
- )}
- {!isLoadingOrder && (
- <>
- setSelectedFeeType(value)}
- onValidateBitcoinSpend={onValidateBitcoinFeeSpend}
- selectedFeeType={selectedFeeType}
- />
- }
- isLoading={isLoading}
- isSendingMax={false}
- onChooseFee={previewTransaction}
- onSetSelectedFeeType={(value: BtcFeeType | null) => setSelectedFeeType(value)}
- onValidateBitcoinSpend={onValidateBitcoinFeeSpend}
- recommendedFeeRate={recommendedFeeRate}
- recipients={recipients}
- showError={showInsufficientBalanceError}
- maxRecommendedFeeRate={feesList[0]?.feeRate}
- />
-
- >
- )}
-
-
- >
- );
-}
diff --git a/src/app/pages/send/send-crypto-asset-form/form/brc20/brc20-send-form-confirmation.tsx b/src/app/pages/send/send-crypto-asset-form/form/brc20/brc20-send-form-confirmation.tsx
deleted file mode 100644
index c4eeaa11c8d..00000000000
--- a/src/app/pages/send/send-crypto-asset-form/form/brc20/brc20-send-form-confirmation.tsx
+++ /dev/null
@@ -1,149 +0,0 @@
-import { useLocation, useNavigate } from 'react-router-dom';
-
-import { SendCryptoAssetSelectors } from '@tests/selectors/send.selectors';
-import { Stack } from 'leather-styles/jsx';
-import get from 'lodash.get';
-
-import { decodeBitcoinTx } from '@leather.io/bitcoin';
-import { useBitcoinBroadcastTransaction } from '@leather.io/query';
-import { Button } from '@leather.io/ui';
-import { createMoney, formatMoney, formatMoneyPadded, sumMoney } from '@leather.io/utils';
-
-import { RouteUrls } from '@shared/route-urls';
-import { analytics } from '@shared/utils/analytics';
-
-import {
- InfoCardAssetValue,
- InfoCardRow,
- InfoCardSeparator,
-} from '@app/components/info-card/info-card';
-import { Card, Content, Page } from '@app/components/layout';
-import { PageHeader } from '@app/features/container/headers/page.header';
-import { useCurrentNativeSegwitUtxos } from '@app/query/bitcoin/address/utxos-by-address.hooks';
-import { useBrc20Transfers } from '@app/query/bitcoin/ordinals/brc20/brc20-tokens.hooks';
-
-import { useSendFormNavigate } from '../../hooks/use-send-form-navigate';
-
-function useBrc20SendFormConfirmationState() {
- const location = useLocation();
- return {
- orderId: get(location.state, 'orderId') as string,
- fee: get(location.state, 'fee') as string,
- feeRowValue: get(location.state, 'feeRowValue') as string,
- serviceFee: get(location.state, 'serviceFee') as number,
- serviceFeeRecipient: get(location.state, 'serviceFeeRecipient') as string,
- recipient: get(location.state, 'recipient') as string,
- ticker: get(location.state, 'ticker') as string,
- amount: get(location.state, 'amount') as string,
- tx: get(location.state, 'tx') as string,
- holderAddress: get(location.state, 'holderAddress') as string,
- };
-}
-
-export function Brc20SendFormConfirmation() {
- const navigate = useNavigate();
-
- const { amount, recipient, fee, ticker, serviceFee, tx, orderId, feeRowValue, holderAddress } =
- useBrc20SendFormConfirmationState();
-
- const summaryFeeMoney = createMoney(Number(fee), 'BTC');
-
- const serviceFeeMoney = createMoney(serviceFee, 'BTC');
- const serviceFeeFormatted = formatMoneyPadded(serviceFeeMoney);
-
- const totalFee = sumMoney([summaryFeeMoney, serviceFeeMoney]);
- const totalFeeFormatted = formatMoney(totalFee);
-
- const amountFormatted = formatMoney(createMoney(Number(amount), ticker, 0));
- const { broadcastTx, isBroadcasting } = useBitcoinBroadcastTransaction();
- const { filteredUtxosQuery } = useCurrentNativeSegwitUtxos();
-
- const psbt = decodeBitcoinTx(tx);
- const nav = useSendFormNavigate();
-
- const { inscriptionPaymentTransactionComplete } = useBrc20Transfers(holderAddress);
-
- async function initiateTransaction() {
- await broadcastTx({
- tx,
- async onSuccess(txId: string) {
- inscriptionPaymentTransactionComplete(orderId, Number(amount), recipient, ticker);
-
- void analytics.track('broadcast_transaction', {
- symbol: ticker,
- type: 'brc-20',
- amount,
- fee,
- inputs: psbt.inputs.length,
- outputs: psbt.inputs.length,
- });
- await filteredUtxosQuery.refetch();
- navigate(RouteUrls.SentBrc20Summary.replace(':ticker', ticker), {
- state: {
- serviceFee: serviceFeeFormatted,
- totalFee: totalFeeFormatted,
- recipient,
- ticker,
- amount,
- txId,
- feeRowValue,
- txLink: {
- blockchain: 'bitcoin',
- txid: txId || '',
- },
- },
- });
- },
- onError(e) {
- void analytics.track('broadcast_brc20_error', {
- error: e,
- });
-
- nav.toErrorPage(e);
- },
- });
- }
-
- return (
- <>
-
-
-
-
- Create transfer inscription
-
- }
- >
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/src/app/pages/send/send-crypto-asset-form/form/brc20/brc20-send-form.tsx b/src/app/pages/send/send-crypto-asset-form/form/brc20/brc20-send-form.tsx
deleted file mode 100644
index c1220fc368a..00000000000
--- a/src/app/pages/send/send-crypto-asset-form/form/brc20/brc20-send-form.tsx
+++ /dev/null
@@ -1,119 +0,0 @@
-import { Outlet, useLocation } from 'react-router-dom';
-
-import { SendCryptoAssetSelectors } from '@tests/selectors/send.selectors';
-import { Form, Formik } from 'formik';
-import { styled } from 'leather-styles/jsx';
-import get from 'lodash.get';
-
-import type { MarketData, Money } from '@leather.io/models';
-import { Brc20AvatarIcon, Button, Callout, Link } from '@leather.io/ui';
-import { convertAmountToBaseUnit, formatMoney } from '@leather.io/utils';
-
-import { openInNewTab } from '@app/common/utils/open-in-new-tab';
-import { AvailableBalance, ButtonRow, Card, Content, Page } from '@app/components/layout';
-import { PageHeader } from '@app/features/container/headers/page.header';
-
-import { AmountField } from '../../components/amount-field';
-import { SelectedAssetField } from '../../components/selected-asset-field';
-import { SendFiatValue } from '../../components/send-fiat-value';
-import { SendMaxButton } from '../../components/send-max-button';
-import { defaultSendFormFormikProps } from '../../send-form.utils';
-import { useBrc20SendForm } from './use-brc20-send-form';
-
-function useBrc20SendFormRouteState() {
- const { state } = useLocation();
- return {
- balance: get(state, 'balance', '') as Money,
- ticker: get(state, 'ticker', '') as string,
- holderAddress: get(state, 'holderAddress', '') as string,
- marketData: get(state, 'marketData') as MarketData,
- };
-}
-
-export function Brc20SendForm() {
- const { balance, ticker, holderAddress, marketData } = useBrc20SendFormRouteState();
- const { initialValues, chooseTransactionFee, validationSchema, formRef, onFormStateChange } =
- useBrc20SendForm({ balance, ticker, holderAddress });
-
- return (
- <>
-
-
-
-
- {props => {
- onFormStateChange(props.values);
- return (
-
- );
- }}
-
-
-
- >
- );
-}
diff --git a/src/app/pages/send/send-crypto-asset-form/form/brc20/use-brc20-send-form.tsx b/src/app/pages/send/send-crypto-asset-form/form/brc20/use-brc20-send-form.tsx
deleted file mode 100644
index 5d8eb3e23bd..00000000000
--- a/src/app/pages/send/send-crypto-asset-form/form/brc20/use-brc20-send-form.tsx
+++ /dev/null
@@ -1,87 +0,0 @@
-import { useRef } from 'react';
-import { useNavigate } from 'react-router-dom';
-
-import { FormikHelpers, FormikProps } from 'formik';
-import * as yup from 'yup';
-
-import type { Money } from '@leather.io/models';
-import { noop } from '@leather.io/utils';
-
-import { btcAddressNetworkValidator, btcAddressValidator } from '@shared/forms/address-validators';
-import { logger } from '@shared/logger';
-import { RouteUrls } from '@shared/route-urls';
-
-import { useOnMount } from '@app/common/hooks/use-on-mount';
-import { useWalletType } from '@app/common/use-wallet-type';
-import { tokenAmountValidator } from '@app/common/validation/forms/amount-validators';
-import { currencyAmountValidator } from '@app/common/validation/forms/currency-validators';
-import { useUpdatePersistedSendFormValues } from '@app/features/popup-send-form-restoration/use-update-persisted-send-form-values';
-import { useCurrentNativeSegwitUtxos } from '@app/query/bitcoin/address/utxos-by-address.hooks';
-import { useCurrentAccountNativeSegwitIndexZeroSigner } from '@app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks';
-import { useCurrentNetwork } from '@app/store/networks/networks.selectors';
-
-import { createDefaultInitialFormValues } from '../../send-form.utils';
-
-interface Brc20SendFormValues {
- recipient: string;
- amount: string;
- symbol: string;
-}
-
-interface UseBrc20SendFormArgs {
- balance: Money;
- ticker: string;
- holderAddress: string;
-}
-
-export function useBrc20SendForm({ balance, ticker, holderAddress }: UseBrc20SendFormArgs) {
- const formRef = useRef>(null);
- const { whenWallet } = useWalletType();
- const navigate = useNavigate();
- const currentNetwork = useCurrentNetwork();
- const nativeSegwitSigner = useCurrentAccountNativeSegwitIndexZeroSigner();
- const { data: utxos = [], filteredUtxosQuery } = useCurrentNativeSegwitUtxos();
-
- // Forcing a refetch to ensure UTXOs are fresh
- useOnMount(() => filteredUtxosQuery.refetch());
-
- // TODO: change recipient to that one user iputs
- const initialValues = createDefaultInitialFormValues({
- recipient: nativeSegwitSigner.address,
- amount: '',
- symbol: ticker,
- });
-
- const validationSchema = yup.object({
- amount: yup.number().concat(currencyAmountValidator()).concat(tokenAmountValidator(balance)),
- recipient: yup
- .string()
- .concat(btcAddressValidator())
- .concat(btcAddressNetworkValidator(currentNetwork.chain.bitcoin.bitcoinNetwork)),
- });
- const { onFormStateChange } = useUpdatePersistedSendFormValues();
-
- async function chooseTransactionFee(
- values: Brc20SendFormValues,
- formikHelpers: FormikHelpers
- ) {
- logger.debug('btc form values', values);
- // Validate and check high fee warning first
- await formikHelpers.validateForm();
- whenWallet({
- software: () =>
- navigate(RouteUrls.SendBrc20ChooseFee.replace(':ticker', ticker), {
- state: { ...values, ticker, utxos, holderAddress, hasHeaderTitle: true },
- }),
- ledger: noop,
- })();
- }
-
- return {
- initialValues,
- chooseTransactionFee,
- validationSchema,
- formRef,
- onFormStateChange,
- };
-}
diff --git a/src/app/pages/send/send-crypto-asset-form/send-crypto-asset-form.routes.tsx b/src/app/pages/send/send-crypto-asset-form/send-crypto-asset-form.routes.tsx
index 7b734acad88..21e92aac41c 100644
--- a/src/app/pages/send/send-crypto-asset-form/send-crypto-asset-form.routes.tsx
+++ b/src/app/pages/send/send-crypto-asset-form/send-crypto-asset-form.routes.tsx
@@ -14,14 +14,10 @@ import { AccountGate } from '@app/routes/account-gate';
import { BroadcastError } from '../broadcast-error/broadcast-error';
import { ChooseCryptoAsset } from '../choose-crypto-asset/choose-crypto-asset';
-import { Brc20SentSummary } from '../sent-summary/brc20-sent-summary';
import { BtcSentSummary } from '../sent-summary/btc-sent-summary';
import { StxSentSummary } from '../sent-summary/stx-sent-summary';
import { RecipientAccountsSheet } from './components/recipient-accounts-dialog/recipient-accounts-dialog';
import { SendBitcoinAssetContainer } from './family/bitcoin/components/send-bitcoin-asset-container';
-import { BrcChooseFee } from './form/brc20/brc20-choose-fee';
-import { Brc20SendForm } from './form/brc20/brc20-send-form';
-import { Brc20SendFormConfirmation } from './form/brc20/brc20-send-form-confirmation';
import { BtcChooseFee } from './form/btc/btc-choose-fee';
import { BtcSendForm } from './form/btc/btc-send-form';
import { BtcSendFormConfirmation } from './form/btc/btc-send-form-confirmation';
@@ -70,13 +66,6 @@ export const sendCryptoAssetFormRoutes = (
{ledgerBitcoinTxSigningRoutes}
} />
-
- } />
- }>
- {ledgerBitcoinTxSigningRoutes}
-
- } />
- } />
-
-
-
-
- }
- label="Pending BRC-20 transfers"
- onClick={onClickLink}
- />
-
- }
- >
-
-
-
-
-
-
-
-
- You'll need to send the transfer inscription to your recipient of choice from
- the home screen once its status changes to "Ready to send"
-
- {
- openInNewTab(
- 'https://leather.gitbook.io/guides/bitcoin/sending-brc-20-tokens'
- );
- }}
- >
- Learn more
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-}
diff --git a/src/app/query/bitcoin/ordinals/brc20/brc20-tokens.hooks.ts b/src/app/query/bitcoin/ordinals/brc20/brc20-tokens.hooks.ts
index 6f3a7ca4043..69b4ed544a2 100644
--- a/src/app/query/bitcoin/ordinals/brc20/brc20-tokens.hooks.ts
+++ b/src/app/query/bitcoin/ordinals/brc20/brc20-tokens.hooks.ts
@@ -7,23 +7,16 @@ import {
createMarketPair,
} from '@leather.io/models';
import {
- createBrc20TransferInscription,
- encodeBrc20TransferInscription,
isFetchedWithSuccess,
- useAverageBitcoinFeeRates,
useCalculateBitcoinFiatValue,
useConfigOrdinalsbot,
useGetBrc20TokensQuery,
- useOrdinalsbotClient,
} from '@leather.io/query';
import { createMoney, unitToFractionalUnit } from '@leather.io/utils';
-import { useAppDispatch } from '@app/store';
-import { useCurrentAccountIndex } from '@app/store/accounts/account';
import { useCurrentAccountNativeSegwitIndexZeroSigner } from '@app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks';
import { useCurrentAccountTaprootSigner } from '@app/store/accounts/blockchain/bitcoin/taproot-account.hooks';
import { useCurrentNetwork } from '@app/store/networks/networks.selectors';
-import { brc20TransferInitiated } from '@app/store/ordinals/ordinals.slice';
// ts-unused-exports:disable-next-line
export function useBrc20FeatureFlag() {
@@ -46,50 +39,6 @@ export function useBrc20FeatureFlag() {
return { enabled: true } as const;
}
-export function useBrc20Transfers(holderAddress: string) {
- const dispatch = useAppDispatch();
- const currentAccountIndex = useCurrentAccountIndex();
- const ordinalsbotClient = useOrdinalsbotClient();
- const { data: fees } = useAverageBitcoinFeeRates();
-
- return {
- async initiateTransfer(tick: string, amount: string) {
- const transferInscription = createBrc20TransferInscription(tick, Number(amount));
- const { payload, size } = encodeBrc20TransferInscription(transferInscription);
-
- const order = await ordinalsbotClient.order({
- receiveAddress: holderAddress,
- file: payload,
- size,
- name: `${tick}-${amount}.txt`,
- fee: fees?.halfHourFee.toNumber() ?? 10,
- });
-
- if (order.data.status !== 'ok') throw new Error('Failed to initiate transfer');
-
- return { id: order.data.id, order };
- },
-
- inscriptionPaymentTransactionComplete(
- orderId: string,
- amount: number,
- recipient: string,
- tick: string
- ) {
- dispatch(
- brc20TransferInitiated({
- accountIndex: currentAccountIndex,
- amount,
- tick,
- recipient,
- status: 'pending',
- id: orderId,
- })
- );
- },
- };
-}
-
function createBrc20CryptoAssetInfo(decimals: number, ticker: string): Brc20CryptoAssetInfo {
return {
decimals,
diff --git a/src/app/query/bitcoin/ordinals/brc20/use-check-order-status.ts b/src/app/query/bitcoin/ordinals/brc20/use-check-order-status.ts
deleted file mode 100644
index 7adf7c5040f..00000000000
--- a/src/app/query/bitcoin/ordinals/brc20/use-check-order-status.ts
+++ /dev/null
@@ -1,71 +0,0 @@
-import { useQueries } from '@tanstack/react-query';
-
-import { fetchInscripionById, useOrdinalsbotClient } from '@leather.io/query';
-
-import { useAppDispatch } from '@app/store';
-import {
- brc20OrderNotFound,
- brc20TransferAwaitingIndexer,
- brc20TransferPaid,
- brc20TransferReady,
- usePendingBrc20TransferEntities,
-} from '@app/store/ordinals/ordinals.slice';
-
-export function useCheckOrderStatuses(ids: string[]) {
- const ordinalsbotClient = useOrdinalsbotClient();
-
- const transferMap = usePendingBrc20TransferEntities();
- const dispatch = useAppDispatch();
-
- return useQueries({
- queries: ids.map(id => ({
- queryKey: ['check-order-status', id],
- queryFn: async () => ordinalsbotClient.orderStatus(id),
- async onSuccess({ data }: Awaited>) {
- if (data.status === 'error') {
- if (data.error.includes('no such order')) {
- dispatch(brc20OrderNotFound({ id }));
- }
- return;
- }
-
- const entry = transferMap[data.id];
-
- if (!entry) return;
-
- const file = data.files[0];
-
- // inscription reported by service
- if ('tx' in file) {
- // see if its on hiro indexer
- try {
- const { data: inscription } = await fetchInscripionById(file.tx?.inscription ?? '');
- // use number to determine legit
- if (inscription.number) {
- dispatch(
- brc20TransferReady({
- id: data.id,
- inscriptionId: file.tx?.inscription ?? '',
- })
- );
- return;
- }
- } catch (error) {}
-
- // or say awaiting indexer
- dispatch(brc20TransferAwaitingIndexer({ id: data.id }));
- return;
- }
-
- if (data.paid && entry.status !== 'paid') {
- dispatch(brc20TransferPaid({ id: data.id }));
- return;
- }
- },
- refetchInterval: 30000,
- refetchOnMount: true,
- refetchIntervalInBackground: true,
- refetchOnWindowFocus: false,
- })),
- });
-}
diff --git a/src/app/store/index.ts b/src/app/store/index.ts
index 9a040547c6d..850f2172cf8 100644
--- a/src/app/store/index.ts
+++ b/src/app/store/index.ts
@@ -30,7 +30,6 @@ import { inMemoryKeySlice } from './in-memory-key/in-memory-key.slice';
import { bitcoinKeysSlice } from './ledger/bitcoin/bitcoin-key.slice';
import { stacksKeysSlice } from './ledger/stacks/stacks-key.slice';
import { networksSlice } from './networks/networks.slice';
-import { ordinalsSlice } from './ordinals/ordinals.slice';
import { settingsSlice } from './settings/settings.slice';
import { keySlice } from './software-keys/software-key.slice';
import { submittedTransactionsSlice } from './submitted-transactions/submitted-transactions.slice';
@@ -45,7 +44,6 @@ export interface RootState {
bitcoin: ReturnType;
stacks: ReturnType;
};
- ordinals: ReturnType;
inMemoryKeys: ReturnType;
softwareKeys: ReturnType;
networks: ReturnType;
@@ -62,9 +60,9 @@ const appReducer = combineReducers({
bitcoin: bitcoinKeysSlice.reducer,
stacks: stacksKeysSlice.reducer,
}),
- ordinals: ordinalsSlice.reducer,
inMemoryKeys: inMemoryKeySlice.reducer,
softwareKeys: keySlice.reducer,
+ ordinals: (state = {}) => state,
networks: networksSlice.reducer,
submittedTransactions: submittedTransactionsSlice.reducer,
settings: settingsSlice.reducer,
diff --git a/src/app/store/ordinals/ordinals.slice.ts b/src/app/store/ordinals/ordinals.slice.ts
deleted file mode 100644
index d782413f8f9..00000000000
--- a/src/app/store/ordinals/ordinals.slice.ts
+++ /dev/null
@@ -1,108 +0,0 @@
-import { useSelector } from 'react-redux';
-
-import { PayloadAction, createEntityAdapter, createSelector, createSlice } from '@reduxjs/toolkit';
-
-import { RootState } from '..';
-import { selectCurrentAccountIndex } from '../software-keys/software-key.selectors';
-
-export type OrdinalsbotInscriptionStatus = 'pending' | 'paid' | 'waiting-for-indexer' | 'ready';
-
-interface BasePendingBrc20Transfer {
- status: OrdinalsbotInscriptionStatus;
- accountIndex: number;
- id: string;
- recipient: string;
- amount: number;
- tick: string;
-}
-interface ReadyPendingBrc20Transfer extends BasePendingBrc20Transfer {
- status: 'ready';
- inscriptionId: string;
- accountIndex: number;
- id: string;
- recipient: string;
- amount: number;
- tick: string;
-}
-
-function isReadyPendingBrc20Transfer(t: PendingBrc20Transfer): t is ReadyPendingBrc20Transfer {
- return t.status === 'ready';
-}
-
-export type PendingBrc20Transfer = BasePendingBrc20Transfer | ReadyPendingBrc20Transfer;
-
-const ordinalsAdapter = createEntityAdapter();
-
-export const ordinalsSlice = createSlice({
- name: 'ordinals',
- initialState: ordinalsAdapter.getInitialState(),
- reducers: {
- brc20TransferInitiated: ordinalsAdapter.addOne,
- brc20TransferPaid(state, action: PayloadAction<{ id: string }>) {
- const transfer = state.entities[action.payload.id];
- if (!transfer) return;
- transfer.status = 'paid';
- },
- brc20TransferAwaitingIndexer(state, action: PayloadAction<{ id: string }>) {
- const transfer = state.entities[action.payload.id];
- if (!transfer) return;
- transfer.status = 'waiting-for-indexer';
- },
- brc20TransferReady(state, action: PayloadAction<{ id: string; inscriptionId: string }>) {
- const transfer = state.entities[action.payload.id] as ReadyPendingBrc20Transfer | undefined;
- if (!transfer) return;
- transfer.status = 'ready';
- transfer.inscriptionId = action.payload.inscriptionId;
- },
- brc20OrderNotFound(state, action: PayloadAction<{ id: string }>) {
- const transferMatch = ordinalsAdapter
- .getSelectors()
- .selectAll(state)
- .find(transfer => transfer.id === action.payload.id);
- if (!transferMatch) return;
- ordinalsAdapter.removeOne(state, transferMatch.id);
- },
- inscriptionSent(state, action: PayloadAction<{ inscriptionId: string }>) {
- const transferMatch = ordinalsAdapter
- .getSelectors()
- .selectAll(state)
- .filter(isReadyPendingBrc20Transfer)
- .find(pendingTransfer => pendingTransfer.inscriptionId === action.payload.inscriptionId);
- if (!transferMatch) return;
- ordinalsAdapter.removeOne(state, transferMatch.id);
- },
- },
-});
-
-export const {
- brc20TransferInitiated,
- brc20TransferPaid,
- brc20TransferAwaitingIndexer,
- brc20TransferReady,
- brc20OrderNotFound,
- inscriptionSent,
-} = ordinalsSlice.actions;
-
-const selectors = ordinalsAdapter.getSelectors();
-
-function selectBrc20TransferState(state: RootState) {
- return state.ordinals;
-}
-
-const selectAllTransfers = createSelector(selectBrc20TransferState, selectors.selectAll);
-
-const selectAllTransfersMap = createSelector(selectBrc20TransferState, selectors.selectEntities);
-
-const selectCurrentAccountBrc20Transfers = createSelector(
- selectAllTransfers,
- selectCurrentAccountIndex,
- (transfers, accountIndex) => transfers.filter(t => t.accountIndex === accountIndex)
-);
-
-export function usePendingBrc20Transfers() {
- return useSelector(selectCurrentAccountBrc20Transfers);
-}
-
-export function usePendingBrc20TransferEntities() {
- return useSelector(selectAllTransfersMap);
-}
diff --git a/src/shared/route-urls.ts b/src/shared/route-urls.ts
index fa45650284f..3e5230377b4 100644
--- a/src/shared/route-urls.ts
+++ b/src/shared/route-urls.ts
@@ -61,10 +61,6 @@ export enum RouteUrls {
SendStacksSip10Confirmation = '/send/:symbol/confirm',
SentBtcTxSummary = '/sent/btc/:txId',
SentStxTxSummary = '/sent/stx/:txId',
- SendBrc20SendForm = '/send/brc20/:ticker',
- SendBrc20ChooseFee = '/send/brc20/:ticker/choose-fee',
- SendBrc20Confirmation = '/send/brc20/:ticker/confirm',
- SentBrc20Summary = '/send/brc20/:ticker/summary',
// Send ordinal inscriptions
SendOrdinalInscription = 'send/ordinal-inscription',