Merge pull request #936 from esteemapp/feature/delegate

Feature/delegate
This commit is contained in:
uğur erdal 2019-07-08 20:04:46 +03:00 committed by GitHub
commit 12a1414e79
6 changed files with 256 additions and 19 deletions

View File

@ -692,7 +692,7 @@ export const delegateVestingShares = (currentAccount, pin, data) => {
'delegate_vesting_shares', 'delegate_vesting_shares',
{ {
delegator: data.from, delegator: data.from,
delegatee: data.to, delegatee: data.destination,
vesting_shares: data.amount, vesting_shares: data.amount,
}, },
], ],

View File

@ -134,6 +134,8 @@ class TransferContainer extends Component {
break; break;
case 'delegate': case 'delegate':
func = delegateVestingShares; func = delegateVestingShares;
currentAccount = selectedAccount;
data.amount = `${amount.toFixed(6)} VESTS`;
break; break;
default: default:
break; break;

View File

@ -4,6 +4,7 @@ import TransferContainer from './container/transferContainer';
import TransferView from './screen/transferScreen'; import TransferView from './screen/transferScreen';
import PowerDownView from './screen/powerDownScreen'; import PowerDownView from './screen/powerDownScreen';
import DelegateView from './screen/delegateScreen';
const Transfer = ({ navigation }) => ( const Transfer = ({ navigation }) => (
<TransferContainer navigation={navigation}> <TransferContainer navigation={navigation}>
@ -44,7 +45,19 @@ const Transfer = ({ navigation }) => (
/> />
); );
case 'delegate': case 'delegate':
return null; return (
<DelegateView
accounts={accounts}
currentAccountName={currentAccountName}
selectedAccount={selectedAccount}
getAccountsWithUsername={getAccountsWithUsername}
balance={balance}
fetchBalance={fetchBalance}
transferToAccount={transferToAccount}
accountType={accountType}
handleOnModalClose={handleOnModalClose}
/>
);
case 'power_down': case 'power_down':
return ( return (
<PowerDownView <PowerDownView

View File

@ -0,0 +1,232 @@
import React, { Component, Fragment } from 'react';
import { View, Text, WebView } from 'react-native';
import { injectIntl } from 'react-intl';
import Slider from 'react-native-slider';
import get from 'lodash/get';
import ActionSheet from 'react-native-actionsheet';
// Constants
import AUTH_TYPE from '../../../constants/authType';
import { steemConnectOptions } from '../../../constants/steemConnectOptions';
// Components
import { BasicHeader } from '../../../components/basicHeader';
import { TransferFormItem } from '../../../components/transferFormItem';
import { DropdownButton } from '../../../components/dropdownButton';
import { TextInput } from '../../../components/textInput';
import { MainButton } from '../../../components/mainButton';
import { UserAvatar } from '../../../components/userAvatar';
import { Icon } from '../../../components/icon';
import { Modal } from '../../../components/modal';
import parseToken from '../../../utils/parseToken';
import { isEmptyDate } from '../../../utils/time';
// Styles
import styles from './transferStyles';
class DelegateScreen extends Component {
constructor(props) {
super(props);
this.state = {
amount: 0,
isTransfering: false,
from: props.currentAccountName,
destination: '',
steemConnectTransfer: false,
};
this.startActionSheet = React.createRef();
}
// Component Life Cycles
// Component Functions
_setState = (key, value) => {
const { getAccountsWithUsername, balance } = this.props;
if (key) {
switch (key) {
case 'destination':
getAccountsWithUsername(value).then(res => {
const isValid = res.includes(value);
this.setState({ isUsernameValid: isValid });
});
this.setState({ [key]: value });
break;
case 'amount':
if (parseFloat(Number(value)) <= parseFloat(balance)) {
this.setState({ [key]: value });
}
break;
default:
this.setState({ [key]: value });
break;
}
}
};
_handleTransferAction = () => {
const { transferToAccount, accountType } = this.props;
const { from, destination, amount } = this.state;
this.setState({ isTransfering: true });
if (accountType === AUTH_TYPE.STEEM_CONNECT) {
this.setState({ steemConnectTransfer: true });
} else {
transferToAccount(from, destination, amount, '');
}
};
_handleOnAmountChange = (state, amount) => {
let _amount = amount.toString();
if (_amount.includes(',')) {
_amount = amount.replace(',', '.');
}
this._setState(state, _amount);
};
_handleOnDropdownChange = value => {
const { fetchBalance } = this.props;
fetchBalance(value);
this.setState({ from: value, amount: 0 });
};
_renderDropdown = (accounts, currentAccountName) => (
<DropdownButton
dropdownButtonStyle={styles.dropdownButtonStyle}
rowTextStyle={styles.rowTextStyle}
style={styles.dropdown}
dropdownStyle={styles.dropdownStyle}
textStyle={styles.dropdownText}
options={accounts.map(item => item.username)}
defaultText={currentAccountName}
selectedOptionIndex={accounts.findIndex(item => item.username === currentAccountName)}
onSelect={(index, value) => this._handleOnDropdownChange(value)}
/>
);
_renderInput = (placeholder, state, keyboardType, isTextArea) => (
<TextInput
style={[isTextArea ? styles.textarea : styles.input]}
onChangeText={amount => this._handleOnAmountChange(state, amount)}
value={this.state[state]}
placeholder={placeholder}
placeholderTextColor="#c1c5c7"
autoCapitalize="none"
multiline={isTextArea}
numberOfLines={isTextArea ? 4 : 1}
keyboardType={keyboardType}
/>
);
_renderInformationText = text => <Text style={styles.amountText}>{text}</Text>;
render() {
const { intl, accounts, currentAccountName, selectedAccount, handleOnModalClose } = this.props;
const { amount, isTransfering, from, destination, steemConnectTransfer } = this.state;
let availableVestingShares = 0;
if (!isEmptyDate(get(selectedAccount, 'next_vesting_withdrawal'))) {
// powering down
availableVestingShares =
parseToken(get(selectedAccount, 'vesting_shares')) -
(Number(get(selectedAccount, 'to_withdraw')) - Number(get(selectedAccount, 'withdrawn'))) /
1e6 -
parseToken(get(selectedAccount, 'delegated_vesting_shares'));
} else {
// not powering down
availableVestingShares =
parseToken(get(selectedAccount, 'vesting_shares')) -
parseToken(get(selectedAccount, 'delegated_vesting_shares'));
}
const fixedAmount = `${amount.toFixed(6)} VESTS`;
const path = `sign/delegate-vesting-shares?delegator=${from}&delegatee=${destination}&vesting_shares=${encodeURIComponent(
fixedAmount,
)}`;
return (
<Fragment>
<BasicHeader title={intl.formatMessage({ id: 'transfer.delegate' })} />
<View style={styles.container}>
<View style={styles.topContent}>
<UserAvatar username={from} size="xl" style={styles.userAvatar} noAction />
<Icon style={styles.icon} name="arrow-forward" iconType="MaterialIcons" />
<UserAvatar username={destination} size="xl" style={styles.userAvatar} noAction />
</View>
<View style={styles.middleContent}>
<TransferFormItem
label={intl.formatMessage({ id: 'transfer.account' })}
rightComponent={() => this._renderDropdown(accounts, currentAccountName)}
/>
<TransferFormItem
label={intl.formatMessage({ id: 'transfer.to' })}
rightComponent={() =>
this._renderInput(
intl.formatMessage({ id: 'transfer.to_placeholder' }),
'destination',
'default',
)
}
/>
<TransferFormItem
label={intl.formatMessage({ id: 'transfer.amount' })}
rightComponent={() => this._renderInformationText(`${amount.toFixed(6)} VESTS`)}
/>
<Slider
style={styles.slider}
trackStyle={styles.track}
thumbStyle={styles.thumb}
minimumTrackTintColor="#357ce6"
thumbTintColor="#007ee5"
maximumValue={availableVestingShares}
value={amount}
onValueChange={value => {
this.setState({ amount: value });
}}
/>
<Text style={styles.informationText}>
{intl.formatMessage({ id: 'transfer.amount_information' })}
</Text>
</View>
<View style={styles.bottomContent}>
<MainButton
style={styles.button}
onPress={() => this.startActionSheet.current.show()}
isLoading={isTransfering}
>
<Text style={styles.buttonText}>{intl.formatMessage({ id: 'transfer.next' })}</Text>
</MainButton>
</View>
</View>
<ActionSheet
ref={this.startActionSheet}
options={[
intl.formatMessage({ id: 'alert.confirm' }),
intl.formatMessage({ id: 'alert.cancel' }),
]}
title={intl.formatMessage({ id: 'transfer.information' })}
cancelButtonIndex={1}
destructiveButtonIndex={0}
onPress={index => (index === 0 ? this._handleTransferAction() : null)}
/>
<Modal
isOpen={steemConnectTransfer}
isFullScreen
isCloseButton
handleOnModalClose={handleOnModalClose}
title={intl.formatMessage({ id: 'transfer.steemconnect_title' })}
>
<WebView source={{ uri: `${steemConnectOptions.base_url}${path}` }} />
</Modal>
</Fragment>
);
}
}
export default injectIntl(DelegateScreen);

View File

@ -1,12 +1,11 @@
import React, { Fragment, Component } from 'react'; import React, { Fragment, Component } from 'react';
import { Text, View, WebView, ScrollView, Alert } from 'react-native'; import { Text, View, ScrollView, Alert } from 'react-native';
import ActionSheet from 'react-native-actionsheet'; import ActionSheet from 'react-native-actionsheet';
import { injectIntl } from 'react-intl'; import { injectIntl } from 'react-intl';
import Slider from 'react-native-slider'; import Slider from 'react-native-slider';
import get from 'lodash/get'; import get from 'lodash/get';
import { getWithdrawRoutes } from '../../../providers/steem/dsteem'; import { getWithdrawRoutes } from '../../../providers/steem/dsteem';
import { steemConnectOptions } from '../../../constants/steemConnectOptions';
import AUTH_TYPE from '../../../constants/authType'; import AUTH_TYPE from '../../../constants/authType';
import { BasicHeader } from '../../../components/basicHeader'; import { BasicHeader } from '../../../components/basicHeader';
@ -75,13 +74,16 @@ class PowerDownView extends Component {
}; };
_handleTransferAction = () => { _handleTransferAction = () => {
const { transferToAccount, accountType } = this.props; const { transferToAccount, accountType, intl } = this.props;
const { from, destinationAccounts, amount } = this.state; const { from, destinationAccounts, amount } = this.state;
this.setState({ isTransfering: true }); this.setState({ isTransfering: true });
if (accountType === AUTH_TYPE.STEEM_CONNECT) { if (accountType === AUTH_TYPE.STEEM_CONNECT) {
this.setState({ steemConnectTransfer: true }); Alert.alert(
intl.formatMessage({ id: 'alert.warning' }),
intl.formatMessage({ id: 'transfer.sc_power_down_error' }),
);
} else { } else {
transferToAccount(from, destinationAccounts, amount, ''); transferToAccount(from, destinationAccounts, amount, '');
} }
@ -190,14 +192,12 @@ class PowerDownView extends Component {
accounts, accounts,
selectedAccount, selectedAccount,
intl, intl,
handleOnModalClose,
getAccountsWithUsername, getAccountsWithUsername,
transferType, transferType,
currentAccountName, currentAccountName,
steemPerMVests, steemPerMVests,
} = this.props; } = this.props;
const { amount, steemConnectTransfer, isTransfering, isOpenWithdrawAccount } = this.state; const { amount, isTransfering, isOpenWithdrawAccount } = this.state;
let path;
let poweringDownVests = 0; let poweringDownVests = 0;
let availableVestingShares = 0; let availableVestingShares = 0;
@ -358,15 +358,6 @@ class PowerDownView extends Component {
handleOnSubmit={this._handleOnSubmit} handleOnSubmit={this._handleOnSubmit}
/> />
</Modal> </Modal>
<Modal
isOpen={steemConnectTransfer}
isFullScreen
isCloseButton
handleOnModalClose={handleOnModalClose}
title={intl.formatMessage({ id: 'transfer.steemconnect_title' })}
>
<WebView source={{ uri: `${steemConnectOptions.base_url}${path}` }} />
</Modal>
</Fragment> </Fragment>
); );
} }

View File

@ -109,7 +109,6 @@ export default EStyleSheet.create({
elevation: 3, elevation: 3,
}, },
slider: { slider: {
flex: 1,
marginHorizontal: 30, marginHorizontal: 30,
}, },
formButton: { formButton: {