mirror of
https://github.com/zhigang1992/wallet.git
synced 2026-01-12 22:53:27 +08:00
refactor: psbt ui inputs query
This commit is contained in:
@@ -3,7 +3,10 @@ import { BitcoinTransactionItem } from '@app/features/activity-list/components/t
|
||||
import { StacksTransaction } from './stacks-transaction/stacks-transaction';
|
||||
import { TransactionListTxs } from './transaction-list.model';
|
||||
|
||||
function renderTransaction(tx: TransactionListTxs) {
|
||||
interface TransactionListItemProps {
|
||||
tx: TransactionListTxs;
|
||||
}
|
||||
export function TransactionListItem({ tx }: TransactionListItemProps) {
|
||||
switch (tx.blockchain) {
|
||||
case 'bitcoin':
|
||||
return <BitcoinTransactionItem transaction={tx.transaction} />;
|
||||
@@ -13,10 +16,3 @@ function renderTransaction(tx: TransactionListTxs) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
interface TransactionListItemProps {
|
||||
tx: TransactionListTxs;
|
||||
}
|
||||
export function TransactionListItem({ tx }: TransactionListItemProps) {
|
||||
return renderTransaction(tx);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
import * as btc from '@scure/btc-signer';
|
||||
|
||||
import {
|
||||
PsbtDecodedUtxosMainnet,
|
||||
PsbtDecodedUtxosTestnet,
|
||||
} from '@app/features/psbt-signer/hooks/use-psbt-decoded-utxos';
|
||||
|
||||
import { PsbtPlaceholderNode } from '../psbt-decoded-request-node/psbt-placeholder-node';
|
||||
import { PsbtUnsignedInputList } from '../psbt-unsigned-input-list/psbt-unsigned-input-list';
|
||||
import { PsbtUnsignedOutputList } from '../psbt-unsigned-output-list/psbt-unsigned-output-list';
|
||||
@@ -7,16 +12,17 @@ import { PsbtUnsignedOutputList } from '../psbt-unsigned-output-list/psbt-unsign
|
||||
interface PsbtDecodedRequestSimpleProps {
|
||||
bitcoinAddressNativeSegwit: string;
|
||||
bitcoinAddressTaproot: string;
|
||||
inputs: btc.TransactionInputRequired[];
|
||||
inputs: PsbtDecodedUtxosMainnet | PsbtDecodedUtxosTestnet;
|
||||
outputs: btc.TransactionOutputRequired[];
|
||||
showPlaceholder: boolean;
|
||||
}
|
||||
|
||||
export function PsbtDecodedRequestSimple({
|
||||
bitcoinAddressNativeSegwit,
|
||||
bitcoinAddressTaproot,
|
||||
inputs,
|
||||
outputs,
|
||||
showPlaceholder,
|
||||
inputs,
|
||||
}: PsbtDecodedRequestSimpleProps) {
|
||||
if (showPlaceholder) return <PsbtPlaceholderNode />;
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ export function PsbtDecodedRequest({ psbt }: PsbtDecodedRequestProps) {
|
||||
shouldDefaultToAdvancedView,
|
||||
shouldShowPlaceholder,
|
||||
showAdvancedView,
|
||||
unsignedUtxos,
|
||||
} = usePsbtDecodedRequest({
|
||||
unsignedInputs,
|
||||
unsignedOutputs,
|
||||
@@ -45,7 +46,7 @@ export function PsbtDecodedRequest({ psbt }: PsbtDecodedRequestProps) {
|
||||
<PsbtDecodedRequestSimple
|
||||
bitcoinAddressNativeSegwit={nativeSegwitSigner.address}
|
||||
bitcoinAddressTaproot={bitcoinAddressTaproot}
|
||||
inputs={unsignedInputs}
|
||||
inputs={unsignedUtxos}
|
||||
outputs={unsignedOutputs}
|
||||
showPlaceholder={shouldShowPlaceholder}
|
||||
/>
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
import { truncateMiddle } from '@stacks/ui-utils';
|
||||
|
||||
import { logger } from '@shared/logger';
|
||||
|
||||
import { i18nFormatCurrency } from '@app/common/money/format-money';
|
||||
import { satToBtc } from '@app/common/money/unit-conversion';
|
||||
import { OrdApiInscriptionTxOutput } from '@app/query/bitcoin/ordinals/ordinals-aware-utxo.query';
|
||||
import { TaprootUtxo } from '@app/query/bitcoin/ordinals/use-taproot-address-utxos.query';
|
||||
import { useCalculateBitcoinFiatValue } from '@app/query/common/market-data/market-data.hooks';
|
||||
|
||||
import { PsbtDecodedNodeLayout } from '../../psbt-decoded-request-node/psbt-decoded-node.layout';
|
||||
import { PsbtUnsignedInputWithInscription } from './psbt-unsigned-input-with-inscription';
|
||||
|
||||
interface PsbtUnsignedInputItemWithPossibleInscriptionProps {
|
||||
addressNativeSegwit: string;
|
||||
addressTaproot: string;
|
||||
utxo: TaprootUtxo & OrdApiInscriptionTxOutput;
|
||||
}
|
||||
export function PsbtUnsignedInputItemWithPossibleInscription({
|
||||
addressNativeSegwit,
|
||||
addressTaproot,
|
||||
utxo,
|
||||
}: PsbtUnsignedInputItemWithPossibleInscriptionProps) {
|
||||
const calculateBitcoinFiatValue = useCalculateBitcoinFiatValue();
|
||||
|
||||
const isInputCurrentAddress =
|
||||
utxo.address === addressNativeSegwit || utxo.address === addressTaproot;
|
||||
const inputValue = satToBtc(utxo.value).toString();
|
||||
|
||||
if (!utxo.address) {
|
||||
logger.error('UTXO does not have an address');
|
||||
return null;
|
||||
}
|
||||
|
||||
return utxo.inscriptions ? (
|
||||
<PsbtUnsignedInputWithInscription
|
||||
address={utxo.address}
|
||||
inputValue={inputValue}
|
||||
path={utxo.inscriptions}
|
||||
/>
|
||||
) : (
|
||||
<PsbtDecodedNodeLayout
|
||||
hoverLabel={utxo.address}
|
||||
subtitle={truncateMiddle(utxo.address)}
|
||||
subValue={i18nFormatCurrency(calculateBitcoinFiatValue(inputValue))}
|
||||
value={`${isInputCurrentAddress ? '-' : '+'}${inputValue}`}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -1,18 +1,17 @@
|
||||
import { truncateMiddle } from '@stacks/ui-utils';
|
||||
|
||||
import { BitcoinTransactionVectorOutput } from '@shared/models/transactions/bitcoin-transaction.model';
|
||||
|
||||
import { i18nFormatCurrency } from '@app/common/money/format-money';
|
||||
import { satToBtc } from '@app/common/money/unit-conversion';
|
||||
import { OrdApiInscriptionTxOutput } from '@app/query/bitcoin/ordinals/ordinals-aware-utxo.query';
|
||||
import { TaprootUtxo } from '@app/query/bitcoin/ordinals/use-taproot-address-utxos.query';
|
||||
import { useCalculateBitcoinFiatValue } from '@app/query/common/market-data/market-data.hooks';
|
||||
|
||||
import { PsbtDecodedNodeLayout } from '../../psbt-decoded-request-node/psbt-decoded-node.layout';
|
||||
import { PsbtUnsignedInputWithInscription } from './psbt-unsigned-input-with-inscription';
|
||||
|
||||
interface PsbtUnsignedInputItemProps {
|
||||
addressNativeSegwit: string;
|
||||
addressTaproot: string;
|
||||
utxo: TaprootUtxo & OrdApiInscriptionTxOutput;
|
||||
utxo: BitcoinTransactionVectorOutput;
|
||||
}
|
||||
export function PsbtUnsignedInputItem({
|
||||
addressNativeSegwit,
|
||||
@@ -22,24 +21,15 @@ export function PsbtUnsignedInputItem({
|
||||
const calculateBitcoinFiatValue = useCalculateBitcoinFiatValue();
|
||||
|
||||
const isInputCurrentAddress =
|
||||
utxo.address === addressNativeSegwit || utxo.address === addressTaproot;
|
||||
utxo.scriptpubkey_address === addressNativeSegwit ||
|
||||
utxo.scriptpubkey_address === addressTaproot;
|
||||
const inputValue = satToBtc(utxo.value).toString();
|
||||
const fiatValue = i18nFormatCurrency(calculateBitcoinFiatValue(utxo.value));
|
||||
const inscription = utxo.inscriptions;
|
||||
|
||||
if (!utxo.address) return null;
|
||||
|
||||
return inscription ? (
|
||||
<PsbtUnsignedInputWithInscription
|
||||
address={utxo.address}
|
||||
inputValue={inputValue}
|
||||
path={inscription}
|
||||
/>
|
||||
) : (
|
||||
return (
|
||||
<PsbtDecodedNodeLayout
|
||||
hoverLabel={utxo.address}
|
||||
subtitle={truncateMiddle(utxo.address)}
|
||||
subValue={`${fiatValue} USD`}
|
||||
hoverLabel={utxo.scriptpubkey_address}
|
||||
subtitle={truncateMiddle(utxo.scriptpubkey_address)}
|
||||
subValue={i18nFormatCurrency(calculateBitcoinFiatValue(inputValue))}
|
||||
value={`${isInputCurrentAddress ? '-' : '+'}${inputValue}`}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Box, Text } from '@stacks/ui';
|
||||
|
||||
import { HasChildren } from '@app/common/has-children';
|
||||
|
||||
export function PsbtUnsignedInputListLayout({ children }: HasChildren) {
|
||||
return (
|
||||
<Box background="white" borderTopLeftRadius="16px" borderTopRightRadius="16px" p="loose">
|
||||
<Text fontWeight={500}>Inputs</Text>
|
||||
{children}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@@ -1,40 +1,62 @@
|
||||
import * as btc from '@scure/btc-signer';
|
||||
import { Box, Text } from '@stacks/ui';
|
||||
|
||||
import { isUndefined } from '@shared/utils';
|
||||
|
||||
import { useOrdinalsAwareUtxoQueries } from '@app/query/bitcoin/ordinals/ordinals-aware-utxo.query';
|
||||
import {
|
||||
PsbtDecodedUtxosMainnet,
|
||||
PsbtDecodedUtxosTestnet,
|
||||
} from '@app/features/psbt-signer/hooks/use-psbt-decoded-utxos';
|
||||
|
||||
import { PsbtDecodedNodeLayout } from '../psbt-decoded-request-node/psbt-decoded-node.layout';
|
||||
import { PsbtUnsignedInputItem } from './components/psbt-unsigned-input-item';
|
||||
import { PsbtUnsignedInputItemWithPossibleInscription } from './components/psbt-unsigned-input-item-with-possible-inscription';
|
||||
import { PsbtUnsignedInputListLayout } from './components/psbt-unsigned-input-list.layout';
|
||||
|
||||
interface PsbtUnsignedInputListProps {
|
||||
addressNativeSegwit: string;
|
||||
addressTaproot: string;
|
||||
inputs: btc.TransactionInputRequired[];
|
||||
inputs: PsbtDecodedUtxosMainnet | PsbtDecodedUtxosTestnet;
|
||||
}
|
||||
export function PsbtUnsignedInputList({
|
||||
addressNativeSegwit,
|
||||
addressTaproot,
|
||||
inputs,
|
||||
}: PsbtUnsignedInputListProps) {
|
||||
const unsignedUtxos = useOrdinalsAwareUtxoQueries(inputs).map(query => query.data);
|
||||
if (!inputs.utxos.length)
|
||||
return (
|
||||
<PsbtUnsignedInputListLayout>
|
||||
<PsbtDecodedNodeLayout value="No inputs found" />
|
||||
</PsbtUnsignedInputListLayout>
|
||||
);
|
||||
|
||||
return (
|
||||
<Box background="white" borderTopLeftRadius="16px" borderTopRightRadius="16px" p="loose">
|
||||
<Text fontWeight={500}>Inputs</Text>
|
||||
{unsignedUtxos.map(utxo => {
|
||||
if (isUndefined(utxo)) return <PsbtDecodedNodeLayout value="No input data found" />;
|
||||
|
||||
return (
|
||||
<PsbtUnsignedInputItem
|
||||
addressNativeSegwit={addressNativeSegwit}
|
||||
addressTaproot={addressTaproot}
|
||||
key={utxo.transaction}
|
||||
utxo={utxo}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
);
|
||||
switch (inputs.network) {
|
||||
case 'mainnet':
|
||||
return (
|
||||
<PsbtUnsignedInputListLayout>
|
||||
{inputs.utxos.map((utxo, i) => {
|
||||
return (
|
||||
<PsbtUnsignedInputItemWithPossibleInscription
|
||||
addressNativeSegwit={addressNativeSegwit}
|
||||
addressTaproot={addressTaproot}
|
||||
key={i}
|
||||
utxo={utxo}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</PsbtUnsignedInputListLayout>
|
||||
);
|
||||
case 'testnet':
|
||||
return (
|
||||
<PsbtUnsignedInputListLayout>
|
||||
{inputs.utxos.map((utxo, i) => {
|
||||
return (
|
||||
<PsbtUnsignedInputItem
|
||||
addressNativeSegwit={addressNativeSegwit}
|
||||
addressTaproot={addressTaproot}
|
||||
key={i}
|
||||
utxo={utxo}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</PsbtUnsignedInputListLayout>
|
||||
);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ export function PsbtUnsignedOutputItem({
|
||||
<PsbtDecodedNodeLayout
|
||||
hoverLabel={addressFromScript}
|
||||
subtitle={truncateMiddle(addressFromScript)}
|
||||
subValue={`${i18nFormatCurrency(calculateBitcoinFiatValue(outputValue))} USD`}
|
||||
subValue={i18nFormatCurrency(calculateBitcoinFiatValue(outputValue))}
|
||||
value={`${isOutputCurrentAddress ? '+' : ' '}${outputValue}`}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Box, Text } from '@stacks/ui';
|
||||
|
||||
import { HasChildren } from '@app/common/has-children';
|
||||
|
||||
export function PsbtUnsignedOutputListLayout({ children }: HasChildren) {
|
||||
return (
|
||||
<Box background="white" borderTopLeftRadius="16px" borderTopRightRadius="16px" p="loose">
|
||||
<Text fontWeight={500}>Outputs</Text>
|
||||
{children}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
import * as btc from '@scure/btc-signer';
|
||||
import { Box, Text } from '@stacks/ui';
|
||||
|
||||
import { PsbtDecodedNodeLayout } from '../psbt-decoded-request-node/psbt-decoded-node.layout';
|
||||
import { PsbtUnsignedOutputItem } from './components/psbt-unsigned-output-item';
|
||||
import { PsbtUnsignedOutputListLayout } from './components/psbt-unsigned-output-list.layout';
|
||||
|
||||
interface PsbtUnsignedOutputListProps {
|
||||
addressNativeSegwit: string;
|
||||
@@ -13,9 +14,15 @@ export function PsbtUnsignedOutputList({
|
||||
addressTaproot,
|
||||
outputs,
|
||||
}: PsbtUnsignedOutputListProps) {
|
||||
if (!outputs.length)
|
||||
return (
|
||||
<PsbtUnsignedOutputListLayout>
|
||||
<PsbtDecodedNodeLayout value="No outputs found" />
|
||||
</PsbtUnsignedOutputListLayout>
|
||||
);
|
||||
|
||||
return (
|
||||
<Box background="white" borderBottomLeftRadius="16px" borderBottomRightRadius="16px" p="loose">
|
||||
<Text fontWeight={500}>Outputs</Text>
|
||||
<PsbtUnsignedOutputListLayout>
|
||||
{outputs.map((output, i) => {
|
||||
return (
|
||||
<PsbtUnsignedOutputItem
|
||||
@@ -26,6 +33,6 @@ export function PsbtUnsignedOutputList({
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
</PsbtUnsignedOutputListLayout>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,29 +4,41 @@ import * as btc from '@scure/btc-signer';
|
||||
|
||||
import { BitcoinNetworkModes } from '@shared/constants';
|
||||
import { getAddressFromOutScript } from '@shared/crypto/bitcoin/bitcoin.utils';
|
||||
import { isUndefined } from '@shared/utils';
|
||||
|
||||
import {
|
||||
OrdApiInscriptionTxOutput,
|
||||
useOrdinalsAwareUtxoQueries,
|
||||
} from '@app/query/bitcoin/ordinals/ordinals-aware-utxo.query';
|
||||
import { useCurrentAccountNativeSegwitIndexZeroSigner } from '@app/store/accounts/blockchain/bitcoin/native-segwit-account.hooks';
|
||||
import { useCurrentNetwork } from '@app/store/networks/networks.selectors';
|
||||
|
||||
import {
|
||||
PsbtDecodedUtxosMainnet,
|
||||
PsbtDecodedUtxosTestnet,
|
||||
usePsbtDecodedUtxos,
|
||||
} from './use-psbt-decoded-utxos';
|
||||
|
||||
function isPlaceholderTransaction(
|
||||
address: string,
|
||||
inputs: (OrdApiInscriptionTxOutput | undefined)[],
|
||||
outputs: btc.TransactionOutputRequired[],
|
||||
network: BitcoinNetworkModes
|
||||
network: BitcoinNetworkModes,
|
||||
unsignedOutputs: btc.TransactionOutputRequired[],
|
||||
unsignedUtxos: PsbtDecodedUtxosMainnet | PsbtDecodedUtxosTestnet
|
||||
) {
|
||||
const inputsNotFromCurrentAddress = inputs.filter(input => {
|
||||
return input?.address !== address;
|
||||
});
|
||||
const outputsNotToCurrentAddress = outputs.filter(output => {
|
||||
let utxosNotFromCurrentAddress = [];
|
||||
|
||||
switch (unsignedUtxos.network) {
|
||||
case 'mainnet':
|
||||
utxosNotFromCurrentAddress = unsignedUtxos.utxos.filter(utxo => utxo.address !== address);
|
||||
break;
|
||||
case 'testnet':
|
||||
utxosNotFromCurrentAddress = unsignedUtxos.utxos.filter(
|
||||
vo => vo.scriptpubkey_address !== address
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
const outputsNotToCurrentAddress = unsignedOutputs.filter(output => {
|
||||
const addressFromScript = getAddressFromOutScript(output.script, network);
|
||||
return addressFromScript !== address;
|
||||
});
|
||||
return inputsNotFromCurrentAddress.length === 0 && outputsNotToCurrentAddress.length === 0;
|
||||
|
||||
return utxosNotFromCurrentAddress.length === 0 && outputsNotToCurrentAddress.length === 0;
|
||||
}
|
||||
|
||||
interface UsePsbtDecodedRequestArgs {
|
||||
@@ -40,20 +52,20 @@ export function usePsbtDecodedRequest({
|
||||
const [showAdvancedView, setShowAdvancedView] = useState(false);
|
||||
const network = useCurrentNetwork();
|
||||
const nativeSegwitSigner = useCurrentAccountNativeSegwitIndexZeroSigner();
|
||||
const unsignedUtxos = useOrdinalsAwareUtxoQueries(unsignedInputs).map(query => query.data);
|
||||
const unsignedUtxos = usePsbtDecodedUtxos(unsignedInputs);
|
||||
|
||||
const defaultToAdvancedView = useCallback(() => {
|
||||
const noInputs = isUndefined(unsignedUtxos) || !unsignedUtxos.length;
|
||||
const noOutputs = isUndefined(unsignedOutputs) || !unsignedOutputs.length;
|
||||
const noInputs = !unsignedInputs.length;
|
||||
const noOutputs = !unsignedOutputs.length;
|
||||
return noInputs || noOutputs;
|
||||
}, [unsignedOutputs, unsignedUtxos]);
|
||||
}, [unsignedInputs.length, unsignedOutputs.length]);
|
||||
|
||||
const showPlaceholder = useCallback(() => {
|
||||
return isPlaceholderTransaction(
|
||||
nativeSegwitSigner.address,
|
||||
unsignedUtxos,
|
||||
network.chain.bitcoin.network,
|
||||
unsignedOutputs,
|
||||
network.chain.bitcoin.network
|
||||
unsignedUtxos
|
||||
);
|
||||
}, [nativeSegwitSigner.address, network.chain.bitcoin.network, unsignedOutputs, unsignedUtxos]);
|
||||
|
||||
@@ -62,5 +74,6 @@ export function usePsbtDecodedRequest({
|
||||
shouldDefaultToAdvancedView: defaultToAdvancedView(),
|
||||
shouldShowPlaceholder: showPlaceholder(),
|
||||
showAdvancedView,
|
||||
unsignedUtxos,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import * as btc from '@scure/btc-signer';
|
||||
|
||||
import { WalletDefaultNetworkConfigurationIds } from '@shared/constants';
|
||||
import { BitcoinTransactionVectorOutput } from '@shared/models/transactions/bitcoin-transaction.model';
|
||||
import { isDefined } from '@shared/utils';
|
||||
|
||||
import {
|
||||
OrdApiInscriptionTxOutput,
|
||||
useOrdinalsAwareUtxoQueries,
|
||||
} from '@app/query/bitcoin/ordinals/ordinals-aware-utxo.query';
|
||||
import { TaprootUtxo } from '@app/query/bitcoin/ordinals/use-taproot-address-utxos.query';
|
||||
import { useGetBitcoinTransactionQueries } from '@app/query/bitcoin/transaction/transaction.query';
|
||||
import { useCurrentNetwork } from '@app/store/networks/networks.selectors';
|
||||
|
||||
export interface PsbtDecodedUtxosMainnet {
|
||||
network: WalletDefaultNetworkConfigurationIds.mainnet;
|
||||
utxos: (TaprootUtxo & OrdApiInscriptionTxOutput)[];
|
||||
}
|
||||
|
||||
export interface PsbtDecodedUtxosTestnet {
|
||||
network: WalletDefaultNetworkConfigurationIds.testnet;
|
||||
utxos: BitcoinTransactionVectorOutput[];
|
||||
}
|
||||
|
||||
export function usePsbtDecodedUtxos(
|
||||
unsignedInputs: btc.TransactionInputRequired[]
|
||||
): PsbtDecodedUtxosMainnet | PsbtDecodedUtxosTestnet {
|
||||
const network = useCurrentNetwork();
|
||||
const unsignedUtxos = useGetBitcoinTransactionQueries(unsignedInputs)
|
||||
.map(query => query.data)
|
||||
.filter(isDefined)
|
||||
.map((input, i) => input.vout[unsignedInputs[i].index]);
|
||||
// Mainnet only enabled query
|
||||
const unsignedUtxosWithInscriptions = useOrdinalsAwareUtxoQueries(unsignedInputs)
|
||||
.map(query => query.data)
|
||||
.filter(isDefined);
|
||||
|
||||
return network.chain.bitcoin.network === 'mainnet' && unsignedUtxosWithInscriptions.length
|
||||
? {
|
||||
network: WalletDefaultNetworkConfigurationIds.mainnet,
|
||||
utxos: unsignedUtxosWithInscriptions,
|
||||
}
|
||||
: { network: WalletDefaultNetworkConfigurationIds.testnet, utxos: unsignedUtxos };
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import { isTypedArray } from '@shared/utils';
|
||||
import { Prettify } from '@shared/utils/type-utils';
|
||||
|
||||
import { QueryPrefixes } from '@app/query/query-prefixes';
|
||||
import { useCurrentNetwork } from '@app/store/networks/networks.selectors';
|
||||
|
||||
import { TaprootUtxo } from './use-taproot-address-utxos.query';
|
||||
|
||||
@@ -58,11 +59,14 @@ const queryOptions = {
|
||||
} as const;
|
||||
|
||||
export function useOrdinalsAwareUtxoQueries(utxos: TaprootUtxo[] | btc.TransactionInputRequired[]) {
|
||||
const network = useCurrentNetwork();
|
||||
|
||||
return useQueries({
|
||||
queries: utxos.map(utxo => {
|
||||
const txId = isTypedArray(utxo.txid) ? bytesToHex(utxo.txid) : utxo.txid;
|
||||
const txIndex = 'index' in utxo ? utxo.index : utxo.vout;
|
||||
return {
|
||||
enabled: network.chain.bitcoin.network === 'mainnet',
|
||||
queryKey: makeOrdinalsAwareUtxoQueryKey(txId, txIndex),
|
||||
queryFn: () => fetchOrdinalsAwareUtxo(txId, txIndex),
|
||||
select: (resp: OrdApiInscriptionTxOutput) =>
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import * as btc from '@scure/btc-signer';
|
||||
import { bytesToHex } from '@stacks/common';
|
||||
import { UseQueryResult, useQueries, useQuery } from '@tanstack/react-query';
|
||||
|
||||
import { BitcoinTransaction } from '@shared/models/transactions/bitcoin-transaction.model';
|
||||
|
||||
import { AppUseQueryConfig } from '@app/query/query-config';
|
||||
import { useBitcoinClient } from '@app/store/common/api-clients.hooks';
|
||||
@@ -29,3 +33,26 @@ export function useGetBitcoinTransaction<T extends unknown = FetchBitcoinTransac
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
||||
const queryOptions = {
|
||||
cacheTime: Infinity,
|
||||
staleTime: 15 * 60 * 1000,
|
||||
refetchOnWindowFocus: false,
|
||||
} as const;
|
||||
|
||||
export function useGetBitcoinTransactionQueries(
|
||||
inputs: btc.TransactionInputRequired[]
|
||||
): UseQueryResult<BitcoinTransaction>[] {
|
||||
const client = useBitcoinClient();
|
||||
|
||||
return useQueries({
|
||||
queries: inputs.map(input => {
|
||||
const txId = bytesToHex(input.txid);
|
||||
return {
|
||||
queryKey: ['bitcoin-transaction', txId],
|
||||
queryFn: () => fetchBitcoinTransaction(client)(txId),
|
||||
...queryOptions,
|
||||
};
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import { CryptoCurrencies } from '@shared/models/currencies.model';
|
||||
import { MarketData, createMarketData, createMarketPair } from '@shared/models/market.model';
|
||||
import { createMoney, currencyDecimalsMap } from '@shared/models/money.model';
|
||||
import { createMoneyFromDecimal } from '@shared/models/money.model';
|
||||
import { isNumber } from '@shared/utils';
|
||||
|
||||
import { calculateMeanAverage } from '@app/common/math/calculate-averages';
|
||||
import { convertAmountToFractionalUnit } from '@app/common/money/calculate-money';
|
||||
@@ -58,8 +59,11 @@ export function useCalculateBitcoinFiatValue() {
|
||||
const btcMarketData = useCryptoCurrencyMarketData('BTC');
|
||||
|
||||
return useCallback(
|
||||
(value: string) =>
|
||||
baseCurrencyAmountInQuote(createMoneyFromDecimal(Number(value), 'BTC'), btcMarketData),
|
||||
(value: string | number) =>
|
||||
baseCurrencyAmountInQuote(
|
||||
createMoneyFromDecimal(isNumber(value) ? value : Number(value), 'BTC'),
|
||||
btcMarketData
|
||||
),
|
||||
[btcMarketData]
|
||||
);
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ interface BitcoinTransactionStatus {
|
||||
block_time: number | null;
|
||||
}
|
||||
|
||||
interface BitcoinTransactionVectorOutput {
|
||||
export interface BitcoinTransactionVectorOutput {
|
||||
scriptpubkey: string;
|
||||
scriptpubkey_asm: string;
|
||||
scriptpubkey_type: string;
|
||||
|
||||
@@ -23,6 +23,10 @@ const bitcoinTestnet: BitcoinNetwork = {
|
||||
wif: 0xef,
|
||||
};
|
||||
|
||||
// For testing mainnet
|
||||
const tempHex =
|
||||
'70736274ff0100fd36010200000004350db8bb43dc351cf4f611aab22363c1fcfb27c61f2f7e55f3e38a1384248c660100000000ffffffff8fcf2bcf05c76ef86595c3bbe2f944064b34eede0c4c3c5dce4f1f94e663183d0000000000ffffffff8391b15b124ad2276c13916a61efabbfcc34f4211b3e6123829eaeab8096b8420000000000ffffffffe4653717d3c1544b073f97978998558be6c8e8aa7e51922303ec4814551fa16e0000000000ffffffff041027000000000000225120e25ef2545bce7dd7bd4215cdc76d16fe72c63163dca3f7a0757efa928841c96b7c920000000000001600146a9d9d7679bfeaf45c3a7d5b88826ec657ea91e2c4090000000000001600146a9d9d7679bfeaf45c3a7d5b88826ec657ea91e2983a0000000000001600149c1a4f6160d35ffada2e230f8bf1c4cfaf6ff52f00000000000100fdaa0301000000000102371586ae4679b5e411fced4b36ec421f65527447be8e3d0206419f979214fdf20000000000fdffffff5466bdc917b6a13f1db9429ee649a08b6b3860366e87202e0934d193e07a0d5b0100000000fdffffff02102700000000000022512044cab551f8178996c12870fcfd0399e3b0e4b9bb0312fc1c8b07b02e2dc17b0af92a0000000000002251207f4d47576eeaaa79a4cf320bf0b1876e50d943bdbbfc2823d99df37e642a37880140c6dff1e2084c2ae245c8b4b7751b9a5b1145f347d9d0ae06b8e2ec4591a2ab53fea2e5c6a356dfc6a54f51a7f15f1d1db8f056e8713842bfed58a1e063841c090341b00ba699988211aaa2e2464290bbc7db231765c5eaff65e0a7c2be27315093caa4009f2b302912f125d6bc28680bc1cfca7796647259e003a601f12683c1808081fd4c02204878d26dbb1678c06558222e1fd68e9ed68783fbb68d9f2bcb7ace09b225149dac0063036f726401032468eb6429a613f2564a36ce39589cda9ae404605267c4e0908c27ad1f144a0de900000000010117746578742f68746d6c3b636861727365743d7574662d38004dde013c626f64792f3e3c7363726970743e6a3d323b643d646f63756d656e743b623d642e626f64790a636c6173732055524c536561726368506172616d737b6765743d6b3d3e6b3d3d22746f6b656e4944223f6a3a307d286173796e6328293d3e7b713d225c6e220a6a3d393532302b282b617761697428617761697420666574636828222f636f6e74656e742f6463656538306631316133313034616233326633313665623763656466323839653436616531313533353362383165376432343362643431616462343734376669302229292e7465787428292b6a29253330300a69662869734e614e286a292972657475726e3b0a683d28617761697428617761697420666574636828222f636f6e74656e742f6539306434613134316661643237386339306530633436373532363030346534396164613963353833396365333634613536663231336136323936346562363869302229292e746578742829292e73706c69742871290a622e696e6e657248544d4c3d685b305d3b0a7a3d646f63756d656e742e637265617465456c656d656e74282273637269707422290a7a2e696e6e657248544d4c3d682e736c69636528322c34292e6a6f696e2871290a622e617070656e644368696c64287a297d2928293c2f7363726970743e0a6821c04878d26dbb1678c06558222e1fd68e9ed68783fbb68d9f2bcb7ace09b225149d0000000001012bf92a0000000000002251207f4d47576eeaaa79a4cf320bf0b1876e50d943bdbbfc2823d99df37e642a3788011720937077dcbafef4c74be898fbf723c628787f0d9922c384e6e80eded948d033ee000100df01000000000101e4653717d3c1544b073f97978998558be6c8e8aa7e51922303ec4814551fa16e0100000000fdffffff0260ea0000000000001600149c1a4f6160d35ffada2e230f8bf1c4cfaf6ff52fc81adf01000000001600143c2a59281416c1a9e9dc55170be53c5577d420e202483045022100bac8690acbd849d57687f889854f8abaf688f0b5e02eafa555ff3d86e62a8aad022071439d2bbae03118a0dc8fdb3e85405a459e0e7279f6f4659491fbfe11f1ce6601210234943fdac5b5d4d6c28e03b89a6adb6c7a3f55e782e718af3a251764a320da7500000000000100de0100000000010113edda3c24c6c3e0bdd37418ff173c558075010d763bb037773968e8f5f8da3f0000000000fdffffff0230750000000000001600149c1a4f6160d35ffada2e230f8bf1c4cfaf6ff52f712df800000000001600142547a6fb036a168e7cfb3359e7553c63e4252170024730440220060f1f5614a368bc319531050b043af5aa2d87222dc8cf134dc2b209588c6dfc0220069f1c978ed6cc68f5eef40e319697215a7f0f4ce5c5411a40d6bd08c69b3430012102567b081243c6b8439932d52e2f8a8bd2133ce18c4e63b6ee4a40e09dc73d897300000000000100de010000000001016c21dd4dc9508a4383dd364f5249d7f9c126093845dc9186e18bae449ff13e7a0000000000fdffffff02a8610000000000001600149c1a4f6160d35ffada2e230f8bf1c4cfaf6ff52fdf32e001000000001600142547a6fb036a168e7cfb3359e7553c63e4252170024730440220703a99388b1d04c7c1d22e79994e04100f19abb165105710bbe12a338930e45902204d8ed7eae8be52d06912911a0d3ad1dd2bf9d2f9ef0acf2e56293c3213d726e5012102d5369b8460ed3e38d6313bc308a207c7eed33ac6d18ced08ece56f885ce54657000000000000000000';
|
||||
|
||||
const ecdsaPublicKeyLength = 33;
|
||||
const TEST_TESTNET_ACCOUNT_1_PUBKEY_P2WPKH =
|
||||
'02b6b0afe5f620bc8e532b640b148dd9dea0ed19d11f8ab420fcce488fe3974893';
|
||||
@@ -67,7 +71,9 @@ function buildTestNativeSegwitPsbtRequest(pubKey: Uint8Array): PsbtRequestOption
|
||||
|
||||
const psbt = tx.toPSBT();
|
||||
|
||||
return { hex: bytesToHex(psbt) };
|
||||
// For testing mainnet
|
||||
return { hex: tempHex };
|
||||
// return { hex: bytesToHex(psbt) };
|
||||
}
|
||||
|
||||
function buildTestNativeSegwitPsbtRequestWithIndexes(pubKey: Uint8Array): PsbtRequestOptions {
|
||||
@@ -121,11 +127,7 @@ function buildTestTaprootPsbtRequest(pubKey: Uint8Array): PsbtRequestOptions {
|
||||
|
||||
const psbt = tx.toPSBT();
|
||||
|
||||
console.log('lksjdflksjdflkj');
|
||||
|
||||
return {
|
||||
hex: '70736274ff0100fd36010200000004350db8bb43dc351cf4f611aab22363c1fcfb27c61f2f7e55f3e38a1384248c660100000000ffffffff8fcf2bcf05c76ef86595c3bbe2f944064b34eede0c4c3c5dce4f1f94e663183d0000000000ffffffff8391b15b124ad2276c13916a61efabbfcc34f4211b3e6123829eaeab8096b8420000000000ffffffffe4653717d3c1544b073f97978998558be6c8e8aa7e51922303ec4814551fa16e0000000000ffffffff041027000000000000225120e25ef2545bce7dd7bd4215cdc76d16fe72c63163dca3f7a0757efa928841c96b7c920000000000001600146a9d9d7679bfeaf45c3a7d5b88826ec657ea91e2c4090000000000001600146a9d9d7679bfeaf45c3a7d5b88826ec657ea91e2983a0000000000001600149c1a4f6160d35ffada2e230f8bf1c4cfaf6ff52f00000000000100fdaa0301000000000102371586ae4679b5e411fced4b36ec421f65527447be8e3d0206419f979214fdf20000000000fdffffff5466bdc917b6a13f1db9429ee649a08b6b3860366e87202e0934d193e07a0d5b0100000000fdffffff02102700000000000022512044cab551f8178996c12870fcfd0399e3b0e4b9bb0312fc1c8b07b02e2dc17b0af92a0000000000002251207f4d47576eeaaa79a4cf320bf0b1876e50d943bdbbfc2823d99df37e642a37880140c6dff1e2084c2ae245c8b4b7751b9a5b1145f347d9d0ae06b8e2ec4591a2ab53fea2e5c6a356dfc6a54f51a7f15f1d1db8f056e8713842bfed58a1e063841c090341b00ba699988211aaa2e2464290bbc7db231765c5eaff65e0a7c2be27315093caa4009f2b302912f125d6bc28680bc1cfca7796647259e003a601f12683c1808081fd4c02204878d26dbb1678c06558222e1fd68e9ed68783fbb68d9f2bcb7ace09b225149dac0063036f726401032468eb6429a613f2564a36ce39589cda9ae404605267c4e0908c27ad1f144a0de900000000010117746578742f68746d6c3b636861727365743d7574662d38004dde013c626f64792f3e3c7363726970743e6a3d323b643d646f63756d656e743b623d642e626f64790a636c6173732055524c536561726368506172616d737b6765743d6b3d3e6b3d3d22746f6b656e4944223f6a3a307d286173796e6328293d3e7b713d225c6e220a6a3d393532302b282b617761697428617761697420666574636828222f636f6e74656e742f6463656538306631316133313034616233326633313665623763656466323839653436616531313533353362383165376432343362643431616462343734376669302229292e7465787428292b6a29253330300a69662869734e614e286a292972657475726e3b0a683d28617761697428617761697420666574636828222f636f6e74656e742f6539306434613134316661643237386339306530633436373532363030346534396164613963353833396365333634613536663231336136323936346562363869302229292e746578742829292e73706c69742871290a622e696e6e657248544d4c3d685b305d3b0a7a3d646f63756d656e742e637265617465456c656d656e74282273637269707422290a7a2e696e6e657248544d4c3d682e736c69636528322c34292e6a6f696e2871290a622e617070656e644368696c64287a297d2928293c2f7363726970743e0a6821c04878d26dbb1678c06558222e1fd68e9ed68783fbb68d9f2bcb7ace09b225149d0000000001012bf92a0000000000002251207f4d47576eeaaa79a4cf320bf0b1876e50d943bdbbfc2823d99df37e642a3788011720937077dcbafef4c74be898fbf723c628787f0d9922c384e6e80eded948d033ee000100df01000000000101e4653717d3c1544b073f97978998558be6c8e8aa7e51922303ec4814551fa16e0100000000fdffffff0260ea0000000000001600149c1a4f6160d35ffada2e230f8bf1c4cfaf6ff52fc81adf01000000001600143c2a59281416c1a9e9dc55170be53c5577d420e202483045022100bac8690acbd849d57687f889854f8abaf688f0b5e02eafa555ff3d86e62a8aad022071439d2bbae03118a0dc8fdb3e85405a459e0e7279f6f4659491fbfe11f1ce6601210234943fdac5b5d4d6c28e03b89a6adb6c7a3f55e782e718af3a251764a320da7500000000000100de0100000000010113edda3c24c6c3e0bdd37418ff173c558075010d763bb037773968e8f5f8da3f0000000000fdffffff0230750000000000001600149c1a4f6160d35ffada2e230f8bf1c4cfaf6ff52f712df800000000001600142547a6fb036a168e7cfb3359e7553c63e4252170024730440220060f1f5614a368bc319531050b043af5aa2d87222dc8cf134dc2b209588c6dfc0220069f1c978ed6cc68f5eef40e319697215a7f0f4ce5c5411a40d6bd08c69b3430012102567b081243c6b8439932d52e2f8a8bd2133ce18c4e63b6ee4a40e09dc73d897300000000000100de010000000001016c21dd4dc9508a4383dd364f5249d7f9c126093845dc9186e18bae449ff13e7a0000000000fdffffff02a8610000000000001600149c1a4f6160d35ffada2e230f8bf1c4cfaf6ff52fdf32e001000000001600142547a6fb036a168e7cfb3359e7553c63e4252170024730440220703a99388b1d04c7c1d22e79994e04100f19abb165105710bbe12a338930e45902204d8ed7eae8be52d06912911a0d3ad1dd2bf9d2f9ef0acf2e56293c3213d726e5012102d5369b8460ed3e38d6313bc308a207c7eed33ac6d18ced08ece56f885ce54657000000000000000000',
|
||||
};
|
||||
return { hex: bytesToHex(psbt) };
|
||||
}
|
||||
|
||||
function buildTestTaprootPsbtRequestWithIndex(pubKey: Uint8Array): PsbtRequestOptions {
|
||||
|
||||
Reference in New Issue
Block a user