From 17d2819e4110d6c0b877fbae79baf7b021b0d503 Mon Sep 17 00:00:00 2001 From: Tim Man Date: Wed, 20 Dec 2023 19:42:07 +0800 Subject: [PATCH 1/5] fix: regenerate the unsignedTx with correct stxAddress after switch account --- .../transactionSetting/editNonce.tsx | 2 +- src/app/hooks/queries/useStxWalletData.ts | 1 + src/app/screens/transactionRequest/index.tsx | 76 +++++++++---------- src/app/stores/wallet/reducer.ts | 31 ++++++++ 4 files changed, 71 insertions(+), 39 deletions(-) diff --git a/src/app/components/transactionSetting/editNonce.tsx b/src/app/components/transactionSetting/editNonce.tsx index 54d30d1c9..5f28bf038 100644 --- a/src/app/components/transactionSetting/editNonce.tsx +++ b/src/app/components/transactionSetting/editNonce.tsx @@ -58,7 +58,7 @@ function EditNonce({ nonce, setNonce }: Props) { useEffect(() => { setNonce(nonceInput); - }, [nonceInput]); + }, [nonceInput, setNonce]); return ( diff --git a/src/app/hooks/queries/useStxWalletData.ts b/src/app/hooks/queries/useStxWalletData.ts index 0b33b3580..bd4d17a5e 100644 --- a/src/app/hooks/queries/useStxWalletData.ts +++ b/src/app/hooks/queries/useStxWalletData.ts @@ -7,6 +7,7 @@ import { useDispatch } from 'react-redux'; import useNetworkSelector from '../useNetwork'; import useWalletSelector from '../useWalletSelector'; +// TODO refactor: no need to put this in store. use this hook instead export const useStxWalletData = () => { const dispatch = useDispatch(); const { stxAddress } = useWalletSelector(); diff --git a/src/app/screens/transactionRequest/index.tsx b/src/app/screens/transactionRequest/index.tsx index 1b8260262..7b670fb99 100644 --- a/src/app/screens/transactionRequest/index.tsx +++ b/src/app/screens/transactionRequest/index.tsx @@ -42,7 +42,6 @@ function TransactionRequest() { const [coinsMetaData, setCoinsMetaData] = useState(null); const [codeBody, setCodeBody] = useState(undefined); const [contractName, setContractName] = useState(undefined); - const [hasSwitchedAccount, setHasSwitchedAccount] = useState(false); const [attachment, setAttachment] = useState(undefined); const handleTokenTransferRequest = async (tokenTransferPayload: any) => { @@ -118,38 +117,6 @@ function TransactionRequest() { setContractName(response.contractName); }; - const switchAccountBasedOnRequest = () => { - if (getNetworkType(payload.network) !== network.type) { - navigate('/tx-status', { - state: { - txid: '', - currency: 'STX', - error: - 'There’s a mismatch between your active network and the network you’re logged with.', - browserTx: true, - }, - }); - return; - } - if (payload.stxAddress !== selectedAccount?.stxAddress && !isHardwareAccount(selectedAccount)) { - const account = accountsList.find((acc) => acc.stxAddress === payload.stxAddress); - if (account) { - switchAccount(account); - } else { - navigate('/tx-status', { - state: { - txid: '', - currency: 'STX', - error: - 'There’s a mismatch between your active address and the address you’re logged with.', - browserTx: true, - }, - }); - } - } - setHasSwitchedAccount(true); - }; - const handleTxSigningRequest = async () => { if (payload.txType === 'contract_call') { await handleContractCallRequest(payload); @@ -169,7 +136,6 @@ function TransactionRequest() { }; const createRequestTx = async () => { - if (hasSwitchedAccount) { if (!payload.txHex) { if (payload.txType === 'token_transfer') { await handleTokenTransferRequest(payload); @@ -181,13 +147,47 @@ function TransactionRequest() { } else { await handleTxSigningRequest(); } - } - }; + } + + + createRequestTx(); useEffect(() => { + const switchAccountBasedOnRequest = () => { + if (getNetworkType(payload.network) !== network.type) { + navigate('/tx-status', { + state: { + txid: '', + currency: 'STX', + error: + 'There’s a mismatch between your active network and the network you’re logged with.', + browserTx: true, + }, + }); + return; + } + if ( + payload.stxAddress !== selectedAccount?.stxAddress && + !isHardwareAccount(selectedAccount) + ) { + const account = accountsList.find((acc) => acc.stxAddress === payload.stxAddress); + if (account) { + switchAccount(account); + } else { + navigate('/tx-status', { + state: { + txid: '', + currency: 'STX', + error: + 'There’s a mismatch between your active address and the address you’re logged with.', + browserTx: true, + }, + }); + } + } + }; switchAccountBasedOnRequest(); - createRequestTx(); - }, [hasSwitchedAccount]); + }, [accountsList, network.type, navigate, payload, selectedAccount, switchAccount]); return ( <> diff --git a/src/app/stores/wallet/reducer.ts b/src/app/stores/wallet/reducer.ts index 28000ab51..6e626e48c 100644 --- a/src/app/stores/wallet/reducer.ts +++ b/src/app/stores/wallet/reducer.ts @@ -31,6 +31,37 @@ import { WalletState, } from './actions/types'; +/* + * This store should ONLY be used for global app settings such as: + * - hasActivatedOrdinalsKey: undefined, + * - hasActivatedRareSatsKey: undefined, + * - hasActivatedRBFKey: true, + * - rareSatsNoticeDismissed: undefined, + * - showBtcReceiveAlert: true, + * - showOrdinalReceiveAlert: true, + * - showDataCollectionAlert: true, + * - btcApiUrl: '', + * - selectedAccount: null, + * - accountType: 'software', + * - accountName: undefined, + * - walletLockPeriod: WalletSessionPeriods.STANDARD, + * - isUnlocked: false, + * - fiatCurrency: 'USD', + * + * because we get many bugs around caching the wrong values when switching accounts, + * we prefer react-query cache (with the correct cache keys) for all + * account-specific values, and API fetch results such as: + * - btcFiatRate: '0', + * - stxBtcRate: '0', + * - stxBalance: '0', + * - stxAvailableBalance: '0', + * - stxLockedBalance: '0', + * - stxNonce: 0, + * - btcBalance: '0', + * - feeMultipliers: null, + * + * TODO refactor most of these values out of the store and use query cache instead + */ const initialWalletState: WalletState = { stxAddress: '', btcAddress: '', From 3e837557664244ae96f152a7c89849d655d52729 Mon Sep 17 00:00:00 2001 From: Tim Man Date: Wed, 20 Dec 2023 19:49:06 +0800 Subject: [PATCH 2/5] fix: minor cleanup --- src/app/screens/transactionRequest/index.tsx | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/app/screens/transactionRequest/index.tsx b/src/app/screens/transactionRequest/index.tsx index 7b670fb99..e3bb73006 100644 --- a/src/app/screens/transactionRequest/index.tsx +++ b/src/app/screens/transactionRequest/index.tsx @@ -18,6 +18,7 @@ import { ContractCallPayload, ContractDeployPayload } from '@stacks/connect'; import { StacksTransaction } from '@stacks/transactions'; import { getNetworkType, isHardwareAccount } from '@utils/helper'; import { useEffect, useState } from 'react'; +import toast from 'react-hot-toast'; import { useNavigate } from 'react-router-dom'; import { MoonLoader } from 'react-spinners'; import styled from 'styled-components'; @@ -134,8 +135,8 @@ function TransactionRequest() { }); } }; - const createRequestTx = async () => { + try { if (!payload.txHex) { if (payload.txType === 'token_transfer') { await handleTokenTransferRequest(payload); @@ -143,12 +144,15 @@ function TransactionRequest() { await handleContractCallRequest(payload); } else if (payload.txType === 'smart_contract') { await handleContractDeployRequest(payload); + } else { + await handleTxSigningRequest(); } - } else { - await handleTxSigningRequest(); } - } - + } catch (e: unknown) { + console.error(e); // eslint-disable-line + toast.error('Unexpected error creating transaction'); + } + }; createRequestTx(); From 8bc637a1e21ca2a0b909eeb902dab06333e159a7 Mon Sep 17 00:00:00 2001 From: Mahmoud Aboelenein Date: Wed, 27 Dec 2023 15:35:45 +0200 Subject: [PATCH 3/5] fix tx-request account switching --- src/app/screens/transactionRequest/index.tsx | 99 +++++++++++--------- 1 file changed, 53 insertions(+), 46 deletions(-) diff --git a/src/app/screens/transactionRequest/index.tsx b/src/app/screens/transactionRequest/index.tsx index e3bb73006..3a99a8ec5 100644 --- a/src/app/screens/transactionRequest/index.tsx +++ b/src/app/screens/transactionRequest/index.tsx @@ -5,6 +5,7 @@ import useStxTransactionRequest from '@hooks/useStxTransactionRequest'; import useWalletReducer from '@hooks/useWalletReducer'; import useWalletSelector from '@hooks/useWalletSelector'; import { + Account, buf2hex, Coin, ContractFunction, @@ -45,13 +46,13 @@ function TransactionRequest() { const [contractName, setContractName] = useState(undefined); const [attachment, setAttachment] = useState(undefined); - const handleTokenTransferRequest = async (tokenTransferPayload: any) => { + const handleTokenTransferRequest = async (tokenTransferPayload: any, requestAccount: Account) => { const stxPendingTxData = await fetchStxPendingTxData(stxAddress, selectedNetwork); const unsignedSendStxTx = await getTokenTransferRequest( tokenTransferPayload.recipient, tokenTransferPayload.amount, tokenTransferPayload.memo!, - stxPublicKey, + requestAccount.stxPublicKey, feeMultipliers!, selectedNetwork, stxPendingTxData || [], @@ -69,16 +70,19 @@ function TransactionRequest() { }); }; - const handleContractCallRequest = async (contractCallPayload: ContractCallPayload) => { + const handleContractCallRequest = async ( + contractCallPayload: ContractCallPayload, + requestAccount: Account, + ) => { const { unSignedContractCall, contractInterface, coinsMetaData: coinMeta, } = await getContractCallPromises( contractCallPayload, - stxAddress, + requestAccount.stxAddress, selectedNetwork, - stxPublicKey, + requestAccount.stxPublicKey, stacksTransaction?.auth, ); setUnsignedTx(unSignedContractCall); @@ -104,13 +108,16 @@ function TransactionRequest() { } }; - const handleContractDeployRequest = async (contractDeployPayload: ContractDeployPayload) => { + const handleContractDeployRequest = async ( + contractDeployPayload: ContractDeployPayload, + requestAccount: Account, + ) => { const response = await createDeployContractRequest( contractDeployPayload, selectedNetwork, - stxPublicKey, + requestAccount.stxPublicKey, feeMultipliers!, - stxAddress, + requestAccount.stxAddress, stacksTransaction?.auth, ); setUnsignedTx(response.contractDeployTx); @@ -118,11 +125,11 @@ function TransactionRequest() { setContractName(response.contractName); }; - const handleTxSigningRequest = async () => { + const handleTxSigningRequest = async (requestAccount: Account) => { if (payload.txType === 'contract_call') { - await handleContractCallRequest(payload); + await handleContractCallRequest(payload, requestAccount); } else if (payload.txType === 'smart_contract') { - await handleContractDeployRequest(payload); + await handleContractDeployRequest(payload, requestAccount); } else { navigate('/confirm-stx-tx', { state: { @@ -135,18 +142,19 @@ function TransactionRequest() { }); } }; - const createRequestTx = async () => { + + const createRequestTx = async (account: Account) => { try { if (!payload.txHex) { if (payload.txType === 'token_transfer') { - await handleTokenTransferRequest(payload); + await handleTokenTransferRequest(payload, account); } else if (payload.txType === 'contract_call') { - await handleContractCallRequest(payload); + await handleContractCallRequest(payload, account); } else if (payload.txType === 'smart_contract') { - await handleContractDeployRequest(payload); - } else { - await handleTxSigningRequest(); + await handleContractDeployRequest(payload, account); } + } else { + await handleTxSigningRequest(account); } } catch (e: unknown) { console.error(e); // eslint-disable-line @@ -154,44 +162,43 @@ function TransactionRequest() { } }; - createRequestTx(); - - useEffect(() => { - const switchAccountBasedOnRequest = () => { - if (getNetworkType(payload.network) !== network.type) { + const handleRequest = async () => { + if (getNetworkType(payload.network) !== network.type) { + navigate('/tx-status', { + state: { + txid: '', + currency: 'STX', + error: + 'There’s a mismatch between your active network and the network you’re logged with.', + browserTx: true, + }, + }); + return; + } + if (payload.stxAddress !== selectedAccount?.stxAddress && !isHardwareAccount(selectedAccount)) { + const account = accountsList.find((acc) => acc.stxAddress === payload.stxAddress); + if (account) { + await switchAccount(account); + await createRequestTx(account); + } else { navigate('/tx-status', { state: { txid: '', currency: 'STX', error: - 'There’s a mismatch between your active network and the network you’re logged with.', + 'There’s a mismatch between your active address and the address you’re logged with.', browserTx: true, }, }); - return; } - if ( - payload.stxAddress !== selectedAccount?.stxAddress && - !isHardwareAccount(selectedAccount) - ) { - const account = accountsList.find((acc) => acc.stxAddress === payload.stxAddress); - if (account) { - switchAccount(account); - } else { - navigate('/tx-status', { - state: { - txid: '', - currency: 'STX', - error: - 'There’s a mismatch between your active address and the address you’re logged with.', - browserTx: true, - }, - }); - } - } - }; - switchAccountBasedOnRequest(); - }, [accountsList, network.type, navigate, payload, selectedAccount, switchAccount]); + } else { + await createRequestTx(selectedAccount!); + } + }; + + useEffect(() => { + handleRequest(); + }, []); return ( <> From 36805682a3c229dd88d23cbfa5f80504f94f51d6 Mon Sep 17 00:00:00 2001 From: Mahmoud Aboelenein Date: Wed, 27 Dec 2023 16:04:15 +0200 Subject: [PATCH 4/5] updated core version --- package-lock.json | 14 +++++++------- package.json | 2 +- src/app/screens/transactionRequest/index.tsx | 8 +++++--- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index 70f12849a..ab8679dc6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "@ledgerhq/hw-transport-webusb": "^6.27.13", "@phosphor-icons/react": "^2.0.10", "@react-spring/web": "^9.6.1", - "@secretkeylabs/xverse-core": "6.0.1-3d747a3", + "@secretkeylabs/xverse-core": "7.0.0", "@stacks/connect": "7.4.1", "@stacks/stacks-blockchain-api-types": "6.1.1", "@stacks/transactions": "6.9.0", @@ -1732,9 +1732,9 @@ } }, "node_modules/@secretkeylabs/xverse-core": { - "version": "6.0.1-3d747a3", - "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/6.0.1-3d747a3/219b63e085fd01f85abaa42902b9759e050e0236", - "integrity": "sha512-oRwgA69GYsmknpSZ6evDtbAR3wOdxcMKPbi+sea8/8KHXLTbA6m1qhmBKypGsIALSS38dFQ9JZuEKfVpwQ6iig==", + "version": "7.0.0", + "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/7.0.0/a9d4470c0bee31b2b751b0f2a3e064d51453ddd4", + "integrity": "sha512-8z5g5dHFin0d9695EwI0t6a/Ji7vzUenCq1AHpTtsj5Z1/SlH6Oa7p95fyJ1usBH99M5NQAYFMBGkjOcNE+jQw==", "license": "ISC", "dependencies": { "@bitcoinerlab/secp256k1": "^1.0.2", @@ -15372,9 +15372,9 @@ } }, "@secretkeylabs/xverse-core": { - "version": "6.0.1-3d747a3", - "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/6.0.1-3d747a3/219b63e085fd01f85abaa42902b9759e050e0236", - "integrity": "sha512-oRwgA69GYsmknpSZ6evDtbAR3wOdxcMKPbi+sea8/8KHXLTbA6m1qhmBKypGsIALSS38dFQ9JZuEKfVpwQ6iig==", + "version": "7.0.0", + "resolved": "https://npm.pkg.github.com/download/@secretkeylabs/xverse-core/7.0.0/a9d4470c0bee31b2b751b0f2a3e064d51453ddd4", + "integrity": "sha512-8z5g5dHFin0d9695EwI0t6a/Ji7vzUenCq1AHpTtsj5Z1/SlH6Oa7p95fyJ1usBH99M5NQAYFMBGkjOcNE+jQw==", "requires": { "@bitcoinerlab/secp256k1": "^1.0.2", "@noble/curves": "^1.2.0", diff --git a/package.json b/package.json index e59854e31..d4d5692f3 100644 --- a/package.json +++ b/package.json @@ -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": "6.0.1-3d747a3", + "@secretkeylabs/xverse-core": "7.0.0", "@stacks/connect": "7.4.1", "@stacks/stacks-blockchain-api-types": "6.1.1", "@stacks/transactions": "6.9.0", diff --git a/src/app/screens/transactionRequest/index.tsx b/src/app/screens/transactionRequest/index.tsx index 3a99a8ec5..e7594cb83 100644 --- a/src/app/screens/transactionRequest/index.tsx +++ b/src/app/screens/transactionRequest/index.tsx @@ -33,8 +33,7 @@ const LoaderContainer = styled.div((props) => ({ })); function TransactionRequest() { - const { stxAddress, network, stxPublicKey, feeMultipliers, accountsList, selectedAccount } = - useWalletSelector(); + const { network, feeMultipliers, accountsList, selectedAccount } = useWalletSelector(); const { payload, tabId, requestToken, stacksTransaction } = useStxTransactionRequest(); const navigate = useNavigate(); const selectedNetwork = useNetworkSelector(); @@ -47,7 +46,10 @@ function TransactionRequest() { const [attachment, setAttachment] = useState(undefined); const handleTokenTransferRequest = async (tokenTransferPayload: any, requestAccount: Account) => { - const stxPendingTxData = await fetchStxPendingTxData(stxAddress, selectedNetwork); + const stxPendingTxData = await fetchStxPendingTxData( + requestAccount.stxAddress, + selectedNetwork, + ); const unsignedSendStxTx = await getTokenTransferRequest( tokenTransferPayload.recipient, tokenTransferPayload.amount, From 4a2287583da74c58a3ca913fc35d7c50adacc311 Mon Sep 17 00:00:00 2001 From: Mahmoud Aboelenein Date: Wed, 27 Dec 2023 16:15:03 +0200 Subject: [PATCH 5/5] added type checking and default values for feeMultipliers --- src/app/screens/transactionRequest/index.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/app/screens/transactionRequest/index.tsx b/src/app/screens/transactionRequest/index.tsx index e7594cb83..504c99eee 100644 --- a/src/app/screens/transactionRequest/index.tsx +++ b/src/app/screens/transactionRequest/index.tsx @@ -55,7 +55,11 @@ function TransactionRequest() { tokenTransferPayload.amount, tokenTransferPayload.memo!, requestAccount.stxPublicKey, - feeMultipliers!, + { + stxSendTxMultiplier: feeMultipliers?.stxSendTxMultiplier || 1, + poolStackingTxMultiplier: feeMultipliers?.poolStackingTxMultiplier || 1, + otherTxMultiplier: feeMultipliers?.otherTxMultiplier || 1, + }, selectedNetwork, stxPendingTxData || [], stacksTransaction?.auth, @@ -193,7 +197,7 @@ function TransactionRequest() { }, }); } - } else { + } else if (selectedAccount) { await createRequestTx(selectedAccount!); } };