-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix payment channels request #946
Changes from all commits
63a0d94
f7392fc
0aee921
3b2ed44
a710408
e860101
226df95
9ed2cd9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,7 @@ import NetInfo from '@react-native-community/netinfo'; | |
import PropTypes from 'prop-types'; | ||
import { connect } from 'react-redux'; | ||
import { createStackNavigator, createBottomTabNavigator } from 'react-navigation'; | ||
import ENS from 'ethjs-ens'; | ||
import GlobalAlert from '../../UI/GlobalAlert'; | ||
import FlashMessage from 'react-native-flash-message'; | ||
import BackgroundTimer from 'react-native-background-timer'; | ||
|
@@ -60,7 +61,7 @@ import TransactionsNotificationManager from '../../../core/TransactionsNotificat | |
import Engine from '../../../core/Engine'; | ||
import AppConstants from '../../../core/AppConstants'; | ||
import PushNotification from 'react-native-push-notification'; | ||
import I18n from '../../../../locales/i18n'; | ||
import I18n, { strings } from '../../../../locales/i18n'; | ||
import { colors } from '../../../styles/common'; | ||
import LockManager from '../../../core/LockManager'; | ||
import FadeOutOverlay from '../../UI/FadeOutOverlay'; | ||
|
@@ -77,7 +78,9 @@ import PaymentChannelDeposit from '../../Views/PaymentChannel/PaymentChannelDepo | |
import PaymentChannelSend from '../../Views/PaymentChannel/PaymentChannelSend'; | ||
import Networks from '../../../util/networks'; | ||
import { CONNEXT_DEPOSIT } from '../../../util/transactions'; | ||
import { toChecksumAddress } from 'ethereumjs-util'; | ||
import { toChecksumAddress, isValidAddress } from 'ethereumjs-util'; | ||
import { isENS } from '../../../util/address'; | ||
import Logger from '../../../util/Logger'; | ||
|
||
const styles = StyleSheet.create({ | ||
flex: { | ||
|
@@ -469,13 +472,109 @@ class Main extends PureComponent { | |
|
||
initializePaymentChannels = () => { | ||
PaymentChannelsClient.init(this.props.selectedAddress); | ||
PaymentChannelsClient.hub.on('payment::request', request => { | ||
this.setState({ paymentChannelRequest: true, paymentChannelRequestInfo: request }); | ||
PaymentChannelsClient.hub.on('payment::request', async request => { | ||
const validRequest = { ...request }; | ||
// Validate amount | ||
if (isNaN(request.amount)) { | ||
Alert.alert( | ||
strings('payment_channel_request.title_error'), | ||
strings('payment_channel_request.amount_error_message') | ||
); | ||
return; | ||
} | ||
|
||
const isAddress = !request.to || request.to.substring(0, 2).toLowerCase() === '0x'; | ||
const isInvalidAddress = isAddress && !isValidAddress(request.to); | ||
|
||
// Validate address | ||
if (isInvalidAddress || (!isAddress && !isENS(request.to))) { | ||
Alert.alert( | ||
strings('payment_channel_request.title_error'), | ||
strings('payment_channel_request.address_error_message') | ||
); | ||
return; | ||
} | ||
|
||
// Check if ENS and resolve the address before sending | ||
if (isENS(request.to)) { | ||
this.setState( | ||
{ | ||
paymentChannelRequest: true, | ||
paymentChannelRequestInfo: null | ||
}, | ||
() => { | ||
InteractionManager.runAfterInteractions(async () => { | ||
const { | ||
state: { network }, | ||
provider | ||
} = Engine.context.NetworkController; | ||
const ensProvider = new ENS({ provider, network }); | ||
try { | ||
const resolvedAddress = await ensProvider.lookup(request.to.trim()); | ||
if (isValidAddress(resolvedAddress)) { | ||
validRequest.to = resolvedAddress; | ||
validRequest.ensName = request.to; | ||
this.setState({ | ||
paymentChannelRequest: true, | ||
paymentChannelRequestInfo: validRequest | ||
}); | ||
return; | ||
} | ||
} catch (e) { | ||
Logger.log('Error with payment request', request); | ||
} | ||
Alert.alert( | ||
strings('payment_channel_request.title_error'), | ||
strings('payment_channel_request.address_error_message') | ||
); | ||
this.setState({ | ||
paymentChannelRequest: false, | ||
paymentChannelRequestInfo: null | ||
}); | ||
}); | ||
} | ||
); | ||
} else { | ||
this.setState({ | ||
paymentChannelRequest: true, | ||
paymentChannelRequestInfo: validRequest | ||
}); | ||
} | ||
}); | ||
|
||
PaymentChannelsClient.hub.on('payment::complete', () => { | ||
// show the success screen | ||
this.setState({ paymentChannelRequestCompleted: true }); | ||
// hide the modal and reset state | ||
setTimeout(() => { | ||
setTimeout(() => { | ||
this.setState({ | ||
paymentChannelRequest: false, | ||
paymentChannelRequestLoading: false, | ||
paymentChannelRequestInfo: {} | ||
}); | ||
setTimeout(() => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. did you do this on purpose? no delay time and you're setting the state two times in this callback There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did it on purpose. The delay times are below (See here) The reason of it is that I need to give enough time the modal to close before changing the flag. |
||
this.setState({ | ||
paymentChannelRequestCompleted: false | ||
}); | ||
}); | ||
}, 1500); | ||
}, 800); | ||
}); | ||
|
||
PaymentChannelsClient.hub.on('payment::error', error => { | ||
if (error === 'INVALID_ENS_NAME') { | ||
Alert.alert( | ||
strings('payment_channel_request.title_error'), | ||
strings('payment_channel_request.address_error_message') | ||
); | ||
} else if (error.indexOf('insufficient_balance') !== -1) { | ||
Alert.alert( | ||
strings('payment_channel_request.error'), | ||
strings('payment_channel_request.balance_error_message') | ||
); | ||
} | ||
|
||
// hide the modal and reset state | ||
setTimeout(() => { | ||
setTimeout(() => { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
import React, { PureComponent } from 'react'; | ||
import { connect } from 'react-redux'; | ||
import PropTypes from 'prop-types'; | ||
import { Platform, Animated, StyleSheet, Text, View } from 'react-native'; | ||
import { ActivityIndicator, Platform, Animated, StyleSheet, Text, View } from 'react-native'; | ||
import Icon from 'react-native-vector-icons/FontAwesome'; | ||
import ActionView from '../ActionView'; | ||
import ElevatedView from 'react-native-elevated-view'; | ||
|
@@ -10,16 +10,23 @@ import { strings } from '../../../../locales/i18n'; | |
import { colors, fontStyles } from '../../../styles/common'; | ||
import DeviceSize from '../../../util/DeviceSize'; | ||
import WebsiteIcon from '../WebsiteIcon'; | ||
import { renderAccountName, renderShortAddress } from '../../../util/address'; | ||
import { renderAccountName } from '../../../util/address'; | ||
import EthereumAddress from '../EthereumAddress'; | ||
|
||
const styles = StyleSheet.create({ | ||
root: { | ||
backgroundColor: colors.white, | ||
borderTopLeftRadius: 10, | ||
borderTopRightRadius: 10, | ||
minHeight: Platform.OS === 'ios' ? '62%' : '80%', | ||
minHeight: Platform.OS === 'ios' ? '65%' : '80%', | ||
paddingBottom: DeviceSize.isIphoneX() ? 20 : 0 | ||
}, | ||
emptyContainer: { | ||
flex: 1, | ||
justifyContent: 'center', | ||
alignItems: 'center', | ||
backgroundColor: colors.white | ||
}, | ||
wrapper: { | ||
paddingHorizontal: 25 | ||
}, | ||
|
@@ -202,9 +209,31 @@ class PaymentChannelApproval extends PureComponent { | |
.toFixed(2) | ||
.toString(); | ||
|
||
renderAddressOrEns = (to, ensName) => { | ||
if (!to) return null; | ||
|
||
if (ensName) { | ||
return <Text style={styles.selectedAddress}>{ensName}</Text>; | ||
} | ||
|
||
return <EthereumAddress style={styles.selectedAddress} address={to} type={'short'} />; | ||
}; | ||
|
||
renderLoader = () => ( | ||
<View style={styles.root}> | ||
<View style={styles.emptyContainer}> | ||
<ActivityIndicator style={styles.loader} size="small" /> | ||
</View> | ||
</View> | ||
); | ||
|
||
render = () => { | ||
if (!this.props.info) { | ||
return this.renderLoader(); | ||
} | ||
|
||
const { | ||
info: { title, detail, to }, | ||
info: { title, detail, to, ensName }, | ||
onConfirm, | ||
onCancel, | ||
selectedAddress, | ||
|
@@ -278,17 +307,17 @@ class PaymentChannelApproval extends PureComponent { | |
{title} | ||
</Text> | ||
) : ( | ||
<Text style={styles.selectedAddress}>{renderShortAddress(to)}</Text> | ||
this.renderAddressOrEns(to, ensName) | ||
)} | ||
</View> | ||
</View> | ||
<Text style={styles.intro}>{strings('paymentRequest.is_requesting_you_to_pay')}</Text> | ||
<View style={styles.total}> | ||
<Text style={styles.totalPrice}> ${formattedAmount}</Text> | ||
<Text style={styles.totalPrice}>{formattedAmount} DAI</Text> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we have locale for this, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I really don't think there's a good reason to add DAI, ETH to locales since it doesn't have translation but if want to keep it consistent I'll do it. |
||
</View> | ||
{detail && ( | ||
<View style={styles.permissions}> | ||
<Text style={styles.permissionText} numberOfLines={1}> | ||
<Text style={styles.permissionText}> | ||
<Text style={styles.permission}> {detail}</Text> | ||
</Text> | ||
</View> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is strange, why two settimeouts? you're calling one settimeout inside the other directly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there are different timeouts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right. My bad. Fixed it here: #957