From fb0d9e1ca215424ff1890ad640bf1dd223435765 Mon Sep 17 00:00:00 2001 From: Dhruv Kelawala Date: Tue, 21 Mar 2023 11:47:17 +0000 Subject: [PATCH 1/5] fix: correct nonce --- .../transactions/transactionMessaging.ts | 768 +++++++++--------- 1 file changed, 388 insertions(+), 380 deletions(-) diff --git a/packages/extension/src/background/transactions/transactionMessaging.ts b/packages/extension/src/background/transactions/transactionMessaging.ts index b3461bbc8..333a43282 100644 --- a/packages/extension/src/background/transactions/transactionMessaging.ts +++ b/packages/extension/src/background/transactions/transactionMessaging.ts @@ -10,337 +10,414 @@ import { import { TransactionMessage } from "../../shared/messages/TransactionMessage" import { isAccountDeployed } from "../accountDeploy" import { HandleMessage, UnhandledMessage } from "../background" -import { getNonce } from "../nonce" import { argentMaxFee } from "../utils/argentMaxFee" import { addEstimatedFees } from "./fees/store" -export const handleTransactionMessage: HandleMessage< - TransactionMessage -> = async ({ msg, background: { wallet, actionQueue }, respond: respond }) => { - switch (msg.type) { - case "EXECUTE_TRANSACTION": { - const { meta } = await actionQueue.push({ - type: "TRANSACTION", - payload: msg.data, - }) - return respond({ - type: "EXECUTE_TRANSACTION_RES", - data: { actionHash: meta.hash }, - }) - } - - case "ESTIMATE_TRANSACTION_FEE": { - const selectedAccount = await wallet.getSelectedAccount() - const starknetAccount = await wallet.getSelectedStarknetAccount() - const transactions = msg.data - - if (!selectedAccount) { - throw Error("no accounts") +export const handleTransactionMessage: HandleMessage = + async ({ msg, background: { wallet, actionQueue }, respond: respond }) => { + switch (msg.type) { + case "EXECUTE_TRANSACTION": { + const { meta } = await actionQueue.push({ + type: "TRANSACTION", + payload: msg.data, + }) + return respond({ + type: "EXECUTE_TRANSACTION_RES", + data: { actionHash: meta.hash }, + }) } - try { - let txFee = "0", - maxTxFee = "0", - accountDeploymentFee: string | undefined, - maxADFee: string | undefined - if ( - selectedAccount.needsDeploy && - !(await isAccountDeployed( - selectedAccount, - starknetAccount.getClassAt, - )) - ) { - if ("estimateFeeBulk" in starknetAccount) { - const bulkTransactions: TransactionBulk = [ - { - type: "DEPLOY_ACCOUNT", - payload: await wallet.getAccountDeploymentPayload( - selectedAccount, - ), - }, - { - type: "INVOKE_FUNCTION", - payload: transactions, - }, - ] - - const estimateFeeBulk = await starknetAccount.estimateFeeBulk( - bulkTransactions, - ) - - accountDeploymentFee = number.toHex(estimateFeeBulk[0].overall_fee) - txFee = number.toHex(estimateFeeBulk[1].overall_fee) - - maxADFee = argentMaxFee(estimateFeeBulk[0].suggestedMaxFee) - maxTxFee = argentMaxFee(estimateFeeBulk[1].suggestedMaxFee) - } - } else { - const { overall_fee, suggestedMaxFee } = - await starknetAccount.estimateFee(transactions) + case "ESTIMATE_TRANSACTION_FEE": { + const selectedAccount = await wallet.getSelectedAccount() + const starknetAccount = await wallet.getSelectedStarknetAccount() + const transactions = msg.data - txFee = number.toHex(overall_fee) - maxTxFee = number.toHex(suggestedMaxFee) // Here, maxFee = estimatedFee * 1.5x + if (!selectedAccount) { + throw Error("no accounts") } + try { + let txFee = "0", + maxTxFee = "0", + accountDeploymentFee: string | undefined, + maxADFee: string | undefined + + if ( + selectedAccount.needsDeploy && + !(await isAccountDeployed( + selectedAccount, + starknetAccount.getClassAt, + )) + ) { + if ("estimateFeeBulk" in starknetAccount) { + const bulkTransactions: TransactionBulk = [ + { + type: "DEPLOY_ACCOUNT", + payload: await wallet.getAccountDeploymentPayload( + selectedAccount, + ), + }, + { + type: "INVOKE_FUNCTION", + payload: transactions, + }, + ] - const suggestedMaxFee = number.toHex( - stark.estimatedFeeToMaxFee(maxTxFee, 1), // This adds the 3x overhead. i.e: suggestedMaxFee = maxFee * 2x = estimatedFee * 3x - ) - addEstimatedFees({ - amount: txFee, - suggestedMaxFee, - accountDeploymentFee, - maxADFee, - transactions, - }) - return respond({ - type: "ESTIMATE_TRANSACTION_FEE_RES", - data: { + const estimateFeeBulk = await starknetAccount.estimateFeeBulk( + bulkTransactions, + ) + + accountDeploymentFee = number.toHex( + estimateFeeBulk[0].overall_fee, + ) + txFee = number.toHex(estimateFeeBulk[1].overall_fee) + + maxADFee = argentMaxFee(estimateFeeBulk[0].suggestedMaxFee) + maxTxFee = argentMaxFee(estimateFeeBulk[1].suggestedMaxFee) + } + } else { + const { overall_fee, suggestedMaxFee } = + await starknetAccount.estimateFee(transactions) + + txFee = number.toHex(overall_fee) + maxTxFee = number.toHex(suggestedMaxFee) // Here, maxFee = estimatedFee * 1.5x + } + + const suggestedMaxFee = number.toHex( + stark.estimatedFeeToMaxFee(maxTxFee, 1), // This adds the 3x overhead. i.e: suggestedMaxFee = maxFee * 2x = estimatedFee * 3x + ) + addEstimatedFees({ amount: txFee, suggestedMaxFee, accountDeploymentFee, maxADFee, - }, - }) - } catch (error) { - console.error(error) - return respond({ - type: "ESTIMATE_TRANSACTION_FEE_REJ", - data: { - error: - (error as any)?.message?.toString?.() ?? - (error as any)?.toString?.() ?? - "Unkown error", - }, - }) - } - } - - case "ESTIMATE_ACCOUNT_DEPLOYMENT_FEE": { - const providedAccount = msg.data - const account = providedAccount - ? await wallet.getAccount(providedAccount) - : await wallet.getSelectedAccount() - - if (!account) { - throw Error("no accounts") + transactions, + }) + return respond({ + type: "ESTIMATE_TRANSACTION_FEE_RES", + data: { + amount: txFee, + suggestedMaxFee, + accountDeploymentFee, + maxADFee, + }, + }) + } catch (error) { + console.error(error) + return respond({ + type: "ESTIMATE_TRANSACTION_FEE_REJ", + data: { + error: + (error as any)?.message?.toString?.() ?? + (error as any)?.toString?.() ?? + "Unkown error", + }, + }) + } } - try { - const { overall_fee, suggestedMaxFee } = - await wallet.getAccountDeploymentFee(account) + case "ESTIMATE_ACCOUNT_DEPLOYMENT_FEE": { + const providedAccount = msg.data + const account = providedAccount + ? await wallet.getAccount(providedAccount) + : await wallet.getSelectedAccount() - const maxADFee = number.toHex( - stark.estimatedFeeToMaxFee(suggestedMaxFee, 1), // This adds the 3x overhead. i.e: suggestedMaxFee = maxFee * 2x = estimatedFee * 3x - ) + if (!account) { + throw Error("no accounts") + } - return respond({ - type: "ESTIMATE_ACCOUNT_DEPLOYMENT_FEE_RES", - data: { - amount: number.toHex(overall_fee), - maxADFee, - }, - }) - } catch (error) { - console.error(error) - return respond({ - type: "ESTIMATE_ACCOUNT_DEPLOYMENT_FEE_REJ", - data: { - error: - (error as any)?.message?.toString?.() ?? - (error as any)?.toString?.() ?? - "Unkown error", - }, - }) + try { + const { overall_fee, suggestedMaxFee } = + await wallet.getAccountDeploymentFee(account) + + const maxADFee = number.toHex( + stark.estimatedFeeToMaxFee(suggestedMaxFee, 1), // This adds the 3x overhead. i.e: suggestedMaxFee = maxFee * 2x = estimatedFee * 3x + ) + + return respond({ + type: "ESTIMATE_ACCOUNT_DEPLOYMENT_FEE_RES", + data: { + amount: number.toHex(overall_fee), + maxADFee, + }, + }) + } catch (error) { + console.error(error) + return respond({ + type: "ESTIMATE_ACCOUNT_DEPLOYMENT_FEE_REJ", + data: { + error: + (error as any)?.message?.toString?.() ?? + (error as any)?.toString?.() ?? + "Unkown error", + }, + }) + } } - } - case "ESTIMATE_DECLARE_CONTRACT_FEE": { - const { classHash, contract, ...restData } = msg.data + case "ESTIMATE_DECLARE_CONTRACT_FEE": { + const { classHash, contract, ...restData } = msg.data - const selectedAccount = await wallet.getSelectedAccount() - const selectedStarknetAccount = - "address" in restData - ? await wallet.getStarknetAccount(restData) - : await wallet.getSelectedStarknetAccount() + const selectedAccount = await wallet.getSelectedAccount() + const selectedStarknetAccount = + "address" in restData + ? await wallet.getStarknetAccount(restData) + : await wallet.getSelectedStarknetAccount() - if (!selectedStarknetAccount) { - throw Error("no accounts") - } + if (!selectedStarknetAccount) { + throw Error("no accounts") + } - let txFee = "0", - maxTxFee = "0", - accountDeploymentFee: string | undefined, - maxADFee: string | undefined - - try { - if ( - selectedAccount?.needsDeploy && - !(await isAccountDeployed( - selectedAccount, - selectedStarknetAccount.getClassAt, - )) - ) { - if ("estimateFeeBulk" in selectedStarknetAccount) { - const bulkTransactions: TransactionBulk = [ - { - type: "DEPLOY_ACCOUNT", - payload: await wallet.getAccountDeploymentPayload( - selectedAccount, - ), - }, - { - type: "DECLARE", - payload: { - classHash, - contract, + let txFee = "0", + maxTxFee = "0", + accountDeploymentFee: string | undefined, + maxADFee: string | undefined + + try { + if ( + selectedAccount?.needsDeploy && + !(await isAccountDeployed( + selectedAccount, + selectedStarknetAccount.getClassAt, + )) + ) { + if ("estimateFeeBulk" in selectedStarknetAccount) { + const bulkTransactions: TransactionBulk = [ + { + type: "DEPLOY_ACCOUNT", + payload: await wallet.getAccountDeploymentPayload( + selectedAccount, + ), + }, + { + type: "DECLARE", + payload: { + classHash, + contract, + }, }, - }, - ] + ] - const estimateFeeBulk = - await selectedStarknetAccount.estimateFeeBulk(bulkTransactions) + const estimateFeeBulk = + await selectedStarknetAccount.estimateFeeBulk(bulkTransactions) - accountDeploymentFee = number.toHex(estimateFeeBulk[0].overall_fee) - txFee = number.toHex(estimateFeeBulk[1].overall_fee) + accountDeploymentFee = number.toHex( + estimateFeeBulk[0].overall_fee, + ) + txFee = number.toHex(estimateFeeBulk[1].overall_fee) - maxADFee = argentMaxFee(estimateFeeBulk[0].suggestedMaxFee) - maxTxFee = estimateFeeBulk[1].suggestedMaxFee - } - } else { - if ("estimateDeclareFee" in selectedStarknetAccount) { - const { overall_fee, suggestedMaxFee } = - await selectedStarknetAccount.estimateDeclareFee({ - classHash, - contract, - }) - txFee = number.toHex(overall_fee) - maxTxFee = number.toHex(suggestedMaxFee) + maxADFee = argentMaxFee(estimateFeeBulk[0].suggestedMaxFee) + maxTxFee = estimateFeeBulk[1].suggestedMaxFee + } } else { - throw Error("estimateDeclareFee not supported") + if ("estimateDeclareFee" in selectedStarknetAccount) { + const { overall_fee, suggestedMaxFee } = + await selectedStarknetAccount.estimateDeclareFee({ + classHash, + contract, + }) + txFee = number.toHex(overall_fee) + maxTxFee = number.toHex(suggestedMaxFee) + } else { + throw Error("estimateDeclareFee not supported") + } } + + const suggestedMaxFee = argentMaxFee(maxTxFee) // This adds the 3x overhead. i.e: suggestedMaxFee = maxFee * 2x = estimatedFee * 3x + + return respond({ + type: "ESTIMATE_DECLARE_CONTRACT_FEE_RES", + data: { + amount: txFee, + suggestedMaxFee, + accountDeploymentFee, + maxADFee, + }, + }) + } catch (error) { + console.error(error) + return respond({ + type: "ESTIMATE_DECLARE_CONTRACT_FEE_REJ", + data: { + error: + (error as any)?.message?.toString?.() ?? + (error as any)?.toString?.() ?? + "Unkown error", + }, + }) } + } - const suggestedMaxFee = argentMaxFee(maxTxFee) // This adds the 3x overhead. i.e: suggestedMaxFee = maxFee * 2x = estimatedFee * 3x + case "ESTIMATE_DEPLOY_CONTRACT_FEE": { + const { classHash, constructorCalldata, salt, unique } = msg.data - return respond({ - type: "ESTIMATE_DECLARE_CONTRACT_FEE_RES", - data: { - amount: txFee, - suggestedMaxFee, - accountDeploymentFee, - maxADFee, - }, - }) - } catch (error) { - console.error(error) - return respond({ - type: "ESTIMATE_DECLARE_CONTRACT_FEE_REJ", - data: { - error: - (error as any)?.message?.toString?.() ?? - (error as any)?.toString?.() ?? - "Unkown error", - }, - }) - } - } + const selectedAccount = await wallet.getSelectedAccount() + const selectedStarknetAccount = + await wallet.getSelectedStarknetAccount() - case "ESTIMATE_DEPLOY_CONTRACT_FEE": { - const { classHash, constructorCalldata, salt, unique } = msg.data + if (!selectedStarknetAccount || !selectedAccount) { + throw Error("no accounts") + } - const selectedAccount = await wallet.getSelectedAccount() - const selectedStarknetAccount = await wallet.getSelectedStarknetAccount() + let txFee = "0", + maxTxFee = "0", + accountDeploymentFee: string | undefined, + maxADFee: string | undefined - if (!selectedStarknetAccount || !selectedAccount) { - throw Error("no accounts") - } + try { + if ( + selectedAccount?.needsDeploy && + !(await isAccountDeployed( + selectedAccount, + selectedStarknetAccount.getClassAt, + )) + ) { + if ("estimateFeeBulk" in selectedStarknetAccount) { + const bulkTransactions: TransactionBulk = [ + { + type: "DEPLOY_ACCOUNT", + payload: await wallet.getAccountDeploymentPayload( + selectedAccount, + ), + }, + { + type: "DEPLOY", + payload: { + classHash, + salt, + unique, + constructorCalldata, + }, + }, + ] + + const estimateFeeBulk = + await selectedStarknetAccount.estimateFeeBulk(bulkTransactions) + + accountDeploymentFee = number.toHex( + estimateFeeBulk[0].overall_fee, + ) + txFee = number.toHex(estimateFeeBulk[1].overall_fee) - let txFee = "0", - maxTxFee = "0", - accountDeploymentFee: string | undefined, - maxADFee: string | undefined - - try { - if ( - selectedAccount?.needsDeploy && - !(await isAccountDeployed( - selectedAccount, - selectedStarknetAccount.getClassAt, - )) - ) { - if ("estimateFeeBulk" in selectedStarknetAccount) { - const bulkTransactions: TransactionBulk = [ - { - type: "DEPLOY_ACCOUNT", - payload: await wallet.getAccountDeploymentPayload( - selectedAccount, - ), - }, - { - type: "DEPLOY", - payload: { + maxADFee = argentMaxFee(estimateFeeBulk[0].suggestedMaxFee) + maxTxFee = estimateFeeBulk[1].suggestedMaxFee + } + } else { + if ("estimateDeployFee" in selectedStarknetAccount) { + const { overall_fee, suggestedMaxFee } = + await selectedStarknetAccount.estimateDeployFee({ classHash, salt, unique, constructorCalldata, - }, - }, - ] + }) + txFee = number.toHex(overall_fee) + maxTxFee = number.toHex(suggestedMaxFee) + } else { + throw Error("estimateDeployFee not supported") + } + } - const estimateFeeBulk = - await selectedStarknetAccount.estimateFeeBulk(bulkTransactions) + const suggestedMaxFee = argentMaxFee(maxTxFee) // This adds the 3x overhead. i.e: suggestedMaxFee = maxFee * 2x = estimatedFee * 3x + + return respond({ + type: "ESTIMATE_DEPLOY_CONTRACT_FEE_RES", + data: { + amount: txFee, + suggestedMaxFee, + accountDeploymentFee, + maxADFee, + }, + }) + } catch (error) { + console.log(error) + return respond({ + type: "ESTIMATE_DEPLOY_CONTRACT_FEE_REJ", + data: { + error: + (error as any)?.message?.toString() ?? + (error as any)?.toString() ?? + "Unkown error", + }, + }) + } + } - accountDeploymentFee = number.toHex(estimateFeeBulk[0].overall_fee) - txFee = number.toHex(estimateFeeBulk[1].overall_fee) + case "SIMULATE_TRANSACTION_INVOCATION": { + const transactions = Array.isArray(msg.data) ? msg.data : [msg.data] - maxADFee = argentMaxFee(estimateFeeBulk[0].suggestedMaxFee) - maxTxFee = estimateFeeBulk[1].suggestedMaxFee + try { + const selectedAccount = await wallet.getSelectedAccount() + const starknetAccount = + (await wallet.getSelectedStarknetAccount()) as Account // Old accounts are not supported + + if (!selectedAccount) { + throw Error("no accounts") } - } else { - if ("estimateDeployFee" in selectedStarknetAccount) { - const { overall_fee, suggestedMaxFee } = - await selectedStarknetAccount.estimateDeployFee({ - classHash, - salt, - unique, - constructorCalldata, - }) - txFee = number.toHex(overall_fee) - maxTxFee = number.toHex(suggestedMaxFee) - } else { - throw Error("estimateDeployFee not supported") + + const nonce = await starknetAccount.getNonce() + + const chainId = starknetAccount.chainId + + const version = number.toHex(hash.feeTransactionVersion) + + const signerDetails: InvocationsSignerDetails = { + walletAddress: starknetAccount.address, + nonce, + maxFee: 0, + version, + chainId, } - } - const suggestedMaxFee = argentMaxFee(maxTxFee) // This adds the 3x overhead. i.e: suggestedMaxFee = maxFee * 2x = estimatedFee * 3x + // TODO: Use this when Simulate Transaction allows multiple transaction types + // const signerDetailsWithZeroNonce = { + // ...signerDetails, + // nonce: 0, + // } + + // const accountDeployPayload = await wallet.getAccountDeploymentPayload( + // selectedAccount, + // ) + + // const accountDeployInvocation = + // await starknetAccount.buildAccountDeployPayload( + // accountDeployPayload, + // signerDetailsWithZeroNonce, + // ) + + const { contractAddress, calldata, signature } = + await starknetAccount.buildInvocation(transactions, signerDetails) + + const invocation = { + type: "INVOKE_FUNCTION" as const, + contract_address: contractAddress, + calldata, + signature, + nonce, + version, + } - return respond({ - type: "ESTIMATE_DEPLOY_CONTRACT_FEE_RES", - data: { - amount: txFee, - suggestedMaxFee, - accountDeploymentFee, - maxADFee, - }, - }) - } catch (error) { - console.log(error) - return respond({ - type: "ESTIMATE_DEPLOY_CONTRACT_FEE_REJ", - data: { - error: - (error as any)?.message?.toString() ?? - (error as any)?.toString() ?? - "Unkown error", - }, - }) + return respond({ + type: "SIMULATE_TRANSACTION_INVOCATION_RES", + data: { + invocation, + chainId, + }, + }) + } catch (error) { + console.log(error) + return respond({ + type: "SIMULATE_TRANSACTION_INVOCATION_REJ", + data: { + error: + (error as any)?.message?.toString() ?? + (error as any)?.toString() ?? + "Unkown error", + }, + }) + } } - } - case "SIMULATE_TRANSACTION_INVOCATION": { - const transactions = Array.isArray(msg.data) ? msg.data : [msg.data] - - try { + case "SIMULATE_TRANSACTION_FALLBACK": { const selectedAccount = await wallet.getSelectedAccount() const starknetAccount = (await wallet.getSelectedStarknetAccount()) as Account // Old accounts are not supported @@ -349,106 +426,37 @@ export const handleTransactionMessage: HandleMessage< throw Error("no accounts") } - const nonce = await getNonce(selectedAccount, wallet) - - const chainId = starknetAccount.chainId - - const version = number.toHex(hash.feeTransactionVersion) - - const signerDetails: InvocationsSignerDetails = { - walletAddress: starknetAccount.address, - nonce, - maxFee: 0, - version, - chainId, - } - - // TODO: Use this when Simulate Transaction allows multiple transaction types - // const signerDetailsWithZeroNonce = { - // ...signerDetails, - // nonce: 0, - // } - - // const accountDeployPayload = await wallet.getAccountDeploymentPayload( - // selectedAccount, - // ) - - // const accountDeployInvocation = - // await starknetAccount.buildAccountDeployPayload( - // accountDeployPayload, - // signerDetailsWithZeroNonce, - // ) - - const { contractAddress, calldata, signature } = - await starknetAccount.buildInvocation(transactions, signerDetails) - - const invocation = { - type: "INVOKE_FUNCTION" as const, - contract_address: contractAddress, - calldata, - signature, - nonce, - version, + const nonce = await starknetAccount.getNonce() + + try { + const simulated = await starknetAccount.simulateTransaction( + msg.data, + { + nonce, + }, + ) + + return respond({ + type: "SIMULATE_TRANSACTION_FALLBACK_RES", + data: simulated, + }) + } catch (error) { + return respond({ + type: "SIMULATE_TRANSACTION_FALLBACK_REJ", + data: { + error: + (error as any)?.message?.toString() ?? + (error as any)?.toString() ?? + "Unkown error", + }, + }) } - - return respond({ - type: "SIMULATE_TRANSACTION_INVOCATION_RES", - data: { - invocation, - chainId, - }, - }) - } catch (error) { - console.log(error) - return respond({ - type: "SIMULATE_TRANSACTION_INVOCATION_REJ", - data: { - error: - (error as any)?.message?.toString() ?? - (error as any)?.toString() ?? - "Unkown error", - }, - }) } - } - case "SIMULATE_TRANSACTION_FALLBACK": { - const selectedAccount = await wallet.getSelectedAccount() - const starknetAccount = - (await wallet.getSelectedStarknetAccount()) as Account // Old accounts are not supported - - if (!selectedAccount) { - throw Error("no accounts") - } - - const nonce = await starknetAccount.getNonce(selectedAccount) - - try { - const simulated = await starknetAccount.simulateTransaction(msg.data, { - nonce, - }) - - return respond({ - type: "SIMULATE_TRANSACTION_FALLBACK_RES", - data: simulated, - }) - } catch (error) { - return respond({ - type: "SIMULATE_TRANSACTION_FALLBACK_REJ", - data: { - error: - (error as any)?.message?.toString() ?? - (error as any)?.toString() ?? - "Unkown error", - }, - }) + case "TRANSACTION_FAILED": { + return await actionQueue.remove(msg.data.actionHash) } } - case "TRANSACTION_FAILED": { - return await actionQueue.remove(msg.data.actionHash) - } + throw new UnhandledMessage() } - - throw new UnhandledMessage() -} From c65a27d8c13d4006e8fa6a3f455a8d4d7f8514b6 Mon Sep 17 00:00:00 2001 From: Dhruv Kelawala Date: Tue, 21 Mar 2023 12:30:55 +0000 Subject: [PATCH 2/5] feat: add SimulationLoadingBanner --- .../SimulationLoadingBanner.tsx | 13 +++++++++++++ .../transaction/ApproveTransactionScreen/index.tsx | 10 ++++------ 2 files changed, 17 insertions(+), 6 deletions(-) create mode 100644 packages/extension/src/ui/features/actions/transaction/ApproveTransactionScreen/SimulationLoadingBanner.tsx diff --git a/packages/extension/src/ui/features/actions/transaction/ApproveTransactionScreen/SimulationLoadingBanner.tsx b/packages/extension/src/ui/features/actions/transaction/ApproveTransactionScreen/SimulationLoadingBanner.tsx new file mode 100644 index 000000000..e5179ff1d --- /dev/null +++ b/packages/extension/src/ui/features/actions/transaction/ApproveTransactionScreen/SimulationLoadingBanner.tsx @@ -0,0 +1,13 @@ +import { P4 } from "@argent/ui" +import { Center, Spinner, Text } from "@chakra-ui/react" + +export const SimulationLoadingBanner = () => { + return ( +
+ + + Simulating transaction... + +
+ ) +} diff --git a/packages/extension/src/ui/features/actions/transaction/ApproveTransactionScreen/index.tsx b/packages/extension/src/ui/features/actions/transaction/ApproveTransactionScreen/index.tsx index 5db03790f..5c44f2ad1 100644 --- a/packages/extension/src/ui/features/actions/transaction/ApproveTransactionScreen/index.tsx +++ b/packages/extension/src/ui/features/actions/transaction/ApproveTransactionScreen/index.tsx @@ -18,7 +18,6 @@ import { useIsMainnet } from "../../../networks/useNetworks" import { ConfirmPageProps } from "../../DeprecatedConfirmScreen" import { CombinedFeeEstimation } from "../../feeEstimation/CombinedFeeEstimation" import { FeeEstimation } from "../../feeEstimation/FeeEstimation" -import { LoadingScreen } from "../../LoadingScreen" import { useTransactionReview } from "../useTransactionReview" import { useAggregatedSimData } from "../useTransactionSimulatedData" import { useTransactionSimulation } from "../useTransactionSimulation" @@ -26,6 +25,7 @@ import { AccountNetworkInfo } from "./AccountNetworkInfo" import { BalanceChangeOverview } from "./BalanceChangeOverview" import { ConfirmScreen } from "./ConfirmScreen" import { DappHeader } from "./DappHeader" +import { SimulationLoadingBanner } from "./SimulationLoadingBanner" import { TransactionActions } from "./TransactionActions" import { TransactionBanner } from "./TransactionBanner" @@ -130,10 +130,6 @@ export const ApproveTransactionScreen: FC = ({ return } - if (isSimulationLoading) { - return - } - return ( = ({ /> )} - {hasBalanceChange && ( + {hasBalanceChange ? ( + ) : ( + isSimulationLoading && )} {showTransactionActions && ( From a56bc71b748c9c4d1f8867fb672463c2d1f7f2bc Mon Sep 17 00:00:00 2001 From: Dhruv Kelawala Date: Tue, 21 Mar 2023 12:44:48 +0000 Subject: [PATCH 3/5] feat: show Actions box by default --- .../ApproveTransactionScreen/index.tsx | 20 +------------------ 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/packages/extension/src/ui/features/actions/transaction/ApproveTransactionScreen/index.tsx b/packages/extension/src/ui/features/actions/transaction/ApproveTransactionScreen/index.tsx index 5c44f2ad1..73275dd3b 100644 --- a/packages/extension/src/ui/features/actions/transaction/ApproveTransactionScreen/index.tsx +++ b/packages/extension/src/ui/features/actions/transaction/ApproveTransactionScreen/index.tsx @@ -1,6 +1,4 @@ -import { P4 } from "@argent/ui" import { WarningIcon } from "@chakra-ui/icons" -import { Center } from "@chakra-ui/react" import { isArray, isEmpty } from "lodash-es" import { FC, useMemo, useState } from "react" import { Navigate } from "react-router-dom" @@ -51,8 +49,6 @@ export const ApproveTransactionScreen: FC = ({ networkId: selectedAccount?.networkId || "unknown", }) const [disableConfirm, setDisableConfirm] = useState(true) - const [txDetails, setTxDetails] = useState(false) - const isMainnet = useIsMainnet() const { data: transactionReview } = useTransactionReview({ @@ -113,8 +109,7 @@ export const ApproveTransactionScreen: FC = ({ transactionSimulation && (txnHasTransfers || txnHasApprovals) // Show actions if there is no balance change or if there is a balance change and the user has expanded the details - const showTransactionActions = - (!hasBalanceChange || (txDetails && hasBalanceChange)) && !isUdcAction + const showTransactionActions = !isUdcAction const verifiedDapp = VERIFIED_DAPP_ENABLED && isMainnet && transactionReview?.targetedDapp @@ -200,19 +195,6 @@ export const ApproveTransactionScreen: FC = ({ : undefined } /> - - {hasBalanceChange && ( -
- setTxDetails(!txDetails)} - > - {txDetails ? "Hide" : "View more"} details - -
- )}
) } From 1ec9cc35512b93804416b3a4f33d6844b1e4146b Mon Sep 17 00:00:00 2001 From: Dhruv Kelawala Date: Tue, 21 Mar 2023 13:06:00 +0000 Subject: [PATCH 4/5] fix: code formatting --- .../src/background/transactions/transactionMessaging.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/extension/src/background/transactions/transactionMessaging.ts b/packages/extension/src/background/transactions/transactionMessaging.ts index 333a43282..a805d5ebf 100644 --- a/packages/extension/src/background/transactions/transactionMessaging.ts +++ b/packages/extension/src/background/transactions/transactionMessaging.ts @@ -222,7 +222,7 @@ export const handleTransactionMessage: HandleMessage = } } - const suggestedMaxFee = argentMaxFee(maxTxFee) // This adds the 3x overhead. i.e: suggestedMaxFee = maxFee * 2x = estimatedFee * 3x + const suggestedMaxFee = argentMaxFee(maxTxFee) // This add the 3x overhead. i.e: suggestedMaxFee = maxFee * 2x = estimatedFee * 3x return respond({ type: "ESTIMATE_DECLARE_CONTRACT_FEE_RES", From 071d9088afafa8df5a7fe0d9b1c8b3ea6dca4fab Mon Sep 17 00:00:00 2001 From: Dhruv Kelawala Date: Tue, 21 Mar 2023 14:05:19 +0000 Subject: [PATCH 5/5] feat: add fade --- packages/extension/package.json | 1 + .../BalanceChangeOverview/index.tsx | 576 +++++++++--------- yarn.lock | 44 +- 3 files changed, 341 insertions(+), 280 deletions(-) diff --git a/packages/extension/package.json b/packages/extension/package.json index 15b85b79f..02a3aae02 100644 --- a/packages/extension/package.json +++ b/packages/extension/package.json @@ -99,6 +99,7 @@ "dexie": "^3.2.2", "dexie-react-hooks": "^1.1.1", "ethers": "^5.5.1", + "framer-motion": "^10.7.0", "jose": "^4.3.6", "lodash-es": "^4.17.21", "micro-starknet": "^0.1.1", diff --git a/packages/extension/src/ui/features/actions/transaction/ApproveTransactionScreen/BalanceChangeOverview/index.tsx b/packages/extension/src/ui/features/actions/transaction/ApproveTransactionScreen/BalanceChangeOverview/index.tsx index fd1b1d606..798d8d6de 100644 --- a/packages/extension/src/ui/features/actions/transaction/ApproveTransactionScreen/BalanceChangeOverview/index.tsx +++ b/packages/extension/src/ui/features/actions/transaction/ApproveTransactionScreen/BalanceChangeOverview/index.tsx @@ -11,6 +11,7 @@ import { Text, Tooltip, } from "@chakra-ui/react" +import { motion } from "framer-motion" import { isEmpty } from "lodash-es" import { FC, useMemo } from "react" @@ -65,297 +66,324 @@ export const BalanceChangeOverview: FC = ({ } return ( - - - - {transactionReviewWithType?.type === "transfer" ? ( - - Balance change - - ) : ( - <> + + + + + {transactionReviewWithType?.type === "transfer" ? ( - Estimated balance change + Balance change - - - - - - - )} - - - - - {aggregatedData.map( - ( - { amount, recipients, token, usdValue, approvals, safe }, - dataIndex, - ) => ( - - {({ isDisabled }) => ( - <> -

- {token.type === "erc20" ? ( - - - {token.image ? ( - - ) : ( - - )} - - {token.name === "Ether" ? "Ethereum" : token.name}{" "} - - {!safe && ( - - - - )} - - + + Estimated balance change + + + + + + + + )} + + + + + {aggregatedData.map( + ( + { amount, recipients, token, usdValue, approvals, safe }, + dataIndex, + ) => ( + + {({ isDisabled }) => ( + <> +

+ {token.type === "erc20" ? ( + - + {token.image ? ( + + ) : ( + + )} + + {token.name === "Ether" + ? "Ethereum" + : token.name}{" "} + + {!safe && ( + + + + )} + + - - {prettifyTokenAmount({ - amount: amount.toFixed(), - decimals: token.decimals, - symbol: - token.type === "erc20" - ? token.symbol - : "NFT", - showPlusSign: true, - })} - - + + {prettifyTokenAmount({ + amount: amount.toFixed(), + decimals: token.decimals, + symbol: + token.type === "erc20" + ? token.symbol + : "NFT", + showPlusSign: true, + })} + + - {/** 0 usdValue means we don't have any value */} - {isMainnet && !!usdValue && !usdValue.isZero() && ( - - {prettifyCurrencyValue( - usdValue.abs().toString(), + {/** 0 usdValue means we don't have any value */} + {isMainnet && + !!usdValue && + !usdValue.isZero() && ( + + {prettifyCurrencyValue( + usdValue.abs().toString(), + )} + )} - - )} - - - ) : ( - - )} -

- - {!isEmpty(approvals) && ( - <> - - - - - - Approved spending limit - - - - - - - +
+ ) : ( + + )} +

+ + {!isEmpty(approvals) && ( + <> + + + + + + Approved spending limit + + + + + + + + - {approvals.map((approval, approvalIndex) => ( - - ( + - - {formatTruncatedAddress(approval.spender)} - - - - + {formatTruncatedAddress(approval.spender)} + + + - {prettifyTokenAmount({ - amount: approval.amount.toFixed(), - ...approval.token, - unlimitedText: "All your", - })} - - - - ))} - - - )} - {!isEmpty(recipients) && ( - <> - - - - - Recipients - + + {prettifyTokenAmount({ + amount: approval.amount.toFixed(), + ...approval.token, + unlimitedText: "All your", + })} + + + + ))} + + )} + {!isEmpty(recipients) && ( + <> + + + + + Recipients + + - {recipients.map((recipient, recipientIndex) => ( - - ( + - - {formatTruncatedAddress(recipient.address)} - - - - - {prettifyTokenAmount({ - amount: recipient.amount.toFixed(), - ...token, - withSymbol: false, - })} - - - - ))} - - - )} - - - )} -
- ), - )} -
- {!allTransferSafe && ( - - - - - - - - Warning: Approved spending limit - - - You’re approving one or more addresses to spend more tokens - than you’re using in this transaction. These funds will not be - spent but you should not proceed if you don’t trust this app - + + {formatTruncatedAddress( + recipient.address, + )} + + + + + {prettifyTokenAmount({ + amount: recipient.amount.toFixed(), + ...token, + withSymbol: false, + })} + + + + ))} + + + )} + + + )} + + ), + )} + + {!allTransferSafe && ( + + + + + + + + Warning: Approved spending limit + + + You’re approving one or more addresses to spend more tokens + than you’re using in this transaction. These funds will not + be spent but you should not proceed if you don’t trust this + app + + -
-
- )} -
-
+
+ )} + + + ) } diff --git a/yarn.lock b/yarn.lock index 49696f441..934fd1ae0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -614,7 +614,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-jsx@^7.17.12": +"@babel/plugin-syntax-jsx@^7.17.12", "@babel/plugin-syntax-jsx@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz#a8feef63b010150abd97f1649ec296e849943ca0" integrity sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q== @@ -884,14 +884,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.20.2" -"@babel/plugin-transform-react-display-name@^7.16.0", "@babel/plugin-transform-react-display-name@^7.16.7": +"@babel/plugin-transform-react-display-name@^7.16.0", "@babel/plugin-transform-react-display-name@^7.16.7", "@babel/plugin-transform-react-display-name@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz#8b1125f919ef36ebdfff061d664e266c666b9415" integrity sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA== dependencies: "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-react-jsx-development@^7.16.7": +"@babel/plugin-transform-react-jsx-development@^7.16.7", "@babel/plugin-transform-react-jsx-development@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz#dbe5c972811e49c7405b630e4d0d2e1380c0ddc5" integrity sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA== @@ -912,7 +912,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.19.0" -"@babel/plugin-transform-react-jsx@7.17.12", "@babel/plugin-transform-react-jsx@^7.12.12", "@babel/plugin-transform-react-jsx@^7.17.12", "@babel/plugin-transform-react-jsx@^7.18.6": +"@babel/plugin-transform-react-jsx@^7.12.12", "@babel/plugin-transform-react-jsx@^7.17.12": version "7.17.12" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.17.12.tgz#2aa20022709cd6a3f40b45d60603d5f269586dba" integrity sha512-Lcaw8bxd1DKht3thfD4A12dqo1X16he1Lm8rIv8sTwjAYNInRS1qHa9aJoqvzpscItXvftKDCfaEQzwoVyXpEQ== @@ -923,7 +923,18 @@ "@babel/plugin-syntax-jsx" "^7.17.12" "@babel/types" "^7.17.12" -"@babel/plugin-transform-react-pure-annotations@^7.16.7": +"@babel/plugin-transform-react-jsx@^7.18.6": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.21.0.tgz#656b42c2fdea0a6d8762075d58ef9d4e3c4ab8a2" + integrity sha512-6OAWljMvQrZjR2DaNhVfRz6dkCAVV+ymcLUmaf8bccGOHn2v5rHJK3tTpij0BuhdYWP4LLaqj5lwcdlpAAPuvg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/plugin-syntax-jsx" "^7.18.6" + "@babel/types" "^7.21.0" + +"@babel/plugin-transform-react-pure-annotations@^7.16.7", "@babel/plugin-transform-react-pure-annotations@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.6.tgz#561af267f19f3e5d59291f9950fd7b9663d0d844" integrity sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ== @@ -1119,7 +1130,7 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/preset-react@7.17.12", "@babel/preset-react@^7.12.10", "@babel/preset-react@^7.12.5", "@babel/preset-react@^7.16.0", "@babel/preset-react@^7.18.6": +"@babel/preset-react@^7.12.10", "@babel/preset-react@^7.12.5", "@babel/preset-react@^7.16.0": version "7.17.12" resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.17.12.tgz#62adbd2d1870c0de3893095757ed5b00b492ab3d" integrity sha512-h5U+rwreXtZaRBEQhW1hOJLMq8XNJBQ/9oymXiCXTuT/0uOwpbT0gUt+sXeOqoXBgNuUKI7TaObVwoEyWkpFgA== @@ -1131,6 +1142,18 @@ "@babel/plugin-transform-react-jsx-development" "^7.16.7" "@babel/plugin-transform-react-pure-annotations" "^7.16.7" +"@babel/preset-react@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.18.6.tgz#979f76d6277048dc19094c217b507f3ad517dd2d" + integrity sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-validator-option" "^7.18.6" + "@babel/plugin-transform-react-display-name" "^7.18.6" + "@babel/plugin-transform-react-jsx" "^7.18.6" + "@babel/plugin-transform-react-jsx-development" "^7.18.6" + "@babel/plugin-transform-react-pure-annotations" "^7.18.6" + "@babel/preset-typescript@^7.12.7", "@babel/preset-typescript@^7.16.0", "@babel/preset-typescript@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz#ce64be3e63eddc44240c6358daefac17b3186399" @@ -12216,6 +12239,15 @@ fragment-cache@^0.2.1: dependencies: map-cache "^0.2.2" +framer-motion@^10.7.0: + version "10.7.0" + resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-10.7.0.tgz#3ad614a00751929c70cfc3f874763f273e84215f" + integrity sha512-7Puk11URM2slwOttzmOJTkkpnyqlXqWGToUAW5sDnryJmADvykYRFWFsexXflRKr3YRmmF5JBd2y9IIe5r9Lzw== + dependencies: + tslib "^2.4.0" + optionalDependencies: + "@emotion/is-prop-valid" "^0.8.2" + framer-motion@^9.0.3: version "9.0.7" resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-9.0.7.tgz#5fe5c1d43e01c458ed4838687901c6c520fe452c"