diff --git a/source/Modules/Controller/controllerBase.js b/source/Modules/Controller/controllerBase.js index 5c234de7..cf28334e 100644 --- a/source/Modules/Controller/controllerBase.js +++ b/source/Modules/Controller/controllerBase.js @@ -1,7 +1,12 @@ import qs from 'query-string'; import extension from 'extensionizer'; -import { checkPendingTransaction, createPendingTransaction, removePendingTransaction } from '@modules/storageManager'; +import { + checkPendingTransaction, + createPendingTransaction, + removePendingTransaction, + resetPendingTransactions, +} from '@modules/storageManager'; import ERRORS from '@background/errors'; import SIZES from '../../views/Popup/components/Transfer/constants'; @@ -30,6 +35,7 @@ export class ControllerModuleBase { this.keyring = keyring; this.secureController = secureController; this.backgroundController = backgroundController; + resetPendingTransactions(); } secureWrapper({ args, handlerObject }) { @@ -48,9 +54,8 @@ export class ControllerModuleBase { return this.secureController( args[0].callback, async () => { - createPendingTransaction((transactionId) => { - handlerObject.handler(...newArgs, transactionId); - }); + const transactionId = await createPendingTransaction(); + await handlerObject.handler(...newArgs, transactionId); }, ); } @@ -66,9 +71,8 @@ export class ControllerModuleBase { return this.secureController( methodArgs[0].callback, async () => { - handlerObject.handler(...methodArgs); - removePendingTransaction(transactionId, () => { - }); + await handlerObject.handler(...methodArgs); + await removePendingTransaction(transactionId); }, ); }); diff --git a/source/Modules/storageManager.js b/source/Modules/storageManager.js index 7039b697..6451020d 100644 --- a/source/Modules/storageManager.js +++ b/source/Modules/storageManager.js @@ -183,10 +183,29 @@ export const setDabContacts = (dabContacts = [], cb = () => ([])) => { secureSetWrapper({ dabContacts }, [], cb); }; -export const createPendingTransaction = (cb) => { +const setActiveTransactions = (newActiveTransactions) => new Promise((resolve) => { + secureSetWrapper({ activeTransactions: newActiveTransactions }, {}, resolve); +}); + +const getActiveTransactions = () => new Promise((resolve) => { + const defaultValue = {}; + secureGetWrapper('activeTransactions', defaultValue, (state) => { + const activeTransactions = state?.activeTransactions || defaultValue; + resolve(activeTransactions); + }); +}); + +export const createPendingTransaction = async () => { const id = uuidv4(); - secureSetWrapper({ activeTransactions: { [id]: 'pending' } }, {}, () => cb(id)); + const activeTransactions = await getActiveTransactions(); + const newActiveTransactions = { + ...activeTransactions, + [id]: 'pending', + }; + await setActiveTransactions(newActiveTransactions); + return id; }; + export const checkPendingTransaction = (transactionId, cb) => { secureGetWrapper('activeTransactions', 'pending', (entry) => { cb(entry.activeTransactions[transactionId]); @@ -194,19 +213,21 @@ export const checkPendingTransaction = (transactionId, cb) => { }; export const reviewPendingTransaction = async (transactionId) => { + const activeTransactions = await getActiveTransactions(); const getTxStatus = () => new Promise((resolve) => { checkPendingTransaction(transactionId, resolve); }); - const setData = () => new Promise((resolve) => { - secureSetWrapper({ activeTransactions: { [transactionId]: 'reviewed' } }, {}, resolve); - }); + const newActiveTransactions = { ...activeTransactions, [transactionId]: 'reviewed' }; const txStatus = await getTxStatus(); - if (txStatus !== 'pending') throw new Error('Unauthorized review'); - const result = await setData(); - return result; + if (txStatus === 'pending') { + return setActiveTransactions(newActiveTransactions); + } + return null; }; -export const removePendingTransaction = (transactionId, cb) => { - secureSetWrapper({ activeTransactions: { [transactionId]: undefined } }, {}, cb); +export const removePendingTransaction = async (transactionId) => { + const activeTransactions = await getActiveTransactions(); + const newActiveTransactions = { ...activeTransactions, [transactionId]: undefined }; + await setActiveTransactions(newActiveTransactions); }; export const resetPendingTransactions = () => { diff --git a/source/views/Popup/components/AllowAgent/index.jsx b/source/views/Popup/components/AllowAgent/index.jsx index d8b9d0be..f391248f 100644 --- a/source/views/Popup/components/AllowAgent/index.jsx +++ b/source/views/Popup/components/AllowAgent/index.jsx @@ -58,7 +58,7 @@ const AllowAgent = ({ const [expand, setExpand] = useState(false); const handleAllowAgent = async (status) => { - reviewPendingTransaction(transactionId, () => {}); + await reviewPendingTransaction(transactionId); const success = await portRPC.call('handleAllowAgent', [ url, { status, whitelist: args.whitelist || {}, metadata }, diff --git a/source/views/Popup/components/AppConnection/index.jsx b/source/views/Popup/components/AppConnection/index.jsx index 0842dfff..02d6e67f 100644 --- a/source/views/Popup/components/AppConnection/index.jsx +++ b/source/views/Popup/components/AppConnection/index.jsx @@ -58,7 +58,7 @@ const AppConnection = ({ setOnTimeout, transactionId, metadata }) => { } = query; const handleResponse = async () => { - reviewPendingTransaction(transactionId, async () => {}); + await reviewPendingTransaction(transactionId); const success = await portRPC.call( 'handleAllowAgent', [ diff --git a/source/views/Popup/components/BurnXTC/hooks/useRequests.jsx b/source/views/Popup/components/BurnXTC/hooks/useRequests.jsx index 0e011219..02caea7f 100644 --- a/source/views/Popup/components/BurnXTC/hooks/useRequests.jsx +++ b/source/views/Popup/components/BurnXTC/hooks/useRequests.jsx @@ -42,7 +42,7 @@ const useRequests = (incomingRequests, callId, portId, transactionId) => { useEffect(async () => { if (requests.length === 0) { setLoading(true); - reviewPendingTransaction(transactionId, async () => {}); + await reviewPendingTransaction(transactionId); const success = await portRPC.call('handleRequestBurnXTC', [response, callId, portId, transactionId]); if (success) { window.close(); @@ -57,7 +57,7 @@ const useRequests = (incomingRequests, callId, portId, transactionId) => { const handleDeclineAll = async () => { const declinedRequests = requests.map((r) => ({ ...r, status: 'declined' })); - reviewPendingTransaction(transactionId, async () => {}); + await reviewPendingTransaction(transactionId); await portRPC.call('handleRequestBurnXTC', [declinedRequests, callId, portId, transactionId]); window.close(); }; diff --git a/source/views/Popup/components/ImportToken/index.jsx b/source/views/Popup/components/ImportToken/index.jsx index 4ba3e002..02238023 100644 --- a/source/views/Popup/components/ImportToken/index.jsx +++ b/source/views/Popup/components/ImportToken/index.jsx @@ -44,7 +44,7 @@ const ImportToken = ({ const handleImportToken = async (status) => { setLoading(status); - reviewPendingTransaction(transactionId, () => { }); + await reviewPendingTransaction(transactionId); const success = await portRPC.call('handleRequestImportToken', [ { status, token: { canisterId, standard, logo } }, callId, diff --git a/source/views/Popup/components/LoginProxy/index.jsx b/source/views/Popup/components/LoginProxy/index.jsx index 9158ab97..f9671880 100644 --- a/source/views/Popup/components/LoginProxy/index.jsx +++ b/source/views/Popup/components/LoginProxy/index.jsx @@ -16,7 +16,7 @@ const LoginProxy = ({ }) => { useEffect(async () => { if (metadata && callId && portId) { - await reviewPendingTransaction(transactionId, async () => {}); + await reviewPendingTransaction(transactionId); await portRPC.call(handler, [metadata.url, args || {}, callId, portId, transactionId]); window.close(); } diff --git a/source/views/Popup/components/Principal/index.jsx b/source/views/Popup/components/Principal/index.jsx index 151250a9..a8076f86 100644 --- a/source/views/Popup/components/Principal/index.jsx +++ b/source/views/Popup/components/Principal/index.jsx @@ -16,7 +16,7 @@ const Principal = ({ }) => { useEffect(async () => { if (metadata && callId && portId) { - reviewPendingTransaction(transactionId, async () => {}); + await reviewPendingTransaction(transactionId); await portRPC.call('handleGetPrincipal', [metadata.url, callId, portId, transactionId]); window.close(); } diff --git a/source/views/Popup/components/Sign/components/BatchTransactions/hooks/useRPCTransactions.jsx b/source/views/Popup/components/Sign/components/BatchTransactions/hooks/useRPCTransactions.jsx index 4c5b2731..779b2326 100644 --- a/source/views/Popup/components/Sign/components/BatchTransactions/hooks/useRPCTransactions.jsx +++ b/source/views/Popup/components/Sign/components/BatchTransactions/hooks/useRPCTransactions.jsx @@ -33,7 +33,7 @@ const useTransactions = (transactions, callId, portId, transactionId) => { const processAll = async (accepted) => { setLoading(true); - reviewPendingTransaction(transactionId, (res) => res); + await reviewPendingTransaction(transactionId); await portRPC.call('handleBatchTransactions', [ accepted, transactions, diff --git a/source/views/Popup/components/Sign/hooks/useRequest.jsx b/source/views/Popup/components/Sign/hooks/useRequest.jsx index cab039f3..14e586cd 100644 --- a/source/views/Popup/components/Sign/hooks/useRequest.jsx +++ b/source/views/Popup/components/Sign/hooks/useRequest.jsx @@ -52,7 +52,7 @@ const useRequests = (incomingRequest, callId, portId, transactionId) => { const handleResponse = async (status) => { request.status = status; const handler = request.type === 'sign' ? 'handleSign' : 'handleCall'; - reviewPendingTransaction(transactionId, async () => {}); + await reviewPendingTransaction(transactionId); const success = await portRPC.call(handler, [status, request, callId, portId, transactionId]); if (success) { window.close(); diff --git a/source/views/Popup/components/Sign/hooks/useRequests.jsx b/source/views/Popup/components/Sign/hooks/useRequests.jsx index 1970aa4e..07ca7f57 100644 --- a/source/views/Popup/components/Sign/hooks/useRequests.jsx +++ b/source/views/Popup/components/Sign/hooks/useRequests.jsx @@ -40,7 +40,7 @@ const useRequests = (incomingRequests, callId, portId, transactionId) => { useEffect(async () => { if (requests.length === 0) { setLoading(true); - reviewPendingTransaction(transactionId, async () => {}); + await reviewPendingTransaction(transactionId); const success = await portRPC.call('handleSign', [response, callId, portId, transactionId]); if (success) { window.close(); @@ -55,7 +55,7 @@ const useRequests = (incomingRequests, callId, portId, transactionId) => { const handleDeclineAll = async () => { const declinedRequests = requests.map((r) => ({ ...r, status: 'declined' })); - reviewPendingTransaction(transactionId, async () => {}); + await reviewPendingTransaction(transactionId); await portRPC.call('handleSign', [declinedRequests, callId, portId, transactionId]); window.close(); }; diff --git a/source/views/Popup/components/SignMessage/index.jsx b/source/views/Popup/components/SignMessage/index.jsx index c5d34e0e..9d59abe7 100644 --- a/source/views/Popup/components/SignMessage/index.jsx +++ b/source/views/Popup/components/SignMessage/index.jsx @@ -46,7 +46,7 @@ const SignMessage = ({ const handleSignMessage = async (status) => { setLoading(status); - reviewPendingTransaction(transactionId, () => { }); + await reviewPendingTransaction(transactionId); const success = await portRPC.call('handleRequestSignMessage', [ { status, token: { canisterId, standard, logo }, messageToSign }, callId, diff --git a/source/views/Popup/components/Transfer/hooks/useRequests.jsx b/source/views/Popup/components/Transfer/hooks/useRequests.jsx index 7b9e8156..41dc6cd3 100644 --- a/source/views/Popup/components/Transfer/hooks/useRequests.jsx +++ b/source/views/Popup/components/Transfer/hooks/useRequests.jsx @@ -54,7 +54,7 @@ const useRequests = (incomingRequests, callId, portId, transactionId) => { if (requests.length === 0) { setLoading(true); const handler = response[0].token ? 'handleRequestTransferToken' : 'handleRequestTransfer'; - reviewPendingTransaction(transactionId, async () => {}); + await reviewPendingTransaction(transactionId); const success = await portRPC.call(handler, [response, callId, portId, transactionId]); if (success) { window.close(); @@ -71,8 +71,8 @@ const useRequests = (incomingRequests, callId, portId, transactionId) => { const declinedRequests = requests.map((r) => ({ ...r, status: 'declined' })); const handler = declinedRequests[0].token ? 'handleRequestTransferToken' : 'handleRequestTransfer'; await Promise.all([ - reviewPendingTransaction(transactionId, async () => {}), - portRPC.call(handler, [declinedRequests, callId, portId, transactionId]), + await reviewPendingTransaction(transactionId), + await portRPC.call(handler, [declinedRequests, callId, portId, transactionId]), ]); window.close();