Skip to content

Commit

Permalink
Merge branch 'feature/my-device-qr-screen'
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielLaanpere committed Oct 31, 2019
2 parents 4c8ab25 + b3a3c9c commit 1a98fb6
Show file tree
Hide file tree
Showing 22 changed files with 395 additions and 147 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
"redux-persist": "^6.0.0",
"redux-persist-expo-securestore": "^2.0.0",
"reselect": "^4.0.0",
"secp256k1": "^3.7.1",
"stream-browserify": "^1.0.0",
"string_decoder": "^0.10.31",
"timers-browserify": "^1.4.2",
Expand Down
5 changes: 5 additions & 0 deletions src/actions/device.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { actionTypes } from './../constants';

export const rotateDeviceTempKey = () => ({
type: actionTypes.DEVICE_TEMP_KEY_ROTATE,
});
30 changes: 29 additions & 1 deletion src/components/ChatListScreen/ActionsBar.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,30 @@
import React from 'react';
import Crypto from 'crypto';
import { connect } from 'react-redux';
import { createStructuredSelector } from 'reselect';
import { TouchableOpacity } from 'react-native';
import { View } from 'native-base';
import { withNavigation } from 'react-navigation';
import { selectDevicePubKey } from './../../selectors/device';
import { hubAddress, urlHost } from './../../lib/OCustom';
import AddContactIcon from './../../assets/images/icon-person-add.svg';
import ScanIcon from './../../assets/images/icon-scan.svg';
import QRIcon from './../../assets/images/icon-qr.svg';
import styles from './styles';


class ActionsBar extends React.Component {
constructor(props) {
super(props);
this._getPairingCode = this._getPairingCode.bind(this);
}

_getPairingCode() {
const pairingSecret = Crypto.randomBytes(9).toString('base64');
pairingCode = `${this.props.devicePubKey}@${hubAddress}#${pairingSecret}`;
return pairingCode;
}

render() {
return (
<View style={styles.actionsBar}>
Expand All @@ -17,7 +33,12 @@ class ActionsBar extends React.Component {
<AddContactIcon style={styles.icon} width={20} height={20} />
</TouchableOpacity>
*/}
<TouchableOpacity style={styles.iconButton} onPress={() => this.props.navigation.navigate('MyQR')}>
<TouchableOpacity
style={styles.iconButton}
onPress={() => this.props.navigation.navigate('MyQR', {
qrData: `${urlHost}${this._getPairingCode()}`,
})}
>
<QRIcon style={styles.icon} width={15} height={15} />
</TouchableOpacity>
<TouchableOpacity style={styles.iconButton} onPress={() => this.props.navigation.navigate('ContactScanner')}>
Expand All @@ -28,4 +49,11 @@ class ActionsBar extends React.Component {
}
}

const mapStateToProps = createStructuredSelector({
devicePubKey: selectDevicePubKey(),
});

const mapDispatchToProps = dispatch => ({});

ActionsBar = connect(mapStateToProps, mapDispatchToProps)(ActionsBar);
export default withNavigation(ActionsBar);
2 changes: 1 addition & 1 deletion src/components/PaymentScreen/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { colors } from '../../constants';
import { TouchableOpacity } from 'react-native-gesture-handler';
import { selectExchangeRates } from './../../selectors/exchangeRates';
import { sendPaymentStart } from './../../actions/wallet';
import { availableUnits, bytesToUnit, unitToBytes } from './../../lib/Wallet';
import { availableUnits, unitToBytes } from './../../lib/Wallet';


class PaymentScreen extends React.Component {
Expand Down
10 changes: 5 additions & 5 deletions src/components/SettingsScreen/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Container, View, Content, List, ListItem, Text, Left, Body, Right, Icon
import UserAvatar from 'react-native-user-avatar';
import makeBlockie from 'ethereum-blockies-base64';
import Header from './../Header';
import { selectInitialAddress } from './../../selectors/wallet';
import { selectWalletAddress } from './../../selectors/wallet';
import styles from './styles';


Expand All @@ -19,13 +19,13 @@ class SettingsScreen extends React.Component {
render() {
const {
navigation,
initialWalletAddress
walletAddress,
} = this.props;

return (
<Container style={styles.content}>
<View style={styles.userInfo}>
<UserAvatar size={64} name={initialWalletAddress} src={makeBlockie(initialWalletAddress)} />
<UserAvatar size={64} name={walletAddress} src={makeBlockie(walletAddress)} />
</View>
<Content>
<List style={styles.list}>
Expand All @@ -46,11 +46,11 @@ class SettingsScreen extends React.Component {
}

SettingsScreen.propTypes = {
initialWalletAddress: PropTypes.string,
walletAddress: PropTypes.string,
};

const mapStateToProps = createStructuredSelector({
initialWalletAddress: selectInitialAddress(),
walletAddress: selectWalletAddress(),
});

SettingsScreen = connect(mapStateToProps)(SettingsScreen);
Expand Down
6 changes: 3 additions & 3 deletions src/components/WalletScreen/ActionsBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { createStructuredSelector } from 'reselect';
import { TouchableOpacity } from 'react-native';
import { View } from 'native-base';
import { withNavigation } from 'react-navigation';
import { selectCurrentAddress } from './../../selectors/wallet';
import { selectWalletAddress } from './../../selectors/wallet';
import SendIcon from './../../assets/images/icon-send.svg';
import ScanIcon from './../../assets/images/icon-scan.svg';
import QRIcon from './../../assets/images/icon-qr.svg';
Expand All @@ -28,7 +28,7 @@ class ActionsBar extends React.Component {
<TouchableOpacity
style={styles.iconButton}
onPress={() => this.props.navigation.navigate('MyWalletQR', {
qrData: `obbychat:${this.props.currentAddress}`,
qrData: `obyte-tn:${this.props.walletAddress}`,
})}
>
<QRIcon
Expand All @@ -54,7 +54,7 @@ class ActionsBar extends React.Component {


const mapStateToProps = createStructuredSelector({
currentAddress: selectCurrentAddress(),
walletAddress: selectWalletAddress(),
});

const mapDispatchToProps = dispatch => ({});
Expand Down
2 changes: 0 additions & 2 deletions src/components/WalletScreen/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { Entypo } from '@expo/vector-icons';
import RNPickerSelect from 'react-native-picker-select';
import Moment from 'react-moment';
import NavigationService from './../../navigation/service';
import { selectAddresses } from './../../selectors/wallet';
import { selectWalletBalances } from './../../selectors/balances';
import { selectExchangeRates } from './../../selectors/exchangeRates';
import { selectTransactions } from './../../selectors/walletHistory';
Expand Down Expand Up @@ -121,7 +120,6 @@ class WalletScreen extends React.Component {

const mapStateToProps = createStructuredSelector({
walletBalance: selectWalletBalances(),
walletAddresses: selectAddresses(),
exchangeRates: selectExchangeRates(),
transactions: selectTransactions(),
});
Expand Down
3 changes: 2 additions & 1 deletion src/constants/actionTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ export const SETTINGS_RESET = 'SETTINGS_RESET';
export const PAYMENT_SEND_START = 'PAYMENT_SEND_START';
export const PAYMENT_SEND_SUCCESS = 'PAYMENT_SEND_SUCCESS';
export const PAYMENT_SEND_FAILED = 'PAYMENT_SEND_FAILED';
export const APP_TOAST_SET = 'APP_TOAST_SET';
export const APP_TOAST_SET = 'APP_TOAST_SET';
export const DEVICE_TEMP_KEY_ROTATE = 'DEVICE_TEMP_KEY_ROTATE';
80 changes: 80 additions & 0 deletions src/lib/OCustom.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import _ from 'lodash';
import Crypto from 'crypto';
import obyte from 'obyte';
import { common } from './../constants';


export const testnet = common.network === 'testnet';

export const hubAddress = common.network === 'testnet'
? 'obyte.org/bb-test'
: 'obyte.org/bb';

export const oClient = common.network === 'testnet'
? new obyte.Client('wss://obyte.org/bb-test', { testnet })
: new obyte.Client('wss://obyte.org/bb');

export const urlHost = common.network === 'testnet'
? 'obyte-tn:'
: 'obyte:';

export const getDeviceMessageHashToSign = (objDeviceMessage) => {
var objNakedDeviceMessage = _.clone(objDeviceMessage);
delete objNakedDeviceMessage.signature;
cleanNullsDeep(objNakedDeviceMessage); // device messages have free format and we can't guarantee absence of malicious fields
return Crypto.createHash('sha256').update(getSourceString(objNakedDeviceMessage), 'utf8').digest();
}

function getSourceString(obj) {
var arrComponents = [];
function extractComponents(variable) {
if (variable === null)
throw Error("null value in " + JSON.stringify(obj));
switch (typeof variable) {
case "string":
arrComponents.push("s", variable);
break;
case "number":
arrComponents.push("n", variable.toString());
break;
case "boolean":
arrComponents.push("b", variable.toString());
break;
case "object":
if (Array.isArray(variable)) {
if (variable.length === 0)
throw Error("empty array in " + JSON.stringify(obj));
arrComponents.push('[');
for (var i = 0; i < variable.length; i++)
extractComponents(variable[i]);
arrComponents.push(']');
}
else {
var keys = Object.keys(variable).sort();
if (keys.length === 0)
throw Error("empty object in " + JSON.stringify(obj));
keys.forEach(function (key) {
if (typeof variable[key] === "undefined")
throw Error("undefined at " + key + " of " + JSON.stringify(obj));
arrComponents.push(key);
extractComponents(variable[key]);
});
}
break;
default:
throw Error("getSourceString: unknown type=" + (typeof variable) + " of " + variable + ", object: " + JSON.stringify(obj));
}
}

extractComponents(obj);
return arrComponents.join("\x00");
}

export const cleanNullsDeep = (obj) => {
Object.keys(obj).forEach(function (key) {
if (obj[key] === null)
delete obj[key];
else if (typeof obj[key] === 'object')
cleanNullsDeep(obj[key]);
});
}
10 changes: 0 additions & 10 deletions src/lib/Wallet.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,3 @@
import { common } from './../constants';
import obyte from 'obyte';


export const testnet = common.network === 'testnet';

export const oClient = common.network === 'testnet'
? new obyte.Client('wss://obyte.org/bb-test', { testnet })
: new obyte.Client('wss://obyte.org/bb');

/**
* Converts bytes to other sizes
* @param {int} n - in bytes (B)
Expand Down
21 changes: 0 additions & 21 deletions src/reducers/app.js

This file was deleted.

38 changes: 38 additions & 0 deletions src/reducers/device.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { REHYDRATE } from 'redux-persist';
import Crypto from 'crypto';
import { actionTypes } from '../constants';


const initialState = {
deviceTempKeys: {
prevPrivKey: Crypto.randomBytes(32),
privKey: Crypto.randomBytes(32),
rotationTimestamp: Date.now(),
}
};

function reducer(state = initialState, action) {
switch (action.type) {
case REHYDRATE:
return {
...state,
...action.payload.app,
};

case actionTypes.DEVICE_TEMP_KEY_ROTATE:
return {
...state,
deviceTempKeys: {
privKey: Crypto.randomBytes(32),
privKey: action.payload.privKey,
prevPrivKey: state.deviceTempKeys.privKey,
rotationTimestamp: Date.now(),
}
};

default:
return state;
}
}

export default reducer;
10 changes: 2 additions & 8 deletions src/reducers/wallet.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,8 @@ import { actionTypes } from '../constants';


const initialState = {
password: null,
seedWords: null,
xPrivateKey: null,
address: null, // index of current address
addresses: [],
masterWif: null,
witnesses: [],
};

Expand All @@ -22,11 +19,8 @@ function reducer(state = initialState, action) {
case actionTypes.INITIAL_WALLET_CREATE_SUCCESS:
return {
...state,
password: action.payload.password,
seedWords: action.payload.seedWords,
address: 0,
addresses: [action.payload.address],
xPrivateKey: action.payload.xPrivateKey,
masterWif: action.payload.masterWif,
};

case actionTypes.WITNESSES_GET_SUCCESS:
Expand Down
Loading

0 comments on commit 1a98fb6

Please sign in to comment.