mirror of https://github.com/trezor/trezor-wallet
commit
7f0d3b507c
@ -1,31 +0,0 @@
|
||||
{
|
||||
"presets": [
|
||||
["env", {
|
||||
"useBuiltIns": true,
|
||||
"loose": true
|
||||
}],
|
||||
"react"
|
||||
],
|
||||
"plugins": [
|
||||
"react-hot-loader/babel",
|
||||
"transform-class-properties",
|
||||
"transform-object-rest-spread",
|
||||
"transform-flow-strip-types",
|
||||
["transform-runtime", {
|
||||
"polyfill": false,
|
||||
"regenerator": true
|
||||
}],
|
||||
["module-resolver", {
|
||||
"root": ["./src"],
|
||||
"alias": {
|
||||
"public": ["./public"]
|
||||
}
|
||||
}],
|
||||
"babel-plugin-styled-components"
|
||||
],
|
||||
"env": {
|
||||
"test": {
|
||||
"presets": ["jest"]
|
||||
}
|
||||
}
|
||||
}
|
@ -1,17 +1,50 @@
|
||||
FROM node:9.3
|
||||
FROM python:latest
|
||||
|
||||
ARG BUILD_TYPE=stable
|
||||
#
|
||||
# setup
|
||||
#
|
||||
RUN apt-get update
|
||||
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash -
|
||||
RUN apt-get install -y chromium libappindicator3-1 xdg-utils fonts-liberation nodejs wget dpkg git python python3 python3-pip xvfb libgtk2.0-0 libnotify-dev libgconf-2-4 libnss3 libxss1 libasound2
|
||||
RUN npm install -g yarn
|
||||
|
||||
WORKDIR /trezor-wallet-app
|
||||
RUN ln -s /usr/bin/chromium /usr/local/bin/chromium-browser
|
||||
|
||||
COPY package.json /trezor-wallet-app
|
||||
COPY yarn.lock /trezor-wallet-app
|
||||
#
|
||||
# build emulator
|
||||
#
|
||||
RUN mkdir /trezor-emulator
|
||||
WORKDIR /trezor-emulator
|
||||
|
||||
RUN yarn install
|
||||
RUN git clone https://github.com/trezor/trezor-core
|
||||
WORKDIR /trezor-emulator/trezor-core
|
||||
RUN git submodule update --init --recursive
|
||||
|
||||
COPY . /trezor-wallet-app
|
||||
RUN apt-get install libusb-1.0-0
|
||||
RUN pip3 install scons trezor
|
||||
RUN make build_unix_noui
|
||||
|
||||
RUN yarn run build:${BUILD_TYPE}
|
||||
#
|
||||
# install bridge
|
||||
#
|
||||
RUN mkdir /trezor-bridge
|
||||
WORKDIR /trezor-bridge
|
||||
RUN wget https://wallet.trezor.io/data/bridge/2.0.25/trezor-bridge_2.0.25_amd64.deb
|
||||
RUN dpkg -x /trezor-bridge/trezor-bridge_2.0.25_amd64.deb /trezor-bridge/extracted
|
||||
|
||||
EXPOSE 8080
|
||||
CMD [ "yarn", "run", "prod-server" ]
|
||||
#
|
||||
# install trezor-wallet
|
||||
#
|
||||
RUN mkdir /trezor-wallet
|
||||
WORKDIR /trezor-wallet
|
||||
COPY package.json /trezor-wallet
|
||||
COPY yarn.lock /trezor-wallet
|
||||
RUN yarn
|
||||
COPY . /trezor-wallet
|
||||
RUN yarn run build:stable
|
||||
|
||||
#
|
||||
# run
|
||||
#
|
||||
ENTRYPOINT ["/trezor-wallet/test/scripts/run-all.sh"]
|
||||
EXPOSE 8080 21325
|
@ -0,0 +1,51 @@
|
||||
module.exports = (api) => {
|
||||
// api.cache.forever();
|
||||
|
||||
const presets = [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
useBuiltIns: 'entry',
|
||||
loose: true,
|
||||
},
|
||||
],
|
||||
'@babel/preset-react',
|
||||
'@babel/preset-flow',
|
||||
];
|
||||
|
||||
const plugins = [
|
||||
'react-hot-loader/babel',
|
||||
'@babel/plugin-transform-flow-strip-types',
|
||||
'@babel/plugin-proposal-class-properties',
|
||||
'@babel/plugin-proposal-object-rest-spread',
|
||||
[
|
||||
'@babel/plugin-transform-runtime',
|
||||
{
|
||||
regenerator: true,
|
||||
},
|
||||
],
|
||||
[
|
||||
'module-resolver',
|
||||
{
|
||||
root: [
|
||||
'./src',
|
||||
],
|
||||
alias: {
|
||||
public: [
|
||||
'./public',
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
'babel-plugin-styled-components',
|
||||
];
|
||||
|
||||
if (api.env('test')) {
|
||||
presets.push('jest');
|
||||
}
|
||||
|
||||
return {
|
||||
presets,
|
||||
plugins,
|
||||
};
|
||||
};
|
@ -0,0 +1,11 @@
|
||||
{
|
||||
"integrationFolder": "test/integration",
|
||||
"fixturesFolder": "test/fixtures",
|
||||
"pluginsFile": "test/plugins/index.js",
|
||||
"supportFile": "test/support/index.js",
|
||||
"defaultCommandTimeout": 10000,
|
||||
"screenshotsFolder": "test/screenshots",
|
||||
"video": false,
|
||||
"trashAssetsBeforeRuns": true,
|
||||
"chromeWebSecurity": false
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,5 @@
|
||||
/* @flow */
|
||||
|
||||
export const START_SUBSCRIBE: 'blockchain__start_subscribe' = 'blockchain__start_subscribe';
|
||||
export const READY: 'blockchain__ready' = 'blockchain__ready';
|
||||
export const UPDATE_FEE: 'blockchain__update_fee' = 'blockchain__update_fee';
|
@ -0,0 +1,37 @@
|
||||
import React from 'react';
|
||||
import styled, { css } from 'styled-components';
|
||||
import PropTypes from 'prop-types';
|
||||
import { FADE_IN } from 'config/animations';
|
||||
|
||||
|
||||
const StyledBackdrop = styled.div`
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
left: 0;
|
||||
top: 0;
|
||||
background-color: rgba(0,0,0,0.5);
|
||||
|
||||
${props => props.animated && css`
|
||||
animation: ${FADE_IN} 0.3s;
|
||||
`};
|
||||
`;
|
||||
|
||||
const Backdrop = ({
|
||||
className,
|
||||
show,
|
||||
animated,
|
||||
onClick,
|
||||
}) => (
|
||||
show ? <StyledBackdrop className={className} animated={animated} onClick={onClick} /> : null
|
||||
);
|
||||
|
||||
Backdrop.propTypes = {
|
||||
show: PropTypes.bool,
|
||||
className: PropTypes.string,
|
||||
animated: PropTypes.bool,
|
||||
onClick: PropTypes.func,
|
||||
};
|
||||
|
||||
export default Backdrop;
|
@ -0,0 +1,74 @@
|
||||
/* @flow */
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import COLORS from 'config/colors';
|
||||
import ICONS from 'config/icons';
|
||||
import styled from 'styled-components';
|
||||
import type { TrezorDevice } from 'flowtype';
|
||||
|
||||
type Props = {
|
||||
device: TrezorDevice,
|
||||
size?: number,
|
||||
color?: string,
|
||||
hoverColor?: string,
|
||||
onClick?: any,
|
||||
}
|
||||
|
||||
const SvgWrapper = styled.svg`
|
||||
:hover {
|
||||
path {
|
||||
fill: ${props => props.hoverColor}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const Path = styled.path`
|
||||
fill: ${props => props.color};
|
||||
`;
|
||||
|
||||
const getDeviceIcon = (majorVersion: number) => {
|
||||
switch (majorVersion) {
|
||||
case 1:
|
||||
return ICONS.T1;
|
||||
case 2:
|
||||
return ICONS.T2;
|
||||
default:
|
||||
return ICONS.T2;
|
||||
}
|
||||
};
|
||||
|
||||
const DeviceIcon = ({
|
||||
device,
|
||||
size = 32,
|
||||
color = COLORS.TEXT_SECONDARY,
|
||||
hoverColor,
|
||||
onClick,
|
||||
}: Props) => {
|
||||
const majorVersion = device.features ? device.features.major_version : 2;
|
||||
return (
|
||||
<SvgWrapper
|
||||
hoverColor={hoverColor}
|
||||
width={`${size}`}
|
||||
height={`${size}`}
|
||||
viewBox="0 0 1024 1024"
|
||||
onClick={onClick}
|
||||
>
|
||||
<Path
|
||||
key={majorVersion}
|
||||
color={color}
|
||||
d={getDeviceIcon(majorVersion)}
|
||||
/>
|
||||
</SvgWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
DeviceIcon.propTypes = {
|
||||
device: PropTypes.object,
|
||||
size: PropTypes.number,
|
||||
color: PropTypes.string,
|
||||
hoverColor: PropTypes.string,
|
||||
onClick: PropTypes.func,
|
||||
};
|
||||
|
||||
export default DeviceIcon;
|
@ -0,0 +1,175 @@
|
||||
/* @flow */
|
||||
|
||||
import * as React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import QrReader from 'react-qr-reader';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import colors from 'config/colors';
|
||||
import icons from 'config/icons';
|
||||
|
||||
import { H2 } from 'components/Heading';
|
||||
import P from 'components/Paragraph';
|
||||
import Icon from 'components/Icon';
|
||||
import Link from 'components/Link';
|
||||
|
||||
import { parseUri } from 'utils/cryptoUriParser';
|
||||
import type { parsedURI } from 'utils/cryptoUriParser';
|
||||
import type { Props as BaseProps } from '../Container';
|
||||
|
||||
const Wrapper = styled.div`
|
||||
width: 90vw;
|
||||
max-width: 450px;
|
||||
padding: 30px 0px;
|
||||
`;
|
||||
|
||||
const Padding = styled.div`
|
||||
padding: 0px 48px;
|
||||
`;
|
||||
|
||||
const CloseLink = styled(Link)`
|
||||
position: absolute;
|
||||
right: 15px;
|
||||
top: 15px;
|
||||
`;
|
||||
|
||||
const CameraPlaceholder = styled(P)`
|
||||
text-align: center;
|
||||
padding: 10px 0;
|
||||
`;
|
||||
|
||||
const Error = styled.div`
|
||||
padding: 10px 0;
|
||||
`;
|
||||
|
||||
const ErrorTitle = styled(P)`
|
||||
text-align: center;
|
||||
color: ${colors.ERROR_PRIMARY};
|
||||
`;
|
||||
const ErrorMessage = styled.span`
|
||||
text-align: center;
|
||||
color: ${colors.TEXT_PRIMARY};
|
||||
`;
|
||||
|
||||
const StyledQrReader = styled(QrReader)`
|
||||
padding: 10px 0;
|
||||
`;
|
||||
|
||||
// TODO fix types
|
||||
type Props = {
|
||||
onScan: (data: parsedURI) => any,
|
||||
onError?: (error: any) => any,
|
||||
onCancel?: $ElementType<$ElementType<BaseProps, 'modalActions'>, 'onCancel'>;
|
||||
}
|
||||
|
||||
type State = {
|
||||
readerLoaded: boolean,
|
||||
error: any,
|
||||
};
|
||||
|
||||
class QrModal extends React.Component<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
readerLoaded: false,
|
||||
error: null,
|
||||
};
|
||||
}
|
||||
|
||||
onLoad = () => {
|
||||
this.setState({
|
||||
readerLoaded: true,
|
||||
});
|
||||
}
|
||||
|
||||
handleScan = (data: string) => {
|
||||
if (data) {
|
||||
try {
|
||||
const parsedUri = parseUri(data);
|
||||
if (parsedUri) {
|
||||
this.props.onScan(parsedUri);
|
||||
// reset error
|
||||
this.setState({
|
||||
error: null,
|
||||
});
|
||||
// close window
|
||||
this.handleCancel();
|
||||
}
|
||||
} catch (error) {
|
||||
this.handleError(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleError = (err: any) => {
|
||||
// log thrown error
|
||||
console.error(err);
|
||||
if (this.props.onError) {
|
||||
this.props.onError(err);
|
||||
}
|
||||
|
||||
if (err.name === 'NotAllowedError' || err.name === 'PermissionDeniedError'
|
||||
|| err.name === 'NotReadableError' || err.name === 'TrackStartError') {
|
||||
this.setState({
|
||||
error: 'Permission to access the camera was denied.',
|
||||
});
|
||||
} else if (err.name === 'NotFoundError' || err.name === 'DevicesNotFoundError') {
|
||||
this.setState({
|
||||
error: 'The camera was not recognized.',
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
error: 'Unknown error. See console logs for details.',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handleCancel = () => {
|
||||
if (this.props.onCancel) {
|
||||
this.props.onCancel();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Wrapper>
|
||||
<CloseLink onClick={this.handleCancel}>
|
||||
<Icon
|
||||
size={24}
|
||||
color={colors.TEXT_SECONDARY}
|
||||
icon={icons.CLOSE}
|
||||
/>
|
||||
</CloseLink>
|
||||
<Padding>
|
||||
<H2>Scan QR code</H2>
|
||||
{!this.state.readerLoaded && !this.state.error && <CameraPlaceholder>Waiting for camera...</CameraPlaceholder>}
|
||||
{this.state.error && (
|
||||
<Error>
|
||||
<ErrorTitle>Oops! Something went wrong!</ErrorTitle>
|
||||
<ErrorMessage>{this.state.error.toString()}</ErrorMessage>
|
||||
</Error>
|
||||
)}
|
||||
</Padding>
|
||||
{!this.state.error && (
|
||||
<StyledQrReader
|
||||
delay={500}
|
||||
onError={this.handleError}
|
||||
onScan={this.handleScan}
|
||||
onLoad={this.onLoad}
|
||||
style={{ width: '100%' }}
|
||||
showViewFinder={false}
|
||||
/>
|
||||
)}
|
||||
</Wrapper>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
QrModal.propTypes = {
|
||||
onScan: PropTypes.func.isRequired,
|
||||
onError: PropTypes.func,
|
||||
onCancel: PropTypes.func,
|
||||
};
|
||||
|
||||
export default QrModal;
|
@ -0,0 +1,85 @@
|
||||
/* @flow */
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import icons from 'config/icons';
|
||||
import { getOldWalletUrl } from 'utils/url';
|
||||
import colors from 'config/colors';
|
||||
|
||||
import { H2 } from 'components/Heading';
|
||||
import P from 'components/Paragraph';
|
||||
import Icon from 'components/Icon';
|
||||
import Button from 'components/Button';
|
||||
import Link from 'components/Link';
|
||||
|
||||
import type { TrezorDevice } from 'flowtype';
|
||||
import type { Props as BaseProps } from '../../Container';
|
||||
|
||||
type Props = {
|
||||
onReceiveConfirmation: $ElementType<$ElementType<BaseProps, 'modalActions'>, 'onReceiveConfirmation'>;
|
||||
device: ?TrezorDevice;
|
||||
}
|
||||
|
||||
const Wrapper = styled.div`
|
||||
max-width: 370px;
|
||||
padding: 30px 48px;
|
||||
`;
|
||||
|
||||
const StyledLink = styled(Link)`
|
||||
position: absolute;
|
||||
right: 15px;
|
||||
top: 15px;
|
||||
`;
|
||||
|
||||
const BackupButton = styled(Button)`
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
`;
|
||||
|
||||
const ProceedButton = styled(Button)`
|
||||
background: transparent;
|
||||
border-color: ${colors.WARNING_PRIMARY};
|
||||
color: ${colors.WARNING_PRIMARY};
|
||||
|
||||
&:focus,
|
||||
&:hover,
|
||||
&:active {
|
||||
color: ${colors.WHITE};
|
||||
background: ${colors.WARNING_PRIMARY};
|
||||
box-shadow: none;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledP = styled(P)`
|
||||
padding-bottom: 20px;
|
||||
`;
|
||||
|
||||
const Row = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
`;
|
||||
|
||||
const Confirmation = (props: Props) => (
|
||||
<Wrapper>
|
||||
<StyledLink onClick={() => props.onReceiveConfirmation(false)}>
|
||||
<Icon size={24} color={colors.TEXT_SECONDARY} icon={icons.CLOSE} />
|
||||
</StyledLink>
|
||||
<H2>Your Trezor is not backed up</H2>
|
||||
<Icon size={48} color={colors.WARNING_PRIMARY} icon={icons.WARNING} />
|
||||
<StyledP isSmaller>If your device is ever lost or damaged, your funds will be lost. Backup your device first, to protect your coins against such events.</StyledP>
|
||||
<Row>
|
||||
<Link href={`${getOldWalletUrl(props.device)}/?backup`}>
|
||||
<BackupButton onClick={() => props.onReceiveConfirmation(false)}>Create a backup in 3 minutes</BackupButton>
|
||||
</Link>
|
||||
<ProceedButton isWhite onClick={() => props.onReceiveConfirmation(true)}>Show address, I will take the risk</ProceedButton>
|
||||
</Row>
|
||||
</Wrapper>
|
||||
);
|
||||
|
||||
Confirmation.propTypes = {
|
||||
onReceiveConfirmation: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default Confirmation;
|
@ -0,0 +1,25 @@
|
||||
/* @flow */
|
||||
import * as React from 'react';
|
||||
import Notification from 'components/Notification';
|
||||
|
||||
import type { Props } from '../../index';
|
||||
|
||||
export default (props: Props) => {
|
||||
const { selectedDevice } = props.wallet;
|
||||
const needsBackup = selectedDevice && selectedDevice.features && selectedDevice.features.needs_backup;
|
||||
if (!needsBackup) return null;
|
||||
return (
|
||||
<Notification
|
||||
key="no-backup"
|
||||
type="warning"
|
||||
title="Your Trezor is not backed up!"
|
||||
message="If your device is ever lost or damaged, your funds will be lost. Backup your device first, to protect your coins against such events."
|
||||
actions={
|
||||
[{
|
||||
label: 'Create a backup',
|
||||
callback: props.routerActions.gotoBackup,
|
||||
}]
|
||||
}
|
||||
/>
|
||||
);
|
||||
};
|
@ -0,0 +1,5 @@
|
||||
export default {
|
||||
NEXT_WALLET: 'https://beta-wallet.trezor.io/next',
|
||||
OLD_WALLET: 'https://wallet.trezor.io',
|
||||
OLD_WALLET_BETA: 'https://beta-wallet.trezor.io',
|
||||
};
|
@ -1,67 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`device utils get status 1`] = `"disconnected"`;
|
||||
|
||||
exports[`device utils get status 2`] = `"unavailable"`;
|
||||
|
||||
exports[`device utils get status 3`] = `"unavailable"`;
|
||||
|
||||
exports[`device utils get status 4`] = `"connected"`;
|
||||
|
||||
exports[`device utils get status 5`] = `"unacquired"`;
|
||||
|
||||
exports[`device utils get status 6`] = `"used-in-other-window"`;
|
||||
|
||||
exports[`device utils get status color 1`] = `"#494949"`;
|
||||
|
||||
exports[`device utils get status color 2`] = `"#494949"`;
|
||||
|
||||
exports[`device utils get status color 3`] = `"#494949"`;
|
||||
|
||||
exports[`device utils get status color 4`] = `"#EB8A00"`;
|
||||
|
||||
exports[`device utils get status color 5`] = `"#01B757"`;
|
||||
|
||||
exports[`device utils get status color 6`] = `"#EB8A00"`;
|
||||
|
||||
exports[`device utils get status color 7`] = `"#ED1212"`;
|
||||
|
||||
exports[`device utils get status color 8`] = `"#ED1212"`;
|
||||
|
||||
exports[`device utils get status name 1`] = `"Status unknown"`;
|
||||
|
||||
exports[`device utils get status name 2`] = `"Status unknown"`;
|
||||
|
||||
exports[`device utils get status name 3`] = `"Status unknown"`;
|
||||
|
||||
exports[`device utils get status name 4`] = `"Used in other window"`;
|
||||
|
||||
exports[`device utils get status name 5`] = `"Connected"`;
|
||||
|
||||
exports[`device utils get status name 6`] = `"Used in other window"`;
|
||||
|
||||
exports[`device utils get status name 7`] = `"Disconnected"`;
|
||||
|
||||
exports[`device utils get status name 8`] = `"Unavailable"`;
|
||||
|
||||
exports[`device utils get version 1`] = `"1"`;
|
||||
|
||||
exports[`device utils get version 2`] = `"1"`;
|
||||
|
||||
exports[`device utils get version 3`] = `"1"`;
|
||||
|
||||
exports[`device utils get version 4`] = `"1"`;
|
||||
|
||||
exports[`device utils get version 5`] = `"1"`;
|
||||
|
||||
exports[`device utils get version 6`] = `"T"`;
|
||||
|
||||
exports[`device utils isDisabled 1`] = `false`;
|
||||
|
||||
exports[`device utils isDisabled 2`] = `true`;
|
||||
|
||||
exports[`device utils isWebUSB 1`] = `true`;
|
||||
|
||||
exports[`device utils isWebUSB 2`] = `false`;
|
||||
|
||||
exports[`device utils isWebUSB 3`] = `true`;
|
@ -1,45 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`eth utils calcGasPrice 1`] = `"89090990901"`;
|
||||
|
||||
exports[`eth utils decimalToHex 1`] = `"0"`;
|
||||
|
||||
exports[`eth utils decimalToHex 2`] = `"1"`;
|
||||
|
||||
exports[`eth utils decimalToHex 3`] = `"2"`;
|
||||
|
||||
exports[`eth utils decimalToHex 4`] = `"64"`;
|
||||
|
||||
exports[`eth utils decimalToHex 5`] = `"2540be3ff"`;
|
||||
|
||||
exports[`eth utils hexToDecimal 1`] = `"9999999999"`;
|
||||
|
||||
exports[`eth utils hexToDecimal 2`] = `"100"`;
|
||||
|
||||
exports[`eth utils hexToDecimal 3`] = `"2"`;
|
||||
|
||||
exports[`eth utils hexToDecimal 4`] = `"1"`;
|
||||
|
||||
exports[`eth utils hexToDecimal 5`] = `"0"`;
|
||||
|
||||
exports[`eth utils hexToDecimal 6`] = `"null"`;
|
||||
|
||||
exports[`eth utils padLeftEven 1`] = `"02540be3ff"`;
|
||||
|
||||
exports[`eth utils sanitizeHex 1`] = `"0x02540be3ff"`;
|
||||
|
||||
exports[`eth utils sanitizeHex 2`] = `"0x01"`;
|
||||
|
||||
exports[`eth utils sanitizeHex 3`] = `"0x02"`;
|
||||
|
||||
exports[`eth utils sanitizeHex 4`] = `"0x0100"`;
|
||||
|
||||
exports[`eth utils sanitizeHex 5`] = `"0x0999"`;
|
||||
|
||||
exports[`eth utils sanitizeHex 6`] = `""`;
|
||||
|
||||
exports[`eth utils strip 1`] = `""`;
|
||||
|
||||
exports[`eth utils strip 2`] = `"02540be3ff"`;
|
||||
|
||||
exports[`eth utils strip 3`] = `"02540be3ff"`;
|
@ -1,45 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`format utils btckb2satoshib 1`] = `0`;
|
||||
|
||||
exports[`format utils btckb2satoshib 2`] = `100000`;
|
||||
|
||||
exports[`format utils btckb2satoshib 3`] = `200000`;
|
||||
|
||||
exports[`format utils btckb2satoshib 4`] = `10000000`;
|
||||
|
||||
exports[`format utils btckb2satoshib 5`] = `99900000`;
|
||||
|
||||
exports[`format utils formatAmount 1`] = `"0 btc"`;
|
||||
|
||||
exports[`format utils formatAmount 2`] = `"10 mBTC"`;
|
||||
|
||||
exports[`format utils formatAmount 3`] = `"0.000005 mBTC"`;
|
||||
|
||||
exports[`format utils formatAmount 4`] = `"1e-8 eth"`;
|
||||
|
||||
exports[`format utils formatAmount 5`] = `"0.00099999 tau"`;
|
||||
|
||||
exports[`format utils formatTime 1`] = `"No time estimate"`;
|
||||
|
||||
exports[`format utils formatTime 2`] = `"1 minutes"`;
|
||||
|
||||
exports[`format utils formatTime 3`] = `"2 minutes"`;
|
||||
|
||||
exports[`format utils formatTime 4`] = `"1 hour 40 minutes"`;
|
||||
|
||||
exports[`format utils formatTime 5`] = `"16 hours 39 minutes"`;
|
||||
|
||||
exports[`format utils formatTime 6`] = `"45 minutes"`;
|
||||
|
||||
exports[`format utils hexToString 1`] = `"test"`;
|
||||
|
||||
exports[`format utils hexToString 2`] = `"0001"`;
|
||||
|
||||
exports[`format utils hexToString 3`] = `"test99999"`;
|
||||
|
||||
exports[`format utils stringToHex 1`] = `"0074006500730074"`;
|
||||
|
||||
exports[`format utils stringToHex 2`] = `"0030003000300031"`;
|
||||
|
||||
exports[`format utils stringToHex 3`] = `"007400650073007400390039003900390039"`;
|
@ -1,41 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`device utils get icon 1`] = `
|
||||
Array [
|
||||
"M693.024 330.944c-99.968-99.936-262.080-99.936-362.048 0s-99.968 262.112 0 362.080c99.968 100 262.144 99.936 362.048 0 99.968-99.904 99.968-262.176 0-362.080zM507.904 300.192c27.008 0 48.992 21.984 48.992 49.088 0 27.296-21.984 49.472-48.992 49.472-27.264 0-49.536-22.176-49.536-49.472 0-27.552 21.728-49.088 49.536-49.088zM586.656 660.8c0 10.304-4.96 15.328-15.264 15.328h-126.464c-10.304 0-15.328-5.024-15.328-15.328v-32.256c0-10.304 5.024-15.264 15.328-15.264h23.36v-136.064h-23.872c-10.304 0-15.264-5.024-15.264-15.328v-32.224c0-10.304 4.96-15.264 15.264-15.264h88.288c10.304 0 15.264 4.96 15.264 15.264v183.648h23.424c10.304 0 15.264 4.96 15.264 15.264v32.224z",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`device utils get icon 2`] = `
|
||||
Array [
|
||||
"M693.12 330.88c-46.317-46.267-110.276-74.88-180.919-74.88-141.385 0-256 114.615-256 256s114.615 256 256 256c70.642 0 134.602-28.613 180.921-74.882l-0.002 0.002c46.387-46.337 75.081-110.377 75.081-181.12s-28.694-134.783-75.079-181.118l-0.002-0.002zM494.080 344.32h53.12c16 0 18.24 9.28 18.24 14.72v10.24l-10.88 194.56c0 14.4-8 17.28-18.88 17.28h-28.16c-10.56 0-17.28-2.88-18.88-17.92l-10.88-193.92v-10.56c-1.28-4.8 2.24-14.080 16.32-14.080zM521.28 717.76c-0.095 0.001-0.207 0.001-0.319 0.001-27.747 0-50.24-22.493-50.24-50.24s22.493-50.24 50.24-50.24c27.747 0 50.24 22.493 50.24 50.24 0 0.112 0 0.224-0.001 0.336v-0.017c0 0 0 0.001 0 0.001 0 27.634-22.311 50.057-49.903 50.239h-0.017z",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`device utils get icon 3`] = `
|
||||
Array [
|
||||
"M795.616 735.008l-264.896-465.44c-10.272-18.080-27.168-18.080-37.504 0l-264.864 465.44c-10.272 18.176-1.696 32.992 19.040 32.992h529.184c20.8 0 29.376-14.816 19.040-32.992zM549.76 673.12c0 10.464-8.48 18.976-18.912 18.976h-37.792c-10.336 0-18.912-8.512-18.912-18.976v-37.952c0-10.464 8.576-18.976 18.912-18.976h37.792c10.4 0 18.912 8.544 18.912 18.976v37.952zM549.76 559.264c0 10.464-8.48 18.976-18.912 18.976h-37.792c-10.336 0-18.912-8.512-18.912-18.976v-113.856c0-10.464 8.576-18.976 18.912-18.976h37.792c10.4 0 18.912 8.544 18.912 18.976v113.856z",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`device utils get icon 4`] = `
|
||||
Array [
|
||||
"M692.8 313.92l-1.92-1.92c-6.246-7.057-15.326-11.484-25.44-11.484s-19.194 4.427-25.409 11.448l-0.031 0.036-196.48 224-3.84 1.6-3.84-1.92-48.64-57.28c-7.010-7.905-17.193-12.862-28.533-12.862-21.031 0-38.080 17.049-38.080 38.080 0 7.495 2.165 14.485 5.905 20.377l-0.092-0.155 100.8 148.16c5.391 8.036 14.386 13.292 24.618 13.44h8.662c17.251-0.146 32.385-9.075 41.163-22.529l0.117-0.191 195.2-296.32c4.473-6.632 7.141-14.803 7.141-23.597 0-11.162-4.297-21.32-11.326-28.911l0.025 0.028z",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`device utils get icon 5`] = `undefined`;
|
||||
|
||||
exports[`device utils get icon 6`] = `undefined`;
|
||||
|
||||
exports[`device utils get status 1`] = `"#1E7FF0"`;
|
||||
|
||||
exports[`device utils get status 2`] = `"#ED1212"`;
|
||||
|
||||
exports[`device utils get status 3`] = `"#EB8A00"`;
|
||||
|
||||
exports[`device utils get status 4`] = `"#01B757"`;
|
||||
|
||||
exports[`device utils get status 5`] = `null`;
|
||||
|
||||
exports[`device utils get status 6`] = `null`;
|
@ -1,112 +1,87 @@
|
||||
import * as dUtils from 'utils/device';
|
||||
import * as utils from 'utils/device';
|
||||
|
||||
describe('device utils', () => {
|
||||
it('get status', () => {
|
||||
const deviceMock = [
|
||||
{
|
||||
connected: false,
|
||||
},
|
||||
{
|
||||
connected: true,
|
||||
available: false,
|
||||
},
|
||||
{
|
||||
connected: true,
|
||||
available: false,
|
||||
type: null,
|
||||
},
|
||||
{
|
||||
connected: true,
|
||||
available: true,
|
||||
type: 'acquired',
|
||||
},
|
||||
{
|
||||
connected: true,
|
||||
available: true,
|
||||
type: 'unacquired',
|
||||
},
|
||||
{
|
||||
connected: true,
|
||||
available: true,
|
||||
type: 'acquired',
|
||||
status: 'occupied',
|
||||
},
|
||||
];
|
||||
expect(utils.getStatus({ connected: false }))
|
||||
.toBe('disconnected');
|
||||
|
||||
expect(utils.getStatus({ connected: true, available: false }))
|
||||
.toBe('unavailable');
|
||||
|
||||
expect(utils.getStatus({
|
||||
connected: true,
|
||||
available: false,
|
||||
type: null,
|
||||
})).toBe('unavailable');
|
||||
|
||||
deviceMock.forEach((device) => {
|
||||
expect(dUtils.getStatus(device)).toMatchSnapshot();
|
||||
});
|
||||
expect(utils.getStatus({
|
||||
connected: true,
|
||||
available: true,
|
||||
type: 'acquired',
|
||||
})).toBe('connected');
|
||||
|
||||
expect(utils.getStatus({
|
||||
connected: true,
|
||||
available: true,
|
||||
type: 'unacquired',
|
||||
})).toBe('unacquired');
|
||||
|
||||
expect(utils.getStatus({
|
||||
connected: true,
|
||||
available: true,
|
||||
type: 'acquired',
|
||||
status: 'occupied',
|
||||
})).toBe('used-in-other-window');
|
||||
});
|
||||
|
||||
it('isWebUSB', () => {
|
||||
const data = [
|
||||
{ transport: { type: 'ParallelTransport', version: 'webusb' } },
|
||||
{ transport: { type: null, version: 'aaaaaa' } },
|
||||
{ transport: { type: 'ParallelTransport', version: 'webusb' } },
|
||||
];
|
||||
|
||||
data.forEach((item) => {
|
||||
expect(dUtils.isWebUSB(item.transport)).toMatchSnapshot();
|
||||
});
|
||||
expect(utils.isWebUSB({ type: 'webusb', version: '1.6.0' })).toBe(true);
|
||||
expect(utils.isWebUSB({ type: 'aaaa', version: 'aaaaaa' })).toBe(false);
|
||||
expect(utils.isWebUSB({ type: 'webusb' })).toBe(true);
|
||||
});
|
||||
|
||||
it('isDisabled', () => {
|
||||
const data = [
|
||||
{ selectedDevice: { features: null }, devices: [1, 2, 3], transport: { version: 'webusb' } },
|
||||
{ selectedDevice: { features: null }, devices: [], transport: { version: 'test' } },
|
||||
];
|
||||
expect(utils.isDisabled(
|
||||
{ selectedDevice: { features: null } },
|
||||
[1, 2, 3],
|
||||
{
|
||||
version: 'webusb',
|
||||
},
|
||||
)).toBe(false);
|
||||
|
||||
data.forEach((item) => {
|
||||
expect(dUtils.isDisabled(item.selectedDevice, item.devices, item.transport)).toMatchSnapshot();
|
||||
});
|
||||
expect(utils.isDisabled(
|
||||
{ features: null }, [], { version: 'test' },
|
||||
)).toBe(true);
|
||||
});
|
||||
|
||||
it('get version', () => {
|
||||
const deviceMock = [
|
||||
{ },
|
||||
{ features: {} },
|
||||
{ features: { major_version: null } },
|
||||
{ features: { major_version: 0 } },
|
||||
{ features: { major_version: 1 } },
|
||||
{ features: { major_version: 2 } },
|
||||
];
|
||||
|
||||
deviceMock.forEach((device) => {
|
||||
expect(dUtils.getVersion(device)).toMatchSnapshot();
|
||||
});
|
||||
expect(utils.getVersion({})).toBe('One');
|
||||
expect(utils.getVersion({ features: {} })).toBe('One');
|
||||
expect(utils.getVersion({ features: { major_version: null } })).toBe('One');
|
||||
expect(utils.getVersion({ features: { major_version: 0 } })).toBe('One');
|
||||
expect(utils.getVersion({ features: { major_version: 1 } })).toBe('One');
|
||||
expect(utils.getVersion({ features: { major_version: 2 } })).toBe('T');
|
||||
});
|
||||
|
||||
it('get status color', () => {
|
||||
const entry = [
|
||||
0,
|
||||
null,
|
||||
'sdsdsdsd',
|
||||
'used-in-other-window',
|
||||
'connected',
|
||||
'unacquired',
|
||||
'disconnected',
|
||||
'unavailable',
|
||||
];
|
||||
|
||||
entry.forEach((status) => {
|
||||
expect(dUtils.getStatusColor(status)).toMatchSnapshot();
|
||||
});
|
||||
expect(utils.getStatusColor(0)).toBe('#494949');
|
||||
expect(utils.getStatusColor(null)).toBe('#494949');
|
||||
expect(utils.getStatusColor('sdsdsdsd')).toBe('#494949');
|
||||
expect(utils.getStatusColor('used-in-other-window')).toBe('#EB8A00');
|
||||
expect(utils.getStatusColor('connected')).toBe('#01B757');
|
||||
expect(utils.getStatusColor('unacquired')).toBe('#EB8A00');
|
||||
expect(utils.getStatusColor('disconnected')).toBe('#ED1212');
|
||||
expect(utils.getStatusColor('unavailable')).toBe('#ED1212');
|
||||
});
|
||||
|
||||
it('get status name', () => {
|
||||
const entry = [
|
||||
0,
|
||||
null,
|
||||
'sdsdsdsd',
|
||||
'used-in-other-window',
|
||||
'connected',
|
||||
'unacquired',
|
||||
'disconnected',
|
||||
'unavailable',
|
||||
];
|
||||
|
||||
entry.forEach((status) => {
|
||||
expect(dUtils.getStatusName(status)).toMatchSnapshot();
|
||||
});
|
||||
expect(utils.getStatusName(0)).toBe('Status unknown');
|
||||
expect(utils.getStatusName(null)).toBe('Status unknown');
|
||||
expect(utils.getStatusName('sdsdsdsd')).toBe('Status unknown');
|
||||
expect(utils.getStatusName('used-in-other-window')).toBe('Used in other window');
|
||||
expect(utils.getStatusName('connected')).toBe('Connected');
|
||||
expect(utils.getStatusName('unacquired')).toBe('Used in other window');
|
||||
expect(utils.getStatusName('disconnected')).toBe('Disconnected');
|
||||
expect(utils.getStatusName('unavailable')).toBe('Unavailable');
|
||||
});
|
||||
});
|
||||
});
|
@ -1,53 +1,44 @@
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as ethUtils from '../ethUtils';
|
||||
import * as utils from '../ethUtils';
|
||||
|
||||
describe('eth utils', () => {
|
||||
it('decimalToHex', () => {
|
||||
const input = [0, 1, 2, 100, 9999999999];
|
||||
|
||||
input.forEach((entry) => {
|
||||
expect(ethUtils.decimalToHex(entry)).toMatchSnapshot();
|
||||
});
|
||||
expect(utils.decimalToHex(0)).toBe('0');
|
||||
expect(utils.decimalToHex(1)).toBe('1');
|
||||
expect(utils.decimalToHex(2)).toBe('2');
|
||||
expect(utils.decimalToHex(100)).toBe('64');
|
||||
expect(utils.decimalToHex(9999999999)).toBe('2540be3ff');
|
||||
});
|
||||
|
||||
// TODO: decimal as string ?????
|
||||
it('hexToDecimal', () => {
|
||||
const input = ['2540be3ff', '64', '2', '1', '0', ''];
|
||||
|
||||
input.forEach((entry) => {
|
||||
expect(ethUtils.hexToDecimal(entry)).toMatchSnapshot();
|
||||
});
|
||||
expect(utils.hexToDecimal('2540be3ff')).toBe('9999999999');
|
||||
expect(utils.hexToDecimal(64)).toBe('100');
|
||||
expect(utils.hexToDecimal(2)).toBe('2');
|
||||
expect(utils.hexToDecimal(1)).toBe('1');
|
||||
expect(utils.hexToDecimal(0)).toBe('0');
|
||||
});
|
||||
|
||||
it('padLeftEven', () => {
|
||||
const input = ['2540be3ff'];
|
||||
|
||||
input.forEach((entry) => {
|
||||
expect(ethUtils.padLeftEven(entry)).toMatchSnapshot();
|
||||
});
|
||||
expect(utils.padLeftEven('2540be3ff')).toBe('02540be3ff');
|
||||
});
|
||||
|
||||
it('sanitizeHex', () => {
|
||||
const input = ['0x2540be3ff', '1', '2', '100', '999', ''];
|
||||
|
||||
input.forEach((entry) => {
|
||||
expect(ethUtils.sanitizeHex(entry)).toMatchSnapshot();
|
||||
});
|
||||
expect(utils.sanitizeHex('0x2540be3ff')).toBe('0x02540be3ff');
|
||||
expect(utils.sanitizeHex('1')).toBe('0x01');
|
||||
expect(utils.sanitizeHex('2')).toBe('0x02');
|
||||
expect(utils.sanitizeHex('100')).toBe('0x0100');
|
||||
expect(utils.sanitizeHex('999')).toBe('0x0999');
|
||||
expect(utils.sanitizeHex('')).toBe('');
|
||||
});
|
||||
|
||||
|
||||
it('strip', () => {
|
||||
const input = ['0x', '0x2540be3ff', '2540be3ff'];
|
||||
|
||||
input.forEach((entry) => {
|
||||
expect(ethUtils.strip(entry)).toMatchSnapshot();
|
||||
});
|
||||
expect(utils.strip('0x')).toBe('');
|
||||
expect(utils.strip('0x2540be3ff')).toBe('02540be3ff');
|
||||
expect(utils.strip('2540be3ff')).toBe('02540be3ff');
|
||||
});
|
||||
|
||||
it('calcGasPrice', () => {
|
||||
const input = [{ price: new BigNumber(9898998989), limit: '9' }];
|
||||
|
||||
input.forEach((entry) => {
|
||||
expect(ethUtils.calcGasPrice(entry.price, entry.limit)).toMatchSnapshot();
|
||||
});
|
||||
it('calculate gas price', () => {
|
||||
expect(utils.calcGasPrice(new BigNumber(9898998989), 9)).toBe('89090990901');
|
||||
});
|
||||
});
|
||||
|
@ -1,49 +1,41 @@
|
||||
import * as formatUtils from '../formatUtils';
|
||||
import * as utils from '../formatUtils';
|
||||
|
||||
describe('format utils', () => {
|
||||
// TODO: check this weird function
|
||||
it('formatAmount', () => {
|
||||
const input = [
|
||||
{ amount: 0, coinInfo: { isBitcoin: true, currencyUnits: 'mbtc', shortcut: 'btc' } },
|
||||
{ amount: 1000000, coinInfo: { isBitcoin: true, currencyUnits: 'mbtc', shortcut: 'btc' } },
|
||||
{ amount: 0.5, coinInfo: { isBitcoin: true, currencyUnits: 'mbtc', shortcut: 'btc' } },
|
||||
{ amount: 1, coinInfo: { isBitcoin: false, shortcut: 'eth' } },
|
||||
{ amount: 99999, coinInfo: { isBitcoin: false, shortcut: 'tau' } },
|
||||
];
|
||||
|
||||
input.forEach((entry) => {
|
||||
expect(formatUtils.formatAmount(entry.amount, entry.coinInfo, entry.coinInfo.currencyUnits)).toMatchSnapshot();
|
||||
});
|
||||
expect(utils.formatAmount(0, { isBitcoin: false, shortcut: 'mbtc' }, 'mbtc')).toBe('0 mbtc');
|
||||
expect(utils.formatAmount(1000000, { isBitcoin: true }, 'mbtc')).toBe('10 mBTC');
|
||||
expect(utils.formatAmount(0.5, { isBitcoin: true }, 'mbtc')).toBe('0.000005 mBTC');
|
||||
expect(utils.formatAmount(1, { isBitcoin: false, shortcut: 'eth' }, null)).toBe('1e-8 eth');
|
||||
expect(utils.formatAmount(99999, { isBitcoin: false, shortcut: 'tau' }, null)).toBe('0.00099999 tau');
|
||||
});
|
||||
|
||||
it('formatTime', () => {
|
||||
const input = [0, 1, 2, 100, 999, 45];
|
||||
|
||||
input.forEach((entry) => {
|
||||
expect(formatUtils.formatTime(entry)).toMatchSnapshot();
|
||||
});
|
||||
it('format time', () => {
|
||||
expect(utils.formatTime(0)).toBe('No time estimate');
|
||||
expect(utils.formatTime(1)).toBe('1 minutes'); // TODO: should be minute
|
||||
expect(utils.formatTime(2)).toBe('2 minutes');
|
||||
expect(utils.formatTime(45)).toBe('45 minutes');
|
||||
expect(utils.formatTime(100)).toBe('1 hour 40 minutes');
|
||||
expect(utils.formatTime(999)).toBe('16 hours 39 minutes');
|
||||
});
|
||||
|
||||
it('btckb2satoshib', () => {
|
||||
const input = [0, 1, 2, 100, 999];
|
||||
|
||||
input.forEach((entry) => {
|
||||
expect(formatUtils.btckb2satoshib(entry)).toMatchSnapshot();
|
||||
});
|
||||
expect(utils.btckb2satoshib(0)).toBe(0);
|
||||
expect(utils.btckb2satoshib(1)).toBe(100000);
|
||||
expect(utils.btckb2satoshib(2)).toBe(200000);
|
||||
expect(utils.btckb2satoshib(100)).toBe(10000000);
|
||||
expect(utils.btckb2satoshib(999)).toBe(99900000);
|
||||
});
|
||||
|
||||
it('stringToHex', () => {
|
||||
const input = ['test', '0001', 'test99999'];
|
||||
|
||||
input.forEach((entry) => {
|
||||
expect(formatUtils.stringToHex(entry)).toMatchSnapshot();
|
||||
});
|
||||
it('string to hex', () => {
|
||||
expect(utils.stringToHex('test')).toBe('0074006500730074');
|
||||
expect(utils.stringToHex('0001')).toBe('0030003000300031');
|
||||
expect(utils.stringToHex('test99999')).toBe('007400650073007400390039003900390039');
|
||||
});
|
||||
|
||||
it('hexToString', () => {
|
||||
const input = ['0074006500730074', '0030003000300031', '007400650073007400390039003900390039'];
|
||||
|
||||
input.forEach((entry) => {
|
||||
expect(formatUtils.hexToString(entry)).toMatchSnapshot();
|
||||
});
|
||||
it('hex to string', () => {
|
||||
expect(utils.hexToString('0074006500730074')).toBe('test');
|
||||
expect(utils.hexToString('0030003000300031')).toBe('0001');
|
||||
expect(utils.hexToString('007400650073007400390039003900390039')).toBe('test99999');
|
||||
});
|
||||
});
|
||||
|
@ -1,32 +1,12 @@
|
||||
import * as nUtils from 'utils/notification';
|
||||
import * as utils from 'utils/notification';
|
||||
|
||||
describe('device utils', () => {
|
||||
it('get status', () => {
|
||||
const types = [
|
||||
'info',
|
||||
'error',
|
||||
'warning',
|
||||
'success',
|
||||
'kdsjflds',
|
||||
'',
|
||||
];
|
||||
|
||||
types.forEach((type) => {
|
||||
expect(nUtils.getPrimaryColor(type)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
it('get icon', () => {
|
||||
const types = [
|
||||
'info',
|
||||
'error',
|
||||
'warning',
|
||||
'success',
|
||||
'kdsjflds',
|
||||
'',
|
||||
];
|
||||
|
||||
types.forEach((type) => {
|
||||
expect(nUtils.getIcon(type)).toMatchSnapshot();
|
||||
});
|
||||
describe('notification utils', () => {
|
||||
it('get colors from status', () => {
|
||||
expect(utils.getPrimaryColor('info')).toBe('#1E7FF0');
|
||||
expect(utils.getPrimaryColor('warning')).toBe('#EB8A00');
|
||||
expect(utils.getPrimaryColor('error')).toBe('#ED1212');
|
||||
expect(utils.getPrimaryColor('success')).toBe('#01B757');
|
||||
expect(utils.getPrimaryColor('kdsjflds')).toBe(null);
|
||||
expect(utils.getPrimaryColor('')).toBe(null);
|
||||
});
|
||||
});
|
||||
|
@ -0,0 +1,39 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
/* eslint-disable prefer-destructuring */
|
||||
/* @flow */
|
||||
|
||||
// copy paste from mytrezor (old wallet) https://github.com/satoshilabs/mytrezor/blob/87f8a8d9ca82a27b3941c5ec0f399079903f2bfd/app/components/address-input/address-input.js
|
||||
|
||||
export type parsedURI = {
|
||||
address: string,
|
||||
amount: ?string,
|
||||
};
|
||||
|
||||
// Parse a string read from a bitcoin QR code into an object
|
||||
export const parseUri = (uri: string): ?parsedURI => {
|
||||
const str = stripPrefix(uri);
|
||||
const query: Array<string> = str.split('?');
|
||||
const values: Object = (query.length > 1) ? parseQuery(query[1]) : {};
|
||||
values.address = query[0];
|
||||
|
||||
return values;
|
||||
};
|
||||
|
||||
const stripPrefix = (str: string): string => {
|
||||
if (!str.match(':')) {
|
||||
return str;
|
||||
}
|
||||
const parts = str.split(':');
|
||||
parts.shift();
|
||||
return parts.join('');
|
||||
};
|
||||
|
||||
// Parse URL query string (like 'foo=bar&baz=1337) into an object
|
||||
const parseQuery = (str: string): {} => str.split('&')
|
||||
.map(val => val.split('='))
|
||||
.reduce((vals, pair) => {
|
||||
if (pair.length > 1) {
|
||||
vals[pair[0]] = pair[1];
|
||||
}
|
||||
return vals;
|
||||
}, {});
|
@ -0,0 +1,24 @@
|
||||
/* @flow */
|
||||
import urlConstants from 'constants/urls';
|
||||
import type { TrezorDevice } from 'flowtype';
|
||||
|
||||
const getOldWalletUrl = (device: ?TrezorDevice): string => {
|
||||
if (!device || !device.firmwareRelease) return urlConstants.OLD_WALLET_BETA;
|
||||
const release = device.firmwareRelease;
|
||||
const url = release.channel === 'beta' ? urlConstants.OLD_WALLET_BETA : urlConstants.OLD_WALLET;
|
||||
return url;
|
||||
};
|
||||
|
||||
// TODO: use uri template to build urls
|
||||
const getOldWalletReleaseUrl = (device: ?TrezorDevice): string => {
|
||||
if (!device || !device.firmwareRelease) return urlConstants.OLD_WALLET_BETA;
|
||||
const release = device.firmwareRelease;
|
||||
const url = getOldWalletUrl(device);
|
||||
const version = release.version.join('.');
|
||||
return `${url}?fw=${version}`;
|
||||
};
|
||||
|
||||
export {
|
||||
getOldWalletUrl,
|
||||
getOldWalletReleaseUrl,
|
||||
};
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue