├── .nvmrc
├── src
├── routes
│ ├── Scoreboard
│ │ ├── api
│ │ │ └── index.js
│ │ ├── store
│ │ │ ├── reducers
│ │ │ │ ├── index.js
│ │ │ │ └── users.js
│ │ │ ├── models
│ │ │ │ ├── index.js
│ │ │ │ └── user.js
│ │ │ ├── index.js
│ │ │ └── actions
│ │ │ │ ├── addUsers.js
│ │ │ │ ├── index.js
│ │ │ │ ├── fetchTournamentUsers.js
│ │ │ │ ├── fetchTournamentUserData.js
│ │ │ │ └── rewards.js
│ │ ├── components
│ │ │ ├── Table
│ │ │ │ ├── ScoreTable
│ │ │ │ │ ├── index.css
│ │ │ │ │ └── index.stories.js
│ │ │ │ └── Table.scss
│ │ │ ├── RewardClaimAddress
│ │ │ │ ├── AddressSection
│ │ │ │ │ └── AddressSection.scss
│ │ │ │ └── RewardClaim.scss
│ │ │ ├── Layout.scss
│ │ │ └── Layout.stories.js
│ │ ├── containers
│ │ │ ├── index.js
│ │ │ ├── actions.js
│ │ │ └── selector.js
│ │ └── assets
│ │ │ ├── ok.svg
│ │ │ └── trophy.svg
│ ├── Dashboard
│ │ ├── api
│ │ │ ├── fetchTrades.js
│ │ │ └── fetchShares.js
│ │ ├── components
│ │ │ └── Dashboard
│ │ │ │ ├── Dashboard.scss
│ │ │ │ ├── Markets
│ │ │ │ ├── Markets.scss
│ │ │ │ ├── Market
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── NoMarket.js
│ │ │ │ ├── ConditionalList.scss
│ │ │ │ ├── Category.scss
│ │ │ │ └── Category.js
│ │ │ │ ├── UserSection
│ │ │ │ ├── Category.scss
│ │ │ │ ├── UserSection.scss
│ │ │ │ └── Category.js
│ │ │ │ ├── Title
│ │ │ │ ├── DashboardTitle.scss
│ │ │ │ └── index.js
│ │ │ │ └── Metrics
│ │ │ │ └── Metric.js
│ │ ├── assets
│ │ │ ├── group.png
│ │ │ ├── arrows.svg
│ │ │ ├── shape.svg
│ │ │ ├── crystal-ball.svg
│ │ │ ├── badges
│ │ │ │ └── crystal-gazer.svg
│ │ │ └── icon_outstandingPredictions.svg
│ │ └── containers
│ │ │ ├── Dashboard
│ │ │ ├── utils
│ │ │ │ ├── index.js
│ │ │ │ └── calculateProfit.js
│ │ │ ├── index.js
│ │ │ └── actions.js
│ │ │ └── index.js
│ ├── MarketDetails
│ │ ├── components
│ │ │ ├── ExpandableViews
│ │ │ │ ├── MarketBuySharesForm
│ │ │ │ │ ├── OutcomesSection
│ │ │ │ │ │ ├── OutcomesSection.scss
│ │ │ │ │ │ └── index.js
│ │ │ │ │ ├── SubmitError
│ │ │ │ │ │ └── index.js
│ │ │ │ │ └── LimitMarginAnnotation
│ │ │ │ │ │ └── index.js
│ │ │ │ ├── MarketMySharesForm
│ │ │ │ │ └── SharesTable
│ │ │ │ │ │ ├── ShareRow
│ │ │ │ │ │ └── ShareRow.scss
│ │ │ │ │ │ └── SharesTable.scss
│ │ │ │ └── MarketMyTrades
│ │ │ │ │ ├── marketMyTrades.scss
│ │ │ │ │ └── TableHeader
│ │ │ │ │ └── index.js
│ │ │ ├── MarketGraph
│ │ │ │ ├── MarketGraph.scss
│ │ │ │ └── DateAxisTick
│ │ │ │ │ └── index.js
│ │ │ └── MarketDetail
│ │ │ │ ├── Details
│ │ │ │ ├── Details.scss
│ │ │ │ ├── RedeemWinnings
│ │ │ │ │ └── RedeemWinnings.scss
│ │ │ │ └── MarketTimer
│ │ │ │ │ └── MarketTimer.scss
│ │ │ │ ├── marketDetail.scss
│ │ │ │ ├── Infos
│ │ │ │ └── utils
│ │ │ │ │ └── embeddedLink.js
│ │ │ │ └── Controls
│ │ │ │ └── Controls.scss
│ │ ├── api
│ │ │ ├── index.js
│ │ │ ├── sellShares.js
│ │ │ └── calculateGasCost.js
│ │ ├── store
│ │ │ ├── selectors
│ │ │ │ ├── isGasPriceFetched.js
│ │ │ │ ├── isGasCostFetched.js
│ │ │ │ ├── getGasCosts.js
│ │ │ │ ├── index.js
│ │ │ │ ├── getGasPrice.js
│ │ │ │ ├── getMarketTradesForAccount.js
│ │ │ │ └── getMarketShares.js
│ │ │ └── actions
│ │ │ │ ├── index.js
│ │ │ │ ├── requestMarketTradesForAccount.js
│ │ │ │ ├── requestMarketSharesForAccount.js
│ │ │ │ ├── requestGasCost.js
│ │ │ │ └── requestMarket.js
│ │ └── containers
│ │ │ └── index.js
│ ├── Transactions
│ │ ├── store
│ │ │ ├── reducers
│ │ │ │ └── index.js
│ │ │ ├── models
│ │ │ │ └── transaction.js
│ │ │ └── selectors
│ │ │ │ └── transactions.spec.js
│ │ ├── components
│ │ │ └── Transactions
│ │ │ │ └── Transaction
│ │ │ │ └── DetailLabel
│ │ │ │ ├── DetailLabel.scss
│ │ │ │ └── index.js
│ │ └── containers
│ │ │ ├── index.js
│ │ │ └── TransactionsPage
│ │ │ └── index.js
│ ├── reducers.js
│ ├── GameGuide
│ │ ├── assets
│ │ │ ├── claim.png
│ │ │ ├── login1.png
│ │ │ ├── login2.png
│ │ │ ├── login3.png
│ │ │ ├── login4.png
│ │ │ ├── profits1.png
│ │ │ ├── profits2.png
│ │ │ ├── profits3.png
│ │ │ ├── prediction1.png
│ │ │ ├── prediction2.png
│ │ │ ├── prediction3.png
│ │ │ ├── prediction4.png
│ │ │ ├── prediction5.png
│ │ │ ├── claimRewards.png
│ │ │ ├── connectWallet.png
│ │ │ ├── registerWallet.png
│ │ │ ├── switchNetwork.png
│ │ │ ├── switchNetwork2.png
│ │ │ ├── marketoverview1.png
│ │ │ ├── claimSwitchNetwork.png
│ │ │ └── dashboardoverview1.png
│ │ ├── containers
│ │ │ └── GameGuide.js
│ │ └── components
│ │ │ ├── metamaskComponents
│ │ │ └── SignUp
│ │ │ │ └── SignUp.scss
│ │ │ ├── uPortComponents
│ │ │ ├── index.css
│ │ │ └── SignUp
│ │ │ │ └── index.js
│ │ │ ├── index.js
│ │ │ └── LayoutMetamask.js
│ └── MarketList
│ │ ├── components
│ │ ├── MarketsTitle
│ │ │ ├── MarketsTitle.scss
│ │ │ └── index.js
│ │ ├── Filter
│ │ │ ├── Filter.scss
│ │ │ └── index.js
│ │ ├── MarketOverview
│ │ │ ├── MarketOverview.scss
│ │ │ └── index.js
│ │ ├── Markets
│ │ │ ├── Markets.scss
│ │ │ └── Market
│ │ │ │ ├── MarketResolution.js
│ │ │ │ └── MarketTrading.js
│ │ ├── NoMarkets
│ │ │ └── index.js
│ │ └── MarketStats
│ │ │ └── MarketStats.scss
│ │ ├── containers
│ │ ├── MarketList
│ │ │ ├── actions.js
│ │ │ ├── index.js
│ │ │ └── selector.js
│ │ └── index.js
│ │ └── store
│ │ └── test
│ │ ├── marketlist.spec.js
│ │ └── market.selector.js
├── store
│ ├── models
│ │ ├── index.js
│ │ ├── share
│ │ │ └── index.js
│ │ ├── market
│ │ │ ├── index.js
│ │ │ ├── scalar.js
│ │ │ └── categorical.js
│ │ └── trade
│ │ │ └── index.js
│ ├── selectors
│ │ ├── interface.js
│ │ ├── notifications.js
│ │ ├── modal.js
│ │ ├── market
│ │ │ └── index.js
│ │ └── account
│ │ │ └── trades.js
│ ├── actions
│ │ ├── market
│ │ │ ├── addMarkets.js
│ │ │ ├── updateMarket.js
│ │ │ ├── index.js
│ │ │ └── constants
│ │ │ │ └── index.js
│ │ ├── interface.js
│ │ ├── shares
│ │ │ ├── updateShare.js
│ │ │ ├── addShare.js
│ │ │ ├── redeemShare.js
│ │ │ └── index.js
│ │ ├── modal.js
│ │ └── trades
│ │ │ ├── addTrade.js
│ │ │ └── index.js
│ ├── middlewares
│ │ ├── Storage
│ │ │ ├── actions.js
│ │ │ ├── constants.js
│ │ │ ├── index.js
│ │ │ └── Load.js
│ │ ├── CrashReporter.js
│ │ └── Notifications.js
│ ├── reducers
│ │ ├── notifications
│ │ │ ├── models
│ │ │ │ └── notification.js
│ │ │ └── index.js
│ │ ├── accountTrades.js
│ │ ├── interface.js
│ │ ├── market.js
│ │ ├── accountShares.js
│ │ ├── modal.js
│ │ └── index.js
│ └── utils
│ │ └── marketStatus.js
├── verification
│ └── onfido
│ │ ├── index.js
│ │ ├── containers
│ │ └── store
│ │ │ └── selectors.js
│ │ └── api
│ │ └── utils
│ │ └── checks.js
├── components
│ ├── Form
│ │ ├── MandatoryHint.scss
│ │ ├── InputError.scss
│ │ ├── RadioButtonGroup.scss
│ │ ├── TextInputAdornment.scss
│ │ ├── index.js
│ │ ├── Select.scss
│ │ ├── InputError.js
│ │ ├── MandatoryHint.js
│ │ └── TextInputAdornment.js
│ ├── layout
│ │ ├── PageFrame
│ │ │ ├── index.scss
│ │ │ └── index.js
│ │ ├── Title
│ │ │ ├── index.scss
│ │ │ └── index.js
│ │ ├── Subtitle
│ │ │ ├── index.scss
│ │ │ └── index.js
│ │ ├── Img
│ │ │ ├── index.css
│ │ │ └── index.js
│ │ ├── Block
│ │ │ ├── index.scss
│ │ │ └── index.js
│ │ ├── Hairline
│ │ │ ├── index.stories.js
│ │ │ └── index.js
│ │ ├── Bold
│ │ │ └── index.js
│ │ ├── Span
│ │ │ └── index.js
│ │ └── Paragraph
│ │ │ ├── index.scss
│ │ │ └── index.js
│ ├── WalletAddress
│ │ └── style.scss
│ ├── Header
│ │ ├── Layouts
│ │ │ ├── DesktopHeader
│ │ │ │ └── components
│ │ │ │ │ └── WrongNetwork
│ │ │ │ │ ├── WrongNetwork.scss
│ │ │ │ │ └── index.js
│ │ │ ├── MobileHeader
│ │ │ │ ├── assets
│ │ │ │ │ ├── icon_copy.png
│ │ │ │ │ └── icon_copy.svg
│ │ │ │ ├── BurgerIcon
│ │ │ │ │ ├── BurgerIcon.scss
│ │ │ │ │ ├── assets
│ │ │ │ │ │ └── menu_icon.svg
│ │ │ │ │ └── index.js
│ │ │ │ └── AccountOverview
│ │ │ │ │ └── AccountOverview.scss
│ │ │ └── index.js
│ │ ├── Balance
│ │ │ └── Balance.scss
│ │ ├── MenuAccountDropdown
│ │ │ ├── Separator.js
│ │ │ ├── MenuActions.js
│ │ │ ├── List.js
│ │ │ ├── index.js
│ │ │ ├── tooltip.scss
│ │ │ └── LogOut.js
│ │ ├── BadgeIcon.js
│ │ └── ProviderIcon.js
│ ├── Outcome
│ │ ├── OutcomeColorBox
│ │ │ ├── OutcomeColorBox.scss
│ │ │ └── index.js
│ │ ├── WinningOutcome
│ │ │ └── WinningOutcome.scss
│ │ └── OutcomeScalar
│ │ │ └── TrendingOutcomeScalar
│ │ │ └── index.js
│ ├── Icon
│ │ └── Icon.scss
│ ├── Spinner
│ │ ├── Indefinite.scss
│ │ └── Transaction.js
│ ├── Responsive
│ │ └── index.js
│ ├── Footer
│ │ ├── index.stories.js
│ │ └── Footer.scss
│ ├── ModalContent
│ │ ├── TransactionsExplanation
│ │ │ ├── TransactionExplanation.scss
│ │ │ └── index.js
│ │ ├── Verification
│ │ │ ├── Verification.scss
│ │ │ └── index.js
│ │ ├── OutcomePriceChanged.js
│ │ ├── InitialisationError
│ │ │ └── InitialisationError.scss
│ │ └── InstallProvider
│ │ │ └── InstallProvider.scss
│ ├── Root
│ │ └── index.js
│ ├── Notifications
│ │ └── Notifications.scss
│ └── TransactionFloater
│ │ └── Notifications
│ │ └── Notifications.scss
├── integrations
│ ├── store
│ │ └── models
│ │ │ ├── index.js
│ │ │ └── provider.js
│ ├── trust
│ │ └── utils.js
│ ├── status
│ │ ├── utils.js
│ │ └── assets
│ │ │ └── status-logo.svg
│ ├── metamask
│ │ ├── utils.js
│ │ └── components
│ │ │ └── UnlockMetamask
│ │ │ └── UnlockMetamask.scss
│ ├── utils.js
│ ├── index.js
│ └── uport
│ │ ├── uportQr.js
│ │ └── uportNotifications.js
├── assets
│ ├── images
│ │ ├── image1.png
│ │ └── image2.png
│ ├── img
│ │ ├── icons
│ │ │ ├── icon_oly.png
│ │ │ ├── icon_wallet.svg
│ │ │ ├── icon_logout.svg
│ │ │ ├── icon_checkmark.svg
│ │ │ ├── icon_link.svg
│ │ │ ├── icon_incomeForecast.svg
│ │ │ ├── icon_share.svg
│ │ │ ├── icon_next.svg
│ │ │ ├── icon_cross.svg
│ │ │ ├── icon_winningOutcome.svg
│ │ │ ├── icon_currency.svg
│ │ │ ├── icon_enddate.svg
│ │ │ └── gno_token.svg
│ │ ├── gnosis_logo_favicon.png
│ │ ├── gnosis_apollo_favicon.png
│ │ ├── olympia_logo_favicon.png
│ │ ├── placeholder.svg
│ │ └── badges
│ │ │ └── crystal-gazer.svg
│ ├── fonts
│ │ ├── Montserrat-Light.ttf
│ │ ├── Montserrat-Medium.ttf
│ │ └── Montserrat-Regular.ttf
│ ├── content
│ │ ├── footer.md
│ │ └── footerOlympia.md
│ ├── verification
│ │ └── onfido
│ │ │ ├── id-type-driverlicense.svg
│ │ │ └── id-type-id.svg
│ └── badges
│ │ └── crystal-gazer.svg
├── embedded
│ ├── routes
│ │ ├── EmbeddedView
│ │ │ ├── index.js
│ │ │ ├── components
│ │ │ │ └── NoMatch
│ │ │ │ │ └── index.js
│ │ │ └── api
│ │ │ │ └── index.js
│ │ └── index.js
│ ├── html
│ │ └── index.html
│ ├── components
│ │ └── Root
│ │ │ └── index.js
│ ├── index.js
│ └── style
│ │ └── embedded.css
├── containers
│ ├── Modals
│ │ ├── ModalOutcomePriceChanged.js
│ │ ├── ModalRegisterWallet
│ │ │ ├── selectors.js
│ │ │ ├── api.js
│ │ │ └── actions.js
│ │ ├── ModalAcceptTOS
│ │ │ └── index.js
│ │ ├── ModalTransactionExplanation.js
│ │ ├── ModalInstallProvider.js
│ │ ├── ModalInitialisationError.js
│ │ ├── ModalClaimReward
│ │ │ ├── api.js
│ │ │ └── action.js
│ │ ├── ModalVerification.js
│ │ ├── ModalRegisterWalletUport.js
│ │ ├── ModalSelectProvider.js
│ │ └── index.js
│ ├── CookieBannerContainer
│ │ └── index.js
│ ├── EnableIntercom
│ │ ├── index.js
│ │ └── EnableIntercom.scss
│ ├── App
│ │ ├── transitions.scss
│ │ └── app.scss
│ ├── InteractionButton
│ │ └── interactionButton.scss
│ ├── LegalCompliance
│ │ ├── index.js
│ │ ├── components
│ │ │ ├── Form.scss
│ │ │ ├── DocumentExplanation.js
│ │ │ └── DocumentField.js
│ │ └── store
│ │ │ └── selectors.js
│ ├── HeaderContainer
│ │ ├── index.js
│ │ └── store
│ │ │ └── actions.js
│ ├── BackdropProvider
│ │ └── backdrop.scss
│ └── TransactionFloaterContainer
│ │ └── index.js
├── api
│ ├── index.js
│ ├── rewards.js
│ ├── utils
│ │ └── fetch.js
│ ├── token.js
│ └── market.js
├── html
│ └── index.html
├── utils
│ ├── transactionExplanations.js
│ ├── analytics
│ │ ├── intercom
│ │ │ └── index.js
│ │ ├── google
│ │ │ └── index.js
│ │ └── index.js
│ └── marginPrice.js
├── scss
│ └── main.scss
└── setup.js
├── jsconfig.json
├── postcss.config.js
├── docker-compose.yml
├── scripts
├── configuration.jest.js
├── env_build.sh
└── configuration.browser.js
├── Dockerfile
├── .github
└── ISSUE_TEMPLATE
│ ├── tech-task.md
│ ├── feature_request.md
│ └── bug_report.md
├── .bootstraprc
├── .travis
└── scripts
│ └── prepare_production_deployment.sh
├── .gitignore
├── PULL_REQUEST_TEMPLATE.md
├── config
└── mainnet
│ └── development.json
├── LICENSE
└── .eslintrc
/.nvmrc:
--------------------------------------------------------------------------------
1 | 10.5.0
2 |
--------------------------------------------------------------------------------
/src/routes/Scoreboard/api/index.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/routes/Dashboard/api/fetchTrades.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/store/models/index.js:
--------------------------------------------------------------------------------
1 | export * from './market'
2 |
--------------------------------------------------------------------------------
/src/verification/onfido/index.js:
--------------------------------------------------------------------------------
1 | export default from './containers'
2 |
--------------------------------------------------------------------------------
/src/components/Form/MandatoryHint.scss:
--------------------------------------------------------------------------------
1 | .mandatoryHint {
2 | color: red;
3 | }
--------------------------------------------------------------------------------
/src/routes/Dashboard/api/fetchShares.js:
--------------------------------------------------------------------------------
1 | export default async () => {
2 |
3 | }
4 |
--------------------------------------------------------------------------------
/src/components/layout/PageFrame/index.scss:
--------------------------------------------------------------------------------
1 | .pageFrame {
2 | margin-top: 30px;
3 | }
4 |
--------------------------------------------------------------------------------
/src/routes/Scoreboard/store/reducers/index.js:
--------------------------------------------------------------------------------
1 | export { default as users } from './users'
2 |
--------------------------------------------------------------------------------
/src/integrations/store/models/index.js:
--------------------------------------------------------------------------------
1 | export { default as ProviderRecord } from './provider'
2 |
--------------------------------------------------------------------------------
/src/routes/Dashboard/components/Dashboard/Dashboard.scss:
--------------------------------------------------------------------------------
1 | .dashboard {
2 | margin-top: 30px;
3 | }
--------------------------------------------------------------------------------
/src/routes/Scoreboard/store/models/index.js:
--------------------------------------------------------------------------------
1 | export { default as UserRecord } from './user'
2 |
--------------------------------------------------------------------------------
/src/routes/MarketDetails/components/ExpandableViews/MarketBuySharesForm/OutcomesSection/OutcomesSection.scss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/routes/Transactions/store/reducers/index.js:
--------------------------------------------------------------------------------
1 | export { default as transactions } from './transactions'
2 |
--------------------------------------------------------------------------------
/src/store/selectors/interface.js:
--------------------------------------------------------------------------------
1 | export const getUiState = (state, key) => state.interfaceState.get(key)
2 |
--------------------------------------------------------------------------------
/src/assets/images/image1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/assets/images/image1.png
--------------------------------------------------------------------------------
/src/assets/images/image2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/assets/images/image2.png
--------------------------------------------------------------------------------
/src/assets/img/icons/icon_oly.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/assets/img/icons/icon_oly.png
--------------------------------------------------------------------------------
/src/routes/reducers.js:
--------------------------------------------------------------------------------
1 | export * from './Transactions/store/reducers'
2 | export * from './Scoreboard/store/reducers'
3 |
--------------------------------------------------------------------------------
/src/routes/Scoreboard/store/index.js:
--------------------------------------------------------------------------------
1 | export * from './actions'
2 | export * from './models'
3 | export * from './selectors'
4 |
--------------------------------------------------------------------------------
/src/assets/fonts/Montserrat-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/assets/fonts/Montserrat-Light.ttf
--------------------------------------------------------------------------------
/src/assets/fonts/Montserrat-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/assets/fonts/Montserrat-Medium.ttf
--------------------------------------------------------------------------------
/src/assets/img/gnosis_logo_favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/assets/img/gnosis_logo_favicon.png
--------------------------------------------------------------------------------
/src/routes/Dashboard/assets/group.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/routes/Dashboard/assets/group.png
--------------------------------------------------------------------------------
/src/routes/GameGuide/assets/claim.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/routes/GameGuide/assets/claim.png
--------------------------------------------------------------------------------
/src/routes/GameGuide/assets/login1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/routes/GameGuide/assets/login1.png
--------------------------------------------------------------------------------
/src/routes/GameGuide/assets/login2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/routes/GameGuide/assets/login2.png
--------------------------------------------------------------------------------
/src/routes/GameGuide/assets/login3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/routes/GameGuide/assets/login3.png
--------------------------------------------------------------------------------
/src/routes/GameGuide/assets/login4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/routes/GameGuide/assets/login4.png
--------------------------------------------------------------------------------
/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "experimentalDecorators": true
4 | },
5 | "exclude": ["node_modules"]
6 | }
7 |
--------------------------------------------------------------------------------
/src/assets/fonts/Montserrat-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/assets/fonts/Montserrat-Regular.ttf
--------------------------------------------------------------------------------
/src/assets/img/gnosis_apollo_favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/assets/img/gnosis_apollo_favicon.png
--------------------------------------------------------------------------------
/src/assets/img/olympia_logo_favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/assets/img/olympia_logo_favicon.png
--------------------------------------------------------------------------------
/src/routes/GameGuide/assets/profits1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/routes/GameGuide/assets/profits1.png
--------------------------------------------------------------------------------
/src/routes/GameGuide/assets/profits2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/routes/GameGuide/assets/profits2.png
--------------------------------------------------------------------------------
/src/routes/GameGuide/assets/profits3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/routes/GameGuide/assets/profits3.png
--------------------------------------------------------------------------------
/src/embedded/routes/EmbeddedView/index.js:
--------------------------------------------------------------------------------
1 | import EmbeddedViewContainer from './containers'
2 |
3 | export default EmbeddedViewContainer
4 |
--------------------------------------------------------------------------------
/src/routes/GameGuide/assets/prediction1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/routes/GameGuide/assets/prediction1.png
--------------------------------------------------------------------------------
/src/routes/GameGuide/assets/prediction2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/routes/GameGuide/assets/prediction2.png
--------------------------------------------------------------------------------
/src/routes/GameGuide/assets/prediction3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/routes/GameGuide/assets/prediction3.png
--------------------------------------------------------------------------------
/src/routes/GameGuide/assets/prediction4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/routes/GameGuide/assets/prediction4.png
--------------------------------------------------------------------------------
/src/routes/GameGuide/assets/prediction5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/routes/GameGuide/assets/prediction5.png
--------------------------------------------------------------------------------
/src/store/actions/market/addMarkets.js:
--------------------------------------------------------------------------------
1 | import { createAction } from 'redux-actions'
2 |
3 | export default createAction('ADD_MARKET_LIST')
4 |
--------------------------------------------------------------------------------
/src/routes/GameGuide/assets/claimRewards.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/routes/GameGuide/assets/claimRewards.png
--------------------------------------------------------------------------------
/src/routes/GameGuide/assets/connectWallet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/routes/GameGuide/assets/connectWallet.png
--------------------------------------------------------------------------------
/src/routes/GameGuide/assets/registerWallet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/routes/GameGuide/assets/registerWallet.png
--------------------------------------------------------------------------------
/src/routes/GameGuide/assets/switchNetwork.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/routes/GameGuide/assets/switchNetwork.png
--------------------------------------------------------------------------------
/src/routes/GameGuide/assets/switchNetwork2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/routes/GameGuide/assets/switchNetwork2.png
--------------------------------------------------------------------------------
/src/components/WalletAddress/style.scss:
--------------------------------------------------------------------------------
1 | .walletAddress {
2 | &:hover {
3 | text-decoration: underline;
4 | cursor: pointer;
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/src/integrations/trust/utils.js:
--------------------------------------------------------------------------------
1 | export const hasTrust = () => window && typeof window.web3 !== 'undefined' && !!window.web3.currentProvider.isTrust
2 |
--------------------------------------------------------------------------------
/src/routes/GameGuide/assets/marketoverview1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/routes/GameGuide/assets/marketoverview1.png
--------------------------------------------------------------------------------
/src/store/actions/interface.js:
--------------------------------------------------------------------------------
1 | import { createAction } from 'redux-actions'
2 |
3 | export const changeUiState = createAction('CHANGE_UI_STATE')
4 |
--------------------------------------------------------------------------------
/src/integrations/status/utils.js:
--------------------------------------------------------------------------------
1 | export const hasStatus = () => window && typeof window.web3 !== 'undefined' && !!window.web3.currentProvider.isStatus
2 |
--------------------------------------------------------------------------------
/src/routes/GameGuide/assets/claimSwitchNetwork.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/routes/GameGuide/assets/claimSwitchNetwork.png
--------------------------------------------------------------------------------
/src/routes/GameGuide/assets/dashboardoverview1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/routes/GameGuide/assets/dashboardoverview1.png
--------------------------------------------------------------------------------
/src/store/middlewares/Storage/actions.js:
--------------------------------------------------------------------------------
1 | import { createAction } from 'redux-actions'
2 |
3 | export const loadStorage = createAction('LOAD_STORAGE')
4 |
--------------------------------------------------------------------------------
/src/components/Header/Layouts/DesktopHeader/components/WrongNetwork/WrongNetwork.scss:
--------------------------------------------------------------------------------
1 | .wrongNetwork {
2 | background-size: cover;
3 | margin-right: 10px;
4 | }
5 |
--------------------------------------------------------------------------------
/src/containers/Modals/ModalOutcomePriceChanged.js:
--------------------------------------------------------------------------------
1 | import OutcomePriceChanged from 'components/ModalContent/OutcomePriceChanged'
2 |
3 | export default OutcomePriceChanged
4 |
--------------------------------------------------------------------------------
/src/components/Header/Layouts/MobileHeader/assets/icon_copy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gnosis/pm-trading-ui/HEAD/src/components/Header/Layouts/MobileHeader/assets/icon_copy.png
--------------------------------------------------------------------------------
/src/routes/MarketList/components/MarketsTitle/MarketsTitle.scss:
--------------------------------------------------------------------------------
1 | @import '~style/vars.scss';
2 |
3 | .marketListTitle {
4 | h1 {
5 | margin: $page-heading-margins;
6 | }
7 | }
--------------------------------------------------------------------------------
/src/routes/Transactions/components/Transactions/Transaction/DetailLabel/DetailLabel.scss:
--------------------------------------------------------------------------------
1 | @import '~style/vars.scss';
2 |
3 | .detailLabel {
4 | color: $font-color-dark;
5 | }
6 |
--------------------------------------------------------------------------------
/src/routes/MarketDetails/api/index.js:
--------------------------------------------------------------------------------
1 | export { default as buyShares } from './buyShares'
2 | export { default as sellShares } from './sellShares'
3 | export * from './calculateGasCost'
4 |
--------------------------------------------------------------------------------
/src/routes/MarketList/components/Filter/Filter.scss:
--------------------------------------------------------------------------------
1 | .filterInput {
2 | input {
3 | font-size: 12px;
4 | }
5 |
6 | label {
7 | margin: 12px 0;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/store/actions/shares/updateShare.js:
--------------------------------------------------------------------------------
1 | import { createAction } from 'redux-actions'
2 |
3 | const UPDATE_SHARE = 'UPDATE_SHARE'
4 |
5 | export default createAction(UPDATE_SHARE)
6 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | sourceMap: true,
3 | plugins: [
4 | require('autoprefixer')({
5 | browsers: ['> 1%', 'last 2 versions'],
6 | }),
7 | ],
8 | }
9 |
--------------------------------------------------------------------------------
/src/api/index.js:
--------------------------------------------------------------------------------
1 | export * from './gnosis'
2 | export * from './account'
3 | export * from './market'
4 | export * from './gasPrice'
5 | export * from './token'
6 | export * from './rewards'
7 |
--------------------------------------------------------------------------------
/src/routes/MarketDetails/store/selectors/isGasPriceFetched.js:
--------------------------------------------------------------------------------
1 | const isGasPriceFetched = state => state.blockchain.get('gasPrice') !== undefined
2 |
3 | export default isGasPriceFetched
4 |
--------------------------------------------------------------------------------
/src/routes/Scoreboard/store/actions/addUsers.js:
--------------------------------------------------------------------------------
1 | import { createAction } from 'redux-actions'
2 |
3 | export const ADD_USERS = 'ADD_USERS'
4 |
5 | export default createAction(ADD_USERS)
6 |
--------------------------------------------------------------------------------
/src/routes/Dashboard/components/Dashboard/Markets/Markets.scss:
--------------------------------------------------------------------------------
1 | @import "~style/vars.scss";
2 |
3 | .dashboardOverview {
4 | background-color: $bg-color-muted;
5 | padding: 40px 0 20px;
6 | }
--------------------------------------------------------------------------------
/src/routes/Dashboard/containers/Dashboard/utils/index.js:
--------------------------------------------------------------------------------
1 | export { default as calcShareWinnings } from './calcShareWinnings'
2 | export { default as calculateProfit } from './calculateProfit'
3 |
--------------------------------------------------------------------------------
/src/store/actions/market/updateMarket.js:
--------------------------------------------------------------------------------
1 | import { createAction } from 'redux-actions'
2 |
3 | export const UPDATE_MARKET = 'UPDATE_MARKET'
4 |
5 | export default createAction(UPDATE_MARKET)
6 |
--------------------------------------------------------------------------------
/src/store/actions/modal.js:
--------------------------------------------------------------------------------
1 | import { createAction } from 'redux-actions'
2 |
3 | export const openModal = createAction('OPEN_MODAL')
4 | export const closeModal = createAction('CLOSE_MODAL')
5 |
--------------------------------------------------------------------------------
/src/routes/GameGuide/containers/GameGuide.js:
--------------------------------------------------------------------------------
1 | import Loadable from 'react-loadable'
2 |
3 | export default Loadable({
4 | loader: () => import('../components'),
5 | loading: () => null,
6 | })
7 |
--------------------------------------------------------------------------------
/src/store/actions/shares/addShare.js:
--------------------------------------------------------------------------------
1 | import { createAction } from 'redux-actions'
2 |
3 | export const ADD_ACCOUNT_SHARE = 'ADD_ACCOUNT_SHARE'
4 |
5 | export default createAction(ADD_ACCOUNT_SHARE)
6 |
--------------------------------------------------------------------------------
/src/store/actions/trades/addTrade.js:
--------------------------------------------------------------------------------
1 | import { createAction } from 'redux-actions'
2 |
3 | export const ADD_ACCOUNT_TRADE = 'ADD_ACCOUNT_TRADE'
4 |
5 | export default createAction(ADD_ACCOUNT_TRADE)
6 |
--------------------------------------------------------------------------------
/src/routes/MarketList/containers/MarketList/actions.js:
--------------------------------------------------------------------------------
1 | import { fetchMarkets } from 'store/actions/market'
2 |
3 | export default dispatch => ({
4 | fetchMarkets: () => dispatch(fetchMarkets()),
5 | })
6 |
--------------------------------------------------------------------------------
/src/components/Form/InputError.scss:
--------------------------------------------------------------------------------
1 | @import "~style/vars.scss";
2 |
3 | .inputError {
4 | position: absolute;
5 | font-weight: 800;
6 | color: $active-highlight-error;
7 | padding: $paddings-inputs;
8 | }
--------------------------------------------------------------------------------
/src/routes/MarketDetails/store/selectors/isGasCostFetched.js:
--------------------------------------------------------------------------------
1 | const isGasCostFetched = (state, property) => state.blockchain.getIn(['gasCosts', property]) !== undefined
2 |
3 | export default isGasCostFetched
4 |
--------------------------------------------------------------------------------
/src/routes/Scoreboard/components/Table/ScoreTable/index.css:
--------------------------------------------------------------------------------
1 | .greenRank {
2 | color: green;
3 | }
4 |
5 | .redRank {
6 | color: red;
7 | }
8 |
9 | .neutralRank {
10 | color: #626262;
11 | }
--------------------------------------------------------------------------------
/src/components/layout/Title/index.scss:
--------------------------------------------------------------------------------
1 | .ol-title {
2 | font-family: Montserrat;
3 | font-size: 42px;
4 | font-weight: 300;
5 | text-align: left;
6 | color: #333333;
7 | margin-bottom: 32px;
8 | }
--------------------------------------------------------------------------------
/src/routes/MarketList/components/MarketOverview/MarketOverview.scss:
--------------------------------------------------------------------------------
1 | @import '~style/vars.scss';
2 |
3 | .marketOverview {
4 | padding: 40px 0;
5 | background-color: $bg-color-muted;
6 | min-height: 420px;
7 | }
--------------------------------------------------------------------------------
/src/store/actions/shares/redeemShare.js:
--------------------------------------------------------------------------------
1 | import { createAction } from 'redux-actions'
2 |
3 | export const REDEEM_ACCOUNT_SHARE = 'REDEEM_ACCOUNT_SHARE'
4 |
5 | export default createAction(REDEEM_ACCOUNT_SHARE)
6 |
--------------------------------------------------------------------------------
/src/store/actions/trades/index.js:
--------------------------------------------------------------------------------
1 | export { default as requestTrades } from './requestTrades'
2 | export { default as addTrade } from './addTrade'
3 | export * from './addTrade'
4 | export * from './requestTrades'
5 |
--------------------------------------------------------------------------------
/src/embedded/routes/EmbeddedView/components/NoMatch/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | const NoMatch = () => (
4 | Sorry, the specified Market can not be found
5 | )
6 |
7 | export default NoMatch
8 |
--------------------------------------------------------------------------------
/src/routes/Dashboard/components/Dashboard/UserSection/Category.scss:
--------------------------------------------------------------------------------
1 | @import '~style/vars.scss';
2 |
3 | .category {
4 | min-height: 200px;
5 |
6 | @media (max-width: $screen-sm) {
7 | min-height: auto;
8 | }
9 | }
--------------------------------------------------------------------------------
/src/components/Header/Balance/Balance.scss:
--------------------------------------------------------------------------------
1 | .weth-explanation {
2 | max-width: 250px;
3 | text-align: center;
4 | }
5 |
6 | .symbol.wrapped {
7 | text-decoration: underline;
8 | text-decoration-style: dotted;
9 | }
10 |
--------------------------------------------------------------------------------
/src/store/selectors/notifications.js:
--------------------------------------------------------------------------------
1 | import { List } from 'immutable'
2 |
3 | export const getVisibleNotifications = state =>
4 | state.notifications.get('currentVisible', List()).map(id => state.notifications.getIn(['log', id]))
5 |
--------------------------------------------------------------------------------
/src/routes/Dashboard/components/Dashboard/Markets/Market/index.js:
--------------------------------------------------------------------------------
1 | export { default as ClosingSoonMarket } from './ClosingSoonMarket'
2 | export { default as NewMarket } from './NewMarket'
3 | export { default as NoMarket } from './NoMarket'
4 |
--------------------------------------------------------------------------------
/src/routes/Dashboard/containers/index.js:
--------------------------------------------------------------------------------
1 | import Loadable from 'react-loadable'
2 |
3 | const LoadableDashboard = Loadable({
4 | loader: () => import('./Dashboard'),
5 | loading: () => null,
6 | })
7 |
8 | export default LoadableDashboard
9 |
--------------------------------------------------------------------------------
/src/store/actions/market/index.js:
--------------------------------------------------------------------------------
1 | export { default as addMarkets } from './addMarkets'
2 | export { default as fetchMarkets } from './fetchMarkets'
3 | export { default as updateMarket } from './updateMarket'
4 | export * from './fetchMarkets'
5 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | web:
4 | command: npm run start
5 | build:
6 | context: .
7 | dockerfile: Dockerfile
8 | volumes:
9 | - ./dist:/app/dist
10 | ports:
11 | - 5000:5000
--------------------------------------------------------------------------------
/src/integrations/metamask/utils.js:
--------------------------------------------------------------------------------
1 | export const hasMetamask = () => window
2 | && typeof window.web3 !== 'undefined'
3 | && (window.web3.currentProvider.constructor.name === 'MetamaskInpageProvider' || window.web3.currentProvider.isMetaMask)
4 |
--------------------------------------------------------------------------------
/src/routes/MarketList/containers/index.js:
--------------------------------------------------------------------------------
1 | import Loadable from 'react-loadable'
2 |
3 | const LoadableMarketList = Loadable({
4 | loader: () => import('./MarketList'),
5 | loading: () => null,
6 | })
7 |
8 | export default LoadableMarketList
9 |
--------------------------------------------------------------------------------
/src/routes/Scoreboard/containers/index.js:
--------------------------------------------------------------------------------
1 | import Loadable from 'react-loadable'
2 |
3 | const LoadableScoreboard = Loadable({
4 | loader: () => import('./ScoreBoard'),
5 | loading: () => null,
6 | })
7 |
8 | export default LoadableScoreboard
9 |
--------------------------------------------------------------------------------
/src/components/layout/Subtitle/index.scss:
--------------------------------------------------------------------------------
1 | .ol-subtitle {
2 | font-family: Montserrat;
3 | font-size: 20px;
4 | font-weight: bold;
5 | letter-spacing: 2px;
6 | text-align: left;
7 | color: #333333;
8 | margin-bottom: 15px;
9 | }
--------------------------------------------------------------------------------
/src/routes/MarketDetails/containers/index.js:
--------------------------------------------------------------------------------
1 | import Loadable from 'react-loadable'
2 |
3 | const LoadableScoreboard = Loadable({
4 | loader: () => import('./MarketDetailPage'),
5 | loading: () => null,
6 | })
7 |
8 | export default LoadableScoreboard
9 |
--------------------------------------------------------------------------------
/src/routes/Transactions/containers/index.js:
--------------------------------------------------------------------------------
1 | import Loadable from 'react-loadable'
2 |
3 | const LoadableTransactions = Loadable({
4 | loader: () => import('./TransactionsPage'),
5 | loading: () => null,
6 | })
7 |
8 | export default LoadableTransactions
9 |
--------------------------------------------------------------------------------
/src/routes/GameGuide/components/metamaskComponents/SignUp/SignUp.scss:
--------------------------------------------------------------------------------
1 | @import '~style/vars.scss';
2 | .link {
3 | text-decoration: underline;
4 | color: $link-color;
5 |
6 | &:visited,
7 | &:active {
8 | color: $link-color;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/containers/CookieBannerContainer/index.js:
--------------------------------------------------------------------------------
1 | import Loadable from 'react-loadable'
2 |
3 | const LoadableCookieBanner = Loadable({
4 | loader: () => import('./CookieBannerContainer'),
5 | loading: () => null,
6 | })
7 |
8 | export default LoadableCookieBanner
9 |
--------------------------------------------------------------------------------
/src/containers/EnableIntercom/index.js:
--------------------------------------------------------------------------------
1 | import Loadable from 'react-loadable'
2 |
3 | const LoadableEnableIntercom = Loadable({
4 | loader: () => import('./EnableIntercomContainer'),
5 | loading: () => null,
6 | })
7 |
8 | export default LoadableEnableIntercom
9 |
--------------------------------------------------------------------------------
/src/components/Outcome/OutcomeColorBox/OutcomeColorBox.scss:
--------------------------------------------------------------------------------
1 | .OutcomeColorBox {
2 | display: inline-block;
3 | width: 20px;
4 | height: 20px;
5 | border-radius: 4px;
6 | vertical-align: middle;
7 | margin-right: 4px;
8 |
9 | background-color: #fff;
10 | }
11 |
--------------------------------------------------------------------------------
/src/store/selectors/modal.js:
--------------------------------------------------------------------------------
1 | import { createSelector } from 'reselect'
2 |
3 | export const getModalData = state => state.modal.get('modalData', [])
4 |
5 | export const getProviderModalData = createSelector(
6 | getModalData,
7 | data => data.get('provider', {}),
8 | )
9 |
--------------------------------------------------------------------------------
/src/components/Header/Layouts/MobileHeader/BurgerIcon/BurgerIcon.scss:
--------------------------------------------------------------------------------
1 | .burgerIcon {
2 | display: flex;
3 | flex-direction: column;
4 |
5 | .icon {
6 | height: 30px;
7 | width: 30px;
8 | }
9 |
10 | .menuLabel {
11 | font-size: 10px;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/components/Icon/Icon.scss:
--------------------------------------------------------------------------------
1 | .icon {
2 | display: inline-block;
3 | position: relative;
4 |
5 | height: 16px;
6 | width: 16px;
7 |
8 | content: '\00a0';
9 | background-position: center center;
10 | background-repeat: no-repeat;
11 |
12 | font-style: normal;
13 | }
--------------------------------------------------------------------------------
/src/store/reducers/notifications/models/notification.js:
--------------------------------------------------------------------------------
1 | import { Record } from 'immutable'
2 |
3 | const NotificationRecord = Record({
4 | id: undefined,
5 | title: undefined,
6 | message: undefined,
7 | icon: undefined,
8 | })
9 |
10 | export default NotificationRecord
11 |
--------------------------------------------------------------------------------
/scripts/configuration.jest.js:
--------------------------------------------------------------------------------
1 | const configLoader = require('./configuration')
2 |
3 | const ENV = 'local'
4 |
5 | // console.info(`[JEST]: using env configuration: '${ENV}'`)
6 | const config = configLoader(ENV)
7 |
8 | window.__GNOSIS_CONFIG__ = config
9 | global.__GNOSIS_CONFIG__ = config
10 |
--------------------------------------------------------------------------------
/src/components/Header/MenuAccountDropdown/Separator.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import cn from 'classnames/bind'
3 | import style from './dropdown.scss'
4 |
5 | const cx = cn.bind(style)
6 |
7 | const Separator = () =>
8 |
9 | export default Separator
10 |
--------------------------------------------------------------------------------
/src/components/layout/Img/index.css:
--------------------------------------------------------------------------------
1 | .ol-img {
2 | max-width: 100%;
3 | box-sizing: border-box;
4 | }
5 |
6 | .bordered {
7 | border: 1px solid #ddd;
8 | }
9 |
10 | .fullwidth {
11 | padding: 0;
12 | width: 40% !important;
13 | margin: 0 60% 25px !important;
14 | }
15 |
--------------------------------------------------------------------------------
/src/containers/App/transitions.scss:
--------------------------------------------------------------------------------
1 | .enter {
2 | opacity: 0;
3 | }
4 |
5 | .enterActive {
6 | transition: opacity 0.3s ease-in;
7 | opacity: 1;
8 | }
9 |
10 | .exit {
11 | opacity: 1;
12 | }
13 |
14 | .exitActive {
15 | transition: opacity 0.3s ease-out;
16 | opacity: 0;
17 | }
18 |
--------------------------------------------------------------------------------
/src/containers/EnableIntercom/EnableIntercom.scss:
--------------------------------------------------------------------------------
1 | .container {
2 | position: fixed;
3 | bottom: 10px;
4 | right: 15px;
5 | z-index: 11;
6 |
7 | & > div {
8 | transition: transform 0.2s ease-in-out;
9 | &:hover {
10 | transform: scale(1.15);
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/scripts/env_build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | export GNOSIS_ENV=olympia/staging;
4 |
5 | if [[ ${TRAVIS_BRANCH} == "master" ]] || [[ -n ${TRAVIS_TAG} ]]; then
6 | export NODE_ENV=production;
7 | else
8 | export NODE_ENV=development;
9 | fi
10 |
11 | npm run build
12 | PROJECT=embedded npm run build
13 |
--------------------------------------------------------------------------------
/src/routes/MarketList/containers/MarketList/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import actions from './actions'
3 | import selector from './selector'
4 | import MarketList from '../../components/MarketList'
5 |
6 | export default connect(
7 | selector,
8 | actions,
9 | )(MarketList)
10 |
--------------------------------------------------------------------------------
/src/routes/Scoreboard/store/actions/index.js:
--------------------------------------------------------------------------------
1 | export { default as fetchTournamentUserData } from './fetchTournamentUserData'
2 | export { default as fetchTournamentUsers } from './fetchTournamentUsers'
3 | export * from './addUsers'
4 | export { default as addUsers } from './addUsers'
5 | export * from './rewards'
6 |
--------------------------------------------------------------------------------
/src/api/rewards.js:
--------------------------------------------------------------------------------
1 | import { getGnosisConnection } from 'api'
2 |
3 | export const claimRewards = async (contractAddress) => {
4 | const gnosis = await getGnosisConnection()
5 | const rewardContract = await gnosis.contracts.RewardClaimHandler.at(contractAddress)
6 |
7 | await rewardContract.claimReward()
8 | }
9 |
--------------------------------------------------------------------------------
/src/routes/MarketList/components/Markets/Markets.scss:
--------------------------------------------------------------------------------
1 | @import '~style/vars.scss';
2 |
3 | .markets {
4 | .title {
5 | margin: 12px 0;
6 | text-transform: uppercase;
7 | color: $font-color-light;
8 | font-weight: 400;
9 | }
10 |
11 | .container {
12 | min-height: 420px;
13 | }
14 | }
--------------------------------------------------------------------------------
/src/store/middlewares/Storage/constants.js:
--------------------------------------------------------------------------------
1 | const INIT = 'INIT'
2 |
3 | export const STORAGE_KEY = `GNOSIS_${process.env.VERSION}`
4 | export const STORAGE_SAVE_INTERVAL = 1000
5 |
6 | export const IGNORE_ACTIONS = [INIT, 'LOAD_STORAGE']
7 |
8 | export const NOOP_MIDDLEWARE = () => next => action => next(action)
9 |
--------------------------------------------------------------------------------
/src/assets/img/placeholder.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/containers/InteractionButton/interactionButton.scss:
--------------------------------------------------------------------------------
1 | .interactionButton {
2 | text-align: center;
3 |
4 | display: inline-flex;
5 | justify-content: center;
6 | align-items: center;
7 | height: 45px;
8 |
9 | &.loading {
10 | .interactionButtonInner {
11 | visibility: hidden;
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/src/components/Spinner/Indefinite.scss:
--------------------------------------------------------------------------------
1 | .indefiniteSpinner {
2 | &.centered {
3 | position: absolute;
4 | left: 50%;
5 | top: 50%;
6 | transform: translate(-50%, -50%);
7 | }
8 |
9 | path {
10 | fill: #000;
11 | }
12 |
13 | &.inverted {
14 | path {
15 | fill: #fff;
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/src/containers/Modals/ModalRegisterWallet/selectors.js:
--------------------------------------------------------------------------------
1 | import { GAS_COST } from 'utils/constants'
2 |
3 | const getRegistrationGasCost = (state) => {
4 | const gasCost = state.blockchain.getIn(['gasCosts', GAS_COST.MAINNET_ADDRESS_REGISTRATION], 0)
5 |
6 | return gasCost
7 | }
8 |
9 | export { getRegistrationGasCost }
10 |
--------------------------------------------------------------------------------
/src/routes/GameGuide/components/uPortComponents/index.css:
--------------------------------------------------------------------------------
1 | .slider {
2 | display: flex;
3 | flex-wrap: wrap;
4 | align-items: flex-start;
5 | margin: 50px auto;
6 | justify-content: center;
7 |
8 | & img {
9 | width: 33%;
10 | height: auto;
11 | margin: 0;
12 | margin: 0 25px 25px 0;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/routes/MarketDetails/store/selectors/getGasCosts.js:
--------------------------------------------------------------------------------
1 | const getGasCosts = (state) => {
2 | const gasCosts = state.blockchain.get('gasCosts')
3 |
4 | return gasCosts.map((cost) => {
5 | if (!cost) {
6 | return undefined
7 | }
8 |
9 | return cost
10 | })
11 | }
12 |
13 | export default getGasCosts
14 |
--------------------------------------------------------------------------------
/src/routes/Scoreboard/assets/ok.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/verification/onfido/containers/store/selectors.js:
--------------------------------------------------------------------------------
1 | import { getCurrentAccount, hasAcceptedTermsAndConditions, isVerified } from 'integrations/store/selectors'
2 |
3 | export default state => ({
4 | account: getCurrentAccount(state),
5 | tosAccepted: hasAcceptedTermsAndConditions(state),
6 | isVerified: isVerified(state),
7 | })
8 |
--------------------------------------------------------------------------------
/src/routes/Dashboard/components/Dashboard/UserSection/UserSection.scss:
--------------------------------------------------------------------------------
1 | @import '~style/vars.scss';
2 |
3 | .userSection {
4 | padding: 40px 0 66px 0;
5 |
6 | background-color: $bg-color-dark;
7 | min-height: 200px;
8 | color: $font-color-bright;
9 |
10 | @media (max-width: $screen-sm) {
11 | min-height: auto;
12 | }
13 | }
--------------------------------------------------------------------------------
/src/components/Form/RadioButtonGroup.scss:
--------------------------------------------------------------------------------
1 | @import '~style/vars.scss';
2 |
3 | .formRadioButtonGroup {
4 | & > label {
5 | margin: 20px 0 6px 0;
6 | display: block;
7 | }
8 |
9 |
10 | &.error {
11 | label {
12 | color: $active-highlight-error;
13 | }
14 |
15 | color: $active-highlight-error;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/components/Header/MenuAccountDropdown/MenuActions.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | import List from './List'
4 | import Separator from './Separator'
5 | import LogOut from './LogOut'
6 |
7 | const MenuActions = () => (
8 |
9 |
10 |
11 |
12 | )
13 |
14 | export default MenuActions
15 |
--------------------------------------------------------------------------------
/src/components/layout/Block/index.scss:
--------------------------------------------------------------------------------
1 | .sm {
2 | margin-bottom: 17px;
3 | }
4 |
5 | .md {
6 | margin-bottom: 42px;
7 | }
8 |
9 | .xl {
10 | margin-bottom: 96px;
11 | }
12 |
13 | .xxl {
14 | margin-bottom: 200px;
15 | }
16 |
17 | .center {
18 | display: flex;
19 | align-items: center;
20 | justify-content: center;
21 | }
--------------------------------------------------------------------------------
/src/routes/GameGuide/components/index.js:
--------------------------------------------------------------------------------
1 | import { getProviderConfig } from 'utils/features'
2 | import { WALLET_PROVIDER } from 'integrations/constants'
3 | import LayoutMetamask from './LayoutMetamask'
4 | import LayoutUport from './LayoutUport'
5 |
6 | export default getProviderConfig().default === WALLET_PROVIDER.METAMASK ? LayoutMetamask : LayoutUport
7 |
--------------------------------------------------------------------------------
/src/embedded/html/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Gnosis Trading Interface Widget
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/store/actions/shares/index.js:
--------------------------------------------------------------------------------
1 | export { default as requestShares } from './requestShares'
2 | export { default as addShare } from './addShare'
3 | export { default as redeemShare } from './redeemShare'
4 | export { default as updateShare } from './updateShare'
5 | export * from './addShare'
6 | export * from './redeemShare'
7 | export * from './requestShares'
8 |
--------------------------------------------------------------------------------
/src/containers/Modals/ModalRegisterWallet/api.js:
--------------------------------------------------------------------------------
1 | import { getGnosisConnection } from 'api'
2 |
3 | const calcRegistrationGasCost = async (account) => {
4 | const gnosis = await getGnosisConnection()
5 | const gasCost = await gnosis.olympiaAddressRegistry.register.estimateGas(account)
6 | return gasCost
7 | }
8 |
9 | export { calcRegistrationGasCost }
10 |
--------------------------------------------------------------------------------
/src/integrations/utils.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line
2 | export const getLogo = providerName => require(`integrations/${providerName}/assets/${providerName}-logo.svg`)
3 |
4 | export const getLastUsedProvider = () => {
5 | if (window && window.localStorage) {
6 | return localStorage.getItem('LAST_USED_PROVIDER')
7 | }
8 |
9 | return undefined
10 | }
11 |
--------------------------------------------------------------------------------
/src/components/Responsive/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Responsive from 'react-responsive'
3 |
4 | const Desktop = props =>
5 | const Tablet = props =>
6 | const Mobile = props =>
7 |
8 | export { Desktop, Tablet, Mobile }
9 |
--------------------------------------------------------------------------------
/src/routes/MarketDetails/components/MarketGraph/MarketGraph.scss:
--------------------------------------------------------------------------------
1 | @import "~style/vars.scss";
2 |
3 | .marketGraph {
4 | width: 100%;
5 | min-height: 400px;
6 | padding: 60px 0;
7 | height: 60vh;
8 | background-color: $bg-color-dark;
9 | color: $font-color-light;
10 | }
11 |
12 | .marketGraphContainer {
13 | width: 100%;
14 | height: 100%;
15 | }
16 |
--------------------------------------------------------------------------------
/src/store/middlewares/CrashReporter.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Sends crash reports as state is updated and listeners are notified.
3 | */
4 | const CrashReporter = () => next => (action) => {
5 | try {
6 | return next(action)
7 | } catch (err) {
8 | console.error('Caught an exception!', err)
9 | throw err
10 | }
11 | }
12 |
13 | export default CrashReporter
14 |
--------------------------------------------------------------------------------
/src/containers/LegalCompliance/index.js:
--------------------------------------------------------------------------------
1 | import { reduxForm } from 'redux-form'
2 | import { connect } from 'react-redux'
3 | import LegalComplianceForm from './components/Form'
4 |
5 | import selectors from './store/selectors'
6 |
7 | const form = {
8 | form: 'legalCompliance',
9 | }
10 |
11 | export default reduxForm(form)(connect(selectors)(LegalComplianceForm))
12 |
--------------------------------------------------------------------------------
/src/assets/content/footer.md:
--------------------------------------------------------------------------------
1 | Trading on prediction markets carries a high degree of financial risk to your capital. Please read our full [Risk Disclaimer](/assets/content/mainnet/RiskDisclaimerPolicy.html), [Privacy Policy](/assets/PrivacyPolicy.html) and [Terms of Service](/assets/content/mainnet/TermsOfService.html) before trading. – [Imprint](/assets/content/mainnet/Imprint.html)
2 |
--------------------------------------------------------------------------------
/src/assets/img/icons/icon_wallet.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/routes/Dashboard/components/Dashboard/Markets/ConditionalList.scss:
--------------------------------------------------------------------------------
1 | @import '~style/vars.scss';
2 |
3 | .list {
4 | min-height: inherit;
5 |
6 | &.loading {
7 | display: flex;
8 | flex-direction: column;
9 | justify-content: center;
10 | align-items: center;
11 | }
12 |
13 | @media (max-width: $screen-sm) {
14 | min-height: none;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/routes/Scoreboard/store/actions/fetchTournamentUsers.js:
--------------------------------------------------------------------------------
1 | import { requestFromRestAPI } from 'api/utils/fetch'
2 | import addUsers from './addUsers'
3 |
4 | export default () => dispatch => requestFromRestAPI('scoreboard').then((response) => {
5 | if (!response) {
6 | dispatch(addUsers([]))
7 | return
8 | }
9 |
10 | dispatch(addUsers(response.results))
11 | })
12 |
--------------------------------------------------------------------------------
/src/components/Header/Layouts/MobileHeader/BurgerIcon/assets/menu_icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/routes/Dashboard/components/Dashboard/Title/DashboardTitle.scss:
--------------------------------------------------------------------------------
1 | @import '~style/vars.scss';
2 |
3 | .dashboardTitle {
4 | .title {
5 | margin-bottom: 30px;
6 | font-family: Montserrat;
7 | font-size: 42px;
8 | font-weight: 300;
9 | text-align: left;
10 | color: #333;
11 |
12 | @media (max-width: $screen-sm) {
13 | text-align: center;
14 | }
15 | }
16 | }
--------------------------------------------------------------------------------
/src/containers/Modals/ModalAcceptTOS/index.js:
--------------------------------------------------------------------------------
1 | import AcceptTOS from 'components/ModalContent/AcceptTOS'
2 | import { connect } from 'react-redux'
3 | import { initProviders, setLegalDocumentsAccepted } from 'integrations/store/actions'
4 |
5 | const mapDispatchToProps = {
6 | initProviders,
7 | setLegalDocumentsAccepted,
8 | }
9 |
10 | export default connect(null, mapDispatchToProps)(AcceptTOS)
11 |
--------------------------------------------------------------------------------
/src/containers/Modals/ModalTransactionExplanation.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import TransactionsExplanation from 'components/ModalContent/TransactionsExplanation'
3 | import { getModalData } from 'store/selectors/modal'
4 |
5 | const mapStateToProps = state => ({
6 | transactions: getModalData(state),
7 | })
8 |
9 | export default connect(mapStateToProps)(TransactionsExplanation)
10 |
--------------------------------------------------------------------------------
/src/html/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Gnosis Trading Interface
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/routes/Scoreboard/store/models/user.js:
--------------------------------------------------------------------------------
1 | import { Record } from 'immutable'
2 |
3 | const UserRecord = Record(
4 | {
5 | currentRank: undefined,
6 | diffRank: undefined,
7 | pastRank: undefined,
8 | account: undefined,
9 | balance: undefined,
10 | score: 0,
11 | predictedProfit: 0,
12 | predictions: 0,
13 | },
14 | 'User',
15 | )
16 |
17 | export default UserRecord
18 |
--------------------------------------------------------------------------------
/src/components/Footer/index.stories.js:
--------------------------------------------------------------------------------
1 | import { storiesOf } from '@storybook/react'
2 | import * as React from 'react'
3 | import { host } from 'storybook-host'
4 | import Component from './index'
5 |
6 | storiesOf('Components', module)
7 | .addDecorator(host({
8 | title: 'Footer',
9 | align: 'center',
10 | height: 250,
11 | width: '100%',
12 | }))
13 | .add('Footer', () => )
14 |
--------------------------------------------------------------------------------
/src/components/Form/TextInputAdornment.scss:
--------------------------------------------------------------------------------
1 | @import "~style/vars.scss";
2 |
3 | .adornment {
4 | display: block;
5 |
6 | font-size: $font-size-inputs;
7 | letter-spacing: $letter-spacing-inputs;
8 | font-weight: $font-weight-inputs;
9 | padding: $paddings-inputs;
10 |
11 | margin: auto 0;
12 | }
13 |
14 | .end {
15 | padding-right: 5px;
16 | }
17 |
18 | .start {
19 | padding-left: 5px;
20 | }
--------------------------------------------------------------------------------
/src/embedded/routes/EmbeddedView/api/index.js:
--------------------------------------------------------------------------------
1 | import { requestFromRestAPI } from 'api/utils/fetch'
2 | import { extractMarkets } from 'store/actions/market/fetchMarkets'
3 |
4 | export const getMarketById = async (marketAddress) => {
5 | const response = await requestFromRestAPI(`markets/${marketAddress}`)
6 | const processedMarkets = extractMarkets([response])
7 |
8 | return processedMarkets[0]
9 | }
10 |
--------------------------------------------------------------------------------
/src/routes/Dashboard/containers/Dashboard/utils/calculateProfit.js:
--------------------------------------------------------------------------------
1 | import Decimal from 'decimal.js'
2 | import calcShareWinnings from './calcShareWinnings'
3 |
4 | const calculateProfit = (share) => {
5 | if (share.resolved) {
6 | return calcShareWinnings(share, share.market)
7 | }
8 |
9 | return new Decimal(share.balance).mul(share.marginalPrice)
10 | }
11 |
12 | export default calculateProfit
13 |
--------------------------------------------------------------------------------
/src/routes/MarketDetails/components/MarketDetail/Details/Details.scss:
--------------------------------------------------------------------------------
1 | .marketDescription {
2 | margin-bottom: 40px;
3 | font-size: 18px;
4 | line-height: 30px;
5 | letter-spacing: 0.25px;
6 | font-weight: 300;
7 |
8 | a {
9 | color: #00a6c4;
10 |
11 | &:focus, &:visited {
12 | color: #00a6c4;
13 | }
14 | }
15 | }
16 |
17 |
18 | .outcomes {
19 | margin-bottom: 40px;
20 | }
21 |
--------------------------------------------------------------------------------
/src/routes/MarketList/components/NoMarkets/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 | import { withNamespaces } from 'react-i18next'
4 |
5 | const NoMarkets = ({ t }) => (
6 |
7 |
{t('markets.no_markets')}
8 |
9 | )
10 |
11 | NoMarkets.propTypes = {
12 | t: PropTypes.func.isRequired,
13 | }
14 |
15 | export default withNamespaces()(NoMarkets)
16 |
--------------------------------------------------------------------------------
/src/assets/img/icons/icon_logout.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/containers/Modals/ModalInstallProvider.js:
--------------------------------------------------------------------------------
1 | import InstallProvider from 'components/ModalContent/InstallProvider'
2 | import { connect } from 'react-redux'
3 | import { getProviderModalData } from 'store/selectors/modal'
4 |
5 | const mapStateToProps = state => ({
6 | providerName: getProviderModalData(state),
7 | })
8 |
9 | export default connect(
10 | mapStateToProps,
11 | null,
12 | )(InstallProvider)
13 |
--------------------------------------------------------------------------------
/src/routes/Dashboard/components/Dashboard/Markets/Market/NoMarket.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import classname from 'classnames/bind'
3 |
4 | import style from './Market.scss'
5 |
6 | const cx = classname.bind(style)
7 |
8 | const NoMarket = () => (
9 |
12 | )
13 |
14 | export default NoMarket
15 |
--------------------------------------------------------------------------------
/src/routes/MarketDetails/components/ExpandableViews/MarketMySharesForm/SharesTable/ShareRow/ShareRow.scss:
--------------------------------------------------------------------------------
1 | @import '~style/vars.scss';
2 |
3 | .ShareSellButton {
4 | color: $link-color !important;
5 | text-transform: uppercase;
6 | letter-spacing: .5px;
7 | border: none;
8 | background: transparent;
9 |
10 | &:focus {
11 | outline: none;
12 | font-weight: bold;
13 | }
14 | }
--------------------------------------------------------------------------------
/src/store/selectors/market/index.js:
--------------------------------------------------------------------------------
1 | import { createSelector } from 'reselect'
2 | import { isMarketFunded } from 'store/utils/marketStatus'
3 |
4 | export const marketsSelector = createSelector(
5 | state => state.marketList,
6 | marketList => marketList.filter(market => isMarketFunded(market.stage)),
7 | )
8 |
9 | export const getMarketById = state => marketAddress => state.marketList.get(marketAddress, {})
10 |
--------------------------------------------------------------------------------
/src/store/reducers/accountTrades.js:
--------------------------------------------------------------------------------
1 | import { Map } from 'immutable'
2 | import { handleActions } from 'redux-actions'
3 | import { ADD_ACCOUNT_TRADE } from 'store/actions/trades'
4 |
5 | export default handleActions(
6 | {
7 | [ADD_ACCOUNT_TRADE]: (state, { payload }) => state.withMutations((stateMap) => {
8 | payload.forEach(trade => stateMap.set(trade.id, trade))
9 | }),
10 | },
11 | Map(),
12 | )
13 |
--------------------------------------------------------------------------------
/src/components/layout/Hairline/index.stories.js:
--------------------------------------------------------------------------------
1 | import { storiesOf } from '@storybook/react'
2 | import * as React from 'react'
3 | import { host } from 'storybook-host'
4 | import Component from './index'
5 |
6 | storiesOf('Components', module)
7 | .addDecorator(host({
8 | title: 'Hairline',
9 | align: 'center',
10 | height: 5,
11 | width: '100%',
12 | }))
13 | .add('Hairline', () => )
14 |
--------------------------------------------------------------------------------
/src/embedded/components/Root/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { I18nextProvider } from 'react-i18next'
3 | import { hot } from 'react-hot-loader'
4 | import i18n from 'i18n'
5 |
6 | import EmbeddedRouter from '../../routes'
7 |
8 | const RootComponent = () => (
9 |
10 |
11 |
12 | )
13 |
14 | export default hot(module)(RootComponent)
15 |
--------------------------------------------------------------------------------
/src/routes/Scoreboard/store/actions/fetchTournamentUserData.js:
--------------------------------------------------------------------------------
1 | import { requestFromRestAPI } from 'api/utils/fetch'
2 | import addUsers from './addUsers'
3 |
4 | export default account => dispatch => requestFromRestAPI(`scoreboard/${account}`).then((response) => {
5 | if (!response || response.detail === 'Not found.') {
6 | dispatch(addUsers([]))
7 | return
8 | }
9 |
10 | dispatch(addUsers([response]))
11 | })
12 |
--------------------------------------------------------------------------------
/src/containers/Modals/ModalInitialisationError.js:
--------------------------------------------------------------------------------
1 | import InitialisationError from 'components/ModalContent/InitialisationError'
2 | import { connect } from 'react-redux'
3 | import { getProviderModalData } from 'store/selectors/modal'
4 |
5 | const mapStateToProps = state => ({
6 | providerName: getProviderModalData(state),
7 | })
8 |
9 | export default connect(
10 | mapStateToProps,
11 | null,
12 | )(InitialisationError)
13 |
--------------------------------------------------------------------------------
/src/routes/Transactions/store/models/transaction.js:
--------------------------------------------------------------------------------
1 | import { Record, List } from 'immutable'
2 |
3 | const TxRecord = Record(
4 | {
5 | id: undefined,
6 | label: '',
7 | events: List(),
8 | startTime: undefined,
9 | progress: undefined,
10 | endTime: undefined,
11 | completed: undefined,
12 | completionStatus: undefined,
13 | },
14 | 'Transaction',
15 | )
16 |
17 | export default TxRecord
18 |
--------------------------------------------------------------------------------
/src/containers/Modals/ModalClaimReward/api.js:
--------------------------------------------------------------------------------
1 | import { getGnosisConnection } from 'api'
2 |
3 | const calcClaimRewardGasCost = async (contractAddress) => {
4 | const gnosis = await getGnosisConnection()
5 | const rewardContract = await gnosis.contracts.RewardClaimHandler.at(contractAddress)
6 | const gasCost = await rewardContract.claimReward.estimateGas()
7 | return gasCost
8 | }
9 |
10 | export { calcClaimRewardGasCost }
11 |
--------------------------------------------------------------------------------
/src/routes/Dashboard/containers/Dashboard/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import Loadable from 'react-loadable'
3 |
4 | import actions from './actions'
5 | import selector from './selectors'
6 |
7 | const LoadableDashboard = Loadable({
8 | loader: () => import('../../components/Dashboard'),
9 | loading: () => null,
10 | })
11 |
12 | export default connect(
13 | selector,
14 | actions,
15 | )(LoadableDashboard)
16 |
--------------------------------------------------------------------------------
/src/store/reducers/interface.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from 'redux-actions'
2 | import { Map } from 'immutable'
3 |
4 | import { changeUiState } from 'store/actions/interface'
5 |
6 | const reducer = handleActions(
7 | {
8 | [changeUiState]: (state, { payload }) => state.merge(payload),
9 | },
10 | Map({
11 | showIntercomReminder: false,
12 | showCookieBanner: false,
13 | }),
14 | )
15 |
16 | export default reducer
17 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:9.11.1-alpine
2 | RUN apk update && apk --no-cache add git python alpine-sdk
3 | RUN npm install -g webpack babel-cli truffle-contract
4 | ADD package.json /tmp/package.json
5 | RUN cd /tmp && npm install && npm install truffle-contract && npm install --only=dev
6 |
7 | RUN mkdir -p /app && cp -a /tmp/node_modules /app/
8 |
9 | COPY . /app/
10 | RUN cd /app && NODE_ENV=development npm run build
11 |
12 | WORKDIR /app
13 |
--------------------------------------------------------------------------------
/src/components/layout/Bold/index.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types'
2 | import React, { PureComponent } from 'react'
3 |
4 | class Bold extends PureComponent {
5 | render() {
6 | const { children, ...props } = this.props
7 |
8 | return (
9 |
10 | { children }
11 |
12 | )
13 | }
14 | }
15 |
16 | Bold.propTypes = {
17 | children: PropTypes.node,
18 | }
19 |
20 | export default Bold
21 |
--------------------------------------------------------------------------------
/src/components/Header/MenuAccountDropdown/List.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import cn from 'classnames/bind'
3 | import PropTypes from 'prop-types'
4 | import style from './dropdown.scss'
5 |
6 | const cx = cn.bind(style)
7 |
8 | const List = ({ children }) => (
9 |
12 | )
13 |
14 | List.propTypes = {
15 | children: PropTypes.node.isRequired,
16 | }
17 |
18 | export default List
19 |
--------------------------------------------------------------------------------
/src/containers/LegalCompliance/components/Form.scss:
--------------------------------------------------------------------------------
1 | @import '~style/vars.scss';
2 |
3 | .checks {
4 | text-align: left;
5 | }
6 |
7 | .annotation {
8 | margin-top: 15px;
9 | }
10 |
11 | .heading {
12 | font-size: 21px;
13 | font-weight: 500;
14 | text-align: center;
15 | color: #333333;
16 | margin-top: 45px;
17 | }
18 |
19 |
20 | .checkBox {
21 | margin: 10px 0;
22 | input {
23 | border: 1px solid #09697b;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/containers/Modals/ModalVerification.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import Verification from 'components/ModalContent/Verification'
3 |
4 | import { closeModal } from 'store/actions/modal'
5 | import { setLegalDocumentsAccepted } from 'integrations/store/actions'
6 |
7 | const mapDispatchToProps = {
8 | setLegalDocumentsAccepted,
9 | closeModal,
10 | }
11 |
12 | export default connect(null, mapDispatchToProps)(Verification)
13 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/tech-task.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Tech Task
3 | about: Describe a task for techs to implement
4 |
5 | ---
6 |
7 | **Description**: Please set up the configuration for our next Olympia Tournament
8 |
9 | **Additional Information**:
10 | This Tournament we will have more rewards than ever, please be sure to add all following changes to Olympia.
11 | - 12 Reward Groups (1 GNO to 10 GNO)
12 | - Legal Document Updates from our G-Drive update
13 |
--------------------------------------------------------------------------------
/src/containers/Modals/ModalRegisterWalletUport.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 |
3 | import { closeModal } from 'store/actions/modal'
4 | import { updateMainnetAddress, requestMainnetAddress } from 'store/actions/account'
5 |
6 | import RegisterWalletUport from 'components/ModalContent/RegisterWalletUport'
7 |
8 | export default connect(null, {
9 | updateMainnetAddress,
10 | requestMainnetAddress,
11 | closeModal,
12 | })(RegisterWalletUport)
13 |
--------------------------------------------------------------------------------
/src/utils/transactionExplanations.js:
--------------------------------------------------------------------------------
1 | export const DEPOSIT = (amount = '', currency = 'ETH') => `Depositing ${amount} ${currency} to this market's contract`
2 |
3 | export const SELL = (outcomeTokens = '') => `Selling ${outcomeTokens} outcome tokens back to the market`
4 |
5 | export const OUTCOME_TOKENS = 'Transaction of outcome tokens'
6 |
7 | export const SETTING_ALLOWANCE = 'Setting allowance'
8 |
9 | export const REVOKE_TOKENS = 'Revoke of outcome tokens'
10 |
--------------------------------------------------------------------------------
/src/assets/content/footerOlympia.md:
--------------------------------------------------------------------------------
1 | Olympia tournament is a testnet alpha for the sole purpose of collecting user experience feedback. Due to the stake of OLY as "play money" no one will face any financial risks.
2 | Please read our full [Privacy Policy](/assets/content/PrivacyPolicy.html), [Cookie Policy](/assets/content/olympia/CookiePolicy.html) and [Terms of Service](/assets/content/olympia/TermsOfService.html) before trading. – [Imprint](/assets/content/olympia/Imprint.html)
--------------------------------------------------------------------------------
/src/routes/Scoreboard/store/reducers/users.js:
--------------------------------------------------------------------------------
1 | import { Map } from 'immutable'
2 | import { handleActions } from 'redux-actions'
3 | import { ADD_USERS } from '../actions'
4 | import { UserRecord } from '../models'
5 |
6 | export default handleActions(
7 | {
8 | [ADD_USERS]: (state, { payload }) =>
9 | state.withMutations((map) => {
10 | payload.forEach(user => map.set(user.account, new UserRecord(user)))
11 | }),
12 | },
13 | Map(),
14 | )
15 |
--------------------------------------------------------------------------------
/src/routes/Dashboard/components/Dashboard/Markets/Category.scss:
--------------------------------------------------------------------------------
1 | @import '~style/vars.scss';
2 |
3 | .marketList {
4 | min-height: 200px;
5 | margin-bottom: 30px;
6 |
7 | > .title {
8 | margin: 0 0 12px 0;
9 | font-size: 12px;
10 | text-transform: uppercase;
11 | color: $font-color-light;
12 |
13 | font-weight: 400;
14 | letter-spacing: 0.5px;
15 | }
16 |
17 | @media (max-width: $screen-sm) {
18 | min-height: auto;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/routes/MarketList/components/Filter/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 | import Form from './Form'
4 |
5 | const MarketsFilter = ({ userAccount }) => (
6 |
7 |
8 |
9 | )
10 |
11 | MarketsFilter.propTypes = {
12 | userAccount: PropTypes.string,
13 | }
14 |
15 | MarketsFilter.defaultProps = {
16 | userAccount: undefined,
17 | }
18 |
19 | export default MarketsFilter
20 |
--------------------------------------------------------------------------------
/src/routes/Dashboard/assets/arrows.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/src/routes/Scoreboard/components/Table/Table.scss:
--------------------------------------------------------------------------------
1 | .ol-account {
2 | display: flex;
3 | flex-direction: row;
4 | align-items: center;
5 | margin-top: 10px;
6 |
7 | .dot {
8 | width: 25px;
9 | height: 25px;
10 | border-radius: 12px;
11 | background-color: #ceedf3;
12 | margin-right: 7px;
13 | }
14 |
15 | .your {
16 | font-size: 10px;
17 | line-height: 1.2;
18 | letter-spacing: 2px;
19 | text-align: left;
20 | margin: 0;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/embedded/index.js:
--------------------------------------------------------------------------------
1 | import 'babel-polyfill'
2 | import 'whatwg-fetch'
3 |
4 | import React from 'react'
5 | import { render } from 'react-dom'
6 |
7 | import 'normalize.css?raw'
8 | import './style/embedded.css?raw'
9 |
10 | import { setMomentRelativeTime, setMomentDurationFormat } from '../setup'
11 |
12 | import RootComponent from './components/Root'
13 |
14 | setMomentRelativeTime()
15 | setMomentDurationFormat()
16 |
17 | render(, document.getElementById('root'))
18 |
--------------------------------------------------------------------------------
/src/integrations/store/models/provider.js:
--------------------------------------------------------------------------------
1 | import { Record } from 'immutable'
2 | import { WALLET_STATUS } from 'integrations/constants'
3 |
4 | const ProviderRecord = Record(
5 | {
6 | name: undefined,
7 | network: undefined,
8 | balance: undefined,
9 | account: undefined,
10 | networkId: 0,
11 | mainnetAddress: undefined,
12 | verificationHash: undefined,
13 | status: WALLET_STATUS.REGISTERED,
14 | },
15 | 'Provider',
16 | )
17 |
18 | export default ProviderRecord
19 |
--------------------------------------------------------------------------------
/src/routes/MarketDetails/store/selectors/index.js:
--------------------------------------------------------------------------------
1 | export { default as getMarketGraph } from './getMarketGraph'
2 | export { default as getMarketTradesForAccount } from './getMarketTradesForAccount'
3 | export { default as getMarketShares } from './getMarketShares'
4 | export { default as getGasCosts } from './getGasCosts'
5 | export { default as getGasPrice } from './getGasPrice'
6 | export { default as isGasCostFetched } from './isGasCostFetched'
7 | export { default as isGasPriceFetched } from './isGasPriceFetched'
8 |
--------------------------------------------------------------------------------
/src/verification/onfido/api/utils/checks.js:
--------------------------------------------------------------------------------
1 | export const handleResponse = async (response) => {
2 | if (response.ok) {
3 | return response.json()
4 | }
5 |
6 | let responseBody
7 | try {
8 | responseBody = await response.json()
9 | } catch (err) {
10 | // json parse error, probably not JSON content returned
11 | }
12 |
13 | if (responseBody && responseBody.Message) {
14 | throw new Error(responseBody.Message)
15 | }
16 |
17 | throw new Error(response.statusText)
18 | }
19 |
--------------------------------------------------------------------------------
/src/components/layout/Span/index.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types'
2 | import React, { PureComponent } from 'react'
3 |
4 | class Span extends PureComponent {
5 | render() {
6 | const { children, ...props } = this.props
7 |
8 | return (
9 |
10 | { children }
11 |
12 | )
13 | }
14 | }
15 |
16 | Span.propTypes = {
17 | children: PropTypes.node,
18 | }
19 |
20 | Span.defaultProps = {
21 | children: null,
22 | }
23 |
24 | export default Span
25 |
--------------------------------------------------------------------------------
/src/routes/Scoreboard/components/RewardClaimAddress/AddressSection/AddressSection.scss:
--------------------------------------------------------------------------------
1 | .addressSection {
2 | padding: 26px 18px;
3 |
4 | .rewardClaimTitle {
5 | font-size: 16px;
6 | text-align: left;
7 | font-weight: 500;
8 | padding-bottom: 12px;
9 | line-height: 1;
10 | color: #000;
11 | margin: 0;
12 | }
13 |
14 | .button {
15 | background: transparent;
16 | border: 0;
17 | text-decoration: underline;
18 | padding: 0;
19 | color: #02b1c1;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/components/layout/Hairline/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 |
4 | const hairlineStyle = {
5 | width: '100%',
6 | height: '2px',
7 | backgroundColor: '#f0f1f1',
8 | marginBottom: '20px',
9 | }
10 |
11 | const Hairline = ({ style = hairlineStyle }) => (
12 |
13 | )
14 |
15 | Hairline.propTypes = {
16 | style: PropTypes.object,
17 | }
18 |
19 | Hairline.defaultProps = {
20 | style: undefined,
21 | }
22 |
23 | export default Hairline
24 |
--------------------------------------------------------------------------------
/src/containers/HeaderContainer/index.js:
--------------------------------------------------------------------------------
1 | import { compose } from 'recompose'
2 | import { connect } from 'react-redux'
3 | import { withRouter } from 'react-router-dom'
4 | import { withNamespaces } from 'react-i18next'
5 |
6 | import Header from 'components/Header'
7 |
8 | import actions from './store/actions'
9 | import selectors from './store/selectors'
10 |
11 | const enhancer = compose(
12 | withRouter,
13 | connect(selectors, actions),
14 | withNamespaces(),
15 | )
16 |
17 | export default enhancer(Header)
18 |
--------------------------------------------------------------------------------
/src/routes/MarketDetails/store/selectors/getGasPrice.js:
--------------------------------------------------------------------------------
1 | import Decimal from 'decimal.js'
2 |
3 | const getGasPrice = (state) => {
4 | const gasPrice = state.blockchain.get('gasPrice', undefined)
5 |
6 | if (typeof gasPrice === 'undefined') {
7 | return undefined
8 | }
9 |
10 | let gasPriceDecimal
11 | try {
12 | gasPriceDecimal = Decimal(gasPrice.toString())
13 | } catch (e) {
14 | gasPriceDecimal = Decimal(0)
15 | }
16 |
17 | return gasPriceDecimal
18 | }
19 |
20 | export default getGasPrice
21 |
--------------------------------------------------------------------------------
/src/routes/Dashboard/containers/Dashboard/actions.js:
--------------------------------------------------------------------------------
1 | import { fetchMarkets } from 'store/actions/market'
2 | import redeemMarket from 'store/actions/market/redeemMarket'
3 | import { requestTrades } from 'store/actions/trades'
4 | import { requestShares } from 'store/actions/shares'
5 | import { fetchTournamentUserData } from 'routes/Scoreboard/store'
6 |
7 | export default {
8 | requestShares,
9 | requestTrades,
10 | fetchMarkets,
11 | fetchTournamentUserData,
12 | redeemWinnings: market => redeemMarket(market),
13 | }
14 |
--------------------------------------------------------------------------------
/src/routes/MarketDetails/store/actions/index.js:
--------------------------------------------------------------------------------
1 | export { default as buyMarketShares } from './buyShares'
2 | export { default as sellMarketShares } from './sellShares'
3 | export { default as requestMarketTradesForAccount } from './requestMarketTradesForAccount'
4 | export { default as requestMarketSharesForAccount } from './requestMarketSharesForAccount'
5 | export { default as requestMarket } from './requestMarket'
6 | export { default as requestMarketGraphTrades } from './requestMarketGraphTrades.js'
7 | export * from './requestGasCost'
8 |
--------------------------------------------------------------------------------
/src/store/reducers/market.js:
--------------------------------------------------------------------------------
1 | import { Map } from 'immutable'
2 | import { handleActions } from 'redux-actions'
3 | import { addMarkets, updateMarket } from 'store/actions/market'
4 |
5 | export default handleActions(
6 | {
7 | [addMarkets]: (state, { payload }) => state.withMutations((stateMap) => {
8 | payload.forEach(market => stateMap.set(market.address, market))
9 | }),
10 | [updateMarket]: (state, { payload: { marketAddress, data } }) => state.mergeIn([marketAddress], data),
11 | },
12 | Map(),
13 | )
14 |
--------------------------------------------------------------------------------
/.bootstraprc:
--------------------------------------------------------------------------------
1 | ---
2 | useFlexbox: true
3 | styles:
4 | grid: true
5 | buttons: true
6 | mixins: true
7 | media: true
8 | tables: true
9 | scripts: false
10 | appStyles: ./src/scss/style.scss
11 | bootstrapVersion: 3
12 | env:
13 | production:
14 | extractStyles: true
15 | styleLoaders:
16 | - css-loader
17 | - postcss-loader
18 | - sass-loader
19 | development:
20 | styleLoaders:
21 | - style-loader
22 | - css-loader?sourceMap
23 | - postcss-loader?sourceMap
24 | - sass-loader?sourceMap
25 |
26 |
--------------------------------------------------------------------------------
/src/routes/MarketList/store/test/marketlist.spec.js:
--------------------------------------------------------------------------------
1 | import marketReducerTests from './market.reducer'
2 | import marketTests from './market.selector'
3 | import openMarketTests from './openMarkets.selector'
4 | import endingSoonTests from './endingSoon.selector'
5 | import newMarketsTests from './newMarkets.selector'
6 |
7 | describe('Market List Test suite', () => {
8 | // ACTIONS AND REDUCERS
9 | marketReducerTests()
10 |
11 | // SELECTORS
12 | marketTests()
13 | openMarketTests()
14 | endingSoonTests()
15 | newMarketsTests()
16 | })
17 |
--------------------------------------------------------------------------------
/src/store/actions/market/constants/index.js:
--------------------------------------------------------------------------------
1 | import { TRANSACTION_STATUS } from 'utils/constants'
2 |
3 | /**
4 | * Constant names for marketcreation stages
5 | * @readonly
6 | * @enum {string}
7 | */
8 | export const TRANSACTION_STAGES = {
9 | GENERIC: 'generic',
10 | }
11 |
12 | /**
13 | * Generic Stage for single-event transactions
14 | */
15 | export const TRANSACTION_EVENTS_GENERIC = [
16 | {
17 | event: TRANSACTION_STAGES.GENERIC,
18 | label: 'Sending Transaction',
19 | status: TRANSACTION_STATUS.RUNNING,
20 | },
21 | ]
22 |
--------------------------------------------------------------------------------
/src/components/Form/index.js:
--------------------------------------------------------------------------------
1 | export { default as OutcomeSelection } from './OutcomeSelection'
2 | export { default as RadioButton } from './RadioButton'
3 | export { default as Checkbox } from './Checkbox'
4 | export { default as RadioButtonGroup } from './RadioButtonGroup'
5 | export { default as Select } from './Select'
6 | export { default as Slider } from './Slider'
7 | export { default as TextInput } from './TextInput'
8 | export { default as TextInputAdornment } from './TextInputAdornment'
9 | export { default as MandatoryHint } from './MandatoryHint'
10 |
--------------------------------------------------------------------------------
/src/integrations/index.js:
--------------------------------------------------------------------------------
1 | import { WALLET_PROVIDER } from './constants'
2 |
3 | import METAMASK from './metamask'
4 | import PARITY from './parity'
5 | import REMOTE from './remote'
6 | import TRUST from './trust'
7 | import STATUS from './status'
8 |
9 | // eslint-disable-next-line
10 | const providers = {
11 | [WALLET_PROVIDER.METAMASK]: METAMASK,
12 | [WALLET_PROVIDER.PARITY]: PARITY,
13 | [WALLET_PROVIDER.REMOTE]: REMOTE,
14 | [WALLET_PROVIDER.TRUST]: TRUST,
15 | [WALLET_PROVIDER.STATUS]: STATUS,
16 | }
17 |
18 | export default providers
19 |
--------------------------------------------------------------------------------
/src/integrations/status/assets/status-logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest a new Feature to be implemented
4 |
5 | ---
6 |
7 | **As a user, I want to view my favorite animal on the site, because I really like dogs**
8 | *Please follow the format of: As a , I want , because *
9 |
10 | **Acceptance Criteria**
11 | - I get to see my favorite animal on every page of the application in the bottom right corner
12 | - The Animal must be a dog
13 | - If I go to `/settings` the dog must wear a hardhat
14 |
15 | **Screenshots/Mockups**
16 |
--------------------------------------------------------------------------------
/src/embedded/routes/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { HashRouter, Switch, Route } from 'react-router-dom'
3 |
4 | import EmbeddedView from './EmbeddedView'
5 |
6 | const NoMatch = () => (404)
7 |
8 | const EmbeddedRouter = () => (
9 |
10 |
11 | {/* Add more Routes here, before the /:address route */}
12 |
13 |
14 |
15 |
16 | )
17 |
18 | export default EmbeddedRouter
19 |
--------------------------------------------------------------------------------
/src/components/layout/PageFrame/index.js:
--------------------------------------------------------------------------------
1 | import classNames from 'classnames/bind'
2 | import Block from 'components/layout/Block'
3 | import PropTypes from 'prop-types'
4 | import React from 'react'
5 | import * as css from './index.scss'
6 |
7 | const cx = classNames.bind(css)
8 |
9 | const PageFrame = ({ width, children }) =>
10 | (
11 | { children }
12 | )
13 |
14 | PageFrame.propTypes = {
15 | children: PropTypes.node,
16 | width: PropTypes.string,
17 | }
18 |
19 | export default PageFrame
20 |
--------------------------------------------------------------------------------
/src/routes/MarketDetails/components/ExpandableViews/MarketMySharesForm/SharesTable/SharesTable.scss:
--------------------------------------------------------------------------------
1 | @import "~style/vars.scss";
2 |
3 | $indexWidth: 36px;
4 | $groupWidth: 33%;
5 |
6 | .sharesTable {
7 | margin-top: 20px;
8 | table-layout: fixed;
9 | }
10 |
11 | .sharesTableHeading {
12 | font-weight: 400;
13 | text-transform: uppercase;
14 | color: $font-color-muted;
15 | border-bottom: none !important;
16 |
17 | &.group {
18 | width: $groupWidth;
19 | }
20 |
21 | &.index {
22 | width: $indexWidth;
23 |
24 | border-bottom: 0 !important;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/routes/MarketDetails/components/MarketDetail/marketDetail.scss:
--------------------------------------------------------------------------------
1 | @import "~style/vars.scss";
2 |
3 | $expandable-arrow-size: 15px;
4 | $expandable-margin: 40px;
5 |
6 | .marketTitleHeading {
7 | margin: $page-heading-margins;
8 | }
9 |
10 | .expandable {
11 | position: relative;
12 | z-index: 2;
13 | margin-top: $expandable-margin;
14 | .inner {
15 | padding: 40px 0;
16 | background-color: $bg-color-muted;
17 |
18 | &::before {
19 | visibility: visible;
20 | content: "";
21 | position: absolute;
22 | margin-bottom: 50px;
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/src/routes/MarketDetails/store/actions/requestMarketTradesForAccount.js:
--------------------------------------------------------------------------------
1 | import { hexWithoutPrefix } from 'utils/helpers'
2 | import { requestFromRestAPI } from 'api/utils/fetch'
3 | import { processTradesResponse } from 'store/actions/trades'
4 |
5 | export default (marketAddress, account) => async (dispatch) => {
6 | const normalizedAccount = hexWithoutPrefix(account)
7 | const normalizedMarket = hexWithoutPrefix(marketAddress)
8 | const response = await requestFromRestAPI(`/markets/${normalizedMarket}/trades/${normalizedAccount}`)
9 | processTradesResponse(response, dispatch)
10 | }
11 |
--------------------------------------------------------------------------------
/src/routes/MarketDetails/store/actions/requestMarketSharesForAccount.js:
--------------------------------------------------------------------------------
1 | import { hexWithoutPrefix } from 'utils/helpers'
2 | import { requestFromRestAPI } from 'api/utils/fetch'
3 | import { processSharesResponse } from 'store/actions/shares'
4 |
5 | export default (marketAddress, account) => async (dispatch) => {
6 | const normalizedAccount = hexWithoutPrefix(account)
7 | const normalizedMarket = hexWithoutPrefix(marketAddress)
8 | const response = await requestFromRestAPI(`/markets/${normalizedMarket}/shares/${normalizedAccount}`)
9 |
10 | processSharesResponse(response, dispatch)
11 | }
12 |
--------------------------------------------------------------------------------
/src/routes/MarketList/containers/MarketList/selector.js:
--------------------------------------------------------------------------------
1 | import { getCurrentAccount } from 'integrations/store/selectors'
2 | import { createStructuredSelector } from 'reselect'
3 |
4 | import {
5 | marketListSelector,
6 | newMarketsSelector,
7 | endingSoonMarketSelector,
8 | openMarketSelector,
9 | } from '../../store/selectors'
10 |
11 | export default createStructuredSelector({
12 | markets: marketListSelector,
13 | openMarkets: openMarketSelector,
14 | newMarkets: newMarketsSelector,
15 | endingSoonMarkets: endingSoonMarketSelector,
16 | userAccount: getCurrentAccount,
17 | })
18 |
--------------------------------------------------------------------------------
/src/components/layout/Title/index.js:
--------------------------------------------------------------------------------
1 | import classNames from 'classnames/bind'
2 | import PropTypes from 'prop-types'
3 | import React, { PureComponent } from 'react'
4 | import * as css from './index.scss'
5 |
6 | const cx = classNames.bind(css)
7 |
8 | class Title extends PureComponent {
9 | render() {
10 | const { children, ...props } = this.props
11 |
12 | return (
13 |
14 | { children }
15 |
16 | )
17 | }
18 | }
19 |
20 | Title.propTypes = {
21 | children: PropTypes.node,
22 | }
23 |
24 | export default Title
25 |
--------------------------------------------------------------------------------
/src/containers/LegalCompliance/store/selectors.js:
--------------------------------------------------------------------------------
1 | import { formValueSelector } from 'redux-form'
2 | import { getFeatureConfig } from 'utils/features'
3 |
4 | const { documents } = getFeatureConfig('legalCompliance')
5 |
6 | const getFormValue = formValueSelector('legalCompliance')
7 |
8 | const getLegalDocumentFields = (state) => {
9 | const fields = {}
10 |
11 | documents.forEach((doc) => {
12 | fields[doc.id] = !!getFormValue(state, doc.id)
13 | })
14 |
15 | return fields
16 | }
17 |
18 | export default state => ({
19 | fields: getLegalDocumentFields(state),
20 | documents,
21 | })
22 |
--------------------------------------------------------------------------------
/src/api/utils/fetch.js:
--------------------------------------------------------------------------------
1 | /* globals fetch */
2 | import qs from 'querystring'
3 | import { getConfiguration } from 'utils/features'
4 |
5 | const config = getConfiguration()
6 |
7 | const API_URL = `${config.gnosisdb.protocol}://${config.gnosisdb.host}/api`
8 |
9 | export const requestFromRestAPI = async (endpoint, queryparams) => {
10 | const url = `${API_URL}/${endpoint}?${qs.stringify(queryparams)}`
11 |
12 | let response
13 |
14 | try {
15 | response = await fetch(url)
16 | return response.json()
17 | } catch (e) {
18 | console.error(`GnosisDB: Couldn't fetch ${e}`)
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/store/reducers/accountShares.js:
--------------------------------------------------------------------------------
1 | import { Map } from 'immutable'
2 | import { handleActions } from 'redux-actions'
3 | import { addShare, updateShare, redeemShare } from 'store/actions/shares'
4 |
5 | export default handleActions(
6 | {
7 | [addShare]: (state, { payload }) => state.withMutations((map) => {
8 | payload.forEach(share => map.set(share.id, share))
9 | }),
10 | [redeemShare]: (state, { payload: shareId }) => state.setIn([shareId, 'balance'], '0'),
11 | [updateShare]: (state, { payload: { shareId, data } }) => state.mergeIn([shareId], data),
12 | },
13 | Map(),
14 | )
15 |
--------------------------------------------------------------------------------
/scripts/configuration.browser.js:
--------------------------------------------------------------------------------
1 | /* globals process */
2 | const fs = require('fs')
3 | const path = require('path')
4 |
5 | const GNOSIS_ENV = process.argv.splice(-1)[0]
6 | const { GNOSIS_CONFIG } = process.env
7 |
8 | const configLoader = require('./configuration.js')
9 |
10 | const applicationConfiguration = configLoader(GNOSIS_ENV, GNOSIS_CONFIG)
11 |
12 | const configTarget = path.join(__dirname, '..', 'dist', 'config.js')
13 | fs.writeFileSync(configTarget, `window.__GNOSIS_CONFIG__ = ${JSON.stringify(applicationConfiguration, null, 2)}`)
14 | console.log('[PM-UI] Config for env written to dist/config.js')
15 |
--------------------------------------------------------------------------------
/.travis/scripts/prepare_production_deployment.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -ev
4 |
5 | # Only:
6 | # - Tagged commits
7 | # - Security env variables are available.
8 | if [ -n "$TRAVIS_TAG" ] && [ -n "$PROD_DEPLOYMENT_HOOK_TOKEN" ] && [ -n "$PROD_DEPLOYMENT_HOOK_URL_DOMAIN" ]
9 | then
10 | curl -X POST \
11 | -F token="$PROD_DEPLOYMENT_HOOK_TOKEN" \
12 | -F ref=master \
13 | -F "variables[TRIGGER_RELEASE_COMMIT_TAG]=$TRAVIS_TAG" \
14 | https://"$PROD_DEPLOYMENT_HOOK_URL_DOMAIN"/api/v4/projects/39/trigger/pipeline
15 | else
16 | echo "[ERROR] Production deployment could not be prepared"
17 | fi
18 |
--------------------------------------------------------------------------------
/src/assets/img/icons/icon_checkmark.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
--------------------------------------------------------------------------------
/src/assets/img/icons/icon_link.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/components/layout/Paragraph/index.scss:
--------------------------------------------------------------------------------
1 | .default-paragraph {
2 | font-family: Montserrat;
3 | color: #626262;
4 |
5 | line-height: 1.7;
6 | font-weight: 300;
7 | color: #333;
8 | }
9 |
10 | .soft {
11 | color: #888888;
12 | }
13 |
14 | .medium {
15 | color: #686868;
16 | }
17 |
18 | .dark {
19 | color: black;
20 | }
21 |
22 | .primary {
23 | color: #00a6c4;
24 | }
25 |
26 | .no-margin{
27 | margin-bottom: 5px;
28 | }
29 |
30 | .center {
31 | text-align: center;
32 | }
33 |
34 | .normal {
35 | font-size: 18px;
36 | }
37 |
38 | .small {
39 | font-size: 12px;
40 | }
--------------------------------------------------------------------------------
/src/components/layout/Subtitle/index.js:
--------------------------------------------------------------------------------
1 | import classNames from 'classnames/bind'
2 | import PropTypes from 'prop-types'
3 | import React, { PureComponent } from 'react'
4 | import * as css from './index.scss'
5 |
6 | const cx = classNames.bind(css)
7 |
8 | class Subtitle extends PureComponent {
9 | render() {
10 | const { children, ...props } = this.props
11 |
12 | return (
13 |
14 | { children }
15 |
16 | )
17 | }
18 | }
19 |
20 | Subtitle.propTypes = {
21 | children: PropTypes.node,
22 | }
23 |
24 | export default Subtitle
25 |
--------------------------------------------------------------------------------
/src/api/token.js:
--------------------------------------------------------------------------------
1 | import { getROGnosisConnection } from 'api'
2 |
3 | export const getTokenSymbol = async (tokenAddress) => {
4 | const gnosis = await getROGnosisConnection()
5 | const token = await gnosis.contracts.DetailedERC20.at(tokenAddress)
6 | const tokenSymbol = await token.symbol()
7 | return tokenSymbol
8 | }
9 |
10 | export const getTokenBalance = async (tokenAddress, accountAddress) => {
11 | const gnosis = await getROGnosisConnection()
12 | const token = await gnosis.contracts.Token.at(tokenAddress)
13 | const balance = await token.balanceOf(accountAddress)
14 | return balance.toString()
15 | }
16 |
--------------------------------------------------------------------------------
/src/assets/img/icons/icon_incomeForecast.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | .DS_STORE
3 | node_modules
4 | *~
5 | *.pyc
6 | static
7 | .grunt
8 | _SpecRunner.html
9 | __benchmarks__
10 | dist/
11 | coverage/
12 | .module-cache
13 | *.gem
14 | docs/.bundle
15 | docs/code
16 | docs/_site
17 | docs/.sass-cache
18 | docs/js/*
19 | docs/downloads/*.zip
20 | docs/vendor/bundle
21 | examples/shared/*.js
22 | examples/**/bundle.js
23 | test/the-files-to-test.generated.js
24 | *.log*
25 | chrome-user-data
26 | *.sublime-project
27 | *.sublime-workspace
28 | .idea
29 | *.iml
30 | .vscode
31 | /semantic.json
32 | /semantic
33 | yarn-error.log
34 | yarn.lock
35 | local.json
36 | production.json
37 | .history
--------------------------------------------------------------------------------
/src/integrations/uport/uportQr.js:
--------------------------------------------------------------------------------
1 | export const isValid = cred => !!cred
2 |
3 | const assignSessionProps = (uport, cred) => {
4 | // eslint-disable-next-line
5 | uport.address = cred.address
6 | // eslint-disable-next-line
7 | uport.firstReq = false
8 | }
9 |
10 | const init = async (uport, requestCredentials, getCredential) => {
11 | let credential = getCredential()
12 | if (!isValid(credential)) {
13 | uport.firstReq = true
14 | credential = await requestCredentials()
15 | }
16 |
17 | if (credential) {
18 | assignSessionProps(uport, credential)
19 | }
20 |
21 | return uport
22 | }
23 |
24 | export default init
25 |
--------------------------------------------------------------------------------
/src/routes/MarketDetails/components/MarketDetail/Infos/utils/embeddedLink.js:
--------------------------------------------------------------------------------
1 | export default (marketAddress) => {
2 | const path = `${window.location.origin}/embedded/${marketAddress}`
3 |
4 | return `
5 |
6 |
7 |
8 |
21 | `
22 | }
23 |
--------------------------------------------------------------------------------
/src/routes/MarketList/components/MarketsTitle/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 | import { withNamespaces } from 'react-i18next'
4 | import classNames from 'classnames/bind'
5 |
6 | import css from './MarketsTitle.scss'
7 |
8 | const cx = classNames.bind(css)
9 |
10 | const MarketListTitle = ({ t }) => (
11 |
12 |
13 |
{t('markets.list_title')}
14 |
15 |
16 | )
17 |
18 | MarketListTitle.propTypes = {
19 | t: PropTypes.func.isRequired,
20 | }
21 |
22 | export default withNamespaces()(MarketListTitle)
23 |
--------------------------------------------------------------------------------
/src/containers/BackdropProvider/backdrop.scss:
--------------------------------------------------------------------------------
1 | .below {
2 | height: 100vh;
3 | background-color: #09697b;
4 | opacity: 0.9;
5 |
6 | z-index: 99;
7 | position: fixed;
8 | top: 0;
9 | left: 0;
10 | right: 0;
11 | bottom: 0;
12 | }
13 |
14 | .above {
15 | z-index: 100;
16 | position: fixed;
17 | top: 0;
18 | left: 0;
19 | right: 0;
20 | bottom: 0;
21 | }
22 |
23 | .fade-enter {
24 | opacity: 0.01;
25 | }
26 | .fade-enter-active {
27 | opacity: 1;
28 | transition: all 300ms ease-out;
29 | }
30 | .fade-exit {
31 | opacity: 1;
32 | }
33 | .fade-exit-active {
34 | opacity: 0.01;
35 | transition: all 300ms ease-out;
36 | }
37 |
--------------------------------------------------------------------------------
/src/routes/MarketList/store/test/market.selector.js:
--------------------------------------------------------------------------------
1 | import { List } from 'immutable'
2 | import { marketListSelector } from '../selectors'
3 |
4 | const marketTests = () => {
5 | describe('Market List Selector[marketsSelector]', () => {
6 | it('should get empty immutable List when they are not loaded', () => {
7 | // GIVEN
8 | const emptyList = List([])
9 | const reduxStore = { marketList: emptyList }
10 |
11 | // WHEN
12 | const marketListState = marketListSelector(reduxStore)
13 |
14 | // THEN
15 | expect(marketListState).toEqual(emptyList)
16 | })
17 | })
18 | }
19 |
20 | export default marketTests
21 |
--------------------------------------------------------------------------------
/src/containers/Modals/ModalClaimReward/action.js:
--------------------------------------------------------------------------------
1 | import { GAS_COST } from 'utils/constants'
2 | import { setGasCost } from 'routes/MarketDetails/store/actions'
3 | import { getFeatureConfig } from 'utils/features'
4 | import { calcClaimRewardGasCost } from './api'
5 |
6 | const contractType = GAS_COST.CLAIM_REWARD
7 | const { claimReward } = getFeatureConfig('rewardClaiming')
8 |
9 | const requestClaimRewardGasCost = () => async (dispatch) => {
10 | const gasCost = await calcClaimRewardGasCost(claimReward.contractAddress)
11 |
12 | dispatch(setGasCost({ entityType: 'gasCosts', contractType, gasCost }))
13 | }
14 |
15 | export { requestClaimRewardGasCost }
16 |
--------------------------------------------------------------------------------
/src/utils/analytics/intercom/index.js:
--------------------------------------------------------------------------------
1 | import { getThirdPartyConfig } from 'utils/features'
2 |
3 | export const THIRD_PARTY_ID = 'intercom'
4 |
5 | const { id: APP_ID } = getThirdPartyConfig(THIRD_PARTY_ID)
6 |
7 | export default () => {
8 | const d = document
9 |
10 | const s = d.createElement('script')
11 | s.type = 'text/javascript'
12 | s.async = true
13 | s.src = `https://widget.intercom.io/widget/${APP_ID}`
14 | const x = d.getElementsByTagName('script')[0]
15 | x.parentNode.insertBefore(s, x)
16 |
17 | s.onload = () => {
18 | window.Intercom('boot', {
19 | app_id: APP_ID,
20 | consent: true,
21 | })
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/routes/MarketDetails/components/ExpandableViews/MarketBuySharesForm/SubmitError/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 | import { withNamespaces } from 'react-i18next'
4 | import cn from 'classnames/bind'
5 | import style from '../marketBuySharesForm.scss'
6 |
7 | const cx = cn.bind(style)
8 |
9 | const SubmitError = ({ t }) => (
10 |
11 |
12 | {t('market.submit_error')}
13 |
14 |
15 | )
16 |
17 | SubmitError.propTypes = {
18 | t: PropTypes.func.isRequired,
19 | }
20 |
21 | export default withNamespaces()(SubmitError)
22 |
--------------------------------------------------------------------------------
/src/utils/marginPrice.js:
--------------------------------------------------------------------------------
1 | import Decimal from 'decimal.js'
2 |
3 | const allowedRangePrice = (oldP, newP) => {
4 | const oldPrice = new Decimal(oldP)
5 | const newPrice = new Decimal(newP)
6 |
7 | // We calculate the 5% of the latest price applying 18 decimals round up
8 | const allowance = new Decimal(newPrice)
9 | .mul(5)
10 | .div(100)
11 | .toDP(18, Decimal.ROUND_UP)
12 |
13 | // Calculate the abs difference between prices
14 | const diff = new Decimal(newPrice).sub(oldPrice).absoluteValue()
15 |
16 | return diff.lte(allowance) // return true if diff between prices is lower than 5 percent
17 | }
18 |
19 | export default allowedRangePrice
20 |
--------------------------------------------------------------------------------
/src/containers/Modals/ModalRegisterWallet/actions.js:
--------------------------------------------------------------------------------
1 | import { GAS_COST } from 'utils/constants'
2 | import { setGasCost } from 'routes/MarketDetails/store/actions'
3 | import { getCurrentAccount } from 'integrations/store/selectors'
4 | import { calcRegistrationGasCost } from './api'
5 |
6 | const contractType = GAS_COST.MAINNET_ADDRESS_REGISTRATION
7 |
8 | const requestRegistrationGasCost = () => async (dispatch, getState) => {
9 | const account = getCurrentAccount(getState())
10 | const gasCost = await calcRegistrationGasCost(account)
11 |
12 | dispatch(setGasCost({ entityType: 'gasCosts', contractType, gasCost }))
13 | }
14 |
15 | export { requestRegistrationGasCost }
16 |
--------------------------------------------------------------------------------
/src/routes/MarketDetails/store/selectors/getMarketTradesForAccount.js:
--------------------------------------------------------------------------------
1 | import { createSelector } from 'reselect'
2 | import moment from 'moment'
3 | import tradeSelector from 'store/selectors/account/trades'
4 | import { normalizeHex } from 'utils/helpers'
5 |
6 | const getMarketTradesForAccount = (eventAddress, accountAddress = '') => createSelector(tradeSelector, trades => trades
7 | .filter(
8 | trade => normalizeHex(trade.eventAddress) === normalizeHex(eventAddress)
9 | && normalizeHex(trade.owner) === normalizeHex(accountAddress),
10 | )
11 | .sort((a, b) => (moment(a.date).isBefore(b.date) ? 1 : -1)))
12 |
13 | export default getMarketTradesForAccount
14 |
--------------------------------------------------------------------------------
/src/routes/MarketList/components/Markets/Market/MarketResolution.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types'
2 | import React from 'react'
3 | import classNames from 'classnames/bind'
4 |
5 | import Icon from 'components/Icon'
6 |
7 | import css from './Market.scss'
8 |
9 | const cx = classNames.bind(css)
10 |
11 | const MarketResolution = ({ resolution }) => (
12 |
13 |
14 |
15 | {resolution}
16 |
17 |
18 | )
19 |
20 | MarketResolution.propTypes = {
21 | resolution: PropTypes.string.isRequired,
22 | }
23 |
24 | export default MarketResolution
25 |
--------------------------------------------------------------------------------
/src/assets/img/icons/icon_share.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/routes/MarketDetails/components/MarketGraph/DateAxisTick/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 | import moment from 'moment'
4 |
5 | const DateAxisTick = ({ x, y, payload }) => (
6 |
7 |
8 | {moment(payload.value).format('DD/MM/YYYY')}
9 |
10 |
11 | )
12 |
13 | DateAxisTick.propTypes = {
14 | x: PropTypes.number,
15 | y: PropTypes.number,
16 | payload: PropTypes.string,
17 | }
18 |
19 | DateAxisTick.defaultProps = {
20 | x: 0,
21 | y: 0,
22 | payload: '',
23 | }
24 |
25 | export default DateAxisTick
26 |
--------------------------------------------------------------------------------
/src/components/Form/Select.scss:
--------------------------------------------------------------------------------
1 | @import "~style/vars.scss";
2 |
3 | .formSelect {
4 | .Select-control {
5 | border: 0;
6 | border-bottom: 1px solid $bg-color-muted;
7 | border-radius: unset;
8 | }
9 |
10 | .Select-menu-outer {
11 | border-radius: unset;
12 | }
13 |
14 | label {
15 | margin: 20px 0 6px 0;
16 | display: block;
17 | }
18 |
19 | &.error {
20 | .Select-value span {
21 | color: $active-highlight-error !important;
22 | }
23 |
24 | label {
25 | color: $active-highlight-error;
26 | }
27 |
28 | .Select-control {
29 | border-color: lighten($color: $active-highlight-error, $amount: 30);
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/src/routes/MarketList/components/MarketOverview/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 | import classNames from 'classnames/bind'
4 |
5 | import css from './MarketOverview.scss'
6 |
7 | const cx = classNames.bind(css)
8 |
9 | const MarketsOverview = ({ children }) => (
10 |
11 |
12 |
13 | {children}
14 |
15 |
16 |
17 | )
18 |
19 | MarketsOverview.propTypes = {
20 | children: PropTypes.node,
21 | }
22 |
23 | MarketsOverview.defaultProps = {
24 | children: null,
25 | }
26 |
27 | export default MarketsOverview
28 |
--------------------------------------------------------------------------------
/src/store/models/share/index.js:
--------------------------------------------------------------------------------
1 | import { Record } from 'immutable'
2 |
3 | const ShareRecord = Record({
4 | id: undefined, // string
5 | owner: undefined, // string
6 | eventAddress: undefined, // string
7 | collateralTokenAddress: undefined, // string
8 | balance: undefined, // int
9 | marketTitle: undefined, // string
10 | marketType: undefined, // oneOf OUTCOME_TYPE
11 | marketResolution: undefined, // moment
12 | marketOutcomes: undefined, // List
13 | marginalPrice: undefined, // decimal
14 | outcomeToken: undefined, // OutcomeRecord
15 | market: undefined, // MarketRecord
16 | winnings: undefined,
17 | }, 'Share')
18 |
19 | export default ShareRecord
20 |
--------------------------------------------------------------------------------
/src/components/Form/InputError.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 |
4 | import className from 'classnames/bind'
5 |
6 | import styles from './InputError.scss'
7 |
8 | const cx = className.bind(styles)
9 |
10 | const InputError = ({ error, style }) => (error ? (
11 |
12 | {error}
13 |
14 | ) : null)
15 |
16 | InputError.propTypes = {
17 | error: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),
18 | // eslint-disable-next-line
19 | style: PropTypes.object,
20 | }
21 |
22 | InputError.defaultProps = {
23 | error: undefined,
24 | style: {},
25 | }
26 |
27 | export default InputError
28 |
--------------------------------------------------------------------------------
/src/containers/App/app.scss:
--------------------------------------------------------------------------------
1 | @import "~style/vars.scss";
2 |
3 | $footer-bottom: 60px;
4 |
5 | .appContainer {
6 | position: relative;
7 | background-color: $bg-color;
8 | height: calc(100vh - #{$footer-bottom});
9 | overflow-y: scroll;
10 |
11 | .loader-container {
12 | height: 100%;
13 | width: 100%;
14 | display: flex;
15 | justify-content: center;
16 | align-items: center;
17 | flex-direction: column;
18 |
19 | @media (max-width: 767px) {
20 | text-align: center;
21 |
22 | h1 {
23 | font-size: 30px;
24 | line-height: 45px;
25 | }
26 | }
27 | }
28 |
29 | @media (max-width: 992px) {
30 | height: 100vh;
31 | }
32 | }
--------------------------------------------------------------------------------
/src/store/models/market/index.js:
--------------------------------------------------------------------------------
1 | import { Record } from 'immutable'
2 |
3 | export const MARKET_STAGES = {
4 | MARKET_CREATED: 0,
5 | MARKET_FUNDED: 1,
6 | MARKET_CLOSED: 2,
7 | }
8 |
9 | export const BoundsRecord = Record({
10 | lower: undefined,
11 | upper: undefined,
12 | unit: undefined,
13 | decimals: undefined,
14 | }, 'Bound')
15 |
16 | export const OutcomeRecord = Record({
17 | name: undefined, // string
18 | index: undefined, // int
19 | marginalPrice: undefined, // decimal
20 | outcomeTokensSold: undefined, // int
21 | }, 'Outcome')
22 |
23 | export { default as ScalarMarketRecord } from './scalar'
24 | export { default as CategoricalMarketRecord } from './categorical'
25 |
--------------------------------------------------------------------------------
/src/assets/img/icons/icon_next.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/scss/main.scss:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'Montserrat';
3 | font-weight: 300;
4 | src: url('~assets/fonts/Montserrat-Light.ttf') format('truetype');
5 | }
6 |
7 | @font-face {
8 | font-family: 'Montserrat';
9 | font-weight: 400;
10 | src: url('~assets/fonts/Montserrat-Regular.ttf') format('truetype');
11 | }
12 |
13 | @font-face {
14 | font-family: 'Montserrat';
15 | font-weight: 500;
16 | src: url('~assets/fonts/Montserrat-Medium.ttf') format('truetype');
17 | }
18 |
19 | * {
20 | box-sizing: border-box;
21 | }
22 | *:before,
23 | *:after {
24 | box-sizing: border-box;
25 | }
26 |
27 | html,
28 | body,
29 | #root {
30 | height: 100%;
31 | font-family: 'Montserrat', sans-serif;
32 | }
--------------------------------------------------------------------------------
/src/components/layout/Img/index.js:
--------------------------------------------------------------------------------
1 | import classNames from 'classnames/bind'
2 | import PropTypes from 'prop-types'
3 | import React, { PureComponent } from 'react'
4 | import * as css from './index.css'
5 |
6 | const cx = classNames.bind(css)
7 |
8 | class Img extends PureComponent {
9 | render() {
10 | const {
11 | fullwidth, alt, bordered, className, ...props
12 | } = this.props
13 |
14 | return
15 | }
16 | }
17 |
18 | Img.propTypes = {
19 | alt: PropTypes.string,
20 | fullwidth: PropTypes.bool,
21 | bordered: PropTypes.bool,
22 | className: PropTypes.string,
23 | }
24 |
25 | export default Img
26 |
--------------------------------------------------------------------------------
/src/components/Footer/Footer.scss:
--------------------------------------------------------------------------------
1 | .footer {
2 | position: fixed;
3 | bottom: 0;
4 | left: 0;
5 | width: 100vw;
6 | background: #fff;
7 | padding: 0;
8 | text-align: center;
9 | z-index: 10;
10 |
11 | .footerContainer {
12 | font-size: 12px;
13 | font-weight: 300;
14 | line-height: normal;
15 | color: #686868;
16 | text-align: center;
17 | }
18 |
19 | .version {
20 | padding: 0;
21 | margin: 0;
22 | font-size: 12px;
23 | color: white;
24 | }
25 |
26 | a {
27 | text-decoration: underline;
28 |
29 | &:hover, &:visited, &:active {
30 | color: #00a6c4
31 | }
32 | }
33 |
34 | @media (max-width: 992px) {
35 | position: static;
36 | }
37 | }
--------------------------------------------------------------------------------
/src/components/Form/MandatoryHint.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 | import { withNamespaces } from 'react-i18next'
4 | import classnames from 'classnames/bind'
5 | import Tooltip from 'rc-tooltip'
6 |
7 | import styles from './MandatoryHint.scss'
8 |
9 | const cx = classnames.bind(styles)
10 |
11 | const MandatoryHint = ({ t }) => (
12 |
14 | {t('form.field_required')};
15 |
16 | )}
17 | >
18 |
19 | *
20 |
21 |
22 | )
23 |
24 | MandatoryHint.propTypes = {
25 | t: PropTypes.func.isRequired,
26 | }
27 |
28 | export default withNamespaces()(MandatoryHint)
29 |
--------------------------------------------------------------------------------
/src/components/Header/MenuAccountDropdown/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Tooltip from 'rc-tooltip'
3 | import cn from 'classnames/bind'
4 | import MenuActions from './MenuActions'
5 | import style from './dropdown.scss'
6 | import './tooltip.scss?raw'
7 |
8 | const cx = cn.bind(style)
9 |
10 | const MenuAccountDropdown = () => (
11 | }
15 | align={{
16 | offset: ['10%', 20],
17 | }}
18 | trigger={['click']}
19 | >
20 |
23 |
24 | )
25 |
26 | export default MenuAccountDropdown
27 |
--------------------------------------------------------------------------------
/src/routes/MarketDetails/components/ExpandableViews/MarketBuySharesForm/LimitMarginAnnotation/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 | import { withNamespaces } from 'react-i18next'
4 | import cn from 'classnames/bind'
5 | import style from '../marketBuySharesForm.scss'
6 |
7 | const cx = cn.bind(style)
8 |
9 | const LimitMarginAnnotation = ({ t }) => (
10 |
11 |
12 | {t('market.limit_margin_warning')}
13 |
14 |
15 | )
16 |
17 | LimitMarginAnnotation.propTypes = {
18 | t: PropTypes.func.isRequired,
19 | }
20 |
21 | export default withNamespaces()(LimitMarginAnnotation)
22 |
--------------------------------------------------------------------------------
/src/components/Header/Layouts/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Loadable from 'react-loadable'
3 | import { Desktop, Tablet, Mobile } from 'components/Responsive'
4 |
5 | const LoadableDesktop = Loadable({
6 | loader: () => import('./DesktopHeader'),
7 | loading: () => null,
8 | })
9 |
10 | const LoadableMobile = Loadable({
11 | loader: () => import('./MobileHeader'),
12 | loading: () => null,
13 | })
14 |
15 | const Layout = props => (
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | )
28 |
29 | export default Layout
30 |
--------------------------------------------------------------------------------
/src/routes/Scoreboard/components/Table/ScoreTable/index.stories.js:
--------------------------------------------------------------------------------
1 | import { text } from '@storybook/addon-knobs'
2 | import { storiesOf } from '@storybook/react'
3 | import * as React from 'react'
4 | import users from 'stories/knobs/scoreboardUsers'
5 | import { host } from 'storybook-host'
6 | import Component from './index'
7 |
8 | storiesOf('Route ScoreBoard components', module)
9 | .addDecorator(host({
10 | title: 'ScoreBoard',
11 | align: 'center',
12 | height: 650,
13 | width: '100%',
14 | }))
15 | .add('ScoreTable', () => {
16 | const data = users
17 | const myWallet = text('User Account', '0x90F8bf6A479f320ead074411a4B0e7944Ea8ca007')
18 |
19 | return
20 | })
21 |
--------------------------------------------------------------------------------
/src/routes/Scoreboard/containers/actions.js:
--------------------------------------------------------------------------------
1 | import { openModal } from 'store/actions/modal'
2 | import { fetchTournamentUsers, addUsers, fetchTournamentUserData } from '../store/actions'
3 |
4 | const openSetMainnetAddressModal = () => openModal({ modalName: 'ModalRegisterWalletUport' })
5 | const openClaimRewardModal = () => openModal({ modalName: 'ModalClaimReward' })
6 |
7 | export default dispatch => ({
8 | fetchTournamentUsers: () => dispatch(fetchTournamentUsers()),
9 | addUsers: () => dispatch(addUsers()),
10 | openSetMainnetAddressModal: () => dispatch(openSetMainnetAddressModal()),
11 | openClaimRewardModal: () => dispatch(openClaimRewardModal()),
12 | fetchTournamentUserData: account => dispatch(fetchTournamentUserData(account)),
13 | })
14 |
--------------------------------------------------------------------------------
/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ### Description
2 | * Example Content
3 |
4 | ### Which Tickets does my PR fix? (Put in title too)
5 | * Fixes task/PM-123
6 |
7 | ### Which PRs are linked to my PR?
8 | * task/PM-123
9 |
10 | ### Which side effects could my PR have?
11 | * Example Content
12 |
13 | ### Which Steps did I take to verify my PR?
14 |
15 | *Case 1*
16 | * Example Content
17 |
18 | *Case 2*
19 | * Example Content
20 |
21 | ### Background Information
22 | * Example Content
23 |
24 | ### Configuration Entries
25 | `/staging/interface.config`
26 | ```
27 | {
28 | "feature": {
29 | "enabled": false,
30 | }
31 | }
32 | ```
33 | `/olympia/staging/interface.config`
34 | ```
35 | {
36 | "feature": {
37 | "enabled" true,
38 | }
39 | }
40 | ```
41 |
--------------------------------------------------------------------------------
/src/components/ModalContent/TransactionsExplanation/TransactionExplanation.scss:
--------------------------------------------------------------------------------
1 | @import "~style/vars.scss";
2 |
3 | .transactionsExplanation {
4 | display: flex;
5 | justify-content: center;
6 | align-items: center;
7 | flex-direction: column;
8 | min-height: 100vh;
9 | color: #fff;
10 |
11 | @media (max-width: 767px) {
12 | text-align: center;
13 | }
14 |
15 | @media (max-width: 320px) {
16 | font-size: 12px;
17 | }
18 |
19 |
20 | .closeButton {
21 | @include closeButton(32px, 5px);
22 | top: 20px;
23 | right: 10px;
24 | }
25 |
26 | .transactionList {
27 | font-size: 16px;
28 | list-style: none;
29 | margin-top: 20px;
30 |
31 | li + li {
32 | margin-top: 5px;
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/embedded/style/embedded.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'Montserrat';
3 | font-weight: 300;
4 | src: url('~assets/fonts/Montserrat-Light.ttf') format('truetype');
5 | }
6 |
7 | @font-face {
8 | font-family: 'Montserrat';
9 | font-weight: 400;
10 | src: url('~assets/fonts/Montserrat-Regular.ttf') format('truetype');
11 | }
12 |
13 | @font-face {
14 | font-family: 'Montserrat';
15 | font-weight: 500;
16 | src: url('~assets/fonts/Montserrat-Medium.ttf') format('truetype');
17 | }
18 |
19 | * {
20 | box-sizing: border-box;
21 | }
22 | *:before,
23 | *:after {
24 | box-sizing: border-box;
25 | }
26 |
27 | body {
28 | overflow: hidden;
29 | }
30 |
31 | html,
32 | body,
33 | #root {
34 | height: 100%;
35 | font-family: 'Montserrat', sans-serif;
36 | }
--------------------------------------------------------------------------------
/src/components/Header/MenuAccountDropdown/tooltip.scss:
--------------------------------------------------------------------------------
1 | .menuAccountDropdown {
2 | &.rc-tooltip {
3 | filter: drop-shadow(0 4px 4px rgba(0, 0, 0, 0.24));
4 | box-shadow: none;
5 | }
6 | .rc-tooltip-inner {
7 | background-color: #fafafa;
8 | width: 140px;
9 | border-radius: 2px;
10 |
11 | box-shadow: none;
12 | z-index: 5;
13 | }
14 | .rc-tooltip-inner {
15 | box-shadow: none;
16 | }
17 | .rc-tooltip .rc-tooltip-content .rc-tooltip-arrow {
18 | background: none;
19 | height: 0;
20 | width: 0;
21 | top: -21px;
22 | margin-right: -7.5px;
23 | position: absolute;
24 | pointer-events: none;
25 | border: transparent 15px solid;
26 | border-bottom: #fafafa 15px solid;
27 |
28 | z-index: 1;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Report a Bug for either Gnosis Apollo, Olympia, Sight or Mainnet
4 |
5 | ---
6 |
7 | **Description**
8 | A clear and concise description of what the bug is.
9 |
10 | **To Reproduce**
11 | Steps to reproduce the behavior:
12 | 1. Go to '...'
13 | 2. Click on '....'
14 | 3. Scroll down to '....'
15 | 4. See error
16 |
17 | **Expected behavior**
18 | A clear and concise description of what you expected to happen.
19 |
20 | **Screenshots**
21 | If applicable, add screenshots to help explain your problem.
22 |
23 | **Desktop (please complete the following information):**
24 | - System [e.g. Mac with Chrome]
25 | - Build [e.g. 22]
26 |
27 | **Additional context**
28 | Add any other context about the problem here.
29 |
--------------------------------------------------------------------------------
/src/components/ModalContent/Verification/Verification.scss:
--------------------------------------------------------------------------------
1 | @import '~style/vars.scss';
2 |
3 | .verification {
4 | width: 100%;
5 | height: 100%;
6 | display: flex;
7 | flex-direction: column;
8 | justify-content: center;
9 | align-items: center;
10 | color: #fff;
11 |
12 | .heading {
13 | font-size: 21px;
14 | margin: 33px 0px 20px 0px;
15 | font-weight: 500;
16 | }
17 |
18 | .text {
19 | font-size: 14px;
20 | line-height: 1.5;
21 | }
22 |
23 | .closeButton {
24 | @include closeButton(32px, 5px);
25 | top: 20px;
26 | right: 20px;
27 | background: transparent;
28 | border: none;
29 |
30 | &:hover {
31 | &::after,
32 | &::before {
33 | background-color: #fff;
34 | }
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/routes/Scoreboard/assets/trophy.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/components/Header/MenuAccountDropdown/LogOut.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 | import cn from 'classnames/bind'
4 | import { connect } from 'react-redux'
5 | import Icon from 'components/Icon'
6 | import { logoutProvider } from 'integrations/store/actions'
7 | import style from './dropdown.scss'
8 |
9 | const cx = cn.bind(style)
10 |
11 | const LogOut = ({ logout }) => (
12 |
13 |
16 |
17 | )
18 |
19 | LogOut.propTypes = {
20 | logout: PropTypes.func.isRequired,
21 | }
22 |
23 | export default connect(
24 | null,
25 | {
26 | logout: logoutProvider,
27 | },
28 | )(LogOut)
29 |
--------------------------------------------------------------------------------
/src/components/ModalContent/OutcomePriceChanged.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { withNamespaces } from 'react-i18next'
3 | import PropTypes from 'prop-types'
4 | import cn from 'classnames/bind'
5 | import style from './TransactionsExplanation/TransactionExplanation.scss'
6 |
7 | const cx = cn.bind(style)
8 |
9 | const OutcomePriceChanged = ({ closeModal, t }) => (
10 |
11 |
12 |
13 | {t('warning.price_changed')}
14 |
15 |
16 | )
17 |
18 | OutcomePriceChanged.propTypes = {
19 | closeModal: PropTypes.func.isRequired,
20 | t: PropTypes.func.isRequired,
21 | }
22 |
23 | export default withNamespaces()(OutcomePriceChanged)
24 |
--------------------------------------------------------------------------------
/src/components/Outcome/WinningOutcome/WinningOutcome.scss:
--------------------------------------------------------------------------------
1 | .winningOutcomeContainer {
2 | display: flex;
3 | margin: 10px 0 10px 3px;
4 | align-items: center;
5 | justify-content: flex-start;
6 | text-transform: uppercase;
7 | font-weight: 500;
8 | }
9 |
10 | .winningOutcomeIcon {
11 | background: url('../../../assets/img/icons/icon_winningOutcome.svg');
12 | background-size: contain;
13 | width: 40px;
14 | height: 40px;
15 | margin-left: -10px;
16 | }
17 |
18 | .winningOutcomeLabel {
19 | color: #87949c;
20 | font-size: 12px;
21 | }
22 |
23 | .winningOutcomeText {
24 | margin-left: 10px;
25 | background-color: #87949c;
26 | color: #fff;
27 | border-radius: 6px;
28 | padding: 5px 10px;
29 | }
30 |
31 | .winningOutcomeUnit {
32 | text-transform: none;
33 | }
34 |
--------------------------------------------------------------------------------
/src/assets/img/icons/icon_cross.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
--------------------------------------------------------------------------------
/src/components/Header/Layouts/MobileHeader/BurgerIcon/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 | import cn from 'classnames/bind'
4 | import menuIcon from './assets/menu_icon.svg'
5 | import style from './BurgerIcon.scss'
6 |
7 | const cx = cn.bind(style)
8 |
9 | // the prop is called addClass because prop className is overwriteen by react-burger-menu
10 | const BurgerIcon = ({ addClass }) => (
11 |
12 |

13 |
MENU
14 |
15 | )
16 |
17 | BurgerIcon.propTypes = {
18 | addClass: PropTypes.string,
19 | }
20 |
21 | BurgerIcon.defaultProps = {
22 | addClass: '',
23 | }
24 |
25 | export default BurgerIcon
26 |
--------------------------------------------------------------------------------
/src/routes/Scoreboard/store/actions/rewards.js:
--------------------------------------------------------------------------------
1 | import { claimRewards } from 'api'
2 |
3 | import { setAccountRewardClaimState } from 'store/actions/account'
4 | import { getCurrentAccount } from 'integrations/store/selectors'
5 | import { getFeatureConfig } from 'utils/features'
6 |
7 | const { claimUntil } = getFeatureConfig('rewards')
8 |
9 | export const claimUserRewards = (contractAddress, rewardClaimAmount) => async (dispatch, getState) => {
10 | const state = getState()
11 | const account = getCurrentAccount(state)
12 | try {
13 | await claimRewards(contractAddress) // These arguments get hashed, this way we can determine if claiming is available again
14 | dispatch(setAccountRewardClaimState(account, claimUntil, rewardClaimAmount))
15 | } catch (e) {
16 | console.error(e)
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/routes/MarketDetails/components/MarketDetail/Controls/Controls.scss:
--------------------------------------------------------------------------------
1 | @import "~style/vars.scss";
2 |
3 | $expandable-arrow-size: 15px;
4 | $expandable-margin: 40px;
5 |
6 | .marketControls {
7 | &.controlsContainer {
8 | padding-top: 40px;
9 | }
10 |
11 | .button {
12 | margin-right: 20px;
13 |
14 | &.active {
15 | &:after {
16 | content: '';
17 | position: absolute;
18 | bottom: -$expandable-margin;
19 | left: 50%;
20 | margin-left: -$expandable-arrow-size;
21 | width: 0;
22 | height: 0;
23 | border-left: $expandable-arrow-size solid transparent;
24 | border-right: $expandable-arrow-size solid transparent;
25 | border-bottom: $expandable-arrow-size solid $bg-color-muted;
26 | }
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/store/middlewares/Storage/index.js:
--------------------------------------------------------------------------------
1 | import StorageLoader from './Load'
2 | import StorageDumper from './Dump'
3 |
4 | export * from './actions'
5 |
6 | const localstorageOptions = {
7 | whitelist: [
8 | 'transactions.log',
9 | 'integrations.accountSettings',
10 | 'blockchain.targetNetworkId',
11 | 'integrations.documentsAccepted',
12 | ],
13 | }
14 | export const LocalStorageDump = StorageDumper(window.localStorage, localstorageOptions)
15 | export const LocalStorageLoad = StorageLoader(window.localStorage, localstorageOptions)
16 |
17 | const sessionstorageOptions = {
18 | whitelist: ['modal'],
19 | }
20 | export const SessionStorageDump = StorageDumper(window.sessionStorage, sessionstorageOptions)
21 | export const SessionStorageLoad = StorageLoader(window.sessionStorage, sessionstorageOptions)
22 |
--------------------------------------------------------------------------------
/src/containers/HeaderContainer/store/actions.js:
--------------------------------------------------------------------------------
1 | import { requestCollateralTokenBalance } from 'store/actions/blockchain'
2 | import { openModal } from 'store/actions/modal'
3 | import { requestMainnetAddress } from 'store/actions/account'
4 |
5 | import { initProviders } from 'integrations/store/actions'
6 | import { WALLET_PROVIDER } from 'integrations/constants'
7 | import { fetchTournamentUserData } from 'routes/Scoreboard/store'
8 |
9 | export default {
10 | requestMainnetAddress,
11 | fetchTournamentUserData: accountAddress => dispatch => dispatch(fetchTournamentUserData(accountAddress)),
12 | requestTokenBalance: requestCollateralTokenBalance,
13 | openModal: modalName => dispatch => dispatch(openModal({ modalName })),
14 | initUport: () => dispatch => dispatch(initProviders({ providers: [WALLET_PROVIDER.UPORT] })),
15 | }
16 |
--------------------------------------------------------------------------------
/src/store/models/trade/index.js:
--------------------------------------------------------------------------------
1 | import { Record } from 'immutable'
2 |
3 | export const ORDER_TYPE_BUY = 'BUY'
4 | export const ORDER_TYPE_SELL = 'SELL'
5 |
6 | const TradeRecord = Record({
7 | id: undefined, // string
8 | date: undefined, // moment
9 | owner: undefined, // string
10 | price: undefined, // string (Decimal)
11 | eventAddress: undefined, // string
12 | collateralTokenAddress: undefined, // string
13 | orderType: undefined, // string oneOf 'BUY', 'SELL'
14 | marketType: undefined, // string
15 | marketTitle: undefined, // string
16 | marketResolution: undefined, // moment
17 | marketOutcomes: undefined, // List
18 | marginalPrices: undefined, // List
19 | outcomeToken: undefined, // OutcomeRecord
20 | market: undefined, // MarketRecord
21 | }, 'Trade')
22 |
23 | export default TradeRecord
24 |
--------------------------------------------------------------------------------
/src/containers/Modals/ModalSelectProvider.js:
--------------------------------------------------------------------------------
1 | import SelectProvider from 'components/ModalContent/SelectProvider'
2 | import { connect } from 'react-redux'
3 | import { getProvidersList } from 'integrations/store/selectors'
4 | import { initProviders } from 'integrations/store/actions'
5 | import { getTargetNetworkId } from 'store/selectors/blockchain'
6 | import { requestTargetNetworkId } from 'store/actions/blockchain'
7 |
8 | const mapStateToProps = state => ({
9 | providersList: getProvidersList(state),
10 | targetNetworkId: getTargetNetworkId(state),
11 | })
12 |
13 | const mapDispatchToProps = dispatch => ({
14 | requestTargetNetworkId: () => dispatch(requestTargetNetworkId()),
15 | initProviders: provider => dispatch(initProviders({ provider })),
16 | })
17 |
18 | export default connect(mapStateToProps, mapDispatchToProps)(SelectProvider)
19 |
--------------------------------------------------------------------------------
/src/routes/Dashboard/components/Dashboard/UserSection/Category.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 |
4 | import IndefiniteSpinner from 'components/Spinner/Indefinite'
5 |
6 | import classnames from 'classnames/bind'
7 | import styles from './Category.scss'
8 |
9 | const cx = classnames.bind(styles)
10 |
11 | const Category = ({ children, className, isLoading }) => (
12 |
13 | {isLoading ? : children}
14 |
15 | )
16 |
17 | Category.propTypes = {
18 | children: PropTypes.node.isRequired,
19 | className: PropTypes.oneOfType([PropTypes.string, PropTypes.array]),
20 | isLoading: PropTypes.bool,
21 | }
22 |
23 | Category.defaultProps = {
24 | className: '',
25 | isLoading: false,
26 | }
27 |
28 | export default Category
29 |
--------------------------------------------------------------------------------
/src/components/Root/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { I18nextProvider } from 'react-i18next'
3 | import { BrowserRouter } from 'react-router-dom'
4 | import { hot } from 'react-hot-loader'
5 | import BackdropProvider from 'containers/BackdropProvider'
6 | import AppContainer from 'containers/App'
7 | import store from 'store'
8 | import { Provider } from 'react-redux'
9 | import AppRouter from 'routes'
10 | import i18n from 'i18n'
11 |
12 | const RootComponent = () => (
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | )
25 |
26 | export default hot(module)(RootComponent)
27 |
--------------------------------------------------------------------------------
/src/integrations/metamask/components/UnlockMetamask/UnlockMetamask.scss:
--------------------------------------------------------------------------------
1 | @import '~style/vars.scss';
2 |
3 | .unlockMetamask {
4 | width: 100%;
5 | height: 100%;
6 | display: flex;
7 | flex-direction: column;
8 | justify-content: center;
9 | align-items: center;
10 | color: #fff;
11 |
12 | @media (max-width: 767px) {
13 | text-align: center;
14 | }
15 |
16 | .heading {
17 | font-size: 21px;
18 | margin: 33px 0px 20px 0px;
19 | font-weight: 500;
20 | }
21 |
22 | .text {
23 | font-size: 14px;
24 | line-height: 1.5;
25 | }
26 |
27 | .closeButton {
28 | @include closeButton(32px, 5px);
29 | top: 20px;
30 | right: 20px;
31 | background: transparent;
32 | border: none;
33 |
34 | &:hover {
35 | &::after,
36 | &::before {
37 | background-color: #fff;
38 | }
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/src/components/ModalContent/InitialisationError/InitialisationError.scss:
--------------------------------------------------------------------------------
1 | @import '~style/vars.scss';
2 |
3 | .initialisationError {
4 | width: 100%;
5 | height: 100%;
6 | display: flex;
7 | flex-direction: column;
8 | justify-content: center;
9 | align-items: center;
10 | color: #fff;
11 |
12 | @media (max-width: 767px) {
13 | text-align: center;
14 | }
15 |
16 | .heading {
17 | font-size: 21px;
18 | margin: 33px 0px 20px 0px;
19 | font-weight: 500;
20 | }
21 |
22 | .text {
23 | font-size: 14px;
24 | line-height: 1.5;
25 | }
26 |
27 | .closeButton {
28 | @include closeButton(32px, 5px);
29 | top: 20px;
30 | right: 20px;
31 | background: transparent;
32 | border: none;
33 |
34 | &:hover {
35 | &::after,
36 | &::before {
37 | background-color: #fff;
38 | }
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/routes/MarketDetails/api/sellShares.js:
--------------------------------------------------------------------------------
1 | import * as api from 'api'
2 | import Decimal from 'decimal.js'
3 | import { hexWithPrefix } from 'utils/helpers'
4 |
5 | const sellShares = async (marketAddress, outcomeTokenIndex, outcomeTokenCount, earnings, approvalResetAmount) => {
6 | const gnosis = await api.getGnosisConnection()
7 |
8 | const outcomeTokenCountWei = Decimal(outcomeTokenCount)
9 | .mul(1e18)
10 | .toString()
11 | const minProfit = Decimal(earnings)
12 | .mul(1e18)
13 | .round()
14 | .toString()
15 |
16 | const collateralTokensReceived = await gnosis.sellOutcomeTokens({
17 | market: hexWithPrefix(marketAddress),
18 | outcomeTokenIndex,
19 | outcomeTokenCount: outcomeTokenCountWei,
20 | minProfit,
21 | approvalResetAmount,
22 | })
23 |
24 | return collateralTokensReceived
25 | }
26 |
27 | export default sellShares
28 |
--------------------------------------------------------------------------------
/src/routes/GameGuide/components/LayoutMetamask.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PageFrame from 'components/layout/PageFrame'
3 | import Title from 'components/layout/Title'
4 | import SignUp from './metamaskComponents/SignUp'
5 | import MarketOverview from './metamaskComponents/MarketOverview'
6 | import DashboardOverview from './metamaskComponents/DashboardOverview'
7 | import MakePrediction from './metamaskComponents/MakePrediction'
8 | import Profits from './metamaskComponents/ProfitsAndScoreboard'
9 | import ClaimRewards from './metamaskComponents/ClaimRewards'
10 |
11 | const GameGuide = () => (
12 |
13 | GAME GUIDE
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | )
22 |
23 | export default GameGuide
24 |
--------------------------------------------------------------------------------
/src/containers/Modals/index.js:
--------------------------------------------------------------------------------
1 | export { default as ModalOutcomePriceChanged } from './ModalOutcomePriceChanged'
2 | export { default as ModalTransactionExplanation } from './ModalTransactionExplanation'
3 | export { default as ModalInstallProvider } from './ModalInstallProvider'
4 | export { default as ModalRegisterWallet } from './ModalRegisterWallet'
5 | export { default as ModalRegisterWalletUport } from './ModalRegisterWalletUport'
6 | export { default as ModalClaimReward } from './ModalClaimReward'
7 | export { default as ModalAcceptTOS } from './ModalAcceptTOS'
8 | export { default as ModalVerification } from './ModalVerification'
9 | export { default as ModalSelectProvider } from './ModalSelectProvider'
10 | export { default as ModalInitialisationError } from './ModalInitialisationError'
11 | export { default as ModalUnlockMetamask } from 'integrations/metamask/components/UnlockMetamask'
12 |
--------------------------------------------------------------------------------
/src/routes/Scoreboard/components/Layout.scss:
--------------------------------------------------------------------------------
1 | @import '~style/vars.scss';
2 |
3 | .rewardContainer {
4 | display: flex;
5 |
6 | @media (max-width: $screen-sm) {
7 | flex-direction: column;
8 | }
9 | }
10 |
11 | .trophy {
12 | display: flex;
13 | flex-direction: row;
14 | flex-wrap: nowrap;
15 | align-items: center;
16 |
17 | & img {
18 | width: 48px;
19 | height: 46px;
20 | }
21 |
22 | & p {
23 | font-size: 44px;
24 | margin: 0 0 0 10px;
25 | font-family: Montserrat;
26 | font-size: 42px;
27 | font-weight: 300;
28 | text-align: left;
29 | color: #333333;
30 | }
31 | }
32 |
33 | .explanation {
34 | font-size: 12px;
35 | line-height: 14px;
36 | text-align: left;
37 | }
38 |
39 | .norows {
40 | text-align: center;
41 | font-family: Montserrat;
42 | font-size: 18px;
43 | color: #626262;
44 | margin: 10px 0px;
45 | }
46 |
--------------------------------------------------------------------------------
/src/routes/Dashboard/components/Dashboard/Title/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 | import { withNamespaces } from 'react-i18next'
4 |
5 | import classname from 'classnames/bind'
6 | import style from './DashboardTitle.scss'
7 |
8 | const cx = classname.bind(style)
9 |
10 | const Title = ({ t }) => (
11 |
12 |
13 |
14 |
15 |
16 |
{t('header.dashboard')}
17 |
18 |
19 |
20 |
21 |
22 | )
23 |
24 | Title.propTypes = {
25 | t: PropTypes.func.isRequired,
26 | }
27 |
28 | export default withNamespaces()(Title)
29 |
--------------------------------------------------------------------------------
/src/store/models/market/scalar.js:
--------------------------------------------------------------------------------
1 | import { Record } from 'immutable'
2 | import { OUTCOME_TYPES } from 'utils/constants'
3 |
4 | const ScalarMarketRecord = Record({
5 | type: OUTCOME_TYPES.SCALAR,
6 | address: undefined,
7 | title: undefined, // string
8 | description: undefined, // string
9 | resolution: undefined, // moment
10 | volume: undefined, // decimal
11 | bounds: undefined, // BoundRecord
12 | eventAddress: undefined, // string
13 | winningOutcome: undefined, // int
14 | funding: undefined, // int
15 | creation: undefined, // moment
16 | stage: undefined,
17 | fee: undefined, // int
18 | resolved: undefined, // boolean
19 | closed: undefined, // boolean
20 | creator: undefined, // string
21 | collateralToken: undefined, // string
22 | outcomeTokensSold: undefined, // List
23 | outcomes: undefined,
24 | }, 'Market')
25 |
26 | export default ScalarMarketRecord
27 |
--------------------------------------------------------------------------------
/src/components/Header/Layouts/DesktopHeader/components/WrongNetwork/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 | import Icon from 'components/Icon'
4 | import classnames from 'classnames/bind'
5 | import Tooltip from 'rc-tooltip'
6 |
7 | import styles from './WrongNetwork.scss'
8 |
9 | const cx = classnames.bind(styles)
10 |
11 | const wrongNetworkIconStyle = {
12 | width: 20,
13 | height: 20,
14 | }
15 |
16 | const WrongNetwork = ({ targetNetwork }) => (
17 | You're connected to the wrong network. Please connect to the {targetNetwork} network.}
20 | >
21 |
22 |
23 | )
24 |
25 | WrongNetwork.propTypes = {
26 | targetNetwork: PropTypes.string.isRequired,
27 | }
28 |
29 | export default WrongNetwork
30 |
--------------------------------------------------------------------------------
/src/components/Outcome/OutcomeColorBox/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import cn from 'classnames/bind'
3 | import PropTypes from 'prop-types'
4 |
5 | import { COLOR_SCHEME_DEFAULT, COLOR_SCHEME_SCALAR, OUTCOME_TYPES } from 'utils/constants'
6 |
7 | import styles from './OutcomeColorBox.scss'
8 |
9 | const cx = cn.bind(styles)
10 |
11 | const COLOR_SCHEMES = {
12 | [OUTCOME_TYPES.SCALAR]: COLOR_SCHEME_SCALAR,
13 | [OUTCOME_TYPES.CATEGORICAL]: COLOR_SCHEME_DEFAULT,
14 | }
15 |
16 | const OutcomeColorBox = ({ outcomeIndex, scheme }) => ()
17 |
18 | OutcomeColorBox.propTypes = {
19 | outcomeIndex: PropTypes.number.isRequired,
20 | scheme: PropTypes.string,
21 | }
22 |
23 | OutcomeColorBox.defaultProps = {
24 | scheme: OUTCOME_TYPES.CATEGORICAL,
25 | }
26 |
27 | export default OutcomeColorBox
28 |
--------------------------------------------------------------------------------
/src/components/layout/Block/index.js:
--------------------------------------------------------------------------------
1 | import classNames from 'classnames/bind'
2 | import PropTypes from 'prop-types'
3 | import React, { PureComponent } from 'react'
4 | import css from './index.scss'
5 |
6 | const cx = classNames.bind(css)
7 |
8 | class Block extends PureComponent {
9 | get blockStyle() {
10 | return {
11 | width: this.props.width,
12 | }
13 | }
14 |
15 | render() {
16 | const {
17 | margin, center, children, className, ...props
18 | } = this.props
19 |
20 | return (
21 |
22 | {children}
23 |
24 | )
25 | }
26 | }
27 |
28 | Block.propTypes = {
29 | width: PropTypes.string,
30 | margin: PropTypes.string,
31 | center: PropTypes.bool,
32 | children: PropTypes.node,
33 | className: PropTypes.string,
34 | }
35 |
36 | export default Block
37 |
--------------------------------------------------------------------------------
/src/routes/MarketList/components/Markets/Market/MarketTrading.js:
--------------------------------------------------------------------------------
1 | import CurrencyName from 'components/CurrencyName'
2 | import PropTypes from 'prop-types'
3 | import React from 'react'
4 | import classNames from 'classnames/bind'
5 | import { hexWithPrefix } from 'utils/helpers'
6 |
7 | import Icon from 'components/Icon'
8 |
9 | import css from './Market.scss'
10 |
11 | const cx = classNames.bind(css)
12 |
13 | const MarketTrading = ({ volume, collateralToken }) => (
14 |
15 |
16 |
17 | {volume} {collateralToken && } Volume
18 |
19 |
20 | )
21 |
22 | MarketTrading.propTypes = {
23 | volume: PropTypes.string.isRequired,
24 | collateralToken: PropTypes.string.isRequired,
25 | }
26 |
27 | export default MarketTrading
28 |
--------------------------------------------------------------------------------
/src/store/models/market/categorical.js:
--------------------------------------------------------------------------------
1 | import { Record } from 'immutable'
2 | import { OUTCOME_TYPES } from 'utils/constants'
3 |
4 | const CategoricalMarketRecord = Record({
5 | type: OUTCOME_TYPES.CATEGORICAL,
6 | address: undefined,
7 | title: undefined, // string
8 | description: undefined, // string
9 | resolution: undefined, // moment
10 | volume: undefined, // decimal
11 | outcomes: undefined, // List
12 | eventAddress: undefined, // string
13 | winningOutcome: undefined, // OutcomeRecord
14 | funding: undefined, // int
15 | creation: undefined, // moment
16 | stage: undefined,
17 | fee: undefined, // int
18 | resolved: undefined, // boolean
19 | closed: undefined, // boolean
20 | creator: undefined, // string
21 | collateralToken: undefined, // string
22 | outcomeTokensSold: undefined, // List
23 | }, 'Market')
24 |
25 | export default CategoricalMarketRecord
26 |
--------------------------------------------------------------------------------
/src/components/Outcome/OutcomeScalar/TrendingOutcomeScalar/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 | import Decimal from 'decimal.js'
4 | import DecimalValue from 'components/DecimalValue'
5 |
6 | const TrendingOutcomeScalar = ({ predictedValue, unit, decimals }) => (
7 |
8 |
9 |
10 | {unit}
11 |
12 |
13 | )
14 |
15 | TrendingOutcomeScalar.propTypes = {
16 | predictedValue: PropTypes.instanceOf(Decimal),
17 | unit: PropTypes.string,
18 | decimals: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
19 | }
20 |
21 | TrendingOutcomeScalar.defaultProps = {
22 | predictedValue: Decimal(0),
23 | unit: '',
24 | decimals: 0,
25 | }
26 |
27 | export default TrendingOutcomeScalar
28 |
--------------------------------------------------------------------------------
/src/routes/MarketDetails/components/ExpandableViews/MarketMyTrades/marketMyTrades.scss:
--------------------------------------------------------------------------------
1 | @import '~style/vars.scss';
2 |
3 | $indexWidth: 36px;
4 | $groupWidth: 20%;
5 |
6 | .marketMyTrades {
7 | .shareTable {
8 | margin-top: 20px;
9 | table-layout: fixed;
10 | }
11 |
12 | .shareTableRow {
13 | vertical-align: middle;
14 |
15 | td {
16 | vertical-align: middle !important;
17 | border-top: 1px solid #ddd;
18 |
19 | &:first-of-type {
20 | border-top: 0;
21 | }
22 | }
23 | }
24 | }
25 |
26 | .shareOutcomeColor {
27 | display: inline-block;
28 | vertical-align: middle;
29 |
30 | width: 20px;
31 | height: 20px;
32 |
33 | border-radius: 4px;
34 | }
35 |
36 | .tableHeading {
37 | &.first {
38 | width: 36px;
39 | }
40 |
41 | font-weight: 400;
42 | text-transform: uppercase;
43 | color: #a3adb3;
44 | border-bottom: none !important;
45 | }
46 |
--------------------------------------------------------------------------------
/src/routes/Transactions/components/Transactions/Transaction/DetailLabel/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 | import cn from 'classnames/bind'
4 | import moment from 'moment'
5 | import { RESOLUTION_TIME } from 'utils/constants'
6 | import style from './DetailLabel.scss'
7 |
8 | const cx = cn.bind(style)
9 |
10 | const DetailLabel = ({ label, date, children }) => (
11 |
12 |
{label}
13 | {children || moment(date).format(RESOLUTION_TIME.ABSOLUTE_FORMAT)}
14 |
15 | )
16 |
17 | DetailLabel.propTypes = {
18 | label: PropTypes.string,
19 | date: PropTypes.string,
20 | children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]),
21 | }
22 |
23 | DetailLabel.defaultProps = {
24 | label: ,
25 | date: undefined,
26 | children: undefined,
27 | }
28 |
29 | export default DetailLabel
30 |
--------------------------------------------------------------------------------
/src/routes/Transactions/containers/TransactionsPage/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import { withRouter } from 'react-router-dom'
3 | import { compose, withProps } from 'recompose'
4 |
5 | import { getRunningTransactions, getCompletedTransactions } from 'routes/Transactions/store/selectors/transactions'
6 | import { getCurrentAccount } from 'integrations/store/selectors'
7 | import Transactions from '../../components/Transactions'
8 |
9 | const mapStateToProps = state => ({
10 | currentAccount: getCurrentAccount(state),
11 | runningTransactions: getRunningTransactions(state),
12 | completedTransactions: getCompletedTransactions(state),
13 | })
14 |
15 | const enhancer = compose(
16 | withRouter,
17 | withProps(({ history }) => ({
18 | changeUrl: url => history.push(url),
19 | })),
20 | connect(
21 | mapStateToProps,
22 | ),
23 | )
24 |
25 | export default enhancer(Transactions)
26 |
--------------------------------------------------------------------------------
/src/routes/Scoreboard/components/Layout.stories.js:
--------------------------------------------------------------------------------
1 | import { text } from '@storybook/addon-knobs'
2 | import { storiesOf } from '@storybook/react'
3 | import * as React from 'react'
4 | import users from 'stories/knobs/scoreboardUsers'
5 | import { host } from 'storybook-host'
6 | import Layout from './Layout'
7 |
8 | storiesOf('Route ScoreBoard', module)
9 | .addDecorator(host({
10 | title: 'ScoreBoard ',
11 | align: 'center',
12 | height: 720,
13 | }))
14 | .add('Account in the first 10 positions ', () => {
15 | const data = users
16 | const myWallet = text('User account', '0x90F8bf6A479f320ead074411a4B0e7944Ea8ca007')
17 |
18 | return (
19 |
20 | )
21 | })
22 | .add('Account NOT in the first 10 positions ', () => {
23 | const data = users
24 |
25 | return (
26 |
27 | )
28 | })
29 |
--------------------------------------------------------------------------------
/src/components/Header/BadgeIcon.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Tooltip from 'rc-tooltip'
3 | import PropTypes from 'prop-types'
4 | import Icon from 'components/Icon'
5 | import { badgeOf } from 'routes/Scoreboard/components/Table/ScoreTable/table'
6 |
7 | const BadgeIcon = ({ userTournamentInfo }) => {
8 | let predictionsAmount = 0
9 |
10 | if (userTournamentInfo) {
11 | predictionsAmount = userTournamentInfo.predictions
12 | }
13 |
14 | const badge = badgeOf(predictionsAmount)
15 |
16 | if (!badge) {
17 | return null
18 | }
19 |
20 | return (
21 |
22 |
23 |
24 | )
25 | }
26 |
27 | BadgeIcon.propTypes = {
28 | userTournamentInfo: PropTypes.shape({}),
29 | }
30 |
31 | BadgeIcon.defaultProps = {
32 | userTournamentInfo: {},
33 | }
34 |
35 | export default BadgeIcon
36 |
--------------------------------------------------------------------------------
/src/routes/Dashboard/assets/shape.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/routes/MarketDetails/components/ExpandableViews/MarketBuySharesForm/OutcomesSection/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { marketShape } from 'utils/shapes'
3 | import { OUTCOME_TYPES } from 'utils/constants'
4 | import OutcomesSectionCategorical from './OutcomesSectionCategorical'
5 | import OutcomesSectionScalar from './OutcomeSectionScalar'
6 |
7 | const BuySharesOutcomeSection = (props) => {
8 | const {
9 | market: { type },
10 | } = props
11 | if (type === OUTCOME_TYPES.CATEGORICAL) {
12 | return
13 | }
14 |
15 | if (type === OUTCOME_TYPES.SCALAR) {
16 | return
17 | }
18 |
19 | return
20 | }
21 |
22 | BuySharesOutcomeSection.propTypes = {
23 | market: marketShape,
24 | }
25 |
26 | BuySharesOutcomeSection.defaultProps = {
27 | market: {
28 | event: {},
29 | },
30 | }
31 |
32 | export default BuySharesOutcomeSection
33 |
--------------------------------------------------------------------------------
/src/components/Form/TextInputAdornment.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 | import className from 'classnames/bind'
4 |
5 | import styles from './TextInputAdornment.scss'
6 |
7 | const cx = className.bind(styles)
8 |
9 | const TextInputAdornment = ({ children, position, style }) => {
10 | const textInputAdornmentClasses = cx('adornment', {
11 | end: position === 'end',
12 | start: position === 'start',
13 | })
14 |
15 | return (
16 |
17 | {children}
18 |
19 | )
20 | }
21 |
22 | TextInputAdornment.propTypes = {
23 | children: PropTypes.node,
24 | position: PropTypes.oneOf(['end', 'start']),
25 | // eslint-disable-next-line
26 | style: PropTypes.object,
27 | }
28 |
29 | TextInputAdornment.defaultProps = {
30 | children: undefined,
31 | position: undefined,
32 | style: {},
33 | }
34 |
35 | export default TextInputAdornment
36 |
--------------------------------------------------------------------------------
/src/api/market.js:
--------------------------------------------------------------------------------
1 | import Gnosis from '@gnosis.pm/pm-js/'
2 | import { OUTCOME_TYPES } from 'utils/constants'
3 | import { getGnosisConnection } from 'api'
4 |
5 | export const resolveEvent = async (event, selectedOutcomeIndex) => {
6 | const gnosis = await getGnosisConnection()
7 |
8 | await gnosis.resolveEvent({ event: event.address, outcome: parseInt(selectedOutcomeIndex, 10) })
9 | }
10 |
11 | export const redeemWinnings = async (eventType, eventAddress) => {
12 | const gnosis = await getGnosisConnection()
13 |
14 | const eventContract = eventType === OUTCOME_TYPES.CATEGORICAL
15 | ? await gnosis.contracts.CategoricalEvent.at(eventAddress)
16 | : await gnosis.contracts.ScalarEvent.at(eventAddress)
17 |
18 | if (eventContract) {
19 | return Gnosis.requireEventFromTXResult(await eventContract.redeemWinnings(), 'WinningsRedemption')
20 | }
21 | throw new Error("Invalid Event - can't find the specified Event, invalid Eventtype?")
22 | }
23 |
--------------------------------------------------------------------------------
/src/utils/analytics/google/index.js:
--------------------------------------------------------------------------------
1 | /* globals ga */
2 | import { getThirdPartyConfig } from 'utils/features'
3 |
4 | export const THIRD_PARTY_ID = 'googleAnalytics'
5 |
6 | const { id } = getThirdPartyConfig(THIRD_PARTY_ID)
7 |
8 | const GOOGLE_ANALYTICS_URL = 'https://www.google-analytics.com/analytics.js'
9 |
10 | export const ga = (...args) => (window.ga && window.ga.q && window.ga.q(...args))
11 | || (window.ga && window.ga(...args))
12 | || (() => {})(...args) // no-op
13 |
14 | const loadGoogleAnalytics = () => new Promise((resolve) => {
15 | const script = document.createElement('script')
16 | script.src = GOOGLE_ANALYTICS_URL
17 | script.type = 'text/javascript'
18 |
19 | document.head.appendChild(script)
20 |
21 | script.onload = () => {
22 | ga('create', id, 'auto')
23 | ga('send', 'pageview')
24 |
25 | resolve()
26 | }
27 | })
28 |
29 | export const gaSend = (...args) => ga(id, ...args)
30 |
31 | export default loadGoogleAnalytics
32 |
--------------------------------------------------------------------------------
/src/setup.js:
--------------------------------------------------------------------------------
1 | import moment from 'moment'
2 | import momentDurationFormatSetup from 'moment-duration-format'
3 |
4 | export const setMomentRelativeTime = () => {
5 | moment.updateLocale('en', {
6 | relativeTime: {
7 | future: '%s',
8 | past: '%s ago',
9 | s: '< 59s',
10 | ss: '> %d s',
11 | m: '< 59m',
12 | mm: '> %d m',
13 | h: '< 1h',
14 | hh: '> %d h',
15 | d: '< 1d',
16 | dd: '< %d d',
17 | M: 'a month',
18 | MM: '%d months',
19 | y: 'a year',
20 | yy: '%d years',
21 | },
22 | })
23 |
24 | // Set new thresholds
25 | moment.relativeTimeThreshold('ss', 3)
26 | moment.relativeTimeThreshold('s', 59)
27 | moment.relativeTimeThreshold('m', 59)
28 | moment.relativeTimeThreshold('h', 20)
29 | moment.relativeTimeThreshold('d', 25)
30 | moment.relativeTimeThreshold('M', 10)
31 | }
32 |
33 | export const setMomentDurationFormat = () => {
34 | momentDurationFormatSetup(moment)
35 | }
36 |
--------------------------------------------------------------------------------
/src/routes/MarketList/components/MarketStats/MarketStats.scss:
--------------------------------------------------------------------------------
1 | @import '~style/vars.scss';
2 |
3 | .marketStats {
4 | width: 100%;
5 | margin-bottom: 96px;
6 |
7 | .inner {
8 | width: 100%;
9 | max-width: 100%;
10 | display: flex;
11 | flex-flow: row wrap;
12 | justify-content: space-between;
13 |
14 | @media (max-width: $screen-sm) {
15 | flex-direction: column;
16 | align-items: baseline;
17 | }
18 |
19 | .stat {
20 | margin-bottom: 12px;
21 | width: auto;
22 |
23 | .content {
24 | margin-left: 20px;
25 | float: left;
26 | }
27 |
28 | .value {
29 | font-size: 28px;
30 | font-weight: 300;
31 | letter-spacing: 1px;
32 | }
33 |
34 | .label {
35 | color: $font-color-light;
36 | opacity: .6;
37 | text-transform: uppercase;
38 | font-size: 10px;
39 | letter-spacing: .5px;
40 | }
41 | }
42 | }
43 |
44 | }
--------------------------------------------------------------------------------
/src/routes/Dashboard/components/Dashboard/Markets/Category.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 | import classnames from 'classnames/bind'
4 |
5 | import { marketRecordListShape } from 'utils/shapes'
6 | import ConditionalList from './ConditionalList'
7 |
8 | import style from './Category.scss'
9 |
10 | const cx = classnames.bind(style)
11 |
12 | const Category = ({
13 | markets, title, viewMarket, component: MarketComponent,
14 | }) => (
15 |
19 | )
20 |
21 | Category.propTypes = {
22 | title: PropTypes.string.isRequired,
23 | viewMarket: PropTypes.func.isRequired,
24 | component: PropTypes.func.isRequired,
25 | markets: marketRecordListShape,
26 | }
27 |
28 | Category.defaultProps = {
29 | markets: undefined,
30 | }
31 |
32 | export default Category
33 |
--------------------------------------------------------------------------------
/src/utils/analytics/index.js:
--------------------------------------------------------------------------------
1 | import { isThirdPartyIntegrationEnabled, getThirdPartyConfig } from 'utils/features'
2 |
3 | import loadGoogleAnalytics, { THIRD_PARTY_ID as GOOGLE_ANALYTICS } from './google'
4 | import loadIntercom, { THIRD_PARTY_ID as INTERCOM } from './intercom'
5 |
6 | export const THIRD_PARTY_INTEGRATIONS = {
7 | [GOOGLE_ANALYTICS]: loadGoogleAnalytics,
8 | [INTERCOM]: loadIntercom,
9 | }
10 |
11 | const initAnalytics = () => {
12 | Object.keys(THIRD_PARTY_INTEGRATIONS).forEach((THIRD_PARTY_ID) => {
13 | if (isThirdPartyIntegrationEnabled(THIRD_PARTY_ID)) {
14 | const init = THIRD_PARTY_INTEGRATIONS[THIRD_PARTY_ID]
15 | const thirdPartyConfig = getThirdPartyConfig(THIRD_PARTY_ID)
16 |
17 | // console.info(`Loading third party: ${THIRD_PARTY_ID}`)
18 | init(thirdPartyConfig).then(() => {
19 | // console.info(`Finished loading third party: ${THIRD_PARTY_ID}`)
20 | })
21 | }
22 | })
23 | }
24 |
25 | export default initAnalytics
26 |
--------------------------------------------------------------------------------
/src/store/reducers/notifications/index.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from 'redux-actions'
2 | import { Map, List } from 'immutable'
3 | import { showNotification, fadeOutNotification, hideAllNotifications } from 'store/actions/notifications'
4 | import NotificationRecord from 'store/reducers/notifications/models/notification'
5 |
6 | const reducer = handleActions(
7 | {
8 | [showNotification]: (state, action) =>
9 | state.withMutations((stateMap) => {
10 | stateMap.update('currentVisible', value => value.push(action.payload.id))
11 | stateMap.setIn(['log', action.payload.id], new NotificationRecord(action.payload))
12 | }),
13 | [fadeOutNotification]: (state, action) =>
14 | state.update('currentVisible', value => value.filter(id => id !== action.payload.id)),
15 | [hideAllNotifications]: state => state.set('currentVisible', List()),
16 | },
17 | Map({
18 | log: Map(),
19 | currentVisible: List(),
20 | }),
21 | )
22 |
23 | export default reducer
24 |
--------------------------------------------------------------------------------
/src/assets/img/icons/icon_winningOutcome.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/components/Header/Layouts/MobileHeader/AccountOverview/AccountOverview.scss:
--------------------------------------------------------------------------------
1 | .overviewContainer {
2 | text-align: center;
3 | margin-bottom: 30px;
4 |
5 | .identicon {
6 | width: 90px;
7 | height: 90px;
8 |
9 | border-radius: 50%;
10 | border: 1px solid white;
11 | }
12 |
13 | .networkBalanceWrapper {
14 | display: flex;
15 | margin-bottom: 10px;
16 |
17 | & > div {
18 | line-height: 1;
19 | margin-top: -1px;
20 | }
21 |
22 | span {
23 | font-size: 15px;
24 | font-weight: bold;
25 | }
26 |
27 | .network {
28 | margin-right: auto;
29 | }
30 | }
31 |
32 | .addressWrapper {
33 | margin-top: 10px;
34 | .address {
35 | padding: 0;
36 | border: 0;
37 | background: transparent;
38 | color: #b8b7ad;
39 | font-size: 16px;
40 |
41 | &:focus,
42 | &:hover {
43 | color: darken($color: #b8b7ad, $amount: 20);
44 | outline: 0;
45 | }
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/routes/MarketDetails/store/actions/requestGasCost.js:
--------------------------------------------------------------------------------
1 | import { GAS_COST } from 'utils/constants'
2 | import { createAction } from 'redux-actions'
3 | import { calcBuySharesGasCost, calcSellSharesGasCost, calcRedeemWinningsGasCost } from '../../api'
4 |
5 | const setGasCost = createAction('SET_GAS_COST')
6 |
7 | const requestGasCost = (contractType, opts) => async (dispatch) => {
8 | if (contractType === GAS_COST.BUY_SHARES) {
9 | const gasCost = await calcBuySharesGasCost()
10 | dispatch(setGasCost({ entityType: 'gasCosts', contractType, gasCost }))
11 | } else if (contractType === GAS_COST.SELL_SHARES) {
12 | const gasCost = await calcSellSharesGasCost()
13 | dispatch(setGasCost({ entityType: 'gasCosts', contractType, gasCost }))
14 | } else if (contractType === GAS_COST.REDEEM_WINNINGS) {
15 | const gasCost = await calcRedeemWinningsGasCost(opts)
16 | dispatch(setGasCost({ entityType: 'gasCosts', contractType, gasCost }))
17 | }
18 | }
19 |
20 | export { requestGasCost, setGasCost }
21 |
--------------------------------------------------------------------------------
/src/routes/Scoreboard/components/RewardClaimAddress/RewardClaim.scss:
--------------------------------------------------------------------------------
1 | @import '~style/vars.scss';
2 |
3 | .rewardClaim {
4 | width: 350px;
5 | height: 110px;
6 | border-radius: 2px;
7 | background-color: #ffffff;
8 | box-shadow: 0 0 6px 0 rgba(0, 0, 0, 0.11);
9 | word-break: break-all;
10 | margin-bottom: 20px;
11 |
12 | display: flex;
13 |
14 | @media (max-width: $screen-sm) {
15 | width: 100%;
16 | }
17 |
18 | .iconSection {
19 | background-color: #f0f1f1;
20 | width: 60px;
21 | flex-shrink: 0;
22 | flex-grow: 0;
23 |
24 | display: flex;
25 | justify-content: center;
26 | align-items: center;
27 | }
28 |
29 | p {
30 | font-size: 14px;
31 | margin: 0;
32 | }
33 |
34 | .loadingSection {
35 | display: flex;
36 | justify-content: center;
37 | align-items: center;
38 | width: 100%;
39 | height: 118px;
40 | }
41 |
42 | a,
43 | a:link,
44 | a:visited {
45 | color: #00a6c4;
46 | text-decoration: underline;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/store/utils/marketStatus.js:
--------------------------------------------------------------------------------
1 | import moment from 'moment'
2 | import { MARKET_STAGES } from 'store/models'
3 |
4 | export const isMarketClosed = ({ stage, resolution }) => {
5 | const stageClosed = stage !== MARKET_STAGES.MARKET_FUNDED
6 | const marketExpired = moment.utc(resolution).isBefore(moment.utc())
7 |
8 | const marketClosed = stageClosed || marketExpired
9 | return marketClosed
10 | }
11 |
12 | export const isMarketEndingSoon = (resolutionDate) => {
13 | const threeDays = moment.utc().add(3, 'days')
14 | return moment.utc(resolutionDate).isSameOrBefore(threeDays)
15 | }
16 |
17 | export const isNewMarket = (creation) => {
18 | const threeDaysAgo = moment.utc().subtract(3, 'days')
19 |
20 | return threeDaysAgo.isBefore(creation)
21 | }
22 |
23 | export const isMarketResolved = ({ resolved }) => resolved
24 |
25 | export const isMarketClosedOrResolved = market => isMarketClosed(market) || isMarketResolved(market)
26 |
27 | export const isMarketFunded = stage => stage > MARKET_STAGES.MARKET_CREATED
28 |
--------------------------------------------------------------------------------
/src/store/middlewares/Storage/Load.js:
--------------------------------------------------------------------------------
1 | import * as actions from './actions'
2 | import { NOOP_MIDDLEWARE, STORAGE_KEY } from './constants'
3 |
4 | const middleware = (storage) => {
5 | const storageIsValid = storage instanceof Storage
6 |
7 | if (!storageIsValid) {
8 | console.warn('StorageLoader: Storage is either not supported or invalid')
9 | return NOOP_MIDDLEWARE
10 | }
11 |
12 | return store => next => (action) => {
13 | const { type } = action
14 | if (type === 'INIT') {
15 | const stringPayload = storage.getItem(STORAGE_KEY)
16 | if (stringPayload) {
17 | let payload
18 | try {
19 | const decoded = Buffer.from(stringPayload, 'base64').toString('ascii')
20 | payload = JSON.parse(decoded)
21 | store.dispatch(actions.loadStorage(payload))
22 | } catch (e) {
23 | console.error('Could not load saved storage: ', e)
24 | }
25 | }
26 | }
27 |
28 | next(action)
29 | }
30 | }
31 |
32 | export default middleware
33 |
--------------------------------------------------------------------------------
/src/routes/MarketDetails/components/MarketDetail/Details/RedeemWinnings/RedeemWinnings.scss:
--------------------------------------------------------------------------------
1 | @import '~style/vars.scss';
2 |
3 | .redeemWinning {
4 | display: flex;
5 | flex-direction: column;
6 | max-width: 267px;
7 | margin: 20px 0;
8 |
9 | .detailsContainer {
10 | display: flex;
11 | align-items: center;
12 |
13 | .details {
14 | padding-left: 10px;
15 | }
16 |
17 | .heading {
18 | font-size: 30px;
19 | }
20 |
21 | .label {
22 | text-transform: uppercase;
23 | color: $font-color-muted;
24 | font-size: 10px;
25 | font-weight: 500;
26 | letter-spacing: 0.5px;
27 | }
28 | }
29 |
30 | .action {
31 | text-align: center;
32 | margin-top: 20px;
33 | .redeemButton {
34 | padding: 10px;
35 | height: auto;
36 | width: 100%;
37 | text-align: center;
38 | line-height: 1;
39 | }
40 | }
41 |
42 | .gasCost {
43 | margin-top: 5px;
44 | display: inline-block;
45 | color: $font-color-muted;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/routes/MarketDetails/store/selectors/getMarketShares.js:
--------------------------------------------------------------------------------
1 | import { getCurrentAccount } from 'integrations/store/selectors'
2 | import Decimal from 'decimal.js'
3 | import { createSelector } from 'reselect'
4 | import { sharesWithMarketsSelector } from 'store/selectors/account/shares'
5 | import { hexWithoutPrefix } from 'utils/helpers'
6 | import { calcShareWinnings } from 'routes/Dashboard/containers/Dashboard/utils'
7 |
8 | const getMarketShares = marketAddress => createSelector(sharesWithMarketsSelector, getCurrentAccount, (shares, account) => shares
9 | .filter(
10 | share => Decimal(share.balance).gt(0)
11 | && share.owner === hexWithoutPrefix(account)
12 | && share.market?.address === marketAddress,
13 | )
14 | .map((share) => {
15 | let shareWinnings = '0'
16 |
17 | if (share.market.resolved) {
18 | shareWinnings = calcShareWinnings(share, share.market)
19 | }
20 |
21 | return share.set('winnings', shareWinnings)
22 | })
23 | .toList())
24 |
25 | export default getMarketShares
26 |
--------------------------------------------------------------------------------
/src/routes/MarketDetails/components/ExpandableViews/MarketMyTrades/TableHeader/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import cn from 'classnames/bind'
3 | import PropTypes from 'prop-types'
4 | import { withNamespaces } from 'react-i18next'
5 | import style from '../marketMyTrades.scss'
6 |
7 | const cx = cn.bind(style)
8 |
9 | const TableHeader = ({ t }) => (
10 |
11 |
12 | |
13 | {t('market.order_type')} |
14 | {t('market.outcome')} |
15 | {t('market.outcome_count')} |
16 | {t('market.avg_price')} |
17 | {t('market.date')} |
18 | {t('market.cost')} |
19 |
20 |
21 | )
22 |
23 | TableHeader.propTypes = {
24 | t: PropTypes.func.isRequired,
25 | }
26 |
27 | export default withNamespaces()(TableHeader)
28 |
--------------------------------------------------------------------------------
/src/assets/verification/onfido/id-type-driverlicense.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/components/ModalContent/InstallProvider/InstallProvider.scss:
--------------------------------------------------------------------------------
1 | @import '~style/vars.scss';
2 |
3 | .installProvider {
4 | width: 100%;
5 | height: 100%;
6 | display: flex;
7 | flex-direction: column;
8 | justify-content: center;
9 | align-items: center;
10 | color: #fff;
11 |
12 | @media (max-width: 767px) {
13 | text-align: center;
14 | }
15 |
16 | .installText {
17 | font-size: 21px;
18 | margin: 33px 0px 20px 0px;
19 | font-weight: 500;
20 | }
21 |
22 | .downloadText {
23 | font-size: 14px;
24 | line-height: 1.5;
25 |
26 | .downloadLink {
27 | &:hover {
28 | color: #fff;
29 | opacity: 0.6;
30 | }
31 |
32 | text-decoration: underline;
33 | }
34 | }
35 |
36 | .closeButton {
37 | @include closeButton(32px, 5px);
38 | top: 20px;
39 | right: 20px;
40 | background: transparent;
41 | border: none;
42 |
43 | &:hover {
44 | &::after,
45 | &::before {
46 | background-color: #fff;
47 | }
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/assets/badges/crystal-gazer.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/src/components/ModalContent/Verification/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 | import { withNamespaces } from 'react-i18next'
4 |
5 | import VerificationHandler from 'verification'
6 |
7 | import classnames from 'classnames/bind'
8 | import styles from './Verification.scss'
9 |
10 | const cx = classnames.bind(styles)
11 |
12 | const ErrorComponent = ({ closeModal, t }) => (
13 | <>
14 | {t('verification.errors.not_loaded')}
15 |
16 | {t('verification.errors.not_found')}
17 | >
18 | )
19 |
20 | const ModalVerification = props => (
21 |
22 |
23 |
24 | )
25 |
26 | ModalVerification.propTypes = {
27 | closeModal: PropTypes.func.isRequired,
28 | t: PropTypes.func.isRequired,
29 | }
30 |
31 | export default withNamespaces()(ModalVerification)
32 |
--------------------------------------------------------------------------------
/src/routes/Dashboard/assets/crystal-ball.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/src/store/reducers/modal.js:
--------------------------------------------------------------------------------
1 | import { handleActions } from 'redux-actions'
2 | import { Map, List, fromJS } from 'immutable'
3 |
4 | import { loadStorage } from 'store/middlewares/Storage'
5 | import { openModal, closeModal } from 'store/actions/modal'
6 |
7 | const reducer = handleActions(
8 | {
9 | [openModal]: (state, { payload: { modalName: currentModal, modalData = {} } }) => state.withMutations((stateMap) => {
10 | stateMap.set('isOpen', true)
11 | stateMap.set('currentModal', currentModal)
12 | stateMap.set('modalData', fromJS(modalData))
13 | }),
14 | [closeModal]: () => Map({
15 | isOpen: false,
16 | currentModal: undefined,
17 | transactions: List(),
18 | }),
19 | [loadStorage]: (state, { payload: { modal } }) => {
20 | if (modal) {
21 | return state.merge(fromJS(modal))
22 | }
23 |
24 | return state
25 | },
26 | },
27 | Map({
28 | isOpen: false,
29 | currentModal: undefined,
30 | modalData: Map(),
31 | }),
32 | )
33 |
34 | export default reducer
35 |
--------------------------------------------------------------------------------
/src/assets/img/badges/crystal-gazer.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/src/routes/MarketDetails/components/MarketDetail/Details/MarketTimer/MarketTimer.scss:
--------------------------------------------------------------------------------
1 | @import '~style/vars.scss';
2 |
3 | .marketTimer {
4 | margin-top: 12px;
5 | margin-bottom: 12px;
6 |
7 | .marketTimerLive {
8 | font-size: 22px;
9 | font-weight: 300;
10 | letter-spacing: 1px;
11 | line-height: 1.2;
12 | @media (min-width: $screen-sm) {
13 | font-size: 28px;
14 | }
15 |
16 | &.big {
17 | font-size: 24px;
18 | }
19 |
20 | .timerLabel {
21 | color: $font-color-muted;
22 | font-size: 18px;
23 | text-transform: uppercase;
24 | }
25 | }
26 |
27 | .marketStatus {
28 | margin-top: 20px;
29 | font-size: 22px;
30 | font-weight: 300;
31 | letter-spacing: 1px;
32 | line-height: 1.2;
33 | @media (min-width: $screen-sm) {
34 | font-size: 28px;
35 | }
36 | }
37 |
38 | .marketTimeAbsolute {
39 | color: $font-color-light;
40 | opacity: 0.6;
41 | font-size: 10px;
42 | text-transform: uppercase;
43 | letter-spacing: 0.5px;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/store/selectors/account/trades.js:
--------------------------------------------------------------------------------
1 | import { List } from 'immutable'
2 | import { createSelector } from 'reselect'
3 | import { getCollateralToken } from 'store/selectors/blockchain'
4 | import { normalizeHex } from 'utils/helpers'
5 |
6 | const tradesWithMarketsSelector = createSelector(
7 | state => state.marketList,
8 | state => state.accountTrades,
9 | (marketList, marketTrades) => marketTrades.map((marketTrade) => {
10 | const tradesMarket = marketList.find(
11 | market => normalizeHex(market.eventAddress) === normalizeHex(marketTrade.eventAddress),
12 | )
13 | return marketTrade.set('market', tradesMarket)
14 | }),
15 | )
16 |
17 | const tradeSelector = createSelector(tradesWithMarketsSelector, getCollateralToken, (trades, collateralToken) => List(
18 | trades
19 | .filter(trade => typeof trade.market !== 'undefined' && trade.collateralTokenAddress === collateralToken.address)
20 | .sortBy(trade => trade.date, (dateA, dateB) => (dateA.isBefore(dateB) ? 1 : -1))
21 | .values(),
22 | ))
23 |
24 | export default tradeSelector
25 |
--------------------------------------------------------------------------------
/src/assets/verification/onfido/id-type-id.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/components/ModalContent/TransactionsExplanation/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 | import { withNamespaces } from 'react-i18next'
4 | import cn from 'classnames/bind'
5 | import style from './TransactionExplanation.scss'
6 |
7 | const cx = cn.bind(style)
8 |
9 | const TransactionsExplanation = ({ transactions, closeModal, t }) => (
10 |
11 |
19 | )
20 |
21 | TransactionsExplanation.propTypes = {
22 | transactions: PropTypes.arrayOf(PropTypes.string).isRequired,
23 | closeModal: PropTypes.func.isRequired,
24 | t: PropTypes.func.isRequired,
25 | }
26 |
27 | export default withNamespaces()(TransactionsExplanation)
28 |
--------------------------------------------------------------------------------
/src/routes/Dashboard/assets/badges/crystal-gazer.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/src/containers/LegalCompliance/components/DocumentExplanation.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 |
4 | const TOS_DOCUMENT = 'TOS_DOCUMENT'
5 | const TOS_TEXT = 'TOS_TEXT'
6 |
7 | const DOCUMENT_TYPES = {
8 | FILE: TOS_DOCUMENT,
9 | TEXT: TOS_TEXT,
10 | }
11 |
12 | const LegalDocumentTitle = ({
13 | type, file, id, t,
14 | }) => {
15 | if (type === DOCUMENT_TYPES.FILE) {
16 | return (
17 |
18 |
19 | {t(`legal.documents.${id}`)}
20 |
21 |
22 | )
23 | }
24 | if (type === DOCUMENT_TYPES.TEXT) {
25 | return {t(`legal.documents.${id}_short`)}
26 | }
27 |
28 | return null
29 | }
30 |
31 | LegalDocumentTitle.propTypes = {
32 | type: PropTypes.string.isRequired,
33 | id: PropTypes.string.isRequired,
34 | t: PropTypes.func.isRequired,
35 | file: PropTypes.string,
36 | }
37 |
38 | LegalDocumentTitle.defaultProps = {
39 | file: '',
40 | }
41 |
42 | export default LegalDocumentTitle
43 |
--------------------------------------------------------------------------------
/src/routes/Transactions/store/selectors/transactions.spec.js:
--------------------------------------------------------------------------------
1 | import { transactionSelector } from 'routes/Transactions/store/selectors/transactions'
2 | import { Map } from 'immutable'
3 |
4 | // import { TRANSACTION_STATUS, TRANSACTION_COMPLETE_STATUS } from 'utils/constants'
5 |
6 | describe('transactionsSelector', () => {
7 | test('it should return a transaction object', () => {
8 | const state = {
9 | transactions: Map({
10 | log: Map({
11 | test123: {
12 | id: 'test123',
13 | },
14 | }),
15 | }),
16 | }
17 |
18 | expect(transactionSelector(state, 'test123')).toMatchObject(state.transactions.getIn(['log', 'test123']))
19 | })
20 |
21 | test('it should return an empty object for an invalid transaction id', () => {
22 | const state = {
23 | transactions: Map({
24 | log: {
25 | test123: {
26 | id: 'test123',
27 | },
28 | },
29 | }),
30 | }
31 |
32 | expect(transactionSelector(state, 'test123')).toMatchObject({})
33 | })
34 | })
35 |
--------------------------------------------------------------------------------
/src/routes/GameGuide/components/uPortComponents/SignUp/index.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react'
2 | import Block from 'components/layout/Block'
3 | import Subtitle from 'components/layout/Subtitle'
4 | import Paragraph from 'components/layout/Paragraph'
5 |
6 | const SignUp = () => (
7 |
8 | Sign-up
9 |
10 | To participate in our two-week tournament, verify your identity by signing up via the uPort app on Android or iOS.{' '}
11 |
12 |
13 | uPort is a secure, easy-to-use system for self-sovereign identity, built on Ethereum. uPort identities are fully
14 | owned and controlled by the creator, and don't rely on centralized third-parties for creation or validation.
15 | Via uPort, you can own and control your personal identity; securely and selectively disclose your data to
16 | counterparties, and interact with decentralized applications and smart contracts such as Gnosis.
17 |
18 |
19 | )
20 |
21 | export default SignUp
22 |
--------------------------------------------------------------------------------
/config/mainnet/development.json:
--------------------------------------------------------------------------------
1 | {
2 | "gnosisdb": {
3 | "protocol": "https",
4 | "host": "tradingdb.staging.gnosisdev.com",
5 | "port": 443
6 | },
7 | "ethereum":{
8 | "protocol":"https",
9 | "host":"rinkeby.infura.io/v3/5e7a225e60184afaa7b888303def93b8",
10 | "port":443
11 | },
12 | "htmlConfig": {
13 | "title": "Gnosis Trading Interface"
14 | },
15 | "whitelist": {
16 | "0x9eab578556de5782445ec036f25a41902ba19eeb": "Gnosis",
17 | "0xb2e87b8ce41184e0688027f370a972a436abe77e": "Giacomo",
18 | "0xb00a24c899f88e5514583cfa8c40e4cdab6c473e": "Andre",
19 | "0x65039084cc6f4773291a6ed7dcf5bc3a2e894ff3": "Denis",
20 | "0x4b07f5a08639bcde3b7275a98dae265cbda608ca": "Lama",
21 | "0xe7e3272a84cf3fe180345b9f7234ba705eb5e2ca": "Mikhail",
22 | "0x95db47d3e9d574cd15b0f02c845bc2971b0fc3e1": "Lauti"
23 | },
24 | "thirdparty": {
25 | "googleAnalytics": {
26 | "enabled": false
27 | }
28 | },
29 | "providers": {
30 | "default": "METAMASK"
31 | },
32 | "legalCompliance": {
33 | "enabled": true
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/containers/LegalCompliance/components/DocumentField.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 | import { Field } from 'redux-form'
4 | import { Checkbox } from 'components/Form'
5 |
6 | const DocumentField = ({
7 | id, type, className, file, t,
8 | }) => (
9 |
10 | {type === 'TOS_DOCUMENT' && (
11 |
12 | {t('legal.read_and_understood')}
13 |
14 | {t(`legal.documents.${id}`)}
15 |
16 |
17 | )}
18 | {type === 'TOS_TEXT' && {t(`legal.documents.${id}_description`)}}
19 |
20 | )
21 |
22 | DocumentField.propTypes = {
23 | t: PropTypes.func.isRequired,
24 | id: PropTypes.string.isRequired,
25 | type: PropTypes.string.isRequired,
26 | file: PropTypes.string,
27 | className: PropTypes.string,
28 | }
29 |
30 | DocumentField.defaultProps = {
31 | className: '',
32 | file: '',
33 | }
34 |
35 | export default DocumentField
36 |
--------------------------------------------------------------------------------
/src/assets/img/icons/icon_currency.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
--------------------------------------------------------------------------------
/src/components/Notifications/Notifications.scss:
--------------------------------------------------------------------------------
1 | @import '~style/vars.scss';
2 | @keyframes slideInFromRight {
3 | 0% {
4 | transform: translateX(400px);
5 | }
6 |
7 | 100% {
8 | transform: translateX(0);
9 | }
10 | }
11 |
12 | .notification {
13 | animation: slideInFromRight 1s ease-out 0s 1;
14 | background-color: $bg-color;
15 |
16 | padding: 4px;
17 | width: 100%;
18 | position: relative;
19 |
20 | color: $font-color-dark;
21 | border: none;
22 |
23 | &:hover {
24 | color: $active-highlight;
25 | }
26 |
27 | .notificationHeaderContainer {
28 | display: flex;
29 | align-items: center;
30 |
31 | .iconContainer {
32 | height: 100%;
33 | vertical-align: middle;
34 | margin-left: 4px;
35 | display: inline-block;
36 | }
37 |
38 | .title {
39 | text-transform: uppercase;
40 | font-weight: 500;
41 | margin-bottom: 8px;
42 | color: inherit;
43 | display: inline-block;
44 | }
45 | }
46 |
47 | .message {
48 | color: inherit;
49 | padding-left: 24px;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/routes/MarketDetails/store/actions/requestMarket.js:
--------------------------------------------------------------------------------
1 | import { requestFromRestAPI } from 'api/utils/fetch'
2 | import { addMarkets, extractMarkets } from 'store/actions/market'
3 | import { getCollateralToken } from 'store/selectors/blockchain'
4 | import { hexWithoutPrefix } from 'utils/helpers'
5 |
6 | export const processMarketResponse = (dispatch, state, response) => {
7 | if (!response) {
8 | dispatch(addMarkets([]))
9 | return
10 | }
11 |
12 | const applicationCollateralToken = getCollateralToken(state)
13 |
14 | let marketRecords = extractMarkets([response])
15 |
16 | if (applicationCollateralToken.address) {
17 | marketRecords = marketRecords.filter(({ collateralToken }) => collateralToken === hexWithoutPrefix(applicationCollateralToken.address))
18 | }
19 |
20 | dispatch(addMarkets(marketRecords))
21 | }
22 |
23 | export default marketAddress => async (dispatch, getState) => {
24 | const response = await requestFromRestAPI(`markets/${marketAddress}`)
25 | const state = getState()
26 |
27 | return processMarketResponse(dispatch, state, response)
28 | }
29 |
--------------------------------------------------------------------------------
/src/routes/MarketDetails/api/calculateGasCost.js:
--------------------------------------------------------------------------------
1 | import { getGnosisConnection } from 'api'
2 |
3 | /*
4 | * Gas Calculation functions
5 | */
6 |
7 | export const calcBuySharesGasCost = async () => {
8 | const gnosis = await getGnosisConnection()
9 | const gasCost = await gnosis.buyOutcomeTokens.estimateGas({ using: 'stats' })
10 | return gasCost
11 | }
12 |
13 | export const calcSellSharesGasCost = async () => {
14 | const gnosis = await getGnosisConnection()
15 | const gasCost = await gnosis.sellOutcomeTokens.estimateGas({ using: 'stats' })
16 | return gasCost
17 | }
18 |
19 | /**
20 | * Returns gas cost for redeem winnings
21 | * @param {*object} opts options
22 | * @param {*string} opts.eventAddress Address for the event
23 | */
24 |
25 | export const calcRedeemWinningsGasCost = async ({ eventAddress }) => {
26 | if (!eventAddress) {
27 | return undefined
28 | }
29 |
30 | const gnosis = await getGnosisConnection()
31 | const event = await gnosis.contracts.Event.at(eventAddress)
32 |
33 | const gasGost = await event.redeemWinnings.estimateGas()
34 | return gasGost
35 | }
36 |
--------------------------------------------------------------------------------
/src/components/layout/Paragraph/index.js:
--------------------------------------------------------------------------------
1 | import classNames from 'classnames/bind'
2 | import PropTypes from 'prop-types'
3 | import React, { PureComponent } from 'react'
4 | import * as css from './index.scss'
5 |
6 | const cx = classNames.bind(css)
7 |
8 | class Paragraph extends PureComponent {
9 | render() {
10 | const {
11 | children, color, center, size, nomargin, ...props
12 | } = this.props
13 | const noMargin = nomargin ? 'no-margin' : undefined
14 |
15 | return (
16 |
17 | { children }
18 |
19 | )
20 | }
21 | }
22 |
23 | Paragraph.propTypes = {
24 | size: PropTypes.oneOf(['normal', 'small']),
25 | nomargin: PropTypes.bool,
26 | center: PropTypes.bool,
27 | color: PropTypes.oneOf(['soft', 'medium', 'dark', 'primary']),
28 | children: PropTypes.node,
29 | }
30 |
31 | Paragraph.defaultProps = {
32 | size: 'normal',
33 | center: false,
34 | color: undefined,
35 | children: undefined,
36 | nomargin: false,
37 | }
38 |
39 | export default Paragraph
40 |
--------------------------------------------------------------------------------
/src/routes/Scoreboard/containers/selector.js:
--------------------------------------------------------------------------------
1 | import { createSelector, createStructuredSelector } from 'reselect'
2 | import { getCurrentAccount, getRegisteredMainnetAddress } from 'integrations/store/selectors'
3 | import { rankSelector } from 'routes/Scoreboard/store/selectors'
4 | import { hasClaimedReward } from 'containers/Modals/ModalClaimReward/selectors'
5 | import { firstTournamentUsersSelectorAsList, meSelector } from '../store/selectors'
6 |
7 | const usersSelector = createSelector(firstTournamentUsersSelectorAsList, meSelector, (firstUsers, me) => {
8 | if (!me) {
9 | return firstUsers
10 | }
11 |
12 | if (!firstUsers) {
13 | return undefined
14 | }
15 |
16 | const foundUser = firstUsers ? firstUsers.find(user => user.account === me.account) : undefined
17 | const dataTable = foundUser ? firstUsers : firstUsers.push(me)
18 |
19 | return dataTable
20 | })
21 |
22 | export default createStructuredSelector({
23 | data: usersSelector,
24 | mainnetAddress: getRegisteredMainnetAddress,
25 | myAccount: getCurrentAccount,
26 | rank: rankSelector,
27 | hasClaimedReward,
28 | })
29 |
--------------------------------------------------------------------------------
/src/components/TransactionFloater/Notifications/Notifications.scss:
--------------------------------------------------------------------------------
1 | @import '~style/vars.scss';
2 |
3 | @keyframes slideInFromRight {
4 | 0% {
5 | transform: translateX(400px);
6 | }
7 |
8 | 100% {
9 | transform: translateX(0);
10 | }
11 | }
12 |
13 | .notification {
14 | animation: slideInFromRight 1s ease-out 0s 1;
15 | background-color: $bg-color;
16 |
17 | padding: 4px;
18 | width: 100%;
19 | position: relative;
20 |
21 | color: $font-color-dark;
22 | border: none;
23 |
24 | &:hover {
25 | color: $active-highlight;
26 | }
27 |
28 | .notificationHeaderContainer {
29 | display: flex;
30 | align-items: center;
31 |
32 | .iconContainer {
33 | height: 100%;
34 | vertical-align: middle;
35 | margin-left: 4px;
36 | display: inline-block;
37 | }
38 |
39 | .title {
40 | text-transform: uppercase;
41 | font-weight: 500;
42 | margin-bottom: 8px;
43 | color: inherit;
44 | display: inline-block;
45 | }
46 | }
47 |
48 | .message {
49 | color: inherit;
50 | padding-left: 24px;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/components/Header/ProviderIcon.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 | import Tooltip from 'rc-tooltip'
4 | import { withNamespaces } from 'react-i18next'
5 |
6 | import Icon from 'components/Icon'
7 |
8 | import { providerPropType } from 'utils/shapes'
9 | import { upperFirst } from 'lodash'
10 |
11 | import { WALLET_PROVIDER } from 'integrations/constants'
12 |
13 | const PROVIDER_ICONS = {
14 | ...WALLET_PROVIDER,
15 | [WALLET_PROVIDER.REMOTE]: 'etherTokens',
16 | }
17 |
18 | const providerIconStyle = {
19 | marginLeft: 10,
20 | }
21 |
22 | const ProviderIcon = ({ provider, t }) => (
23 |
24 |
25 |
26 | )
27 |
28 | ProviderIcon.propTypes = {
29 | provider: providerPropType,
30 | t: PropTypes.func.isRequired,
31 | }
32 |
33 | ProviderIcon.defaultProps = {
34 | provider: {},
35 | }
36 |
37 | export default withNamespaces()(ProviderIcon)
38 |
--------------------------------------------------------------------------------
/src/assets/img/icons/icon_enddate.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
--------------------------------------------------------------------------------
/src/store/middlewares/Notifications.js:
--------------------------------------------------------------------------------
1 | import {
2 | createNotificationFromTransaction,
3 | hideAllNotifications,
4 | } from 'store/actions/notifications'
5 |
6 | let isModalOpen = false
7 |
8 | export default store => next => (action) => {
9 | const handledAction = next(action)
10 |
11 | const { type, payload } = action
12 |
13 | if (type === 'SHOW_MODAL') {
14 | isModalOpen = true
15 | }
16 |
17 | if (type === 'CLOSE_MODAL') {
18 | isModalOpen = false
19 | }
20 |
21 | if (!isModalOpen) {
22 | if (type === 'CLOSE_TRANSACTION_LOG') {
23 | // intercept close log messages, fire notification handler
24 | store.dispatch(createNotificationFromTransaction(payload.id, 'CLOSE'))
25 | }
26 |
27 | if (type === 'START_TRANSACTION_LOG') {
28 | store.dispatch(createNotificationFromTransaction(payload.id, 'START'))
29 | }
30 |
31 | // disable/hide all notifications while menu is open
32 | if (type === 'SHOW_TRANSACTION_LOG' || type === 'HIDE_TRANSACTION_LOG') {
33 | store.dispatch(hideAllNotifications())
34 | }
35 | }
36 |
37 | return handledAction
38 | }
39 |
--------------------------------------------------------------------------------
/src/routes/Dashboard/assets/icon_outstandingPredictions.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Gnosis Ltd
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/routes/Dashboard/components/Dashboard/Metrics/Metric.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 |
4 | import IndefiniteSpinner from 'components/Spinner/Indefinite'
5 |
6 | import classnames from 'classnames/bind'
7 | import style from './Metrics.scss'
8 |
9 | const cx = classnames.bind(style)
10 |
11 | const Metric = ({
12 | src, explanation, children, isLoading,
13 | }) => (
14 |
15 |

16 | {isLoading ? (
17 |
18 | ) : (
19 |
20 | {children}
21 | {explanation}
22 |
23 | )}
24 |
25 | )
26 |
27 | Metric.propTypes = {
28 | src: PropTypes.string.isRequired,
29 | explanation: PropTypes.string,
30 | children: PropTypes.node,
31 | isLoading: PropTypes.bool,
32 | }
33 |
34 | Metric.defaultProps = {
35 | explanation: 'N/A',
36 | children: ,
37 | isLoading: false,
38 | }
39 |
40 | export default Metric
41 |
--------------------------------------------------------------------------------
/src/assets/img/icons/gno_token.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/components/Header/Layouts/MobileHeader/assets/icon_copy.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
41 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb",
3 | "parser": "babel-eslint",
4 | "plugins": ["jest"],
5 | "rules": {
6 | "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
7 | "react/forbid-prop-types": [1, { "forbid": ["object", "any"] }],
8 | "class-methods-use-this": 0,
9 | "semi": ["error", "never"],
10 | "max-len": [
11 | "error",
12 | 120,
13 | 2,
14 | {
15 | "ignoreUrls": true,
16 | "ignoreComments": false,
17 | "ignoreRegExpLiterals": true,
18 | "ignoreStrings": true,
19 | "ignoreTemplateLiterals": true
20 | }
21 | ],
22 | "import/no-unresolved": 0,
23 | "import/no-extraneous-dependencies": 0,
24 | "import/extensions": 0,
25 | "import/prefer-default-export": 0,
26 | "react/jsx-one-expression-per-line": "off",
27 | "jsx-a11y/label-has-for": 0,
28 | "jsx-a11y/anchor-is-valid": ["error", {
29 | "components": []
30 | }],
31 | "indent": ["error", 2],
32 | "no-console": ["error", { "allow": ["warn", "error"] }]
33 | },
34 | "env": {
35 | "jest/globals": true,
36 | "browser": true
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/integrations/uport/uportNotifications.js:
--------------------------------------------------------------------------------
1 | import { decodeToken } from 'jsontokens'
2 |
3 | export const isValid = (cred) => {
4 | if (cred === null) {
5 | return false
6 | }
7 |
8 | const pushToken = decodeToken(cred.pushToken)
9 | if (!pushToken) {
10 | return false
11 | }
12 |
13 | const expiration = pushToken.payload.exp // When the uPort credential will expire
14 | const oneDay = 24 * 60 * 6 // one day in seconds
15 | const now = new Date() / 1000 // in seconds
16 | const valid = expiration - oneDay > now
17 |
18 | return valid
19 | }
20 |
21 | const assignSessionProps = (uport, cred) => {
22 | /* eslint-disable */
23 | uport.address = cred.address
24 | uport.pushToken = cred.pushToken
25 | uport.publicEncKey = cred.publicEncKey
26 | /* eslint-enable */
27 | }
28 |
29 | const init = async (uport, requestCredentials, getCredential) => {
30 | let credential = getCredential()
31 | if (!isValid(credential)) {
32 | credential = await requestCredentials()
33 | }
34 |
35 | if (credential) {
36 | assignSessionProps(uport, credential)
37 | }
38 |
39 | return uport
40 | }
41 |
42 | export default init
43 |
--------------------------------------------------------------------------------
/src/containers/TransactionFloaterContainer/index.js:
--------------------------------------------------------------------------------
1 | import { connect } from 'react-redux'
2 | import TransactionFloater from 'components/TransactionFloater'
3 | import { showTransactionLog, hideTransactionLog } from 'routes/Transactions/store/actions/transactions'
4 | import {
5 | getRunningTransactions,
6 | getCompletedTransactions,
7 | getRunningTransactionsProgress,
8 | areLogsVisible,
9 | } from 'routes/Transactions/store/selectors/transactions'
10 | import { getVisibleNotifications } from 'store/selectors/notifications'
11 |
12 | const LIMIT_COUNT_RUNNING_TRANSACTIONS = 3
13 | const LIMIT_COUNT_COMPLETED_TRANSACTIONS = 3
14 |
15 | const mapStateToProps = state => ({
16 | runningTransactions: getRunningTransactions(state).takeLast(LIMIT_COUNT_RUNNING_TRANSACTIONS),
17 | completedTransactions: getCompletedTransactions(state).takeLast(LIMIT_COUNT_COMPLETED_TRANSACTIONS),
18 | progress: getRunningTransactionsProgress(state),
19 | notifications: getVisibleNotifications(state),
20 | showLogs: areLogsVisible(state),
21 | })
22 |
23 | export default connect(mapStateToProps, {
24 | showTransactionLog,
25 | hideTransactionLog,
26 | })(TransactionFloater)
27 |
--------------------------------------------------------------------------------
/src/components/Spinner/Transaction.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 | import Icon from 'components/Icon'
4 | import { TRANSACTION_COMPLETE_STATUS } from 'utils/constants'
5 |
6 | import IndefiniteSpinner from './Indefinite'
7 |
8 | const ProgressIndicator = ({ completed, completionStatus, progress }) => {
9 | const iconType = completionStatus === TRANSACTION_COMPLETE_STATUS.NO_ERROR ? 'checkmark' : 'cross'
10 | const iconStyle = {
11 | top: '50%',
12 | marginTop: -24,
13 | }
14 |
15 | return completed ? (
16 |
17 | ) : (
18 |
26 | )
27 | }
28 |
29 | ProgressIndicator.propTypes = {
30 | completed: PropTypes.bool,
31 | completionStatus: PropTypes.string,
32 | progress: PropTypes.number,
33 | }
34 |
35 | ProgressIndicator.defaultProps = {
36 | completed: false,
37 | completionStatus: undefined,
38 | progress: 0,
39 | }
40 |
41 | export default ProgressIndicator
42 |
--------------------------------------------------------------------------------
/src/store/reducers/index.js:
--------------------------------------------------------------------------------
1 | import { combineReducers } from 'redux'
2 | import { reducer as formReducer } from 'redux-form'
3 | import { isFeatureEnabled } from 'utils/features'
4 |
5 | // Reducers
6 | import integrations from 'integrations/store/reducers'
7 | import users from 'routes/Scoreboard/store/reducers/users'
8 | import transactions from 'routes/Transactions/store/reducers/transactions'
9 | import modal from './modal'
10 | import blockchain from './blockchain'
11 | import notifications from './notifications'
12 | import marketList from './market'
13 | import accountShares from './accountShares'
14 | import accountTrades from './accountTrades'
15 | import interfaceState from './interface'
16 |
17 | const tournamentEnabled = isFeatureEnabled('tournament')
18 |
19 | const reducers = {
20 | form: formReducer,
21 | modal,
22 | transactions,
23 | blockchain,
24 | notifications,
25 | integrations,
26 | marketList,
27 | accountShares,
28 | accountTrades,
29 | interfaceState,
30 | }
31 |
32 | if (tournamentEnabled) {
33 | reducers.tournament = combineReducers({
34 | ranking: users,
35 | })
36 | }
37 |
38 | export default combineReducers(reducers)
39 |
--------------------------------------------------------------------------------