Skip to content

Commit

Permalink
Feature: WalletConnect support (#643)
Browse files Browse the repository at this point in the history
* working

* show session prompt

* support for multiple connectors

* persisting sessions and list

* update snapshots

* clean up

* clean-up

* Update WalletConnect.js
  • Loading branch information
Bruno Barbieri authored May 14, 2019
1 parent 83ce3f2 commit 02c2954
Show file tree
Hide file tree
Showing 25 changed files with 1,595 additions and 195 deletions.
4 changes: 4 additions & 0 deletions app/components/Nav/App/__snapshots__/index.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -160,11 +160,13 @@ exports[`App should render correctly 1`] = `
"childRouters": Object {
"AdvancedSettings": null,
"CompanySettings": null,
"ExperimentalSettings": null,
"GeneralSettings": null,
"RevealPrivateCredentialView": null,
"SecuritySettings": null,
"Settings": null,
"SyncWithExtensionView": null,
"WalletConnectSessionsView": null,
},
"getActionCreators": [Function],
"getActionForPathAndParams": [Function],
Expand Down Expand Up @@ -534,11 +536,13 @@ exports[`App should render correctly 1`] = `
"childRouters": Object {
"AdvancedSettings": null,
"CompanySettings": null,
"ExperimentalSettings": null,
"GeneralSettings": null,
"RevealPrivateCredentialView": null,
"SecuritySettings": null,
"Settings": null,
"SyncWithExtensionView": null,
"WalletConnectSessionsView": null,
},
"getActionCreators": [Function],
"getActionForPathAndParams": [Function],
Expand Down
4 changes: 4 additions & 0 deletions app/components/Nav/Main/__snapshots__/index.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,13 @@ exports[`Main should render correctly 1`] = `
"childRouters": Object {
"AdvancedSettings": null,
"CompanySettings": null,
"ExperimentalSettings": null,
"GeneralSettings": null,
"RevealPrivateCredentialView": null,
"SecuritySettings": null,
"Settings": null,
"SyncWithExtensionView": null,
"WalletConnectSessionsView": null,
},
"getActionCreators": [Function],
"getActionForPathAndParams": [Function],
Expand Down Expand Up @@ -428,11 +430,13 @@ exports[`Main should render correctly 1`] = `
"childRouters": Object {
"AdvancedSettings": null,
"CompanySettings": null,
"ExperimentalSettings": null,
"GeneralSettings": null,
"RevealPrivateCredentialView": null,
"SecuritySettings": null,
"Settings": null,
"SyncWithExtensionView": null,
"WalletConnectSessionsView": null,
},
"getActionCreators": [Function],
"getActionForPathAndParams": [Function],
Expand Down
210 changes: 198 additions & 12 deletions app/components/Nav/Main/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import GeneralSettings from '../../Views/GeneralSettings';
import AdvancedSettings from '../../Views/AdvancedSettings';
import AppInformation from '../../UI/AppInformation';
import SecuritySettings from '../../Views/SecuritySettings';
import ExperimentalSettings from '../../Views/ExperimentalSettings';
import Wallet from '../../Views/Wallet';
import TransactionsView from '../../Views/TransactionsView';
import SyncWithExtension from '../../Views/SyncWithExtension';
Expand All @@ -25,6 +26,7 @@ import Collectible from '../../Views/Collectible';
import CollectibleView from '../../Views/CollectibleView';
import Send from '../../Views/Send';
import RevealPrivateCredential from '../../Views/RevealPrivateCredential';
import WalletConnectSessions from '../../Views/WalletConnectSessions';
import QrScanner from '../../Views/QRScanner';
import LockScreen from '../../Views/LockScreen';
import ProtectYourAccount from '../../Views/ProtectYourAccount';
Expand All @@ -49,6 +51,13 @@ import { colors } from '../../../styles/common';
import LockManager from '../../../core/LockManager';
import OnboardingWizard from '../../UI/OnboardingWizard';
import FadeOutOverlay from '../../UI/FadeOutOverlay';
import { hexToBN, fromWei } from '../../../util/number';
import { setTransactionObject } from '../../../actions/transaction';
import PersonalSign from '../../UI/PersonalSign';
import TypedSign from '../../UI/TypedSign';
import Modal from 'react-native-modal';
import WalletConnect from '../../../core/WalletConnect';
import WalletConnectSessionApproval from '../../UI/WalletConnectSessionApproval';

const styles = StyleSheet.create({
flex: {
Expand All @@ -59,6 +68,10 @@ const styles = StyleSheet.create({
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
bottomModal: {
justifyContent: 'flex-end',
margin: 0
}
});

Expand Down Expand Up @@ -138,6 +151,9 @@ const MainNavigator = createStackNavigator(
SecuritySettings: {
screen: SecuritySettings
},
ExperimentalSettings: {
screen: ExperimentalSettings
},
CompanySettings: {
screen: AppInformation
},
Expand All @@ -146,6 +162,9 @@ const MainNavigator = createStackNavigator(
},
RevealPrivateCredentialView: {
screen: RevealPrivateCredential
},
WalletConnectSessionsView: {
screen: WalletConnectSessions
}
})
},
Expand Down Expand Up @@ -266,11 +285,24 @@ class Main extends Component {
/**
* Current onboarding wizard step
*/
wizardStep: PropTypes.number
wizardStep: PropTypes.number,
/**
* Action that sets a transaction
*/
setTransactionObject: PropTypes.func,
/**
* Object containing the information for the current transaction
*/
transaction: PropTypes.object
};

state = {
forceReload: false
forceReload: false,
signMessage: false,
signMessageParams: { data: '' },
signType: '',
walletConnectRequest: false,
walletConnectRequestInfo: {}
};

backgroundMode = false;
Expand All @@ -290,7 +322,6 @@ class Main extends Component {
TransactionsNotificationManager.init(this.props.navigation);
this.pollForIncomingTransactions();
AppState.addEventListener('change', this.handleAppStateChange);

this.lockManager = new LockManager(this.props.navigation, this.props.lockTime);

PushNotification.configure({
Expand All @@ -314,6 +345,55 @@ class Main extends Component {
}
}
});

Engine.context.TransactionController.hub.on('unapprovedTransaction', this.onUnapprovedTransaction);

Engine.context.PersonalMessageManager.hub.on('unapprovedMessage', messageParams => {
const { title: currentPageTitle, url: currentPageUrl } = messageParams.meta;
delete messageParams.meta;
this.setState({
signMessage: true,
signMessageParams: messageParams,
signType: 'personal',
currentPageTitle,
currentPageUrl
});
});

Engine.context.TypedMessageManager.hub.on('unapprovedMessage', messageParams => {
const { title: currentPageTitle, url: currentPageUrl } = messageParams.meta;
delete messageParams.meta;
this.setState({
signMessage: true,
signMessageParams: messageParams,
signType: 'typed',
currentPageTitle,
currentPageUrl
});
});

WalletConnect.hub.on('walletconnectSessionRequest', peerInfo => {
this.setState({ walletConnectRequest: true, walletConnectRequestInfo: peerInfo });
});
WalletConnect.init();
};

onUnapprovedTransaction = transactionMeta => {
if (this.props.transaction.value || this.props.transaction.to) {
return;
}
const {
transaction: { value, gas, gasPrice }
} = transactionMeta;
transactionMeta.transaction.value = hexToBN(value);
transactionMeta.transaction.readableValue = fromWei(transactionMeta.transaction.value);
transactionMeta.transaction.gas = hexToBN(gas);
transactionMeta.transaction.gasPrice = hexToBN(gasPrice);
this.props.setTransactionObject({
...{ symbol: 'ETH', type: 'ETHER_TRANSACTION', assetType: 'ETH', id: transactionMeta.id },
...transactionMeta.transaction
});
this.props.navigation.push('ApprovalView');
};

handleAppStateChange = appState => {
Expand Down Expand Up @@ -365,6 +445,9 @@ class Main extends Component {
componentWillUnmount() {
AppState.removeEventListener('change', this.handleAppStateChange);
this.lockManager.stopListening();
Engine.context.PersonalMessageManager.hub.removeAllListeners();
Engine.context.TypedMessageManager.hub.removeAllListeners();
Engine.context.TransactionController.hub.removeListener('unapprovedTransaction', this.onUnapprovedTransaction);
}

/**
Expand All @@ -375,24 +458,127 @@ class Main extends Component {
return wizardStep !== 5 && wizardStep > 0 && <OnboardingWizard navigation={this.props.navigation} />;
};

onSignAction = () => {
this.setState({ signMessage: false });
};

renderSigningModal = () => {
const { signMessage, signMessageParams, signType, currentPageTitle, currentPageUrl } = this.state;
return (
<Modal
isVisible={signMessage}
animationIn="slideInUp"
animationOut="slideOutDown"
style={styles.bottomModal}
backdropOpacity={0.7}
animationInTiming={600}
animationOutTiming={600}
onBackdropPress={this.onSignAction}
onSwipeComplete={this.onSignAction}
swipeDirection={'down'}
propagateSwipe
>
{signType === 'personal' && (
<PersonalSign
messageParams={signMessageParams}
onCancel={this.onSignAction}
onConfirm={this.onSignAction}
currentPageInformation={{ title: currentPageTitle, url: currentPageUrl }}
/>
)}
{signType === 'typed' && (
<TypedSign
messageParams={signMessageParams}
onCancel={this.onSignAction}
onConfirm={this.onSignAction}
currentPageInformation={{ title: currentPageTitle, url: currentPageUrl }}
/>
)}
</Modal>
);
};

onWalletConnectSessionApproval = () => {
const { peerId } = this.state.walletConnectRequestInfo;
this.setState({
walletConnectRequest: false,
walletConnectRequestInfo: {}
});
WalletConnect.hub.emit('walletconnectSessionRequest::approved', peerId);
};

onWalletConnectSessionRejected = () => {
const peerId = this.state.walletConnectRequestInfo.peerId;
this.setState({
walletConnectRequest: false,
walletConnectRequestInfo: {}
});
WalletConnect.hub.emit('walletconnectSessionRequest::rejected', peerId);
};

renderWalletConnectSessionRequestModal = () => {
const { walletConnectRequest, walletConnectRequestInfo } = this.state;

const meta = walletConnectRequestInfo.peerMeta || null;

return (
<Modal
isVisible={walletConnectRequest}
animationIn="slideInUp"
animationOut="slideOutDown"
style={styles.bottomModal}
backdropOpacity={0.7}
animationInTiming={300}
animationOutTiming={300}
onSwipeComplete={this.onWalletConnectSessionRejected}
swipeDirection={'down'}
>
<WalletConnectSessionApproval
onCancel={this.onWalletConnectSessionRejected}
onConfirm={this.onWalletConnectSessionApproval}
currentPageInformation={{
title: meta && meta.name,
url: meta && meta.url
}}
/>
</Modal>
);
};

render() {
const { forceReload } = this.state;

return (
<View style={styles.flex}>
{!forceReload ? <MainNavigator navigation={this.props.navigation} /> : this.renderLoader()}
{this.renderOnboardingWizard()}
<GlobalAlert />
<FlashMessage position="bottom" MessageComponent={TransactionNotification} animationDuration={150} />
<FadeOutOverlay />
</View>
<React.Fragment>
<View style={styles.flex}>
{!forceReload ? <MainNavigator navigation={this.props.navigation} /> : this.renderLoader()}
{this.renderOnboardingWizard()}
<GlobalAlert />
<FlashMessage
position="bottom"
MessageComponent={TransactionNotification}
animationDuration={150}
/>
<FadeOutOverlay />
</View>
{this.renderSigningModal()}
{this.renderWalletConnectSessionRequestModal()}
</React.Fragment>
);
}
}

const mapStateToProps = state => ({
lockTime: state.settings.lockTime,
wizardStep: state.wizard.step
wizardStep: state.wizard.step,
transaction: state.transaction
});

const mapDispatchToProps = dispatch => ({
setTransactionObject: asset => dispatch(setTransactionObject(asset))
});

export default connect(mapStateToProps)(Main);
export default connect(
mapStateToProps,
mapDispatchToProps
)(Main);
3 changes: 3 additions & 0 deletions app/components/UI/Navbar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import URL from 'url-parse';
import { strings } from '../../../../locales/i18n';
import AppConstants from '../../../core/AppConstants';
import TabCountIcon from '../../UI/Tabs/TabCountIcon';
import WalletConnect from '../../../core/WalletConnect';
const HOMEPAGE_URL = 'about:blank';

const styles = StyleSheet.create({
Expand Down Expand Up @@ -438,6 +439,8 @@ export function getWalletNavbarOptions(title, navigation) {
const onScanSuccess = data => {
if (data.target_address) {
navigation.navigate('SendView', { txMeta: data });
} else if (data.walletConnectURI) {
WalletConnect.newSession(data.walletConnectURI);
}
};

Expand Down
Loading

0 comments on commit 02c2954

Please sign in to comment.