|
|
@ -10,6 +10,7 @@ import * as PENDING from 'actions/constants/pendingTx';
|
|
|
|
import * as WALLET from 'actions/constants/wallet';
|
|
|
|
import * as WALLET from 'actions/constants/wallet';
|
|
|
|
import { httpRequest } from 'utils/networkUtils';
|
|
|
|
import { httpRequest } from 'utils/networkUtils';
|
|
|
|
import * as buildUtils from 'utils/build';
|
|
|
|
import * as buildUtils from 'utils/build';
|
|
|
|
|
|
|
|
import * as storageUtils from 'utils/storage';
|
|
|
|
|
|
|
|
|
|
|
|
import { findAccountTokens } from 'reducers/TokensReducer';
|
|
|
|
import { findAccountTokens } from 'reducers/TokensReducer';
|
|
|
|
import type { Account } from 'reducers/AccountsReducer';
|
|
|
|
import type { Account } from 'reducers/AccountsReducer';
|
|
|
@ -17,7 +18,6 @@ import type { Token } from 'reducers/TokensReducer';
|
|
|
|
import type { PendingTx } from 'reducers/PendingTxReducer';
|
|
|
|
import type { PendingTx } from 'reducers/PendingTxReducer';
|
|
|
|
import type { Discovery } from 'reducers/DiscoveryReducer';
|
|
|
|
import type { Discovery } from 'reducers/DiscoveryReducer';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import type {
|
|
|
|
import type {
|
|
|
|
TrezorDevice,
|
|
|
|
TrezorDevice,
|
|
|
|
ThunkAction,
|
|
|
|
ThunkAction,
|
|
|
@ -43,22 +43,15 @@ export type StorageAction = {
|
|
|
|
error: string,
|
|
|
|
error: string,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const get = (key: string): ?string => {
|
|
|
|
const TYPE: 'local' = 'local';
|
|
|
|
try {
|
|
|
|
const { STORAGE_PATH } = storageUtils;
|
|
|
|
return window.localStorage.getItem(key);
|
|
|
|
const KEY_VERSION: string = `${STORAGE_PATH}version`;
|
|
|
|
} catch (error) {
|
|
|
|
const KEY_DEVICES: string = `${STORAGE_PATH}devices`;
|
|
|
|
// available = false;
|
|
|
|
const KEY_ACCOUNTS: string = `${STORAGE_PATH}accounts`;
|
|
|
|
return null;
|
|
|
|
const KEY_DISCOVERY: string = `${STORAGE_PATH}discovery`;
|
|
|
|
}
|
|
|
|
const KEY_TOKENS: string = `${STORAGE_PATH}tokens`;
|
|
|
|
};
|
|
|
|
const KEY_PENDING: string = `${STORAGE_PATH}pending`;
|
|
|
|
|
|
|
|
const KEY_BETA_MODAL: string = '/betaModalPrivacy'; // this key needs to be compatible with "parent" (old) wallet
|
|
|
|
const set = (key: string, value: string | boolean): void => {
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
window.localStorage.setItem(key, value);
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
|
|
console.error(`Local Storage ERROR: ${error}`);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// https://github.com/STRML/react-localstorage/blob/master/react-localstorage.js
|
|
|
|
// https://github.com/STRML/react-localstorage/blob/master/react-localstorage.js
|
|
|
|
// or
|
|
|
|
// or
|
|
|
@ -80,25 +73,25 @@ export const save = (): ThunkAction => (dispatch: Dispatch, getState: GetState):
|
|
|
|
const discovery: Array<Discovery> = findDiscovery(devices, getState().discovery);
|
|
|
|
const discovery: Array<Discovery> = findDiscovery(devices, getState().discovery);
|
|
|
|
|
|
|
|
|
|
|
|
// save devices
|
|
|
|
// save devices
|
|
|
|
set('devices', JSON.stringify(devices));
|
|
|
|
storageUtils.set(TYPE, KEY_DEVICES, JSON.stringify(devices));
|
|
|
|
|
|
|
|
|
|
|
|
// save already preloaded accounts
|
|
|
|
// save already preloaded accounts
|
|
|
|
set('accounts', JSON.stringify(accounts));
|
|
|
|
storageUtils.set(TYPE, KEY_ACCOUNTS, JSON.stringify(accounts));
|
|
|
|
|
|
|
|
|
|
|
|
// save discovery state
|
|
|
|
// save discovery state
|
|
|
|
set('discovery', JSON.stringify(discovery));
|
|
|
|
storageUtils.set(TYPE, KEY_DISCOVERY, JSON.stringify(discovery));
|
|
|
|
|
|
|
|
|
|
|
|
// tokens
|
|
|
|
// tokens
|
|
|
|
set('tokens', JSON.stringify(tokens));
|
|
|
|
storageUtils.set(TYPE, KEY_TOKENS, JSON.stringify(tokens));
|
|
|
|
|
|
|
|
|
|
|
|
// pending transactions
|
|
|
|
// pending transactions
|
|
|
|
set('pending', JSON.stringify(pending));
|
|
|
|
storageUtils.set(TYPE, KEY_PENDING, JSON.stringify(pending));
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export const update = (event: StorageEvent): ThunkAction => (dispatch: Dispatch): void => {
|
|
|
|
export const update = (event: StorageEvent): ThunkAction => (dispatch: Dispatch): void => {
|
|
|
|
if (!event.newValue) return;
|
|
|
|
if (!event.newValue) return;
|
|
|
|
|
|
|
|
|
|
|
|
if (event.key === 'devices') {
|
|
|
|
if (event.key === KEY_DEVICES) {
|
|
|
|
// check if device was added/ removed
|
|
|
|
// check if device was added/ removed
|
|
|
|
// const newDevices: Array<TrezorDevice> = JSON.parse(event.newValue);
|
|
|
|
// const newDevices: Array<TrezorDevice> = JSON.parse(event.newValue);
|
|
|
|
// const myDevices: Array<TrezorDevice> = getState().connect.devices.filter(d => d.features);
|
|
|
|
// const myDevices: Array<TrezorDevice> = getState().connect.devices.filter(d => d.features);
|
|
|
@ -113,28 +106,28 @@ export const update = (event: StorageEvent): ThunkAction => (dispatch: Dispatch)
|
|
|
|
// const diff = oldDevices.filter(d => newDevices.indexOf())
|
|
|
|
// const diff = oldDevices.filter(d => newDevices.indexOf())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (event.key === 'accounts') {
|
|
|
|
if (event.key === KEY_ACCOUNTS) {
|
|
|
|
dispatch({
|
|
|
|
dispatch({
|
|
|
|
type: ACCOUNT.FROM_STORAGE,
|
|
|
|
type: ACCOUNT.FROM_STORAGE,
|
|
|
|
payload: JSON.parse(event.newValue),
|
|
|
|
payload: JSON.parse(event.newValue),
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (event.key === 'tokens') {
|
|
|
|
if (event.key === KEY_TOKENS) {
|
|
|
|
dispatch({
|
|
|
|
dispatch({
|
|
|
|
type: TOKEN.FROM_STORAGE,
|
|
|
|
type: TOKEN.FROM_STORAGE,
|
|
|
|
payload: JSON.parse(event.newValue),
|
|
|
|
payload: JSON.parse(event.newValue),
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (event.key === 'pending') {
|
|
|
|
if (event.key === KEY_PENDING) {
|
|
|
|
dispatch({
|
|
|
|
dispatch({
|
|
|
|
type: PENDING.FROM_STORAGE,
|
|
|
|
type: PENDING.FROM_STORAGE,
|
|
|
|
payload: JSON.parse(event.newValue),
|
|
|
|
payload: JSON.parse(event.newValue),
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (event.key === 'discovery') {
|
|
|
|
if (event.key === KEY_DISCOVERY) {
|
|
|
|
dispatch({
|
|
|
|
dispatch({
|
|
|
|
type: DISCOVERY.FROM_STORAGE,
|
|
|
|
type: DISCOVERY.FROM_STORAGE,
|
|
|
|
payload: JSON.parse(event.newValue),
|
|
|
|
payload: JSON.parse(event.newValue),
|
|
|
@ -142,14 +135,13 @@ export const update = (event: StorageEvent): ThunkAction => (dispatch: Dispatch)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const VERSION: string = '1';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const loadJSON = (): AsyncAction => async (dispatch: Dispatch): Promise<void> => {
|
|
|
|
const loadJSON = (): AsyncAction => async (dispatch: Dispatch): Promise<void> => {
|
|
|
|
if (typeof window.localStorage === 'undefined') return;
|
|
|
|
if (typeof window.localStorage === 'undefined') return;
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
const config: Config = await httpRequest(AppConfigJSON, 'json');
|
|
|
|
const config: Config = await httpRequest(AppConfigJSON, 'json');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// remove ropsten testnet from config networks
|
|
|
|
if (!buildUtils.isDev()) {
|
|
|
|
if (!buildUtils.isDev()) {
|
|
|
|
const index = config.networks.findIndex(c => c.shortcut === 'trop');
|
|
|
|
const index = config.networks.findIndex(c => c.shortcut === 'trop');
|
|
|
|
delete config.networks[index];
|
|
|
|
delete config.networks[index];
|
|
|
@ -161,18 +153,6 @@ const loadJSON = (): AsyncAction => async (dispatch: Dispatch): Promise<void> =>
|
|
|
|
dispatch(update(event));
|
|
|
|
dispatch(update(event));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// validate version
|
|
|
|
|
|
|
|
const version: ?string = get('version');
|
|
|
|
|
|
|
|
if (version !== VERSION) {
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
window.localStorage.clear();
|
|
|
|
|
|
|
|
window.sessionStorage.clear();
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
|
|
// empty
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
set('version', VERSION);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// load tokens
|
|
|
|
// load tokens
|
|
|
|
const tokens = await config.networks.reduce(async (promise: Promise<TokensCollection>, network: Network): Promise<TokensCollection> => {
|
|
|
|
const tokens = await config.networks.reduce(async (promise: Promise<TokensCollection>, network: Network): Promise<TokensCollection> => {
|
|
|
|
const collection: TokensCollection = await promise;
|
|
|
|
const collection: TokensCollection = await promise;
|
|
|
@ -195,9 +175,17 @@ const loadJSON = (): AsyncAction => async (dispatch: Dispatch): Promise<void> =>
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const VERSION: string = '1';
|
|
|
|
|
|
|
|
|
|
|
|
const loadStorageData = (): ThunkAction => (dispatch: Dispatch): void => {
|
|
|
|
const loadStorageData = (): ThunkAction => (dispatch: Dispatch): void => {
|
|
|
|
const devices: ?string = get('devices');
|
|
|
|
// validate version
|
|
|
|
|
|
|
|
const version: ?string = storageUtils.get(TYPE, KEY_VERSION);
|
|
|
|
|
|
|
|
if (version && version !== VERSION) {
|
|
|
|
|
|
|
|
storageUtils.clearAll();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
storageUtils.set(TYPE, KEY_VERSION, VERSION);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const devices: ?string = storageUtils.get(TYPE, KEY_DEVICES);
|
|
|
|
if (devices) {
|
|
|
|
if (devices) {
|
|
|
|
dispatch({
|
|
|
|
dispatch({
|
|
|
|
type: CONNECT.DEVICE_FROM_STORAGE,
|
|
|
|
type: CONNECT.DEVICE_FROM_STORAGE,
|
|
|
@ -205,7 +193,7 @@ const loadStorageData = (): ThunkAction => (dispatch: Dispatch): void => {
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const accounts: ?string = get('accounts');
|
|
|
|
const accounts: ?string = storageUtils.get(TYPE, KEY_ACCOUNTS);
|
|
|
|
if (accounts) {
|
|
|
|
if (accounts) {
|
|
|
|
dispatch({
|
|
|
|
dispatch({
|
|
|
|
type: ACCOUNT.FROM_STORAGE,
|
|
|
|
type: ACCOUNT.FROM_STORAGE,
|
|
|
@ -213,7 +201,7 @@ const loadStorageData = (): ThunkAction => (dispatch: Dispatch): void => {
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const userTokens: ?string = get('tokens');
|
|
|
|
const userTokens: ?string = storageUtils.get(TYPE, KEY_TOKENS);
|
|
|
|
if (userTokens) {
|
|
|
|
if (userTokens) {
|
|
|
|
dispatch({
|
|
|
|
dispatch({
|
|
|
|
type: TOKEN.FROM_STORAGE,
|
|
|
|
type: TOKEN.FROM_STORAGE,
|
|
|
@ -221,7 +209,7 @@ const loadStorageData = (): ThunkAction => (dispatch: Dispatch): void => {
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const pending: ?string = get('pending');
|
|
|
|
const pending: ?string = storageUtils.get(TYPE, KEY_PENDING);
|
|
|
|
if (pending) {
|
|
|
|
if (pending) {
|
|
|
|
dispatch({
|
|
|
|
dispatch({
|
|
|
|
type: PENDING.FROM_STORAGE,
|
|
|
|
type: PENDING.FROM_STORAGE,
|
|
|
@ -229,7 +217,7 @@ const loadStorageData = (): ThunkAction => (dispatch: Dispatch): void => {
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const discovery: ?string = get('discovery');
|
|
|
|
const discovery: ?string = storageUtils.get(TYPE, KEY_DISCOVERY);
|
|
|
|
if (discovery) {
|
|
|
|
if (discovery) {
|
|
|
|
dispatch({
|
|
|
|
dispatch({
|
|
|
|
type: DISCOVERY.FROM_STORAGE,
|
|
|
|
type: DISCOVERY.FROM_STORAGE,
|
|
|
@ -238,7 +226,7 @@ const loadStorageData = (): ThunkAction => (dispatch: Dispatch): void => {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (buildUtils.isDev() || buildUtils.isBeta()) {
|
|
|
|
if (buildUtils.isDev() || buildUtils.isBeta()) {
|
|
|
|
const betaModal = get('/betaModalPrivacy');
|
|
|
|
const betaModal = Object.keys(window.localStorage).find(key => key.indexOf(KEY_BETA_MODAL) >= 0);
|
|
|
|
if (!betaModal) {
|
|
|
|
if (!betaModal) {
|
|
|
|
dispatch({
|
|
|
|
dispatch({
|
|
|
|
type: WALLET.SHOW_BETA_DISCLAIMER,
|
|
|
|
type: WALLET.SHOW_BETA_DISCLAIMER,
|
|
|
@ -258,6 +246,6 @@ export const loadData = (): ThunkAction => (dispatch: Dispatch, getState: GetSta
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export const hideBetaDisclaimer = (): ThunkAction => (dispatch: Dispatch): void => {
|
|
|
|
export const hideBetaDisclaimer = (): ThunkAction => (dispatch: Dispatch): void => {
|
|
|
|
set('/betaModalPrivacy', true);
|
|
|
|
storageUtils.set(TYPE, KEY_BETA_MODAL, true);
|
|
|
|
dispatch(loadJSON());
|
|
|
|
dispatch(loadJSON());
|
|
|
|
};
|
|
|
|
};
|
|
|
|