From d3671b1ae06bdedee65bac287512c060441f253d Mon Sep 17 00:00:00 2001 From: Benaor Date: Sun, 29 Dec 2024 02:06:41 +0100 Subject: [PATCH 1/2] fix(linter): fix issues from linter in packages/extension --- packages/extension/src/App.tsx | 5 +- .../src/chromeServices/background/index.ts | 17 ++- .../utils/focusOrCreatePopupWindow.ts | 15 ++- .../background/utils/rejectOnClose.ts | 10 +- .../molecules/DataCard/DataCard.tsx | 2 +- .../TransactionDisplay/TransactionDisplay.tsx | 122 +++++++++++------- .../PreparePayment/PreparePayment.tsx | 2 +- .../RecapView/RecapView.tsx | 4 +- .../StepperView/StepperView.tsx | 16 ++- .../SubmitBulkTransactions.tsx | 50 ++++--- .../SubmitRawTransaction.tsx | 7 +- .../templates/GemWallet/GemWallet.tsx | 77 +++++++++++ .../components/templates/GemWallet/index.ts | 1 + .../contexts/LedgerContext/LedgerContext.tsx | 19 ++- .../src/contexts/LedgerContext/chains/XRPL.ts | 2 +- .../contexts/LedgerContext/chains/Xahau.ts | 12 +- .../utils/buildXRPLTransaction.test.ts | 4 +- .../utils/buildXahauTransaction.test.ts | 3 +- packages/extension/src/global.d.ts | 7 + .../extension/src/hooks/useFees/useFees.ts | 4 +- packages/extension/src/index.tsx | 76 +---------- packages/extension/src/setupTests.ts | 1 + packages/extension/src/types/utils.types.ts | 12 ++ .../extension/src/utils/NFTViewer.test.ts | 6 +- packages/extension/src/utils/baseParams.ts | 19 +-- .../extension/src/utils/fetchTokenData.ts | 11 +- packages/extension/src/utils/link.test.ts | 1 - packages/extension/src/utils/network.test.ts | 1 - .../extension/src/utils/parseParams.test.ts | 8 +- packages/extension/src/utils/parseParams.ts | 18 +-- .../src/utils/storageChromeSession.ts | 12 +- .../extension/src/utils/transaction.test.ts | 6 +- packages/extension/src/utils/transaction.ts | 5 +- packages/extension/src/utils/typeof-fns.ts | 2 +- 34 files changed, 334 insertions(+), 223 deletions(-) create mode 100644 packages/extension/src/components/templates/GemWallet/GemWallet.tsx create mode 100644 packages/extension/src/components/templates/GemWallet/index.ts create mode 100644 packages/extension/src/global.d.ts diff --git a/packages/extension/src/App.tsx b/packages/extension/src/App.tsx index 2ff39a6b5..bae2cb461 100644 --- a/packages/extension/src/App.tsx +++ b/packages/extension/src/App.tsx @@ -109,7 +109,10 @@ const App: FC = () => { useEffect(() => { if (process.env.NODE_ENV === 'production') { - const messageListener = (message: any, sender: chrome.runtime.MessageSender) => { + const messageListener = ( + message: { app: string; type: string }, + sender: chrome.runtime.MessageSender + ) => { if (message.app !== GEM_WALLET || sender.id !== chrome.runtime.id) { return; // exit early if the message is not from gem-wallet or the sender is not the extension itself } diff --git a/packages/extension/src/chromeServices/background/index.ts b/packages/extension/src/chromeServices/background/index.ts index b10d11d20..49de5c94e 100644 --- a/packages/extension/src/chromeServices/background/index.ts +++ b/packages/extension/src/chromeServices/background/index.ts @@ -85,7 +85,7 @@ chrome.runtime.onStartup.addListener(createOffscreen); chrome.runtime.onMessage.addListener(() => {}); // keepAlive const session = Session.getInstance(); -let currentReceivingMessage: string | undefined = undefined; // For reject message on popup close +let currentReceivingMessage: ReceiveMessage | undefined = undefined; // For reject message on popup close // Used to send a message to the view through the chrome.storage.local memory. // Useful when the data to send is big. @@ -866,7 +866,14 @@ chrome.windows.onRemoved.addListener(function (windowId) { isPopupWindow(windowId).then((isPopup) => { if (isPopup && currentReceivingMessage) { const response = buildRejectMessage(currentReceivingMessage); - sendToActiveTabs(response); + + if (!response) return; + + sendToActiveTabs({ + app: response.app, + type: response.type, + source: 'GEM_WALLET_MSG_REQUEST' + }); } }); }); @@ -909,7 +916,11 @@ chrome.runtime.onMessage.addListener((request, sender) => { } }); -const sendToActiveTabs = (payload: Omit) => { +const sendToActiveTabs = ( + payload: Pick & { + type: string; + } +) => { activeTabs.forEach((tabId) => { chrome.tabs.get(tabId, () => { if (!chrome.runtime.lastError) { diff --git a/packages/extension/src/chromeServices/background/utils/focusOrCreatePopupWindow.ts b/packages/extension/src/chromeServices/background/utils/focusOrCreatePopupWindow.ts index 50988a06a..5a6869a7c 100644 --- a/packages/extension/src/chromeServices/background/utils/focusOrCreatePopupWindow.ts +++ b/packages/extension/src/chromeServices/background/utils/focusOrCreatePopupWindow.ts @@ -9,6 +9,8 @@ import { import { MAIN_FILE } from '../../../constants/paths'; import { POPUP_HEIGHT, POPUP_WIDTH, WINDOWS_POPUP_PADDING } from '../../../constants/sizes'; import { STORAGE_CURRENT_WINDOW_ID } from '../../../constants/storage'; +import { isBoolean, isString } from '../../../utils'; +import { isNumber } from 'xrpl/dist/npm/models/transactions/common'; const isWindows = navigator.userAgent.includes('Win'); @@ -19,11 +21,20 @@ const isWindows = navigator.userAgent.includes('Win'); const getLastFocusedWindow = (): Promise => new Promise((resolve) => chrome.windows.getLastFocused(resolve)); -export const serializeToQueryString = (payload?: Record) => +/** + * Its a helper function to encode only compatible values + * Necessary to avoid types errors from TS + */ +const encodeOnlyCompatibleValueURIComponent = (uriComponent?: unknown) => { + if (isString(uriComponent) || isNumber(uriComponent) || isBoolean(uriComponent)) + return encodeURIComponent(uriComponent); +}; + +export const serializeToQueryString = (payload?: Record) => payload ? '?' + Object.entries(payload) - .map(([key, value]) => [key, value].map(encodeURIComponent).join('=')) + .map(([key, value]) => [key, value].map(encodeOnlyCompatibleValueURIComponent).join('=')) .join('&') : ''; diff --git a/packages/extension/src/chromeServices/background/utils/rejectOnClose.ts b/packages/extension/src/chromeServices/background/utils/rejectOnClose.ts index 2afeb5230..8fe5b2ed3 100644 --- a/packages/extension/src/chromeServices/background/utils/rejectOnClose.ts +++ b/packages/extension/src/chromeServices/background/utils/rejectOnClose.ts @@ -1,10 +1,16 @@ -import { GEM_WALLET } from '@gemwallet/constants'; +import { GEM_WALLET, ReceiveMessage } from '@gemwallet/constants'; const defaultPayload = { result: null }; -export const buildRejectMessage = (type: string): any => { +type RejectMessage = { + app: typeof GEM_WALLET; + type: ReceiveMessage; + payload: Record; +}; + +export const buildRejectMessage = (type: ReceiveMessage): RejectMessage | undefined => { if (type === 'RECEIVE_SEND_PAYMENT/V3' || type === 'RECEIVE_PAYMENT_HASH') { return { app: GEM_WALLET, diff --git a/packages/extension/src/components/molecules/DataCard/DataCard.tsx b/packages/extension/src/components/molecules/DataCard/DataCard.tsx index 4e5074132..07e93ddcb 100644 --- a/packages/extension/src/components/molecules/DataCard/DataCard.tsx +++ b/packages/extension/src/components/molecules/DataCard/DataCard.tsx @@ -7,7 +7,7 @@ import { IconButton, Paper, Typography } from '@mui/material'; import { SECONDARY_GRAY } from '../../../constants'; export interface DataCardProps { - formattedData: any; + formattedData: string; dataName?: string; isExpanded: boolean; setIsExpanded: (value: boolean) => void; diff --git a/packages/extension/src/components/molecules/TransactionDisplay/TransactionDisplay.tsx b/packages/extension/src/components/molecules/TransactionDisplay/TransactionDisplay.tsx index a6dafc0da..4a8a6df48 100644 --- a/packages/extension/src/components/molecules/TransactionDisplay/TransactionDisplay.tsx +++ b/packages/extension/src/components/molecules/TransactionDisplay/TransactionDisplay.tsx @@ -32,55 +32,66 @@ export const TransactionDisplay: FC = ({ mainToken }) => { const { selectedWallet, wallets } = useWallet(); - const keyMap: Record JSX.Element | null> = { - TransactionType: (value: string) => + const keyMap: Record JSX.Element | null> = { + TransactionType: (value) => renderSimpleText({ title: 'Transaction Type', - value, + value: value as string, useLegacy }), - Amount: (value: Amount) => + Amount: (value) => renderAmount({ title: 'Amount', - value, + value: value as Amount, useLegacy, mainToken, hasMultipleAmounts }), - Amount2: (value: Amount) => + Amount2: (value) => renderAmount({ title: 'Amount 2', - value, + value: value as Amount, useLegacy, hasMultipleAmounts }), - Account: (value: string) => + Account: (value) => wallets[selectedWallet].publicAddress === value ? null - : renderSimpleText({ title: 'Account', value, hasTooltip: true, useLegacy }), - NFTokenID: (value: string) => - renderSimpleText({ title: 'NFT', value, hasTooltip: true, useLegacy }), - DeliverMin: (value: Amount) => + : renderSimpleText({ + title: 'Account', + value: value as string, + hasTooltip: true, + useLegacy + }), + NFTokenID: (value) => + renderSimpleText({ title: 'NFT', value: value as string, hasTooltip: true, useLegacy }), + DeliverMin: (value) => renderAmount({ title: 'Deliver Min', - value, + value: value as Amount, useLegacy }), - Destination: (value: string) => - renderSimpleText({ title: 'Destination', value, hasTooltip: true, useLegacy }), - DestinationTag: (value?: number) => - renderSimpleText({ title: 'Destination Tag', value, useLegacy }), - Flags: (value?: GlobalFlags) => + Destination: (value) => + renderSimpleText({ + title: 'Destination', + value: value as string, + hasTooltip: true, + useLegacy + }), + DestinationTag: (value?) => + renderSimpleText({ title: 'Destination Tag', value: value as number | undefined, useLegacy }), + Flags: (value?) => value !== undefined ? renderSimpleText({ title: 'Flags', - value: formatFlags(value, tx.TransactionType), + value: formatFlags(value as GlobalFlags, tx.TransactionType), useLegacy }) : null, - Memos: (value?: Memo[]) => renderMemos({ memos: value, useLegacy }), - NFTokenOffers: (value: string[]) => renderArray({ title: 'Offer', value, useLegacy }), - Signers: (value?: Signer[]) => renderArray({ title: 'Signer', value, useLegacy }), + Memos: (value?) => renderMemos({ memos: value as Memo[] | undefined, useLegacy }), + NFTokenOffers: (value) => renderArray({ title: 'Offer', value: value as string[], useLegacy }), + Signers: (value?) => + renderArray({ title: 'Signer', value: value as Signer[] | undefined, useLegacy }), LimitAmount: (value) => renderAmount({ title: 'Limit Amount', @@ -88,17 +99,23 @@ export const TransactionDisplay: FC = ({ useLegacy, mainToken }), - NFTokenSellOffer: (value?: string) => - value !== undefined ? renderSimpleText({ title: 'Sell Offer', value, useLegacy }) : null, - NFTokenBuyOffer: (value?: string) => - value !== undefined ? renderSimpleText({ title: 'Buy Offer', value, useLegacy }) : null, - NFTokenBrokerFee: (value?: Amount) => + NFTokenSellOffer: (value?) => + value !== undefined + ? renderSimpleText({ title: 'Sell Offer', value: value as string, useLegacy }) + : null, + NFTokenBuyOffer: (value?) => + value !== undefined + ? renderSimpleText({ title: 'Buy Offer', value: value as string, useLegacy }) + : null, + NFTokenBrokerFee: (value?) => + value !== undefined + ? renderAmount({ title: 'Broker Fee', value: value as Amount, useLegacy, mainToken }) + : null, + NFTokenMinter: (value?) => value !== undefined - ? renderAmount({ title: 'Broker Fee', value, useLegacy, mainToken }) + ? renderSimpleText({ title: 'Minter', value: value as string | undefined, useLegacy }) : null, - NFTokenMinter: (value?: string) => - value !== undefined ? renderSimpleText({ title: 'Minter', value, useLegacy }) : null, - URI: (value?: string | null) => + URI: (value?) => value !== undefined ? renderSimpleText({ title: 'URI', @@ -108,36 +125,43 @@ export const TransactionDisplay: FC = ({ }) : null, Fee: () => null, // Fee is rendered in the BaseTransaction component - TakerGets: (value: Amount) => - renderAmount({ title: 'Taker Gets', value, useLegacy, mainToken }), - TakerPays: (value: Amount) => - renderAmount({ title: 'Taker Pays', value, useLegacy, mainToken }), - TransferFee: (value?: number) => + TakerGets: (value) => + renderAmount({ title: 'Taker Gets', value: value as Amount, useLegacy, mainToken }), + TakerPays: (value) => + renderAmount({ title: 'Taker Pays', value: value as Amount, useLegacy, mainToken }), + TransferFee: (value?) => renderSimpleText({ title: 'Transfer Fee', - value: value ? `${formatTransferFee(value)}%` : '', + value: value ? `${formatTransferFee(value as number)}%` : '', useLegacy }), - OfferSequence: (value?: number) => - renderSimpleText({ title: 'Offer Sequence', value, useLegacy }), - EmailHash: (value?: string) => renderSimpleText({ title: 'Email Hash', value, useLegacy }), - NFTokenTaxon: (value?: string) => renderSimpleText({ title: 'Taxon', value, useLegacy }), - RegularKey: (value?: string) => - renderSimpleText({ title: 'Regular Key', value, hasTooltip: true, useLegacy }), - Asset: (value: Currency) => renderCurrency({ title: 'Asset', value }), - Asset2: (value: Currency) => renderCurrency({ title: 'Asset 2', value }), - SendMax: (value: Amount) => + OfferSequence: (value?) => + renderSimpleText({ title: 'Offer Sequence', value: value as number | undefined, useLegacy }), + EmailHash: (value?) => + renderSimpleText({ title: 'Email Hash', value: value as string | undefined, useLegacy }), + NFTokenTaxon: (value?) => + renderSimpleText({ title: 'Taxon', value: value as string | undefined, useLegacy }), + RegularKey: (value?) => + renderSimpleText({ + title: 'Regular Key', + value: value as string | undefined, + hasTooltip: true, + useLegacy + }), + Asset: (value) => renderCurrency({ title: 'Asset', value: value as Currency }), + Asset2: (value) => renderCurrency({ title: 'Asset 2', value: value as Currency }), + SendMax: (value) => renderAmount({ title: 'Send Max', - value, + value: value as Amount, useLegacy }), - Hooks: (value?: Hook[]) => renderHooks({ hooks: value }) + Hooks: (value?) => renderHooks({ hooks: value as Hook[] | undefined }) }; const renderSimpleText = (params: { title: string; - value: any; + value: string | number | undefined; hasTooltip?: boolean; useLegacy: boolean; }): JSX.Element | null => { diff --git a/packages/extension/src/components/pages/SendPayment/PreparePayment/PreparePayment.tsx b/packages/extension/src/components/pages/SendPayment/PreparePayment/PreparePayment.tsx index 52a16566d..263de28d6 100644 --- a/packages/extension/src/components/pages/SendPayment/PreparePayment/PreparePayment.tsx +++ b/packages/extension/src/components/pages/SendPayment/PreparePayment/PreparePayment.tsx @@ -146,7 +146,7 @@ export const PreparePayment: FC = ({ onSendPaymentClick }) } else { setErrorTokens("Impossible to fetch tokens, we couldn't get your current wallet"); } - } catch (e: any) { + } catch (e) { setErrorTokens('Impossible to fetch tokens, please try again'); Sentry.captureException(e); } diff --git a/packages/extension/src/components/pages/SubmitBulkTransactions/RecapView/RecapView.tsx b/packages/extension/src/components/pages/SubmitBulkTransactions/RecapView/RecapView.tsx index 266d4466d..92bb49c3a 100644 --- a/packages/extension/src/components/pages/SubmitBulkTransactions/RecapView/RecapView.tsx +++ b/packages/extension/src/components/pages/SubmitBulkTransactions/RecapView/RecapView.tsx @@ -9,8 +9,8 @@ import { TransactionPage } from '../../../templates'; interface RecapProps { transactionsListParam: TransactionWithID[]; - estimatedFees: any; - errorFees: any; + estimatedFees: string; + errorFees: string | undefined; hasEnoughFunds: boolean; handleReject: () => void; beginProcess: () => void; diff --git a/packages/extension/src/components/pages/SubmitBulkTransactions/StepperView/StepperView.tsx b/packages/extension/src/components/pages/SubmitBulkTransactions/StepperView/StepperView.tsx index a6ba3ba98..5e769defe 100644 --- a/packages/extension/src/components/pages/SubmitBulkTransactions/StepperView/StepperView.tsx +++ b/packages/extension/src/components/pages/SubmitBulkTransactions/StepperView/StepperView.tsx @@ -100,21 +100,25 @@ export const StepperView: FC = ({ const URI = NFTInfo.result.uri; resolveNFTDataFromURI(URI, index, amount); - } catch (error) {} + } catch (error) { + // nothing + } }; const resolveNFTDataFromNFTOfferID = async (NFTOfferID: string, index: number) => { try { const ledgerEntry = await getLedgerEntry(NFTOfferID); - const NFTokenID = (ledgerEntry?.result?.node as any)?.NFTokenID; + const NFTokenID = ledgerEntry?.result?.node?.NFTokenID; if (!NFTokenID) return; - const amount = (ledgerEntry?.result?.node as any)?.Amount; + const amount = ledgerEntry?.result?.node?.Amount; resolveNFTDataFromNFTokenID(NFTokenID, index, amount); - } catch (error) {} + } catch (error) { + // nothing + } }; - for (let key in transactionsToDisplay) { - if (transactionsToDisplay.hasOwnProperty(key)) { + for (const key in transactionsToDisplay) { + if (Object.prototype.hasOwnProperty.call(transactionsToDisplay, key)) { if (transactionsToDisplay[key].TransactionType === 'NFTokenMint') { // We can only resolve using the URI. No NFT data since the NFT does not exist const URI = (transactionsToDisplay[key] as NFTokenMint).URI; diff --git a/packages/extension/src/components/pages/SubmitBulkTransactions/SubmitBulkTransactions.tsx b/packages/extension/src/components/pages/SubmitBulkTransactions/SubmitBulkTransactions.tsx index 248e90ce0..75f43cd3c 100644 --- a/packages/extension/src/components/pages/SubmitBulkTransactions/SubmitBulkTransactions.tsx +++ b/packages/extension/src/components/pages/SubmitBulkTransactions/SubmitBulkTransactions.tsx @@ -202,35 +202,31 @@ export const SubmitBulkTransactions: FC = () => { // Convert transactions to array. Sort them by their key to ensure order const transactions = Object.entries(transactionsRecord) .sort(([keyA], [keyB]) => Number(keyA) - Number(keyB)) - .map(([_, value]) => value); + .map(([, value]) => value); // Divide transactions into chunks of five or less for (let i = 0; i < transactions.length; i += CHUNK_SIZE) { const chunk = transactions.slice(i, i + CHUNK_SIZE); - try { - const response = await submitBulkTransactions({ - transactions: chunk, - onError, - waitForHashes - }); - results = [...results, ...response.txResults]; - - if (response.hasError && onError === 'abort') { - setErrorRequestRejection(new Error('Some transactions were rejected')); - setTransaction(TransactionStatus.Rejected); - return results; - } - - const totalTransactions = Object.values(params.transactionsMapParam ?? {}).length; - setProgressPercentage(Math.floor((results.length / totalTransactions) * 100)); - - if (!waitForHashes && i < transactions.length) { - // Throttle requests - await new Promise((resolve) => setTimeout(resolve, 5000)); - } - } catch (e) { - throw e; + const response = await submitBulkTransactions({ + transactions: chunk, + onError, + waitForHashes + }); + results = [...results, ...response.txResults]; + + if (response.hasError && onError === 'abort') { + setErrorRequestRejection(new Error('Some transactions were rejected')); + setTransaction(TransactionStatus.Rejected); + return results; + } + + const totalTransactions = Object.values(params.transactionsMapParam ?? {}).length; + setProgressPercentage(Math.floor((results.length / totalTransactions) * 100)); + + if (!waitForHashes && i < transactions.length) { + // Throttle requests + await new Promise((resolve) => setTimeout(resolve, 5000)); } } @@ -263,10 +259,10 @@ export const SubmitBulkTransactions: FC = () => { const { transactionsMapParam } = params; const allTransactions = transactionsMapParam ?? {}; - let transactionsToDisplay: Record = {}; + const transactionsToDisplay: Record = {}; let i = 0; - for (let key in allTransactions) { - if (allTransactions.hasOwnProperty(key)) { + for (const key in allTransactions) { + if (Object.prototype.hasOwnProperty.call(allTransactions, key)) { if ( i >= activeStep * MAX_TRANSACTIONS_PER_STEP && i < (activeStep + 1) * MAX_TRANSACTIONS_PER_STEP diff --git a/packages/extension/src/components/pages/SubmitRawTransaction/SubmitRawTransaction.tsx b/packages/extension/src/components/pages/SubmitRawTransaction/SubmitRawTransaction.tsx index c5f09e56b..8ab5c4dba 100644 --- a/packages/extension/src/components/pages/SubmitRawTransaction/SubmitRawTransaction.tsx +++ b/packages/extension/src/components/pages/SubmitRawTransaction/SubmitRawTransaction.tsx @@ -38,8 +38,13 @@ export const SubmitRawTransaction: FC = () => { navigate(SETTINGS_PATH); }, [navigate]); + interface ParsedTransaction { + Account?: string; + [key: string]: unknown; + } + const validateTx = useCallback( - (parsed: any) => { + (parsed: ParsedTransaction) => { if (!('Account' in parsed)) { parsed.Account = wallet?.publicAddress; } diff --git a/packages/extension/src/components/templates/GemWallet/GemWallet.tsx b/packages/extension/src/components/templates/GemWallet/GemWallet.tsx new file mode 100644 index 000000000..cc64f6bfc --- /dev/null +++ b/packages/extension/src/components/templates/GemWallet/GemWallet.tsx @@ -0,0 +1,77 @@ +import React, { useMemo } from 'react'; + +import Paper from '@mui/material/Paper'; +import { ThemeProvider, createTheme } from '@mui/material/styles'; + +import { BrowserRouter } from 'react-router-dom'; + +import { POPUP_HEIGHT, POPUP_WIDTH } from '../../../constants'; +import { + BrowserProvider, + LedgerProvider, + NavBarPositionProvider, + NetworkProvider, + ServerProvider, + TransactionProgressProvider, + WalletProvider +} from '../../../contexts'; +import App from '../../../App'; + +export const GemWallet = () => { + const theme = useMemo( + () => + createTheme({ + ...{ + palette: { + mode: 'dark' + }, + components: { + MuiBottomNavigation: { + styleOverrides: { + root: { + backgroundColor: 'transparent', + borderTop: 'solid 1px #bcbcbc' + } + } + }, + MuiBottomNavigationAction: { + styleOverrides: { + root: { + '&.Mui-selected': { + color: '#ffffff' + } + } + } + } + } + } + }), + [] + ); + + return ( + + + + + + + + + + + + + + + + + + + + + + + + ); +}; diff --git a/packages/extension/src/components/templates/GemWallet/index.ts b/packages/extension/src/components/templates/GemWallet/index.ts new file mode 100644 index 000000000..35d04a8e8 --- /dev/null +++ b/packages/extension/src/components/templates/GemWallet/index.ts @@ -0,0 +1 @@ +export * from './GemWallet'; diff --git a/packages/extension/src/contexts/LedgerContext/LedgerContext.tsx b/packages/extension/src/contexts/LedgerContext/LedgerContext.tsx index 412797883..905970aa2 100644 --- a/packages/extension/src/contexts/LedgerContext/LedgerContext.tsx +++ b/packages/extension/src/contexts/LedgerContext/LedgerContext.tsx @@ -166,7 +166,12 @@ export interface LedgerContextType { getNFTData: (payload: NFTImageRequest) => Promise; deleteAccount: (destinationAddress: string) => Promise; getNFTInfo: (NFTokenID: string) => Promise; - getLedgerEntry: (ID: string) => Promise; + getLedgerEntry: (ID: string) => Promise< + LedgerEntryResponse<{ + Amount: string; + NFTokenID: string; + }> + >; setHook: (payload: SetHook) => Promise; } @@ -835,15 +840,21 @@ const LedgerProvider: FC = ({ children }) => { ); const getLedgerEntry = useCallback( - async (ID: string): Promise => { + async function (ID: string) { if (!client) throw new Error('You need to be connected to a ledger'); try { - return client.request({ + return client.request< + LedgerEntryRequest, + LedgerEntryResponse<{ + Amount: string; + NFTokenID: string; + }> + >({ command: 'ledger_entry', index: ID, ledger_index: 'validated' - } as LedgerEntryRequest); + }); } catch (e) { Sentry.captureException(e); throw e; diff --git a/packages/extension/src/contexts/LedgerContext/chains/XRPL.ts b/packages/extension/src/contexts/LedgerContext/chains/XRPL.ts index bb20f602d..ecfcbd064 100644 --- a/packages/extension/src/contexts/LedgerContext/chains/XRPL.ts +++ b/packages/extension/src/contexts/LedgerContext/chains/XRPL.ts @@ -71,7 +71,7 @@ export const handleMintNFT = async (param: { const tx = await submit({ transaction, client, wallet }); const NFTokenID = tx.result.meta && typeof tx.result.meta === 'object' && 'nftoken_id' in tx.result.meta - ? ((tx.result.meta as any).nftoken_id as string) + ? tx.result.meta.nftoken_id : undefined; if (NFTokenID) { diff --git a/packages/extension/src/contexts/LedgerContext/chains/Xahau.ts b/packages/extension/src/contexts/LedgerContext/chains/Xahau.ts index 640db5403..58a6df35d 100644 --- a/packages/extension/src/contexts/LedgerContext/chains/Xahau.ts +++ b/packages/extension/src/contexts/LedgerContext/chains/Xahau.ts @@ -1,5 +1,13 @@ import { Client, NFTokenMint, setTransactionFlagsToNumber, Wallet as WalletXRPL } from 'xrpl'; -import { XrplClient, XrplDefinitions, derive, sign, signAndSubmit, utils } from 'xrpl-accountlib'; +import { + DefinitionsData, + XrplClient, + XrplDefinitions, + derive, + sign, + signAndSubmit, + utils +} from 'xrpl-accountlib'; import { FAUCET_XAHAU_TESTNET, @@ -62,7 +70,7 @@ export const handleTransaction = async (param: { // Logic comes from: https://github.com/WietseWind/xrpl-accountlib/blob/master/src/sign/index.ts#L203 const connection = new XrplClient(server); const definitions = (await connection.definitions()) ?? undefined; - const signed = sign(tx, account, new XrplDefinitions(definitions as any)); + const signed = sign(tx, account, new XrplDefinitions(definitions as DefinitionsData)); if (!signed.signedTransaction) { throw new Error("Couldn't sign the transaction"); diff --git a/packages/extension/src/contexts/LedgerContext/utils/buildXRPLTransaction.test.ts b/packages/extension/src/contexts/LedgerContext/utils/buildXRPLTransaction.test.ts index 6e7551557..de9bb1377 100644 --- a/packages/extension/src/contexts/LedgerContext/utils/buildXRPLTransaction.test.ts +++ b/packages/extension/src/contexts/LedgerContext/utils/buildXRPLTransaction.test.ts @@ -1,4 +1,4 @@ -import { Path, SetRegularKey } from 'xrpl'; +import { Path, SetRegularKey, Wallet } from 'xrpl'; import { Amount } from 'xrpl/dist/npm/models/common'; import { NFTokenMint } from 'xrpl/dist/npm/models/transactions/NFTokenMint'; @@ -30,7 +30,7 @@ import { describe, it, expect } from 'vitest'; const wallet: WalletLedger = { name: 'name', publicAddress: 'publicAddress', - wallet: {} as any + wallet: {} as Wallet }; describe('buildBaseTransaction', () => { diff --git a/packages/extension/src/contexts/LedgerContext/utils/buildXahauTransaction.test.ts b/packages/extension/src/contexts/LedgerContext/utils/buildXahauTransaction.test.ts index e8f25ed49..eb285a168 100644 --- a/packages/extension/src/contexts/LedgerContext/utils/buildXahauTransaction.test.ts +++ b/packages/extension/src/contexts/LedgerContext/utils/buildXahauTransaction.test.ts @@ -3,11 +3,12 @@ import { SetHookRequest } from '@gemwallet/constants'; import { WalletLedger } from '../../../types'; import { buildSetHook } from './buildXahauTransaction'; import { describe, it, expect } from 'vitest'; +import { Wallet } from 'xrpl'; const wallet: WalletLedger = { name: 'name', publicAddress: 'publicAddress', - wallet: {} as any + wallet: {} as Wallet }; describe('buildSetHook', () => { diff --git a/packages/extension/src/global.d.ts b/packages/extension/src/global.d.ts new file mode 100644 index 000000000..c599834da --- /dev/null +++ b/packages/extension/src/global.d.ts @@ -0,0 +1,7 @@ +declare global { + interface Window { + Cypress?: unknown; + } +} + +export {}; diff --git a/packages/extension/src/hooks/useFees/useFees.ts b/packages/extension/src/hooks/useFees/useFees.ts index 60044f83e..c0c509eb9 100644 --- a/packages/extension/src/hooks/useFees/useFees.ts +++ b/packages/extension/src/hooks/useFees/useFees.ts @@ -68,8 +68,8 @@ export const useFees = (tx: Transaction | Transaction[], fee?: string | null) => setDifference(difference); Sentry.captureException(e); } - } catch (e: any) { - setError(`Error while calculating fees: ${e.message}`); + } catch (e) { + setError(`Error while calculating fees: ${(e as Error).message}`); Sentry.captureException(e); } }; diff --git a/packages/extension/src/index.tsx b/packages/extension/src/index.tsx index 11c304d68..5ae3b5d87 100644 --- a/packages/extension/src/index.tsx +++ b/packages/extension/src/index.tsx @@ -1,31 +1,18 @@ -import React, { useMemo } from 'react'; +import React from 'react'; -import Paper from '@mui/material/Paper'; -import { ThemeProvider, createTheme } from '@mui/material/styles'; import { BrowserTracing, Replay } from '@sentry/browser'; import * as Sentry from '@sentry/react'; import { - BrowserRouter, useLocation, useNavigationType, createRoutesFromChildren, matchRoutes } from 'react-router-dom'; -import App from './App'; -import { POPUP_HEIGHT, POPUP_WIDTH } from './constants'; -import { - BrowserProvider, - LedgerProvider, - NavBarPositionProvider, - NetworkProvider, - ServerProvider, - TransactionProgressProvider, - WalletProvider -} from './contexts'; import reportWebVitals from './reportWebVitals'; import './index.css'; import { createRoot } from 'react-dom/client'; +import { GemWallet } from './components/templates/GemWallet'; Sentry.init({ dsn: process.env.REACT_APP_SENTRY_DSN, @@ -51,65 +38,6 @@ Sentry.init({ replaysOnErrorSampleRate: process.env.NODE_ENV === 'development' ? 0.0 : 1.0 }); -const GemWallet = () => { - const theme = useMemo( - () => - createTheme({ - ...{ - palette: { - mode: 'dark' - }, - components: { - MuiBottomNavigation: { - styleOverrides: { - root: { - backgroundColor: 'transparent', - borderTop: 'solid 1px #bcbcbc' - } - } - }, - MuiBottomNavigationAction: { - styleOverrides: { - root: { - '&.Mui-selected': { - color: '#ffffff' - } - } - } - } - } - } - }), - [] - ); - - return ( - - - - - - - - - - - - - - - - - - - - - - - - ); -}; - createRoot(document.getElementById('root') as HTMLElement).render(); // If you want to start measuring performance in your app, pass a function diff --git a/packages/extension/src/setupTests.ts b/packages/extension/src/setupTests.ts index ce58896dd..54afad7a1 100644 --- a/packages/extension/src/setupTests.ts +++ b/packages/extension/src/setupTests.ts @@ -7,6 +7,7 @@ import { vi } from 'vitest'; import 'vitest-canvas-mock'; // Export globally TextEncoder and TextDecoder for hashicon-react +// eslint-disable-next-line @typescript-eslint/no-var-requires const { TextEncoder, TextDecoder } = require('util'); global.TextEncoder = TextEncoder; global.TextDecoder = TextDecoder; diff --git a/packages/extension/src/types/utils.types.ts b/packages/extension/src/types/utils.types.ts index a87516199..9ce177437 100644 --- a/packages/extension/src/types/utils.types.ts +++ b/packages/extension/src/types/utils.types.ts @@ -1 +1,13 @@ export type PartiallyOptional = Omit & Partial>; + +export type PartialExcept = Partial & Required>; + +export type DeepPartial = T extends object + ? { + [P in keyof T]?: DeepPartial; + } + : T; + +export type DeepPartialExcept = { + [P in keyof T]: P extends K ? T[P] : T[P] extends object ? DeepPartial : T[P] | undefined; +}; diff --git a/packages/extension/src/utils/NFTViewer.test.ts b/packages/extension/src/utils/NFTViewer.test.ts index a64da1baa..cc5686d1b 100644 --- a/packages/extension/src/utils/NFTViewer.test.ts +++ b/packages/extension/src/utils/NFTViewer.test.ts @@ -37,8 +37,8 @@ describe('parseJSON function', () => { global.fetch = vi.fn(() => Promise.resolve({ json: () => Promise.resolve({ name: 'Mock NFT' }) - }) - ) as any; + } as Response) + ); }); afterEach(() => { @@ -62,7 +62,7 @@ describe('parseJSON function', () => { it('throws an error when the fetch promise rejects', async () => { // Mock the fetch function to reject with an error - global.fetch = vi.fn(() => Promise.reject('Error')) as any; + global.fetch = vi.fn(() => Promise.reject('Error')); const mockUrl = 'https://someUrl.json'; const mockNFTokenID = '123'; diff --git a/packages/extension/src/utils/baseParams.ts b/packages/extension/src/utils/baseParams.ts index 9ebc7c8d9..a7447cb57 100644 --- a/packages/extension/src/utils/baseParams.ts +++ b/packages/extension/src/utils/baseParams.ts @@ -2,6 +2,7 @@ import { Memo, Signer } from '@gemwallet/constants'; import { parseMemos, parseSigners } from './parseParams'; import { checkFee } from './transaction'; +import { DeepPartialExcept } from '../types'; export type BaseTransactionParamsNew = { fee?: string; @@ -31,15 +32,15 @@ export const parseBaseParamsFromURLParamsNew = ( } }; - addParam('fee', checkFee(urlParams.get('fee'))); + addParam('fee', checkFee(urlParams.get('fee') || undefined)); addParam('sequence', urlParams.get('sequence') ? Number(urlParams.get('sequence')) : undefined); addParam('accountTxnID', urlParams.get('accountTxnID')); addParam( 'lastLedgerSequence', urlParams.get('lastLedgerSequence') ? Number(urlParams.get('lastLedgerSequence')) : undefined ); - addParam('memos', parseMemos(urlParams.get('memos'))); - addParam('signers', parseSigners(urlParams.get('signers'))); + addParam('memos', parseMemos(urlParams.get('memos') || undefined)); + addParam('signers', parseSigners(urlParams.get('signers') || undefined)); addParam( 'sourceTag', urlParams.get('sourceTag') ? Number(urlParams.get('sourceTag')) : undefined @@ -54,7 +55,9 @@ export const parseBaseParamsFromURLParamsNew = ( return result; }; -export const parseBaseParamsFromStoredData = (storedObject: any): BaseTransactionParamsNew => { +export const parseBaseParamsFromStoredData = ( + storedObject: DeepPartialExcept +): BaseTransactionParamsNew => { const result: Partial = {}; const addParam = ( @@ -121,14 +124,14 @@ export const initialBaseTransactionParams: BaseTransactionParams = { export const parseBaseParamsFromURLParams = (urlParams: URLSearchParams): BaseTransactionParams => { return { - fee: checkFee(urlParams.get('fee')), + fee: checkFee(urlParams.get('fee') || undefined) || null, sequence: urlParams.get('sequence') ? Number(urlParams.get('sequence')) : null, accountTxnID: urlParams.get('accountTxnID'), lastLedgerSequence: urlParams.get('lastLedgerSequence') ? Number(urlParams.get('lastLedgerSequence')) : null, - memos: parseMemos(urlParams.get('memos')), - signers: parseSigners(urlParams.get('signers')), + memos: parseMemos(urlParams.get('memos') || undefined) || null, + signers: parseSigners(urlParams.get('signers') || undefined) || null, sourceTag: urlParams.get('sourceTag') ? Number(urlParams.get('sourceTag')) : null, signingPubKey: urlParams.get('signingPubKey'), ticketSequence: urlParams.get('ticketSequence') @@ -138,7 +141,7 @@ export const parseBaseParamsFromURLParams = (urlParams: URLSearchParams): BaseTr }; }; -export const getBaseFromParams = (params: any) => { +export const getBaseFromParams = (params: Partial) => { return { fee: params.fee || undefined, sequence: params.sequence || undefined, diff --git a/packages/extension/src/utils/fetchTokenData.ts b/packages/extension/src/utils/fetchTokenData.ts index 354b6341d..335e1e083 100644 --- a/packages/extension/src/utils/fetchTokenData.ts +++ b/packages/extension/src/utils/fetchTokenData.ts @@ -17,17 +17,24 @@ export const getTrustLineData = async (params: { const { token, issuer } = params; try { - const cachedData = await loadFromChromeSessionStorage(`tokenData-${token}-${issuer}`); + const cachedData = await loadFromChromeSessionStorage( + `tokenData-${token}-${issuer}` + ); if (cachedData) { return cachedData; } } catch (e) { - } finally { + // nothing + } + + try { const fetchedData = fetchDataFromAPI(token, issuer); if (fetchedData) { saveInChromeSessionStorage(`tokenData-${token}-${issuer}`, fetchedData); return fetchedData; } + } catch (e) { + // nothing } return { diff --git a/packages/extension/src/utils/link.test.ts b/packages/extension/src/utils/link.test.ts index 9b2a0c675..d93b421ea 100644 --- a/packages/extension/src/utils/link.test.ts +++ b/packages/extension/src/utils/link.test.ts @@ -5,7 +5,6 @@ describe('openExternalLink', () => { it('should open a new window with the given url', () => { // Arrange const url = 'http://example.com'; - // @ts-ignore window.open = vi.fn(); // Act diff --git a/packages/extension/src/utils/network.test.ts b/packages/extension/src/utils/network.test.ts index 6cf56f406..96b4d0963 100644 --- a/packages/extension/src/utils/network.test.ts +++ b/packages/extension/src/utils/network.test.ts @@ -84,7 +84,6 @@ describe('removeNetwork', () => { try { await removeNetwork(); } catch (e) { - // eslint-disable-next-line jest/no-conditional-expect expect(e).toBe(error); } }); diff --git a/packages/extension/src/utils/parseParams.test.ts b/packages/extension/src/utils/parseParams.test.ts index dd6a72242..f9b58cf03 100644 --- a/packages/extension/src/utils/parseParams.test.ts +++ b/packages/extension/src/utils/parseParams.test.ts @@ -133,19 +133,19 @@ describe('parseMemos', () => { describe('parseSigners', () => { it('should return null when input is null', () => { - expect(parseSigners(null)).toBeNull(); + expect(parseSigners(undefined)).toBeUndefined(); }); it('should return null when input is an empty string', () => { - expect(parseSigners('')).toBeNull(); + expect(parseSigners('')).toBeUndefined(); }); it('should return null when input is not a valid JSON string', () => { - expect(parseSigners('invalidJSON')).toBeNull(); + expect(parseSigners('invalidJSON')).toBeUndefined(); }); it('should return null when input is a valid JSON string but not an array', () => { - expect(parseSigners('{"key": "value"}')).toBeNull(); + expect(parseSigners('{"key": "value"}')).toBeUndefined(); }); it('should return parsed signers when input is a valid JSON string of signers array or already signers array', () => { diff --git a/packages/extension/src/utils/parseParams.ts b/packages/extension/src/utils/parseParams.ts index 098db860a..84d3ce6e2 100644 --- a/packages/extension/src/utils/parseParams.ts +++ b/packages/extension/src/utils/parseParams.ts @@ -135,9 +135,9 @@ export const parseLimitAmount = ( return null; }; -export const parseMemos = (input: Memo[] | string | null): Memo[] | null => { +export const parseMemos = (input: Memo[] | string | undefined): Memo[] | undefined => { if (!input) { - return null; + return; } if (typeof input === 'object' && Array.isArray(input)) { @@ -155,12 +155,12 @@ export const parseMemos = (input: Memo[] | string | null): Memo[] | null => { /* empty */ } - return null; + return; }; -export const parseSigners = (input: Signer[] | string | null): Signer[] | null => { +export const parseSigners = (input: Signer[] | string | undefined): Signer[] | undefined => { if (!input) { - return null; + return; } if (typeof input === 'object' && Array.isArray(input)) { @@ -178,12 +178,12 @@ export const parseSigners = (input: Signer[] | string | null): Signer[] | null = /* empty */ } - return null; + return; }; -export const parsePaymentFlags = (input?: PaymentFlags | string): PaymentFlags | null => { +export const parsePaymentFlags = (input?: PaymentFlags | string): PaymentFlags | undefined => { if (!input) { - return null; + return; } if (typeof input === 'object' || typeof input === 'number') { @@ -215,7 +215,7 @@ export const parsePaymentFlags = (input?: PaymentFlags | string): PaymentFlags | /* empty */ } - return null; + return; }; export const parseTrustSetFlags = (input?: TrustSetFlags | string): TrustSetFlags | null => { diff --git a/packages/extension/src/utils/storageChromeSession.ts b/packages/extension/src/utils/storageChromeSession.ts index 88fd57a4a..6e02d4ed1 100644 --- a/packages/extension/src/utils/storageChromeSession.ts +++ b/packages/extension/src/utils/storageChromeSession.ts @@ -2,13 +2,9 @@ * Manages the storage in Chrome session storage */ -interface CypressWindow extends Window { - Cypress?: any; -} - -export const saveInChromeSessionStorage = (key: string, value: any): Promise => { +export const saveInChromeSessionStorage = (key: string, value: unknown): Promise => { return new Promise((resolve, reject) => { - if (process.env.NODE_ENV === 'production' || (window as CypressWindow).Cypress) { + if (process.env.NODE_ENV === 'production' || window.Cypress) { chrome.storage.session.set({ [key]: value }, () => { if (chrome.runtime.lastError) { reject(chrome.runtime.lastError); @@ -22,10 +18,10 @@ export const saveInChromeSessionStorage = (key: string, value: any): Promise( key: string, deleteAfterLoad: boolean = false -): Promise => { +): Promise => { return new Promise((resolve, reject) => { chrome.storage.session.get(key, (result) => { if (chrome.runtime.lastError) { diff --git a/packages/extension/src/utils/transaction.test.ts b/packages/extension/src/utils/transaction.test.ts index f53fc059a..3e40d4734 100644 --- a/packages/extension/src/utils/transaction.test.ts +++ b/packages/extension/src/utils/transaction.test.ts @@ -223,15 +223,15 @@ describe('buildAmount', () => { describe('checkFee', () => { it('should return null if fee is null', () => { - expect(checkFee(null)).toBe(null); + expect(checkFee(undefined)).toBeUndefined(); }); it('should return null if fee is an empty string', () => { - expect(checkFee('')).toBe(null); + expect(checkFee('')).toBeUndefined(); }); it('should return null if fee is not a number string', () => { - expect(checkFee('abc')).toBe(null); + expect(checkFee('abc')).toBeUndefined(); }); it('should return the fee if it is a number string and dropsToXrp does not throw an error', () => { diff --git a/packages/extension/src/utils/transaction.ts b/packages/extension/src/utils/transaction.ts index b96aa353a..fe4fd7a64 100644 --- a/packages/extension/src/utils/transaction.ts +++ b/packages/extension/src/utils/transaction.ts @@ -89,7 +89,7 @@ export const buildDestinationTag = (destinationTag: string | undefined): number return Number(destinationTag); }; -export const checkFee = (fee: string | null) => { +export const checkFee = (fee: string | undefined): string | undefined => { if (fee) { try { if (Number(fee) && dropsToXrp(fee)) { @@ -99,7 +99,8 @@ export const checkFee = (fee: string | null) => { /* empty */ } } - return null; + + return; }; export const buildAmount = ( diff --git a/packages/extension/src/utils/typeof-fns.ts b/packages/extension/src/utils/typeof-fns.ts index b66da8b48..33541d790 100644 --- a/packages/extension/src/utils/typeof-fns.ts +++ b/packages/extension/src/utils/typeof-fns.ts @@ -26,7 +26,7 @@ export const isString = isTypeof('string'); export const isUndefined = isTypeof('undefined'); /** Determines if a value is an object (excluding arrays and functions). */ -export const isObject = >(thing: unknown): thing is T => { +export const isObject = >(thing: unknown): thing is T => { if (thing === null || typeof thing !== 'object') return false; return thing.toString() === '[object Object]'; }; From da7b6cfba93fcb52c67510c63b374704860c49ca Mon Sep 17 00:00:00 2001 From: Benaor Date: Sun, 29 Dec 2024 11:59:13 +0100 Subject: [PATCH 2/2] fix(linter): remove all of any types --- .../molecules/DataCard/DataCard.tsx | 4 ++-- .../pages/Transaction/Transaction.tsx | 2 +- .../useFetchFromSessionStorage.ts | 2 +- .../extension/src/utils/baseParams.test.ts | 7 +++--- packages/extension/src/utils/baseParams.ts | 23 +++++++++++++++---- packages/extension/src/utils/parseParams.ts | 12 ++++++---- 6 files changed, 34 insertions(+), 16 deletions(-) diff --git a/packages/extension/src/components/molecules/DataCard/DataCard.tsx b/packages/extension/src/components/molecules/DataCard/DataCard.tsx index 07e93ddcb..e51728db6 100644 --- a/packages/extension/src/components/molecules/DataCard/DataCard.tsx +++ b/packages/extension/src/components/molecules/DataCard/DataCard.tsx @@ -1,4 +1,4 @@ -import { FC, useEffect, useRef, useState } from 'react'; +import { FC, ReactNode, useEffect, useRef, useState } from 'react'; import ChevronRightIcon from '@mui/icons-material/ChevronRight'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; @@ -7,7 +7,7 @@ import { IconButton, Paper, Typography } from '@mui/material'; import { SECONDARY_GRAY } from '../../../constants'; export interface DataCardProps { - formattedData: string; + formattedData: ReactNode; dataName?: string; isExpanded: boolean; setIsExpanded: (value: boolean) => void; diff --git a/packages/extension/src/components/pages/Transaction/Transaction.tsx b/packages/extension/src/components/pages/Transaction/Transaction.tsx index 34dc4d8ae..b3016d041 100644 --- a/packages/extension/src/components/pages/Transaction/Transaction.tsx +++ b/packages/extension/src/components/pages/Transaction/Transaction.tsx @@ -159,7 +159,7 @@ export const Transaction: FC = () => { const transaction = buildPayment( { - ...parseBaseParamsFromStoredData(fetchedData), + ...parseBaseParamsFromStoredData(fetchedData as SendPaymentRequest), amount: amount ?? '0', destination: destination ?? '', ...(destinationTag && { destinationTag }), diff --git a/packages/extension/src/hooks/useFetchFromSessionStorage/useFetchFromSessionStorage.ts b/packages/extension/src/hooks/useFetchFromSessionStorage/useFetchFromSessionStorage.ts index 555b1a33b..8f633c031 100644 --- a/packages/extension/src/hooks/useFetchFromSessionStorage/useFetchFromSessionStorage.ts +++ b/packages/extension/src/hooks/useFetchFromSessionStorage/useFetchFromSessionStorage.ts @@ -13,7 +13,7 @@ export const useFetchFromSessionStorage = (key?: string) => { const fetchData = async () => { try { if (key) { - const storedData = await loadFromChromeSessionStorage(key, true); + const storedData = await loadFromChromeSessionStorage(key, true); if (storedData) { setFetchedData(JSON.parse(storedData)); } diff --git a/packages/extension/src/utils/baseParams.test.ts b/packages/extension/src/utils/baseParams.test.ts index 980b770e8..9dec6a2c2 100644 --- a/packages/extension/src/utils/baseParams.test.ts +++ b/packages/extension/src/utils/baseParams.test.ts @@ -1,4 +1,5 @@ import { + AnyBaseTransactionParamsNew, getBaseFromParams, initialBaseTransactionParams, parseBaseParamsFromStoredData, @@ -81,7 +82,7 @@ describe('parseBaseParamsFromURLParams', () => { describe('getBaseFromParams', () => { test('should get base transaction parameters from an object', () => { - const params = { + const params: AnyBaseTransactionParamsNew = { fee: '10', sequence: 1, accountTxnID: '123', @@ -100,7 +101,7 @@ describe('getBaseFromParams', () => { }); test('should handle undefined parameters', () => { - const params = {}; + const params: AnyBaseTransactionParamsNew = {}; const result = getBaseFromParams(params); @@ -121,7 +122,7 @@ describe('getBaseFromParams', () => { describe('parseBaseParamsFromStoredData', () => { it('should parse all values correctly', () => { - const storedObject = { + const storedObject: AnyBaseTransactionParamsNew = { fee: '12', sequence: '2', accountTxnID: 'abc123', diff --git a/packages/extension/src/utils/baseParams.ts b/packages/extension/src/utils/baseParams.ts index a7447cb57..73700bee2 100644 --- a/packages/extension/src/utils/baseParams.ts +++ b/packages/extension/src/utils/baseParams.ts @@ -2,7 +2,6 @@ import { Memo, Signer } from '@gemwallet/constants'; import { parseMemos, parseSigners } from './parseParams'; import { checkFee } from './transaction'; -import { DeepPartialExcept } from '../types'; export type BaseTransactionParamsNew = { fee?: string; @@ -18,6 +17,20 @@ export type BaseTransactionParamsNew = { txnSignature?: string; }; +export type AnyBaseTransactionParamsNew = Partial<{ + fee: string; + sequence: string | number; + accountTxnID: string; + lastLedgerSequence: string | number; + memos: Record[] | unknown[] | Memo[]; + networkID: string | number; + signers: Record[] | unknown[] | Signer[]; + sourceTag: string | number; + signingPubKey: string; + ticketSequence: string | number; + txnSignature: string; +}>; + export const parseBaseParamsFromURLParamsNew = ( urlParams: URLSearchParams ): BaseTransactionParamsNew => { @@ -56,13 +69,13 @@ export const parseBaseParamsFromURLParamsNew = ( }; export const parseBaseParamsFromStoredData = ( - storedObject: DeepPartialExcept + storedObject: AnyBaseTransactionParamsNew ): BaseTransactionParamsNew => { const result: Partial = {}; const addParam = ( key: T, - value: BaseTransactionParamsNew[T] | null + value: BaseTransactionParamsNew[T] ) => { if (value !== null && value !== undefined) { result[key] = value; @@ -77,7 +90,7 @@ export const parseBaseParamsFromStoredData = ( 'lastLedgerSequence' in storedObject ? Number(storedObject.lastLedgerSequence) : undefined ); addParam('memos', 'memos' in storedObject ? parseMemos(storedObject.memos) : undefined); - addParam('networkID', 'networkID' in storedObject ? storedObject.networkID : undefined); + addParam('networkID', 'networkID' in storedObject ? Number(storedObject.networkID) : undefined); addParam('signers', 'signers' in storedObject ? parseSigners(storedObject.signers) : undefined); addParam('sourceTag', 'sourceTag' in storedObject ? Number(storedObject.sourceTag) : undefined); addParam( @@ -141,7 +154,7 @@ export const parseBaseParamsFromURLParams = (urlParams: URLSearchParams): BaseTr }; }; -export const getBaseFromParams = (params: Partial) => { +export const getBaseFromParams = (params: AnyBaseTransactionParamsNew) => { return { fee: params.fee || undefined, sequence: params.sequence || undefined, diff --git a/packages/extension/src/utils/parseParams.ts b/packages/extension/src/utils/parseParams.ts index 84d3ce6e2..cb11f0fb8 100644 --- a/packages/extension/src/utils/parseParams.ts +++ b/packages/extension/src/utils/parseParams.ts @@ -135,13 +135,15 @@ export const parseLimitAmount = ( return null; }; -export const parseMemos = (input: Memo[] | string | undefined): Memo[] | undefined => { +export const parseMemos = ( + input: Memo[] | Record[] | unknown[] | string | undefined +): Memo[] | undefined => { if (!input) { return; } if (typeof input === 'object' && Array.isArray(input)) { - return input; + return input as Memo[]; } // For API version < 3.6 @@ -158,13 +160,15 @@ export const parseMemos = (input: Memo[] | string | undefined): Memo[] | undefin return; }; -export const parseSigners = (input: Signer[] | string | undefined): Signer[] | undefined => { +export const parseSigners = ( + input: Signer[] | Record[] | unknown[] | string | undefined +): Signer[] | undefined => { if (!input) { return; } if (typeof input === 'object' && Array.isArray(input)) { - return input; + return input as Signer[]; } // For API version < 3.6