MessageDetails.tsx 5.99 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
26
27
28
29
30
31
32
33
34
35
36
37
import { NETWORK_LIST } from 'constants/networkSpecs';
import { FoundAccount } from 'types/identityTypes';
import {
	isEthereumNetworkParams,
	SubstrateNetworkParams,
	UnknownNetworkParams
} from 'types/networkSpecsTypes';
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';
38
39
40
import {
	navigateToSignedMessage,
	unlockSeedPhrase
41
42
43
44
45
46
} 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
47

48
49
50
51
52
53
54
55
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
56
57
		try {
			if (sender.isLegacy) {
58
				this.props.navigation.navigate('AccountUnlockAndSign', {
Hanwen Cheng's avatar
Hanwen Cheng committed
59
60
					next: 'SignedMessage'
				});
61
				return;
Hanwen Cheng's avatar
Hanwen Cheng committed
62
63
64
65
66
			}
			const senderIdentity = getIdentityFromSender(
				sender,
				accountsStore.state.identities
			);
67
68
69
70
71
72
			const seedPhrase = await unlockSeedPhrase(
				this.props.navigation,
				senderIdentity
			);
			await scannerStore.signDataWithSeedPhrase(
				seedPhrase,
Hanwen Cheng's avatar
Hanwen Cheng committed
73
74
75
76
77
78
79
80
				NETWORK_LIST[sender.networkKey].protocol
			);
			return navigateToSignedMessage(this.props.navigation);
		} catch (e) {
			scannerStore.setErrorMsg(e.message);
		}
	}

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

121
122
123
124
125
126
127
128
129
130
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
131

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

144
145
146
147
148
		const networkParams = NETWORK_LIST[sender.networkKey];
		const isEthereum = isEthereumNetworkParams(networkParams);
		const prefix = (networkParams as
			| SubstrateNetworkParams
			| UnknownNetworkParams)?.prefix;
149

150
151
152
153
		return (
			<ScrollView
				contentContainerStyle={styles.bodyContent}
				style={styles.body}
154
				testID={testIDs.MessageDetails.scrollScreen}
155
156
			>
				<Background />
Hanwen Cheng's avatar
Hanwen Cheng committed
157
158
159
				<Text style={styles.topTitle}>Sign Message</Text>
				<Text style={styles.title}>From Account</Text>
				<CompatibleCard account={sender} accountsStore={accountsStore} />
160
161
162
163
164
165
166
				{!isEthereum && prehash && prefix ? (
					<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}
						prefix={prefix}
					/>
				) : null}
Hanwen Cheng's avatar
Hanwen Cheng committed
167
				<MessageDetailsCard
168
					isHash={isHash ?? false}
Hanwen Cheng's avatar
Hanwen Cheng committed
169
170
171
					message={message}
					data={dataToSign}
				/>
172
				<Button
173
					buttonStyles={styles.signButton}
174
					testID={testIDs.MessageDetails.signButton}
175
					title="Sign Message"
176
					onPress={(): void => {
Hanwen Cheng's avatar
Hanwen Cheng committed
177
						isHash ? alertMultipart(onNext) : onNext();
178
179
180
181
182
					}}
				/>
			</ScrollView>
		);
	}
Alexey's avatar
Alexey committed
183
184
185
}

const styles = StyleSheet.create({
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
	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'
	},
213
214
215
216
	signButton: {
		height: 60,
		paddingHorizontal: 0
	},
217
	title: {
Hanwen Cheng's avatar
Hanwen Cheng committed
218
		...fontStyles.h2,
219
220
221
		paddingBottom: 20
	},
	topTitle: {
Hanwen Cheng's avatar
Hanwen Cheng committed
222
		...fontStyles.h1,
223
224
225
226
227
228
229
230
231
232
		paddingBottom: 20,
		textAlign: 'center'
	},
	transactionDetails: {
		backgroundColor: colors.card_bg,
		flex: 1
	},
	wrapper: {
		borderRadius: 5
	}
Alexey's avatar
Alexey committed
233
});