1
0
mirror of https://github.com/trezor/trezor-wallet synced 2024-12-29 02:18:06 +00:00

Merge pull request #320 from trezor/fix/ripple-destination-tag

Fix/ripple destination tag
This commit is contained in:
Vladimir Volek 2019-01-09 18:30:20 +01:00 committed by GitHub
commit ba68fffc20
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 105 additions and 17 deletions

View File

@ -70,7 +70,7 @@
"rimraf": "^2.6.2", "rimraf": "^2.6.2",
"styled-components": "^4.1.2", "styled-components": "^4.1.2",
"styled-normalize": "^8.0.4", "styled-normalize": "^8.0.4",
"trezor-connect": "7.0.0-beta.1", "trezor-connect": "7.0.0-beta.2",
"wallet-address-validator": "^0.2.4", "wallet-address-validator": "^0.2.4",
"web3": "1.0.0-beta.35", "web3": "1.0.0-beta.35",
"webpack": "^4.16.3", "webpack": "^4.16.3",

View File

@ -118,7 +118,7 @@ export const onNotification = (payload: $ElementType<BlockchainNotification, 'pa
const updatedAccount = await TrezorConnect.rippleGetAccountInfo({ const updatedAccount = await TrezorConnect.rippleGetAccountInfo({
account: { account: {
address: account.descriptor, descriptor: account.descriptor,
from: account.block, from: account.block,
history: false, history: false,
}, },

View File

@ -76,6 +76,7 @@ export const discoverAccount = (device: TrezorDevice, discoveryProcess: Discover
networkType: 'ripple', networkType: 'ripple',
sequence: account.sequence, sequence: account.sequence,
reserve: '0', reserve: toDecimalAmount(account.reserve, network.decimals),
// reserve: '20',
}; };
}; };

View File

@ -244,6 +244,23 @@ export const onFeeChange = (fee: string): ThunkAction => (dispatch: Dispatch, ge
}); });
}; };
/*
* Called from UI on "advanced / destination tag" field change
*/
export const onDestinationTagChange = (destinationTag: string): ThunkAction => (dispatch: Dispatch, getState: GetState): void => {
const state: State = getState().sendFormRipple;
dispatch({
type: SEND.CHANGE,
networkType: 'ripple',
state: {
...state,
untouched: false,
touched: { ...state.touched, destinationTag: true },
destinationTag,
},
});
};
/* /*
* Called from UI from "send" button * Called from UI from "send" button
*/ */
@ -262,7 +279,13 @@ export const onSend = (): AsyncAction => async (dispatch: Dispatch, getState: Ge
if (!blockchain) return; if (!blockchain) return;
const currentState: State = getState().sendFormRipple; const currentState: State = getState().sendFormRipple;
const amount = fromDecimalAmount(currentState.amount, 6); const payment: { amount: string, destination: string, destinationTag?: number } = {
amount: fromDecimalAmount(currentState.amount, network.decimals),
destination: currentState.address,
};
if (currentState.destinationTag.length > 0) {
payment.destinationTag = parseInt(currentState.destinationTag, 10);
}
const signedTransaction = await TrezorConnect.rippleSignTransaction({ const signedTransaction = await TrezorConnect.rippleSignTransaction({
device: { device: {
@ -276,10 +299,7 @@ export const onSend = (): AsyncAction => async (dispatch: Dispatch, getState: Ge
fee: currentState.selectedFeeLevel.fee, // Fee must be in the range of 10 to 10,000 drops fee: currentState.selectedFeeLevel.fee, // Fee must be in the range of 10 to 10,000 drops
flags: 0x80000000, flags: 0x80000000,
sequence: account.sequence, sequence: account.sequence,
payment: { payment,
amount,
destination: currentState.address,
},
}, },
}); });
@ -346,5 +366,6 @@ export default {
onFeeLevelChange, onFeeLevelChange,
updateFeeLevels, updateFeeLevels,
onFeeChange, onFeeChange,
onDestinationTagChange,
onSend, onSend,
}; };

View File

@ -73,6 +73,7 @@ export const validation = (): PayloadAction<State> => (dispatch: Dispatch, getSt
state = dispatch(addressLabel(state)); state = dispatch(addressLabel(state));
state = dispatch(amountValidation(state)); state = dispatch(amountValidation(state));
state = dispatch(feeValidation(state)); state = dispatch(feeValidation(state));
state = dispatch(destinationTagValidation(state));
return state; return state;
}; };
@ -229,6 +230,19 @@ export const feeValidation = ($state: State): PayloadAction<State> => (dispatch:
} }
return state; return state;
}; };
/*
* Destination Tag value validation
*/
export const destinationTagValidation = ($state: State): PayloadAction<State> => (): State => {
const state = { ...$state };
if (!state.touched.destinationTag) return state;
const { destinationTag } = state;
if (destinationTag.length > 0 && !destinationTag.match(ABS_RE)) {
state.errors.destinationTag = 'Destination tag must be an absolute number';
}
return state;
};
/* /*

View File

@ -27,6 +27,7 @@ export type State = {
fee: string; fee: string;
feeNeedsUpdate: boolean; feeNeedsUpdate: boolean;
sequence: string; sequence: string;
destinationTag: string;
total: string; total: string;
errors: {[k: string]: string}; errors: {[k: string]: string};
@ -56,6 +57,7 @@ export const initialState: State = {
fee: '0', fee: '0',
feeNeedsUpdate: false, feeNeedsUpdate: false,
sequence: '0', sequence: '0',
destinationTag: '',
total: '0', total: '0',
errors: {}, errors: {},

View File

@ -95,6 +95,7 @@ export const getPendingSequence = (pending: Array<Transaction>): number => pendi
}, 0); }, 0);
export const getPendingAmount = (pending: Array<Transaction>, currency: string, token: boolean = false): BigNumber => pending.reduce((value: BigNumber, tx: Transaction): BigNumber => { export const getPendingAmount = (pending: Array<Transaction>, currency: string, token: boolean = false): BigNumber => pending.reduce((value: BigNumber, tx: Transaction): BigNumber => {
if (tx.type !== 'send') return value;
if (!token) { if (!token) {
// regular transactions // regular transactions
// add fees from token txs and amount from regular txs // add fees from token txs and amount from regular txs

View File

@ -35,7 +35,7 @@ const AdvancedSettingsWrapper = styled.div`
border-top: 1px solid ${colors.DIVIDER}; border-top: 1px solid ${colors.DIVIDER};
`; `;
const GasInputRow = styled.div` const InputRow = styled.div`
width: 100%; width: 100%;
display: flex; display: flex;
@ -44,7 +44,7 @@ const GasInputRow = styled.div`
} }
`; `;
const GasInput = styled(Input)` const StyledInput = styled(Input)`
/* min-height: 85px; */ /* min-height: 85px; */
padding-bottom: 28px; padding-bottom: 28px;
&:first-child { &:first-child {
@ -75,6 +75,17 @@ const getFeeInputState = (feeErrors: string, feeWarnings: string): string => {
return state; return state;
}; };
const getDestinationTagInputState = (errors: string, warnings: string): string => {
let state = '';
if (warnings && !errors) {
state = 'warning';
}
if (errors) {
state = 'error';
}
return state;
};
const Left = styled.div` const Left = styled.div`
display: flex; display: flex;
align-items: center; align-items: center;
@ -91,15 +102,17 @@ const AdvancedForm = (props: Props) => {
warnings, warnings,
infos, infos,
fee, fee,
destinationTag,
} = props.sendForm; } = props.sendForm;
const { const {
onFeeChange, onFeeChange,
onDestinationTagChange,
} = props.sendFormActions; } = props.sendFormActions;
return ( return (
<AdvancedSettingsWrapper> <AdvancedSettingsWrapper>
<GasInputRow> <InputRow>
<GasInput <StyledInput
state={getFeeInputState(errors.fee, warnings.fee)} state={getFeeInputState(errors.fee, warnings.fee)}
autoComplete="off" autoComplete="off"
autoCorrect="off" autoCorrect="off"
@ -115,7 +128,7 @@ const AdvancedForm = (props: Props) => {
Transfer cost in XRP drops Transfer cost in XRP drops
</React.Fragment> </React.Fragment>
)} )}
maxWidth={410} maxWidth={100}
readMoreLink="https://developers.ripple.com/transaction-cost.html" readMoreLink="https://developers.ripple.com/transaction-cost.html"
placement="top" placement="top"
> >
@ -132,7 +145,43 @@ const AdvancedForm = (props: Props) => {
value={fee} value={fee}
onChange={event => onFeeChange(event.target.value)} onChange={event => onFeeChange(event.target.value)}
/> />
</GasInputRow> </InputRow>
<InputRow>
<StyledInput
state={getDestinationTagInputState(errors.destinationTag, warnings.destinationTag)}
autoComplete="off"
autoCorrect="off"
autoCapitalize="off"
spellCheck="false"
topLabel={(
<InputLabelWrapper>
<Left>
Destination tag
<Tooltip
content={(
<React.Fragment>
An arbitrary unsigned 32-bit integer that identifies a reason for payment or a non-Ripple account.
</React.Fragment>
)}
maxWidth={200}
readMoreLink="https://developers.ripple.com/rippleapi-reference.html#payment"
placement="top"
>
<Icon
icon={ICONS.HELP}
color={colors.TEXT_SECONDARY}
size={24}
/>
</Tooltip>
</Left>
</InputLabelWrapper>
)}
bottomText={errors.destinationTag || warnings.destinationTag || infos.destinationTag}
value={destinationTag}
onChange={event => onDestinationTagChange(event.target.value)}
/>
</InputRow>
<AdvancedSettingsSendButtonWrapper> <AdvancedSettingsSendButtonWrapper>
{ props.children } { props.children }

View File

@ -9790,9 +9790,9 @@ tr46@^1.0.1:
dependencies: dependencies:
punycode "^2.1.0" punycode "^2.1.0"
trezor-connect@7.0.0-beta.1: trezor-connect@7.0.0-beta.2:
version "7.0.0-beta.1" version "7.0.0-beta.2"
resolved "https://registry.yarnpkg.com/trezor-connect/-/trezor-connect-7.0.0-beta.1.tgz#de87d8f1d9878101380f7b3198bf2531d7560a5c" resolved "https://registry.yarnpkg.com/trezor-connect/-/trezor-connect-7.0.0-beta.2.tgz#10dc04e1b60804263e9873cd503a4fc9d3e940d2"
dependencies: dependencies:
babel-runtime "^6.26.0" babel-runtime "^6.26.0"
events "^1.1.1" events "^1.1.1"