mirror of
https://github.com/ecency/ecency-mobile.git
synced 2024-11-24 00:46:27 +03:00
Merge pull request #2764 from ecency/feat/GU-2746/recurrent-transfer
feat: 2746 add recurrent transfer feature for hive
This commit is contained in:
commit
6e7d13d66f
@ -20,7 +20,7 @@ PODS:
|
||||
- boost (1.76.0)
|
||||
- BugsnagReactNative (7.19.0):
|
||||
- React-Core
|
||||
- BVLinearGradient (2.6.2):
|
||||
- BVLinearGradient (2.8.3):
|
||||
- React-Core
|
||||
- CocoaAsyncSocket (7.6.5)
|
||||
- DoubleConversion (1.1.6)
|
||||
@ -998,7 +998,7 @@ SPEC CHECKSUMS:
|
||||
AppCenterReactNativeShared: f395caeabde0dc3a11609dbcb737d0f14cd40e79
|
||||
boost: a7c83b31436843459a1961bfd74b96033dc77234
|
||||
BugsnagReactNative: fa312f53a83ca21c0afdfeaec98a9c5eeb8fc4ed
|
||||
BVLinearGradient: 34a999fda29036898a09c6a6b728b0b4189e1a44
|
||||
BVLinearGradient: 880f91a7854faff2df62518f0281afb1c60d49a3
|
||||
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
|
||||
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
|
||||
FBLazyVector: a6454570f573a0f6f1d397e5a95c13e8e45d1700
|
||||
@ -1112,4 +1112,4 @@ SPEC CHECKSUMS:
|
||||
|
||||
PODFILE CHECKSUM: 6b212d63236c21489948e9b73b59fcff2feeeb08
|
||||
|
||||
COCOAPODS: 1.11.3
|
||||
COCOAPODS: 1.13.0
|
||||
|
@ -126,7 +126,7 @@
|
||||
"react-native-iphone-x-helper": "Norcy/react-native-iphone-x-helper",
|
||||
"react-native-keyboard-aware-scroll-view": "^0.9.1",
|
||||
"react-native-level-fs": "^3.0.0",
|
||||
"react-native-linear-gradient": "^2.4.2",
|
||||
"react-native-linear-gradient": "^2.8.3",
|
||||
"react-native-media-controls": "^2.3.0",
|
||||
"react-native-modal": "13.0.1",
|
||||
"react-native-modal-dropdown": "^1.0.2",
|
||||
@ -220,11 +220,6 @@
|
||||
"git add"
|
||||
]
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "lint-staged"
|
||||
}
|
||||
},
|
||||
"jest": {
|
||||
"preset": "react-native"
|
||||
},
|
||||
|
@ -15,3 +15,8 @@ const reactotron = Reactotron.setAsyncStorageHandler(AsyncStorage) // AsyncStora
|
||||
.connect(); // let's connect!
|
||||
|
||||
export default reactotron;
|
||||
|
||||
export const log = (...rest) => {
|
||||
Reactotron.log(...rest);
|
||||
console.log(...rest);
|
||||
};
|
||||
|
@ -78,7 +78,7 @@ const DropdownButtonView = ({
|
||||
}}
|
||||
style={[!style ? styles.button : style]}
|
||||
textStyle={[textStyle || styles.buttonText]}
|
||||
dropdownStyle={[styles.dropdown, dropdownStyle, { height: 32 * (options.length + 1.5) }]}
|
||||
dropdownStyle={[styles.dropdown, dropdownStyle, { height: 32 * (options.length + 0.8) }]}
|
||||
dropdownTextStyle={[dropdownTextStyle || styles.dropdownText]}
|
||||
dropdownTextHighlightStyle={styles.dropdownTextHighlight}
|
||||
options={options}
|
||||
|
@ -107,7 +107,7 @@ class SettingsItemView extends PureComponent {
|
||||
|
||||
return (
|
||||
<View style={styles.wrapper}>
|
||||
<Text style={[styles.text, titleStyle]}>{title}</Text>
|
||||
{!!title && <Text style={[styles.text, titleStyle]}>{title}</Text>}
|
||||
{this._renderItem()}
|
||||
</View>
|
||||
);
|
||||
|
@ -19,7 +19,7 @@ export const calculateTimeLeftForPostCheck = (firstPost: any) => {
|
||||
|
||||
// filter posts that are not present in top 5 posts currently in list.
|
||||
export const filterLatestPosts = (fetchedPosts: any[], cachedPosts: any[]) => {
|
||||
console.log('Comparing: ', fetchedPosts, cachedPosts);
|
||||
// console.log('Comparing: ', fetchedPosts, cachedPosts);
|
||||
|
||||
const latestPosts = [];
|
||||
fetchedPosts.forEach((post) => {
|
||||
|
@ -31,6 +31,7 @@ export interface TransferAccountSelectorProps {
|
||||
memo: string;
|
||||
setMemo: (value: string) => void;
|
||||
spkMarkets: Market[];
|
||||
getRecurrentTransferOfUser: (username: string) => string;
|
||||
}
|
||||
|
||||
const TransferAccountSelector = ({
|
||||
@ -50,6 +51,7 @@ const TransferAccountSelector = ({
|
||||
memo,
|
||||
setMemo,
|
||||
spkMarkets,
|
||||
getRecurrentTransferOfUser,
|
||||
}: TransferAccountSelectorProps) => {
|
||||
const intl = useIntl();
|
||||
const destinationRef = useRef('');
|
||||
@ -91,10 +93,16 @@ const TransferAccountSelector = ({
|
||||
return;
|
||||
}
|
||||
const isValid = res.includes(username);
|
||||
|
||||
|
||||
if (isValid) {
|
||||
getRecurrentTransferOfUser(username);
|
||||
}
|
||||
|
||||
setIsUsernameValid(isValid);
|
||||
});
|
||||
}, 300),
|
||||
[],
|
||||
[getRecurrentTransferOfUser],
|
||||
);
|
||||
|
||||
const _handleOnChange = (state: string, val: string) => {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { Text, TouchableOpacity, View } from 'react-native';
|
||||
import TextInput from '../textInput';
|
||||
@ -7,6 +7,8 @@ import { TransferFormItem } from '../transferFormItem';
|
||||
// Styles
|
||||
import styles from './transferAmountInputSectionStyles';
|
||||
import TransferTypes from '../../constants/transferTypes';
|
||||
import DropdownButton from '../dropdownButton';
|
||||
import { dateToFormatted } from '../../utils/time';
|
||||
|
||||
export interface TransferAmountInputSectionProps {
|
||||
balance: number;
|
||||
@ -18,6 +20,10 @@ export interface TransferAmountInputSectionProps {
|
||||
setMemo: (value: string) => void;
|
||||
amount: string;
|
||||
setAmount: (value: string) => void;
|
||||
recurrence: string;
|
||||
setRecurrence: (value: string) => void;
|
||||
executions: string;
|
||||
setExecutions: (value: string) => void;
|
||||
hsTransfer: boolean;
|
||||
transferType: string;
|
||||
selectedAccount: any;
|
||||
@ -26,6 +32,24 @@ export interface TransferAmountInputSectionProps {
|
||||
disableMinimum?: boolean;
|
||||
}
|
||||
|
||||
export const RECURRENCE_TYPES = [
|
||||
{
|
||||
key: 'daily',
|
||||
hours: 24,
|
||||
intlId: 'leaderboard.daily',
|
||||
},
|
||||
{
|
||||
key: 'weekly',
|
||||
hours: 168,
|
||||
intlId: 'leaderboard.weekly',
|
||||
},
|
||||
{
|
||||
key: 'monthly',
|
||||
hours: 731,
|
||||
intlId: 'leaderboard.monthly',
|
||||
},
|
||||
];
|
||||
|
||||
const TransferAmountInputSection = ({
|
||||
balance,
|
||||
getAccountsWithUsername,
|
||||
@ -36,39 +60,50 @@ const TransferAmountInputSection = ({
|
||||
setMemo,
|
||||
amount,
|
||||
setAmount,
|
||||
transferType,
|
||||
fundType,
|
||||
disableMinimum,
|
||||
transferType,
|
||||
recurrence,
|
||||
setRecurrence,
|
||||
executions,
|
||||
setExecutions,
|
||||
startDate,
|
||||
onNext,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const dpRef = useRef();
|
||||
|
||||
const _handleOnChange = (state, val) => {
|
||||
let _amount = val.toString();
|
||||
if (_amount.includes(',')) {
|
||||
_amount = val.replace(',', '.');
|
||||
let newValue = val.toString();
|
||||
|
||||
if (newValue.includes(',')) {
|
||||
newValue = val.replace(',', '.');
|
||||
}
|
||||
if (state === 'amount') {
|
||||
if (parseFloat(Number(_amount)) <= parseFloat(balance)) {
|
||||
setAmount(_amount);
|
||||
if (parseFloat(Number(newValue)) <= parseFloat(balance)) {
|
||||
setAmount(newValue);
|
||||
}
|
||||
}
|
||||
if (state === 'destination') {
|
||||
} else if (state === 'destination') {
|
||||
getAccountsWithUsername(val).then((res) => {
|
||||
console.log(res);
|
||||
|
||||
const isValid = res.includes(val);
|
||||
|
||||
setIsUsernameValid(isValid);
|
||||
});
|
||||
setDestination(_amount);
|
||||
}
|
||||
if (state === 'memo') {
|
||||
setMemo(_amount);
|
||||
setDestination(newValue);
|
||||
} else if (state === 'memo') {
|
||||
setMemo(newValue);
|
||||
} else if (state === 'executions') {
|
||||
setExecutions(val);
|
||||
}
|
||||
};
|
||||
|
||||
const _renderInput = (placeholder, state, keyboardType, isTextArea) => (
|
||||
<TextInput
|
||||
style={[isTextArea ? styles.textarea : styles.input]}
|
||||
onChangeText={(amount) => _handleOnChange(state, amount)}
|
||||
onChangeText={(newVal) => _handleOnChange(state, newVal)}
|
||||
value={
|
||||
state === 'destination'
|
||||
? destination
|
||||
@ -76,6 +111,8 @@ const TransferAmountInputSection = ({
|
||||
? amount
|
||||
: state === 'memo'
|
||||
? memo
|
||||
: state === 'executions'
|
||||
? executions
|
||||
: ''
|
||||
}
|
||||
placeholder={placeholder}
|
||||
@ -87,8 +124,38 @@ const TransferAmountInputSection = ({
|
||||
/>
|
||||
);
|
||||
|
||||
const [recurrenceIndex, setRecurrenceIndex] = useState(
|
||||
RECURRENCE_TYPES.findIndex((r) => r.hours === recurrence),
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const newSelectedIndex = RECURRENCE_TYPES.findIndex((r) => r.hours === +recurrence);
|
||||
|
||||
setRecurrenceIndex(newSelectedIndex);
|
||||
|
||||
if (newSelectedIndex > -1) {
|
||||
setRecurrence(RECURRENCE_TYPES[newSelectedIndex].hours);
|
||||
}
|
||||
|
||||
if (dpRef?.current) {
|
||||
dpRef.current.select(newSelectedIndex);
|
||||
}
|
||||
}, [recurrence, dpRef]);
|
||||
|
||||
const _handleRecurrenceChange = useCallback((index: number) => {
|
||||
setRecurrenceIndex(index);
|
||||
|
||||
setRecurrence(RECURRENCE_TYPES[index].hours);
|
||||
}, []);
|
||||
|
||||
const _onDelete = () => {
|
||||
onNext(true);
|
||||
}
|
||||
|
||||
const _renderDescription = (text) => <Text style={styles.description}>{text}</Text>;
|
||||
const _renderCenterDescription = (text) => <Text style={styles.centerDescription}>{text}</Text>;
|
||||
const _renderCenterDescription = (text, extraStyles = {}) => (
|
||||
<Text style={[styles.centerDescription, extraStyles]}>{text}</Text>
|
||||
);
|
||||
|
||||
const amountLimitText = disableMinimum
|
||||
? ''
|
||||
@ -105,6 +172,16 @@ const TransferAmountInputSection = ({
|
||||
{ suffix: amountLimitText },
|
||||
)}
|
||||
</Text>
|
||||
|
||||
{startDate && startDate !== '' && (
|
||||
<TouchableOpacity onPress={_onDelete}>
|
||||
<Text style={[styles.sectionSubheading, styles.dangerDescription]}>
|
||||
{intl.formatMessage({ id: 'transfer.delete_recurrent_transfer' }) +
|
||||
dateToFormatted(startDate, 'LL')}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
|
||||
<TransferFormItem
|
||||
label={intl.formatMessage({ id: 'transfer.amount' })}
|
||||
rightComponent={() =>
|
||||
@ -124,8 +201,41 @@ const TransferAmountInputSection = ({
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
/>
|
||||
{transferType === TransferTypes.RECURRENT_TRANSFER && (
|
||||
<>
|
||||
<TransferFormItem
|
||||
label={intl.formatMessage({ id: 'transfer.recurrence' })}
|
||||
rightComponent={() => (
|
||||
<DropdownButton
|
||||
dropdownButtonStyle={styles.dropdownButtonStyle}
|
||||
rowTextStyle={styles.rowTextStyle}
|
||||
style={styles.dropdown}
|
||||
dropdownStyle={styles.dropdownStyle}
|
||||
textStyle={styles.dropdownText}
|
||||
options={RECURRENCE_TYPES.map((k) => intl.formatMessage({ id: k.intlId }))}
|
||||
defaultText={intl.formatMessage({ id: 'transfer.recurrence_placeholder' })}
|
||||
selectedOptionIndex={recurrenceIndex}
|
||||
onSelect={(index) => _handleRecurrenceChange(index)}
|
||||
dropdownRef={dpRef}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<TransferFormItem
|
||||
label={intl.formatMessage({ id: 'transfer.executions' })}
|
||||
rightComponent={() =>
|
||||
_renderInput(
|
||||
intl.formatMessage({ id: 'transfer.executions_placeholder' }),
|
||||
'executions',
|
||||
'numeric',
|
||||
false,
|
||||
)
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{(transferType === TransferTypes.POINTS ||
|
||||
transferType === TransferTypes.TRANSFER_TOKEN ||
|
||||
transferType === TransferTypes.RECURRENT_TRANSFER ||
|
||||
transferType === TransferTypes.TRANSFER_TO_SAVINGS ||
|
||||
transferType === TransferTypes.TRANSFER_ENGINE ||
|
||||
transferType === TransferTypes.TRANSFER_SPK ||
|
||||
@ -143,6 +253,7 @@ const TransferAmountInputSection = ({
|
||||
containerStyle={{ height: 80 }}
|
||||
/>
|
||||
)}
|
||||
|
||||
{(transferType === TransferTypes.POINTS || transferType === TransferTypes.TRANSFER_TOKEN) && (
|
||||
<TransferFormItem
|
||||
rightComponentStyle={styles.transferItemRightStyle}
|
||||
|
@ -59,6 +59,10 @@ export default EStyleSheet.create({
|
||||
color: '$primaryBlack',
|
||||
fontWeight: '600',
|
||||
},
|
||||
dangerDescription: {
|
||||
color: 'red',
|
||||
fontWeight: '700',
|
||||
},
|
||||
transferItemContainer: {
|
||||
height: 20,
|
||||
},
|
||||
@ -82,4 +86,28 @@ export default EStyleSheet.create({
|
||||
fontWeight: '600',
|
||||
textAlign: 'left',
|
||||
},
|
||||
dropdownText: {
|
||||
fontSize: 14,
|
||||
paddingLeft: 12,
|
||||
paddingHorizontal: 14,
|
||||
// color: '$primaryDarkGray',
|
||||
color: '$primaryBlack',
|
||||
},
|
||||
dropdownStyle: {
|
||||
marginTop: 15,
|
||||
minWidth: 192,
|
||||
width: 192,
|
||||
maxHeight: 300,
|
||||
},
|
||||
dropdownButtonStyle: {
|
||||
borderColor: '$borderColor',
|
||||
borderWidth: 1,
|
||||
height: 44,
|
||||
width: '100%',
|
||||
borderRadius: 8,
|
||||
},
|
||||
dropdown: {
|
||||
flexGrow: 1,
|
||||
width: 150,
|
||||
},
|
||||
});
|
||||
|
@ -11,12 +11,12 @@ const api = axios.create({
|
||||
});
|
||||
|
||||
api.interceptors.request.use((request) => {
|
||||
console.log('Starting api Request', request);
|
||||
// console.log('Starting api Request', request);
|
||||
return request;
|
||||
});
|
||||
|
||||
api.interceptors.response.use((response) => {
|
||||
console.log('Response:', response);
|
||||
// console.log('Response:', response);
|
||||
return response;
|
||||
});
|
||||
|
||||
|
@ -18,7 +18,7 @@ const ecencyApi = axios.create({
|
||||
});
|
||||
|
||||
ecencyApi.interceptors.request.use((request) => {
|
||||
console.log('Starting ecency Request', request);
|
||||
// console.log(`Starting ecency Request`, request);
|
||||
|
||||
// skip code addition is register and token refresh endpoint is triggered
|
||||
if (
|
||||
@ -68,7 +68,7 @@ ecencyApi.interceptors.request.use((request) => {
|
||||
});
|
||||
|
||||
ecencyApi.interceptors.response.use((response) => {
|
||||
console.log('Response:', response);
|
||||
// console.log('Response:', response);
|
||||
return response;
|
||||
});
|
||||
|
||||
|
@ -12,12 +12,12 @@ function upload(fd, username, signature, uploadProgress) {
|
||||
});
|
||||
|
||||
image.interceptors.request.use((request) => {
|
||||
console.log('Starting image Request', request);
|
||||
// console.log('Starting image Request', request);
|
||||
return request;
|
||||
});
|
||||
|
||||
image.interceptors.response.use((response) => {
|
||||
console.log('Response:', response);
|
||||
// console.log('Response:', response);
|
||||
return response;
|
||||
});
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
"claim_reward_balance": "Claim Reward ",
|
||||
"points_activity":"Activity",
|
||||
"transfer": "Transfer",
|
||||
"recurrent_transfer": "Recurrent Transfer",
|
||||
"power_up": "To Vesting",
|
||||
"transfer_from_savings": "From Savings",
|
||||
"withdraw_savings":"Withdraw Savings",
|
||||
@ -770,13 +771,19 @@
|
||||
"to": "To",
|
||||
"amount_information": "Drag the slider to adjust the amount",
|
||||
"amount": "Amount",
|
||||
"executions": "Executions",
|
||||
"recurrence": "Recurrence",
|
||||
"memo": "Memo",
|
||||
"recurrent_transfer": "Recurrent Transfer",
|
||||
"delete_recurrent_transfer": "Delete Recurrent Transfer ",
|
||||
"information": "Continue transaction?",
|
||||
"amount_desc": "Balance",
|
||||
"memo_desc": "This memo is public",
|
||||
"convert_desc": "Convert takes 3.5 days and NOT recommended IF HBD price is higher than $1",
|
||||
"to_placeholder": "Username",
|
||||
"memo_placeholder": "Enter your notes here",
|
||||
"recurrence_placeholder": "Choose Recurrence",
|
||||
"executions_placeholder": "Number of Repeats",
|
||||
"transfer_token": "Transfer",
|
||||
"purchase_estm": "Purchase Points",
|
||||
"convert": "Convert HBD to HIVE",
|
||||
|
@ -10,12 +10,12 @@ const slist = axios.create({
|
||||
});
|
||||
|
||||
slist.interceptors.request.use((request) => {
|
||||
console.log('Starting server list Request', request);
|
||||
// console.log('Starting server list Request', request);
|
||||
return request;
|
||||
});
|
||||
|
||||
slist.interceptors.response.use((response) => {
|
||||
console.log('Response:', response);
|
||||
// console.log('Response:', response);
|
||||
return response;
|
||||
});
|
||||
|
||||
|
@ -12,6 +12,7 @@ const TransferTypes = {
|
||||
POWER_DOWN: 'power_down',
|
||||
ADDRESS_VIEW: 'address_view',
|
||||
DELEGATE_VESTING_SHARES: 'delegate_vesting_shares',
|
||||
RECURRENT_TRANSFER: 'recurrent_transfer',
|
||||
|
||||
// Engine Transfer types
|
||||
WITHDRAW_VESTING: 'withdraw_vesting',
|
||||
|
@ -16,6 +16,8 @@ import {
|
||||
withdrawVesting,
|
||||
delegateVestingShares,
|
||||
setWithdrawVestingRoute,
|
||||
recurrentTransferToken,
|
||||
getRecurrentTransfers,
|
||||
} from '../providers/hive/dhive';
|
||||
import { toastNotification } from '../redux/actions/uiAction';
|
||||
import { getUserDataWithUsername } from '../realm/realm';
|
||||
@ -63,6 +65,7 @@ class TransferContainer extends Component {
|
||||
spkMarkets: [],
|
||||
initialAmount: props.route.params?.initialAmount,
|
||||
initialMemo: props.route.params?.initialMemo,
|
||||
recurrentTransfers: [],
|
||||
};
|
||||
}
|
||||
|
||||
@ -74,6 +77,8 @@ class TransferContainer extends Component {
|
||||
|
||||
this.fetchBalance(name);
|
||||
|
||||
this._fetchRecurrentTransfers(name);
|
||||
|
||||
if (this.state.transferType === TransferTypes.DELEGATE_SPK) {
|
||||
this._fetchSpkMarkets();
|
||||
}
|
||||
@ -181,6 +186,16 @@ class TransferContainer extends Component {
|
||||
return validUsers;
|
||||
};
|
||||
|
||||
_fetchRecurrentTransfers = async (username) => {
|
||||
const recTransfers = await getRecurrentTransfers(username);
|
||||
|
||||
this.setState({
|
||||
recurrentTransfers: recTransfers,
|
||||
});
|
||||
|
||||
return recTransfers;
|
||||
};
|
||||
|
||||
_delayedRefreshCoinsData = () => {
|
||||
const { dispatch } = this.props;
|
||||
setTimeout(() => {
|
||||
@ -188,7 +203,14 @@ class TransferContainer extends Component {
|
||||
}, 3000);
|
||||
};
|
||||
|
||||
_transferToAccount = async (from, destination, amount, memo) => {
|
||||
_transferToAccount = async (
|
||||
from,
|
||||
destination,
|
||||
amount,
|
||||
memo,
|
||||
recurrence = null,
|
||||
executions = 0,
|
||||
) => {
|
||||
const { pinCode, navigation, dispatch, intl, route } = this.props;
|
||||
let { currentAccount } = this.props;
|
||||
const { selectedAccount } = this.state;
|
||||
@ -205,6 +227,11 @@ class TransferContainer extends Component {
|
||||
fundType,
|
||||
};
|
||||
|
||||
if (recurrence && executions) {
|
||||
data.recurrence = +recurrence;
|
||||
data.executions = +executions;
|
||||
}
|
||||
|
||||
if (countDecimals(Number(data.amount)) < 3) {
|
||||
data.amount = Number(data.amount).toFixed(3);
|
||||
}
|
||||
@ -214,6 +241,9 @@ class TransferContainer extends Component {
|
||||
case 'transfer_token':
|
||||
func = transferToken;
|
||||
break;
|
||||
case TransferTypes.RECURRENT_TRANSFER:
|
||||
func = recurrentTransferToken;
|
||||
break;
|
||||
case 'purchase_estm':
|
||||
func = transferToken;
|
||||
break;
|
||||
@ -344,6 +374,7 @@ class TransferContainer extends Component {
|
||||
spkMarkets,
|
||||
initialAmount,
|
||||
initialMemo,
|
||||
recurrentTransfers,
|
||||
} = this.state;
|
||||
|
||||
const transferType = route.params?.transferType ?? '';
|
||||
@ -371,6 +402,8 @@ class TransferContainer extends Component {
|
||||
setWithdrawVestingRoute: this._setWithdrawVestingRoute,
|
||||
initialAmount,
|
||||
initialMemo,
|
||||
fetchRecurrentTransfers: this._fetchRecurrentTransfers,
|
||||
recurrentTransfers,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ import { SERVER_LIST } from '../../constants/options/api';
|
||||
import { b64uEnc } from '../../utils/b64';
|
||||
import bugsnagInstance from '../../config/bugsnag';
|
||||
import bugsnapInstance from '../../config/bugsnag';
|
||||
import { makeJsonMetadataReply } from '../../utils/editor';
|
||||
import TransferTypes from '../../constants/transferTypes';
|
||||
|
||||
const hiveuri = require('hive-uri');
|
||||
global.Buffer = global.Buffer || require('buffer').Buffer;
|
||||
@ -987,6 +987,51 @@ export const transferToken = (currentAccount, pin, data) => {
|
||||
);
|
||||
};
|
||||
|
||||
export const recurrentTransferToken = (currentAccount, pin, data) => {
|
||||
const digitPinCode = getDigitPinCode(pin);
|
||||
const key = getAnyPrivateKey(
|
||||
{
|
||||
activeKey: get(currentAccount, 'local.activeKey'),
|
||||
},
|
||||
digitPinCode,
|
||||
);
|
||||
|
||||
if (key) {
|
||||
const privateKey = PrivateKey.fromString(key);
|
||||
const args = {
|
||||
from: get(data, 'from'),
|
||||
to: get(data, 'destination'),
|
||||
amount: get(data, 'amount'),
|
||||
memo: get(data, 'memo'),
|
||||
recurrence: get(data, 'recurrence'),
|
||||
executions: get(data, 'executions'),
|
||||
extensions: [],
|
||||
};
|
||||
|
||||
const opArray = [[TransferTypes.RECURRENT_TRANSFER, args]];
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
sendHiveOperations(opArray, privateKey)
|
||||
.then((result) => {
|
||||
if (result) {
|
||||
resolve(result);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log('====================================');
|
||||
console.log('error on recurrent transfer token');
|
||||
console.log('====================================');
|
||||
console.log(err);
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.reject(
|
||||
new Error('Check private key permission! Required private active key or above.'),
|
||||
);
|
||||
};
|
||||
|
||||
export const convert = (currentAccount, pin, data) => {
|
||||
const digitPinCode = getDigitPinCode(pin);
|
||||
const key = getAnyPrivateKey(
|
||||
@ -1456,6 +1501,19 @@ export const getTrendingTags = async (tag, number = 20) => {
|
||||
}
|
||||
};
|
||||
|
||||
export const getRecurrentTransfers = async (username) => {
|
||||
try {
|
||||
const rawData = await client.call('condenser_api', 'find_recurrent_transfers', [username]);
|
||||
if (!rawData || !rawData.length) {
|
||||
return [];
|
||||
}
|
||||
return rawData;
|
||||
} catch (err) {
|
||||
console.warn('Failed to get recurrent transfers', err);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
export const postContent = (
|
||||
account,
|
||||
pin,
|
||||
|
@ -26,7 +26,7 @@ export const useNotificationsQuery = (filter: NotificationFilters) => {
|
||||
const _fetchNotifications = async (pageParam: string) => {
|
||||
console.log('fetching page since:', pageParam);
|
||||
const response = await getNotifications({ filter, since: pageParam, limit: FETCH_LIMIT });
|
||||
console.log('new page fetched', response);
|
||||
// console.log('new page fetched', response);
|
||||
return response || [];
|
||||
};
|
||||
|
||||
|
@ -259,7 +259,7 @@ export const useInjectVotesCache = (_data: any | any[]) => {
|
||||
};
|
||||
|
||||
const _cData = isArray(_data) ? _data.map(_itemFunc) : _itemFunc({ ..._data });
|
||||
console.log('data received', _cData.length, _cData);
|
||||
// console.log('data received', _cData.length, _cData);
|
||||
setRetData(_cData);
|
||||
}, [_data]);
|
||||
|
||||
|
@ -278,7 +278,7 @@ export const useActivitiesQuery = (assetId: string) => {
|
||||
isEngine: assetData.isEngine,
|
||||
});
|
||||
|
||||
console.log('new page fetched', _activites);
|
||||
// console.log('new page fetched', _activites);
|
||||
return _activites || [];
|
||||
};
|
||||
|
||||
|
@ -12,7 +12,7 @@ const initialState: State = {
|
||||
walkthroughMap: new Map(),
|
||||
};
|
||||
export default function (state = initialState, action) {
|
||||
console.log('action : ', action);
|
||||
// console.log('action : ', action);
|
||||
|
||||
const { type, payload } = action;
|
||||
switch (type) {
|
||||
|
@ -59,6 +59,8 @@ export interface CoinActivity {
|
||||
details: string | null;
|
||||
memo: string;
|
||||
cancelable: boolean;
|
||||
recurrence: string;
|
||||
executions: string;
|
||||
}
|
||||
|
||||
export interface QuoteItem {
|
||||
|
@ -15,6 +15,7 @@ import { DelegationsModal, MODES } from '../children/delegationsModal';
|
||||
import TransferTypes from '../../../constants/transferTypes';
|
||||
import { walletQueries } from '../../../providers/queries';
|
||||
import parseToken from '../../../utils/parseToken';
|
||||
import { log } from '../../../../reactotron-config';
|
||||
|
||||
export interface AssetDetailsScreenParams {
|
||||
coinId: string;
|
||||
|
@ -30,6 +30,8 @@ const Transfer = ({ navigation, route }) => (
|
||||
spkMarkets,
|
||||
initialAmount,
|
||||
initialMemo,
|
||||
recurrentTransfers,
|
||||
fetchRecurrentTransfers,
|
||||
}) => {
|
||||
switch (transferType) {
|
||||
case 'delegate':
|
||||
@ -98,6 +100,8 @@ const Transfer = ({ navigation, route }) => (
|
||||
referredUsername={referredUsername || ''}
|
||||
initialAmount={initialAmount || ''}
|
||||
initialMemo={initialMemo || ''}
|
||||
recurrentTransfers={recurrentTransfers || []}
|
||||
fetchRecurrentTransfers={fetchRecurrentTransfers}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useState, useMemo } from 'react';
|
||||
import React, { useState, useMemo, useEffect, useCallback } from 'react';
|
||||
import { Alert, Text, View } from 'react-native';
|
||||
import { WebView } from 'react-native-webview';
|
||||
import { injectIntl } from 'react-intl';
|
||||
@ -26,6 +26,7 @@ import {
|
||||
getSpkTransactionId,
|
||||
SPK_NODE_ECENCY,
|
||||
} from '../../../providers/hive-spk/hiveSpk';
|
||||
import parseToken from '../../../utils/parseToken';
|
||||
|
||||
const TransferView = ({
|
||||
currentAccountName,
|
||||
@ -44,7 +45,8 @@ const TransferView = ({
|
||||
referredUsername,
|
||||
initialAmount,
|
||||
initialMemo,
|
||||
transactionData,
|
||||
fetchRecurrentTransfers,
|
||||
recurrentTransfers,
|
||||
}) => {
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
@ -75,6 +77,10 @@ const TransferView = ({
|
||||
const [memo, setMemo] = useState(
|
||||
transferType === 'purchase_estm' ? 'estm-purchase' : initialMemo,
|
||||
);
|
||||
const [recurrence, setRecurrence] = useState('');
|
||||
const [executions, setExecutions] = useState('');
|
||||
const [startDate, setStartDate] = useState('');
|
||||
|
||||
const [isUsernameValid, setIsUsernameValid] = useState(
|
||||
!!(
|
||||
transferType === 'purchase_estm' ||
|
||||
@ -96,6 +102,8 @@ const TransferView = ({
|
||||
const [hsTransfer, setHsTransfer] = useState(false);
|
||||
const [isTransfering, setIsTransfering] = useState(false);
|
||||
|
||||
const isRecurrentTransfer = transferType === TransferTypes.RECURRENT_TRANSFER;
|
||||
|
||||
const isEngineToken = useMemo(() => transferType.endsWith('_engine'), [transferType]);
|
||||
const isSpkToken = useMemo(() => transferType.endsWith('_spk'), [transferType]);
|
||||
|
||||
@ -105,7 +113,27 @@ const TransferView = ({
|
||||
if (accountType === AUTH_TYPE.STEEM_CONNECT) {
|
||||
setHsTransfer(true);
|
||||
} else {
|
||||
transferToAccount(from, destination, amount, memo);
|
||||
transferToAccount(
|
||||
from,
|
||||
destination,
|
||||
amount,
|
||||
memo,
|
||||
isRecurrentTransfer ? recurrence : null,
|
||||
isRecurrentTransfer ? executions : null,
|
||||
);
|
||||
}
|
||||
},
|
||||
300,
|
||||
{ trailing: true },
|
||||
);
|
||||
|
||||
const _handleDeleteRecurrentTransfer = debounce(
|
||||
() => {
|
||||
setIsTransfering(true);
|
||||
if (accountType === AUTH_TYPE.STEEM_CONNECT) {
|
||||
setHsTransfer(true);
|
||||
} else {
|
||||
transferToAccount(from, destination, '0', memo, 24, 2);
|
||||
}
|
||||
},
|
||||
300,
|
||||
@ -133,7 +161,11 @@ const TransferView = ({
|
||||
// )}`;
|
||||
// } else
|
||||
|
||||
if (transferType === TransferTypes.TRANSFER_TO_SAVINGS) {
|
||||
if (transferType === TransferTypes.RECURRENT_TRANSFER) {
|
||||
path = `sign/recurrent_transfer?from=${currentAccountName}&to=${destination}&amount=${encodeURIComponent(
|
||||
`${amount} ${fundType}`,
|
||||
)}&memo=${encodeURIComponent(memo)}&recurrence=${recurrence}&executions=${executions}`;
|
||||
} else if (transferType === TransferTypes.TRANSFER_TO_SAVINGS) {
|
||||
path = `sign/transfer_to_savings?from=${currentAccountName}&to=${destination}&amount=${encodeURIComponent(
|
||||
`${amount} ${fundType}`,
|
||||
)}&memo=${encodeURIComponent(memo)}`;
|
||||
@ -200,9 +232,10 @@ const TransferView = ({
|
||||
`${amount} ${fundType}`,
|
||||
)}&memo=${encodeURIComponent(memo)}`;
|
||||
}
|
||||
console.log('path is: ', path);
|
||||
}
|
||||
|
||||
const _onNextPress = () => {
|
||||
const _onNextPress = (deleteTransfer = false) => {
|
||||
if (balance < amount) {
|
||||
Alert.alert(intl.formatMessage({ id: 'wallet.low_liquidity' }));
|
||||
|
||||
@ -218,7 +251,7 @@ const TransferView = ({
|
||||
},
|
||||
{
|
||||
text: intl.formatMessage({ id: 'alert.confirm' }),
|
||||
onPress: _handleTransferAction,
|
||||
onPress: deleteTransfer ? _handleDeleteRecurrentTransfer : _handleTransferAction,
|
||||
},
|
||||
],
|
||||
}),
|
||||
@ -228,6 +261,49 @@ const TransferView = ({
|
||||
|
||||
const nextBtnDisabled = !((isEngineToken ? amount > 0 : amount >= 0.001) && isUsernameValid);
|
||||
|
||||
useEffect(() => {
|
||||
if (isRecurrentTransfer) {
|
||||
fetchRecurrentTransfers(currentAccountName);
|
||||
}
|
||||
}, [isRecurrentTransfer]);
|
||||
|
||||
const _findRecurrentTransferOfUser = useCallback(
|
||||
(userToFind) => {
|
||||
if (!isRecurrentTransfer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const existingRecurrentTransfer = recurrentTransfers.find((rt) => rt.to === userToFind);
|
||||
|
||||
let newMemo,
|
||||
newAmount,
|
||||
newRecurrence,
|
||||
newStartDate,
|
||||
newExecutions = '';
|
||||
|
||||
if (existingRecurrentTransfer) {
|
||||
newMemo = existingRecurrentTransfer.memo;
|
||||
newAmount = parseToken(existingRecurrentTransfer.amount).toString();
|
||||
newRecurrence = existingRecurrentTransfer.recurrence.toString();
|
||||
newExecutions = `${existingRecurrentTransfer.remaining_executions}`;
|
||||
newStartDate = existingRecurrentTransfer.trigger_date;
|
||||
|
||||
console.log('====================================');
|
||||
console.log('existingRecurrentTransfer');
|
||||
console.log('====================================');
|
||||
console.log(existingRecurrentTransfer);
|
||||
}
|
||||
setMemo(newMemo);
|
||||
setAmount(newAmount);
|
||||
setRecurrence(newRecurrence);
|
||||
setExecutions(newExecutions);
|
||||
setStartDate(newStartDate);
|
||||
|
||||
return existingRecurrentTransfer;
|
||||
},
|
||||
[recurrentTransfers],
|
||||
);
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<BasicHeader
|
||||
@ -257,6 +333,7 @@ const TransferView = ({
|
||||
memo={memo}
|
||||
setMemo={setMemo}
|
||||
spkMarkets={spkMarkets}
|
||||
getRecurrentTransferOfUser={_findRecurrentTransferOfUser}
|
||||
/>
|
||||
<TransferAmountInputSection
|
||||
balance={balance}
|
||||
@ -274,6 +351,12 @@ const TransferView = ({
|
||||
fundType={fundType}
|
||||
currentAccountName={currentAccountName}
|
||||
disableMinimum={isEngineToken}
|
||||
recurrence={recurrence}
|
||||
setRecurrence={setRecurrence}
|
||||
executions={executions}
|
||||
setExecutions={setExecutions}
|
||||
startDate={startDate}
|
||||
onNext={_onNextPress}
|
||||
/>
|
||||
<View style={styles.bottomContent}>
|
||||
<MainButton
|
||||
|
@ -151,7 +151,7 @@ export const daysTillDate = (dateObj) => {
|
||||
*
|
||||
* */
|
||||
export const dateToFormatted = (d, format = 'LLLL') => {
|
||||
const isTimeZoned = d.indexOf('.') !== -1 || d.indexOf('+') !== -1 ? d : `${d}.000Z`;
|
||||
const isTimeZoned = d?.indexOf('.') !== -1 || d?.indexOf('+') !== -1 ? d : `${d}.000Z`;
|
||||
const dm = moment(new Date(isTimeZoned));
|
||||
return dm.format(format);
|
||||
};
|
||||
|
@ -68,7 +68,8 @@ const HIVE_ACTIONS = [
|
||||
'transfer_to_savings',
|
||||
'transfer_to_vesting',
|
||||
'withdraw_hive',
|
||||
'swap_token'
|
||||
'swap_token',
|
||||
TransferTypes.RECURRENT_TRANSFER
|
||||
];
|
||||
const HBD_ACTIONS = [
|
||||
'transfer_token',
|
||||
|
@ -9131,10 +9131,10 @@ react-native-level-fs@^3.0.0:
|
||||
level-filesystem "^1.0.1"
|
||||
levelup "^0.18.2"
|
||||
|
||||
react-native-linear-gradient@^2.4.2:
|
||||
version "2.6.2"
|
||||
resolved "https://registry.yarnpkg.com/react-native-linear-gradient/-/react-native-linear-gradient-2.6.2.tgz#56598a76832724b2afa7889747635b5c80948f38"
|
||||
integrity sha512-Z8Xxvupsex+9BBFoSYS87bilNPWcRfRsGC0cpJk72Nxb5p2nEkGSBv73xZbEHnW2mUFvP+huYxrVvjZkr/gRjQ==
|
||||
react-native-linear-gradient@^2.8.3:
|
||||
version "2.8.3"
|
||||
resolved "https://registry.yarnpkg.com/react-native-linear-gradient/-/react-native-linear-gradient-2.8.3.tgz#9a116649f86d74747304ee13db325e20b21e564f"
|
||||
integrity sha512-KflAXZcEg54PXkLyflaSZQ3PJp4uC4whM7nT/Uot9m0e/qxFV3p6uor1983D1YOBJbJN7rrWdqIjq0T42jOJyA==
|
||||
|
||||
react-native-media-controls@^2.3.0:
|
||||
version "2.3.0"
|
||||
|
Loading…
Reference in New Issue
Block a user