mirror of
https://github.com/trezor/trezor-wallet
synced 2025-07-05 22:32:33 +00:00
merge
This commit is contained in:
commit
851c7f23cb
@ -43,7 +43,7 @@
|
|||||||
"settings": {
|
"settings": {
|
||||||
"import/resolver": {
|
"import/resolver": {
|
||||||
"babel-module": {}
|
"babel-module": {}
|
||||||
},
|
},
|
||||||
"import/ignore": [
|
"import/ignore": [
|
||||||
"\\.(scss|less|css)$"
|
"\\.(scss|less|css)$"
|
||||||
]
|
]
|
||||||
|
@ -41,6 +41,8 @@ build beta:
|
|||||||
script:
|
script:
|
||||||
- yarn install
|
- yarn install
|
||||||
- yarn run build:beta
|
- yarn run build:beta
|
||||||
|
only:
|
||||||
|
- beta
|
||||||
artifacts:
|
artifacts:
|
||||||
expire_in: 1 week
|
expire_in: 1 week
|
||||||
paths:
|
paths:
|
||||||
@ -52,6 +54,8 @@ build stable:
|
|||||||
script:
|
script:
|
||||||
- yarn install
|
- yarn install
|
||||||
- yarn run build:stable
|
- yarn run build:stable
|
||||||
|
only:
|
||||||
|
- stable
|
||||||
artifacts:
|
artifacts:
|
||||||
expire_in: 1 week
|
expire_in: 1 week
|
||||||
paths:
|
paths:
|
||||||
@ -64,6 +68,9 @@ deploy review:
|
|||||||
GIT_STRATEGY: none
|
GIT_STRATEGY: none
|
||||||
dependencies:
|
dependencies:
|
||||||
- build development
|
- build development
|
||||||
|
environment:
|
||||||
|
name: $CI_BUILD_REF_NAME
|
||||||
|
url: $BASE_REVIEW_URL/$CI_BUILD_REF_NAME
|
||||||
script:
|
script:
|
||||||
- echo "Deploy a review app"
|
- echo "Deploy a review app"
|
||||||
- '[ -z "${DEPLOY_BASE_DIR}" ] && echo "Deploy base dir cannot be empty" && exit 255'
|
- '[ -z "${DEPLOY_BASE_DIR}" ] && echo "Deploy base dir cannot be empty" && exit 255'
|
||||||
|
22
CHANGELOG.md
Normal file
22
CHANGELOG.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# 1.0.2-beta
|
||||||
|
- Fiat rates from coingecko (https://github.com/trezor/trezor-wallet/pull/242)
|
||||||
|
- firmware update link to beta-wallet (https://github.com/trezor/trezor-wallet/commit/b9b7d2d076f2d4c59ae2e055dc140cda6aaa5512)
|
||||||
|
- set default gas limit button
|
||||||
|
- update list of ETH and ETC tokens
|
||||||
|
- added 1 click to select value in input (https://github.com/trezor/trezor-wallet/issues/251)
|
||||||
|
- added account loader (https://github.com/trezor/trezor-wallet/pull/225)
|
||||||
|
|
||||||
|
# 1.0.1-beta
|
||||||
|
__added__
|
||||||
|
- DigiByte in coin menu
|
||||||
|
- blocking device with seedless setup
|
||||||
|
|
||||||
|
__fixed__
|
||||||
|
- token input in "Account/Summary" (https://github.com/trezor/trezor-wallet/issues/235)
|
||||||
|
- "Go to your standard wallet" button in passphrase modal (https://github.com/trezor/trezor-wallet/issues/222)
|
||||||
|
- Double click on "show passphrase" (https://github.com/trezor/trezor-wallet/issues/221)
|
||||||
|
- images preloader for offline status (https://github.com/trezor/trezor-wallet/issues/218)
|
||||||
|
|
||||||
|
|
||||||
|
# 1.0.0-beta
|
||||||
|
- first release
|
@ -70,7 +70,7 @@
|
|||||||
"styled-components": "^3.4.9",
|
"styled-components": "^3.4.9",
|
||||||
"styled-media-query": "^2.0.2",
|
"styled-media-query": "^2.0.2",
|
||||||
"styled-normalize": "^8.0.0",
|
"styled-normalize": "^8.0.0",
|
||||||
"trezor-connect": "6.0.0",
|
"trezor-connect": "6.0.2",
|
||||||
"web3": "1.0.0-beta.35",
|
"web3": "1.0.0-beta.35",
|
||||||
"webpack": "^4.16.3",
|
"webpack": "^4.16.3",
|
||||||
"webpack-build-notifier": "^0.1.29",
|
"webpack-build-notifier": "^0.1.29",
|
||||||
|
@ -59,11 +59,11 @@
|
|||||||
"fiatValueTickers": [
|
"fiatValueTickers": [
|
||||||
{
|
{
|
||||||
"network": "eth",
|
"network": "eth",
|
||||||
"url": "https://api.coinmarketcap.com/v1/ticker/ethereum/"
|
"url": "https://api.coingecko.com/api/v3/coins/ethereum"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"network": "etc",
|
"network": "etc",
|
||||||
"url": "https://api.coinmarketcap.com/v1/ticker/ethereum-classic/"
|
"url": "https://api.coingecko.com/api/v3/coins/ethereum-classic"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"address": "0x6F6DEb5db0C4994A8283A01D6CFeEB27Fc3bBe9C",
|
"address": "0x085fb4f24031EAedbC2B611AA528f22343eB52Db",
|
||||||
"name": "SmartBillions",
|
"decimals": 8,
|
||||||
"symbol": "Smart",
|
"name": "BEC",
|
||||||
"decimals": 0
|
"symbol": "BEC"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"address": "0x5ace17f87c7391e5792a7683069a8025b83bbd85",
|
"address": "0x6ADa6F48C815689502C43eC1a59F1b5DD3C04E1F",
|
||||||
"name": "SmartBillions Token",
|
"decimals": 18,
|
||||||
"symbol": "PLAY",
|
"name": "UniversalCoin",
|
||||||
"decimals": 0
|
"symbol": "UNV"
|
||||||
}
|
}
|
||||||
]
|
]
|
File diff suppressed because it is too large
Load Diff
@ -38,31 +38,87 @@ export const dispose = (): Action => ({
|
|||||||
type: ACCOUNT.DISPOSE,
|
type: ACCOUNT.DISPOSE,
|
||||||
});
|
});
|
||||||
|
|
||||||
const getAccountStatus = (state: State, selectedAccount: SelectedAccountState): ?AccountStatus => {
|
const getAccountLoader = (state: State, selectedAccount: SelectedAccountState): ?AccountStatus => {
|
||||||
const device = state.wallet.selectedDevice;
|
const device = state.wallet.selectedDevice;
|
||||||
if (!device || !device.state) {
|
|
||||||
return {
|
|
||||||
type: 'loader-progress',
|
|
||||||
title: 'Loading device...',
|
|
||||||
shouldRender: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
account,
|
account,
|
||||||
discovery,
|
discovery,
|
||||||
network,
|
network,
|
||||||
} = selectedAccount;
|
} = selectedAccount;
|
||||||
|
|
||||||
|
if (!device || !device.state) {
|
||||||
|
return {
|
||||||
|
type: 'progress',
|
||||||
|
title: 'Loading device...',
|
||||||
|
shouldRender: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// corner case: accountState didn't finish loading state after LOCATION_CHANGE action
|
// corner case: accountState didn't finish loading state after LOCATION_CHANGE action
|
||||||
if (!network) {
|
if (!network) {
|
||||||
return {
|
return {
|
||||||
type: 'loader-progress',
|
type: 'progress',
|
||||||
title: 'Loading account state...',
|
title: 'Loading account state...',
|
||||||
shouldRender: false,
|
shouldRender: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (account) return null;
|
||||||
|
// account not found (yet). checking why...
|
||||||
|
|
||||||
|
if (!discovery || (discovery.waitingForDevice || discovery.interrupted)) {
|
||||||
|
if (device.connected) {
|
||||||
|
// case 1: device is connected but discovery not started yet (probably waiting for auth)
|
||||||
|
if (device.available) {
|
||||||
|
return {
|
||||||
|
type: 'progress',
|
||||||
|
title: 'Authenticating device...',
|
||||||
|
shouldRender: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// case 2: device is unavailable (created with different passphrase settings) account cannot be accessed
|
||||||
|
// this is related to device instance in url, it's not used for now (device clones are disabled)
|
||||||
|
return {
|
||||||
|
type: 'info',
|
||||||
|
title: `Device ${device.instanceLabel} is unavailable`,
|
||||||
|
message: 'Change passphrase settings to use this device',
|
||||||
|
shouldRender: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// case 3: device is disconnected
|
||||||
|
return {
|
||||||
|
type: 'info',
|
||||||
|
title: `Device ${device.instanceLabel} is disconnected`,
|
||||||
|
message: 'Connect device to load accounts',
|
||||||
|
shouldRender: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (discovery.completed) {
|
||||||
|
// case 4: account not found and discovery is completed
|
||||||
|
return {
|
||||||
|
type: 'info',
|
||||||
|
title: 'Account does not exist',
|
||||||
|
shouldRender: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// case default: account information isn't loaded yet
|
||||||
|
return {
|
||||||
|
type: 'progress',
|
||||||
|
title: 'Loading account',
|
||||||
|
shouldRender: false,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const getAccountNotification = (state: State, selectedAccount: SelectedAccountState): ?AccountStatus => {
|
||||||
|
const device = state.wallet.selectedDevice;
|
||||||
|
const { account, network, discovery } = selectedAccount;
|
||||||
|
if (!device || !network) return null;
|
||||||
|
|
||||||
|
// case 1: backend status
|
||||||
const blockchain = state.blockchain.find(b => b.shortcut === network.shortcut);
|
const blockchain = state.blockchain.find(b => b.shortcut === network.shortcut);
|
||||||
if (blockchain && !blockchain.connected) {
|
if (blockchain && !blockchain.connected) {
|
||||||
return {
|
return {
|
||||||
@ -72,47 +128,16 @@ const getAccountStatus = (state: State, selectedAccount: SelectedAccountState):
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// account not found (yet). checking why...
|
// case 2: account does exists and it's visible but shouldn't be active
|
||||||
if (!account) {
|
if (account && discovery && !discovery.completed && !discovery.waitingForDevice) {
|
||||||
if (!discovery || (discovery.waitingForDevice || discovery.interrupted)) {
|
return {
|
||||||
if (device.connected) {
|
type: 'info',
|
||||||
// case 1: device is connected but discovery not started yet (probably waiting for auth)
|
title: 'Loading other accounts...',
|
||||||
if (device.available) {
|
shouldRender: true,
|
||||||
return {
|
};
|
||||||
type: 'loader-progress',
|
|
||||||
title: 'Authenticating device...',
|
|
||||||
shouldRender: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// case 2: device is unavailable (created with different passphrase settings) account cannot be accessed
|
|
||||||
return {
|
|
||||||
type: 'loader-info',
|
|
||||||
title: `Device ${device.instanceLabel} is unavailable`,
|
|
||||||
message: 'Change passphrase settings to use this device',
|
|
||||||
shouldRender: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// case 3: device is disconnected
|
|
||||||
return {
|
|
||||||
type: 'loader-info',
|
|
||||||
title: `Device ${device.instanceLabel} is disconnected`,
|
|
||||||
message: 'Connect device to load accounts',
|
|
||||||
shouldRender: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (discovery.completed) {
|
|
||||||
// case 4: account not found and discovery is completed
|
|
||||||
return {
|
|
||||||
type: 'loader-info',
|
|
||||||
title: 'Account does not exist',
|
|
||||||
shouldRender: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Additional status: account does exists and it's visible but shouldn't be active
|
// case 3: account does exists and device is disconnected
|
||||||
if (!device.connected) {
|
if (!device.connected) {
|
||||||
return {
|
return {
|
||||||
type: 'info',
|
type: 'info',
|
||||||
@ -121,6 +146,8 @@ const getAccountStatus = (state: State, selectedAccount: SelectedAccountState):
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// case 4: account does exists and device is unavailable (created with different passphrase settings) account cannot be accessed
|
||||||
|
// this is related to device instance in url, it's not used for now (device clones are disabled)
|
||||||
if (!device.available) {
|
if (!device.available) {
|
||||||
return {
|
return {
|
||||||
type: 'info',
|
type: 'info',
|
||||||
@ -130,6 +157,7 @@ const getAccountStatus = (state: State, selectedAccount: SelectedAccountState):
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// case default
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -153,13 +181,18 @@ const actions = [
|
|||||||
export const observe = (prevState: State, action: Action): PayloadAction<boolean> => (dispatch: Dispatch, getState: GetState): boolean => {
|
export const observe = (prevState: State, action: Action): PayloadAction<boolean> => (dispatch: Dispatch, getState: GetState): boolean => {
|
||||||
// ignore not listed actions
|
// ignore not listed actions
|
||||||
if (actions.indexOf(action.type) < 0) return false;
|
if (actions.indexOf(action.type) < 0) return false;
|
||||||
|
|
||||||
const state: State = getState();
|
const state: State = getState();
|
||||||
const notification = {
|
const notification = {
|
||||||
type: null,
|
type: null,
|
||||||
message: null,
|
message: null,
|
||||||
title: null,
|
title: null,
|
||||||
};
|
};
|
||||||
|
const loader = {
|
||||||
|
type: null,
|
||||||
|
message: null,
|
||||||
|
title: null,
|
||||||
|
};
|
||||||
|
|
||||||
const { location } = state.router;
|
const { location } = state.router;
|
||||||
// displayed route is not an account route
|
// displayed route is not an account route
|
||||||
if (!location.state.account) return false;
|
if (!location.state.account) return false;
|
||||||
@ -180,13 +213,18 @@ export const observe = (prevState: State, action: Action): PayloadAction<boolean
|
|||||||
tokens,
|
tokens,
|
||||||
pending,
|
pending,
|
||||||
notification,
|
notification,
|
||||||
|
loader,
|
||||||
shouldRender: false,
|
shouldRender: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
// get "selectedAccount" status from newState
|
// get "selectedAccount" status from newState
|
||||||
const status = getAccountStatus(state, newState);
|
const statusNotification = getAccountNotification(state, newState);
|
||||||
newState.notification = status || notification;
|
const statusLoader = getAccountLoader(state, newState);
|
||||||
newState.shouldRender = status ? status.shouldRender : true;
|
const shouldRender = (statusNotification && statusLoader) ? (statusNotification.shouldRender || statusLoader.shouldRender) : true;
|
||||||
|
|
||||||
|
newState.notification = statusNotification || notification;
|
||||||
|
newState.shouldRender = shouldRender;
|
||||||
|
newState.loader = statusLoader || loader;
|
||||||
// check if newState is different than previous state
|
// check if newState is different than previous state
|
||||||
const stateChanged = reducerUtils.observeChanges(prevState.selectedAccount, newState, {
|
const stateChanged = reducerUtils.observeChanges(prevState.selectedAccount, newState, {
|
||||||
account: ['balance', 'nonce'],
|
account: ['balance', 'nonce'],
|
||||||
|
@ -90,8 +90,20 @@ export const observe = (prevState: ReducersState, action: Action): ThunkAction =
|
|||||||
let shouldUpdate: boolean = false;
|
let shouldUpdate: boolean = false;
|
||||||
// check if "selectedAccount" reducer changed
|
// check if "selectedAccount" reducer changed
|
||||||
shouldUpdate = reducerUtils.observeChanges(prevState.selectedAccount, currentState.selectedAccount, {
|
shouldUpdate = reducerUtils.observeChanges(prevState.selectedAccount, currentState.selectedAccount, {
|
||||||
account: ['balance', 'nonce'],
|
account: ['balance', 'nonce', 'tokens'],
|
||||||
});
|
});
|
||||||
|
if (shouldUpdate && currentState.sendForm.currency !== currentState.sendForm.networkSymbol) {
|
||||||
|
// make sure that this token is added into account
|
||||||
|
const { account, tokens } = getState().selectedAccount;
|
||||||
|
if (!account) return;
|
||||||
|
const token = findToken(tokens, account.address, currentState.sendForm.currency, account.deviceState);
|
||||||
|
if (!token) {
|
||||||
|
// token not found, re-init form
|
||||||
|
dispatch(init());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// check if "sendForm" reducer changed
|
// check if "sendForm" reducer changed
|
||||||
if (!shouldUpdate) {
|
if (!shouldUpdate) {
|
||||||
@ -384,6 +396,26 @@ export const onDataChange = (data: string): ThunkAction => (dispatch: Dispatch,
|
|||||||
dispatch(estimateGasPrice());
|
dispatch(estimateGasPrice());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const setDefaultGasLimit = (): ThunkAction => (dispatch: Dispatch, getState: GetState): void => {
|
||||||
|
const state: State = getState().sendForm;
|
||||||
|
const { network } = getState().selectedAccount;
|
||||||
|
if (!network) return;
|
||||||
|
|
||||||
|
const isToken = state.currency !== state.networkSymbol;
|
||||||
|
const gasLimit = isToken ? network.defaultGasLimitTokens.toString() : network.defaultGasLimit.toString();
|
||||||
|
|
||||||
|
dispatch({
|
||||||
|
type: SEND.CHANGE,
|
||||||
|
state: {
|
||||||
|
...state,
|
||||||
|
calculatingGasLimit: false,
|
||||||
|
untouched: false,
|
||||||
|
touched: { ...state.touched, gasLimit: false },
|
||||||
|
gasLimit,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Internal method
|
* Internal method
|
||||||
* Called from "onDataChange" action
|
* Called from "onDataChange" action
|
||||||
@ -548,6 +580,7 @@ export default {
|
|||||||
updateFeeLevels,
|
updateFeeLevels,
|
||||||
onGasPriceChange,
|
onGasPriceChange,
|
||||||
onGasLimitChange,
|
onGasLimitChange,
|
||||||
|
setDefaultGasLimit,
|
||||||
onNonceChange,
|
onNonceChange,
|
||||||
onDataChange,
|
onDataChange,
|
||||||
onSend,
|
onSend,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/* @flow */
|
/* @flow */
|
||||||
import * as storageUtils from 'utils/storage';
|
import * as storageUtils from 'utils/storage';
|
||||||
|
import { findToken } from 'reducers/TokensReducer';
|
||||||
|
|
||||||
import type { State as SendFormState } from 'reducers/SendFormReducer';
|
import type { State as SendFormState } from 'reducers/SendFormReducer';
|
||||||
import type {
|
import type {
|
||||||
@ -38,6 +39,16 @@ export const loadDraftTransaction = (): PayloadAction<?SendFormState> => (dispat
|
|||||||
storageUtils.remove(TYPE, key);
|
storageUtils.remove(TYPE, key);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
// check if selected currency is token and make sure that this token is added into account
|
||||||
|
if (state.currency !== state.networkSymbol) {
|
||||||
|
const { account, tokens } = getState().selectedAccount;
|
||||||
|
if (!account) return null;
|
||||||
|
const token = findToken(tokens, account.address, state.currency, account.deviceState);
|
||||||
|
if (!token) {
|
||||||
|
storageUtils.remove(TYPE, key);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
return state;
|
return state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ declare var COMMITHASH: string;
|
|||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
opened: boolean,
|
opened: boolean,
|
||||||
|
isLanding: boolean,
|
||||||
toggle: () => any,
|
toggle: () => any,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,29 +26,48 @@ const Wrapper = styled.div`
|
|||||||
color: ${colors.TEXT_SECONDARY};
|
color: ${colors.TEXT_SECONDARY};
|
||||||
padding: 22px 48px;
|
padding: 22px 48px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
border-top: 1px solid ${colors.BACKGROUND};
|
border-top: 1px solid ${colors.BACKGROUND};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledLink = styled(Link)`
|
const StyledLink = styled(Link)`
|
||||||
margin: 0 6px;
|
margin: 0 6px;
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
|
white-space: nowrap;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Copy = styled.div`
|
const Copy = styled.div`
|
||||||
|
white-space: nowrap;
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Footer = ({ opened, toggle }: Props) => (
|
const Left = styled.div`
|
||||||
|
display: flex;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Right = styled.div`
|
||||||
|
white-space: nowrap;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Footer = ({ opened, toggle, isLanding }: Props) => (
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
<Copy title={COMMITHASH}>© {getYear(new Date())}</Copy>
|
<Left>
|
||||||
<StyledLink href="http://satoshilabs.com" isGreen>SatoshiLabs</StyledLink>
|
<Copy title={COMMITHASH}>© {getYear(new Date())}</Copy>
|
||||||
<StyledLink href="/assets/tos.pdf" isGreen>Terms</StyledLink>
|
<StyledLink href="http://satoshilabs.com" isGreen>SatoshiLabs</StyledLink>
|
||||||
<StyledLink onClick={toggle} isGreen>{ opened ? 'Hide Log' : 'Show Log' }</StyledLink>
|
<StyledLink href="/assets/tos.pdf" isGreen>Terms</StyledLink>
|
||||||
|
<StyledLink onClick={toggle} isGreen>{ opened ? 'Hide Log' : 'Show Log' }</StyledLink>
|
||||||
|
</Left>
|
||||||
|
{!isLanding && (
|
||||||
|
<Right>
|
||||||
|
Exchange rates by<StyledLink href="https://www.coingecko.com" isGreen>Coingecko</StyledLink>
|
||||||
|
</Right>
|
||||||
|
)}
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
);
|
);
|
||||||
|
|
||||||
Footer.propTypes = {
|
Footer.propTypes = {
|
||||||
opened: PropTypes.bool.isRequired,
|
opened: PropTypes.bool.isRequired,
|
||||||
|
isLanding: PropTypes.bool,
|
||||||
toggle: PropTypes.func.isRequired,
|
toggle: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -55,13 +55,10 @@ class Link extends PureComponent {
|
|||||||
} else {
|
} else {
|
||||||
LinkComponent = (
|
LinkComponent = (
|
||||||
<A
|
<A
|
||||||
className={this.props.className}
|
|
||||||
href={this.props.href}
|
href={this.props.href}
|
||||||
target={this.props.target || '_blank'}
|
target={this.props.target || '_blank'}
|
||||||
rel="noreferrer noopener"
|
rel="noreferrer noopener"
|
||||||
onClick={this.props.onClick}
|
{...this.props}
|
||||||
isGreen={this.props.isGreen}
|
|
||||||
isGray={this.props.isGray}
|
|
||||||
>{this.props.children}
|
>{this.props.children}
|
||||||
</A>
|
</A>
|
||||||
);
|
);
|
||||||
|
BIN
src/components/images/CoinLogo/images/dgb.png
Normal file
BIN
src/components/images/CoinLogo/images/dgb.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.6 KiB |
@ -185,7 +185,9 @@ class Input extends PureComponent {
|
|||||||
autocapitalize={this.props.autocapitalize}
|
autocapitalize={this.props.autocapitalize}
|
||||||
spellCheck={this.props.spellCheck}
|
spellCheck={this.props.spellCheck}
|
||||||
value={this.props.value}
|
value={this.props.value}
|
||||||
|
readOnly={this.props.readOnly}
|
||||||
onChange={this.props.onChange}
|
onChange={this.props.onChange}
|
||||||
|
onClick={this.props.autoSelect ? event => event.target.select() : null}
|
||||||
borderColor={this.getColor(this.props.state)}
|
borderColor={this.getColor(this.props.state)}
|
||||||
disabled={this.props.isDisabled}
|
disabled={this.props.isDisabled}
|
||||||
name={this.props.name}
|
name={this.props.name}
|
||||||
@ -220,6 +222,8 @@ Input.propTypes = {
|
|||||||
icon: PropTypes.node,
|
icon: PropTypes.node,
|
||||||
spellCheck: PropTypes.string,
|
spellCheck: PropTypes.string,
|
||||||
value: PropTypes.string,
|
value: PropTypes.string,
|
||||||
|
readOnly: PropTypes.bool,
|
||||||
|
autoSelect: PropTypes.bool,
|
||||||
onChange: PropTypes.func,
|
onChange: PropTypes.func,
|
||||||
state: PropTypes.string,
|
state: PropTypes.string,
|
||||||
bottomText: PropTypes.string,
|
bottomText: PropTypes.string,
|
||||||
@ -234,6 +238,7 @@ Input.propTypes = {
|
|||||||
|
|
||||||
Input.defaultProps = {
|
Input.defaultProps = {
|
||||||
type: 'text',
|
type: 'text',
|
||||||
|
autoSelect: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Input;
|
export default Input;
|
||||||
|
@ -7,7 +7,7 @@ import type { Props } from '../../index';
|
|||||||
// There could be only one account notification
|
// There could be only one account notification
|
||||||
export default (props: Props) => {
|
export default (props: Props) => {
|
||||||
const { network, notification } = props.selectedAccount;
|
const { network, notification } = props.selectedAccount;
|
||||||
if (network && notification.type && notification.title && notification.type !== 'loader-progress' && notification.type !== 'loader-info') {
|
if (network && notification.type && notification.title) {
|
||||||
if (notification.type === 'backend') {
|
if (notification.type === 'backend') {
|
||||||
// special case: backend is down
|
// special case: backend is down
|
||||||
// TODO: this is a different component with "auto resolve" button
|
// TODO: this is a different component with "auto resolve" button
|
||||||
|
@ -19,6 +19,11 @@ export default [
|
|||||||
coinName: 'Dash',
|
coinName: 'Dash',
|
||||||
url: '../?coin=dash',
|
url: '../?coin=dash',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'dgb',
|
||||||
|
coinName: 'DigiByte',
|
||||||
|
url: '../?coin=dgb',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'doge',
|
id: 'doge',
|
||||||
coinName: 'Dogecoin',
|
coinName: 'Dogecoin',
|
||||||
|
@ -32,7 +32,7 @@ import type { TokenAction } from 'actions/TokenActions';
|
|||||||
import type { TrezorConnectAction } from 'actions/TrezorConnectActions';
|
import type { TrezorConnectAction } from 'actions/TrezorConnectActions';
|
||||||
import type { WalletAction } from 'actions/WalletActions';
|
import type { WalletAction } from 'actions/WalletActions';
|
||||||
import type { Web3Action } from 'actions/Web3Actions';
|
import type { Web3Action } from 'actions/Web3Actions';
|
||||||
import type { FiatRateAction } from 'services/CoinmarketcapService'; // this service has no action file, all is written inside one file
|
import type { FiatRateAction } from 'services/CoingeckoService'; // this service has no action file, all is written inside one file
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
Device,
|
Device,
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 408 KiB |
BIN
src/images/macbook.png
Normal file
BIN
src/images/macbook.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 509 KiB |
@ -1,29 +1,26 @@
|
|||||||
/* @flow */
|
/* @flow */
|
||||||
|
|
||||||
import { RATE_UPDATE } from 'services/CoinmarketcapService';
|
import { RATE_UPDATE } from 'services/CoingeckoService';
|
||||||
|
|
||||||
import type { Action } from 'flowtype';
|
import type { Action } from 'flowtype';
|
||||||
import type { FiatRateAction } from 'services/CoinmarketcapService';
|
import type { FiatRateAction } from 'services/CoingeckoService';
|
||||||
|
|
||||||
export type Fiat = {
|
export type Fiat = {
|
||||||
+network: string;
|
+network: string;
|
||||||
value: string;
|
value: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const initialState: Array<Fiat> = [];
|
export const initialState: Array<Fiat> = [];
|
||||||
|
|
||||||
const update = (state: Array<Fiat>, action: FiatRateAction): Array<Fiat> => {
|
const update = (state: Array<Fiat>, action: FiatRateAction): Array<Fiat> => {
|
||||||
const newState: Array<Fiat> = [...state];
|
const affected = state.find(f => f.network === action.network);
|
||||||
const exists: ?Fiat = newState.find(f => f.network === action.network);
|
const otherRates = state.filter(d => d !== affected);
|
||||||
if (exists) {
|
const { network, rate } = action;
|
||||||
exists.value = action.rate.price_usd;
|
|
||||||
} else {
|
return otherRates.concat([{
|
||||||
newState.push({
|
network,
|
||||||
network: action.network,
|
value: rate.toFixed(2),
|
||||||
value: action.rate.price_usd,
|
}]);
|
||||||
});
|
|
||||||
}
|
|
||||||
return newState;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default (state: Array<Fiat> = initialState, action: Action): Array<Fiat> => {
|
export default (state: Array<Fiat> = initialState, action: Action): Array<Fiat> => {
|
||||||
|
@ -22,6 +22,11 @@ export type State = {
|
|||||||
title: ?string,
|
title: ?string,
|
||||||
message: ?string,
|
message: ?string,
|
||||||
},
|
},
|
||||||
|
loader: {
|
||||||
|
type: ?string,
|
||||||
|
title: ?string,
|
||||||
|
message: ?string,
|
||||||
|
},
|
||||||
shouldRender: boolean,
|
shouldRender: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -37,6 +42,14 @@ export const initialState: State = {
|
|||||||
title: null,
|
title: null,
|
||||||
message: null,
|
message: null,
|
||||||
},
|
},
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
loader: {
|
||||||
|
type: null,
|
||||||
|
title: null,
|
||||||
|
message: null,
|
||||||
|
},
|
||||||
|
>>>>>>> master
|
||||||
shouldRender: false,
|
shouldRender: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ export const RATE_UPDATE: 'rate__update' = 'rate__update';
|
|||||||
export type FiatRateAction = {
|
export type FiatRateAction = {
|
||||||
type: typeof RATE_UPDATE;
|
type: typeof RATE_UPDATE;
|
||||||
network: string;
|
network: string;
|
||||||
rate: any;
|
rate: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const loadRateAction = (): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<void> => {
|
const loadRateAction = (): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise<void> => {
|
||||||
@ -28,13 +28,12 @@ const loadRateAction = (): AsyncAction => async (dispatch: Dispatch, getState: G
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
config.fiatValueTickers.forEach(async (ticker) => {
|
config.fiatValueTickers.forEach(async (ticker) => {
|
||||||
// const rate: ?Array<any> = await JSONRequest(`${ticker.url}?convert=USD`, 'json');
|
const response = await httpRequest(`${ticker.url}?tickers=false&market_data=true&community_data=false&developer_data=false&sparkline=false`, 'json');
|
||||||
const rate: ?Array<any> = await httpRequest(`${ticker.url}?convert=USD`, 'json');
|
if (response) {
|
||||||
if (rate) {
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: RATE_UPDATE,
|
type: RATE_UPDATE,
|
||||||
network: ticker.network,
|
network: response.symbol,
|
||||||
rate: rate[0],
|
rate: response.market_data.current_price.usd,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -48,7 +47,7 @@ const loadRateAction = (): AsyncAction => async (dispatch: Dispatch, getState: G
|
|||||||
/**
|
/**
|
||||||
* Middleware
|
* Middleware
|
||||||
*/
|
*/
|
||||||
const CoinmarketcapService: Middleware = (api: MiddlewareAPI) => (next: MiddlewareDispatch) => (action: Action): Action => {
|
const CoingeckoService: Middleware = (api: MiddlewareAPI) => (next: MiddlewareDispatch) => (action: Action): Action => {
|
||||||
next(action);
|
next(action);
|
||||||
|
|
||||||
if (action.type === READY) {
|
if (action.type === READY) {
|
||||||
@ -58,4 +57,4 @@ const CoinmarketcapService: Middleware = (api: MiddlewareAPI) => (next: Middlewa
|
|||||||
return action;
|
return action;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CoinmarketcapService;
|
export default CoingeckoService;
|
@ -2,7 +2,7 @@ import WalletService from './WalletService';
|
|||||||
import LogService from './LogService';
|
import LogService from './LogService';
|
||||||
import RouterService from './RouterService';
|
import RouterService from './RouterService';
|
||||||
import LocalStorageService from './LocalStorageService';
|
import LocalStorageService from './LocalStorageService';
|
||||||
import CoinmarketcapService from './CoinmarketcapService';
|
import CoingeckoService from './CoingeckoService';
|
||||||
import TrezorConnectService from './TrezorConnectService';
|
import TrezorConnectService from './TrezorConnectService';
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
@ -11,5 +11,5 @@ export default [
|
|||||||
RouterService,
|
RouterService,
|
||||||
LocalStorageService,
|
LocalStorageService,
|
||||||
TrezorConnectService,
|
TrezorConnectService,
|
||||||
CoinmarketcapService,
|
CoingeckoService,
|
||||||
];
|
];
|
25
src/support/ImagesPreloader.js
Normal file
25
src/support/ImagesPreloader.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
const Wrapper = styled.div`
|
||||||
|
display: none;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Img = styled.img``;
|
||||||
|
|
||||||
|
class ImagesPreloader extends Component {
|
||||||
|
importAll(r) {
|
||||||
|
return r.keys().map(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const images = this.importAll(require.context('../images', false, /\.(png|jpe?g)$/));
|
||||||
|
return (
|
||||||
|
<Wrapper>
|
||||||
|
{images.map(image => <Img key={image} src={image} />)}
|
||||||
|
</Wrapper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ImagesPreloader;
|
@ -12,7 +12,7 @@ describe('device utils', () => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
types.forEach((type) => {
|
types.forEach((type) => {
|
||||||
expect(nUtils.getColor(type)).toMatchSnapshot();
|
expect(nUtils.getPrimaryColor(type)).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('get icon', () => {
|
it('get icon', () => {
|
||||||
|
@ -9,7 +9,7 @@ import { H2 } from 'components/Heading';
|
|||||||
import { PULSATE } from 'config/animations';
|
import { PULSATE } from 'config/animations';
|
||||||
import colors from 'config/colors';
|
import colors from 'config/colors';
|
||||||
import { FONT_SIZE, FONT_WEIGHT } from 'config/variables';
|
import { FONT_SIZE, FONT_WEIGHT } from 'config/variables';
|
||||||
import CaseImage from 'images/case.png';
|
import CaseImage from 'images/macbook.png';
|
||||||
import Link from 'components/Link';
|
import Link from 'components/Link';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
@ -53,7 +53,7 @@ const LandingWrapper = (props: Props) => (
|
|||||||
{ props.children }
|
{ props.children }
|
||||||
</LandingContent>
|
</LandingContent>
|
||||||
)}
|
)}
|
||||||
<Footer />
|
<Footer isLanding />
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)}
|
)}
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
|
@ -45,10 +45,10 @@ const Content = ({
|
|||||||
}) => (
|
}) => (
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
{(!isLoading) && children}
|
{(!isLoading) && children}
|
||||||
{isLoading && (type === 'loader-progress' || type === 'loader-info') && (
|
{isLoading && (type === 'progress' || type === 'info') && (
|
||||||
<Loading>
|
<Loading>
|
||||||
<Row>
|
<Row>
|
||||||
{type === 'loader-progress' && <Loader size={30} />}
|
{type === 'progress' && <Loader size={30} />}
|
||||||
<Text>{title || 'Initializing accounts'}</Text>
|
<Text>{title || 'Initializing accounts'}</Text>
|
||||||
</Row>
|
</Row>
|
||||||
{message && <Message>{message}</Message>}
|
{message && <Message>{message}</Message>}
|
||||||
@ -58,7 +58,7 @@ const Content = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
Content.propTypes = {
|
Content.propTypes = {
|
||||||
children: PropTypes.oneOfType([PropTypes.element, PropTypes.array]),
|
children: PropTypes.element,
|
||||||
isLoading: PropTypes.bool,
|
isLoading: PropTypes.bool,
|
||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
message: PropTypes.string,
|
message: PropTypes.string,
|
||||||
|
@ -93,9 +93,9 @@ const AccountReceive = (props: Props) => {
|
|||||||
account,
|
account,
|
||||||
discovery,
|
discovery,
|
||||||
shouldRender,
|
shouldRender,
|
||||||
notification,
|
loader,
|
||||||
} = props.selectedAccount;
|
} = props.selectedAccount;
|
||||||
const { type, title, message } = notification;
|
const { type, title, message } = loader;
|
||||||
if (!device || !account || !discovery || !shouldRender) return <Content type={type} title={title} message={message} isLoading />;
|
if (!device || !account || !discovery || !shouldRender) return <Content type={type} title={title} message={message} isLoading />;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -120,6 +120,8 @@ const AccountReceive = (props: Props) => {
|
|||||||
<Row>
|
<Row>
|
||||||
<Input
|
<Input
|
||||||
type="text"
|
type="text"
|
||||||
|
readOnly
|
||||||
|
autoSelect
|
||||||
value={address}
|
value={address}
|
||||||
isPartiallyHidden={isAddressHidden}
|
isPartiallyHidden={isAddressHidden}
|
||||||
trezorAction={isAddressVerifying ? (
|
trezorAction={isAddressVerifying ? (
|
||||||
|
@ -9,6 +9,7 @@ import Textarea from 'components/Textarea';
|
|||||||
import Tooltip from 'components/Tooltip';
|
import Tooltip from 'components/Tooltip';
|
||||||
import Icon from 'components/Icon';
|
import Icon from 'components/Icon';
|
||||||
import ICONS from 'config/icons';
|
import ICONS from 'config/icons';
|
||||||
|
import { FONT_SIZE } from 'config/variables';
|
||||||
|
|
||||||
import type { Props as BaseProps } from '../../Container';
|
import type { Props as BaseProps } from '../../Container';
|
||||||
|
|
||||||
@ -28,6 +29,7 @@ const InputRow = styled.div`
|
|||||||
const InputLabelWrapper = styled.div`
|
const InputLabelWrapper = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const GreenSpan = styled.span`
|
const GreenSpan = styled.span`
|
||||||
@ -110,6 +112,18 @@ const getDataTextareaState = (dataError: string, dataWarning: string): string =>
|
|||||||
return state;
|
return state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const Left = styled.div`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Right = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
font-size: ${FONT_SIZE.SMALLER};
|
||||||
|
cursor: pointer;
|
||||||
|
`;
|
||||||
|
|
||||||
// stateless component
|
// stateless component
|
||||||
const AdvancedForm = (props: Props) => {
|
const AdvancedForm = (props: Props) => {
|
||||||
const {
|
const {
|
||||||
@ -124,16 +138,17 @@ const AdvancedForm = (props: Props) => {
|
|||||||
errors,
|
errors,
|
||||||
warnings,
|
warnings,
|
||||||
infos,
|
infos,
|
||||||
|
touched,
|
||||||
data,
|
data,
|
||||||
gasLimit,
|
gasLimit,
|
||||||
gasPrice,
|
gasPrice,
|
||||||
} = props.sendForm;
|
} = props.sendForm;
|
||||||
const {
|
const {
|
||||||
|
setDefaultGasLimit,
|
||||||
onGasLimitChange,
|
onGasLimitChange,
|
||||||
onGasPriceChange,
|
onGasPriceChange,
|
||||||
onDataChange,
|
onDataChange,
|
||||||
} = props.sendFormActions;
|
} = props.sendFormActions;
|
||||||
|
|
||||||
let gasLimitTooltipCurrency: string;
|
let gasLimitTooltipCurrency: string;
|
||||||
let gasLimitTooltipValue: string;
|
let gasLimitTooltipValue: string;
|
||||||
if (networkSymbol !== currency) {
|
if (networkSymbol !== currency) {
|
||||||
@ -144,6 +159,8 @@ const AdvancedForm = (props: Props) => {
|
|||||||
gasLimitTooltipValue = network.defaultGasLimit.toString(10);
|
gasLimitTooltipValue = network.defaultGasLimit.toString(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const showDefaultGasLimitButton = data.length === 0 && touched.gasLimit;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AdvancedSettingsWrapper>
|
<AdvancedSettingsWrapper>
|
||||||
<GasInputRow>
|
<GasInputRow>
|
||||||
@ -155,29 +172,36 @@ const AdvancedForm = (props: Props) => {
|
|||||||
spellCheck="false"
|
spellCheck="false"
|
||||||
topLabel={(
|
topLabel={(
|
||||||
<InputLabelWrapper>
|
<InputLabelWrapper>
|
||||||
|
<Left>
|
||||||
Gas limit
|
Gas limit
|
||||||
<Tooltip
|
<Tooltip
|
||||||
content={(
|
content={(
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
Gas limit refers to the maximum amount of gas user is willing to spendon a particular transaction.{' '}
|
Gas limit refers to the maximum amount of gas user is willing to spendon a particular transaction.{' '}
|
||||||
<GreenSpan>Transaction fee = gas limit * gas price</GreenSpan>.{' '}Increasing the gas limit will not get the transaction confirmed sooner.
|
<GreenSpan>Transaction fee = gas limit * gas price</GreenSpan>.{' '}Increasing the gas limit will not get the transaction confirmed sooner.
|
||||||
Default value for sending {gasLimitTooltipCurrency} is <GreenSpan>{gasLimitTooltipValue}</GreenSpan>.
|
Default value for sending {gasLimitTooltipCurrency} is <GreenSpan>{gasLimitTooltipValue}</GreenSpan>.
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)}
|
)}
|
||||||
maxWidth={410}
|
maxWidth={410}
|
||||||
readMoreLink="https://wiki.trezor.io/Ethereum_Wallet#Gas_limit"
|
readMoreLink="https://wiki.trezor.io/Ethereum_Wallet#Gas_limit"
|
||||||
placement="top"
|
placement="top"
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
icon={ICONS.HELP}
|
icon={ICONS.HELP}
|
||||||
color={colors.TEXT_SECONDARY}
|
color={colors.TEXT_SECONDARY}
|
||||||
size={24}
|
size={24}
|
||||||
/>
|
/>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
</Left>
|
||||||
|
{ showDefaultGasLimitButton && (
|
||||||
|
<Right onClick={() => setDefaultGasLimit()}>
|
||||||
|
Set default
|
||||||
|
</Right>)
|
||||||
|
}
|
||||||
</InputLabelWrapper>
|
</InputLabelWrapper>
|
||||||
)}
|
)}
|
||||||
bottomText={errors.gasLimit || warnings.gasLimit || infos.gasLimit || (calculatingGasLimit ? 'Calculating...' : '')}
|
bottomText={errors.gasLimit || warnings.gasLimit || infos.gasLimit}
|
||||||
value={gasLimit}
|
value={calculatingGasLimit ? 'Calculating...' : gasLimit}
|
||||||
isDisabled={networkSymbol === currency && data.length > 0}
|
isDisabled={networkSymbol === currency && data.length > 0}
|
||||||
onChange={event => onGasLimitChange(event.target.value)}
|
onChange={event => onGasLimitChange(event.target.value)}
|
||||||
/>
|
/>
|
||||||
|
@ -185,7 +185,11 @@ const AccountSend = (props: Props) => {
|
|||||||
discovery,
|
discovery,
|
||||||
tokens,
|
tokens,
|
||||||
shouldRender,
|
shouldRender,
|
||||||
|
<<<<<<< HEAD
|
||||||
notification,
|
notification,
|
||||||
|
=======
|
||||||
|
loader,
|
||||||
|
>>>>>>> master
|
||||||
} = props.selectedAccount;
|
} = props.selectedAccount;
|
||||||
const {
|
const {
|
||||||
address,
|
address,
|
||||||
@ -214,7 +218,7 @@ const AccountSend = (props: Props) => {
|
|||||||
updateFeeLevels,
|
updateFeeLevels,
|
||||||
onSend,
|
onSend,
|
||||||
} = props.sendFormActions;
|
} = props.sendFormActions;
|
||||||
const { type, title, message } = notification;
|
const { type, title, message } = loader;
|
||||||
if (!device || !account || !discovery || !network || !shouldRender) return <Content type={type} title={title} message={message} isLoading />;
|
if (!device || !account || !discovery || !network || !shouldRender) return <Content type={type} title={title} message={message} isLoading />;
|
||||||
|
|
||||||
const isCurrentCurrencyToken = networkSymbol !== currency;
|
const isCurrentCurrencyToken = networkSymbol !== currency;
|
||||||
|
@ -106,8 +106,7 @@ class AccountBalance extends PureComponent<Props, State> {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { network } = this.props;
|
const { network } = this.props;
|
||||||
const fiatRate: any = this.props.fiat.find(f => f.network === network.shortcut);
|
const fiatRate = this.props.fiat.find(f => f.network === network.shortcut);
|
||||||
|
|
||||||
let accountBalance = '';
|
let accountBalance = '';
|
||||||
let fiatRateValue = '';
|
let fiatRateValue = '';
|
||||||
let fiat = '';
|
let fiat = '';
|
||||||
@ -117,7 +116,6 @@ class AccountBalance extends PureComponent<Props, State> {
|
|||||||
fiat = accountBalance.times(fiatRateValue).toFixed(2);
|
fiat = accountBalance.times(fiatRateValue).toFixed(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
<HideBalanceIconWrapper
|
<HideBalanceIconWrapper
|
||||||
|
@ -75,11 +75,12 @@ const AccountSummary = (props: Props) => {
|
|||||||
network,
|
network,
|
||||||
tokens,
|
tokens,
|
||||||
pending,
|
pending,
|
||||||
notification,
|
loader,
|
||||||
shouldRender,
|
shouldRender,
|
||||||
} = props.selectedAccount;
|
} = props.selectedAccount;
|
||||||
|
|
||||||
const { type, title, message } = notification;
|
const { type, title, message } = loader;
|
||||||
|
|
||||||
if (!device || !account || !network || !shouldRender) return <Content type={type} title={title} message={message} isLoading />;
|
if (!device || !account || !network || !shouldRender) return <Content type={type} title={title} message={message} isLoading />;
|
||||||
|
|
||||||
const explorerLink: string = `${network.explorer.address}${account.address}`;
|
const explorerLink: string = `${network.explorer.address}${account.address}`;
|
||||||
@ -125,9 +126,11 @@ const AccountSummary = (props: Props) => {
|
|||||||
loadingMessage={() => 'Loading...'}
|
loadingMessage={() => 'Loading...'}
|
||||||
noOptionsMessage={() => 'Token not found'}
|
noOptionsMessage={() => 'Token not found'}
|
||||||
onChange={(token) => {
|
onChange={(token) => {
|
||||||
const isAdded = tokens.find(t => t.symbol === token.symbol);
|
if (token.name) {
|
||||||
if (!isAdded) {
|
const isAdded = tokens.find(t => t.symbol === token.symbol);
|
||||||
props.addToken(token, account);
|
if (!isAdded) {
|
||||||
|
props.addToken(token, account);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
loadOptions={input => props.loadTokens(input, account.network)}
|
loadOptions={input => props.loadTokens(input, account.network)}
|
||||||
@ -142,7 +145,6 @@ const AccountSummary = (props: Props) => {
|
|||||||
getOptionValue={option => option.symbol}
|
getOptionValue={option => option.symbol}
|
||||||
/>
|
/>
|
||||||
</AsyncSelectWrapper>
|
</AsyncSelectWrapper>
|
||||||
|
|
||||||
<AddedTokensWrapper>
|
<AddedTokensWrapper>
|
||||||
{tokens.map(token => (
|
{tokens.map(token => (
|
||||||
<AddedToken
|
<AddedToken
|
||||||
|
@ -41,7 +41,7 @@ const DeviceSettings = () => (
|
|||||||
/>
|
/>
|
||||||
<H2>Device settings is under construction</H2>
|
<H2>Device settings is under construction</H2>
|
||||||
<StyledP isSmaller>Please use Bitcoin wallet interface to change your device settings</StyledP>
|
<StyledP isSmaller>Please use Bitcoin wallet interface to change your device settings</StyledP>
|
||||||
<Link href="https://wallet.trezor.io/">
|
<Link href="https://beta-wallet.trezor.io/">
|
||||||
<Button>Take me to the Bitcoin wallet</Button>
|
<Button>Take me to the Bitcoin wallet</Button>
|
||||||
</Link>
|
</Link>
|
||||||
</Row>
|
</Row>
|
||||||
|
@ -127,9 +127,9 @@ const FirmwareUpdate = (props: Props) => (
|
|||||||
</svg>
|
</svg>
|
||||||
</Image>
|
</Image>
|
||||||
<H1>It’s time to update your firmware</H1>
|
<H1>It’s time to update your firmware</H1>
|
||||||
<StyledP>Please use the old wallet to do that.</StyledP>
|
<StyledP>Please use Bitcoin wallet interface to update your firmware.</StyledP>
|
||||||
<Link href="https://wallet.trezor.io">
|
<Link href="https://beta-wallet.trezor.io">
|
||||||
<Button>Take me to the old wallet</Button>
|
<Button>Take me to the Bitcoin wallet</Button>
|
||||||
</Link>
|
</Link>
|
||||||
{deviceUtils.isDeviceAccessible(props.device) && (
|
{deviceUtils.isDeviceAccessible(props.device) && (
|
||||||
<StyledNavLink to="/">I’ll do that later.</StyledNavLink>
|
<StyledNavLink to="/">I’ll do that later.</StyledNavLink>
|
||||||
|
@ -32,7 +32,7 @@ const Initialize = () => (
|
|||||||
<Row>
|
<Row>
|
||||||
<H2>Your device is in not initialized</H2>
|
<H2>Your device is in not initialized</H2>
|
||||||
<StyledParagraph>Please use Bitcoin wallet interface to start initialization process</StyledParagraph>
|
<StyledParagraph>Please use Bitcoin wallet interface to start initialization process</StyledParagraph>
|
||||||
<A href="https://wallet.trezor.io/">
|
<A href="https://beta-wallet.trezor.io/">
|
||||||
<Button>Take me to the Bitcoin wallet</Button>
|
<Button>Take me to the Bitcoin wallet</Button>
|
||||||
</A>
|
</A>
|
||||||
</Row>
|
</Row>
|
||||||
|
@ -6,6 +6,7 @@ import { ConnectedRouter } from 'react-router-redux';
|
|||||||
|
|
||||||
// general
|
// general
|
||||||
import ErrorBoundary from 'support/ErrorBoundary';
|
import ErrorBoundary from 'support/ErrorBoundary';
|
||||||
|
import ImagesPreloader from 'support/ImagesPreloader';
|
||||||
import { getPattern } from 'support/routes';
|
import { getPattern } from 'support/routes';
|
||||||
|
|
||||||
// landing views
|
// landing views
|
||||||
@ -41,6 +42,7 @@ const App = () => (
|
|||||||
<Route exact path={getPattern('landing-import')} component={ImportView} />
|
<Route exact path={getPattern('landing-import')} component={ImportView} />
|
||||||
<Route>
|
<Route>
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
|
<ImagesPreloader />
|
||||||
<WalletContainer>
|
<WalletContainer>
|
||||||
<Route exact path={getPattern('wallet-settings')} component={WalletSettings} />
|
<Route exact path={getPattern('wallet-settings')} component={WalletSettings} />
|
||||||
<Route exact path={getPattern('wallet-dashboard')} component={WalletDashboard} />
|
<Route exact path={getPattern('wallet-dashboard')} component={WalletDashboard} />
|
||||||
|
@ -10274,9 +10274,9 @@ tr46@^1.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
punycode "^2.1.0"
|
punycode "^2.1.0"
|
||||||
|
|
||||||
trezor-connect@6.0.0:
|
trezor-connect@6.0.2:
|
||||||
version "6.0.0"
|
version "6.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/trezor-connect/-/trezor-connect-6.0.0.tgz#2a45336f29a4a3f2a8ad2d121363b0e7a1b767ef"
|
resolved "https://registry.yarnpkg.com/trezor-connect/-/trezor-connect-6.0.2.tgz#a4ca892cc4a167b34b97644e1404a56f6a110379"
|
||||||
dependencies:
|
dependencies:
|
||||||
babel-runtime "^6.26.0"
|
babel-runtime "^6.26.0"
|
||||||
events "^1.1.1"
|
events "^1.1.1"
|
||||||
|
Loading…
Reference in New Issue
Block a user