Commit cbfbd328 authored by Hanwen Cheng's avatar Hanwen Cheng Committed by Thibaut Sardan
Browse files

QR Code Scanner Fixes (#332)

* fix: create enable scanner state

* fix: add warnnings when address detected

* fix: remove unhandled promise rejection warning

* fix: remove useless code

* fix: changes according to review
parent bfb5bc03
Pipeline #50258 failed with stage
in 15 seconds
......@@ -23,10 +23,10 @@ import { RNCamera } from 'react-native-camera';
import { Subscribe } from 'unstated';
import colors from '../colors';
import fonts from "../fonts";
import fonts from '../fonts';
import AccountsStore from '../stores/AccountsStore';
import ScannerStore from '../stores/ScannerStore';
import { isJsonString, rawDataToU8A } from '../util/decoders';
import {isAddressString, isJsonString, rawDataToU8A} from '../util/decoders';
export default class Scanner extends React.PureComponent {
static navigationOptions = {
......@@ -34,6 +34,24 @@ export default class Scanner extends React.PureComponent {
headerBackTitle: 'Scanner'
};
constructor(props) {
super(props);
this.state = { enableScan: true };
}
showErrorMessage(scannerStore, title, message) {
this.setState({ enableScan: false });
Alert.alert(title, message, [
{
text: 'Try again',
onPress: () => {
scannerStore.cleanup();
this.setState({ enableScan: true });
}
}
]);
}
render() {
return (
<Subscribe to={[ScannerStore, AccountsStore]}>
......@@ -43,27 +61,26 @@ export default class Scanner extends React.PureComponent {
navigation={this.props.navigation}
scannerStore={scannerStore}
onBarCodeRead={async txRequestData => {
if (scannerStore.isBusy()) {
if (scannerStore.isBusy() || !this.state.enableScan) {
return;
}
if (isJsonString(txRequestData.data)) { // Ethereum Legacy
if(isAddressString(txRequestData.data)){
return this.showErrorMessage(scannerStore, text.ADDRESS_ERROR_TITLE, text.ADDRESS_ERROR_MESSAGE);
} else if (isJsonString(txRequestData.data)) {
// Ethereum Legacy
await scannerStore.setUnsigned(txRequestData.data);
} else {
try {
const strippedData = rawDataToU8A(txRequestData.rawData);
await scannerStore.setParsedData(strippedData, accountsStore);
await scannerStore.setParsedData(
strippedData,
accountsStore
);
} catch (e) {
Alert.alert('Unable to parse transaction', e.message, [
{
text: 'Try again',
onPress: () => {
scannerStore.cleanup();
}
}
]);
return this.showErrorMessage(scannerStore, text.PARSE_ERROR_TITLE, e.message);
}
}
}
if (await scannerStore.setData(accountsStore)) {
if (scannerStore.getType() === 'transaction') {
......@@ -143,6 +160,12 @@ export class QrScannerView extends React.PureComponent {
}
}
const text = {
ADDRESS_ERROR_TITLE: 'Address detected',
ADDRESS_ERROR_MESSAGE: 'Please create a transaction using a software such as MyCrypto or Fether so that Parity Signer can sign it.',
PARSE_ERROR_TITLE: 'Unable to parse transaction'
};
const styles = StyleSheet.create({
inactive: {
backgroundColor: colors.bg,
......@@ -207,6 +230,6 @@ const styles = StyleSheet.create({
color: colors.bg_text,
fontSize: 14,
fontFamily: fonts.bold,
paddingBottom: 20,
paddingBottom: 20
}
});
......@@ -80,7 +80,7 @@ export default class ScannerStore extends Container<ScannerState> {
async setParsedData(strippedData, accountsStore) {
const parsedData = await constructDataFromBytes(strippedData);
if (parsedData.isMultipart) {
this.setPartData(parseData.frame, parsedData.frameCount, parseData.partData, accountsStore);
return;
......@@ -100,7 +100,7 @@ export default class ScannerStore extends Container<ScannerState> {
// we havne't filled all the frames yet
if (Object.keys(this.state.multipartData.length) < frameCount) {
const nextDataState = this.state.multipartData;
nextDataState[frame] = partData;
this.setState({
......@@ -268,7 +268,7 @@ export default class ScannerStore extends Container<ScannerState> {
cleanup() {
this.setState(defaultState);
}
getIsOversized() {
return this.state.isOversized;
}
......@@ -308,4 +308,4 @@ export default class ScannerStore extends Container<ScannerState> {
getErrorMsg() {
return this.state.scanErrorMsg;
}
}
\ No newline at end of file
}
......@@ -17,7 +17,12 @@
// @flow
import { GenericExtrinsicPayload } from '@polkadot/types';
import { hexStripPrefix, hexToU8a, u8aToHex, u8aToString } from '@polkadot/util';
import {
hexStripPrefix,
hexToU8a,
u8aToHex,
u8aToString
} from '@polkadot/util';
import { encodeAddress } from '@polkadot/util-crypto';
import { blake2s, keccak } from './native';
......@@ -88,7 +93,7 @@ export function rawDataToU8A(rawData) {
export async function constructDataFromBytes(bytes) {
const frameInfo = hexStripPrefix(u8aToHex(bytes.slice(0, 5)));
const isMultipart = !!(parseInt(frameInfo.substr(0, 2), 16));
const isMultipart = !!parseInt(frameInfo.substr(0, 2), 16);
const frameCount = parseInt(frameInfo.substr(2, 4), 16);
const currentFrame = parseInt(frameInfo.substr(6, 4), 16);
const uosAfterFrames = hexStripPrefix(u8aToHex(bytes.slice(5)));
......@@ -116,7 +121,12 @@ export async function constructDataFromBytes(bytes) {
// decode payload appropriately via UOS
switch (zerothByte) {
case '45': // Ethereum UOS payload
action = firstByte === '00' || firstByte === '01' ? 'signData' : firstByte === '01' ? 'signTransaction' : null;
action =
firstByte === '00' || firstByte === '01'
? 'signData'
: firstByte === '01'
? 'signTransaction'
: null;
address = uosAfterFrames.substr(4, 44);
data['action'] = action;
......@@ -142,12 +152,14 @@ export async function constructDataFromBytes(bytes) {
data['data']['crypto'] = crypto;
data['data']['account'] = ss58Encoded;
switch(secondByte) {
switch (secondByte) {
case '00':
data['action'] = 'signTransaction';
data['oversized'] = isOversized;
data['isHash'] = isOversized;
data['data']['data'] = isOversized ? await blake2s(u8aToHex(rawPayload)) : new GenericExtrinsicPayload(rawPayload, { version: 3 });
data['data']['data'] = isOversized
? await blake2s(u8aToHex(rawPayload))
: new GenericExtrinsicPayload(rawPayload, { version: 3 });
break;
case '01':
data['action'] = 'signTransaction';
......@@ -159,13 +171,17 @@ export async function constructDataFromBytes(bytes) {
data['action'] = 'signTransaction';
data['oversized'] = isOversized;
data['isHash'] = isOversized;
data['data']['data'] = isOversized ? await blake2s(u8aToHex(rawPayload)) : new GenericExtrinsicPayload(rawPayload, { version: 3 });
data['data']['data'] = isOversized
? await blake2s(u8aToHex(rawPayload))
: new GenericExtrinsicPayload(rawPayload, { version: 3 });
break;
case '03': // Cold Signer should attempt to decode message to utf8
data['action'] = 'signData';
data['oversized'] = isOversized;
data['isHash'] = isOversized;
data['data']['data'] = isOversized ? await blake2s(u8aToHex(rawPayload)) : u8aToString(rawPayload);
data['data']['data'] = isOversized
? await blake2s(u8aToHex(rawPayload))
: u8aToString(rawPayload);
break;
default:
break;
......@@ -188,29 +204,35 @@ export function decodeToString(message: Uint8Array): string {
}
export function asciiToHex(message: string): string {
var result = [];
for (let i = 0; i < message.length; i++) {
var hex = Number(message.charCodeAt(i)).toString(16);
result.push(hex);
let result = [];
for (let i = 0; i < message.length; i++) {
const hex = Number(message.charCodeAt(i)).toString(16);
result.push(hex);
}
return result.join('');
return result.join('');
}
export function hexToAscii(hexBytes: Uint8Array): string {
var hex = hexBytes.toString();
var str = '';
for (var n = 0; n < hex.length; n += 2) {
str += String.fromCharCode(parseInt(hex.substr(n, 2), 16));
}
const hex = hexBytes.toString();
let str = '';
for (let n = 0; n < hex.length; n += 2) {
str += String.fromCharCode(parseInt(hex.substr(n, 2), 16));
}
return str;
return str;
}
export function isJsonString(str) {
try {
JSON.parse(str);
JSON.parse(str);
} catch (e) {
return false;
return false;
}
return true;
}
\ No newline at end of file
}
export function isAddressString(str) {
return str.substr(0, 2) === '0x' ||
str.substr(0, 9) === 'ethereum:' ||
str.substr(0, 10) === 'substrate:'
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment