Skip to content
This repository has been archived by the owner on Nov 10, 2024. It is now read-only.

Feat/remove txhashes from snap state #56

Merged
merged 2 commits into from
Nov 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
216 changes: 94 additions & 122 deletions packages/site/src/components/Account.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { MetaMaskContext, MetamaskActions, useAcount } from '../hooks';
import styled from 'styled-components';
import { connectSnap, convertToEth, filterPendingRequests, getMMProvider, getSnap, handleCopyToClipboard, storeTxHash, trimAccount } from '../utils';
import { connectSnap, convertToEth, filterPendingRequests, getSnap, handleCopyToClipboard, trimAccount } from '../utils';
import { FaCloudDownloadAlt, FaRegLightbulb } from 'react-icons/fa';
import { InstallFlaskButton, ConnectSnapButton, SimpleButton } from './Buttons';
import { AccountActivity, AccountActivityType, SupportedChainIdMap, UserOperation } from '../types';
import { AccountActivity, SupportedChainIdMap, UserOperation } from '../types';
import { useContext, useState } from 'react';
import { KeyringAccount, KeyringRequest } from "@metamask/keyring-api";
import { BlockieAccountModal } from './Blockie-Icon';
Expand Down Expand Up @@ -226,7 +226,8 @@ export const AccountModalDropdown = ({
closeModal();
await selectKeyringSnapAccount(account);
await getSmartAccount(account.id);
await getAccountActivity(account.id);
// TODO: Add account activity
// await getAccountActivity(account.id);
}

const handleCreateAccount = async (event: any) => {
Expand Down Expand Up @@ -670,128 +671,99 @@ export const AccountActivityDisplay = () => {
const [state] = useContext(MetaMaskContext);

const renderAccountActivityItem = (item: AccountActivity) => {
switch (item.type) {
case AccountActivityType.SmartContract:
if (item.userOperationReceipt === null) {
return (
<>
<ActivityItem>
<p>Status:</p>
<p><ActivityPending>Pending</ActivityPending></p>
</ActivityItem>

<ActivityItem>
<p>UserOp hash:</p>
<FlexRowNoMargin>
<p>{trimAccount(item.userOpHash)}</p>
<ActivityCopy onClick={e => handleCopyToClipboard(e, item.userOpHash)}>
<FaCopy />
</ActivityCopy>
</FlexRowNoMargin>
</ActivityItem>
</>
)
} else {
const sender = item.userOperationReceipt.sender;
const receipt = item.userOperationReceipt.receipt;
if (item.userOperationReceipt === null) {
return (
<>
<ActivityItem>
<p>Status:</p>
<p><ActivityPending>Pending</ActivityPending></p>
</ActivityItem>

<ActivityItem>
<p>UserOp hash:</p>
<FlexRowNoMargin>
<p>{trimAccount(item.userOpHash)}</p>
<ActivityCopy onClick={e => handleCopyToClipboard(e, item.userOpHash)}>
<FaCopy />
</ActivityCopy>
</FlexRowNoMargin>
</ActivityItem>
</>
)
} else {
const sender = item.userOperationReceipt.sender;
const receipt = item.userOperationReceipt.receipt;

return (
<>
<ActivityItem>
<p>Status:</p>
<p>{item.userOperationReceipt.success? <ActivitySuccess>Confirmed</ActivitySuccess>: <ActivityFailed>Failed</ActivityFailed>}</p>
</ActivityItem>

{!item.userOperationReceipt.success && item.userOperationReceipt.reason && (
<ActivityItem>
<p>Revert:</p>
<p>{item.userOperationReceipt.reason}</p>
</ActivityItem>
)}

<ActivityItem>
<p>Sender:</p>
<FlexRowNoMargin>
<p>eth:{trimAccount(item.userOperationReceipt.sender)}</p>
<ActivityCopy onClick={e => handleCopyToClipboard(e, sender)}>
<FaCopy />
</ActivityCopy>
</FlexRowNoMargin>
</ActivityItem>

<ActivityItem>
<p>To:</p>
<FlexRowNoMargin>
<p>eth:{trimAccount(item.userOperationReceipt.receipt.to)}</p>
<ActivityCopy onClick={e => handleCopyToClipboard(e, receipt.to)}>
<FaCopy />
</ActivityCopy>
</FlexRowNoMargin>
</ActivityItem>

<ActivityItem>
<p>Nonce:</p>
<p>{BigNumber.from(item.userOperationReceipt.nonce).toNumber()}</p>
</ActivityItem>

<ActivityItem>
<p>Actual Gas Used(units):</p>
<p>{BigNumber.from(item.userOperationReceipt.actualGasUsed).toNumber()}</p>
</ActivityItem>

<ActivityItem>
<p>Actual Gas Cost:</p>
<p>{convertToEth(BigNumber.from(item.userOperationReceipt.actualGasCost).toString())} ETH</p>
</ActivityItem>

<ActivityItem>
<p>UserOp hash:</p>
<FlexRowNoMargin>
<p>{trimAccount(item.userOperationReceipt.userOpHash)}</p>
<ActivityCopy onClick={e => handleCopyToClipboard(e, item.userOpHash)}>
<FaCopy />
</ActivityCopy>
</FlexRowNoMargin>
</ActivityItem>

<ActivityItem>
<p>Transaction hash:</p>
<FlexRowNoMargin>
<p>{trimAccount(receipt.transactionHash)}</p>
<ActivityCopy onClick={e => handleCopyToClipboard(e, receipt.transactionHash)}>
<FaCopy />
</ActivityCopy>
</FlexRowNoMargin>
</ActivityItem>
</>
)
}
return (
<>
<ActivityItem>
<p>Status:</p>
<p>{item.userOperationReceipt.success? <ActivitySuccess>Confirmed</ActivitySuccess>: <ActivityFailed>Failed</ActivityFailed>}</p>
</ActivityItem>

case AccountActivityType.EOA:
const txHash = item.txHash ? item.txHash : '';
return (
<>
{!item.userOperationReceipt.success && item.userOperationReceipt.reason && (
<ActivityItem>
<p>Status:</p>
<p>{<ActivitySuccess>Confirmed</ActivitySuccess>}</p>
<p>Revert:</p>
<p>{item.userOperationReceipt.reason}</p>
</ActivityItem>

<ActivityItem>
<p>Transaction hash:</p>
<FlexRowNoMargin>
<p>{trimAccount(txHash)}</p>
<ActivityCopy onClick={e => handleCopyToClipboard(e, txHash)}>
<FaCopy />
</ActivityCopy>
</FlexRowNoMargin>
</ActivityItem>
</>
)
default:
return (
<>
</>
);
)}

<ActivityItem>
<p>Sender:</p>
<FlexRowNoMargin>
<p>eth:{trimAccount(item.userOperationReceipt.sender)}</p>
<ActivityCopy onClick={e => handleCopyToClipboard(e, sender)}>
<FaCopy />
</ActivityCopy>
</FlexRowNoMargin>
</ActivityItem>

<ActivityItem>
<p>To:</p>
<FlexRowNoMargin>
<p>eth:{trimAccount(item.userOperationReceipt.receipt.to)}</p>
<ActivityCopy onClick={e => handleCopyToClipboard(e, receipt.to)}>
<FaCopy />
</ActivityCopy>
</FlexRowNoMargin>
</ActivityItem>

<ActivityItem>
<p>Nonce:</p>
<p>{BigNumber.from(item.userOperationReceipt.nonce).toNumber()}</p>
</ActivityItem>

<ActivityItem>
<p>Actual Gas Used(units):</p>
<p>{BigNumber.from(item.userOperationReceipt.actualGasUsed).toNumber()}</p>
</ActivityItem>

<ActivityItem>
<p>Actual Gas Cost:</p>
<p>{convertToEth(BigNumber.from(item.userOperationReceipt.actualGasCost).toString())} ETH</p>
</ActivityItem>

<ActivityItem>
<p>UserOp hash:</p>
<FlexRowNoMargin>
<p>{trimAccount(item.userOperationReceipt.userOpHash)}</p>
<ActivityCopy onClick={e => handleCopyToClipboard(e, item.userOpHash)}>
<FaCopy />
</ActivityCopy>
</FlexRowNoMargin>
</ActivityItem>

<ActivityItem>
<p>Transaction hash:</p>
<FlexRowNoMargin>
<p>{trimAccount(receipt.transactionHash)}</p>
<ActivityCopy onClick={e => handleCopyToClipboard(e, receipt.transactionHash)}>
<FaCopy />
</ActivityCopy>
</FlexRowNoMargin>
</ActivityItem>
</>
)
}
}

Expand All @@ -802,7 +774,7 @@ export const AccountActivityDisplay = () => {
<ActivityItemContainer key={index}>
<ActivityItem>
<TextBold>Type:</TextBold>
<TextBold>{item.type === AccountActivityType.SmartContract ? 'Withdraw': 'Deposit'}</TextBold>
<TextBold>Withdraw</TextBold>
</ActivityItem>
{renderAccountActivityItem(item)}
</ActivityItemContainer>
Expand Down
2 changes: 1 addition & 1 deletion packages/site/src/components/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ const BlockExplorerLink = styled.a`
margin-top: auto;
margin-bottom: 0;
margin-right: 1rem;
color: black;
color: ${(props) => props.theme.colors.primary.default};

&:hover {
color: ${(props) => props.theme.colors.text.default};
Expand Down
27 changes: 13 additions & 14 deletions packages/site/src/components/Transaction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { AccountRequestDisplay } from './Account';
import { convertToEth, convertToWei, estimateGas, trimAccount } from '../utils/eth';
import { BlockieAccountModal } from './Blockie-Icon';
import { BigNumber, ethers } from 'ethers';
import { calcPreVerificationGas, estimatCreationGas, estimateUserOperationGas, getDummySignature, getMMProvider, getUserOpCallData, handleCopyToClipboard, notify, storeTxHash } from '../utils';
import { calcPreVerificationGas, estimatCreationGas, estimateUserOperationGas, getDummySignature, getMMProvider, getUserOpCallData, handleCopyToClipboard, notify } from '../utils';
import { EntryPoint__factory } from '@account-abstraction/contracts';
import { UserOperation } from '../types';
import { FaCopy } from "react-icons/fa";
Expand Down Expand Up @@ -107,6 +107,7 @@ enum Stage {
Loading = 'Loading',
Success = 'Success',
Failed = 'Failed',
UserConfirmation = 'User Confirmation',
}

export enum TransactionType {
Expand All @@ -129,8 +130,6 @@ export const EthereumTransactionModalComponent = ({
const {
sendRequestSync,
getSmartAccount,
getAccountActivity,
getKeyringSnapAccounts,
} = useAcount();

const handleDepositSubmit = async () => {
Expand All @@ -154,13 +153,12 @@ export const EthereumTransactionModalComponent = ({
);

// check the selected account is connected
console.log(state)
if (!state.isSelectedSnapKeyringAccountConnected) {
throw new Error('The selected account is not connected. Please connect the account using Settings page.')
}

// send transaction
const res = await getMMProvider().request({
const txHash = await getMMProvider().request({
method: 'eth_sendTransaction',
params: [
{
Expand All @@ -176,16 +174,11 @@ export const EthereumTransactionModalComponent = ({
}) as string

// show success message
await getSmartAccount(state.selectedSnapKeyringAccount.id);
await storeTxHash(
state.selectedSnapKeyringAccount.id,
res,
state.chainId,
);
setAmount('');
setSuccessMessage(`${amount} ETH successfully depoisted to entry point contract.`);
setStatus(Stage.Success);
// notify('Deposit Transaction sent (txHash)', 'View activity for details.', res)
notify('Transaction sent (txHash)', 'Check wallet activity for details.', txHash)
await getSmartAccount(state.selectedSnapKeyringAccount.id);
}

const handleWithdrawSubmit = async () => {
Expand Down Expand Up @@ -258,11 +251,11 @@ export const EthereumTransactionModalComponent = ({
try {
e.preventDefault();

setStatus(Stage.Loading);

if (transactionType === TransactionType.Deposit) {
setStatus(Stage.UserConfirmation);
await handleDepositSubmit();
} else if (transactionType === TransactionType.Withdraw) {
setStatus(Stage.Loading);
await handleWithdrawSubmit();
} else {
throw new Error('Invalid transaction type');
Expand Down Expand Up @@ -391,6 +384,12 @@ export const EthereumTransactionModalComponent = ({
<ClipLoader color="#8093ff" size={50} />
</SpinnerContainer>
);
case Stage.UserConfirmation:
return (
<SpinnerContainer>
<ClipLoader color="#8093ff" size={50} />
</SpinnerContainer>
);
case Stage.Failed:
return (
<Container>
Expand Down
Loading
Loading