├── src ├── shared │ ├── log │ │ ├── serverLog.js │ │ └── common.js │ ├── components │ │ ├── common │ │ │ ├── table │ │ │ │ ├── index.js │ │ │ │ └── Table.js │ │ │ ├── timeago │ │ │ │ ├── index.js │ │ │ │ └── TimeAgo.js │ │ │ ├── card │ │ │ │ └── index.js │ │ │ ├── loading │ │ │ │ ├── index.js │ │ │ │ └── PageLoading.js │ │ │ ├── logo │ │ │ │ ├── index.js │ │ │ │ ├── TitleLogo.js │ │ │ │ └── Logo.js │ │ │ ├── error │ │ │ │ ├── index.js │ │ │ │ └── PageError.js │ │ │ └── view │ │ │ │ ├── index.js │ │ │ │ ├── getPagingStartEnd.js │ │ │ │ ├── SearchView.js │ │ │ │ ├── PagingView.js │ │ │ │ ├── PageView.js │ │ │ │ └── RightPager.js │ │ ├── transaction │ │ │ ├── index.js │ │ │ ├── summary │ │ │ │ ├── index.js │ │ │ │ └── __generated__ │ │ │ │ │ ├── TransactionSummaryList_transactions.graphql.js │ │ │ │ │ ├── TransactionSummaryFooter_transaction.graphql.js │ │ │ │ │ ├── TransactionSummary_transaction.graphql.js │ │ │ │ │ ├── TransactionSummaryHeader_transaction.graphql.js │ │ │ │ │ └── TransactionSummaryBody_transaction.graphql.js │ │ │ ├── lib │ │ │ │ ├── getTitle.js │ │ │ │ ├── DownArrow.js │ │ │ │ ├── RightArrow.js │ │ │ │ ├── index.js │ │ │ │ ├── __generated__ │ │ │ │ │ ├── TransactionHeaderBackground_transaction.graphql.js │ │ │ │ │ ├── TransactionTypeAndLink_transaction.graphql.js │ │ │ │ │ ├── TransactionInputTable_inputs.graphql.js │ │ │ │ │ ├── TransactionOutputTable_outputs.graphql.js │ │ │ │ │ └── TransactionInputOutputTable_input_outputs.graphql.js │ │ │ │ ├── TransactionLink.js │ │ │ │ ├── getIcon.js │ │ │ │ ├── TransactionTimeLink.js │ │ │ │ └── TransactionValue.js │ │ │ ├── __generated__ │ │ │ │ ├── TransactionPagingView_transactions.graphql.js │ │ │ │ └── TransactionTable_transactions.graphql.js │ │ │ ├── TransactionTable.js │ │ │ └── TransactionPagingView.js │ │ ├── address │ │ │ ├── index.js │ │ │ └── lib │ │ │ │ ├── index.js │ │ │ │ ├── CoinValue.js │ │ │ │ ├── Coin.js │ │ │ │ ├── getSortedCoins.js │ │ │ │ ├── CoinBase.js │ │ │ │ ├── __generated__ │ │ │ │ ├── Coin_coin.graphql.js │ │ │ │ └── CoinTable_coins.graphql.js │ │ │ │ └── AddressLink.js │ │ ├── contract │ │ │ └── lib │ │ │ │ ├── index.js │ │ │ │ ├── __generated__ │ │ │ │ └── ContractNameLink_contract.graphql.js │ │ │ │ ├── ContractLink.js │ │ │ │ └── ContractNameLink.js │ │ ├── block │ │ │ └── lib │ │ │ │ ├── getBlockSize.js │ │ │ │ ├── index.js │ │ │ │ ├── __generated__ │ │ │ │ ├── BlockTime_block.graphql.js │ │ │ │ ├── BlockHashLink_block.graphql.js │ │ │ │ └── BlockIndexLink_block.graphql.js │ │ │ │ ├── BlockHashLink.js │ │ │ │ ├── BlockIndexLink.js │ │ │ │ └── BlockTime.js │ │ └── asset │ │ │ └── lib │ │ │ ├── index.js │ │ │ ├── AssetLink.js │ │ │ ├── getName.js │ │ │ ├── AssetNameLink.js │ │ │ ├── AssetNameLinkBase.js │ │ │ └── __generated__ │ │ │ └── AssetNameLink_asset.graphql.js │ ├── graphql │ │ └── relay │ │ │ ├── index.js │ │ │ ├── queryRenderer.js │ │ │ └── paginationContainer.js │ ├── AppContext.js │ └── redux │ │ ├── timer.js │ │ ├── snackbar.js │ │ ├── configureStore.js │ │ └── index.js ├── lib │ ├── components │ │ └── shared │ │ │ ├── error │ │ │ ├── index.js │ │ │ └── Error404.js │ │ │ ├── base │ │ │ ├── Tab.js │ │ │ ├── Card.js │ │ │ ├── Chip.js │ │ │ ├── Grid.js │ │ │ ├── List.js │ │ │ ├── Menu.js │ │ │ ├── Tabs.js │ │ │ ├── Input.js │ │ │ ├── Modal.js │ │ │ ├── Paper.js │ │ │ ├── Radio.js │ │ │ ├── Button.js │ │ │ ├── Dialog.js │ │ │ ├── Drawer.js │ │ │ ├── Hidden.js │ │ │ ├── Portal.js │ │ │ ├── Slide.js │ │ │ ├── ListItem.js │ │ │ ├── MenuItem.js │ │ │ ├── Popover.js │ │ │ ├── SvgIcon.js │ │ │ ├── Checkbox.js │ │ │ ├── Collapse.js │ │ │ ├── FormLabel.js │ │ │ ├── Snackbar.js │ │ │ ├── CardContent.js │ │ │ ├── FormControl.js │ │ │ ├── InputLabel.js │ │ │ ├── RadioGroup.js │ │ │ ├── Transition.js │ │ │ ├── DialogTitle.js │ │ │ ├── IconButton.js │ │ │ ├── ListItemIcon.js │ │ │ ├── ListItemText.js │ │ │ ├── Typography.js │ │ │ ├── DialogActions.js │ │ │ ├── DialogContent.js │ │ │ ├── ListSubheader.js │ │ │ ├── FormControlLabel.js │ │ │ ├── LinearProgress.js │ │ │ ├── ClickAwayListener.js │ │ │ └── Icon.js │ │ │ ├── help │ │ │ ├── index.js │ │ │ └── Help.js │ │ │ ├── pager │ │ │ └── index.js │ │ │ ├── qr │ │ │ ├── index.js │ │ │ └── QRCode.js │ │ │ ├── animated │ │ │ ├── index.js │ │ │ └── Chevron.js │ │ │ ├── tooltip │ │ │ ├── index.js │ │ │ └── Tooltip.js │ │ │ ├── markdown │ │ │ └── index.js │ │ │ ├── selector │ │ │ └── index.js │ │ │ ├── theme │ │ │ ├── index.js │ │ │ └── ThemeProvider.js │ │ │ ├── link │ │ │ ├── index.js │ │ │ └── IconLink.js │ │ │ └── layout │ │ │ ├── index.js │ │ │ ├── CardView.js │ │ │ ├── TitleCard.js │ │ │ └── CenteredView.js │ ├── graphql │ │ └── shared │ │ │ └── relay │ │ │ ├── getDisplayName.js │ │ │ ├── relay │ │ │ ├── getDisplayName.js │ │ │ ├── index.js │ │ │ ├── fragmentContainer.js │ │ │ └── paginationContainer.js │ │ │ ├── index.js │ │ │ ├── fragmentContainer.js │ │ │ └── paginationContainer.js │ ├── utils │ │ ├── shared │ │ │ ├── DateTime.js │ │ │ ├── index.js │ │ │ ├── formatTime.js │ │ │ ├── formatNumber.js │ │ │ ├── createSafeRetry.js │ │ │ └── tryParseInt.js │ │ └── objects │ │ │ ├── index.js │ │ │ ├── values.js │ │ │ ├── entries.js │ │ │ └── filterObject.js │ ├── errors │ │ ├── server │ │ │ ├── index.js │ │ │ ├── ValidationError.js │ │ │ ├── HTTPError.js │ │ │ └── CodedError.js │ │ └── shared │ │ │ ├── BaseError.js │ │ │ ├── index.js │ │ │ ├── sanitizeError.js │ │ │ └── ClientError.js │ ├── jss2css │ │ ├── createClassName.js │ │ ├── transform │ │ │ ├── removeStyleSheet.js │ │ │ ├── styleSheet.js │ │ │ └── utils.js │ │ ├── utils.js │ │ └── createClientStyleManager.js │ ├── transform │ │ ├── components │ │ │ └── withStyles.js │ │ ├── flow.js │ │ └── utils.js │ ├── log │ │ └── shared │ │ │ ├── common.js │ │ │ └── createServerLog.js │ └── blockchain │ │ └── shared │ │ └── constants.js └── wallet │ ├── server │ └── index.js │ ├── shared │ ├── components │ │ ├── faq │ │ │ └── index.js │ │ ├── new │ │ │ ├── index.js │ │ │ └── NewWalletSaveKeystore.js │ │ ├── main │ │ │ ├── index.js │ │ │ └── MainWalletView.js │ │ ├── open │ │ │ └── index.js │ │ ├── info │ │ │ ├── index.js │ │ │ ├── InfoLabeled.js │ │ │ └── InfoCard.js │ │ ├── common │ │ │ ├── index.js │ │ │ └── CopyField.js │ │ ├── transaction │ │ │ ├── index.js │ │ │ └── __generated__ │ │ │ │ └── WalletTransactionsCard_address.graphql.js │ │ ├── select │ │ │ ├── index.js │ │ │ ├── __generated__ │ │ │ │ └── SelectCard_address.graphql.js │ │ │ ├── MainSelectCardLocked.js │ │ │ ├── MainSelectCard.js │ │ │ └── MainSelectCardUnlocked.js │ │ ├── paper │ │ │ ├── index.js │ │ │ ├── PaperWalletHeader.js │ │ │ ├── PaperWalletLabelLine.js │ │ │ ├── PaperWallet.js │ │ │ └── PaperWalletLabeled.js │ │ ├── keystore │ │ │ ├── index.js │ │ │ ├── SaveOrGenerateKeystore.js │ │ │ ├── SaveKeystoreFileText.js │ │ │ └── GenerateKeystore.js │ │ └── account │ │ │ ├── index.js │ │ │ ├── __generated__ │ │ │ ├── AccountView_address.graphql.js │ │ │ ├── TransferCard_address.graphql.js │ │ │ ├── TransferView_address.graphql.js │ │ │ └── AccountViewBase_address.graphql.js │ │ │ ├── TransferView.js │ │ │ └── AccountView.js │ ├── utils │ │ ├── index.js │ │ └── validatePassword.js │ ├── pages │ │ ├── index.js │ │ ├── MainWallet.js │ │ ├── NewWallet.js │ │ ├── WalletFAQ.js │ │ └── OpenWallet.js │ ├── WalletContext.js │ ├── redux │ │ └── configureStore.js │ └── routes.js │ └── client │ ├── init.js │ ├── index.html │ └── renderApp.js ├── postcss.config.js ├── internal ├── utils │ ├── index.js │ ├── profile.js │ ├── log.js │ └── logError.js ├── jss2css │ ├── watch.js │ ├── compile.js │ └── createCompiler.js └── codegen │ └── writer.js ├── gulpfile.babel.js ├── README.md ├── .babelrc ├── .flowconfig ├── .gitignore └── LICENSE.md /src/shared/log/serverLog.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export default () => {}; 3 | -------------------------------------------------------------------------------- /src/lib/components/shared/error/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export { default as Error404 } from './Error404'; 3 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/Tab.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import Tab from 'material-ui/Tabs/Tab'; 3 | 4 | export default Tab; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/Card.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import Card from 'material-ui/Card/Card'; 3 | 4 | export default Card; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/Chip.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import Chip from 'material-ui/Chip/Chip'; 3 | 4 | export default Chip; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/Grid.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import Grid from 'material-ui/Grid/Grid'; 3 | 4 | export default Grid; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/List.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import List from 'material-ui/List/List'; 3 | 4 | export default List; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/Menu.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import Menu from 'material-ui/Menu/Menu'; 3 | 4 | export default Menu; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/Tabs.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import Tabs from 'material-ui/Tabs/Tabs'; 3 | 4 | export default Tabs; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/help/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | // eslint-disable-next-line 3 | export { default as Help } from './Help'; 4 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/Input.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import Input from 'material-ui/Input/Input'; 3 | 4 | export default Input; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/Modal.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import Modal from 'material-ui/internal/Modal'; 3 | 4 | export default Modal; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/Paper.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import Paper from 'material-ui/Paper/Paper'; 3 | 4 | export default Paper; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/Radio.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import Radio from 'material-ui/Radio/Radio'; 3 | 4 | export default Radio; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/pager/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | // eslint-disable-next-line 3 | export { default as Pager } from './Pager'; 4 | -------------------------------------------------------------------------------- /src/lib/components/shared/qr/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | // eslint-disable-next-line 3 | export { default as QRCode } from './QRCode'; 4 | -------------------------------------------------------------------------------- /src/lib/components/shared/animated/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | // eslint-disable-next-line 3 | export { default as Chevron } from './Chevron'; 4 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/Button.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import Button from 'material-ui/Button/Button'; 3 | 4 | export default Button; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/Dialog.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import Dialog from 'material-ui/Dialog/Dialog'; 3 | 4 | export default Dialog; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/Drawer.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import Drawer from 'material-ui/Drawer/Drawer'; 3 | 4 | export default Drawer; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/Hidden.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import Hidden from 'material-ui/Hidden/Hidden'; 3 | 4 | export default Hidden; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/Portal.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import Portal from 'material-ui/internal/Portal'; 3 | 4 | export default Portal; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/Slide.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import Slide from 'material-ui/transitions/Slide'; 3 | 4 | export default Slide; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/tooltip/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | // eslint-disable-next-line 3 | export { default as Tooltip } from './Tooltip'; 4 | -------------------------------------------------------------------------------- /src/shared/components/common/table/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | // eslint-disable-next-line 3 | export { default as Table } from './Table'; 4 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/ListItem.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import ListItem from 'material-ui/List/ListItem'; 3 | 4 | export default ListItem; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/MenuItem.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import MenuItem from 'material-ui/Menu/MenuItem'; 3 | 4 | export default MenuItem; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/Popover.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import Popover from 'material-ui/internal/Popover'; 3 | 4 | export default Popover; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/SvgIcon.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import SvgIcon from 'material-ui/SvgIcon/SvgIcon'; 3 | 4 | export default SvgIcon; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/markdown/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | // eslint-disable-next-line 3 | export { default as Markdown } from './Markdown'; 4 | -------------------------------------------------------------------------------- /src/lib/components/shared/selector/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | // eslint-disable-next-line 3 | export { default as Selector } from './Selector'; 4 | -------------------------------------------------------------------------------- /src/shared/components/common/timeago/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | // eslint-disable-next-line 3 | export { default as TimeAgo } from './TimeAgo'; 4 | -------------------------------------------------------------------------------- /src/wallet/server/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | // eslint-disable-next-line 3 | export { default as sendRawTransaction } from './sendRawTransaction'; 4 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/Checkbox.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import Checkbox from 'material-ui/Checkbox/Checkbox'; 3 | 4 | export default Checkbox; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/Collapse.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import Collapse from 'material-ui/transitions/Collapse'; 3 | 4 | export default Collapse; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/FormLabel.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import FormLabel from 'material-ui/Form/FormLabel'; 3 | 4 | export default FormLabel; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/Snackbar.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import Snackbar from 'material-ui/Snackbar/Snackbar'; 3 | 4 | export default Snackbar; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/theme/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | // eslint-disable-next-line 3 | export { default as ThemeProvider } from './ThemeProvider'; 4 | -------------------------------------------------------------------------------- /src/shared/components/common/card/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | // eslint-disable-next-line 3 | export { default as ExpandoCard } from './ExpandoCard'; 4 | -------------------------------------------------------------------------------- /src/shared/components/common/loading/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | // eslint-disable-next-line 3 | export { default as PageLoading } from './PageLoading'; 4 | -------------------------------------------------------------------------------- /src/wallet/shared/components/faq/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | // eslint-disable-next-line 3 | export { default as WalletFAQView } from './WalletFAQView'; 4 | -------------------------------------------------------------------------------- /src/wallet/shared/components/new/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | // eslint-disable-next-line 3 | export { default as NewWalletFlow } from './NewWalletFlow'; 4 | -------------------------------------------------------------------------------- /src/wallet/shared/utils/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | // eslint-disable-next-line 3 | export { default as validatePassword } from './validatePassword'; 4 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | 'postcss-import': {}, 4 | 'postcss-cssnext': {}, 5 | 'cssnano': {} 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/CardContent.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import CardContent from 'material-ui/Card/CardContent'; 3 | 4 | export default CardContent; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/FormControl.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import FormControl from 'material-ui/Form/FormControl'; 3 | 4 | export default FormControl; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/InputLabel.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import InputLabel from 'material-ui/Input/InputLabel'; 3 | 4 | export default InputLabel; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/RadioGroup.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import RadioGroup from 'material-ui/Radio/RadioGroup'; 3 | 4 | export default RadioGroup; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/Transition.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import Transition from 'material-ui/internal/Transition'; 3 | 4 | export default Transition; 5 | -------------------------------------------------------------------------------- /src/wallet/shared/components/main/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | // eslint-disable-next-line 3 | export { default as MainWalletView } from './MainWalletView'; 4 | -------------------------------------------------------------------------------- /src/wallet/shared/components/open/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | // eslint-disable-next-line 3 | export { default as OpenWalletView } from './OpenWalletView'; 4 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/DialogTitle.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import DialogTitle from 'material-ui/Dialog/DialogTitle'; 3 | 4 | export default DialogTitle; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/IconButton.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import IconButton from 'material-ui/IconButton/IconButton'; 3 | 4 | export default IconButton; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/ListItemIcon.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import ListItemIcon from 'material-ui/List/ListItemIcon'; 3 | 4 | export default ListItemIcon; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/ListItemText.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import ListItemText from 'material-ui/List/ListItemText'; 3 | 4 | export default ListItemText; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/Typography.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import Typography from 'material-ui/Typography/Typography'; 3 | 4 | export default Typography; 5 | -------------------------------------------------------------------------------- /src/lib/graphql/shared/relay/getDisplayName.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export default (component: any) => 3 | component.displayName || component.name || 'Component'; 4 | -------------------------------------------------------------------------------- /src/shared/components/common/logo/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export { default as Logo } from './Logo'; 3 | export { default as TitleLogo } from './TitleLogo'; 4 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/DialogActions.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import DialogActions from 'material-ui/Dialog/DialogActions'; 3 | 4 | export default DialogActions; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/DialogContent.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import DialogContent from 'material-ui/Dialog/DialogContent'; 3 | 4 | export default DialogContent; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/ListSubheader.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import ListSubheader from 'material-ui/List/ListSubheader'; 3 | 4 | export default ListSubheader; 5 | -------------------------------------------------------------------------------- /src/wallet/client/init.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import '../../../__generated__/css/main.css'; 3 | // eslint-disable-next-line 4 | import 'regenerator-runtime/runtime'; 5 | -------------------------------------------------------------------------------- /src/wallet/shared/components/info/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export { default as InfoCard } from './InfoCard'; 3 | export { default as InfoView } from './InfoView'; 4 | -------------------------------------------------------------------------------- /src/lib/graphql/shared/relay/relay/getDisplayName.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export default (component: any) => 3 | component.displayName || component.name || 'Component'; 4 | -------------------------------------------------------------------------------- /src/shared/components/common/error/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export { default as ErrorView } from './ErrorView'; 3 | export { default as PageError } from './PageError'; 4 | -------------------------------------------------------------------------------- /src/shared/components/transaction/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | // eslint-disable-next-line 3 | export { default as TransactionPagingView } from './TransactionPagingView'; 4 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/FormControlLabel.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import FormControlLabel from 'material-ui/Form/FormControlLabel'; 3 | 4 | export default FormControlLabel; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/LinearProgress.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import LinearProgress from 'material-ui/Progress/LinearProgress'; 3 | 4 | export default LinearProgress; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/tooltip/Tooltip.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import 'react-tippy/dist/tippy.css' 3 | 4 | import { Tooltip } from 'react-tippy'; 5 | 6 | export default Tooltip; 7 | -------------------------------------------------------------------------------- /src/shared/components/address/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | // eslint-disable-next-line 3 | export { default as AddressTransactionPagingView } from './AddressTransactionPagingView'; 4 | -------------------------------------------------------------------------------- /src/wallet/shared/components/common/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export { default as CopyField } from './CopyField'; 3 | export { default as PasswordField } from './PasswordField'; 4 | -------------------------------------------------------------------------------- /src/wallet/shared/components/transaction/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | // eslint-disable-next-line 3 | export { default as WalletTransactionsCard } from './WalletTransactionsCard'; 4 | -------------------------------------------------------------------------------- /internal/utils/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export { default as log } from './log'; 3 | export { default as logError } from './logError' 4 | export { default as profile } from './profile' 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/ClickAwayListener.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import ClickAwayListener from 'material-ui/internal/ClickAwayListener'; 3 | 4 | export default ClickAwayListener; 5 | -------------------------------------------------------------------------------- /src/lib/utils/shared/DateTime.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | 3 | export default class DateTime { 4 | static nowInSeconds(): number { 5 | return Math.round(Date.now() / 1000); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/wallet/shared/components/select/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export { default as MainSelectCard } from './MainSelectCard'; 3 | export { default as SelectCard } from './SelectCard'; 4 | -------------------------------------------------------------------------------- /src/shared/components/contract/lib/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export { default as ContractLink } from './ContractLink'; 3 | export { default as ContractNameLink } from './ContractNameLink'; 4 | -------------------------------------------------------------------------------- /src/shared/graphql/relay/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export { default as paginationContainer } from './paginationContainer'; 3 | export { default as queryRenderer } from './queryRenderer'; 4 | -------------------------------------------------------------------------------- /src/shared/components/block/lib/getBlockSize.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import { formatNumber } from '~/src/lib/utils/shared'; 3 | 4 | export default (size: number) => `${formatNumber(size)} Bytes`; 5 | -------------------------------------------------------------------------------- /src/lib/components/shared/link/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export { default as IconLink } from './IconLink'; 3 | export { default as Link } from './Link'; 4 | 5 | 6 | export type { Type } from './Link'; 7 | -------------------------------------------------------------------------------- /src/lib/utils/objects/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export { default as entries } from './entries'; 3 | export { default as filterObject } from './filterObject'; 4 | export { default as values } from './values'; 5 | -------------------------------------------------------------------------------- /src/lib/utils/objects/values.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | 3 | // $FlowFixMe 4 | export default function entries( 5 | obj: {[key: string]: TValue}, 6 | ): Array { 7 | return Object.values(obj); 8 | } 9 | -------------------------------------------------------------------------------- /src/shared/graphql/relay/queryRenderer.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import log from '~/src/shared/log'; 3 | import { queryRenderer } from '~/src/lib/graphql/shared/relay'; 4 | 5 | export default queryRenderer(log); 6 | -------------------------------------------------------------------------------- /src/wallet/shared/components/paper/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export { default as PrintPaperWalletButton } from './PrintPaperWalletButton'; 3 | export { default as createPaperWallet } from './createPaperWallet'; 4 | -------------------------------------------------------------------------------- /src/shared/components/transaction/summary/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export { default as TransactionSummary } from './TransactionSummary'; 3 | export { default as TransactionSummaryList } from './TransactionSummaryList'; 4 | -------------------------------------------------------------------------------- /src/lib/errors/server/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export { default as CodedError } from './CodedError'; 3 | export { default as HTTPError } from './HTTPError'; 4 | export { default as ValidationError } from './ValidationError'; 5 | -------------------------------------------------------------------------------- /src/shared/graphql/relay/paginationContainer.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import log from '~/src/shared/log'; 3 | import { paginationContainer } from '~/src/lib/graphql/shared/relay'; 4 | 5 | export default paginationContainer(log); 6 | -------------------------------------------------------------------------------- /src/lib/components/shared/layout/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export { default as CardView } from './CardView'; 3 | export { default as CenteredView } from './CenteredView'; 4 | export { default as TitleCard } from './TitleCard'; 5 | -------------------------------------------------------------------------------- /src/lib/utils/objects/entries.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | 3 | // $FlowFixMe 4 | export default function entries( 5 | obj: {[key: TKey]: TValue}, 6 | ): Array<[string, TValue]> { 7 | return Object.entries(obj); 8 | } 9 | -------------------------------------------------------------------------------- /src/wallet/shared/utils/validatePassword.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export default (password: string) => { 3 | if (password.length < 8) { 4 | return 'Password must be at least 8 characters long.'; 5 | } 6 | 7 | return undefined; 8 | }; 9 | -------------------------------------------------------------------------------- /gulpfile.babel.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | /* eslint-disable */ 3 | import 'babel-polyfill'; 4 | 5 | import gulp from 'gulp'; 6 | 7 | import buildWallet from './internal/wallet/build'; 8 | 9 | gulp.task('build:wallet', () => buildWallet()); 10 | -------------------------------------------------------------------------------- /src/lib/errors/shared/BaseError.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export default class BaseError extends Error { 3 | data: ?Object; 4 | 5 | constructor(message: string, data?: Object) { 6 | super(message); 7 | this.data = data; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/lib/graphql/shared/relay/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export { default as fragmentContainer } from './fragmentContainer'; 3 | export { default as paginationContainer } from './paginationContainer'; 4 | export { default as queryRenderer } from './queryRenderer'; 5 | -------------------------------------------------------------------------------- /src/lib/graphql/shared/relay/relay/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export { default as fragmentContainer } from './fragmentContainer'; 3 | export { default as paginationContainer } from './paginationContainer'; 4 | export { default as queryRenderer } from './queryRenderer'; 5 | -------------------------------------------------------------------------------- /src/wallet/shared/components/keystore/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export { default as CreateKeystoreView } from './CreateKeystoreView'; 3 | export { default as SaveKeystoreFile } from './SaveKeystoreFile'; 4 | export { default as SaveOrGenerateKeystore } from './SaveOrGenerateKeystore'; 5 | -------------------------------------------------------------------------------- /src/shared/AppContext.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export type AppContext = {| 3 | css: Array, 4 | nonce: ?string, 5 | feature: {| 6 | wallet: {| 7 | enabled: boolean, 8 | |}, 9 | |}, 10 | routes: { 11 | makePublic: (path: string) => string, 12 | }, 13 | |}; 14 | -------------------------------------------------------------------------------- /src/lib/errors/server/ValidationError.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import CodedError from './CodedError'; 3 | 4 | export default class ValidationError extends CodedError { 5 | constructor(message: string, data?: Object) { 6 | super('VALIDATION_ERROR', message, { ...(data || {}), message }); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/shared/components/asset/lib/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export { default as AssetLink } from './AssetLink'; 3 | export { default as AssetNameLink } from './AssetNameLink'; 4 | export { default as AssetNameLinkBase } from './AssetNameLinkBase'; 5 | 6 | export { default as getName } from './getName'; 7 | -------------------------------------------------------------------------------- /src/shared/components/block/lib/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export { default as BlockIndexLink } from './BlockIndexLink'; 3 | export { default as BlockHashLink } from './BlockHashLink'; 4 | export { default as BlockTime } from './BlockTime'; 5 | 6 | export { default as getBlockSize } from './getBlockSize'; 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # neotracker-wallet 2 | 3 | https://neotracker.io/wallet 4 | 5 | See the release pages for a version of the wallet that you can run entirely locally: https://github.com/neotracker/neotracker-wallet/releases 6 | 7 | Read more about the wallet here: https://neotracker.io/wallet/faq 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/wallet/shared/components/account/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export { default as AccountCard } from './AccountCard'; 3 | export { default as AccountView } from './AccountView'; 4 | export { default as SendTransactionDialog } from './SendTransactionDialog'; 5 | export { default as TransferCard } from './TransferCard'; 6 | -------------------------------------------------------------------------------- /src/wallet/shared/pages/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export { default as CreateKeystore } from './CreateKeystore'; 3 | export { default as MainWallet } from './MainWallet'; 4 | export { default as NewWallet } from './NewWallet'; 5 | export { default as OpenWallet } from './OpenWallet'; 6 | export { default as WalletFAQ } from './WalletFAQ'; 7 | -------------------------------------------------------------------------------- /src/shared/components/transaction/lib/getTitle.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import { 3 | type TransactionType, 4 | } from '~/src/lib/blockchain/shared/constants'; 5 | 6 | const TRANSACTION_LENGTH = 'Transaction'.length; 7 | 8 | export default (type: TransactionType) => type.substring( 9 | 0, 10 | type.length - TRANSACTION_LENGTH, 11 | ); 12 | -------------------------------------------------------------------------------- /src/lib/errors/shared/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export { default as BaseError } from './BaseError'; 3 | export { 4 | COPY_UNSUPPORTED_BROWSER, 5 | NETWORK_ERROR, 6 | SOMETHING_WENT_WRONG, 7 | default as ClientError, 8 | } from './ClientError'; 9 | 10 | export { 11 | sanitizeError, 12 | sanitizeErrorNullable, 13 | } from './sanitizeError'; 14 | -------------------------------------------------------------------------------- /src/shared/components/address/lib/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export { default as AddressLink } from './AddressLink'; 3 | export { default as Coin } from './Coin'; 4 | export { default as CoinBase } from './CoinBase'; 5 | export { default as CoinTable } from './CoinTable'; 6 | export { default as CoinValue } from './CoinValue'; 7 | export { default as getSortedCoins } from './getSortedCoins'; 8 | -------------------------------------------------------------------------------- /src/lib/jss2css/createClassName.js: -------------------------------------------------------------------------------- 1 | module.exports = function createClassName(name, rule) { 2 | if (name == null) { 3 | // eslint-disable-next-line 4 | console.error(`Found null name for rule: ${rule}`) 5 | } 6 | if (rule == null) { 7 | // eslint-disable-next-line 8 | console.error(`Found null rule for name: ${name}`) 9 | } 10 | return `${name}-${rule}`; 11 | } 12 | -------------------------------------------------------------------------------- /src/lib/utils/shared/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export { default as DateTime } from './DateTime'; 3 | 4 | export { default as clipboard } from './clipboard'; 5 | export { default as createSafeRetry } from './createSafeRetry'; 6 | export { default as formatNumber } from './formatNumber'; 7 | export { default as formatTime } from './formatTime'; 8 | export { default as tryParseInt } from './tryParseInt'; 9 | -------------------------------------------------------------------------------- /src/shared/log/common.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import { type ClientLoggingContext } from './index'; 3 | 4 | export type BaseDataLayer = {| 5 | originalRequestID?: string, 6 | |}; 7 | 8 | // eslint-disable-next-line 9 | export const getBaseDataLayer = ( 10 | loggingContext: ClientLoggingContext, 11 | ): BaseDataLayer => ({ 12 | originalRequestID: loggingContext.originalRequestID, 13 | }); 14 | -------------------------------------------------------------------------------- /src/shared/components/common/view/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export { default as PageView } from './PageView'; 3 | export { default as PagingView } from './PagingView'; 4 | export { default as RightPager } from './RightPager'; 5 | export { default as SearchView } from './SearchView'; 6 | export { default as TableView } from './TableView'; 7 | 8 | export { default as getPagingStartEnd } from './getPagingStartEnd'; 9 | -------------------------------------------------------------------------------- /src/wallet/shared/WalletContext.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | export type WalletContext = {| 5 | rootPath: string, 6 | selectWallet: (state: Object) => Object, 7 | setSnackbar: ({| 8 | message: string | React.Element, 9 | timeoutMS?: number, 10 | |}) => void, 11 | showSnackbarError: ({| 12 | error: Error, 13 | |}) => void, 14 | rpcEndpoint: string, 15 | |}; 16 | -------------------------------------------------------------------------------- /src/lib/utils/shared/formatTime.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import timeago from 'timeago.js' 3 | 4 | const TWO_DAYS_MS = 2 * 24 * 60 * 60 * 1000; 5 | 6 | export default (time: number) => { 7 | let value; 8 | const timeMS = time * 1000; 9 | if ((Date.now() - timeMS) > TWO_DAYS_MS) { 10 | value = (new Date(timeMS)).toLocaleString(); 11 | } else { 12 | value = timeago().format(timeMS); 13 | } 14 | return value; 15 | } 16 | -------------------------------------------------------------------------------- /internal/utils/profile.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import now from 'performance-now'; 3 | 4 | import log from './log'; 5 | 6 | export default (title: string, what: string): { stop: () => void } => { 7 | const start = now(); 8 | return { 9 | stop: () => { 10 | const durationMS = now() - start; 11 | log({ 12 | title, 13 | message: `${what} in ${durationMS} ms`, 14 | }); 15 | }, 16 | }; 17 | }; 18 | -------------------------------------------------------------------------------- /src/wallet/shared/redux/configureStore.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import { createStore } from 'redux'; 3 | import { persistStore } from 'redux-persist'; 4 | 5 | import reducer from './index'; 6 | 7 | export default (initialState: Object = {}) => { 8 | const store = createStore( 9 | reducer, 10 | initialState, 11 | ); 12 | 13 | if (process.env.BUILD_FLAG_IS_CLIENT) { 14 | persistStore(store); 15 | } 16 | 17 | return store; 18 | }; 19 | -------------------------------------------------------------------------------- /internal/jss2css/watch.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import mkdirp from 'mkdirp'; 3 | 4 | import createCompiler from './createCompiler'; 5 | import { watch } from '../codegen/compile'; 6 | 7 | export default async ({ 8 | outputDir, 9 | jss2cssPaths, 10 | }: {| 11 | outputDir: string, 12 | jss2cssPaths: Array, 13 | |}) => { 14 | mkdirp.sync(outputDir); 15 | await watch(createCompiler({ 16 | outputDir, 17 | jss2cssPaths, 18 | })); 19 | }; 20 | -------------------------------------------------------------------------------- /src/shared/redux/timer.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import { createAction, handleActions } from 'redux-actions'; 3 | 4 | export type State = { 5 | state: boolean, 6 | }; 7 | 8 | export const flip = createAction('timer/flip'); 9 | 10 | export default handleActions( 11 | { 12 | [flip]: (state: State): State => ({ 13 | state: !state.state, 14 | }), 15 | }, 16 | { state: true }, 17 | ); 18 | 19 | export const selectTimerState = (state: State) => state.state; 20 | -------------------------------------------------------------------------------- /src/shared/components/common/view/getPagingStartEnd.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export default ({ 3 | page, 4 | pageSize, 5 | isLoadingMore, 6 | }: { 7 | page: number, 8 | pageSize: number, 9 | isLoadingMore: boolean, 10 | }) => { 11 | let start = (page - 1) * pageSize; 12 | let end = page * pageSize; 13 | let pageOut = page; 14 | if (isLoadingMore) { 15 | start -= pageSize; 16 | end -= pageSize; 17 | pageOut = page - 1; 18 | } 19 | 20 | return { start, end, pageOut }; 21 | }; 22 | -------------------------------------------------------------------------------- /internal/jss2css/compile.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import mkdirp from 'mkdirp'; 3 | import rimraf from 'rimraf'; 4 | 5 | import createCompiler from './createCompiler'; 6 | import { compile } from '../codegen/compile'; 7 | 8 | export default async ({ 9 | outputDir, 10 | jss2cssPaths, 11 | }: {| 12 | outputDir: string, 13 | jss2cssPaths: Array, 14 | |}) => { 15 | rimraf.sync(outputDir); 16 | mkdirp.sync(outputDir); 17 | 18 | await compile(createCompiler({ outputDir, jss2cssPaths })); 19 | }; 20 | -------------------------------------------------------------------------------- /src/lib/utils/shared/formatNumber.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import BigNumber from 'bignumber.js'; 3 | 4 | type Options = {| 5 | decimalPlaces?: number, 6 | |}; 7 | export default ( 8 | number: number | string, 9 | optionsIn?: Options, 10 | ): string => { 11 | const options = optionsIn || {}; 12 | const value = new BigNumber(number); 13 | const decimalPlaces = options.decimalPlaces == null 14 | ? value.decimalPlaces() 15 | : options.decimalPlaces; 16 | return value.toFormat(decimalPlaces); 17 | } 18 | -------------------------------------------------------------------------------- /internal/jss2css/createCompiler.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import appRootDir from 'app-root-dir'; 3 | 4 | import createJSS2CSSCompiler, { 5 | type JSS2CSSCompiler, 6 | } from './createJSS2CSSCompiler'; 7 | 8 | export default ({ 9 | onlyValidate, 10 | outputDir, 11 | jss2cssPaths, 12 | }: {| 13 | onlyValidate?: boolean, 14 | outputDir: string, 15 | jss2cssPaths: Array, 16 | |}): JSS2CSSCompiler => { 17 | const srcDir = appRootDir.get(); 18 | 19 | return createJSS2CSSCompiler( 20 | srcDir, 21 | outputDir, 22 | jss2cssPaths, 23 | onlyValidate, 24 | ); 25 | }; 26 | -------------------------------------------------------------------------------- /src/lib/errors/server/HTTPError.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import CodedError from './CodedError'; 3 | 4 | type StatusCode = 5 | 400 | 6 | 403 | 7 | 500; 8 | export default class HTTPError extends CodedError { 9 | expose: boolean; 10 | status: number; 11 | statusCode: number; 12 | 13 | constructor( 14 | statusCode: StatusCode, 15 | errorCode: string, 16 | message: string, 17 | data?: Object, 18 | ) { 19 | super(errorCode, message, { ...(data || {}), statusCode }); 20 | this.expose = true; 21 | this.status = statusCode; 22 | this.statusCode = statusCode; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/wallet/client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /internal/utils/log.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import gutil from 'gulp-util'; 3 | 4 | 5 | export default function log({ 6 | title, 7 | level, 8 | message, 9 | }: { 10 | title: string, 11 | level?: 'info' | 'warn' | 'error', 12 | message: string, 13 | notify?: boolean, 14 | }): void { 15 | const msg = `==> ${title} -> ${message}`; 16 | 17 | switch (level || 'info') { 18 | case 'warn': 19 | gutil.log(gutil.colors.yellow(msg)); 20 | break; 21 | case 'error': 22 | gutil.log(gutil.colors.bgRed.white(msg)); 23 | break; 24 | case 'info': 25 | default: 26 | gutil.log(gutil.colors.green(msg)); 27 | break; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/wallet/shared/components/select/__generated__/SelectCard_address.graphql.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @flow 3 | */ 4 | 5 | /* eslint-disable */ 6 | 7 | 'use strict'; 8 | 9 | /*:: 10 | import type {ConcreteFragment} from 'relay-runtime'; 11 | export type SelectCard_address = {| |}; 12 | */ 13 | 14 | 15 | const fragment /*: ConcreteFragment*/ = { 16 | "argumentDefinitions": [], 17 | "kind": "Fragment", 18 | "metadata": null, 19 | "name": "SelectCard_address", 20 | "selections": [ 21 | { 22 | "kind": "FragmentSpread", 23 | "name": "AccountView_address", 24 | "args": null 25 | } 26 | ], 27 | "type": "Address" 28 | }; 29 | 30 | module.exports = fragment; 31 | -------------------------------------------------------------------------------- /src/wallet/shared/components/account/__generated__/AccountView_address.graphql.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @flow 3 | */ 4 | 5 | /* eslint-disable */ 6 | 7 | 'use strict'; 8 | 9 | /*:: 10 | import type {ConcreteFragment} from 'relay-runtime'; 11 | export type AccountView_address = {| |}; 12 | */ 13 | 14 | 15 | const fragment /*: ConcreteFragment*/ = { 16 | "argumentDefinitions": [], 17 | "kind": "Fragment", 18 | "metadata": null, 19 | "name": "AccountView_address", 20 | "selections": [ 21 | { 22 | "kind": "FragmentSpread", 23 | "name": "AccountViewBase_address", 24 | "args": null 25 | } 26 | ], 27 | "type": "Address" 28 | }; 29 | 30 | module.exports = fragment; 31 | -------------------------------------------------------------------------------- /src/wallet/shared/components/account/__generated__/TransferCard_address.graphql.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @flow 3 | */ 4 | 5 | /* eslint-disable */ 6 | 7 | 'use strict'; 8 | 9 | /*:: 10 | import type {ConcreteFragment} from 'relay-runtime'; 11 | export type TransferCard_address = {| |}; 12 | */ 13 | 14 | 15 | const fragment /*: ConcreteFragment*/ = { 16 | "argumentDefinitions": [], 17 | "kind": "Fragment", 18 | "metadata": null, 19 | "name": "TransferCard_address", 20 | "selections": [ 21 | { 22 | "kind": "FragmentSpread", 23 | "name": "TransferView_address", 24 | "args": null 25 | } 26 | ], 27 | "type": "Address" 28 | }; 29 | 30 | module.exports = fragment; 31 | -------------------------------------------------------------------------------- /src/wallet/shared/components/account/__generated__/TransferView_address.graphql.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @flow 3 | */ 4 | 5 | /* eslint-disable */ 6 | 7 | 'use strict'; 8 | 9 | /*:: 10 | import type {ConcreteFragment} from 'relay-runtime'; 11 | export type TransferView_address = {| |}; 12 | */ 13 | 14 | 15 | const fragment /*: ConcreteFragment*/ = { 16 | "argumentDefinitions": [], 17 | "kind": "Fragment", 18 | "metadata": null, 19 | "name": "TransferView_address", 20 | "selections": [ 21 | { 22 | "kind": "FragmentSpread", 23 | "name": "SendTransaction_address", 24 | "args": null 25 | } 26 | ], 27 | "type": "Address" 28 | }; 29 | 30 | module.exports = fragment; 31 | -------------------------------------------------------------------------------- /src/lib/errors/shared/sanitizeError.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import ClientError, { 3 | SOMETHING_WENT_WRONG 4 | } from './ClientError'; 5 | 6 | export const sanitizeErrorNullable = (error: Error): ?ClientError => { 7 | if (error instanceof ClientError) { 8 | return error; 9 | } 10 | 11 | const clientError = ClientError.getClientError(error); 12 | if (clientError != null) { 13 | return clientError; 14 | } 15 | 16 | return null; 17 | }; 18 | 19 | export const sanitizeError = (error: Error): ClientError => { 20 | const sanitizedError = sanitizeErrorNullable(error); 21 | return sanitizedError == null 22 | ? new ClientError(SOMETHING_WENT_WRONG) 23 | : sanitizedError; 24 | }; 25 | -------------------------------------------------------------------------------- /src/lib/utils/shared/createSafeRetry.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | const RETRY_INTERVAL = 30000; 3 | export default (retryInterval: number = RETRY_INTERVAL) => { 4 | let retrying = false; 5 | let timer; 6 | 7 | const retry = (retryFunc: () => void) => { 8 | if (!retrying) { 9 | retrying = true; 10 | timer = setTimeout( 11 | () => { 12 | retrying = false; 13 | timer = null; 14 | retryFunc(); 15 | }, 16 | retryInterval, 17 | ); 18 | } 19 | }; 20 | 21 | retry.cancel = () => { 22 | if (timer) { 23 | clearTimeout(timer); 24 | retrying = false; 25 | timer = null; 26 | } 27 | }; 28 | 29 | return retry; 30 | }; 31 | -------------------------------------------------------------------------------- /src/lib/utils/shared/tryParseInt.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import { 3 | SOMETHING_WENT_WRONG, 4 | ClientError, 5 | } from '~/src/lib/errors/shared'; 6 | 7 | const DEFAULT = Object.create(null); 8 | 9 | export default ({ 10 | value, 11 | // $FlowFixMe 12 | default: defaultValue = DEFAULT, 13 | }: {| 14 | value: string, 15 | default?: ?number | typeof DEFAULT, 16 | |}) => { 17 | const result = Number(value); 18 | if (Number.isNaN(result)) { 19 | if (defaultValue === DEFAULT) { 20 | throw new ClientError( 21 | SOMETHING_WENT_WRONG, 22 | { message: 'Not a number', value }, 23 | ); 24 | } else { 25 | return defaultValue; 26 | } 27 | } 28 | return result; 29 | }; 30 | -------------------------------------------------------------------------------- /src/shared/components/block/lib/__generated__/BlockTime_block.graphql.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @flow 3 | */ 4 | 5 | /* eslint-disable */ 6 | 7 | 'use strict'; 8 | 9 | /*:: 10 | import type {ConcreteFragment} from 'relay-runtime'; 11 | export type BlockTime_block = {| 12 | +time: number; 13 | |}; 14 | */ 15 | 16 | 17 | const fragment /*: ConcreteFragment*/ = { 18 | "argumentDefinitions": [], 19 | "kind": "Fragment", 20 | "metadata": null, 21 | "name": "BlockTime_block", 22 | "selections": [ 23 | { 24 | "kind": "ScalarField", 25 | "alias": null, 26 | "args": null, 27 | "name": "time", 28 | "storageKey": null 29 | } 30 | ], 31 | "type": "Block" 32 | }; 33 | 34 | module.exports = fragment; 35 | -------------------------------------------------------------------------------- /src/shared/components/transaction/lib/DownArrow.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | pure, 7 | } from 'recompose'; 8 | 9 | import { Icon } from '~/src/lib/components/shared/base'; 10 | 11 | type ExternalProps = {| 12 | className?: string, 13 | |}; 14 | // eslint-disable-next-line 15 | type InternalProps = {| 16 | |}; 17 | /* :: 18 | type Props = {| 19 | ...ExternalProps, 20 | ...InternalProps, 21 | |}; 22 | */ 23 | function DownArrow({ 24 | className, 25 | }: Props): React.Element<*> { 26 | return keyboard_arrow_down; 27 | } 28 | 29 | export default (compose( 30 | pure, 31 | )(DownArrow): Class>); 32 | -------------------------------------------------------------------------------- /src/shared/components/transaction/lib/RightArrow.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | pure, 7 | } from 'recompose'; 8 | 9 | import { Icon } from '~/src/lib/components/shared/base'; 10 | 11 | type ExternalProps = {| 12 | className?: string, 13 | |}; 14 | // eslint-disable-next-line 15 | type InternalProps = {| 16 | |}; 17 | /* :: 18 | type Props = {| 19 | ...ExternalProps, 20 | ...InternalProps, 21 | |}; 22 | */ 23 | function RightArrow({ 24 | className, 25 | }: Props): React.Element<*> { 26 | return keyboard_arrow_right; 27 | } 28 | 29 | export default (compose( 30 | pure, 31 | )(RightArrow): Class>); 32 | -------------------------------------------------------------------------------- /src/wallet/shared/components/transaction/__generated__/WalletTransactionsCard_address.graphql.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @flow 3 | */ 4 | 5 | /* eslint-disable */ 6 | 7 | 'use strict'; 8 | 9 | /*:: 10 | import type {ConcreteFragment} from 'relay-runtime'; 11 | export type WalletTransactionsCard_address = {| |}; 12 | */ 13 | 14 | 15 | const fragment /*: ConcreteFragment*/ = { 16 | "argumentDefinitions": [], 17 | "kind": "Fragment", 18 | "metadata": null, 19 | "name": "WalletTransactionsCard_address", 20 | "selections": [ 21 | { 22 | "kind": "FragmentSpread", 23 | "name": "AddressTransactionPagingView_address", 24 | "args": null 25 | } 26 | ], 27 | "type": "Address" 28 | }; 29 | 30 | module.exports = fragment; 31 | -------------------------------------------------------------------------------- /src/shared/components/block/lib/__generated__/BlockHashLink_block.graphql.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @flow 3 | */ 4 | 5 | /* eslint-disable */ 6 | 7 | 'use strict'; 8 | 9 | /*:: 10 | import type {ConcreteFragment} from 'relay-runtime'; 11 | export type BlockHashLink_block = {| 12 | +hash: string; 13 | |}; 14 | */ 15 | 16 | 17 | const fragment /*: ConcreteFragment*/ = { 18 | "argumentDefinitions": [], 19 | "kind": "Fragment", 20 | "metadata": null, 21 | "name": "BlockHashLink_block", 22 | "selections": [ 23 | { 24 | "kind": "ScalarField", 25 | "alias": null, 26 | "args": null, 27 | "name": "hash", 28 | "storageKey": null 29 | } 30 | ], 31 | "type": "Block" 32 | }; 33 | 34 | module.exports = fragment; 35 | -------------------------------------------------------------------------------- /src/shared/components/block/lib/__generated__/BlockIndexLink_block.graphql.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @flow 3 | */ 4 | 5 | /* eslint-disable */ 6 | 7 | 'use strict'; 8 | 9 | /*:: 10 | import type {ConcreteFragment} from 'relay-runtime'; 11 | export type BlockIndexLink_block = {| 12 | +index: number; 13 | |}; 14 | */ 15 | 16 | 17 | const fragment /*: ConcreteFragment*/ = { 18 | "argumentDefinitions": [], 19 | "kind": "Fragment", 20 | "metadata": null, 21 | "name": "BlockIndexLink_block", 22 | "selections": [ 23 | { 24 | "kind": "ScalarField", 25 | "alias": null, 26 | "args": null, 27 | "name": "index", 28 | "storageKey": null 29 | } 30 | ], 31 | "type": "Block" 32 | }; 33 | 34 | module.exports = fragment; 35 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "react", 4 | "flow", 5 | ["env", { 6 | "targets": { "node": true }, 7 | "exclude": [ 8 | "transform-es2015-classes", 9 | "transform-async-to-generator", 10 | "transform-regenerator" 11 | ] 12 | }] 13 | ], 14 | "plugins": [ 15 | "babel-plugin-root-import", 16 | "babel-plugin-idx", 17 | "relay", 18 | "transform-runtime", 19 | "transform-class-properties", 20 | "transform-export-extensions", 21 | "transform-object-rest-spread" 22 | ], 23 | "env": { 24 | "production": { 25 | "plugins": [ 26 | "babel-plugin-transform-react-constant-elements", 27 | "transform-react-inline-elements" 28 | ] 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/lib/components/shared/theme/ThemeProvider.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | withContext, 7 | pure, 8 | } from 'recompose'; 9 | 10 | type ExternalProps = {| 11 | styleManager: any, 12 | children?: any, 13 | |}; 14 | // eslint-disable-next-line 15 | type InternalProps = {| 16 | |}; 17 | /* :: 18 | type Props = {| 19 | ...ExternalProps, 20 | ...InternalProps, 21 | |}; 22 | */ 23 | function ThemeProvider({ 24 | children, 25 | }: Props): ?React.Element<*> { 26 | return children; 27 | } 28 | 29 | export default (compose( 30 | withContext( 31 | { styleManager: () => null }, 32 | ({ styleManager }) => ({ styleManager }), 33 | ), 34 | pure, 35 | )(ThemeProvider): Class>); 36 | -------------------------------------------------------------------------------- /src/shared/components/transaction/__generated__/TransactionPagingView_transactions.graphql.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @flow 3 | */ 4 | 5 | /* eslint-disable */ 6 | 7 | 'use strict'; 8 | 9 | /*:: 10 | import type {ConcreteFragment} from 'relay-runtime'; 11 | export type TransactionPagingView_transactions = $ReadOnlyArray<{| |}>; 12 | */ 13 | 14 | 15 | const fragment /*: ConcreteFragment*/ = { 16 | "argumentDefinitions": [], 17 | "kind": "Fragment", 18 | "metadata": { 19 | "plural": true 20 | }, 21 | "name": "TransactionPagingView_transactions", 22 | "selections": [ 23 | { 24 | "kind": "FragmentSpread", 25 | "name": "TransactionTable_transactions", 26 | "args": null 27 | } 28 | ], 29 | "type": "Transaction" 30 | }; 31 | 32 | module.exports = fragment; 33 | -------------------------------------------------------------------------------- /internal/utils/logError.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import log from './log'; 3 | 4 | export default function logError({ 5 | title, 6 | message, 7 | errorMessage, 8 | error, 9 | notify, 10 | }: { 11 | title: string, 12 | message: string, 13 | errorMessage?: string, 14 | error?: Error, 15 | notify?: boolean, 16 | }): void { 17 | log({ 18 | title, 19 | message: `${message} Please check the console for more information.`, 20 | level: 'error', 21 | notify: notify == null ? true : notify, 22 | }); 23 | if (error) { 24 | // eslint-disable-next-line no-console 25 | console.error(error); 26 | } 27 | if (errorMessage) { 28 | log({ 29 | title, 30 | message: errorMessage, 31 | level: 'error', 32 | notify: false, 33 | }); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/shared/components/transaction/lib/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export { default as DownArrow } from './DownArrow'; 3 | export { default as RightArrow } from './RightArrow'; 4 | export { 5 | default as TransactionHeaderBackground, 6 | getBackgroundClassName, 7 | } from './TransactionHeaderBackground'; 8 | export { default as TransactionInputTable } from './TransactionInputTable'; 9 | export { default as TransactionLink } from './TransactionLink'; 10 | export { default as TransactionOutputTable } from './TransactionOutputTable'; 11 | export { default as TransactionTimeLink } from './TransactionTimeLink'; 12 | export { default as TransactionTypeAndLink } from './TransactionTypeAndLink'; 13 | 14 | export { default as getIcon } from './getIcon'; 15 | export { default as getTitle } from './getTitle'; 16 | -------------------------------------------------------------------------------- /src/shared/components/transaction/lib/__generated__/TransactionHeaderBackground_transaction.graphql.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @flow 3 | */ 4 | 5 | /* eslint-disable */ 6 | 7 | 'use strict'; 8 | 9 | /*:: 10 | import type {ConcreteFragment} from 'relay-runtime'; 11 | export type TransactionHeaderBackground_transaction = {| 12 | +type: string; 13 | |}; 14 | */ 15 | 16 | 17 | const fragment /*: ConcreteFragment*/ = { 18 | "argumentDefinitions": [], 19 | "kind": "Fragment", 20 | "metadata": null, 21 | "name": "TransactionHeaderBackground_transaction", 22 | "selections": [ 23 | { 24 | "kind": "ScalarField", 25 | "alias": null, 26 | "args": null, 27 | "name": "type", 28 | "storageKey": null 29 | } 30 | ], 31 | "type": "Transaction" 32 | }; 33 | 34 | module.exports = fragment; 35 | -------------------------------------------------------------------------------- /src/shared/redux/snackbar.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import type React from 'react'; 3 | 4 | import { createAction, handleActions } from 'redux-actions'; 5 | 6 | export type SnackbarProps = { 7 | message: string | React.Element, 8 | action: React.Element, 9 | omitClose?: boolean, 10 | timeoutMS?: number, 11 | }; 12 | export type State = { 13 | props: ?SnackbarProps, 14 | }; 15 | 16 | export const setSnackbar = createAction('snackbar/setSnackbar'); 17 | export const clearSnackbar = createAction('snackbar/clearSnackbar'); 18 | 19 | export default handleActions( 20 | { 21 | [setSnackbar]: (state: State, { payload }): State => ({ 22 | props: payload, 23 | }), 24 | [clearSnackbar]: (): State => ({ props: null }), 25 | }, 26 | { props: null }, 27 | ); 28 | 29 | export const selectSnackbarProps = (state: State) => state.props; 30 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [version] 2 | 0.52.0 3 | 4 | [ignore] 5 | ; .*/node_modules/jss/.* 6 | ; .*/node_modules/jss-props-sort/.* 7 | ; .*/node_modules/jss-theme-reactor/.* 8 | ; .*/node_modules/jss-vendor-prefixer/.* 9 | ; .*/node_modules/jss-nested/.* 10 | ; .*/node_modules/jss-global/.* 11 | ; .*/node_modules/jss-preset-default/.* 12 | ; .*/node_modules/jss-extend/.* 13 | ; .*/node_modules/jss-expand/.* 14 | ; .*/node_modules/jss-default-unit/.* 15 | ; .*/node_modules/jss-compose/.* 16 | ; .*/node_modules/jss-camel-case/.* 17 | .*/node_modules/eslint-plugin-jsx-a11y/.* 18 | .*/node_modules/config-chain/.* 19 | 20 | [include] 21 | 22 | [libs] 23 | decls/ 24 | 25 | [options] 26 | module.name_mapper='^~/\(.*\)$' -> '/\1' 27 | module.use_strict=true 28 | 29 | esproposal.decorators=ignore 30 | esproposal.export_star_as=enable 31 | 32 | unsafe.enable_getters_and_setters=true 33 | -------------------------------------------------------------------------------- /src/lib/errors/server/CodedError.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import ClientError, { 3 | SOMETHING_WENT_WRONG, 4 | } from '../shared/ClientError'; 5 | 6 | const ERROR_CODES = { 7 | GRAPHQL_QUERY_NOT_FOUND_ERROR: SOMETHING_WENT_WRONG, 8 | INVALID_CSRF_TOKEN: SOMETHING_WENT_WRONG, 9 | NOT_FOUND_ERROR: SOMETHING_WENT_WRONG, 10 | PROGRAMMING_ERROR: SOMETHING_WENT_WRONG, 11 | }; 12 | 13 | export default class CodedError extends ClientError { 14 | static GRAPHQL_QUERY_NOT_FOUND_ERROR = 'GRAPHQL_QUERY_NOT_FOUND_ERROR'; 15 | static INVALID_CSRF_TOKEN = 'INVALID_CSRF_TOKEN'; 16 | static NOT_FOUND_ERROR = 'NOT_FOUND_ERROR'; 17 | static PROGRAMMING_ERROR = 'PROGRAMMING_ERROR'; 18 | 19 | static ERROR_CODES = ERROR_CODES; 20 | 21 | constructor(errorCode: string, message: string, data?: Object) { 22 | super( 23 | message, 24 | { ...(data || {}), errorCode }, 25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/lib/transform/components/withStyles.js: -------------------------------------------------------------------------------- 1 | // @flow weak 2 | import { hoistStatics, withProps } from 'recompose'; 3 | 4 | export default styleSheet => BaseComponent => { 5 | const Component = hoistStatics(withProps(({ 6 | classes: classesProp, 7 | innerRef, 8 | ...other 9 | }) => { 10 | let classes; 11 | if (classesProp) { 12 | classes = Object.keys(styleSheet).reduce((acc, key) => { 13 | if (classesProp[key] == null) { 14 | acc[key] = styleSheet[key] 15 | } else { 16 | acc[key] = `${styleSheet[key]} ${classesProp[key]}`; 17 | } 18 | return acc; 19 | }, {}); 20 | } else { 21 | classes = styleSheet; 22 | } 23 | 24 | return { 25 | classes, 26 | ref: innerRef, 27 | ...other, 28 | }; 29 | }))(BaseComponent); 30 | 31 | Component.Naked = BaseComponent; 32 | return Component; 33 | } 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Environment Configuration 2 | .env 3 | 4 | # Build output folders 5 | /build/ 6 | /keys/ 7 | /__generated__/ 8 | /__generated__/css/ 9 | /certbot/ 10 | /logs/ 11 | 12 | # Logs 13 | logs 14 | *.log 15 | 16 | # Runtime data 17 | pids 18 | *.pid 19 | *.seed 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | 24 | # node-waf configuration 25 | .lock-wscript 26 | 27 | # Dependency directory 28 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- 29 | node_modules 30 | 31 | # Debug log from npm 32 | npm-debug.log 33 | 34 | # IntelliJ IDE ignore 35 | .idea 36 | 37 | # Visual Studio Code 38 | .vscode 39 | .history 40 | 41 | # flow-typed Lib Defs 42 | flow-typed/ 43 | 44 | # Flow Coverage Report 45 | flow-coverage/ 46 | 47 | # Happypack 48 | .happypack 49 | 50 | # OSX Files 51 | .DS_Store 52 | 53 | src/server/graphql/__generated__/persistedQueries.json 54 | -------------------------------------------------------------------------------- /src/shared/components/contract/lib/__generated__/ContractNameLink_contract.graphql.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @flow 3 | */ 4 | 5 | /* eslint-disable */ 6 | 7 | 'use strict'; 8 | 9 | /*:: 10 | import type {ConcreteFragment} from 'relay-runtime'; 11 | export type ContractNameLink_contract = {| 12 | +hash: string; 13 | +name: string; 14 | |}; 15 | */ 16 | 17 | 18 | const fragment /*: ConcreteFragment*/ = { 19 | "argumentDefinitions": [], 20 | "kind": "Fragment", 21 | "metadata": null, 22 | "name": "ContractNameLink_contract", 23 | "selections": [ 24 | { 25 | "kind": "ScalarField", 26 | "alias": null, 27 | "args": null, 28 | "name": "hash", 29 | "storageKey": null 30 | }, 31 | { 32 | "kind": "ScalarField", 33 | "alias": null, 34 | "args": null, 35 | "name": "name", 36 | "storageKey": null 37 | } 38 | ], 39 | "type": "Contract" 40 | }; 41 | 42 | module.exports = fragment; 43 | -------------------------------------------------------------------------------- /src/shared/components/transaction/__generated__/TransactionTable_transactions.graphql.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @flow 3 | */ 4 | 5 | /* eslint-disable */ 6 | 7 | 'use strict'; 8 | 9 | /*:: 10 | import type {ConcreteFragment} from 'relay-runtime'; 11 | export type TransactionTable_transactions = $ReadOnlyArray<{| 12 | +hash: string; 13 | |}>; 14 | */ 15 | 16 | 17 | const fragment /*: ConcreteFragment*/ = { 18 | "argumentDefinitions": [], 19 | "kind": "Fragment", 20 | "metadata": { 21 | "plural": true 22 | }, 23 | "name": "TransactionTable_transactions", 24 | "selections": [ 25 | { 26 | "kind": "ScalarField", 27 | "alias": null, 28 | "args": null, 29 | "name": "hash", 30 | "storageKey": null 31 | }, 32 | { 33 | "kind": "FragmentSpread", 34 | "name": "TransactionSummary_transaction", 35 | "args": null 36 | } 37 | ], 38 | "type": "Transaction" 39 | }; 40 | 41 | module.exports = fragment; 42 | -------------------------------------------------------------------------------- /src/wallet/shared/pages/MainWallet.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import Helmet from 'react-helmet'; 3 | import React from 'react'; 4 | 5 | import { 6 | compose, 7 | pure, 8 | } from 'recompose'; 9 | 10 | import { 11 | CenteredView, 12 | } from '~/src/lib/components/shared/layout'; 13 | import { MainWalletView } from '~/src/wallet/shared/components/main'; 14 | 15 | type ExternalProps = {| 16 | className?: string, 17 | |}; 18 | // eslint-disable-next-line 19 | type InternalProps = {| 20 | |}; 21 | /* :: 22 | type Props = {| 23 | ...ExternalProps, 24 | ...InternalProps, 25 | |}; 26 | */ 27 | function MainWallet({ 28 | className, 29 | }: Props): React.Element<*> { 30 | return ( 31 | 32 | {'Wallet'} 33 | 34 | 35 | ); 36 | } 37 | 38 | export default (compose( 39 | pure, 40 | )(MainWallet): Class>); 41 | -------------------------------------------------------------------------------- /src/wallet/shared/pages/NewWallet.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import Helmet from 'react-helmet'; 3 | import React from 'react'; 4 | 5 | import { 6 | compose, 7 | pure, 8 | } from 'recompose'; 9 | 10 | import { 11 | CardView, 12 | } from '~/src/lib/components/shared/layout'; 13 | import { NewWalletFlow } from '~/src/wallet/shared/components/new'; 14 | 15 | type ExternalProps = {| 16 | className?: string, 17 | |}; 18 | // eslint-disable-next-line 19 | type InternalProps = {| 20 | |}; 21 | /* :: 22 | type Props = {| 23 | ...ExternalProps, 24 | ...InternalProps, 25 | |}; 26 | */ 27 | function NewWallet({ 28 | className, 29 | }: Props): React.Element<*> { 30 | return ( 31 | 32 | {'New Wallet'} 33 | 34 | 35 | ); 36 | } 37 | 38 | export default (compose( 39 | pure, 40 | )(NewWallet): Class>); 41 | -------------------------------------------------------------------------------- /src/wallet/shared/pages/WalletFAQ.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import Helmet from 'react-helmet'; 3 | import React from 'react'; 4 | 5 | import { 6 | compose, 7 | pure, 8 | } from 'recompose'; 9 | 10 | import { 11 | CardView, 12 | } from '~/src/lib/components/shared/layout'; 13 | import { WalletFAQView } from '~/src/wallet/shared/components/faq'; 14 | 15 | type ExternalProps = {| 16 | className?: string, 17 | |}; 18 | // eslint-disable-next-line 19 | type InternalProps = {| 20 | |}; 21 | /* :: 22 | type Props = {| 23 | ...ExternalProps, 24 | ...InternalProps, 25 | |}; 26 | */ 27 | function WalletFAQ({ 28 | className, 29 | }: Props): React.Element<*> { 30 | return ( 31 | 32 | {'Wallet FAQ'} 33 | 34 | 35 | ); 36 | } 37 | 38 | export default (compose( 39 | pure, 40 | )(WalletFAQ): Class>); 41 | -------------------------------------------------------------------------------- /src/lib/jss2css/transform/removeStyleSheet.js: -------------------------------------------------------------------------------- 1 | const t = require('babel-types'); 2 | 3 | const { 4 | isJSSThemeReactorImport, 5 | isJSSThemeReactorRequire, 6 | } = require('./utils'); 7 | 8 | module.exports = () => ({ 9 | visitor: { 10 | Program: { 11 | exit(path) { 12 | const bodyPaths = path.get('body'); 13 | bodyPaths.forEach(bodyPath => { 14 | if ( 15 | t.isImportDeclaration(bodyPath.node) && 16 | bodyPath.node.specifiers.length === 1 && 17 | isJSSThemeReactorImport(bodyPath.get('specifiers')[0]) 18 | ) { 19 | bodyPath.remove(); 20 | } else if ( 21 | t.isVariableDeclaration(bodyPath.node) && 22 | bodyPath.node.declarations.length === 1 && 23 | isJSSThemeReactorRequire(bodyPath.node.declarations[0].init) 24 | ) { 25 | bodyPath.remove(); 26 | } 27 | }); 28 | }, 29 | }, 30 | }, 31 | }); 32 | -------------------------------------------------------------------------------- /src/wallet/shared/pages/OpenWallet.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import Helmet from 'react-helmet'; 3 | import React from 'react'; 4 | 5 | import { 6 | compose, 7 | pure, 8 | } from 'recompose'; 9 | 10 | import { 11 | CardView, 12 | } from '~/src/lib/components/shared/layout'; 13 | import { OpenWalletView } from '~/src/wallet/shared/components/open'; 14 | 15 | type ExternalProps = {| 16 | className?: string, 17 | |}; 18 | // eslint-disable-next-line 19 | type InternalProps = {| 20 | |}; 21 | /* :: 22 | type Props = {| 23 | ...ExternalProps, 24 | ...InternalProps, 25 | |}; 26 | */ 27 | function OpenWallet({ 28 | className, 29 | }: Props): React.Element<*> { 30 | return ( 31 | 32 | {'Open Wallet'} 33 | 34 | 35 | ); 36 | } 37 | 38 | export default (compose( 39 | pure, 40 | )(OpenWallet): Class>); 41 | -------------------------------------------------------------------------------- /src/shared/components/transaction/lib/__generated__/TransactionTypeAndLink_transaction.graphql.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @flow 3 | */ 4 | 5 | /* eslint-disable */ 6 | 7 | 'use strict'; 8 | 9 | /*:: 10 | import type {ConcreteFragment} from 'relay-runtime'; 11 | export type TransactionTypeAndLink_transaction = {| 12 | +type: string; 13 | +hash: string; 14 | |}; 15 | */ 16 | 17 | 18 | const fragment /*: ConcreteFragment*/ = { 19 | "argumentDefinitions": [], 20 | "kind": "Fragment", 21 | "metadata": null, 22 | "name": "TransactionTypeAndLink_transaction", 23 | "selections": [ 24 | { 25 | "kind": "ScalarField", 26 | "alias": null, 27 | "args": null, 28 | "name": "type", 29 | "storageKey": null 30 | }, 31 | { 32 | "kind": "ScalarField", 33 | "alias": null, 34 | "args": null, 35 | "name": "hash", 36 | "storageKey": null 37 | } 38 | ], 39 | "type": "Transaction" 40 | }; 41 | 42 | module.exports = fragment; 43 | -------------------------------------------------------------------------------- /src/shared/components/transaction/summary/__generated__/TransactionSummaryList_transactions.graphql.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @flow 3 | */ 4 | 5 | /* eslint-disable */ 6 | 7 | 'use strict'; 8 | 9 | /*:: 10 | import type {ConcreteFragment} from 'relay-runtime'; 11 | export type TransactionSummaryList_transactions = $ReadOnlyArray<{| 12 | +hash: string; 13 | |}>; 14 | */ 15 | 16 | 17 | const fragment /*: ConcreteFragment*/ = { 18 | "argumentDefinitions": [], 19 | "kind": "Fragment", 20 | "metadata": { 21 | "plural": true 22 | }, 23 | "name": "TransactionSummaryList_transactions", 24 | "selections": [ 25 | { 26 | "kind": "ScalarField", 27 | "alias": null, 28 | "args": null, 29 | "name": "hash", 30 | "storageKey": null 31 | }, 32 | { 33 | "kind": "FragmentSpread", 34 | "name": "TransactionSummary_transaction", 35 | "args": null 36 | } 37 | ], 38 | "type": "Transaction" 39 | }; 40 | 41 | module.exports = fragment; 42 | -------------------------------------------------------------------------------- /src/lib/components/shared/layout/CardView.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | pure, 7 | } from 'recompose'; 8 | 9 | import CenteredView from './CenteredView'; 10 | import TitleCard from './TitleCard'; 11 | 12 | type ExternalProps = {| 13 | title: string, 14 | extra?: React.Element, 15 | children?: any, 16 | className?: string, 17 | |}; 18 | // eslint-disable-next-line 19 | type InternalProps = {| 20 | |}; 21 | /* :: 22 | type Props = {| 23 | ...ExternalProps, 24 | ...InternalProps, 25 | |}; 26 | */ 27 | function CardView({ 28 | title, 29 | children, 30 | extra, 31 | className, 32 | }: Props): React.Element<*> { 33 | return ( 34 | 35 | 36 | {children} 37 | 38 | {extra} 39 | 40 | ); 41 | } 42 | 43 | export default (compose( 44 | pure, 45 | )(CardView): Class>); 46 | -------------------------------------------------------------------------------- /src/lib/transform/flow.js: -------------------------------------------------------------------------------- 1 | const t = require("babel-types"); 2 | 3 | // eslint-disable-next-line 4 | module.exports = () => { 5 | return { 6 | visitor: { 7 | ImportDeclaration: { 8 | enter: (path) => { 9 | const node = path.node; 10 | if (node.importKind !== 'value') { 11 | return; 12 | } 13 | 14 | if (!node.specifiers.every(specifier => isTypeSpecifier(specifier))) { 15 | return; 16 | } 17 | 18 | const declaration = t.importDeclaration( 19 | node.specifiers.map(specifier => t.importSpecifier( 20 | specifier.local, 21 | specifier.imported, 22 | )), 23 | node.source, 24 | ); 25 | declaration.importKind = 'type'; 26 | path.replaceWith(declaration); 27 | }, 28 | }, 29 | }, 30 | }; 31 | }; 32 | 33 | const isTypeSpecifier = node => 34 | t.isImportSpecifier(node) && 35 | node.importKind === 'type'; 36 | -------------------------------------------------------------------------------- /src/wallet/shared/routes.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import type { WalletContext } from './WalletContext'; 3 | 4 | export const HOME = '/'; 5 | export const PUBLIC = '/public'; 6 | export const SEND_RAW_TRANSACTION = '/api/v1/sendrawtransaction'; 7 | 8 | export const NEW_WALLET = '/new-wallet'; 9 | export const isNewWallet = (path: string) => 10 | path.endsWith('/new-wallet') || 11 | path.endsWith('/new-wallet/'); 12 | 13 | export const OPEN_WALLET = '/open-wallet'; 14 | export const isOpenWallet = (path: string) => 15 | path.endsWith('/open-wallet') || 16 | path.endsWith('/open-wallet/'); 17 | 18 | export const CREATE_KEYSTORE = '/create-keystore'; 19 | 20 | export const WALLET_FAQ = '/faq'; 21 | 22 | export const makePublic = (path: string) => `${PUBLIC}${path}`; 23 | 24 | export const makePath = (context: WalletContext, path: string) => { 25 | if (context.rootPath.endsWith('/')) { 26 | return `${context.rootPath}${path.substring(1)}`; 27 | } 28 | 29 | return `${context.rootPath}${path}`; 30 | } 31 | -------------------------------------------------------------------------------- /src/shared/components/block/lib/BlockHashLink.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | getContext, 7 | pure, 8 | } from 'recompose'; 9 | 10 | import { Link } from '~/src/lib/components/shared/link'; 11 | 12 | import * as routes from '~/src/shared/routes'; 13 | 14 | type ExternalProps = {| 15 | blockHash: string, 16 | className?: string, 17 | |}; 18 | // eslint-disable-next-line 19 | type InternalProps = {||}; 20 | /* :: 21 | type Props = {| 22 | ...ExternalProps, 23 | ...InternalProps, 24 | |}; 25 | */ 26 | function BlockHashLink({ 27 | blockHash, 28 | className, 29 | }: Props): React.Element<*> { 30 | return ( 31 | 37 | ); 38 | } 39 | 40 | export default (compose( 41 | getContext({ styleManager: () => null }), 42 | pure, 43 | )(BlockHashLink): Class>); 44 | -------------------------------------------------------------------------------- /src/shared/components/transaction/lib/__generated__/TransactionInputTable_inputs.graphql.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @flow 3 | */ 4 | 5 | /* eslint-disable */ 6 | 7 | 'use strict'; 8 | 9 | /*:: 10 | import type {ConcreteFragment} from 'relay-runtime'; 11 | export type TransactionInputTable_inputs = $ReadOnlyArray<{| 12 | +output_transaction_hash: string; 13 | |}>; 14 | */ 15 | 16 | 17 | const fragment /*: ConcreteFragment*/ = { 18 | "argumentDefinitions": [], 19 | "kind": "Fragment", 20 | "metadata": { 21 | "plural": true 22 | }, 23 | "name": "TransactionInputTable_inputs", 24 | "selections": [ 25 | { 26 | "kind": "FragmentSpread", 27 | "name": "TransactionInputOutputTable_input_outputs", 28 | "args": null 29 | }, 30 | { 31 | "kind": "ScalarField", 32 | "alias": null, 33 | "args": null, 34 | "name": "output_transaction_hash", 35 | "storageKey": null 36 | } 37 | ], 38 | "type": "TransactionInputOutput" 39 | }; 40 | 41 | module.exports = fragment; 42 | -------------------------------------------------------------------------------- /src/shared/components/transaction/summary/__generated__/TransactionSummaryFooter_transaction.graphql.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @flow 3 | */ 4 | 5 | /* eslint-disable */ 6 | 7 | 'use strict'; 8 | 9 | /*:: 10 | import type {ConcreteFragment} from 'relay-runtime'; 11 | export type TransactionSummaryFooter_transaction = {| 12 | +network_fee: string; 13 | +system_fee: string; 14 | |}; 15 | */ 16 | 17 | 18 | const fragment /*: ConcreteFragment*/ = { 19 | "argumentDefinitions": [], 20 | "kind": "Fragment", 21 | "metadata": null, 22 | "name": "TransactionSummaryFooter_transaction", 23 | "selections": [ 24 | { 25 | "kind": "ScalarField", 26 | "alias": null, 27 | "args": null, 28 | "name": "network_fee", 29 | "storageKey": null 30 | }, 31 | { 32 | "kind": "ScalarField", 33 | "alias": null, 34 | "args": null, 35 | "name": "system_fee", 36 | "storageKey": null 37 | } 38 | ], 39 | "type": "Transaction" 40 | }; 41 | 42 | module.exports = fragment; 43 | -------------------------------------------------------------------------------- /src/shared/components/transaction/lib/__generated__/TransactionOutputTable_outputs.graphql.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @flow 3 | */ 4 | 5 | /* eslint-disable */ 6 | 7 | 'use strict'; 8 | 9 | /*:: 10 | import type {ConcreteFragment} from 'relay-runtime'; 11 | export type TransactionOutputTable_outputs = $ReadOnlyArray<{| 12 | +input_transaction_hash: ?string; 13 | |}>; 14 | */ 15 | 16 | 17 | const fragment /*: ConcreteFragment*/ = { 18 | "argumentDefinitions": [], 19 | "kind": "Fragment", 20 | "metadata": { 21 | "plural": true 22 | }, 23 | "name": "TransactionOutputTable_outputs", 24 | "selections": [ 25 | { 26 | "kind": "FragmentSpread", 27 | "name": "TransactionInputOutputTable_input_outputs", 28 | "args": null 29 | }, 30 | { 31 | "kind": "ScalarField", 32 | "alias": null, 33 | "args": null, 34 | "name": "input_transaction_hash", 35 | "storageKey": null 36 | } 37 | ], 38 | "type": "TransactionInputOutput" 39 | }; 40 | 41 | module.exports = fragment; 42 | -------------------------------------------------------------------------------- /src/shared/components/transaction/summary/__generated__/TransactionSummary_transaction.graphql.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @flow 3 | */ 4 | 5 | /* eslint-disable */ 6 | 7 | 'use strict'; 8 | 9 | /*:: 10 | import type {ConcreteFragment} from 'relay-runtime'; 11 | export type TransactionSummary_transaction = {| |}; 12 | */ 13 | 14 | 15 | const fragment /*: ConcreteFragment*/ = { 16 | "argumentDefinitions": [], 17 | "kind": "Fragment", 18 | "metadata": null, 19 | "name": "TransactionSummary_transaction", 20 | "selections": [ 21 | { 22 | "kind": "FragmentSpread", 23 | "name": "TransactionSummaryHeader_transaction", 24 | "args": null 25 | }, 26 | { 27 | "kind": "FragmentSpread", 28 | "name": "TransactionSummaryBody_transaction", 29 | "args": null 30 | }, 31 | { 32 | "kind": "FragmentSpread", 33 | "name": "TransactionSummaryFooter_transaction", 34 | "args": null 35 | } 36 | ], 37 | "type": "Transaction" 38 | }; 39 | 40 | module.exports = fragment; 41 | -------------------------------------------------------------------------------- /src/shared/components/contract/lib/ContractLink.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | getContext, 7 | pure, 8 | } from 'recompose'; 9 | 10 | import { Link } from '~/src/lib/components/shared/link'; 11 | 12 | import * as routes from '~/src/shared/routes'; 13 | 14 | type ExternalProps = {| 15 | contractHash: string, 16 | className?: string, 17 | |}; 18 | // eslint-disable-next-line 19 | type InternalProps = {||}; 20 | /* :: 21 | type Props = {| 22 | ...ExternalProps, 23 | ...InternalProps, 24 | |}; 25 | */ 26 | function ContractLink({ 27 | contractHash, 28 | className, 29 | }: Props): React.Element<*> { 30 | return ( 31 | 37 | ); 38 | } 39 | 40 | export default (compose( 41 | getContext({ styleManager: () => null }), 42 | pure, 43 | )(ContractLink): Class>); 44 | -------------------------------------------------------------------------------- /src/shared/components/asset/lib/AssetLink.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | getContext, 7 | pure, 8 | } from 'recompose'; 9 | 10 | import { Link } from '~/src/lib/components/shared/link'; 11 | 12 | import * as routes from '~/src/shared/routes'; 13 | 14 | type ExternalProps = {| 15 | assetTransactionHash: string, 16 | className?: string, 17 | |}; 18 | // eslint-disable-next-line 19 | type InternalProps = {| 20 | |}; 21 | /* :: 22 | type Props = {| 23 | ...ExternalProps, 24 | ...InternalProps, 25 | |}; 26 | */ 27 | function AssetLink({ 28 | assetTransactionHash, 29 | className, 30 | }: Props): React.Element<*> { 31 | return ( 32 | 38 | ); 39 | } 40 | 41 | export default (compose( 42 | getContext({ styleManager: () => null }), 43 | pure, 44 | )(AssetLink): Class>); 45 | -------------------------------------------------------------------------------- /src/shared/components/transaction/lib/TransactionLink.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | getContext, 7 | pure, 8 | } from 'recompose'; 9 | 10 | import { Link } from '~/src/lib/components/shared/link'; 11 | 12 | import * as routes from '~/src/shared/routes'; 13 | 14 | type ExternalProps = {| 15 | transactionHash: string, 16 | className?: string, 17 | |}; 18 | // eslint-disable-next-line 19 | type InternalProps = {| 20 | |}; 21 | /* :: 22 | type Props = {| 23 | ...ExternalProps, 24 | ...InternalProps, 25 | |}; 26 | */ 27 | function TransactionLink({ 28 | transactionHash, 29 | className, 30 | }: Props): React.Element<*> { 31 | return ( 32 | 38 | ); 39 | } 40 | 41 | export default (compose( 42 | getContext({ styleManager: () => null }), 43 | pure, 44 | )(TransactionLink): Class>); 45 | -------------------------------------------------------------------------------- /src/shared/components/transaction/lib/getIcon.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import { 3 | type TransactionType, 4 | } from '~/src/lib/blockchain/shared/constants'; 5 | 6 | export default (type: TransactionType) => { 7 | let icon; 8 | switch (type) { 9 | case 'MinerTransaction': 10 | icon = 'build'; 11 | break; 12 | case 'IssueTransaction': 13 | icon = 'account_balance'; 14 | break; 15 | case 'ClaimTransaction': 16 | icon = 'redeem'; 17 | break; 18 | case 'EnrollmentTransaction': 19 | icon = 'supervisor_account'; 20 | break; 21 | case 'RegisterTransaction': 22 | icon = 'assignment'; 23 | break; 24 | case 'ContractTransaction': 25 | icon = 'payment'; 26 | break; 27 | case 'PublishTransaction': 28 | icon = 'description'; 29 | break; 30 | case 'InvocationTransaction': 31 | icon = 'play_arrow'; 32 | break; 33 | default: 34 | // eslint-disable-next-line 35 | (type: empty); 36 | break; 37 | } 38 | 39 | return icon; 40 | }; 41 | -------------------------------------------------------------------------------- /src/shared/components/block/lib/BlockIndexLink.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | getContext, 7 | pure, 8 | } from 'recompose'; 9 | 10 | import { Link } from '~/src/lib/components/shared/link'; 11 | 12 | import { formatNumber } from '~/src/lib/utils/shared'; 13 | import * as routes from '~/src/shared/routes'; 14 | 15 | type ExternalProps = {| 16 | blockIndex: number, 17 | className?: string, 18 | |}; 19 | // eslint-disable-next-line 20 | type InternalProps = {||}; 21 | /* :: 22 | type Props = {| 23 | ...ExternalProps, 24 | ...InternalProps, 25 | |}; 26 | */ 27 | function BlockIndexLink({ 28 | blockIndex, 29 | className, 30 | }: Props): React.Element<*> { 31 | return ( 32 | 38 | ); 39 | } 40 | 41 | export default (compose( 42 | getContext({ styleManager: () => null }), 43 | pure, 44 | )(BlockIndexLink): Class>); 45 | -------------------------------------------------------------------------------- /src/shared/components/address/lib/CoinValue.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | pure, 7 | } from 'recompose'; 8 | 9 | import { 10 | Typography, 11 | } from '~/src/lib/components/shared/base'; 12 | 13 | import { formatNumber } from '~/src/lib/utils/shared'; 14 | 15 | type ExternalProps = {| 16 | value: string, 17 | type?: string, 18 | component?: string, 19 | className?: string, 20 | |}; 21 | // eslint-disable-next-line 22 | type InternalProps = {| 23 | |}; 24 | /* :: 25 | type Props = {| 26 | ...ExternalProps, 27 | ...InternalProps, 28 | |}; 29 | */ 30 | function CoinValue({ 31 | value, 32 | type: typeIn, 33 | component, 34 | className, 35 | }: Props): React.Element<*> { 36 | const type = typeIn || 'body1'; 37 | return ( 38 | 43 | {formatNumber(value)} 44 | 45 | ); 46 | } 47 | 48 | export default (compose( 49 | pure, 50 | )(CoinValue): Class>); 51 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 NEO Tracker 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/shared/components/common/view/SearchView.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | pure, 7 | } from 'recompose'; 8 | 9 | import { Card } from '~/src/lib/components/shared/base'; 10 | import { CenteredView } from '~/src/lib/components/shared/layout'; 11 | 12 | import CommonHeader from './CommonHeader'; 13 | 14 | type ExternalProps = {| 15 | name: string, 16 | pluralName: string, 17 | content: React.Element, 18 | className?: string, 19 | |}; 20 | // eslint-disable-next-line 21 | type InternalProps = {| 22 | |}; 23 | /* :: 24 | type Props = {| 25 | ...ExternalProps, 26 | ...InternalProps, 27 | |}; 28 | */ 29 | function SearchView({ 30 | name, 31 | pluralName, 32 | content, 33 | className, 34 | }: Props): React.Element<*> { 35 | return ( 36 | 37 | 38 | 42 | {content} 43 | 44 | 45 | ); 46 | } 47 | 48 | export default (compose( 49 | pure, 50 | )(SearchView): Class>); 51 | -------------------------------------------------------------------------------- /src/shared/redux/configureStore.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import { createStore, combineReducers } from 'redux'; 3 | import { persistStore } from 'redux-persist'; 4 | 5 | import reducers, { flip } from './index'; 6 | 7 | export default (initialState: Object = {}) => { 8 | const createReducer = (rootReducer: Object) => combineReducers(Object.assign( 9 | {}, 10 | rootReducer, 11 | )); 12 | 13 | const store = createStore( 14 | createReducer(reducers), 15 | initialState, 16 | ); 17 | 18 | if (process.env.BUILD_FLAG_IS_DEV && module.hot) { 19 | // Enable Webpack hot module replacement for reducers. This is so that we 20 | // don't lose all of our current application state during hot reloading. 21 | // $FlowFixMe 22 | module.hot.accept('./index', () => { 23 | // eslint-disable-next-line global-require 24 | const nextRootReducer = require('./index').default; 25 | 26 | store.replaceReducer(createReducer(nextRootReducer)); 27 | }); 28 | } 29 | 30 | if (process.env.BUILD_FLAG_IS_CLIENT) { 31 | setInterval( 32 | () => store.dispatch(flip()), 33 | 1000, 34 | ); 35 | 36 | persistStore(store); 37 | } 38 | 39 | return store; 40 | }; 41 | -------------------------------------------------------------------------------- /src/lib/components/shared/qr/QRCode.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | getContext, 7 | pure, 8 | } from 'recompose'; 9 | import qr from 'qr-image'; 10 | 11 | import { type AppStyleManager } from '~/src/shared/styles/createStyleManager'; 12 | 13 | type ExternalProps = {| 14 | value: string, 15 | size: number, 16 | alt: string, 17 | className?: string, 18 | |}; 19 | // eslint-disable-next-line 20 | type InternalProps = {| 21 | styleManager: AppStyleManager, 22 | |}; 23 | /* :: 24 | type Props = {| 25 | ...ExternalProps, 26 | ...InternalProps, 27 | |}; 28 | */ 29 | function QRCode({ 30 | value, 31 | size, 32 | alt, 33 | className, 34 | }: Props): React.Element<*> { 35 | const buffer = qr.imageSync(value, { margin: 0 }); 36 | const dataURI = `data:image/png;base64,${buffer.toString('base64')}`; 37 | return ( 38 | {alt} 45 | ); 46 | } 47 | 48 | export default (compose( 49 | getContext({ styleManager: () => null }), 50 | pure, 51 | )(QRCode): Class>); 52 | -------------------------------------------------------------------------------- /src/shared/components/address/lib/Coin.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | pure, 7 | } from 'recompose'; 8 | import { graphql } from 'react-relay'; 9 | 10 | import { fragmentContainer } from '~/src/lib/graphql/shared/relay'; 11 | 12 | import { 13 | type Coin_coin, 14 | } from './__generated__/Coin_coin.graphql'; 15 | import CoinBase from './CoinBase'; 16 | 17 | type ExternalProps = {| 18 | coin: any, 19 | className?: string, 20 | |}; 21 | // eslint-disable-next-line 22 | type InternalProps = {| 23 | coin: Coin_coin, 24 | |}; 25 | /* :: 26 | type Props = {| 27 | ...ExternalProps, 28 | ...InternalProps, 29 | |}; 30 | */ 31 | function Coin({ 32 | coin, 33 | className, 34 | }: Props): React.Element<*> { 35 | return ; 36 | } 37 | 38 | export default (compose( 39 | fragmentContainer({ 40 | coin: graphql` 41 | fragment Coin_coin on Coin { 42 | value 43 | asset { 44 | transaction_hash 45 | name { 46 | lang 47 | name 48 | } 49 | } 50 | } 51 | `, 52 | }), 53 | pure, 54 | )(Coin): Class>); 55 | -------------------------------------------------------------------------------- /src/shared/redux/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import { createSelector } from 'reselect'; 3 | 4 | import walletReducer from '~/src/wallet/shared/redux'; 5 | 6 | import snackbarReducer, { 7 | selectSnackbarProps as _selectSnackbarProps, 8 | type State as SnackbarState, 9 | } from './snackbar'; 10 | import timerReducer, { 11 | selectTimerState as _selectTimerState, 12 | type State as TimerState, 13 | } from './timer'; 14 | 15 | export type { SnackbarProps } from './snackbar'; 16 | 17 | export { 18 | clearSnackbar, 19 | setSnackbar, 20 | } from './snackbar'; 21 | export { 22 | flip, 23 | } from './timer'; 24 | 25 | type State = { 26 | snackbar: SnackbarState, 27 | timer: TimerState, 28 | wallet: Object, 29 | }; 30 | 31 | const selectSnackbar = (state: State) => state.snackbar; 32 | export const selectSnackbarProps = createSelector( 33 | selectSnackbar, 34 | _selectSnackbarProps, 35 | ); 36 | 37 | const selectTimer = (state: State) => state.timer; 38 | export const selectTimerState = createSelector( 39 | selectTimer, 40 | _selectTimerState, 41 | ); 42 | 43 | export const selectWallet = (state: State) => state.wallet; 44 | 45 | export default { 46 | snackbar: snackbarReducer, 47 | timer: timerReducer, 48 | wallet: walletReducer, 49 | }; 50 | -------------------------------------------------------------------------------- /src/shared/components/asset/lib/getName.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import locale2 from 'locale2' 3 | 4 | import { getBest } from '~/src/lib/locale-id'; 5 | 6 | import { 7 | ANTSHARES_ASSET_HASH, 8 | ANTCOINS_ASSET_HASH, 9 | } from '~/src/lib/blockchain/shared/constants'; 10 | 11 | const NAME_MAP = { 12 | [ANTSHARES_ASSET_HASH]: 'NEO', 13 | [ANTCOINS_ASSET_HASH]: 'GAS', 14 | }; 15 | 16 | const getName = (name, lang) => { 17 | const nameObj = name.find(n => n.lang === lang); 18 | return nameObj == null ? null : nameObj.name; 19 | }; 20 | 21 | // TODO: INTL 22 | export default (name: $ReadOnlyArray<{ +name: string, +lang: string }>, hash: string) => { 23 | let finalName = NAME_MAP[hash]; 24 | if (finalName == null) { 25 | const langs = name.map(n => n.lang); 26 | const lang = getBest(langs, locale2); 27 | 28 | if (lang == null) { 29 | const enLang = getBest(langs, 'en'); 30 | if (enLang != null) { 31 | finalName = getName(name, enLang); 32 | } 33 | } else { 34 | finalName = getName(name, lang); 35 | } 36 | 37 | if (finalName == null) { 38 | if (name.length > 0) { 39 | finalName = name[0].name; 40 | } else { 41 | finalName = hash; 42 | } 43 | } 44 | } 45 | 46 | return finalName; 47 | } 48 | -------------------------------------------------------------------------------- /src/shared/components/transaction/summary/__generated__/TransactionSummaryHeader_transaction.graphql.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @flow 3 | */ 4 | 5 | /* eslint-disable */ 6 | 7 | 'use strict'; 8 | 9 | /*:: 10 | import type {ConcreteFragment} from 'relay-runtime'; 11 | export type TransactionSummaryHeader_transaction = {| 12 | +type: string; 13 | +block_time: ?number; 14 | |}; 15 | */ 16 | 17 | 18 | const fragment /*: ConcreteFragment*/ = { 19 | "argumentDefinitions": [], 20 | "kind": "Fragment", 21 | "metadata": null, 22 | "name": "TransactionSummaryHeader_transaction", 23 | "selections": [ 24 | { 25 | "kind": "FragmentSpread", 26 | "name": "TransactionHeaderBackground_transaction", 27 | "args": null 28 | }, 29 | { 30 | "kind": "FragmentSpread", 31 | "name": "TransactionTypeAndLink_transaction", 32 | "args": null 33 | }, 34 | { 35 | "kind": "ScalarField", 36 | "alias": null, 37 | "args": null, 38 | "name": "type", 39 | "storageKey": null 40 | }, 41 | { 42 | "kind": "ScalarField", 43 | "alias": null, 44 | "args": null, 45 | "name": "block_time", 46 | "storageKey": null 47 | } 48 | ], 49 | "type": "Transaction" 50 | }; 51 | 52 | module.exports = fragment; 53 | -------------------------------------------------------------------------------- /src/shared/components/transaction/lib/TransactionTimeLink.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | getContext, 7 | pure, 8 | } from 'recompose'; 9 | 10 | import { Link } from '~/src/lib/components/shared/link'; 11 | 12 | import { BlockTime } from '~/src/shared/components/block/lib'; 13 | 14 | import * as routes from '~/src/shared/routes'; 15 | 16 | type ExternalProps = {| 17 | transactionHash: ?string, 18 | blockTime: ?number, 19 | className?: string, 20 | |}; 21 | // eslint-disable-next-line 22 | type InternalProps = {| 23 | |}; 24 | /* :: 25 | type Props = {| 26 | ...ExternalProps, 27 | ...InternalProps, 28 | |}; 29 | */ 30 | function TransactionTimeLink({ 31 | transactionHash, 32 | blockTime, 33 | className, 34 | }: Props): React.Element { 35 | const title = ; 36 | if (transactionHash == null) { 37 | return title; 38 | } 39 | 40 | return ( 41 | 47 | ); 48 | } 49 | 50 | export default (compose( 51 | getContext({ styleManager: () => null }), 52 | pure, 53 | )(TransactionTimeLink): Class>); 54 | -------------------------------------------------------------------------------- /src/lib/components/shared/base/Icon.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | import MUIIcon from 'material-ui/Icon/Icon'; 4 | 5 | import { 6 | compose, 7 | getContext, 8 | pure, 9 | } from 'recompose'; 10 | import { createStyleSheet } from 'jss-theme-reactor'; 11 | 12 | import { type AppStyleManager } from '~/src/shared/styles/createStyleManager'; 13 | 14 | const styleSheet = createStyleSheet('Icon', theme => ({ 15 | icon: { 16 | color: theme.palette.text.primary, 17 | }, 18 | })); 19 | 20 | type ExternalProps = { 21 | children?: any, 22 | className?: string, 23 | }; 24 | // eslint-disable-next-line 25 | type InternalProps = {| 26 | styleManager: AppStyleManager, 27 | |}; 28 | /* :: 29 | type Props = { 30 | ...ExternalProps, 31 | ...InternalProps, 32 | }; 33 | */ 34 | function Icon({ 35 | className, 36 | styleManager, 37 | children, 38 | ...other 39 | }: Props): React.Element<*> { 40 | const classes = styleManager.render(styleSheet); 41 | return ( 42 | 46 | {children} 47 | 48 | ); 49 | } 50 | 51 | export default (compose( 52 | getContext({ styleManager: () => null }), 53 | pure, 54 | )(Icon): Class>); 55 | -------------------------------------------------------------------------------- /src/lib/jss2css/utils.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-bitwise, no-plusplus */ 2 | 3 | module.exports.transform = function transform( 4 | obj, 5 | iteratee, 6 | accumulator, 7 | ) { 8 | Object.keys(obj).forEach((key) => { 9 | iteratee(accumulator, obj[key], key); 10 | }); 11 | return accumulator; 12 | } 13 | 14 | const contains = function contains(obj, pred) { 15 | for (const key in pred) { 16 | if ( 17 | !Object.prototype.hasOwnProperty.call(obj, key) || 18 | obj[key] !== pred[key] 19 | ) { 20 | return false; 21 | } 22 | } 23 | return true; 24 | }; 25 | 26 | const findIndex = function findIndex(arr, pred) { 27 | const predType = typeof pred; 28 | for (let i = 0; i < arr.length; i++) { 29 | if (predType === 'function' && pred(arr[i], i, arr) === true) { 30 | return i; 31 | } 32 | if (predType === 'object' && contains(arr[i], pred)) { 33 | return i; 34 | } 35 | if (['string', 'number', 'boolean'].indexOf(predType) !== -1) { 36 | return arr.indexOf(pred); 37 | } 38 | } 39 | return -1; 40 | }; 41 | 42 | module.exports.find = function find(arr, pred) { 43 | const index = findIndex(arr, pred); 44 | return index > -1 ? arr[index] : undefined; 45 | } 46 | 47 | module.exports.findIndex = findIndex; 48 | module.exports.contains = contains; 49 | -------------------------------------------------------------------------------- /src/shared/components/asset/lib/AssetNameLink.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | getContext, 7 | pure, 8 | } from 'recompose'; 9 | import { graphql } from 'react-relay'; 10 | 11 | import { fragmentContainer } from '~/src/lib/graphql/shared/relay'; 12 | 13 | import { 14 | type AssetNameLink_asset 15 | } from './__generated__/AssetNameLink_asset.graphql'; 16 | import AssetNameLinkBase from './AssetNameLinkBase'; 17 | 18 | type ExternalProps = {| 19 | asset: any, 20 | className?: string, 21 | |}; 22 | // eslint-disable-next-line 23 | type InternalProps = {| 24 | asset: AssetNameLink_asset, 25 | |}; 26 | /* :: 27 | type Props = {| 28 | ...ExternalProps, 29 | ...InternalProps, 30 | |}; 31 | */ 32 | function AssetNameLink({ 33 | asset, 34 | className, 35 | }: Props): React.Element<*> { 36 | return ; 37 | } 38 | 39 | export default (compose( 40 | getContext({ styleManager: () => null }), 41 | fragmentContainer({ 42 | asset: graphql` 43 | fragment AssetNameLink_asset on Asset { 44 | transaction_hash 45 | name { 46 | lang 47 | name 48 | } 49 | } 50 | `, 51 | }), 52 | pure, 53 | )(AssetNameLink): Class>); 54 | -------------------------------------------------------------------------------- /src/shared/components/common/timeago/TimeAgo.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | pure, 7 | } from 'recompose'; 8 | import { connect } from 'react-redux'; 9 | 10 | import { 11 | Typography, 12 | } from '~/src/lib/components/shared/base'; 13 | 14 | import { formatTime } from '~/src/lib/utils/shared'; 15 | import { selectTimerState } from '~/src/shared/redux'; 16 | 17 | type ExternalProps = { 18 | time: ?number, 19 | nullString?: string, 20 | prefix?: string, 21 | }; 22 | // eslint-disable-next-line 23 | type InternalProps = {| 24 | |}; 25 | /* :: 26 | type Props = { 27 | ...ExternalProps, 28 | ...InternalProps, 29 | }; 30 | */ 31 | function TimeAgo({ 32 | time, 33 | nullString, 34 | state, 35 | dispatch, 36 | prefix, 37 | ...otherProps, 38 | }: Props): React.Element<*> { 39 | let value; 40 | if (time == null) { 41 | value = nullString; 42 | } else { 43 | value = formatTime(time); 44 | } 45 | 46 | if (prefix != null) { 47 | value = `${prefix}${value || ''}`; 48 | } 49 | 50 | return ( 51 | 52 | {value} 53 | 54 | ); 55 | } 56 | 57 | export default (compose( 58 | connect( 59 | state => ({ state: selectTimerState(state) }), 60 | ), 61 | pure, 62 | )(TimeAgo): Class>); 63 | -------------------------------------------------------------------------------- /src/lib/jss2css/createClientStyleManager.js: -------------------------------------------------------------------------------- 1 | module.exports = function createClientStyleManager(theme) { 2 | const sheetMap = []; 3 | let sheetOrder; 4 | 5 | /** 6 | * styleManager 7 | */ 8 | const styleManager = { 9 | get sheetMap() { return sheetMap; }, 10 | get sheetOrder() { return sheetOrder; }, 11 | setSheetOrder, 12 | theme, 13 | render, 14 | reset, 15 | rerender, 16 | prepareInline, 17 | sheetsToString, 18 | }; 19 | 20 | function render(styleSheet) { 21 | return styleSheet; 22 | } 23 | 24 | /** 25 | * Set DOM rendering order by sheet names. 26 | */ 27 | function setSheetOrder(sheetNames) { 28 | sheetOrder = sheetNames; 29 | } 30 | 31 | /** 32 | * Reset JSS registry, remove sheets and empty the styleManager. 33 | */ 34 | function reset() { 35 | } 36 | 37 | /** 38 | * Reset and update all existing stylesheets 39 | * 40 | * @memberOf module:styleManager~styleManager 41 | */ 42 | function rerender() { 43 | } 44 | 45 | /** 46 | * Prepare inline styles using Theme Reactor 47 | */ 48 | function prepareInline() { 49 | throw new Error('Unsupported operation'); 50 | } 51 | 52 | /** 53 | * Render sheets to an HTML string 54 | */ 55 | function sheetsToString() { 56 | throw new Error('Should not be called'); 57 | } 58 | 59 | return styleManager; 60 | } 61 | -------------------------------------------------------------------------------- /src/shared/components/asset/lib/AssetNameLinkBase.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | getContext, 7 | pure, 8 | } from 'recompose'; 9 | 10 | import { Link } from '~/src/lib/components/shared/link'; 11 | 12 | import * as routes from '~/src/shared/routes'; 13 | 14 | import { 15 | type AssetNameLink_asset 16 | } from './__generated__/AssetNameLink_asset.graphql'; 17 | 18 | import getName from './getName'; 19 | 20 | type ExternalProps = {| 21 | asset: AssetNameLink_asset, 22 | type?: string, 23 | component?: string, 24 | className?: string, 25 | |}; 26 | // eslint-disable-next-line 27 | type InternalProps = {||}; 28 | /* :: 29 | type Props = {| 30 | ...ExternalProps, 31 | ...InternalProps, 32 | |}; 33 | */ 34 | function AssetNameLinkBase({ 35 | asset, 36 | type: typeIn, 37 | component, 38 | className, 39 | }: Props): React.Element<*> { 40 | const type = typeIn || 'body1'; 41 | return ( 42 | 49 | ); 50 | } 51 | 52 | export default (compose( 53 | getContext({ styleManager: () => null }), 54 | pure, 55 | )(AssetNameLinkBase): Class>); 56 | -------------------------------------------------------------------------------- /src/lib/components/shared/help/Help.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | getContext, 7 | pure, 8 | } from 'recompose'; 9 | import { createStyleSheet } from 'jss-theme-reactor'; 10 | 11 | import { type AppStyleManager } from '~/src/shared/styles/createStyleManager'; 12 | import { Icon } from '~/src/lib/components/shared/base'; 13 | import { Tooltip } from '~/src/lib/components/shared/tooltip'; 14 | 15 | const styleSheet = createStyleSheet('Help', () => ({ 16 | root: { 17 | cursor: 'pointer', 18 | }, 19 | })); 20 | 21 | type ExternalProps = {| 22 | tooltip: string, 23 | className?: string, 24 | |}; 25 | // eslint-disable-next-line 26 | type InternalProps = {| 27 | styleManager: AppStyleManager, 28 | |}; 29 | /* :: 30 | type Props = {| 31 | ...ExternalProps, 32 | ...InternalProps, 33 | |}; 34 | */ 35 | function Help({ 36 | tooltip, 37 | className, 38 | styleManager, 39 | }: Props): React.Element<*> { 40 | const classes = styleManager.render(styleSheet); 41 | return ( 42 | 47 | help_outline 48 | 49 | ); 50 | } 51 | 52 | export default (compose( 53 | getContext({ styleManager: () => null }), 54 | pure, 55 | )(Help): Class>); 56 | -------------------------------------------------------------------------------- /src/wallet/shared/components/select/MainSelectCardLocked.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | pure, 7 | } from 'recompose'; 8 | import { graphql } from 'react-relay'; 9 | 10 | import { SelectCard } from '~/src/wallet/shared/components/select'; 11 | import type { Wallet } from '~/src/wallet/shared/wallet'; 12 | 13 | import { queryRenderer } from '~/src/shared/graphql/relay'; 14 | 15 | type ExternalProps = {| 16 | wallet: Wallet, 17 | className?: string, 18 | |}; 19 | // eslint-disable-next-line 20 | type InternalProps = {| 21 | |}; 22 | /* :: 23 | type Props = {| 24 | ...ExternalProps, 25 | ...InternalProps, 26 | |}; 27 | */ 28 | function MainSelectCardLocked({ 29 | wallet, 30 | className, 31 | }: Props): React.Element { 32 | return ( 33 | 39 | ); 40 | } 41 | 42 | export default (compose( 43 | queryRenderer(graphql` 44 | query MainSelectCardLockedQuery($hash: String!) { 45 | address(hash: $hash) { 46 | ...SelectCard_address 47 | } 48 | } 49 | `, { 50 | skipNullVariables: true, 51 | mapPropsToVariables: { 52 | client: () => null, 53 | server: () => null, 54 | }, 55 | }), 56 | pure, 57 | )(MainSelectCardLocked): Class>); 58 | -------------------------------------------------------------------------------- /src/wallet/shared/components/keystore/SaveOrGenerateKeystore.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | pure, 7 | withPropsOnChange, 8 | } from 'recompose'; 9 | 10 | import type { UnlockedWallet } from '~/src/wallet/shared/wallet'; 11 | 12 | import * as walletAPI from '~/src/wallet/shared/wallet'; 13 | 14 | import GenerateKeystore from './GenerateKeystore'; 15 | import SaveKeystoreFile from './SaveKeystoreFile'; 16 | 17 | type ExternalProps = {| 18 | wallet: UnlockedWallet, 19 | className?: string, 20 | |}; 21 | // eslint-disable-next-line 22 | type InternalProps = {| 23 | filename: string, 24 | |}; 25 | /* :: 26 | type Props = {| 27 | ...ExternalProps, 28 | ...InternalProps, 29 | |}; 30 | */ 31 | function SaveOrGenerateKeystore({ 32 | wallet, 33 | className, 34 | filename, 35 | }: Props): React.Element { 36 | if (wallet.keystore == null) { 37 | return ; 38 | } 39 | 40 | return ( 41 | 46 | ) 47 | } 48 | 49 | export default (compose( 50 | withPropsOnChange( 51 | ['wallet'], 52 | ({ wallet }) => ({ 53 | filename: walletAPI.createKeystoreFilename({ address: wallet.address }), 54 | }), 55 | ), 56 | pure, 57 | )(SaveOrGenerateKeystore): Class>); 58 | -------------------------------------------------------------------------------- /src/shared/components/block/lib/BlockTime.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import classNames from 'classnames'; 5 | import { 6 | compose, 7 | getContext, 8 | pure, 9 | } from 'recompose'; 10 | import { createStyleSheet } from 'jss-theme-reactor'; 11 | 12 | import { type AppStyleManager } from '~/src/shared/styles/createStyleManager'; 13 | import { 14 | TimeAgo, 15 | } from '~/src/shared/components/common/timeago'; 16 | 17 | const styleSheet = createStyleSheet('BlockTime', () => ({ 18 | root: { 19 | whiteSpace: 'nowrap', 20 | overflow: 'hidden', 21 | textOverflow: 'ellipsis', 22 | }, 23 | })); 24 | 25 | type ExternalProps = {| 26 | blockTime: ?number, 27 | className?: string, 28 | |}; 29 | // eslint-disable-next-line 30 | type InternalProps = {| 31 | styleManager: AppStyleManager, 32 | |}; 33 | /* :: 34 | type Props = {| 35 | ...ExternalProps, 36 | ...InternalProps, 37 | |}; 38 | */ 39 | function BlockTime({ 40 | blockTime, 41 | className, 42 | styleManager, 43 | }: Props): React.Element<*> { 44 | const classes = styleManager.render(styleSheet); 45 | return ( 46 | 52 | ); 53 | } 54 | 55 | export default (compose( 56 | getContext({ styleManager: () => null }), 57 | pure, 58 | )(BlockTime): Class>); 59 | -------------------------------------------------------------------------------- /src/shared/components/common/view/PagingView.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | pure, 7 | } from 'recompose'; 8 | 9 | import { PageLoading } from '~/src/shared/components/common/loading'; 10 | 11 | import RightPager from './RightPager'; 12 | 13 | type ExternalProps = {| 14 | content: React.Element, 15 | isInitialLoad: boolean, 16 | isLoadingMore: boolean, 17 | page: number, 18 | total: ?number, 19 | pageSize: number, 20 | onUpdatePage: (page: number) => void, 21 | error?: ?string, 22 | className?: string, 23 | |}; 24 | // eslint-disable-next-line 25 | type InternalProps = {||}; 26 | /* :: 27 | type Props = {| 28 | ...ExternalProps, 29 | ...InternalProps, 30 | |}; 31 | */ 32 | function PagingView({ 33 | content, 34 | isInitialLoad, 35 | isLoadingMore, 36 | error, 37 | className, 38 | page, 39 | total, 40 | pageSize, 41 | onUpdatePage, 42 | }: Props): React.Element<*> { 43 | return ( 44 |
45 | {isInitialLoad 46 | ? 47 | : content 48 | } 49 | 57 |
58 | ); 59 | } 60 | 61 | export default (compose( 62 | pure, 63 | )(PagingView): Class>); 64 | -------------------------------------------------------------------------------- /src/lib/components/shared/link/IconLink.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import { Link as RRLink } from 'react-router-dom'; 3 | import React from 'react'; 4 | 5 | import classNames from 'classnames'; 6 | import { 7 | compose, 8 | getContext, 9 | pure, 10 | } from 'recompose'; 11 | import { createStyleSheet } from 'jss-theme-reactor'; 12 | 13 | import { Icon } from '~/src/lib/components/shared/base'; 14 | 15 | const styleSheet = createStyleSheet('IconLink', theme => ({ 16 | link: { 17 | color: theme.palette.text.secondary, 18 | textDecoration: 'none', 19 | '&:hover': { 20 | color: theme.palette.text.primary, 21 | }, 22 | }, 23 | })); 24 | 25 | type ExternalProps = {| 26 | path: string, 27 | icon: string, 28 | className?: string, 29 | |}; 30 | // eslint-disable-next-line 31 | type InternalProps = {| 32 | styleManager: any, 33 | |}; 34 | /* :: 35 | type Props = {| 36 | ...ExternalProps, 37 | ...InternalProps, 38 | |}; 39 | */ 40 | function IconLink({ 41 | path, 42 | icon, 43 | className, 44 | styleManager, 45 | }: Props): React.Element<*> { 46 | const classes = styleManager.render(styleSheet); 47 | return ( 48 | 49 | 50 | {icon} 51 | 52 | 53 | ); 54 | } 55 | 56 | export default (compose( 57 | getContext({ styleManager: () => null }), 58 | pure, 59 | )(IconLink): Class>); 60 | -------------------------------------------------------------------------------- /src/shared/components/contract/lib/ContractNameLink.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | getContext, 7 | pure, 8 | } from 'recompose'; 9 | import { graphql } from 'react-relay'; 10 | 11 | import { Link } from '~/src/lib/components/shared/link'; 12 | 13 | import { fragmentContainer } from '~/src/lib/graphql/shared/relay'; 14 | import * as routes from '~/src/shared/routes'; 15 | 16 | import { 17 | type ContractNameLink_contract 18 | } from './__generated__/ContractNameLink_contract.graphql'; 19 | 20 | type ExternalProps = {| 21 | contract: any, 22 | className?: string, 23 | |}; 24 | // eslint-disable-next-line 25 | type InternalProps = {| 26 | contract: ContractNameLink_contract, 27 | |}; 28 | /* :: 29 | type Props = {| 30 | ...ExternalProps, 31 | ...InternalProps, 32 | |}; 33 | */ 34 | function ContractNameLink({ 35 | contract, 36 | className, 37 | }: Props): React.Element<*> { 38 | return ( 39 | 45 | ); 46 | } 47 | 48 | export default (compose( 49 | getContext({ styleManager: () => null }), 50 | fragmentContainer({ 51 | contract: graphql` 52 | fragment ContractNameLink_contract on Contract { 53 | hash 54 | name 55 | } 56 | `, 57 | }), 58 | pure, 59 | )(ContractNameLink): Class>); 60 | -------------------------------------------------------------------------------- /internal/codegen/writer.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import crypto from 'crypto'; 3 | 4 | import type CodegenDirectory from './CodegenDirectory'; 5 | 6 | export const writeFile = async ( 7 | codegenDir: CodegenDirectory, 8 | filename: string, 9 | text: string, 10 | hash: string, 11 | formatText: (text: string, hash: string) => string, 12 | ): Promise => { 13 | const oldContent = await codegenDir.read(filename); 14 | if (hash === extractHash(oldContent)) { 15 | codegenDir.markUnchanged(filename); 16 | return; 17 | } 18 | 19 | if (codegenDir.onlyValidate) { 20 | codegenDir.markUpdated(filename); 21 | return; 22 | } 23 | 24 | await codegenDir.writeFile( 25 | filename, 26 | formatText(text, `@hash ${hash}`), 27 | ); 28 | } 29 | 30 | export const formatJSText = (text: string, hash: string) => `/* @flow */ 31 | /* eslint-disable */ 32 | // ${hash} 33 | 34 | 'use strict'; 35 | 36 | ${text} 37 | `; 38 | 39 | export const formatCSSText = (text: string, hash: string) => `/* ${hash} */ 40 | ${text} 41 | `; 42 | 43 | const extractHash = (text: ?string): ?string => { 44 | if (text == null) { 45 | return null; 46 | } 47 | 48 | if (/<<<<<|>>>>>/.test(text)) { 49 | // looks like a merge conflict 50 | return null; 51 | } 52 | 53 | const match = text.match(/@hash (\w{32})\b/m); 54 | return match && match[1]; 55 | }; 56 | 57 | export const hash = (text: string): string => { 58 | return crypto.createHash('md5').update(text).digest('hex'); 59 | } 60 | -------------------------------------------------------------------------------- /src/shared/components/asset/lib/__generated__/AssetNameLink_asset.graphql.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @flow 3 | */ 4 | 5 | /* eslint-disable */ 6 | 7 | 'use strict'; 8 | 9 | /*:: 10 | import type {ConcreteFragment} from 'relay-runtime'; 11 | export type AssetNameLink_asset = {| 12 | +transaction_hash: string; 13 | +name: $ReadOnlyArray<{| 14 | +lang: string; 15 | +name: string; 16 | |}>; 17 | |}; 18 | */ 19 | 20 | 21 | const fragment /*: ConcreteFragment*/ = { 22 | "argumentDefinitions": [], 23 | "kind": "Fragment", 24 | "metadata": null, 25 | "name": "AssetNameLink_asset", 26 | "selections": [ 27 | { 28 | "kind": "ScalarField", 29 | "alias": null, 30 | "args": null, 31 | "name": "transaction_hash", 32 | "storageKey": null 33 | }, 34 | { 35 | "kind": "LinkedField", 36 | "alias": null, 37 | "args": null, 38 | "concreteType": "AssetName", 39 | "name": "name", 40 | "plural": true, 41 | "selections": [ 42 | { 43 | "kind": "ScalarField", 44 | "alias": null, 45 | "args": null, 46 | "name": "lang", 47 | "storageKey": null 48 | }, 49 | { 50 | "kind": "ScalarField", 51 | "alias": null, 52 | "args": null, 53 | "name": "name", 54 | "storageKey": null 55 | } 56 | ], 57 | "storageKey": null 58 | } 59 | ], 60 | "type": "Asset" 61 | }; 62 | 63 | module.exports = fragment; 64 | -------------------------------------------------------------------------------- /src/shared/components/transaction/lib/__generated__/TransactionInputOutputTable_input_outputs.graphql.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @flow 3 | */ 4 | 5 | /* eslint-disable */ 6 | 7 | 'use strict'; 8 | 9 | /*:: 10 | import type {ConcreteFragment} from 'relay-runtime'; 11 | export type TransactionInputOutputTable_input_outputs = $ReadOnlyArray<{| 12 | +address_hash: string; 13 | +value: string; 14 | +asset: {| |}; 15 | |}>; 16 | */ 17 | 18 | 19 | const fragment /*: ConcreteFragment*/ = { 20 | "argumentDefinitions": [], 21 | "kind": "Fragment", 22 | "metadata": { 23 | "plural": true 24 | }, 25 | "name": "TransactionInputOutputTable_input_outputs", 26 | "selections": [ 27 | { 28 | "kind": "ScalarField", 29 | "alias": null, 30 | "args": null, 31 | "name": "address_hash", 32 | "storageKey": null 33 | }, 34 | { 35 | "kind": "ScalarField", 36 | "alias": null, 37 | "args": null, 38 | "name": "value", 39 | "storageKey": null 40 | }, 41 | { 42 | "kind": "LinkedField", 43 | "alias": null, 44 | "args": null, 45 | "concreteType": "Asset", 46 | "name": "asset", 47 | "plural": false, 48 | "selections": [ 49 | { 50 | "kind": "FragmentSpread", 51 | "name": "AssetNameLink_asset", 52 | "args": null 53 | } 54 | ], 55 | "storageKey": null 56 | } 57 | ], 58 | "type": "TransactionInputOutput" 59 | }; 60 | 61 | module.exports = fragment; 62 | -------------------------------------------------------------------------------- /src/wallet/shared/components/paper/PaperWalletHeader.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import classNames from 'classnames'; 5 | import { 6 | compose, 7 | getContext, 8 | pure, 9 | } from 'recompose'; 10 | import { createStyleSheet } from 'jss-theme-reactor'; 11 | 12 | import { type AppStyleManager } from '~/src/shared/styles/createStyleManager'; 13 | import { type AppContext } from '~/src/shared/AppContext'; 14 | 15 | const styleSheet = createStyleSheet('PaperWalletHeader', () => ({ 16 | root: { 17 | }, 18 | })); 19 | 20 | type ExternalProps = {| 21 | className?: string, 22 | |}; 23 | // eslint-disable-next-line 24 | type InternalProps = {| 25 | styleManager: AppStyleManager, 26 | appContext: AppContext, 27 | |}; 28 | /* :: 29 | type Props = {| 30 | ...ExternalProps, 31 | ...InternalProps, 32 | |}; 33 | */ 34 | function PaperWalletHeader({ 35 | className, 36 | styleManager, 37 | appContext, 38 | }: Props): React.Element<*> { 39 | const classes = styleManager.render(styleSheet); 40 | return ( 41 | NEO Tracker 48 | ); 49 | } 50 | 51 | export default (compose( 52 | getContext({ 53 | styleManager: () => null, 54 | appContext: () => null, 55 | }), 56 | pure, 57 | )(PaperWalletHeader): Class>); 58 | -------------------------------------------------------------------------------- /src/shared/components/transaction/summary/__generated__/TransactionSummaryBody_transaction.graphql.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @flow 3 | */ 4 | 5 | /* eslint-disable */ 6 | 7 | 'use strict'; 8 | 9 | /*:: 10 | import type {ConcreteFragment} from 'relay-runtime'; 11 | export type TransactionSummaryBody_transaction = {| 12 | +type: string; 13 | |}; 14 | */ 15 | 16 | 17 | const fragment /*: ConcreteFragment*/ = { 18 | "argumentDefinitions": [], 19 | "kind": "Fragment", 20 | "metadata": null, 21 | "name": "TransactionSummaryBody_transaction", 22 | "selections": [ 23 | { 24 | "kind": "ScalarField", 25 | "alias": null, 26 | "args": null, 27 | "name": "type", 28 | "storageKey": null 29 | }, 30 | { 31 | "kind": "FragmentSpread", 32 | "name": "TransactionClaimSummaryBody_transaction", 33 | "args": null 34 | }, 35 | { 36 | "kind": "FragmentSpread", 37 | "name": "TransactionEnrollmentSummaryBody_transaction", 38 | "args": null 39 | }, 40 | { 41 | "kind": "FragmentSpread", 42 | "name": "TransactionInputOutputSummaryBody_transaction", 43 | "args": null 44 | }, 45 | { 46 | "kind": "FragmentSpread", 47 | "name": "TransactionPublishSummaryBody_transaction", 48 | "args": null 49 | }, 50 | { 51 | "kind": "FragmentSpread", 52 | "name": "TransactionRegisterSummaryBody_transaction", 53 | "args": null 54 | } 55 | ], 56 | "type": "Transaction" 57 | }; 58 | 59 | module.exports = fragment; 60 | -------------------------------------------------------------------------------- /src/shared/components/transaction/lib/TransactionValue.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import BigNumber from 'bignumber.js'; 3 | import React from 'react'; 4 | 5 | import classNames from 'classnames'; 6 | import { 7 | compose, 8 | getContext, 9 | pure, 10 | } from 'recompose'; 11 | import { createStyleSheet } from 'jss-theme-reactor'; 12 | 13 | import { type AppStyleManager } from '~/src/shared/styles/createStyleManager'; 14 | import { CoinValue } from '~/src/shared/components/address/lib'; 15 | 16 | const styleSheet = createStyleSheet('TransactionValue', () => ({ 17 | value: { 18 | textAlign: 'right', 19 | }, 20 | })); 21 | 22 | type ExternalProps = {| 23 | value: string, 24 | negative?: boolean, 25 | className?: string, 26 | |}; 27 | // eslint-disable-next-line 28 | type InternalProps = {| 29 | styleManager: AppStyleManager, 30 | |}; 31 | /* :: 32 | type Props = {| 33 | ...ExternalProps, 34 | ...InternalProps, 35 | |}; 36 | */ 37 | function TransactionValue({ 38 | value: valueIn, 39 | negative, 40 | className, 41 | styleManager, 42 | }: Props): React.Element<*> { 43 | const classes = styleManager.render(styleSheet); 44 | let value = valueIn; 45 | if (negative) { 46 | value = (new BigNumber(value)).negated().toString(); 47 | } 48 | return ( 49 | 53 | ); 54 | } 55 | 56 | export default (compose( 57 | getContext({ styleManager: () => null }), 58 | pure, 59 | )(TransactionValue): Class>); 60 | -------------------------------------------------------------------------------- /src/shared/components/address/lib/getSortedCoins.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import BigNumber from 'bignumber.js'; 3 | 4 | import _ from 'lodash'; 5 | 6 | import { 7 | ANTSHARES_ASSET_HASH, 8 | ANTCOINS_ASSET_HASH, 9 | NEO_COIN_ASSET, 10 | GAS_COIN_ASSET, 11 | } from '~/src/lib/blockchain/shared/constants'; 12 | 13 | import { 14 | type CoinTable_coins, 15 | } from './__generated__/CoinTable_coins.graphql'; 16 | 17 | export default (coins: CoinTable_coins) => { 18 | let result = _.partition( 19 | coins, 20 | coin => coin.asset.transaction_hash === ANTSHARES_ASSET_HASH, 21 | ); 22 | let neoCoin = null; 23 | if (result[0].length > 0) { 24 | neoCoin = result[0][0]; 25 | } else { 26 | neoCoin = { 27 | value: '0', 28 | asset: NEO_COIN_ASSET, 29 | }; 30 | } 31 | 32 | result = _.partition( 33 | result[1], 34 | coin => coin.asset.transaction_hash === ANTCOINS_ASSET_HASH, 35 | ); 36 | let gasCoin = null; 37 | if (result[0].length > 0) { 38 | gasCoin = result[0][0]; 39 | } else { 40 | gasCoin = { 41 | value: '0', 42 | asset: GAS_COIN_ASSET, 43 | }; 44 | } 45 | 46 | const sortedResult = result[1].sort((x, y) => { 47 | const xNumber = new BigNumber(x.value); 48 | const yNumber = new BigNumber(y.value); 49 | if (xNumber.lt(yNumber)) { 50 | return -1; 51 | } else if (xNumber.gt(yNumber)) { 52 | return 1; 53 | } 54 | 55 | return 0; 56 | }); 57 | 58 | // TODO: Eventually sort by real world value 59 | return [neoCoin, gasCoin].concat(sortedResult).filter(Boolean); 60 | } 61 | -------------------------------------------------------------------------------- /src/lib/log/shared/common.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import { BaseError } from '~/src/lib/errors/shared'; 3 | 4 | import { type BaseLogMeta } from './index'; 5 | 6 | const handleError = ( 7 | error: Error, 8 | explodeError: (error: Error) => Object, 9 | ): Object => { 10 | let errorData = null; 11 | if (error instanceof BaseError) { 12 | errorData = error.data; 13 | if ( 14 | errorData != null && 15 | errorData.originalError != null && 16 | errorData.originalError instanceof Error 17 | ) { 18 | errorData = { 19 | ...errorData, 20 | originalError: handleError(errorData.originalError, explodeError), 21 | }; 22 | } 23 | } else if (error.source != null) { 24 | errorData = { source: error.source }; 25 | } 26 | return { 27 | error: explodeError(error), 28 | errorData, 29 | }; 30 | }; 31 | 32 | // eslint-disable-next-line 33 | export function transformMeta( 34 | logMeta?: BaseLogMeta | LogMeta, 35 | explodeError: (error: Error) => Object, 36 | ): ?(BaseLogMeta | LogMeta) { 37 | if (logMeta) { 38 | if (logMeta.error && logMeta.error instanceof Error) { 39 | if ( 40 | process.env.BUILD_FLAG_IS_DEV || 41 | process.env.BUILD_FLAG_IS_TEST === 'true' || 42 | process.env.BUILD_FLAG_IS_STAGING 43 | ) { 44 | // eslint-disable-next-line no-console 45 | console.error(logMeta.error); 46 | } 47 | return ({ 48 | ...logMeta, 49 | error: handleError(logMeta.error, explodeError), 50 | }: any); 51 | } 52 | } 53 | 54 | return logMeta; 55 | }; 56 | -------------------------------------------------------------------------------- /src/lib/components/shared/animated/Chevron.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import classNames from 'classnames'; 5 | import { 6 | compose, 7 | getContext, 8 | hoistStatics, 9 | pure, 10 | } from 'recompose'; 11 | import { createStyleSheet } from 'jss-theme-reactor'; 12 | 13 | import { Icon } from '~/src/lib/components/shared/base'; 14 | 15 | const styleSheet = createStyleSheet('Chevron', theme => ({ 16 | chevron: { 17 | cursor: 'pointer', 18 | transition: theme.transitions.create(['transform']), 19 | }, 20 | chevronUp: { 21 | transform: 'rotate(0deg)', 22 | }, 23 | chevronDown: { 24 | transform: 'rotate(180deg)', 25 | }, 26 | })); 27 | 28 | type ExternalProps = { 29 | up: boolean, 30 | className?: string, 31 | }; 32 | // eslint-disable-next-line 33 | type InternalProps = {| 34 | styleManager: any, 35 | |}; 36 | /* :: 37 | type Props = { 38 | ...ExternalProps, 39 | ...InternalProps, 40 | }; 41 | */ 42 | function Chevron({ 43 | up, 44 | className, 45 | styleManager, 46 | ...otherProps 47 | }: Props): React.Element<*> { 48 | const classes = styleManager.render(styleSheet); 49 | return ( 50 | 58 | keyboard_arrow_up 59 | 60 | ); 61 | } 62 | 63 | export default (hoistStatics(compose( 64 | getContext({ styleManager: () => null }), 65 | pure, 66 | ))(Chevron): Class>); 67 | -------------------------------------------------------------------------------- /src/wallet/shared/components/keystore/SaveKeystoreFileText.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | getContext, 7 | pure, 8 | } from 'recompose'; 9 | import { createStyleSheet } from 'jss-theme-reactor'; 10 | 11 | import { type AppStyleManager } from '~/src/shared/styles/createStyleManager'; 12 | import { CopyField } from '~/src/wallet/shared/components/common'; 13 | import { type Keystore } from '~/src/wallet/shared/wallet'; 14 | import { Typography } from '~/src/lib/components/shared/base'; 15 | 16 | const styleSheet = createStyleSheet('SaveKeystoreFileText', theme => ({ 17 | })); 18 | 19 | type ExternalProps = {| 20 | keystore: Keystore, 21 | onSave?: () => void, 22 | className?: string, 23 | |}; 24 | // eslint-disable-next-line 25 | type InternalProps = {| 26 | styleManager: AppStyleManager, 27 | |}; 28 | /* :: 29 | type Props = {| 30 | ...ExternalProps, 31 | ...InternalProps, 32 | |}; 33 | */ 34 | function SaveKeystoreFileText({ 35 | keystore, 36 | onSave, 37 | className, 38 | styleManager, 39 | }: Props): React.Element<*> { 40 | const classes = styleManager.render(styleSheet); 41 | return ( 42 |
43 | 44 | Save Keystore: 45 | 46 | 51 |
52 | ); 53 | } 54 | 55 | export default (compose( 56 | getContext({ styleManager: () => null }), 57 | pure, 58 | )(SaveKeystoreFileText): Class>); 59 | -------------------------------------------------------------------------------- /src/shared/components/address/lib/CoinBase.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import classNames from 'classnames'; 5 | import { 6 | compose, 7 | getContext, 8 | pure, 9 | } from 'recompose'; 10 | import { createStyleSheet } from 'jss-theme-reactor'; 11 | 12 | import { type AppStyleManager } from '~/src/shared/styles/createStyleManager'; 13 | import { 14 | AssetNameLinkBase 15 | } from '~/src/shared/components/asset/lib'; 16 | import { 17 | type Coin_coin, 18 | } from './__generated__/Coin_coin.graphql'; 19 | 20 | import CoinValue from './CoinValue'; 21 | 22 | const styleSheet = createStyleSheet('CoinBase', theme => ({ 23 | coinValue: { 24 | display: 'flex', 25 | }, 26 | value: { 27 | marginRight: theme.spacing.unit / 2, 28 | }, 29 | })); 30 | 31 | type ExternalProps = {| 32 | coin: Coin_coin, 33 | className?: string, 34 | |}; 35 | // eslint-disable-next-line 36 | type InternalProps = {| 37 | styleManager: AppStyleManager, 38 | |}; 39 | /* :: 40 | type Props = {| 41 | ...ExternalProps, 42 | ...InternalProps, 43 | |}; 44 | */ 45 | function CoinBase({ 46 | coin, 47 | className, 48 | styleManager, 49 | }: Props): React.Element<*> { 50 | const classes = styleManager.render(styleSheet); 51 | return ( 52 |
53 | 54 | 55 |
56 | ); 57 | } 58 | 59 | export default (compose( 60 | getContext({ styleManager: () => null }), 61 | pure, 62 | )(CoinBase): Class>); 63 | -------------------------------------------------------------------------------- /src/wallet/shared/components/paper/PaperWalletLabelLine.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import classNames from 'classnames'; 5 | import { 6 | compose, 7 | getContext, 8 | pure, 9 | } from 'recompose'; 10 | import { createStyleSheet } from 'jss-theme-reactor'; 11 | 12 | import { type AppStyleManager } from '~/src/shared/styles/createStyleManager'; 13 | import { 14 | Typography, 15 | } from '~/src/lib/components/shared/base'; 16 | 17 | const styleSheet = createStyleSheet('PaperWalletLabelLine', () => ({ 18 | borderBox: { 19 | boxSizing: 'border-box', 20 | }, 21 | })); 22 | 23 | type ExternalProps = {| 24 | label: string, 25 | value: string, 26 | className?: string, 27 | |}; 28 | // eslint-disable-next-line 29 | type InternalProps = {| 30 | styleManager: AppStyleManager, 31 | |}; 32 | /* :: 33 | type Props = {| 34 | ...ExternalProps, 35 | ...InternalProps, 36 | |}; 37 | */ 38 | function PaperWalletLabelLine({ 39 | label, 40 | value, 41 | className, 42 | styleManager, 43 | }: Props): React.Element<*> { 44 | const classes = styleManager.render(styleSheet); 45 | return ( 46 | 51 | {label} 52 |
53 | {value} 54 |
55 | ); 56 | } 57 | 58 | export default (compose( 59 | getContext({ styleManager: () => null }), 60 | pure, 61 | )(PaperWalletLabelLine): Class>); 62 | -------------------------------------------------------------------------------- /src/wallet/shared/components/select/MainSelectCard.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | getContext, 7 | pure, 8 | } from 'recompose'; 9 | import { connect } from 'react-redux'; 10 | 11 | import type { Wallet } from '~/src/wallet/shared/wallet'; 12 | 13 | import { 14 | selectSelectedWallet, 15 | selectWalletReady, 16 | } from '~/src/wallet/shared/redux'; 17 | 18 | import MainSelectCardLocked from './MainSelectCardLocked'; 19 | import MainSelectCardUnlocked from './MainSelectCardUnlocked'; 20 | 21 | type ExternalProps = {| 22 | className?: string, 23 | |}; 24 | // eslint-disable-next-line 25 | type InternalProps = {| 26 | ready: boolean, 27 | selectedWallet: Wallet, 28 | |}; 29 | /* :: 30 | type Props = {| 31 | ...ExternalProps, 32 | ...InternalProps, 33 | |}; 34 | */ 35 | function MainSelectCard({ 36 | className, 37 | selectedWallet, 38 | }: Props): React.Element { 39 | if (selectedWallet == null || selectedWallet.isLocked) { 40 | return ( 41 | 45 | ); 46 | } 47 | 48 | return ( 49 | 53 | ); 54 | } 55 | 56 | export default (compose( 57 | getContext({ walletContext: () => null }), 58 | connect((state, { walletContext }) => ({ 59 | ready: selectWalletReady(walletContext, state), 60 | selectedWallet: selectSelectedWallet(walletContext, state), 61 | })), 62 | pure, 63 | )(MainSelectCard): Class>); 64 | -------------------------------------------------------------------------------- /src/lib/transform/utils.js: -------------------------------------------------------------------------------- 1 | const t = require("babel-types"); 2 | 3 | module.exports.isImportedIdentifier = (importedName, source) => path => { 4 | const node = path.node; 5 | if (t.isIdentifier(node)) { 6 | if (_isImport(path, importedName, source)) { 7 | return true; 8 | } else if (_isRequire(path, importedName, source)) { 9 | return true; 10 | } 11 | } 12 | 13 | return false; 14 | }; 15 | 16 | const _isImport = (path, importedName, source) => { 17 | if (!( 18 | t.isIdentifier(path.node) && 19 | t.isReferenced(path.node, path.parent) 20 | )) { 21 | return false; 22 | } 23 | 24 | const binding = path.scope.getBinding(path.node.name); 25 | if (binding == null) { 26 | return false; 27 | } 28 | 29 | return ( 30 | t.isImportSpecifier(path.node) && 31 | path.node.imported.name === importedName && 32 | t.isImportDeclaration(path.parent) && 33 | path.parent.source.value === source 34 | ); 35 | }; 36 | 37 | const _isRequire = (path, importedName, source) => { 38 | if (!t.isReferenced(path.node, path.parent)) { 39 | return false; 40 | } 41 | 42 | const binding = path.scope.getBinding(path.node.name); 43 | if (binding == null) { 44 | return false; 45 | } 46 | 47 | if (!t.isVariableDeclarator(binding.path.node)) { 48 | return false; 49 | } 50 | 51 | const initPath = binding.path.get('init'); 52 | const init = initPath.node; 53 | return ( 54 | t.isCallExpression(init) && 55 | t.isIdentifier(init.callee) && 56 | init.callee.name === 'require' && 57 | init.arguments.length === 1 && 58 | t.isStringLiteral(init.arguments[0]) && 59 | init.arguments[0].value === source 60 | ); 61 | } 62 | -------------------------------------------------------------------------------- /src/lib/components/shared/error/Error404.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import Helmet from 'react-helmet'; 3 | import React from 'react'; 4 | 5 | import { createStyleSheet } from 'jss-theme-reactor'; 6 | import { compose, getContext, pure } from 'recompose'; 7 | 8 | import type { AppStyleManager } from '~/src/shared/styles/createStyleManager'; 9 | import { Card, Grid, Typography } from '~/src/lib/components/shared/base'; 10 | 11 | const styleSheet = createStyleSheet('Error404', () => ({ 12 | root: { 13 | padding: 16, 14 | }, 15 | card: { 16 | alignItems: 'center', 17 | display: 'flex', 18 | flexDirection: 'column', 19 | justifyContent: 'center', 20 | padding: 24, 21 | }, 22 | headline: { 23 | paddingBottom: 8, 24 | }, 25 | })); 26 | 27 | type Props = {| 28 | styleManager: AppStyleManager, 29 | |}; 30 | const Error404 = ({ styleManager }: Props) => { 31 | const classes = styleManager.render(styleSheet); 32 | return ( 33 |
34 | 35 | {'404'} 36 | 37 | 38 | 39 | 40 | 41 | Sorry, that page was not found. 42 | 43 | 44 | Try going back to where you were or heading to the home page. 45 | 46 | 47 | 48 | 49 |
50 | ); 51 | }; 52 | 53 | export default compose( 54 | getContext({ styleManager: () => null }), 55 | pure, 56 | )(Error404); 57 | -------------------------------------------------------------------------------- /src/shared/components/transaction/TransactionTable.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | pure, 7 | } from 'recompose'; 8 | import { graphql } from 'react-relay'; 9 | 10 | import { 11 | TransactionSummary, 12 | } from '~/src/shared/components/transaction/summary'; 13 | 14 | import { fragmentContainer } from '~/src/lib/graphql/shared/relay'; 15 | 16 | import { 17 | type TransactionTable_transactions, 18 | } from './__generated__/TransactionTable_transactions.graphql'; 19 | 20 | type ExternalProps = {| 21 | transactions: any, 22 | addressHash?: string, 23 | dense?: boolean, 24 | className?: string, 25 | |}; 26 | // eslint-disable-next-line 27 | type InternalProps = {| 28 | transactions: TransactionTable_transactions, 29 | |}; 30 | /* :: 31 | type Props = {| 32 | ...ExternalProps, 33 | ...InternalProps, 34 | |}; 35 | */ 36 | function TransactionTable({ 37 | transactions, 38 | addressHash, 39 | dense, 40 | className, 41 | }: Props): React.Element<*> { 42 | return ( 43 |
44 | {transactions.map(transaction => ( 45 | 51 | ))} 52 |
53 | ) 54 | } 55 | 56 | export default (compose( 57 | fragmentContainer({ 58 | transactions: graphql` 59 | fragment TransactionTable_transactions on Transaction @relay(plural: true) { 60 | hash 61 | ...TransactionSummary_transaction 62 | } 63 | ` 64 | }), 65 | pure, 66 | )(TransactionTable): Class>); 67 | -------------------------------------------------------------------------------- /src/wallet/shared/components/new/NewWalletSaveKeystore.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | pure, 7 | withHandlers, 8 | withProps, 9 | withState, 10 | } from 'recompose'; 11 | 12 | import { type Keystore } from '~/src/wallet/shared/wallet'; 13 | import { SaveKeystoreFile } from '~/src/wallet/shared/components/keystore'; 14 | 15 | import NewWalletSaveCommon from './NewWalletSaveCommon'; 16 | 17 | type ExternalProps = {| 18 | keystore: Keystore, 19 | filename: string, 20 | onContinue: () => void, 21 | className?: string, 22 | |}; 23 | // eslint-disable-next-line 24 | type InternalProps = {| 25 | keystoreSaved: boolean, 26 | onSave: () => void, 27 | |}; 28 | /* :: 29 | type Props = {| 30 | ...ExternalProps, 31 | ...InternalProps, 32 | |}; 33 | */ 34 | function NewWalletSaveKeystore({ 35 | keystore, 36 | filename, 37 | onContinue, 38 | className, 39 | keystoreSaved, 40 | onSave, 41 | }: Props): React.Element<*> { 42 | return ( 43 | 52 | } 53 | saved={keystoreSaved} 54 | onContinue={onContinue} 55 | /> 56 | ); 57 | } 58 | 59 | export default (compose( 60 | pure, 61 | withState('state', 'setState', () => ({ 62 | keystoreSaved: false, 63 | })), 64 | withProps(({ state }) => state), 65 | withHandlers({ 66 | onSave: ({ setState }) => () => setState(prevState => ({ 67 | ...prevState, 68 | keystoreSaved: true, 69 | })), 70 | }), 71 | )(NewWalletSaveKeystore): Class>); 72 | -------------------------------------------------------------------------------- /src/wallet/shared/components/account/TransferView.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | pure, 7 | } from 'recompose'; 8 | import { graphql } from 'react-relay'; 9 | 10 | import { ErrorView } from '~/src/shared/components/common/error'; 11 | import { PageLoading } from '~/src/shared/components/common/loading'; 12 | import type { UnlockedWallet } from '~/src/wallet/shared/wallet'; 13 | 14 | import { fragmentContainer } from '~/src/lib/graphql/shared/relay'; 15 | 16 | import { 17 | type TransferView_address 18 | } from './__generated__/TransferView_address.graphql'; 19 | import SendTransaction from './SendTransaction'; 20 | 21 | type ExternalProps = {| 22 | wallet: UnlockedWallet, 23 | address: any, 24 | loading?: boolean, 25 | error?: ?Error, 26 | retry?: ?() => void, 27 | className?: string, 28 | |}; 29 | // eslint-disable-next-line 30 | type InternalProps = {| 31 | address: TransferView_address, 32 | |}; 33 | /* :: 34 | type Props = {| 35 | ...ExternalProps, 36 | ...InternalProps, 37 | |}; 38 | */ 39 | function TransferView({ 40 | wallet, 41 | address, 42 | loading, 43 | error, 44 | retry, 45 | className, 46 | }: Props): React.Element { 47 | if (error != null) { 48 | return ; 49 | } 50 | 51 | if (loading) { 52 | return ; 53 | } 54 | 55 | return ( 56 | 61 | ); 62 | } 63 | 64 | export default (compose( 65 | fragmentContainer({ 66 | address: graphql` 67 | fragment TransferView_address on Address { 68 | ...SendTransaction_address 69 | } 70 | `, 71 | }), 72 | pure, 73 | )(TransferView): Class>); 74 | -------------------------------------------------------------------------------- /src/lib/graphql/shared/relay/fragmentContainer.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import { 3 | type GraphQLTaggedNode, 4 | createFragmentContainer, 5 | } from 'react-relay'; 6 | import React from 'react'; 7 | 8 | import { getFragment, getSelectorsFromObject } from 'relay-runtime'; 9 | 10 | import { compose, getContext, withProps } from 'recompose'; 11 | 12 | let fragmentContainer; 13 | if (process.env.BUILD_FLAG_IS_SERVER) { 14 | fragmentContainer = (fragments: { [key: string]: GraphQLTaggedNode }) => { 15 | const fragmentSpec = {}; 16 | for (const [key, fragment] of Object.entries(fragments)) { 17 | fragmentSpec[key] = getFragment(fragment); 18 | } 19 | return compose( 20 | getContext({ relay: () => null }), 21 | withProps((props) => { 22 | const selectors = getSelectorsFromObject( 23 | props.relay, 24 | fragmentSpec, 25 | props, 26 | ); 27 | return Object.entries(selectors).reduce( 28 | (res, [key, selector]) => { 29 | if (Array.isArray(selector)) { 30 | res[key] = selector.map( 31 | sel => props.relay.environment.lookup(sel).data, 32 | ); 33 | } else if (selector == null && Array.isArray(props[key])) { 34 | res[key] = []; 35 | } else { 36 | res[key] = props.relay.environment.lookup(selector).data; 37 | } 38 | return res; 39 | }, 40 | {}, 41 | ); 42 | }), 43 | ); 44 | }; 45 | } else { 46 | fragmentContainer = (fragments: { [key: string]: GraphQLTaggedNode }) => 47 | (WrappedComponent: Class>) => 48 | createFragmentContainer(WrappedComponent, fragments); 49 | } 50 | 51 | const fragmentContainetExport = fragmentContainer; 52 | export default fragmentContainetExport; 53 | -------------------------------------------------------------------------------- /src/lib/graphql/shared/relay/relay/fragmentContainer.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import { 3 | type GraphQLTaggedNode, 4 | createFragmentContainer, 5 | } from 'react-relay'; 6 | import React from 'react'; 7 | 8 | import { getFragment, getSelectorsFromObject } from 'relay-runtime'; 9 | 10 | import { compose, getContext, withProps } from 'recompose'; 11 | 12 | let fragmentContainer; 13 | if (process.env.BUILD_FLAG_IS_SERVER) { 14 | fragmentContainer = (fragments: { [key: string]: GraphQLTaggedNode }) => { 15 | const fragmentSpec = {}; 16 | for (const [key, fragment] of Object.entries(fragments)) { 17 | fragmentSpec[key] = getFragment(fragment); 18 | } 19 | return compose( 20 | getContext({ relay: () => null }), 21 | withProps((props) => { 22 | const selectors = getSelectorsFromObject( 23 | props.relay, 24 | fragmentSpec, 25 | props, 26 | ); 27 | return Object.entries(selectors).reduce( 28 | (res, [key, selector]) => { 29 | if (Array.isArray(selector)) { 30 | res[key] = selector.map( 31 | sel => props.relay.environment.lookup(sel).data, 32 | ); 33 | } else if (selector == null && Array.isArray(props[key])) { 34 | res[key] = []; 35 | } else { 36 | res[key] = props.relay.environment.lookup(selector).data; 37 | } 38 | return res; 39 | }, 40 | {}, 41 | ); 42 | }), 43 | ); 44 | }; 45 | } else { 46 | fragmentContainer = (fragments: { [key: string]: GraphQLTaggedNode }) => 47 | (WrappedComponent: Class>) => 48 | createFragmentContainer(WrappedComponent, fragments); 49 | } 50 | 51 | const fragmentContainetExport = fragmentContainer; 52 | export default fragmentContainetExport; 53 | -------------------------------------------------------------------------------- /src/wallet/shared/components/paper/PaperWallet.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import classNames from 'classnames'; 5 | import { 6 | compose, 7 | getContext, 8 | pure, 9 | withContext, 10 | } from 'recompose'; 11 | import { createStyleSheet } from 'jss-theme-reactor'; 12 | 13 | import { type AppContext } from '~/src/shared/AppContext'; 14 | import { type AppStyleManager } from '~/src/shared/styles/createStyleManager'; 15 | 16 | import PaperWalletHeader from './PaperWalletHeader'; 17 | import PaperWalletContent from './PaperWalletContent'; 18 | 19 | const styleSheet = createStyleSheet('PaperWallet', (theme) => ({ 20 | root: { 21 | border: `1px solid ${theme.palette.text.lightDivider}`, 22 | display: 'flex', 23 | height: 290, 24 | width: 739, 25 | boxSizing: 'border-box', 26 | }, 27 | })); 28 | 29 | type ExternalProps = {| 30 | appContext: AppContext, 31 | address: string, 32 | privateKey: Buffer, 33 | className?: string, 34 | |}; 35 | // eslint-disable-next-line 36 | type InternalProps = {| 37 | styleManager: AppStyleManager, 38 | |}; 39 | /* :: 40 | type Props = {| 41 | ...ExternalProps, 42 | ...InternalProps, 43 | |}; 44 | */ 45 | function PaperWallet({ 46 | address, 47 | privateKey, 48 | className, 49 | styleManager, 50 | }: Props): React.Element<*> { 51 | const classes = styleManager.render(styleSheet); 52 | return ( 53 |
54 | 55 | 56 |
57 | ); 58 | } 59 | 60 | export default (compose( 61 | withContext( 62 | { appContext: () => null }, 63 | ({ appContext }) => ({ appContext }), 64 | ), 65 | getContext({ styleManager: () => null }), 66 | pure, 67 | )(PaperWallet): Class>); 68 | -------------------------------------------------------------------------------- /src/wallet/shared/components/info/InfoLabeled.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | getContext, 7 | pure, 8 | } from 'recompose'; 9 | import { createStyleSheet } from 'jss-theme-reactor'; 10 | 11 | import { type AppStyleManager } from '~/src/shared/styles/createStyleManager'; 12 | import { 13 | Help, 14 | } from '~/src/lib/components/shared/help'; 15 | import { 16 | Typography, 17 | } from '~/src/lib/components/shared/base'; 18 | 19 | const styleSheet = createStyleSheet('InfoLabeled', theme => ({ 20 | labelArea: { 21 | alignItems: 'center', 22 | display: 'flex', 23 | }, 24 | label: { 25 | marginLeft: theme.spacing.unit, 26 | }, 27 | element: { 28 | marginLeft: theme.spacing.unit * 4, 29 | marginTop: theme.spacing.unit, 30 | }, 31 | })); 32 | 33 | type ExternalProps = {| 34 | label: string, 35 | tooltip: string, 36 | element: React.Element, 37 | className?: string, 38 | |}; 39 | // eslint-disable-next-line 40 | type InternalProps = {| 41 | styleManager: AppStyleManager, 42 | |}; 43 | /* :: 44 | type Props = {| 45 | ...ExternalProps, 46 | ...InternalProps, 47 | |}; 48 | */ 49 | function InfoLabeled({ 50 | label, 51 | tooltip, 52 | element, 53 | className, 54 | styleManager, 55 | }: Props): React.Element<*> { 56 | const classes = styleManager.render(styleSheet); 57 | return ( 58 |
59 |
60 | 61 | 62 | {label} 63 | 64 |
65 |
66 | {element} 67 |
68 |
69 | ); 70 | } 71 | 72 | export default (compose( 73 | getContext({ styleManager: () => null }), 74 | pure, 75 | )(InfoLabeled): Class>); 76 | -------------------------------------------------------------------------------- /src/shared/components/common/view/PageView.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | pure, 7 | } from 'recompose'; 8 | 9 | import { Card } from '~/src/lib/components/shared/base'; 10 | import { CenteredView } from '~/src/lib/components/shared/layout'; 11 | 12 | import PageViewHeader from './PageViewHeader'; 13 | import TableView from './TableView'; 14 | 15 | type ExternalProps = {| 16 | id: string, 17 | title: string, 18 | name: string, 19 | pluralName: string, 20 | searchRoute: string, 21 | headerIcon?: string, 22 | headerBackgroundColorClassName?: string, 23 | bodyColumns: Array< 24 | [string, React.Element | string] | 25 | [string, React.Element | string, number] 26 | >, 27 | extraCard?: any, 28 | extra?: any, 29 | children?: any, 30 | className?: string, 31 | |}; 32 | // eslint-disable-next-line 33 | type InternalProps = {| 34 | |}; 35 | /* :: 36 | type Props = {| 37 | ...ExternalProps, 38 | ...InternalProps, 39 | |}; 40 | */ 41 | function PageView({ 42 | id, 43 | title, 44 | name, 45 | pluralName, 46 | searchRoute, 47 | headerIcon, 48 | headerBackgroundColorClassName, 49 | bodyColumns, 50 | extraCard, 51 | extra, 52 | className, 53 | }: Props): React.Element<*> { 54 | return ( 55 | 56 | 57 | 66 | 67 | {extraCard} 68 | 69 | {extra} 70 | 71 | ); 72 | } 73 | 74 | export default (compose( 75 | pure, 76 | )(PageView): Class>); 77 | -------------------------------------------------------------------------------- /src/lib/blockchain/shared/constants.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | export type AntSharesAssetIDType = 3 | 'c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b'; 4 | export const ANTSHARES_ASSET_HASH = 5 | 'c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b'; 6 | export const ANTSHARES_ASSET_ID = 1; 7 | export type AntCoinsAssetIDType = 8 | '602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7'; 9 | export const ANTCOINS_ASSET_HASH = 10 | '602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7'; 11 | export const ANTCOINS_ASSET_ID = 2; 12 | 13 | export const NEO_COIN_ASSET = { 14 | transaction_hash: ANTSHARES_ASSET_HASH, 15 | name: [ 16 | { 'lang': 'zh-CN', 'name': '小蚁股' }, 17 | { 'lang': 'en', 'name': 'AntShare' }, 18 | ], 19 | }; 20 | 21 | export const GAS_COIN_ASSET = { 22 | transaction_hash: ANTCOINS_ASSET_HASH, 23 | name: [ 24 | { 'lang': 'zh-CN', 'name': '小蚁币' }, 25 | { 'lang': 'en', 'name': 'AntCoin' }, 26 | ], 27 | }; 28 | 29 | export const TRANSACTION_TYPES = [ 30 | 'MinerTransaction', 31 | 'IssueTransaction', 32 | 'ClaimTransaction', 33 | 'EnrollmentTransaction', 34 | 'RegisterTransaction', 35 | 'ContractTransaction', 36 | 'PublishTransaction', 37 | 'InvocationTransaction', 38 | ]; 39 | export type TransactionType = 40 | 'MinerTransaction' | // 0x00 Transactions for allocating byte fees 41 | 'IssueTransaction' | // 0x01 42 | 'ClaimTransaction' | // 0x02 Transactions for the distribution of AntShares coins 43 | 'EnrollmentTransaction' | // 0x20 (Not usable) Special transaction for registration as a consensus candidate 44 | 'RegisterTransaction' | // 0x40 45 | 'ContractTransaction' | // 0x80 Contract transaction, which is the most commonly used transaction type 46 | 'PublishTransaction' | // 0xd0 (Not usuable) Special Transactions for Smart Contracts 47 | 'InvocationTransaction'; // 0xd1 Special transcations for calling smart contracts 48 | -------------------------------------------------------------------------------- /src/wallet/shared/components/paper/PaperWalletLabeled.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import classNames from 'classnames'; 5 | import { 6 | compose, 7 | getContext, 8 | pure, 9 | } from 'recompose'; 10 | import { createStyleSheet } from 'jss-theme-reactor'; 11 | 12 | import { type AppStyleManager } from '~/src/shared/styles/createStyleManager'; 13 | import { Typography } from '~/src/lib/components/shared/base'; 14 | 15 | const styleSheet = createStyleSheet('PaperWalletLabeled', theme => ({ 16 | root: { 17 | display: 'flex', 18 | }, 19 | label: { 20 | color: theme.palette.primary[500], 21 | display: 'flex', 22 | justifyContent: 'center', 23 | paddingRight: theme.spacing.unit, 24 | transform: 'rotate(-180deg)', 25 | writingMode: 'vertical-rl', 26 | }, 27 | borderBox: { 28 | boxSizing: 'border-box', 29 | }, 30 | })); 31 | 32 | type ExternalProps = {| 33 | element: React.Element, 34 | label: string, 35 | className?: string, 36 | |}; 37 | // eslint-disable-next-line 38 | type InternalProps = {| 39 | styleManager: AppStyleManager, 40 | |}; 41 | /* :: 42 | type Props = {| 43 | ...ExternalProps, 44 | ...InternalProps, 45 | |}; 46 | */ 47 | function PaperWalletLabeled({ 48 | element, 49 | label, 50 | className, 51 | styleManager, 52 | }: Props): React.Element<*> { 53 | const classes = styleManager.render(styleSheet); 54 | return ( 55 |
58 | {element} 59 | 64 | {label} 65 | 66 |
67 | ); 68 | } 69 | 70 | export default (compose( 71 | getContext({ styleManager: () => null }), 72 | pure, 73 | )(PaperWalletLabeled): Class>); 74 | -------------------------------------------------------------------------------- /src/wallet/shared/components/account/AccountView.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | pure, 7 | } from 'recompose'; 8 | import { graphql } from 'react-relay'; 9 | 10 | import { ErrorView } from '~/src/shared/components/common/error'; 11 | import { PageLoading } from '~/src/shared/components/common/loading'; 12 | import type { UnlockedWallet } from '~/src/wallet/shared/wallet'; 13 | 14 | import { fragmentContainer } from '~/src/lib/graphql/shared/relay'; 15 | 16 | import { 17 | type AccountView_address 18 | } from './__generated__/AccountView_address.graphql'; 19 | import AccountViewBase from './AccountViewBase'; 20 | 21 | type ExternalProps = {| 22 | wallet: UnlockedWallet, 23 | address?: any, 24 | loading?: boolean, 25 | error?: ?Error, 26 | retry?: ?() => void, 27 | forward?: boolean, 28 | className?: string, 29 | |}; 30 | // eslint-disable-next-line 31 | type InternalProps = {| 32 | address: AccountView_address, 33 | |}; 34 | /* :: 35 | type Props = {| 36 | ...ExternalProps, 37 | ...InternalProps, 38 | |}; 39 | */ 40 | function AccountView({ 41 | wallet, 42 | address, 43 | loading, 44 | error, 45 | retry, 46 | forward, 47 | className, 48 | }: Props): React.Element { 49 | if (error != null) { 50 | return ; 51 | } 52 | 53 | if (loading) { 54 | return ; 55 | } 56 | 57 | return ( 58 | 65 | ); 66 | } 67 | 68 | export default (compose( 69 | fragmentContainer({ 70 | address: graphql` 71 | fragment AccountView_address on Address { 72 | ...AccountViewBase_address 73 | } 74 | `, 75 | }), 76 | pure, 77 | )(AccountView): Class>); 78 | -------------------------------------------------------------------------------- /src/wallet/shared/components/keystore/GenerateKeystore.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import { Link } from 'react-router-dom'; 3 | import React from 'react'; 4 | 5 | import { 6 | compose, 7 | getContext, 8 | pure, 9 | } from 'recompose'; 10 | import { createStyleSheet } from 'jss-theme-reactor'; 11 | 12 | import { type AppStyleManager } from '~/src/shared/styles/createStyleManager'; 13 | import { 14 | Button, 15 | Typography, 16 | } from '~/src/lib/components/shared/base'; 17 | import type { WalletContext } from '~/src/wallet/shared/WalletContext'; 18 | 19 | import * as routes from '~/src/wallet/shared/routes'; 20 | 21 | const styleSheet = createStyleSheet('GenerateKeystore', theme => ({ 22 | link: { 23 | textDecoration: 'none', 24 | }, 25 | buttonText: { 26 | color: theme.custom.colors.common.white, 27 | }, 28 | })); 29 | 30 | type ExternalProps = {| 31 | className?: string, 32 | |}; 33 | // eslint-disable-next-line 34 | type InternalProps = {| 35 | styleManager: AppStyleManager, 36 | walletContext: WalletContext, 37 | |}; 38 | /* :: 39 | type Props = {| 40 | ...ExternalProps, 41 | ...InternalProps, 42 | |}; 43 | */ 44 | function GenerateKeystore({ 45 | className, 46 | styleManager, 47 | walletContext, 48 | }: Props): React.Element<*> { 49 | const classes = styleManager.render(styleSheet); 50 | return ( 51 | 55 | 64 | 65 | ); 66 | } 67 | 68 | export default (compose( 69 | getContext({ 70 | styleManager: () => null, 71 | walletContext: () => null, 72 | }), 73 | pure, 74 | )(GenerateKeystore): Class>); 75 | -------------------------------------------------------------------------------- /src/shared/components/common/view/RightPager.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import classNames from 'classnames'; 5 | import { 6 | compose, 7 | getContext, 8 | pure, 9 | } from 'recompose'; 10 | import { createStyleSheet } from 'jss-theme-reactor'; 11 | 12 | import { type AppStyleManager } from '~/src/shared/styles/createStyleManager'; 13 | import { Pager } from '~/src/lib/components/shared/pager'; 14 | 15 | const styleSheet = createStyleSheet('RightPager', theme => ({ 16 | [theme.breakpoints.down('sm')]: { 17 | pagerArea: { 18 | padding: theme.spacing.unit, 19 | }, 20 | }, 21 | [theme.breakpoints.up('sm')]: { 22 | pagerArea: { 23 | padding: theme.spacing.unit * 2, 24 | }, 25 | }, 26 | pagerArea: { 27 | alignItems: 'center', 28 | display: 'flex', 29 | justifyContent: 'flex-end', 30 | }, 31 | })); 32 | 33 | type ExternalProps = {| 34 | page: number, 35 | total: ?number, 36 | pageSize: number, 37 | onUpdatePage: (page: number) => void, 38 | isLoading?: boolean, 39 | error?: ?string, 40 | className?: string, 41 | |}; 42 | // eslint-disable-next-line 43 | type InternalProps = {| 44 | styleManager: AppStyleManager, 45 | |}; 46 | /* :: 47 | type Props = {| 48 | ...ExternalProps, 49 | ...InternalProps, 50 | |}; 51 | */ 52 | function RightPager({ 53 | page, 54 | total, 55 | pageSize, 56 | onUpdatePage, 57 | isLoading, 58 | error, 59 | className, 60 | styleManager, 61 | }: Props): React.Element<*> { 62 | const classes = styleManager.render(styleSheet); 63 | return ( 64 |
65 | 73 |
74 | ); 75 | } 76 | 77 | export default (compose( 78 | getContext({ styleManager: () => null }), 79 | pure, 80 | )(RightPager): Class>); 81 | -------------------------------------------------------------------------------- /src/lib/utils/objects/filterObject.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | function filterObjectLoop( 3 | obj: Object, 4 | filters: Object, 5 | basePropPath: string = '', 6 | ): Object { 7 | return Object.keys(filters).reduce( 8 | (acc, key) => { 9 | const propPath = basePropPath !== '' ? `${basePropPath}.${key}` : key; 10 | 11 | if (typeof filters[key] === 'object') { 12 | if (typeof obj[key] !== 'object') { 13 | throw new Error( 14 | `Expected prop at path "${propPath}" to be an object`, 15 | ); 16 | } 17 | acc[key] = filterObjectLoop(obj[key], filters[key], propPath); // eslint-disable-line no-param-reassign,max-len 18 | } else if (filters[key]) { 19 | if (typeof obj[key] === 'undefined') { 20 | throw new Error( 21 | `Filter set an "allow" on path "${propPath}", however, this path ` + 22 | 'was not found on the source object.', 23 | ); 24 | } 25 | acc[key] = obj[key]; // eslint-disable-line no-param-reassign 26 | } 27 | return acc; 28 | }, 29 | {}, 30 | ); 31 | } 32 | 33 | // Applies a given set of filters to filter a given object's structure. 34 | // 35 | // The filters object should match the shape of the source object and should 36 | // have a truthy/falsey value indicating if the property should be included/ 37 | // excluded. If the filters do not contain a property that exists on the 38 | // source object then the respective property will be excluded. 39 | // 40 | // Example: 41 | // filter( 42 | // // source 43 | // { 44 | // foo: { bar: 'bar', qux: 'qux' }, 45 | // bob: 'bob', 46 | // poop: { plop: 'splash' } 47 | // }, 48 | // // filters 49 | // { 50 | // foo: { bar: true }, 51 | // poop: true 52 | // } 53 | // ) 54 | // 55 | // Results in: 56 | // { 57 | // foo: { bar: 'bar' }, 58 | // poop: { plop: 'splash' } 59 | // }, 60 | export default function filterObject(obj: Object, filters: Object): Object { 61 | return filterObjectLoop(obj, filters); 62 | } 63 | -------------------------------------------------------------------------------- /src/shared/components/address/lib/__generated__/Coin_coin.graphql.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @flow 3 | */ 4 | 5 | /* eslint-disable */ 6 | 7 | 'use strict'; 8 | 9 | /*:: 10 | import type {ConcreteFragment} from 'relay-runtime'; 11 | export type Coin_coin = {| 12 | +value: string; 13 | +asset: {| 14 | +transaction_hash: string; 15 | +name: $ReadOnlyArray<{| 16 | +lang: string; 17 | +name: string; 18 | |}>; 19 | |}; 20 | |}; 21 | */ 22 | 23 | 24 | const fragment /*: ConcreteFragment*/ = { 25 | "argumentDefinitions": [], 26 | "kind": "Fragment", 27 | "metadata": null, 28 | "name": "Coin_coin", 29 | "selections": [ 30 | { 31 | "kind": "ScalarField", 32 | "alias": null, 33 | "args": null, 34 | "name": "value", 35 | "storageKey": null 36 | }, 37 | { 38 | "kind": "LinkedField", 39 | "alias": null, 40 | "args": null, 41 | "concreteType": "Asset", 42 | "name": "asset", 43 | "plural": false, 44 | "selections": [ 45 | { 46 | "kind": "ScalarField", 47 | "alias": null, 48 | "args": null, 49 | "name": "transaction_hash", 50 | "storageKey": null 51 | }, 52 | { 53 | "kind": "LinkedField", 54 | "alias": null, 55 | "args": null, 56 | "concreteType": "AssetName", 57 | "name": "name", 58 | "plural": true, 59 | "selections": [ 60 | { 61 | "kind": "ScalarField", 62 | "alias": null, 63 | "args": null, 64 | "name": "lang", 65 | "storageKey": null 66 | }, 67 | { 68 | "kind": "ScalarField", 69 | "alias": null, 70 | "args": null, 71 | "name": "name", 72 | "storageKey": null 73 | } 74 | ], 75 | "storageKey": null 76 | } 77 | ], 78 | "storageKey": null 79 | } 80 | ], 81 | "type": "Coin" 82 | }; 83 | 84 | module.exports = fragment; 85 | -------------------------------------------------------------------------------- /src/shared/components/common/error/PageError.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import classNames from 'classnames'; 5 | import { 6 | compose, 7 | getContext, 8 | pure, 9 | } from 'recompose'; 10 | import { createStyleSheet } from 'jss-theme-reactor'; 11 | 12 | import { type AppStyleManager } from '~/src/shared/styles/createStyleManager'; 13 | import { 14 | Card, 15 | Grid, 16 | } from '~/src/lib/components/shared/base'; 17 | 18 | import ErrorView from './ErrorView'; 19 | 20 | const styleSheet = createStyleSheet('PageError', theme => ({ 21 | [theme.breakpoints.down('md')]: { 22 | root: { 23 | padding: theme.spacing.unit, 24 | }, 25 | }, 26 | [theme.breakpoints.up('md')]: { 27 | root: { 28 | padding: theme.spacing.unit * 2, 29 | }, 30 | }, 31 | root: { 32 | margin: 0, 33 | width: '100%', 34 | }, 35 | cardContainer: { 36 | maxWidth: 456, 37 | }, 38 | })); 39 | 40 | type ExternalProps = {| 41 | error: Error, 42 | retry: ?() => void, 43 | allowRetry?: boolean, 44 | className?: string, 45 | |}; 46 | // eslint-disable-next-line 47 | type InternalProps = {| 48 | styleManager: AppStyleManager, 49 | |}; 50 | /* :: 51 | type Props = {| 52 | ...ExternalProps, 53 | ...InternalProps, 54 | |}; 55 | */ 56 | function PageError({ 57 | error, 58 | retry, 59 | allowRetry, 60 | className, 61 | styleManager, 62 | }: Props): React.Element<*> { 63 | const classes = styleManager.render(styleSheet); 64 | return ( 65 | 71 | 72 | 73 | 78 | 79 | 80 | 81 | ); 82 | } 83 | 84 | export default (compose( 85 | getContext({ styleManager: () => null }), 86 | pure, 87 | )(PageError): Class>); 88 | -------------------------------------------------------------------------------- /src/shared/components/common/loading/PageLoading.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import classNames from 'classnames'; 5 | import { 6 | compose, 7 | getContext, 8 | pure, 9 | } from 'recompose'; 10 | import { createStyleSheet } from 'jss-theme-reactor'; 11 | 12 | import { type AppStyleManager } from '~/src/shared/styles/createStyleManager'; 13 | import { LinearProgress } from '~/src/lib/components/shared/base'; 14 | import { Logo } from '~/src/shared/components/common/logo'; 15 | 16 | const styleSheet = createStyleSheet('PageLoading', theme => ({ 17 | [theme.breakpoints.down('md')]: { 18 | padding: { 19 | paddingTop: theme.spacing.unit * 2, 20 | paddingBottom: theme.spacing.unit * 2, 21 | }, 22 | }, 23 | [theme.breakpoints.up('md')]: { 24 | padding: { 25 | paddingTop: theme.spacing.unit * 3, 26 | paddingBottom: theme.spacing.unit * 3, 27 | }, 28 | }, 29 | root: { 30 | alignItems: 'center', 31 | display: 'flex', 32 | justifyContent: 'center', 33 | flexDirection: 'column', 34 | }, 35 | padding: {}, 36 | progress: { 37 | marginTop: theme.spacing.unit * 2, 38 | width: theme.spacing.unit * 16, 39 | }, 40 | })); 41 | 42 | type ExternalProps = {| 43 | disablePadding?: boolean, 44 | className?: string, 45 | |}; 46 | // eslint-disable-next-line 47 | type InternalProps = {| 48 | styleManager: AppStyleManager, 49 | |}; 50 | /* :: 51 | type Props = {| 52 | ...ExternalProps, 53 | ...InternalProps, 54 | |}; 55 | */ 56 | function PageLoading({ 57 | disablePadding, 58 | className, 59 | styleManager, 60 | }: Props): React.Element<*> { 61 | const classes = styleManager.render(styleSheet); 62 | return ( 63 |
66 | 67 | 68 |
69 | ); 70 | } 71 | 72 | export default (compose( 73 | getContext({ styleManager: () => null }), 74 | pure, 75 | )(PageLoading): Class>); 76 | -------------------------------------------------------------------------------- /src/lib/components/shared/layout/TitleCard.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | getContext, 7 | pure, 8 | } from 'recompose'; 9 | import { createStyleSheet } from 'jss-theme-reactor'; 10 | 11 | import { type AppStyleManager } from '~/src/shared/styles/createStyleManager'; 12 | import { 13 | Card, 14 | Typography, 15 | } from '~/src/lib/components/shared/base'; 16 | 17 | const styleSheet = createStyleSheet('TitleCard', theme => ({ 18 | [theme.breakpoints.down('sm')]: { 19 | header: { 20 | padding: theme.spacing.unit, 21 | }, 22 | }, 23 | [theme.breakpoints.up('sm')]: { 24 | header: { 25 | padding: theme.spacing.unit * 2, 26 | }, 27 | }, 28 | header: { 29 | alignItems: 'center', 30 | borderBottom: `1px solid ${theme.palette.text.lightDivider}`, 31 | display: 'flex', 32 | }, 33 | })); 34 | 35 | type ExternalProps = {| 36 | title: string, 37 | extra?: React.Element, 38 | titleComponent?: string, 39 | titleType?: string, 40 | children?: any, 41 | className?: string, 42 | |}; 43 | // eslint-disable-next-line 44 | type InternalProps = {| 45 | styleManager: AppStyleManager, 46 | |}; 47 | /* :: 48 | type Props = {| 49 | ...ExternalProps, 50 | ...InternalProps, 51 | |}; 52 | */ 53 | function TitleCard({ 54 | title, 55 | children, 56 | titleComponent: titleComponentIn, 57 | titleType: titleTypeIn, 58 | className, 59 | styleManager, 60 | }: Props): React.Element<*> { 61 | const classes = styleManager.render(styleSheet); 62 | const titleComponent = titleComponentIn || 'h1'; 63 | const titleType = titleTypeIn || 'title'; 64 | return ( 65 | 66 |
67 | 71 | {title} 72 | 73 |
74 | {children} 75 |
76 | ); 77 | } 78 | 79 | export default (compose( 80 | getContext({ styleManager: () => null }), 81 | pure, 82 | )(TitleCard): Class>); 83 | -------------------------------------------------------------------------------- /src/lib/errors/shared/ClientError.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import BaseError from './BaseError'; 3 | 4 | const CLIENT_ERROR_PREFIX = 'CLIENT:'; 5 | 6 | export const COPY_UNSUPPORTED_BROWSER = 7 | 'Copying to clipboard is not supported in your browser.'; 8 | export const SOMETHING_WENT_WRONG = 9 | 'Something went wrong. Try refreshing the page or going back to where you ' + 10 | 'were.'; 11 | export const NETWORK_ERROR = 12 | 'Network failure. Try refreshing the page.'; 13 | 14 | export default class ClientError extends BaseError { 15 | clientMessage: string; 16 | 17 | constructor(message: string, data?: Object) { 18 | super(`${CLIENT_ERROR_PREFIX}${message}`, data); 19 | this.clientMessage = message; 20 | } 21 | 22 | static extractClientErrorMessage(message: string): ?string { 23 | if (message.startsWith(CLIENT_ERROR_PREFIX)) { 24 | return message.substr(CLIENT_ERROR_PREFIX.length); 25 | } 26 | 27 | return null; 28 | } 29 | 30 | static getClientError(error: Error): ?ClientError { 31 | const message = this.extractClientErrorMessage(error.message); 32 | if (message != null) { 33 | return new ClientError(message, { originalError: error }); 34 | } 35 | 36 | return null; 37 | } 38 | 39 | // eslint-disable-next-line 40 | static getMessageForStatusCode(statusCode: number): string { 41 | // TODO: Make this better for each status code 42 | return SOMETHING_WENT_WRONG; 43 | } 44 | 45 | static async getFromResponse(response: Response): Promise { 46 | let originalMessage; 47 | let message; 48 | try { 49 | originalMessage = await response.text(); 50 | message = this.extractClientErrorMessage(originalMessage); 51 | } catch (error) { 52 | // Do nothing 53 | } 54 | return new ClientError( 55 | message || this.getMessageForStatusCode(response.status), 56 | { originalMessage, statusCode: response.status }, 57 | ); 58 | } 59 | 60 | static getFromNetworkError(error: Error): ClientError { 61 | return new ClientError( 62 | NETWORK_ERROR, 63 | { originalError: error }, 64 | ); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/shared/components/address/lib/__generated__/CoinTable_coins.graphql.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @flow 3 | */ 4 | 5 | /* eslint-disable */ 6 | 7 | 'use strict'; 8 | 9 | /*:: 10 | import type {ConcreteFragment} from 'relay-runtime'; 11 | export type CoinTable_coins = $ReadOnlyArray<{| 12 | +value: string; 13 | +asset: {| 14 | +transaction_hash: string; 15 | +name: $ReadOnlyArray<{| 16 | +lang: string; 17 | +name: string; 18 | |}>; 19 | |}; 20 | |}>; 21 | */ 22 | 23 | 24 | const fragment /*: ConcreteFragment*/ = { 25 | "argumentDefinitions": [], 26 | "kind": "Fragment", 27 | "metadata": { 28 | "plural": true 29 | }, 30 | "name": "CoinTable_coins", 31 | "selections": [ 32 | { 33 | "kind": "ScalarField", 34 | "alias": null, 35 | "args": null, 36 | "name": "value", 37 | "storageKey": null 38 | }, 39 | { 40 | "kind": "LinkedField", 41 | "alias": null, 42 | "args": null, 43 | "concreteType": "Asset", 44 | "name": "asset", 45 | "plural": false, 46 | "selections": [ 47 | { 48 | "kind": "ScalarField", 49 | "alias": null, 50 | "args": null, 51 | "name": "transaction_hash", 52 | "storageKey": null 53 | }, 54 | { 55 | "kind": "LinkedField", 56 | "alias": null, 57 | "args": null, 58 | "concreteType": "AssetName", 59 | "name": "name", 60 | "plural": true, 61 | "selections": [ 62 | { 63 | "kind": "ScalarField", 64 | "alias": null, 65 | "args": null, 66 | "name": "lang", 67 | "storageKey": null 68 | }, 69 | { 70 | "kind": "ScalarField", 71 | "alias": null, 72 | "args": null, 73 | "name": "name", 74 | "storageKey": null 75 | } 76 | ], 77 | "storageKey": null 78 | } 79 | ], 80 | "storageKey": null 81 | } 82 | ], 83 | "type": "Coin" 84 | }; 85 | 86 | module.exports = fragment; 87 | -------------------------------------------------------------------------------- /src/lib/components/shared/layout/CenteredView.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import classNames from 'classnames'; 5 | import { 6 | compose, 7 | getContext, 8 | pure, 9 | } from 'recompose'; 10 | import { createStyleSheet } from 'jss-theme-reactor'; 11 | 12 | import { type AppStyleManager } from '~/src/shared/styles/createStyleManager'; 13 | import { Grid } from '~/src/lib/components/shared/base'; 14 | 15 | const styleSheet = createStyleSheet('CenteredView', theme => ({ 16 | [theme.breakpoints.down('sm')]: { 17 | root: { 18 | padding: theme.spacing.unit, 19 | }, 20 | }, 21 | [theme.breakpoints.up('sm')]: { 22 | root: { 23 | padding: theme.spacing.unit * 2, 24 | }, 25 | }, 26 | root: { 27 | margin: 0, 28 | width: '100%', 29 | }, 30 | col: { 31 | display: 'flex', 32 | flexDirection: 'column', 33 | justifyContent: 'center', 34 | maxWidth: 1200, 35 | width: '100%', 36 | }, 37 | gridItem: { 38 | display: 'flex', 39 | justifyContent: 'center', 40 | }, 41 | })); 42 | 43 | type ExternalProps = {| 44 | children?: any, 45 | className?: string, 46 | |}; 47 | // eslint-disable-next-line 48 | type InternalProps = {| 49 | styleManager: AppStyleManager, 50 | |}; 51 | /* :: 52 | type Props = {| 53 | ...ExternalProps, 54 | ...InternalProps, 55 | |}; 56 | */ 57 | function CenteredView({ 58 | children, 59 | className, 60 | styleManager, 61 | }: Props): React.Element<*> { 62 | const classes = styleManager.render(styleSheet); 63 | return ( 64 | 70 | 77 |
78 | {children} 79 |
80 |
81 |
82 | ); 83 | } 84 | 85 | export default (compose( 86 | getContext({ styleManager: () => null }), 87 | pure, 88 | )(CenteredView): Class>); 89 | -------------------------------------------------------------------------------- /src/shared/components/common/logo/TitleLogo.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { compose, pure } from 'recompose'; 5 | 6 | type ExternalProps = {| 7 | id: string, 8 | |}; 9 | // eslint-disable-next-line 10 | type InternalProps = {| 11 | |} 12 | /* :: 13 | type Props = {| 14 | ...ExternalProps, 15 | ...InternalProps, 16 | |}; 17 | */ 18 | // eslint-disable-next-line 19 | function TitleLogo({ id }: Props): React.Element<*> { 20 | const a = `${id}a`; 21 | const b = `${id}b`; 22 | return ( 23 | 31 | NEO Tracker Blockchain Explorer 32 | NEO Tracker Blockchain Explorer 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | NEO Tracker 51 | 52 | 53 | 54 | ); 55 | } 56 | 57 | export default (compose( 58 | pure, 59 | )(TitleLogo): Class>); 60 | -------------------------------------------------------------------------------- /src/shared/components/transaction/TransactionPagingView.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | pure, 7 | } from 'recompose'; 8 | import { graphql } from 'react-relay'; 9 | 10 | import { PagingView } from '~/src/shared/components/common/view'; 11 | 12 | import { fragmentContainer } from '~/src/lib/graphql/shared/relay'; 13 | 14 | import TransactionTable from './TransactionTable'; 15 | import { 16 | type TransactionPagingView_transactions, 17 | } from './__generated__/TransactionPagingView_transactions.graphql'; 18 | 19 | type ExternalProps = {| 20 | transactions: any, 21 | isInitialLoad?: boolean, 22 | isLoadingMore: boolean, 23 | error?: ?string, 24 | page: number, 25 | total: ?number, 26 | pageSize: number, 27 | onUpdatePage: (page: number) => void, 28 | addressHash?: string, 29 | className?: string, 30 | |}; 31 | // eslint-disable-next-line 32 | type InternalProps = {| 33 | transactions: TransactionPagingView_transactions, 34 | |}; 35 | /* :: 36 | type Props = {| 37 | ...ExternalProps, 38 | ...InternalProps, 39 | |}; 40 | */ 41 | function TransactionPagingView({ 42 | transactions, 43 | isInitialLoad, 44 | isLoadingMore, 45 | error, 46 | page, 47 | total, 48 | pageSize, 49 | onUpdatePage, 50 | addressHash, 51 | className, 52 | }: Props): React.Element<*> { 53 | return ( 54 | 61 | } 62 | isInitialLoad={isInitialLoad} 63 | isLoadingMore={isLoadingMore} 64 | error={error} 65 | page={page} 66 | total={total} 67 | pageSize={pageSize} 68 | onUpdatePage={onUpdatePage} 69 | /> 70 | ); 71 | } 72 | 73 | export default (compose( 74 | fragmentContainer({ 75 | transactions: graphql` 76 | fragment TransactionPagingView_transactions on Transaction @relay(plural: true) { 77 | ...TransactionTable_transactions 78 | } 79 | ` 80 | }), 81 | pure, 82 | )(TransactionPagingView): Class>); 83 | -------------------------------------------------------------------------------- /src/wallet/shared/components/common/CopyField.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | getContext, 7 | pure, 8 | withHandlers, 9 | } from 'recompose'; 10 | 11 | import TextField, { 12 | // eslint-disable-next-line 13 | type ExternalProps as TextFieldExternalProps, 14 | } from '~/src/lib/components/shared/base/TextField'; 15 | 16 | import { clipboard } from '~/src/lib/utils/shared'; 17 | import log from '~/src/shared/log'; 18 | 19 | /* :: 20 | type ExternalProps = {| 21 | ...TextFieldExternalProps, 22 | name: string, 23 | value: string, 24 | |}; 25 | */ 26 | // eslint-disable-next-line 27 | type InternalProps = {| 28 | loggingContext: any, 29 | onClick: () => void, 30 | |}; 31 | /* :: 32 | type Props = {| 33 | ...ExternalProps, 34 | ...InternalProps, 35 | |}; 36 | */ 37 | function CopyField({ 38 | onClick: onClickIn, 39 | loggingContext, 40 | name, 41 | ...props 42 | }: Props): React.Element<*> { 43 | let onClick; 44 | if (clipboard.isSupported(loggingContext.userAgent)) { 45 | onClick = onClickIn; 46 | } 47 | return ( 48 | 53 | ); 54 | } 55 | 56 | export default (compose( 57 | getContext({ 58 | loggingContext: () => null, 59 | walletContext: () => null, 60 | }), 61 | pure, 62 | withHandlers({ 63 | onClick: ({ 64 | value, 65 | loggingContext, 66 | name, 67 | onClick, 68 | walletContext, 69 | }) => (event) => { 70 | clipboard.copy(value, loggingContext.userAgent) 71 | .then(() => { 72 | walletContext.setSnackbar({ 73 | message: `${name} Copied`, 74 | }); 75 | }) 76 | .catch(error => { 77 | walletContext.showSnackbarError({ error }); 78 | log({ 79 | event: 'COPY_ERROR', 80 | meta: { type: 'error', error }, 81 | context: loggingContext, 82 | }); 83 | }); 84 | if (onClick) { 85 | onClick(event); 86 | } 87 | }, 88 | }), 89 | )(CopyField): Class>); 90 | -------------------------------------------------------------------------------- /src/lib/log/shared/createServerLog.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import _ from 'lodash'; 3 | import winston from 'winston'; 4 | 5 | import type { BaseLogMeta, LogMessage } from './index'; 6 | 7 | const explodeError = (error: Error) => winston.exception.getAllInfo(error); 8 | 9 | const isError = (event: string) => 10 | event.toLowerCase().includes('error') || 11 | event.toLowerCase().includes('failure'); 12 | 13 | const cleanObject = (obj: Object) => { 14 | const newObj = _.pickBy( 15 | _.mapValues( 16 | obj, 17 | val => { 18 | if (typeof val === 'object') { 19 | return cleanObject(val); 20 | } 21 | return val; 22 | } 23 | ), 24 | val => val != null, 25 | ); 26 | 27 | return _.isEmpty(newObj) ? null : newObj; 28 | }; 29 | 30 | export default function< 31 | LogEvent: string, 32 | LogEventWithoutContext: string, 33 | LogMeta, 34 | LoggingContext, 35 | >( 36 | transformMeta: ( 37 | logMeta?: BaseLogMeta | LogMeta, 38 | explodeError: (error: Error) => Object, 39 | ) => ?(BaseLogMeta | LogMeta), 40 | log: { 41 | log: ( 42 | level: string, 43 | event: string, 44 | message: ?(string | Object), 45 | data?: Object, 46 | ) => void 47 | }, 48 | ) { 49 | return ( 50 | logMessage: LogMessage< 51 | LogEvent, 52 | LogEventWithoutContext, 53 | LogMeta, 54 | LoggingContext 55 | >, 56 | exitCallback?: () => void, 57 | ) => { 58 | const { event, message, context } = logMessage; 59 | let level = logMessage.level; 60 | if (level == null) { 61 | level = isError(event) ? 'error' : 'info'; 62 | } 63 | const meta = transformMeta(logMessage.meta, explodeError); 64 | const data = cleanObject({ message, meta, context }); 65 | 66 | if (exitCallback == null) { 67 | if (data == null) { 68 | log.log(level, event); 69 | } else { 70 | log.log(level, event, data); 71 | } 72 | } else { 73 | // eslint-disable-next-line 74 | if (data == null) { 75 | log.log(level, event, exitCallback); 76 | } else { 77 | log.log(level, event, data, exitCallback); 78 | } 79 | } 80 | }; 81 | } 82 | -------------------------------------------------------------------------------- /src/lib/graphql/shared/relay/paginationContainer.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import { 3 | type ConnectionConfig, 4 | type GraphQLTaggedNode, 5 | createPaginationContainer, 6 | } from 'react-relay'; 7 | import React from 'react'; 8 | 9 | import { 10 | compose, 11 | getContext, 12 | withHandlers, 13 | withProps, 14 | withState, 15 | } from 'recompose'; 16 | 17 | import { type Log } from '~/src/lib/log/shared'; 18 | 19 | import { sanitizeError } from '~/src/lib/errors/shared'; 20 | 21 | type Config = { 22 | pageSize: number, 23 | }; 24 | 25 | export default function( 26 | log: Log<*, *, *, LoggingContext>, 27 | ) { 28 | return ( 29 | fragments: { [key: string]: GraphQLTaggedNode }, 30 | connectionConfig: ConnectionConfig, 31 | config?: Config, 32 | ) => compose( 33 | getContext({ loggingContext: () => null }), 34 | (WrappedComponent: Class>) => 35 | createPaginationContainer( 36 | WrappedComponent, 37 | fragments, 38 | connectionConfig, 39 | ), 40 | withState('state', 'setState', () => ({ 41 | isLoadingMore: false, 42 | error: null, 43 | })), 44 | withProps(({ state }) => state), 45 | withHandlers({ 46 | onLoadMore: ({ 47 | relay, 48 | setState, 49 | loggingContext, 50 | }) => () => { 51 | if (relay.hasMore() && !relay.isLoading()) { 52 | setState(prevState => ({ 53 | ...prevState, 54 | isLoadingMore: true, 55 | error: null, 56 | })); 57 | relay.loadMore((config || { pageSize: 10 }).pageSize, (error) => { 58 | setState(prevState => ({ 59 | ...prevState, 60 | isLoadingMore: false, 61 | error: error == null ? null : sanitizeError(error).message, 62 | })); 63 | if (error != null) { 64 | log({ 65 | event: 'GRAPHQL_FETCH_ERROR', 66 | meta: { type: 'error', error: (error: Error) }, 67 | context: (loggingContext: LoggingContext), 68 | }); 69 | } 70 | }); 71 | } 72 | }, 73 | }), 74 | ); 75 | } 76 | -------------------------------------------------------------------------------- /src/lib/graphql/shared/relay/relay/paginationContainer.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import { 3 | type ConnectionConfig, 4 | type GraphQLTaggedNode, 5 | createPaginationContainer, 6 | } from 'react-relay'; 7 | import React from 'react'; 8 | 9 | import { 10 | compose, 11 | getContext, 12 | withHandlers, 13 | withProps, 14 | withState, 15 | } from 'recompose'; 16 | 17 | import { type Log } from '~/src/lib/log/shared'; 18 | 19 | import { sanitizeError } from '~/src/lib/errors/shared'; 20 | 21 | type Config = { 22 | pageSize: number, 23 | }; 24 | 25 | export default function( 26 | log: Log<*, *, *, LoggingContext>, 27 | ) { 28 | return ( 29 | fragments: { [key: string]: GraphQLTaggedNode }, 30 | connectionConfig: ConnectionConfig, 31 | config?: Config, 32 | ) => compose( 33 | getContext({ loggingContext: () => null }), 34 | (WrappedComponent: Class>) => 35 | createPaginationContainer( 36 | WrappedComponent, 37 | fragments, 38 | connectionConfig, 39 | ), 40 | withState('state', 'setState', () => ({ 41 | isLoadingMore: false, 42 | error: null, 43 | })), 44 | withProps(({ state }) => state), 45 | withHandlers({ 46 | onLoadMore: ({ 47 | relay, 48 | setState, 49 | loggingContext, 50 | }) => () => { 51 | if (relay.hasMore() && !relay.isLoading()) { 52 | setState(prevState => ({ 53 | ...prevState, 54 | isLoadingMore: true, 55 | error: null, 56 | })); 57 | relay.loadMore((config || { pageSize: 10 }).pageSize, (error) => { 58 | setState(prevState => ({ 59 | ...prevState, 60 | isLoadingMore: false, 61 | error: error == null ? null : sanitizeError(error).message, 62 | })); 63 | if (error != null) { 64 | log({ 65 | event: 'GRAPHQL_FETCH_ERROR', 66 | meta: { type: 'error', error: (error: Error) }, 67 | context: (loggingContext: LoggingContext), 68 | }); 69 | } 70 | }); 71 | } 72 | }, 73 | }), 74 | ); 75 | } 76 | -------------------------------------------------------------------------------- /src/shared/components/address/lib/AddressLink.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | getContext, 7 | pure, 8 | } from 'recompose'; 9 | import { createStyleSheet } from 'jss-theme-reactor'; 10 | 11 | import { type AppStyleManager } from '~/src/shared/styles/createStyleManager'; 12 | import { Link } from '~/src/lib/components/shared/link'; 13 | import { 14 | Typography, 15 | } from '~/src/lib/components/shared/base'; 16 | 17 | import * as routes from '~/src/shared/routes'; 18 | 19 | const styleSheet = createStyleSheet('AddressLink', theme => ({ 20 | highlighted: { 21 | color: theme.palette.accent.A200, 22 | fontWeight: theme.typography.fontWeightRegular, 23 | textDecoration: 'none', 24 | overflow: 'hidden', 25 | textOverflow: 'ellipsis', 26 | }, 27 | })); 28 | 29 | 30 | type ExternalProps = {| 31 | addressHash: string, 32 | highlighted?: boolean, 33 | white?: boolean, 34 | absolute?: 'main' | 'test', 35 | className?: string, 36 | |}; 37 | // eslint-disable-next-line 38 | type InternalProps = {| 39 | styleManager: AppStyleManager, 40 | |}; 41 | /* :: 42 | type Props = {| 43 | ...ExternalProps, 44 | ...InternalProps, 45 | |}; 46 | */ 47 | function AddressLink({ 48 | addressHash, 49 | highlighted, 50 | white, 51 | absolute, 52 | className, 53 | styleManager, 54 | }: Props): React.Element { 55 | const classes = styleManager.render(styleSheet); 56 | if (highlighted) { 57 | return ( 58 | 62 | {addressHash} 63 | 64 | ) 65 | } 66 | let path = routes.makeAddress(addressHash); 67 | const isAbsolute = absolute != null; 68 | if (isAbsolute) { 69 | path = routes.makeURL({ testNet: absolute === 'test', path }); 70 | } 71 | return ( 72 | 80 | ); 81 | } 82 | 83 | export default (compose( 84 | getContext({ styleManager: () => null }), 85 | pure, 86 | )(AddressLink): Class>); 87 | -------------------------------------------------------------------------------- /src/wallet/shared/components/info/InfoCard.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | getContext, 7 | pure, 8 | } from 'recompose'; 9 | import { createStyleSheet } from 'jss-theme-reactor'; 10 | 11 | import { type AppStyleManager } from '~/src/shared/styles/createStyleManager'; 12 | import { TitleCard } from '~/src/lib/components/shared/layout'; 13 | import { 14 | Typography, 15 | } from '~/src/lib/components/shared/base'; 16 | import type { Wallet } from '~/src/wallet/shared/wallet'; 17 | 18 | import InfoView from './InfoView'; 19 | 20 | const styleSheet = createStyleSheet('InfoCard', theme => ({ 21 | [theme.breakpoints.down('sm')]: { 22 | content: { 23 | padding: theme.spacing.unit, 24 | }, 25 | }, 26 | [theme.breakpoints.up('sm')]: { 27 | content: { 28 | padding: theme.spacing.unit * 2, 29 | }, 30 | }, 31 | content: {}, 32 | })); 33 | 34 | type ExternalProps = {| 35 | wallet: ?Wallet, 36 | className?: string, 37 | |}; 38 | // eslint-disable-next-line 39 | type InternalProps = {| 40 | styleManager: AppStyleManager, 41 | |}; 42 | /* :: 43 | type Props = {| 44 | ...ExternalProps, 45 | ...InternalProps, 46 | |}; 47 | */ 48 | function InfoCard({ 49 | wallet, 50 | className, 51 | styleManager, 52 | }: Props): React.Element<*> { 53 | const classes = styleManager.render(styleSheet); 54 | let content = ( 55 | 56 | Open or create a wallet to view wallet details. 57 | 58 | ); 59 | if (wallet != null) { 60 | if (wallet.isLocked) { 61 | content = ( 62 | 63 | Unlock your wallet to see wallet details. 64 | 65 | ); 66 | } else { 67 | content = ; 68 | } 69 | } 70 | 71 | return ( 72 | 77 |
78 | {content} 79 |
80 |
81 | ); 82 | } 83 | 84 | export default (compose( 85 | getContext({ styleManager: () => null }), 86 | pure, 87 | )(InfoCard): Class>); 88 | -------------------------------------------------------------------------------- /src/shared/components/common/logo/Logo.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { compose, pure } from 'recompose'; 5 | 6 | type ExternalProps = {| 7 | width?: number, 8 | height?: number, 9 | white?: boolean, 10 | className?: string, 11 | |}; 12 | // eslint-disable-next-line 13 | type InternalProps = {| 14 | |} 15 | /* :: 16 | type Props = {| 17 | ...ExternalProps, 18 | ...InternalProps, 19 | |}; 20 | */ 21 | function Logo({ 22 | width, 23 | height, 24 | white, 25 | className, 26 | }: Props): React.Element<*> { 27 | let defs; 28 | let g = ( 29 | 30 | 31 | 32 | 33 | 34 | ); 35 | if (!white) { 36 | defs = ( 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | ); 48 | g = ( 49 | 50 | 51 | 52 | 53 | 54 | ); 55 | } 56 | return ( 57 | 64 | {defs} 65 | {g} 66 | 67 | ); 68 | } 69 | 70 | export default (compose( 71 | pure, 72 | )(Logo): Class>); 73 | -------------------------------------------------------------------------------- /src/wallet/client/renderApp.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | // eslint-disable-next-line 3 | import { AppContainer } from 'react-hot-loader'; 4 | import { HashRouter } from 'react-router-dom'; 5 | import { type Environment } from 'relay-runtime'; 6 | import { Provider } from 'react-redux'; 7 | import React from 'react'; 8 | 9 | import { render } from 'react-dom'; 10 | import { withContext } from 'recompose'; 11 | 12 | import type { AppContext } from '~/src/shared/AppContext'; 13 | import WalletApp from '~/src/wallet/shared/WalletApp'; 14 | import type { WalletContext } from '~/src/wallet/shared/WalletContext'; 15 | import { ThemeProvider } from '~/src/lib/components/shared/theme'; 16 | 17 | import createStyleManager from '~/src/shared/styles/createStyleManager'; 18 | import { type ClientLoggingContext } from '~/src/shared/log'; 19 | 20 | const ContextProvider = withContext( 21 | { 22 | loggingContext: () => null, 23 | relayEnvironment: () => null, 24 | appContext: () => null, 25 | walletContext: () => null, 26 | }, 27 | ({ loggingContext, relayEnvironment, appContext, walletContext }) => ({ 28 | loggingContext, 29 | relayEnvironment, 30 | appContext, 31 | walletContext, 32 | }), 33 | )(({ children }) => children); 34 | 35 | const basename = window.location.pathname; 36 | let container; 37 | export default function renderApp( 38 | store: any, 39 | relayEnvironment: Environment, 40 | loggingContext: ClientLoggingContext, 41 | walletContext: WalletContext, 42 | appContext: AppContext, 43 | TheApp?: Class, 44 | ): void { 45 | const AppComponent = TheApp || WalletApp; 46 | const app = ( 47 | 48 | 49 | 50 | 56 | 57 | 58 | 59 | 60 | 61 | ); 62 | if (container == null) { 63 | container = document.querySelector('#app'); 64 | } 65 | 66 | render(app, container); 67 | } 68 | -------------------------------------------------------------------------------- /src/shared/components/common/table/Table.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import classNames from 'classnames'; 5 | import { 6 | compose, 7 | getContext, 8 | pure, 9 | } from 'recompose'; 10 | import { createStyleSheet } from 'jss-theme-reactor'; 11 | 12 | import { type AppStyleManager } from '~/src/shared/styles/createStyleManager'; 13 | 14 | import Column from './Column'; 15 | 16 | const styleSheet = createStyleSheet('Table', (theme) => ({ 17 | [theme.breakpoints.down('sm')]: { 18 | root: { 19 | '& > div:last-child > div': { 20 | paddingRight: theme.spacing.unit, 21 | }, 22 | }, 23 | }, 24 | [theme.breakpoints.up('sm')]: { 25 | root: { 26 | '& > div:last-child > div': { 27 | paddingRight: theme.spacing.unit * 2, 28 | }, 29 | }, 30 | }, 31 | root: { 32 | display: 'flex', 33 | }, 34 | })); 35 | 36 | type ColumnType = { 37 | name: string, 38 | className?: string, 39 | values: Array>, 40 | numeric?: boolean, 41 | visibleAt?: string, 42 | minWidth?: boolean, 43 | }; 44 | 45 | type ExternalProps = {| 46 | columns: Array, 47 | getRowHeight?: (idx: number) => ?number, 48 | className?: string, 49 | |}; 50 | // eslint-disable-next-line 51 | type InternalProps = {| 52 | styleManager: AppStyleManager, 53 | |}; 54 | /* :: 55 | type Props = {| 56 | ...ExternalProps, 57 | ...InternalProps, 58 | |}; 59 | */ 60 | function Table({ 61 | columns, 62 | getRowHeight, 63 | className, 64 | styleManager, 65 | }: Props): React.Element<*> { 66 | const classes = styleManager.render(styleSheet); 67 | return ( 68 |
69 | {columns.map((col, idx) => ( 70 | 81 | ))} 82 |
83 | ); 84 | } 85 | 86 | export default (compose( 87 | getContext({ styleManager: () => null }), 88 | pure, 89 | )(Table): Class>); 90 | -------------------------------------------------------------------------------- /src/wallet/shared/components/main/MainWalletView.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | getContext, 7 | pure, 8 | } from 'recompose'; 9 | import { connect } from 'react-redux'; 10 | import { createStyleSheet } from 'jss-theme-reactor'; 11 | 12 | import type { AppStyleManager } from '~/src/shared/styles/createStyleManager'; 13 | import { PageLoading } from '~/src/shared/components/common/loading'; 14 | import type { Wallet } from '~/src/wallet/shared/wallet'; 15 | 16 | import { 17 | selectSelectedWallet, 18 | selectWalletReady, 19 | } from '~/src/wallet/shared/redux'; 20 | 21 | import MainWalletViewLocked from './MainWalletViewLocked'; 22 | import MainWalletViewUnlocked from './MainWalletViewUnlocked'; 23 | 24 | const styleSheet = createStyleSheet('MainWalletView', theme => ({ 25 | padding: { 26 | paddingTop: theme.spacing.unit, 27 | paddingBottom: theme.spacing.unit, 28 | }, 29 | })); 30 | 31 | type ExternalProps = {| 32 | className?: string, 33 | |}; 34 | // eslint-disable-next-line 35 | type InternalProps = {| 36 | ready: boolean, 37 | selectedWallet: Wallet, 38 | styleManager: AppStyleManager, 39 | |}; 40 | /* :: 41 | type Props = {| 42 | ...ExternalProps, 43 | ...InternalProps, 44 | |}; 45 | */ 46 | function MainWalletView({ 47 | className, 48 | ready, 49 | selectedWallet, 50 | styleManager, 51 | }: Props): React.Element { 52 | const classes = styleManager.render(styleSheet); 53 | if (!ready) { 54 | return ; 55 | } 56 | 57 | if (selectedWallet == null || selectedWallet.isLocked) { 58 | return ( 59 | 63 | ); 64 | } 65 | 66 | return ( 67 | 71 | ); 72 | } 73 | 74 | export default (compose( 75 | getContext({ walletContext: () => null, styleManager: () => null }), 76 | connect((state, { walletContext }) => ({ 77 | ready: selectWalletReady(walletContext, state), 78 | selectedWallet: selectSelectedWallet(walletContext, state), 79 | })), 80 | pure, 81 | )(MainWalletView): Class>); 82 | -------------------------------------------------------------------------------- /src/lib/jss2css/transform/styleSheet.js: -------------------------------------------------------------------------------- 1 | const appRootDir = require('app-root-dir'); 2 | const nodePath = require('path'); 3 | const t = require('babel-types'); 4 | const { isCreateStylesheet } = require('./utils'); 5 | 6 | module.exports = () => ({ 7 | visitor: { 8 | Program: { 9 | enter(path) { 10 | this.context = { 11 | isES6: path.node.body.some( 12 | node => t.isImportDeclaration(node), 13 | ), 14 | }; 15 | }, 16 | }, 17 | CallExpression: { 18 | enter(path, state) { 19 | if (!isCreateStylesheet(path.get('callee'))) { 20 | return; 21 | } 22 | if (!t.isStringLiteral(path.node.arguments[0])) { 23 | throw path.buildCodeFrameError( 24 | 'Non-string literal stylesheet names are not supported.' 25 | ); 26 | } 27 | 28 | const { isES6 } = this.context; 29 | const sheetName = path.node.arguments[0].value; 30 | const rel = nodePath.relative( 31 | nodePath.dirname(state.file.opts.filename), 32 | nodePath.resolve( 33 | appRootDir.get(), 34 | './__generated__/css', 35 | ), 36 | ); 37 | const pathLiteral = t.stringLiteral(`${rel}/${sheetName}.js`); 38 | if (isES6) { 39 | if (!( 40 | t.isVariableDeclarator(path.parentPath.node) && 41 | t.isVariableDeclaration(path.parentPath.parentPath.node) 42 | )) { 43 | throw path.buildCodeFrameError( 44 | 'Expected variable declaration for createStyleSheet.' 45 | ); 46 | } 47 | const declaratorPath = path.parentPath; 48 | const declarationPath = declaratorPath.parentPath; 49 | declarationPath.replaceWith( 50 | t.importDeclaration( 51 | [t.importDefaultSpecifier(declaratorPath.node.id)], 52 | pathLiteral, 53 | ), 54 | ); 55 | } else { 56 | path.replaceWith( 57 | t.memberExpression( 58 | t.callExpression( 59 | t.identifier('require'), 60 | [pathLiteral], 61 | ), 62 | t.identifier('default'), 63 | ), 64 | ); 65 | } 66 | }, 67 | }, 68 | }, 69 | }); 70 | -------------------------------------------------------------------------------- /src/wallet/shared/components/select/MainSelectCardUnlocked.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | import React from 'react'; 3 | 4 | import { 5 | compose, 6 | pure, 7 | } from 'recompose'; 8 | import { graphql } from 'react-relay'; 9 | 10 | import { SelectCard } from '~/src/wallet/shared/components/select'; 11 | import type { UnlockedWallet } from '~/src/wallet/shared/wallet'; 12 | 13 | import { createSafeRetry } from '~/src/lib/utils/shared'; 14 | import { queryRenderer } from '~/src/shared/graphql/relay'; 15 | 16 | import { 17 | type MainSelectCardUnlockedQueryResponse 18 | } from './__generated__/MainSelectCardUnlockedQuery.graphql'; 19 | 20 | const safeRetry = createSafeRetry(); 21 | 22 | type ExternalProps = {| 23 | wallet: UnlockedWallet, 24 | className?: string, 25 | |}; 26 | // eslint-disable-next-line 27 | type InternalProps = {| 28 | props: ?MainSelectCardUnlockedQueryResponse, 29 | lastProps: ?MainSelectCardUnlockedQueryResponse, 30 | error: ?Error, 31 | retry: ?() => void, 32 | |}; 33 | /* :: 34 | type Props = {| 35 | ...ExternalProps, 36 | ...InternalProps, 37 | |}; 38 | */ 39 | function MainSelectCardUnlocked({ 40 | wallet, 41 | props: propsIn, 42 | lastProps, 43 | error: errorIn, 44 | retry, 45 | className, 46 | }: Props): React.Element { 47 | const props = propsIn || lastProps; 48 | if (errorIn != null && retry != null) { 49 | safeRetry(retry); 50 | } else { 51 | safeRetry.cancel(); 52 | } 53 | const error = props == null ? errorIn : null; 54 | const address = props == null ? null : props.address; 55 | const loading = props == null; 56 | return ( 57 | 66 | ); 67 | } 68 | 69 | export default (compose( 70 | queryRenderer(graphql` 71 | query MainSelectCardUnlockedQuery($hash: String!) { 72 | address(hash: $hash) { 73 | ...SelectCard_address 74 | } 75 | } 76 | `, { 77 | mapPropsToVariables: { 78 | client: ({ wallet }) => ({ 79 | hash: wallet.address, 80 | }), 81 | }, 82 | cacheConfig: { 83 | poll: 10000, 84 | }, 85 | }), 86 | pure, 87 | )(MainSelectCardUnlocked): Class>); 88 | -------------------------------------------------------------------------------- /src/wallet/shared/components/account/__generated__/AccountViewBase_address.graphql.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @flow 3 | */ 4 | 5 | /* eslint-disable */ 6 | 7 | 'use strict'; 8 | 9 | /*:: 10 | import type {ConcreteFragment} from 'relay-runtime'; 11 | export type AccountViewBase_address = {| 12 | +confirmed_coins: {| 13 | +edges: $ReadOnlyArray<{| 14 | +node: {| |}; 15 | |}>; 16 | |}; 17 | +claim_value_available_coin: {| 18 | +value: string; 19 | |}; 20 | |}; 21 | */ 22 | 23 | 24 | const fragment /*: ConcreteFragment*/ = { 25 | "argumentDefinitions": [], 26 | "kind": "Fragment", 27 | "metadata": null, 28 | "name": "AccountViewBase_address", 29 | "selections": [ 30 | { 31 | "kind": "LinkedField", 32 | "alias": null, 33 | "args": null, 34 | "concreteType": "AddressToConfirmedCoinsConnection", 35 | "name": "confirmed_coins", 36 | "plural": false, 37 | "selections": [ 38 | { 39 | "kind": "LinkedField", 40 | "alias": null, 41 | "args": null, 42 | "concreteType": "AddressToConfirmedCoinsEdge", 43 | "name": "edges", 44 | "plural": true, 45 | "selections": [ 46 | { 47 | "kind": "LinkedField", 48 | "alias": null, 49 | "args": null, 50 | "concreteType": "Coin", 51 | "name": "node", 52 | "plural": false, 53 | "selections": [ 54 | { 55 | "kind": "FragmentSpread", 56 | "name": "CoinTable_coins", 57 | "args": null 58 | } 59 | ], 60 | "storageKey": null 61 | } 62 | ], 63 | "storageKey": null 64 | } 65 | ], 66 | "storageKey": null 67 | }, 68 | { 69 | "kind": "LinkedField", 70 | "alias": null, 71 | "args": null, 72 | "concreteType": "Coin", 73 | "name": "claim_value_available_coin", 74 | "plural": false, 75 | "selections": [ 76 | { 77 | "kind": "ScalarField", 78 | "alias": null, 79 | "args": null, 80 | "name": "value", 81 | "storageKey": null 82 | } 83 | ], 84 | "storageKey": null 85 | } 86 | ], 87 | "type": "Address" 88 | }; 89 | 90 | module.exports = fragment; 91 | -------------------------------------------------------------------------------- /src/lib/jss2css/transform/utils.js: -------------------------------------------------------------------------------- 1 | const t = require("babel-types"); 2 | 3 | module.exports.isCreateStylesheet = path => { 4 | const node = path.node; 5 | if (t.isIdentifier(node)) { 6 | return isCreateStylesheetImport(path); 7 | } 8 | 9 | if ( 10 | t.isSequenceExpression(node) && 11 | node.expressions.length === 2 && 12 | t.isNumericLiteral(node.expressions[0]) && 13 | node.expressions[0].value === 0 14 | ) { 15 | return isCreateStylesheetRequire(path.get('expressions')[1]); 16 | } 17 | 18 | return false; 19 | }; 20 | 21 | const isCreateStylesheetImport = path => { 22 | if (!( 23 | t.isIdentifier(path.node) && 24 | t.isReferenced(path.node, path.parent) 25 | )) { 26 | return false; 27 | } 28 | 29 | const binding = path.scope.getBinding(path.node.name); 30 | if (binding == null) { 31 | return false; 32 | } 33 | 34 | return isJSSThemeReactorImport(binding.path); 35 | }; 36 | 37 | const isJSSThemeReactorImport = path => 38 | t.isImportSpecifier(path.node) && 39 | path.node.imported.name === 'createStyleSheet' && 40 | t.isImportDeclaration(path.parent) && 41 | path.parent.source.value === 'jss-theme-reactor' 42 | module.exports.isJSSThemeReactorImport = isJSSThemeReactorImport; 43 | 44 | const isCreateStylesheetRequire = path => { 45 | const node = path.node; 46 | if (!( 47 | t.isMemberExpression(node) && 48 | t.isIdentifier(node.object) && 49 | t.isIdentifier(node.property) && 50 | node.property.name === 'createStyleSheet' 51 | )) { 52 | return false; 53 | } 54 | 55 | const jssPath = path.get('object'); 56 | if (!t.isReferenced(jssPath.node, jssPath.parent)) { 57 | return false; 58 | } 59 | 60 | const binding = jssPath.scope.getBinding(jssPath.node.name); 61 | if (binding == null) { 62 | return false; 63 | } 64 | 65 | if (!t.isVariableDeclarator(binding.path.node)) { 66 | return false; 67 | } 68 | 69 | const initPath = binding.path.get('init'); 70 | return isJSSThemeReactorRequire(initPath.node); 71 | } 72 | 73 | const isJSSThemeReactorRequire = node => 74 | t.isCallExpression(node) && 75 | t.isIdentifier(node.callee) && 76 | node.callee.name === 'require' && 77 | node.arguments.length === 1 && 78 | t.isStringLiteral(node.arguments[0]) && 79 | node.arguments[0].value === 'jss-theme-reactor'; 80 | 81 | module.exports.isJSSThemeReactorRequire = isJSSThemeReactorRequire; 82 | --------------------------------------------------------------------------------