MessageDetails.tsx 5.85 KB
Newer Older
Thibaut Sardan's avatar
Thibaut Sardan committed
1
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
Alexey's avatar
Alexey committed
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity.  If not, see <http://www.gnu.org/licenses/>.

17
import { GenericExtrinsicPayload } from '@polkadot/types';
18
import { isU8a, u8aToHex } from '@polkadot/util';
Alexey's avatar
Alexey committed
19
import React from 'react';
Hanwen Cheng's avatar
Hanwen Cheng committed
20
import { ScrollView, StyleSheet, Text } from 'react-native';
Alexey's avatar
Alexey committed
21
import { Subscribe } from 'unstated';
22

23
import testIDs from 'e2e/testIDs';
24
25
import { NETWORK_LIST } from 'constants/networkSpecs';
import { FoundAccount } from 'types/identityTypes';
26
import { isEthereumNetworkParams } from 'types/networkSpecsTypes';
27
28
29
30
31
32
33
import { NavigationProps } from 'types/props';
import colors from 'styles/colors';
import Background from 'components/Background';
import Button from 'components/Button';
import PayloadDetailsCard from 'components/PayloadDetailsCard';
import ScannerStore from 'stores/ScannerStore';
import AccountsStore from 'stores/AccountsStore';
34
35
36
import {
	navigateToSignedMessage,
	unlockSeedPhrase
37
38
39
40
41
42
} from 'utils/navigationHelpers';
import fontStyles from 'styles/fontStyles';
import MessageDetailsCard from 'components/MessageDetailsCard';
import { alertMultipart } from 'utils/alertUtils';
import CompatibleCard from 'components/CompatibleCard';
import { getIdentityFromSender } from 'utils/identitiesUtils';
Alexey's avatar
Alexey committed
43

44
45
46
47
48
49
50
51
export default class MessageDetails extends React.PureComponent<
	NavigationProps<{}>
> {
	async onSignMessage(
		scannerStore: ScannerStore,
		accountsStore: AccountsStore,
		sender: FoundAccount
	): Promise<void> {
Hanwen Cheng's avatar
Hanwen Cheng committed
52
53
		try {
			if (sender.isLegacy) {
54
				this.props.navigation.navigate('AccountUnlockAndSign', {
Hanwen Cheng's avatar
Hanwen Cheng committed
55
56
					next: 'SignedMessage'
				});
57
				return;
Hanwen Cheng's avatar
Hanwen Cheng committed
58
59
60
61
62
			}
			const senderIdentity = getIdentityFromSender(
				sender,
				accountsStore.state.identities
			);
63
64
65
66
67
68
			const seedPhrase = await unlockSeedPhrase(
				this.props.navigation,
				senderIdentity
			);
			await scannerStore.signDataWithSeedPhrase(
				seedPhrase,
Hanwen Cheng's avatar
Hanwen Cheng committed
69
70
71
72
73
74
75
76
				NETWORK_LIST[sender.networkKey].protocol
			);
			return navigateToSignedMessage(this.props.navigation);
		} catch (e) {
			scannerStore.setErrorMsg(e.message);
		}
	}

77
	render(): React.ReactElement {
78
		return (
Hanwen Cheng's avatar
Hanwen Cheng committed
79
			<Subscribe to={[ScannerStore, AccountsStore]}>
80
81
82
83
84
85
86
				{(
					scannerStore: ScannerStore,
					accountsStore: AccountsStore
				): React.ReactNode => {
					const dataToSign = scannerStore.getDataToSign()!;
					const message = scannerStore.getMessage()!;
					const sender = scannerStore.getSender()!;
87
88
89
90
91
					if (dataToSign) {
						return (
							<MessageDetailsView
								{...this.props}
								scannerStore={scannerStore}
Hanwen Cheng's avatar
Hanwen Cheng committed
92
93
								accountsStore={accountsStore}
								sender={sender}
94
95
								message={isU8a(message) ? u8aToHex(message) : message}
								dataToSign={
96
97
98
99
									//dataToSign could be U8A?
									isU8a(dataToSign)
										? u8aToHex(dataToSign)
										: dataToSign.toString()
100
								}
101
								prehash={scannerStore.getPrehashPayload()}
102
								isHash={scannerStore.getIsHash()}
103
								onNext={(): Promise<void> =>
Hanwen Cheng's avatar
Hanwen Cheng committed
104
105
									this.onSignMessage(scannerStore, accountsStore, sender)
								}
106
107
108
109
110
111
112
113
114
							/>
						);
					} else {
						return null;
					}
				}}
			</Subscribe>
		);
	}
Alexey's avatar
Alexey committed
115
116
}

117
118
119
120
121
122
123
124
125
126
interface Props extends NavigationProps<{}> {
	dataToSign: string;
	isHash?: boolean;
	message: string;
	onNext: () => void;
	prehash: GenericExtrinsicPayload | null;
	sender: FoundAccount;
	scannerStore: ScannerStore;
	accountsStore: AccountsStore;
}
Alexey's avatar
Alexey committed
127

128
129
export class MessageDetailsView extends React.PureComponent<Props> {
	render(): React.ReactElement {
Hanwen Cheng's avatar
Hanwen Cheng committed
130
131
132
133
134
135
136
137
138
		const {
			accountsStore,
			dataToSign,
			isHash,
			message,
			onNext,
			prehash,
			sender
		} = this.props;
139

140
141
		const networkParams = NETWORK_LIST[sender.networkKey];
		const isEthereum = isEthereumNetworkParams(networkParams);
142

143
144
145
146
		return (
			<ScrollView
				contentContainerStyle={styles.bodyContent}
				style={styles.body}
147
				testID={testIDs.MessageDetails.scrollScreen}
148
149
			>
				<Background />
Hanwen Cheng's avatar
Hanwen Cheng committed
150
151
152
				<Text style={styles.topTitle}>Sign Message</Text>
				<Text style={styles.title}>From Account</Text>
				<CompatibleCard account={sender} accountsStore={accountsStore} />
153
				{!isEthereum && prehash ? (
154
155
156
					<PayloadDetailsCard
						description="You are about to confirm sending the following extrinsic. We will sign the hash of the payload as it is oversized."
						payload={prehash}
157
						networkKey={sender.networkKey}
158
159
					/>
				) : null}
Hanwen Cheng's avatar
Hanwen Cheng committed
160
				<MessageDetailsCard
161
					isHash={isHash ?? false}
Hanwen Cheng's avatar
Hanwen Cheng committed
162
163
164
					message={message}
					data={dataToSign}
				/>
165
				<Button
166
					buttonStyles={styles.signButton}
167
					testID={testIDs.MessageDetails.signButton}
168
					title="Sign Message"
169
					onPress={(): void => {
Hanwen Cheng's avatar
Hanwen Cheng committed
170
						isHash ? alertMultipart(onNext) : onNext();
171
172
173
174
175
					}}
				/>
			</ScrollView>
		);
	}
Alexey's avatar
Alexey committed
176
177
178
}

const styles = StyleSheet.create({
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
	actionButtonContainer: {
		flex: 1
	},
	actionsContainer: {
		flex: 1,
		flexDirection: 'row'
	},
	address: {
		flex: 1
	},
	body: {
		backgroundColor: colors.bg,
		flex: 1,
		flexDirection: 'column',
		overflow: 'hidden',
		padding: 20
	},
	bodyContent: {
		paddingBottom: 40
	},
	changePinText: {
		color: 'green',
		textAlign: 'left'
	},
	deleteText: {
		textAlign: 'right'
	},
206
207
208
209
	signButton: {
		height: 60,
		paddingHorizontal: 0
	},
210
	title: {
Hanwen Cheng's avatar
Hanwen Cheng committed
211
		...fontStyles.h2,
212
213
214
		paddingBottom: 20
	},
	topTitle: {
Hanwen Cheng's avatar
Hanwen Cheng committed
215
		...fontStyles.h1,
216
217
218
219
220
221
222
223
224
225
		paddingBottom: 20,
		textAlign: 'center'
	},
	transactionDetails: {
		backgroundColor: colors.card_bg,
		flex: 1
	},
	wrapper: {
		borderRadius: 5
	}
Alexey's avatar
Alexey committed
226
});