Skip to content

Commit

Permalink
Merge branch 'main' into refactor-revert-noBorder-ramp-box-param
Browse files Browse the repository at this point in the history
  • Loading branch information
digiwand committed Jan 16, 2025
2 parents 1dffc13 + ff19ced commit 171f2cf
Show file tree
Hide file tree
Showing 28 changed files with 867 additions and 69 deletions.
3 changes: 3 additions & 0 deletions .js.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ export SEGMENT_FLUSH_INTERVAL="1"
# example for flush when 1 event is queued
export SEGMENT_FLUSH_EVENT_LIMIT="1"

# URL of the decoding API used to provide additional data from signature requests
export DECODING_API_URL: 'https://signature-insights.api.cx.metamask.io/v1'

# URL of security alerts API used to validate dApp requests.
export SECURITY_ALERTS_API_URL="https://security-alerts.api.cx.metamask.io"

Expand Down
2 changes: 1 addition & 1 deletion app/components/Views/confirmations/Confirm/Confirm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Footer from '../components/Confirm/Footer';
import Info from '../components/Confirm/Info';
import SignatureBlockaidBanner from '../components/Confirm/SignatureBlockaidBanner';
import Title from '../components/Confirm/Title';
import useConfirmationRedesignEnabled from '../hooks/useConfirmationRedesignEnabled';
import { useConfirmationRedesignEnabled } from '../hooks/useConfirmationRedesignEnabled';
import styleSheet from './Confirm.styles';

const Confirm = () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from 'react';

import { useTypedSignSimulationEnabled } from '../../../../../hooks/useTypedSignSimulationEnabled';
import { isRecognizedPermit } from '../../../../../utils/signature';
import { useSignatureRequest } from '../../../../../hooks/useSignatureRequest';
import DecodedSimulation from './TypedSignDecoded';
import PermitSimulation from './TypedSignPermit';

const TypedSignV3V4Simulation: React.FC<object> = () => {
const signatureRequest = useSignatureRequest();
const isPermit = signatureRequest && isRecognizedPermit(signatureRequest);
const isSimulationSupported = useTypedSignSimulationEnabled();

if (!isSimulationSupported || !signatureRequest) {
return null;
}

const { decodingData, decodingLoading } = signatureRequest;
const hasDecodingData = !(
(!decodingLoading && decodingData === undefined) ||
decodingData?.error
);

if (!hasDecodingData && isPermit) {
return <PermitSimulation />;
}

return <DecodedSimulation />;
};

export default TypedSignV3V4Simulation;
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React from 'react';
import { StyleSheet, View } from 'react-native';

import { useStyles } from '../../../../../../../../../component-library/hooks';
import InfoRow from '../../../../../UI/InfoRow';
import InfoSection from '../../../../../UI/InfoRow/InfoSection';
import Loader from '../../../../../../../../../component-library/components-temp/Loader';

const styleSheet = () => StyleSheet.create({
base: {
display: 'flex',
justifyContent: 'space-between',
},
loaderContainer: {
display: 'flex',
justifyContent: 'center',
},
});

const StaticSimulation: React.FC<{
title: string;
titleTooltip: string;
description?: string;
simulationElements: React.ReactNode;
isLoading?: boolean;
isCollapsed?: boolean;
}> = ({
title,
titleTooltip,
description,
simulationElements,
isLoading,
isCollapsed = false,
}) => {
const { styles } = useStyles(styleSheet, {});

return(
<View style={isCollapsed ? styles.base : {}}>
<InfoSection>
<InfoRow label={title} tooltip={titleTooltip}>
{description}
</InfoRow>
{isLoading ? (
<View style={styles.loaderContainer}>
<Loader size={'small'} />
</View>
) : (
simulationElements
)}
</InfoSection>
</View>
);
};

export default StaticSimulation;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './Static';
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
import React from 'react';
import cloneDeep from 'lodash/cloneDeep';
import {
DecodingDataChangeType,
DecodingDataStateChanges,
SignatureRequest,
} from '@metamask/signature-controller';

import { strings } from '../../../../../../../../../../locales/i18n';
import { typedSignV4ConfirmationState } from '../../../../../../../../../util/test/confirm-data-helpers';
import renderWithProvider from '../../../../../../../../../util/test/renderWithProvider';
import TypedSignDecoded, { getStateChangeToolip, getStateChangeType, StateChangeType } from './TypedSignDecoded';

const stateChangesApprove = [
{
assetType: 'ERC20',
changeType: DecodingDataChangeType.Approve,
address: '0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad',
amount: '12345',
contractAddress: '0x6b175474e89094c44da98b954eedeac495271d0f',
},
];

const stateChangesListingERC1155: DecodingDataStateChanges = [
{
assetType: 'NATIVE',
changeType: DecodingDataChangeType.Receive,
address: '',
amount: '900000000000000000',
contractAddress: '',
},
{
assetType: 'ERC1155',
changeType: DecodingDataChangeType.Listing,
address: '',
amount: '',
contractAddress: '0xafd4896984CA60d2feF66136e57f958dCe9482d5',
tokenID: '77789',
},
];

const stateChangesNftListing: DecodingDataStateChanges = [
{
assetType: 'ERC721',
changeType: DecodingDataChangeType.Listing,
address: '',
amount: '',
contractAddress: '0x922dC160f2ab743312A6bB19DD5152C1D3Ecca33',
tokenID: '22222',
},
{
assetType: 'ERC20',
changeType: DecodingDataChangeType.Receive,
address: '',
amount: '950000000000000000',
contractAddress: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
},
];

const stateChangesNftBidding: DecodingDataStateChanges = [
{
assetType: 'ERC20',
changeType: DecodingDataChangeType.Bidding,
address: '',
amount: '',
contractAddress: '0x922dC160f2ab743312A6bB19DD5152C1D3Ecca33',
tokenID: '189',
},
{
assetType: 'ERC721',
changeType: DecodingDataChangeType.Receive,
address: '',
amount: '950000000000000000',
contractAddress: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
},
];

const mockState = (mockStateChanges: DecodingDataStateChanges, stubDecodingLoading: boolean = false) => {
const clonedMockState = cloneDeep(typedSignV4ConfirmationState);
const request = clonedMockState.engine.backgroundState.SignatureController.signatureRequests['fb2029e1-b0ab-11ef-9227-05a11087c334'] as SignatureRequest;
request.decodingLoading = stubDecodingLoading;
request.decodingData = {
stateChanges: mockStateChanges,
};

return clonedMockState;
};

describe('DecodedSimulation', () => {
it('renders for ERC20 approval', async () => {
const { getByText } = renderWithProvider(<TypedSignDecoded />, {
state: mockState(stateChangesApprove),
});

expect(await getByText('Estimated changes')).toBeDefined();
expect(await getByText('Spending cap')).toBeDefined();
expect(await getByText('12,345')).toBeDefined();
});

it('renders for ERC712 token', async () => {
const { getByText } = renderWithProvider(<TypedSignDecoded />, {
state: mockState(stateChangesNftListing),
});

expect(await getByText('Estimated changes')).toBeDefined();
expect(await getByText('Listing price')).toBeDefined();
expect(await getByText('You list')).toBeDefined();
expect(await getByText('#22222')).toBeDefined();
});

it('renders for ERC1155 token', async () => {
const { getByText } = renderWithProvider(<TypedSignDecoded />, {
state: mockState(stateChangesListingERC1155),
});

expect(await getByText('Estimated changes')).toBeDefined();
expect(await getByText('You receive')).toBeDefined();
expect(await getByText('You list')).toBeDefined();
expect(await getByText('#77789')).toBeDefined();
});

it('renders label only once if there are multiple state changes of same changeType', async () => {
const { getAllByText } = renderWithProvider(<TypedSignDecoded />, {
state: mockState([stateChangesApprove[0], stateChangesApprove[0], stateChangesApprove[0]]),
});

expect(await getAllByText('12,345')).toHaveLength(3);
expect(await getAllByText('Spending cap')).toHaveLength(1);
});

it('renders unavailable message if no state change is returned', async () => {
const { getByText } = renderWithProvider(<TypedSignDecoded />, {
state: mockState([]),
});

expect(await getByText('Estimated changes')).toBeDefined();
expect(await getByText('Unavailable')).toBeDefined();
});

describe('getStateChangeToolip', () => {
it('return correct tooltip when permit is for listing NFT', () => {
const tooltip = getStateChangeToolip(
StateChangeType.NFTListingReceive,
);
expect(tooltip).toBe(strings('confirm.simulation.decoded_tooltip_list_nft'));
});

it('return correct tooltip when permit is for bidding NFT', () => {
const tooltip = getStateChangeToolip(
StateChangeType.NFTBiddingReceive,
);
expect(tooltip).toBe(strings('confirm.simulation.decoded_tooltip_bid_nft'));
});
});

describe('getStateChangeType', () => {
it('return correct state change type for NFT listing receive', () => {
const stateChange = getStateChangeType(stateChangesNftListing, stateChangesNftListing[1]);
expect(stateChange).toBe(StateChangeType.NFTListingReceive);
});

it('return correct state change type for NFT bidding receive', () => {
const stateChange = getStateChangeType(stateChangesNftBidding, stateChangesNftBidding[1]);
expect(stateChange).toBe(StateChangeType.NFTBiddingReceive);
});
});
});
Loading

0 comments on commit 171f2cf

Please sign in to comment.