├── .eslintignore ├── public ├── _redirects ├── favicon.ico ├── images │ └── synthetix-logo-small.png └── manifest.json ├── src ├── pages │ ├── Home │ │ ├── index.ts │ │ ├── Hero │ │ │ ├── index.js │ │ │ └── Hero.js │ │ ├── ExchangeFeatures │ │ │ └── index.ts │ │ └── Home.tsx │ ├── Root │ │ ├── index.js │ │ └── components │ │ │ ├── AppBanner │ │ │ └── index.ts │ │ │ ├── AppHeader │ │ │ ├── Logo │ │ │ │ ├── index.ts │ │ │ │ └── Logo.tsx │ │ │ ├── index.ts │ │ │ ├── UserInfo │ │ │ │ └── index.ts │ │ │ ├── SupportLink │ │ │ │ ├── index.ts │ │ │ │ └── SupportLink.tsx │ │ │ ├── ThemeToggle │ │ │ │ ├── index.ts │ │ │ │ └── ThemeToggle.stories.js │ │ │ ├── WalletMenu │ │ │ │ └── index.js │ │ │ ├── MobileAppHeader │ │ │ │ ├── Dropdown │ │ │ │ │ ├── index.ts │ │ │ │ │ └── Dropdown.tsx │ │ │ │ ├── Overlay │ │ │ │ │ ├── index.ts │ │ │ │ │ └── Overlay.tsx │ │ │ │ └── index.ts │ │ │ ├── common.ts │ │ │ └── constants.ts │ │ │ ├── HomeLayout │ │ │ ├── Footer │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ └── HomeLayout.tsx │ │ │ ├── MainLayout │ │ │ ├── index.ts │ │ │ └── MainLayout.tsx │ │ │ ├── ProtectedRoute │ │ │ ├── index.ts │ │ │ └── ProtectedRoute.tsx │ │ │ ├── MaintenanceMessage │ │ │ ├── index.ts │ │ │ └── MaintenanceMessage.tsx │ │ │ └── MaterialUIThemeProvider.tsx │ ├── Trade │ │ ├── index.ts │ │ └── components │ │ │ ├── ChartCard │ │ │ ├── index.ts │ │ │ ├── PairListPanel │ │ │ │ ├── index.ts │ │ │ │ └── common.ts │ │ │ └── types.ts │ │ │ ├── BlurBackground │ │ │ ├── index.ts │ │ │ └── BlurBackground.tsx │ │ │ ├── OrderBookCard │ │ │ ├── constants.ts │ │ │ ├── index.js │ │ │ ├── AllTrades.tsx │ │ │ ├── ViewLink.tsx │ │ │ └── MyTrades.tsx │ │ │ └── CreateOrderCard │ │ │ └── index.js │ ├── Assets │ │ ├── index.ts │ │ ├── Exchanges │ │ │ └── index.js │ │ ├── Options │ │ │ ├── index.ts │ │ │ ├── Banner │ │ │ │ └── index.ts │ │ │ └── Markets │ │ │ │ └── index.ts │ │ ├── Overview │ │ │ ├── index.ts │ │ │ ├── Dashboard │ │ │ │ ├── index.js │ │ │ │ ├── BalanceChart │ │ │ │ │ └── index.js │ │ │ │ ├── TotalBalance │ │ │ │ │ └── index.js │ │ │ │ ├── SynthBreakdown │ │ │ │ │ ├── index.js │ │ │ │ │ └── mockData.js │ │ │ │ └── Dashboard.js │ │ │ ├── YourSynths │ │ │ │ └── index.ts │ │ │ └── Overview.tsx │ │ ├── Transfers │ │ │ └── index.js │ │ └── components │ │ │ └── AssetsNavigation │ │ │ └── index.ts │ ├── Markets │ │ ├── index.ts │ │ └── Markets.tsx │ ├── Options │ │ ├── index.ts │ │ ├── Home │ │ │ ├── index.ts │ │ │ ├── HotMarkets │ │ │ │ └── index.ts │ │ │ ├── MarketsTable │ │ │ │ └── index.ts │ │ │ ├── ExploreMarkets │ │ │ │ └── index.ts │ │ │ ├── MarketCreation │ │ │ │ └── index.ts │ │ │ ├── components │ │ │ │ └── TimeRemaining │ │ │ │ │ └── index.ts │ │ │ └── utils.ts │ │ ├── Market │ │ │ ├── index.ts │ │ │ ├── ChartCard │ │ │ │ ├── index.ts │ │ │ │ ├── PriceChart │ │ │ │ │ └── index.ts │ │ │ │ ├── OptionsChart │ │ │ │ │ └── index.ts │ │ │ │ └── common.ts │ │ │ ├── TradeCard │ │ │ │ ├── index.ts │ │ │ │ ├── BiddingPhaseCard │ │ │ │ │ ├── index.ts │ │ │ │ │ └── types.ts │ │ │ │ ├── MaturityPhaseCard │ │ │ │ │ └── index.ts │ │ │ │ ├── TradingPhaseCard │ │ │ │ │ └── index.ts │ │ │ │ ├── components │ │ │ │ │ ├── OptionResult │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── ResultCard │ │ │ │ │ │ └── index.ts │ │ │ │ │ └── BidNetworkFees │ │ │ │ │ │ └── index.ts │ │ │ │ └── common.ts │ │ │ ├── MarketInfoModal │ │ │ │ └── index.ts │ │ │ ├── components │ │ │ │ └── SideIcon │ │ │ │ │ ├── index.ts │ │ │ │ │ └── SideIcon.tsx │ │ │ ├── TransactionsCard │ │ │ │ ├── index.ts │ │ │ │ ├── YourTransactions │ │ │ │ │ ├── index.ts │ │ │ │ │ └── YourTransactions.tsx │ │ │ │ ├── PendingTransactions │ │ │ │ │ └── index.ts │ │ │ │ ├── RecentTransactions │ │ │ │ │ ├── index.ts │ │ │ │ │ └── RecentTransactions.tsx │ │ │ │ └── components │ │ │ │ │ └── TransactionsTable │ │ │ │ │ └── index.ts │ │ │ ├── contexts │ │ │ │ ├── MarketContext.tsx │ │ │ │ └── BOMContractContext.tsx │ │ │ └── MarketContainer.tsx │ │ ├── CreateMarketModal │ │ │ └── index.ts │ │ ├── components │ │ │ ├── NetworkFees │ │ │ │ └── index.ts │ │ │ ├── MarketSentiment │ │ │ │ └── index.ts │ │ │ └── NewToBinaryOptions │ │ │ │ ├── index.ts │ │ │ │ └── NewToBinaryOptions.tsx │ │ └── constants.ts │ ├── Synths │ │ ├── Home │ │ │ ├── index.ts │ │ │ ├── Hero │ │ │ │ ├── index.ts │ │ │ │ └── Hero.tsx │ │ │ ├── SynthsSection │ │ │ │ ├── index.ts │ │ │ │ ├── SynthsCharts │ │ │ │ │ └── index.ts │ │ │ │ ├── SynthsTable │ │ │ │ │ └── index.ts │ │ │ │ └── constants.ts │ │ │ └── Home.tsx │ │ ├── index.ts │ │ ├── Overview │ │ │ ├── index.ts │ │ │ ├── SynthInfo │ │ │ │ └── index.ts │ │ │ ├── SynthChart │ │ │ │ └── index.ts │ │ │ └── SynthMarkets │ │ │ │ └── index.ts │ │ ├── mockData.ts │ │ └── Synths.tsx │ ├── Loans │ │ ├── components │ │ │ ├── Dashboard │ │ │ │ └── index.js │ │ │ ├── MyLoans │ │ │ │ ├── Loans │ │ │ │ │ └── index.js │ │ │ │ ├── index.js │ │ │ │ ├── Activity │ │ │ │ │ ├── index.js │ │ │ │ │ └── ViewLink.jsx │ │ │ │ └── Liquidations │ │ │ │ │ └── index.js │ │ │ ├── Actions │ │ │ │ └── index.ts │ │ │ ├── LiquidateCard │ │ │ │ └── index.js │ │ │ └── LoanCards │ │ │ │ ├── RepayLoan │ │ │ │ └── index.js │ │ │ │ ├── CloseLoanCard │ │ │ │ ├── index.js │ │ │ │ └── CloseLoanCard.stories.js │ │ │ │ ├── BlockingOverlay │ │ │ │ ├── index.js │ │ │ │ └── BlockingOverlay.js │ │ │ │ ├── LoanWarningModal │ │ │ │ └── index.ts │ │ │ │ ├── ModifyCollateral │ │ │ │ └── index.js │ │ │ │ ├── commonStyles.js │ │ │ │ └── CreateLoanCard │ │ │ │ └── CreateLoanCard.stories.js │ │ ├── index.js │ │ └── contexts │ │ │ └── LoanContext.js │ └── shared │ │ └── components │ │ ├── NewUserPromo │ │ └── index.ts │ │ ├── SelectCRatio │ │ └── index.ts │ │ ├── SelectGasMenu │ │ └── index.ts │ │ ├── ViewLinkCell │ │ └── index.ts │ │ └── MarketsSection │ │ ├── index.ts │ │ ├── MarketsCharts │ │ └── index.ts │ │ ├── MarketsTable │ │ └── index.ts │ │ └── constants.ts ├── components │ ├── Card │ │ ├── index.ts │ │ ├── Card.stories.js │ │ ├── CardBody.tsx │ │ ├── Card.tsx │ │ └── CardHeader.tsx │ ├── Link │ │ ├── index.ts │ │ └── Link.tsx │ ├── Table │ │ ├── index.ts │ │ ├── constants.ts │ │ └── common.tsx │ ├── Margin │ │ └── index.ts │ ├── Select │ │ └── index.ts │ ├── Slider │ │ ├── index.js │ │ ├── Slider.js │ │ └── Slider.css │ ├── Spinner │ │ ├── index.ts │ │ └── Spinner.tsx │ ├── ChartCard │ │ └── index.ts │ ├── Dropdown │ │ ├── index.js │ │ └── Dropdown.js │ ├── NetworkInfo │ │ └── index.js │ ├── WalletPopup │ │ └── index.ts │ ├── ChangePercent │ │ ├── index.ts │ │ ├── ChangePercent.stories.js │ │ └── ChangePercent.tsx │ ├── DropdownPanel │ │ └── index.ts │ ├── TrendLineChart │ │ ├── index.ts │ │ └── TrendLineChart.tsx │ ├── TxErrorMessage │ │ ├── index.ts │ │ └── TxErrorMessage.tsx │ ├── WalletPaginator │ │ └── index.ts │ ├── BaseTradingPairs │ │ ├── index.ts │ │ └── BaseTradingPairs.tsx │ ├── Currency │ │ ├── CurrencyIcon │ │ │ ├── index.ts │ │ │ ├── CurrencyIcon.tsx │ │ │ └── CurrencyIcon.stories.js │ │ ├── CurrencyName │ │ │ ├── index.ts │ │ │ ├── CurrencyName.tsx │ │ │ └── CurrencyName.stories.js │ │ ├── CurrencyPair │ │ │ ├── index.ts │ │ │ ├── CurrencyPair.stories.js │ │ │ └── CurrencyPair.tsx │ │ ├── index.js │ │ └── commonStyles.tsx │ ├── DismissableMessage │ │ ├── index.ts │ │ └── DismissableMessage.tsx │ ├── WalletAddressTable │ │ └── index.js │ ├── RechartsResponsiveContainer │ │ ├── index.ts │ │ └── RechartsResponsiveContainer.tsx │ ├── deprecated │ │ └── Table │ │ │ ├── index.js │ │ │ └── Table.js │ ├── Input │ │ ├── constants.ts │ │ ├── TextInput.tsx │ │ ├── NumericInput.tsx │ │ ├── common.ts │ │ ├── Input.tsx │ │ └── SearchInput.tsx │ ├── Icons │ │ ├── index.ts │ │ └── Arrow.tsx │ ├── Typography │ │ ├── index.ts │ │ ├── Table.tsx │ │ ├── Form.tsx │ │ ├── General.tsx │ │ ├── Label.tsx │ │ ├── Data.tsx │ │ └── Heading.tsx │ └── Button │ │ ├── index.js │ │ ├── Button.stories.js │ │ ├── ButtonSort.js │ │ └── ButtonPrimary.js ├── constants │ ├── placeholder.ts │ ├── order.ts │ ├── storage.ts │ ├── transaction.ts │ ├── rates.ts │ ├── ui.ts │ ├── events.ts │ ├── links.ts │ ├── period.ts │ └── queryKeys.ts ├── react-app-env.d.ts ├── typings │ ├── missing-types.d.ts │ ├── styled-components.d.ts │ └── window.d.ts ├── utils │ ├── history.js │ ├── rates.js │ ├── transactions.js │ ├── currency.ts │ ├── errorMessages.js │ ├── browserUtils.js │ ├── explorers.js │ ├── balances.js │ ├── synthOrdering.js │ └── balances.spec.js ├── ducks │ ├── types.ts │ ├── options │ │ ├── index.ts │ │ └── pendingTransaction.ts │ ├── wallet │ │ └── index.ts │ ├── loans │ │ └── index.js │ ├── trades │ │ ├── utils.ts │ │ └── types.ts │ ├── index.ts │ └── sagas.ts ├── assets │ ├── fonts │ │ ├── apercu-bold.eot │ │ ├── apercu-bold.ttf │ │ ├── apercu-bold.woff │ │ ├── apercu-light.eot │ │ ├── apercu-light.ttf │ │ ├── apercu-bold.woff2 │ │ ├── apercu-light.woff │ │ ├── apercu-light.woff2 │ │ ├── apercu-medium.eot │ │ ├── apercu-medium.ttf │ │ ├── apercu-medium.woff │ │ ├── apercu-medium.woff2 │ │ ├── apercu-regular.eot │ │ ├── apercu-regular.ttf │ │ ├── apercu-regular.woff │ │ └── apercu-regular.woff2 │ ├── images │ │ ├── spinner-big.png │ │ ├── etherscan-logo.png │ │ ├── spinner-small.png │ │ ├── menu-arrow-down.svg │ │ ├── arrow-down.svg │ │ ├── sort-up.svg │ │ ├── sort-down.svg │ │ ├── sort.svg │ │ ├── trend-up.svg │ │ ├── trend-down.svg │ │ ├── arrow-hyperlink.svg │ │ ├── options-line.svg │ │ ├── menu-hamburger.svg │ │ ├── menu-close.svg │ │ ├── pencil.svg │ │ ├── finish.svg │ │ ├── search.svg │ │ ├── error-circle.svg │ │ ├── blocked.svg │ │ ├── arrow-back.svg │ │ ├── clock-square.svg │ │ ├── close-cross.svg │ │ ├── close.svg │ │ ├── sun.svg │ │ ├── exclamation.svg │ │ ├── moon.svg │ │ ├── person.svg │ │ ├── info-rounded.svg │ │ ├── cog.svg │ │ ├── wallets │ │ │ └── trezor.svg │ │ ├── dollar-sign.svg │ │ ├── reverse-arrow.svg │ │ ├── charts-square.svg │ │ ├── arrows-rotated-square.svg │ │ ├── wallet.svg │ │ ├── arrows-square.svg │ │ ├── splash │ │ │ ├── github-logo.svg │ │ │ ├── twitter-logo.svg │ │ │ └── medium-logo.svg │ │ └── no-wallet.svg │ └── currencies │ │ ├── crypto │ │ ├── LTC.svg │ │ ├── MKR.svg │ │ ├── LEND.svg │ │ ├── XRP.svg │ │ ├── EOS.svg │ │ ├── BNB.svg │ │ ├── XMR.svg │ │ ├── ETH.svg │ │ ├── DASH.svg │ │ ├── ETC.svg │ │ ├── LINK.svg │ │ ├── BTC.svg │ │ ├── BCH.svg │ │ ├── COMP.svg │ │ ├── XTZ.svg │ │ └── REN.svg │ │ ├── fiat │ │ ├── JPY.svg │ │ ├── EUR.svg │ │ ├── KRW.svg │ │ ├── GBP.svg │ │ └── CHF.svg │ │ ├── equities │ │ └── NIKKEI.svg │ │ └── indices │ │ ├── DEFI.svg │ │ └── CEX.svg ├── styles │ └── theme │ │ ├── fonts.ts │ │ ├── colors.ts │ │ ├── types.ts │ │ ├── dark.ts │ │ ├── light.ts │ │ └── index.ts ├── setupTests.ts ├── i18n.ts ├── shared │ ├── hooks │ │ ├── useInterval.ts │ │ ├── useDebouncedMemo.ts │ │ └── useLocalStorage.ts │ └── media.ts ├── index.js └── config │ └── store.js ├── .prettierignore ├── .prettierrc ├── .storybook ├── addons.js ├── main.js ├── providers │ ├── withReduxProvider.js │ └── withReactRouterProvider.js ├── libs │ └── i18n.js ├── preview.js └── mocks │ └── reducers │ └── wallet.js ├── .stylelintrc ├── .gitignore ├── netlify.toml ├── tsconfig.json ├── .eslintrc ├── .circleci └── config.yml ├── scripts └── test.js └── README.md /.eslintignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /public/_redirects: -------------------------------------------------------------------------------- 1 | /* /index.html 200 2 | -------------------------------------------------------------------------------- /src/pages/Home/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Home'; 2 | -------------------------------------------------------------------------------- /src/pages/Root/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './Root'; 2 | -------------------------------------------------------------------------------- /src/pages/Trade/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Trade'; 2 | -------------------------------------------------------------------------------- /src/components/Card/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Card'; 2 | -------------------------------------------------------------------------------- /src/components/Link/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Link'; 2 | -------------------------------------------------------------------------------- /src/components/Table/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Table'; 2 | -------------------------------------------------------------------------------- /src/constants/placeholder.ts: -------------------------------------------------------------------------------- 1 | export const EMPTY_VALUE = '-'; 2 | -------------------------------------------------------------------------------- /src/pages/Assets/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Assets'; 2 | -------------------------------------------------------------------------------- /src/pages/Home/Hero/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './Hero'; 2 | -------------------------------------------------------------------------------- /src/pages/Markets/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Markets'; 2 | -------------------------------------------------------------------------------- /src/pages/Options/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Options'; 2 | -------------------------------------------------------------------------------- /src/pages/Synths/Home/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Home'; 2 | -------------------------------------------------------------------------------- /src/pages/Synths/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Synths'; 2 | -------------------------------------------------------------------------------- /src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /src/typings/missing-types.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'synthetix-data'; 2 | -------------------------------------------------------------------------------- /src/components/Margin/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Margin'; 2 | -------------------------------------------------------------------------------- /src/components/Select/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Select'; 2 | -------------------------------------------------------------------------------- /src/components/Slider/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './Slider'; 2 | -------------------------------------------------------------------------------- /src/components/Spinner/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Spinner'; 2 | -------------------------------------------------------------------------------- /src/pages/Options/Home/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Home'; 2 | -------------------------------------------------------------------------------- /src/pages/Synths/Home/Hero/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Hero'; 2 | -------------------------------------------------------------------------------- /src/components/ChartCard/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './ChartCard'; 2 | -------------------------------------------------------------------------------- /src/components/Dropdown/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './Dropdown'; 2 | -------------------------------------------------------------------------------- /src/constants/order.ts: -------------------------------------------------------------------------------- 1 | export const BALANCE_FRACTIONS = [25, 50, 75, 100]; 2 | -------------------------------------------------------------------------------- /src/pages/Assets/Exchanges/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './Exchanges'; 2 | -------------------------------------------------------------------------------- /src/pages/Assets/Options/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Options'; 2 | -------------------------------------------------------------------------------- /src/pages/Assets/Overview/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Overview'; 2 | -------------------------------------------------------------------------------- /src/pages/Assets/Transfers/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './Transfers'; 2 | -------------------------------------------------------------------------------- /src/pages/Synths/Overview/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Overview'; 2 | -------------------------------------------------------------------------------- /src/components/NetworkInfo/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './NetworkInfo'; 2 | -------------------------------------------------------------------------------- /src/components/WalletPopup/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './WalletPopup'; 2 | -------------------------------------------------------------------------------- /src/pages/Assets/Options/Banner/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Banner'; 2 | -------------------------------------------------------------------------------- /src/pages/Assets/Options/Markets/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Markets'; 2 | -------------------------------------------------------------------------------- /src/pages/Options/Market/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './MarketContainer'; 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | package.json 2 | *.json 3 | *.min.d.ts 4 | *.min.js 5 | /README.md 6 | -------------------------------------------------------------------------------- /src/components/ChangePercent/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './ChangePercent'; 2 | -------------------------------------------------------------------------------- /src/components/DropdownPanel/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './DropdownPanel'; 2 | -------------------------------------------------------------------------------- /src/components/TrendLineChart/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './TrendLineChart'; 2 | -------------------------------------------------------------------------------- /src/components/TxErrorMessage/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './TxErrorMessage'; 2 | -------------------------------------------------------------------------------- /src/components/WalletPaginator/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './WalletPaginator'; 2 | -------------------------------------------------------------------------------- /src/pages/Assets/Overview/Dashboard/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './Dashboard'; 2 | -------------------------------------------------------------------------------- /src/pages/Loans/components/Dashboard/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './Dashboard'; 2 | -------------------------------------------------------------------------------- /src/pages/Loans/components/MyLoans/Loans/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './Loans'; 2 | -------------------------------------------------------------------------------- /src/pages/Loans/components/MyLoans/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './MyLoans'; 2 | -------------------------------------------------------------------------------- /src/pages/Options/Home/HotMarkets/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './HotMarkets'; 2 | -------------------------------------------------------------------------------- /src/pages/Options/Market/ChartCard/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './ChartCard'; 2 | -------------------------------------------------------------------------------- /src/pages/Options/Market/TradeCard/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './TradeCard'; 2 | -------------------------------------------------------------------------------- /src/pages/Root/components/AppBanner/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './AppBanner'; 2 | -------------------------------------------------------------------------------- /src/pages/Root/components/AppHeader/Logo/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Logo'; 2 | -------------------------------------------------------------------------------- /src/pages/Root/components/AppHeader/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './AppHeader'; 2 | -------------------------------------------------------------------------------- /src/pages/Synths/Overview/SynthInfo/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './SynthInfo'; 2 | -------------------------------------------------------------------------------- /src/pages/Trade/components/ChartCard/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './ChartCard'; 2 | -------------------------------------------------------------------------------- /src/components/BaseTradingPairs/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './BaseTradingPairs'; 2 | -------------------------------------------------------------------------------- /src/components/Currency/CurrencyIcon/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './CurrencyIcon'; 2 | -------------------------------------------------------------------------------- /src/components/Currency/CurrencyName/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './CurrencyName'; 2 | -------------------------------------------------------------------------------- /src/components/Currency/CurrencyPair/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './CurrencyPair'; 2 | -------------------------------------------------------------------------------- /src/pages/Assets/Overview/YourSynths/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './YourSynths'; 2 | -------------------------------------------------------------------------------- /src/pages/Home/ExchangeFeatures/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './ExchangeFeatures'; 2 | -------------------------------------------------------------------------------- /src/pages/Options/Home/MarketsTable/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './MarketsTable'; 2 | -------------------------------------------------------------------------------- /src/pages/Root/components/HomeLayout/Footer/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Footer'; 2 | -------------------------------------------------------------------------------- /src/pages/Root/components/HomeLayout/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './HomeLayout'; 2 | -------------------------------------------------------------------------------- /src/pages/Root/components/MainLayout/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './MainLayout'; 2 | -------------------------------------------------------------------------------- /src/pages/Synths/Home/SynthsSection/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './SynthsSection'; 2 | -------------------------------------------------------------------------------- /src/pages/Synths/Overview/SynthChart/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './SynthChart'; 2 | -------------------------------------------------------------------------------- /src/pages/Synths/Overview/SynthMarkets/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './SynthMarkets'; 2 | -------------------------------------------------------------------------------- /src/components/DismissableMessage/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './DismissableMessage'; 2 | -------------------------------------------------------------------------------- /src/components/WalletAddressTable/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './WalletAddressTable'; 2 | -------------------------------------------------------------------------------- /src/pages/Loans/components/Actions/index.ts: -------------------------------------------------------------------------------- 1 | export { default, ActionTypes } from './Actions'; 2 | -------------------------------------------------------------------------------- /src/pages/Loans/components/LiquidateCard/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './LiquidateCard'; 2 | -------------------------------------------------------------------------------- /src/pages/Loans/components/LoanCards/RepayLoan/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './RepayLoan'; 2 | -------------------------------------------------------------------------------- /src/pages/Loans/components/MyLoans/Activity/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './Activity'; 2 | -------------------------------------------------------------------------------- /src/pages/Options/CreateMarketModal/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './CreateMarketModal'; 2 | -------------------------------------------------------------------------------- /src/pages/Options/Home/ExploreMarkets/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './ExploreMarkets'; 2 | -------------------------------------------------------------------------------- /src/pages/Options/Home/MarketCreation/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './MarketCreation'; 2 | -------------------------------------------------------------------------------- /src/pages/Options/Market/ChartCard/PriceChart/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './PriceChart'; 2 | -------------------------------------------------------------------------------- /src/pages/Options/Market/MarketInfoModal/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './MarketInfoModal'; 2 | -------------------------------------------------------------------------------- /src/pages/Options/Market/components/SideIcon/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './SideIcon'; 2 | -------------------------------------------------------------------------------- /src/pages/Options/components/NetworkFees/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './NetworkFees'; 2 | -------------------------------------------------------------------------------- /src/pages/Root/components/AppHeader/UserInfo/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './UserInfo'; 2 | -------------------------------------------------------------------------------- /src/pages/Root/components/ProtectedRoute/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './ProtectedRoute'; 2 | -------------------------------------------------------------------------------- /src/pages/Trade/components/BlurBackground/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './BlurBackground'; 2 | -------------------------------------------------------------------------------- /src/pages/Trade/components/OrderBookCard/constants.ts: -------------------------------------------------------------------------------- 1 | export const REFRESH_INTERVAL = 10000; 2 | -------------------------------------------------------------------------------- /src/pages/Trade/components/OrderBookCard/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './OrderBookCard'; 2 | -------------------------------------------------------------------------------- /src/pages/shared/components/NewUserPromo/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './NewUserPromo'; 2 | -------------------------------------------------------------------------------- /src/pages/shared/components/SelectCRatio/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './SelectCRatio'; 2 | -------------------------------------------------------------------------------- /src/pages/shared/components/SelectGasMenu/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './SelectGasMenu'; 2 | -------------------------------------------------------------------------------- /src/pages/shared/components/ViewLinkCell/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './ViewLinkCell'; 2 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Synthetixio/synthetix-exchange/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /src/pages/Assets/Overview/Dashboard/BalanceChart/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './BalanceChart'; 2 | -------------------------------------------------------------------------------- /src/pages/Assets/Overview/Dashboard/TotalBalance/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './TotalBalance'; 2 | -------------------------------------------------------------------------------- /src/pages/Assets/components/AssetsNavigation/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './AssetsNavigation'; 2 | -------------------------------------------------------------------------------- /src/pages/Loans/components/MyLoans/Liquidations/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './Liquidations'; 2 | -------------------------------------------------------------------------------- /src/pages/Options/Home/components/TimeRemaining/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './TimeRemaining'; 2 | -------------------------------------------------------------------------------- /src/pages/Options/Market/ChartCard/OptionsChart/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './OptionsChart'; 2 | -------------------------------------------------------------------------------- /src/pages/Options/Market/TransactionsCard/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './TransactionsCard'; 2 | -------------------------------------------------------------------------------- /src/pages/Options/components/MarketSentiment/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './MarketSentiment'; 2 | -------------------------------------------------------------------------------- /src/pages/Root/components/AppHeader/SupportLink/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './SupportLink'; 2 | -------------------------------------------------------------------------------- /src/pages/Root/components/AppHeader/ThemeToggle/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './ThemeToggle'; 2 | -------------------------------------------------------------------------------- /src/pages/Root/components/AppHeader/WalletMenu/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './WalletMenu'; 2 | -------------------------------------------------------------------------------- /src/pages/Synths/Home/SynthsSection/SynthsCharts/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './SynthsCharts'; 2 | -------------------------------------------------------------------------------- /src/pages/Synths/Home/SynthsSection/SynthsTable/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './SynthsTable'; 2 | -------------------------------------------------------------------------------- /src/pages/Trade/components/CreateOrderCard/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './CreateOrderCard'; 2 | -------------------------------------------------------------------------------- /src/pages/shared/components/MarketsSection/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './MarketsSection'; 2 | -------------------------------------------------------------------------------- /src/pages/Assets/Overview/Dashboard/SynthBreakdown/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './SynthBreakdown'; 2 | -------------------------------------------------------------------------------- /src/pages/Loans/components/LoanCards/CloseLoanCard/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './CloseLoanCard'; 2 | -------------------------------------------------------------------------------- /src/pages/Options/components/NewToBinaryOptions/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './NewToBinaryOptions'; 2 | -------------------------------------------------------------------------------- /src/pages/Root/components/MaintenanceMessage/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './MaintenanceMessage'; 2 | -------------------------------------------------------------------------------- /src/pages/Trade/components/ChartCard/PairListPanel/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './PairListPanel'; 2 | -------------------------------------------------------------------------------- /src/components/RechartsResponsiveContainer/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './RechartsResponsiveContainer'; 2 | -------------------------------------------------------------------------------- /src/pages/Loans/components/LoanCards/BlockingOverlay/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './BlockingOverlay'; 2 | -------------------------------------------------------------------------------- /src/pages/Loans/components/LoanCards/LoanWarningModal/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './LoanWarningModal'; 2 | -------------------------------------------------------------------------------- /src/pages/Loans/components/LoanCards/ModifyCollateral/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './ModifyCollateral'; 2 | -------------------------------------------------------------------------------- /src/pages/Options/Market/TradeCard/BiddingPhaseCard/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './BiddingPhaseCard'; 2 | -------------------------------------------------------------------------------- /src/pages/Options/Market/TradeCard/MaturityPhaseCard/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './MaturityPhaseCard'; 2 | -------------------------------------------------------------------------------- /src/pages/Options/Market/TradeCard/TradingPhaseCard/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './TradingPhaseCard'; 2 | -------------------------------------------------------------------------------- /src/pages/Options/Market/TradeCard/components/OptionResult/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './OptionResult'; 2 | -------------------------------------------------------------------------------- /src/pages/Options/Market/TradeCard/components/ResultCard/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './ResultCard'; 2 | -------------------------------------------------------------------------------- /src/pages/Root/components/AppHeader/MobileAppHeader/Dropdown/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Dropdown'; 2 | -------------------------------------------------------------------------------- /src/pages/Root/components/AppHeader/MobileAppHeader/Overlay/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Overlay'; 2 | -------------------------------------------------------------------------------- /src/pages/Root/components/AppHeader/MobileAppHeader/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './MobileAppHeader'; 2 | -------------------------------------------------------------------------------- /src/pages/shared/components/MarketsSection/MarketsCharts/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './MarketsCharts'; 2 | -------------------------------------------------------------------------------- /src/pages/shared/components/MarketsSection/MarketsTable/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './MarketsTable'; 2 | -------------------------------------------------------------------------------- /src/components/deprecated/Table/index.js: -------------------------------------------------------------------------------- 1 | export { Table, Tr, Thead, Tbody, Th, Td, DataLabel } from './Table'; 2 | -------------------------------------------------------------------------------- /src/pages/Options/Market/TradeCard/components/BidNetworkFees/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './BidNetworkFees'; 2 | -------------------------------------------------------------------------------- /src/pages/Options/Market/TransactionsCard/YourTransactions/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './YourTransactions'; 2 | -------------------------------------------------------------------------------- /src/utils/history.js: -------------------------------------------------------------------------------- 1 | import { createHashHistory } from 'history'; 2 | 3 | export default createHashHistory(); 4 | -------------------------------------------------------------------------------- /src/ducks/types.ts: -------------------------------------------------------------------------------- 1 | import rootReducer from './index'; 2 | 3 | export type RootState = ReturnType; 4 | -------------------------------------------------------------------------------- /src/pages/Options/Market/TransactionsCard/PendingTransactions/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './PendingTransactions'; 2 | -------------------------------------------------------------------------------- /src/pages/Options/Market/TransactionsCard/RecentTransactions/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './RecentTransactions'; 2 | -------------------------------------------------------------------------------- /src/assets/fonts/apercu-bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Synthetixio/synthetix-exchange/HEAD/src/assets/fonts/apercu-bold.eot -------------------------------------------------------------------------------- /src/assets/fonts/apercu-bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Synthetixio/synthetix-exchange/HEAD/src/assets/fonts/apercu-bold.ttf -------------------------------------------------------------------------------- /src/assets/fonts/apercu-bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Synthetixio/synthetix-exchange/HEAD/src/assets/fonts/apercu-bold.woff -------------------------------------------------------------------------------- /src/assets/fonts/apercu-light.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Synthetixio/synthetix-exchange/HEAD/src/assets/fonts/apercu-light.eot -------------------------------------------------------------------------------- /src/assets/fonts/apercu-light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Synthetixio/synthetix-exchange/HEAD/src/assets/fonts/apercu-light.ttf -------------------------------------------------------------------------------- /src/assets/images/spinner-big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Synthetixio/synthetix-exchange/HEAD/src/assets/images/spinner-big.png -------------------------------------------------------------------------------- /src/pages/Options/Market/TransactionsCard/components/TransactionsTable/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './TransactionsTable'; 2 | -------------------------------------------------------------------------------- /src/assets/fonts/apercu-bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Synthetixio/synthetix-exchange/HEAD/src/assets/fonts/apercu-bold.woff2 -------------------------------------------------------------------------------- /src/assets/fonts/apercu-light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Synthetixio/synthetix-exchange/HEAD/src/assets/fonts/apercu-light.woff -------------------------------------------------------------------------------- /src/assets/fonts/apercu-light.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Synthetixio/synthetix-exchange/HEAD/src/assets/fonts/apercu-light.woff2 -------------------------------------------------------------------------------- /src/assets/fonts/apercu-medium.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Synthetixio/synthetix-exchange/HEAD/src/assets/fonts/apercu-medium.eot -------------------------------------------------------------------------------- /src/assets/fonts/apercu-medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Synthetixio/synthetix-exchange/HEAD/src/assets/fonts/apercu-medium.ttf -------------------------------------------------------------------------------- /src/assets/fonts/apercu-medium.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Synthetixio/synthetix-exchange/HEAD/src/assets/fonts/apercu-medium.woff -------------------------------------------------------------------------------- /src/assets/fonts/apercu-medium.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Synthetixio/synthetix-exchange/HEAD/src/assets/fonts/apercu-medium.woff2 -------------------------------------------------------------------------------- /src/assets/fonts/apercu-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Synthetixio/synthetix-exchange/HEAD/src/assets/fonts/apercu-regular.eot -------------------------------------------------------------------------------- /src/assets/fonts/apercu-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Synthetixio/synthetix-exchange/HEAD/src/assets/fonts/apercu-regular.ttf -------------------------------------------------------------------------------- /src/assets/fonts/apercu-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Synthetixio/synthetix-exchange/HEAD/src/assets/fonts/apercu-regular.woff -------------------------------------------------------------------------------- /src/assets/images/etherscan-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Synthetixio/synthetix-exchange/HEAD/src/assets/images/etherscan-logo.png -------------------------------------------------------------------------------- /src/assets/images/spinner-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Synthetixio/synthetix-exchange/HEAD/src/assets/images/spinner-small.png -------------------------------------------------------------------------------- /public/images/synthetix-logo-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Synthetixio/synthetix-exchange/HEAD/public/images/synthetix-logo-small.png -------------------------------------------------------------------------------- /src/assets/fonts/apercu-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Synthetixio/synthetix-exchange/HEAD/src/assets/fonts/apercu-regular.woff2 -------------------------------------------------------------------------------- /src/components/Input/constants.ts: -------------------------------------------------------------------------------- 1 | export const INPUT_SIZES = { 2 | xs: '32px', 3 | sm: '40px', 4 | md: '42px', 5 | lg: '48px', 6 | }; 7 | -------------------------------------------------------------------------------- /src/pages/Options/Market/TradeCard/BiddingPhaseCard/types.ts: -------------------------------------------------------------------------------- 1 | export type CurrentPosition = { 2 | bid: number; 3 | payout: number; 4 | }; 5 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": true, 3 | "printWidth": 100, 4 | "semi": true, 5 | "singleQuote": true, 6 | "trailingComma": "es5" 7 | } 8 | -------------------------------------------------------------------------------- /src/utils/rates.js: -------------------------------------------------------------------------------- 1 | export const getExchangeRatesForCurrencies = (rates, base, quote) => 2 | rates === null ? 0 : rates[base] * (1 / rates[quote]); 3 | -------------------------------------------------------------------------------- /src/components/Table/constants.ts: -------------------------------------------------------------------------------- 1 | export const TABLE_PALETTE = { 2 | PRIMARY: 'primary', 3 | LIGHT: 'light-secondary', 4 | STRIPED: 'striped', 5 | }; 6 | -------------------------------------------------------------------------------- /src/components/Icons/index.ts: -------------------------------------------------------------------------------- 1 | import Arrow from './Arrow'; 2 | import SnowflakeCircle from './SnowflakeCircle'; 3 | 4 | export { Arrow, SnowflakeCircle }; 5 | -------------------------------------------------------------------------------- /src/pages/Trade/components/ChartCard/types.ts: -------------------------------------------------------------------------------- 1 | export type ChartData = { 2 | rates: any[]; 3 | low24H: number; 4 | high24H: number; 5 | change24H: number; 6 | }; 7 | -------------------------------------------------------------------------------- /src/utils/transactions.js: -------------------------------------------------------------------------------- 1 | import { GAS_LIMIT_BUFFER } from '../constants/transaction'; 2 | 3 | export const normalizeGasLimit = (gasLimit) => gasLimit + GAS_LIMIT_BUFFER; 4 | -------------------------------------------------------------------------------- /.storybook/addons.js: -------------------------------------------------------------------------------- 1 | import 'storybook-addon-styled-component-theme/dist/register'; 2 | import '@storybook/addon-backgrounds/register'; 3 | import '@storybook/addon-knobs/register'; 4 | -------------------------------------------------------------------------------- /src/typings/styled-components.d.ts: -------------------------------------------------------------------------------- 1 | import { ThemeInterface } from 'styles/theme'; 2 | 3 | declare module 'styled-components' { 4 | interface DefaultTheme extends ThemeInterface {} 5 | } 6 | -------------------------------------------------------------------------------- /.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "processors": ["stylelint-processor-styled-components"], 3 | "extends": [ 4 | "stylelint-config-recommended", 5 | "stylelint-config-styled-components" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /src/assets/images/menu-arrow-down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/images/arrow-down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/images/sort-up.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/ducks/options/index.ts: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | 3 | import pendingTransaction from './pendingTransaction'; 4 | 5 | export default combineReducers({ 6 | pendingTransaction, 7 | }); 8 | -------------------------------------------------------------------------------- /.storybook/main.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | stories: ['../src/**/*.stories.js'], 3 | addons: [ 4 | '@storybook/preset-create-react-app', 5 | '@storybook/addon-actions', 6 | '@storybook/addon-links', 7 | ], 8 | }; 9 | -------------------------------------------------------------------------------- /src/assets/images/sort-down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/images/sort.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/Input/TextInput.tsx: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | import Input from './Input'; 4 | 5 | export const TextInput = styled(Input).attrs({ type: 'text' })``; 6 | 7 | export default TextInput; 8 | -------------------------------------------------------------------------------- /src/styles/theme/fonts.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | light: `'apercu-light', sans-serif`, 3 | regular: `'apercu-regular', sans-serif`, 4 | medium: `'apercu-medium', sans-serif`, 5 | bold: `'apercu-bold', sans-serif`, 6 | }; 7 | -------------------------------------------------------------------------------- /src/assets/images/trend-up.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/images/trend-down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/Input/NumericInput.tsx: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | import Input from './Input'; 4 | 5 | export const NumericInput = styled(Input).attrs({ type: 'number' })``; 6 | 7 | export default NumericInput; 8 | -------------------------------------------------------------------------------- /src/styles/theme/colors.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | green: '#10BA97', 3 | white: '#FFFFFF', 4 | red: '#D94454', 5 | hyperlink: '#A08AFF', 6 | buttonDefault: '#795DF5', 7 | buttonHover: '#947BFF', 8 | icons: '#5641F2', 9 | }; 10 | -------------------------------------------------------------------------------- /src/constants/storage.ts: -------------------------------------------------------------------------------- 1 | export const LOCAL_STORAGE_KEYS = { 2 | WALLET_DERIVATION_PATH: 'derivationPath', 3 | APP_BANNER_DISMISSED: 'appBannerDismissed', 4 | BO_WITHDRAWALS_DISABLED_TOOLTIP_DISMISSED: 'boWithdrawalsDisabledTooltipDismissed', 5 | }; 6 | -------------------------------------------------------------------------------- /src/components/Currency/index.js: -------------------------------------------------------------------------------- 1 | import CurrencyIcon from './CurrencyIcon'; 2 | import CurrencyName from './CurrencyName'; 3 | import CurrencyPair from './CurrencyPair'; 4 | 5 | export default { Icon: CurrencyIcon, Name: CurrencyName, Pair: CurrencyPair }; 6 | -------------------------------------------------------------------------------- /src/pages/Loans/components/LoanCards/commonStyles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | import DismissableMessage from '../../../../components/DismissableMessage'; 3 | 4 | export const TxErrorMessage = styled(DismissableMessage)` 5 | margin-top: 8px; 6 | `; 7 | -------------------------------------------------------------------------------- /src/ducks/wallet/index.ts: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | 3 | import walletDetails from './walletDetails'; 4 | import walletBalances from './walletBalances'; 5 | 6 | export default combineReducers({ 7 | walletDetails, 8 | walletBalances, 9 | }); 10 | -------------------------------------------------------------------------------- /src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /src/pages/Loans/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { LoanProvider } from './contexts/LoanContext'; 3 | import Loans from './Loans'; 4 | 5 | const LoanWrapper = () => ( 6 | 7 | 8 | 9 | ); 10 | 11 | export default LoanWrapper; 12 | -------------------------------------------------------------------------------- /.storybook/providers/withReduxProvider.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Provider } from 'react-redux'; 3 | 4 | import store from '../../src/config/store'; 5 | 6 | const withReduxProvider = story => {story()}; 7 | 8 | export default withReduxProvider; 9 | -------------------------------------------------------------------------------- /src/assets/images/arrow-hyperlink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/pages/shared/components/MarketsSection/constants.ts: -------------------------------------------------------------------------------- 1 | import { SYNTHS_MAP } from 'constants/currency'; 2 | 3 | export const ASSET_FILTERS = [ 4 | { 5 | asset: SYNTHS_MAP.sUSD, 6 | }, 7 | { 8 | asset: SYNTHS_MAP.sBTC, 9 | }, 10 | { 11 | asset: SYNTHS_MAP.sETH, 12 | }, 13 | ]; 14 | -------------------------------------------------------------------------------- /src/assets/images/options-line.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/constants/transaction.ts: -------------------------------------------------------------------------------- 1 | export const TRANSACTION_STATUS = { 2 | WAITING: 'waiting', 3 | PENDING: 'pending', 4 | CONFIRMED: 'confirmed', 5 | FAILED: 'failed', 6 | CANCELLED: 'cancelled', 7 | }; 8 | 9 | export const GAS_LIMIT_BUFFER = 15000; 10 | export const DEFAULT_GAS_LIMIT = 500000; 11 | -------------------------------------------------------------------------------- /src/components/Typography/index.ts: -------------------------------------------------------------------------------- 1 | import { DataLarge, DataMedium, DataSmall } from './Data'; 2 | import { LabelMedium, LabelSmall } from './Label'; 3 | import { HeadingMedium, HeadingSmall } from './Heading'; 4 | 5 | export { DataLarge, DataMedium, DataSmall, LabelMedium, LabelSmall, HeadingMedium, HeadingSmall }; 6 | -------------------------------------------------------------------------------- /src/assets/images/menu-hamburger.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/ducks/loans/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | 3 | import myLoans from './myLoans'; 4 | import contractInfo from './contractInfo'; 5 | import allLiquidations from './allLiquidations'; 6 | 7 | export default combineReducers({ 8 | myLoans, 9 | allLiquidations, 10 | contractInfo, 11 | }); 12 | -------------------------------------------------------------------------------- /src/pages/Assets/Overview/Overview.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | import Dashboard from './Dashboard'; 4 | import YourSynths from './YourSynths'; 5 | 6 | export const Overview: FC = () => ( 7 | <> 8 | 9 | 10 | 11 | ); 12 | 13 | export default Overview; 14 | -------------------------------------------------------------------------------- /src/pages/Synths/Home/SynthsSection/constants.ts: -------------------------------------------------------------------------------- 1 | import { CATEGORY_MAP } from 'constants/currency'; 2 | 3 | export const CATEGORY_FILTERS = [ 4 | CATEGORY_MAP.crypto, 5 | CATEGORY_MAP.forex, 6 | CATEGORY_MAP.equities, 7 | CATEGORY_MAP.commodity, 8 | ]; 9 | 10 | export const SYNTHS_REFRESH_INTERVAL_MS = 30000; 11 | -------------------------------------------------------------------------------- /.storybook/providers/withReactRouterProvider.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { BrowserRouter as Router } from 'react-router-dom'; 3 | 4 | import store from '../../src/config/store'; 5 | 6 | const withReactRouterProvider = story => {story()}; 7 | 8 | export default withReactRouterProvider; 9 | -------------------------------------------------------------------------------- /src/styles/theme/types.ts: -------------------------------------------------------------------------------- 1 | export type ThemeColors = { 2 | brand: string; 3 | surfaceL1: string; 4 | surfaceL2: string; 5 | surfaceL3: string; 6 | accentL1: string; 7 | accentL2: string; 8 | fontPrimary: string; 9 | fontSecondary: string; 10 | fontTertiary: string; 11 | }; 12 | 13 | export type Theme = 'light' | 'dark'; 14 | -------------------------------------------------------------------------------- /src/utils/currency.ts: -------------------------------------------------------------------------------- 1 | import { currencyKeyToIconMap, CurrencyKey } from 'constants/currency'; 2 | 3 | export const getCurrencyKeyIcon = (currencyKey: CurrencyKey) => currencyKeyToIconMap[currencyKey]; 4 | 5 | export const getCurrencyKeyURLPath = (currencyKey: CurrencyKey) => 6 | `https:///www.synthetix.io/assets/synths/svg/${currencyKey}.svg`; 7 | -------------------------------------------------------------------------------- /src/assets/images/menu-close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/currencies/crypto/LTC.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/currencies/crypto/MKR.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/pages/Markets/Markets.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import MarketsSection from 'pages/shared/components/MarketsSection'; 4 | import NewUserPromo from 'pages/shared/components/NewUserPromo'; 5 | 6 | export const Markets = () => ( 7 | <> 8 | 9 | 10 | 11 | ); 12 | 13 | export default Markets; 14 | -------------------------------------------------------------------------------- /src/components/Input/common.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | import { FlexDivCentered } from 'shared/commonStyles'; 3 | 4 | export const Label = styled(FlexDivCentered)` 5 | justify-content: space-between; 6 | margin-bottom: 6px; 7 | `; 8 | 9 | export const InputContainer = styled.div` 10 | width: 100%; 11 | position: relative; 12 | `; 13 | -------------------------------------------------------------------------------- /src/pages/Synths/mockData.ts: -------------------------------------------------------------------------------- 1 | export const mockRates = (periodInHours: number, rate = 1, points = 100) => { 2 | let now = Date.now(); 3 | 4 | const rates = []; 5 | 6 | for (let i = 0; i < points; i++) { 7 | rates.unshift({ 8 | timestamp: now, 9 | rate, 10 | }); 11 | now -= 1000 * 60 * periodInHours; 12 | } 13 | 14 | return rates; 15 | }; 16 | -------------------------------------------------------------------------------- /src/pages/Synths/Home/Home.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | import NewUserPromo from 'pages/shared/components/NewUserPromo'; 4 | import SynthsSection from './SynthsSection'; 5 | import Hero from './Hero'; 6 | 7 | export const Home: FC = () => ( 8 | <> 9 | 10 | 11 | 12 | 13 | ); 14 | 15 | export default Home; 16 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /src/assets/currencies/crypto/LEND.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/assets/images/pencil.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/Button/index.js: -------------------------------------------------------------------------------- 1 | import { ButtonFilter, ButtonFilterWithDropdown } from './ButtonFilter'; 2 | import ButtonPrimary, { ButtonPrimarySmall } from './ButtonPrimary'; 3 | import ButtonSort from './ButtonSort'; 4 | import Button from './Button'; 5 | 6 | export { 7 | ButtonFilter, 8 | ButtonPrimary, 9 | ButtonPrimarySmall, 10 | ButtonFilterWithDropdown, 11 | ButtonSort, 12 | Button, 13 | }; 14 | -------------------------------------------------------------------------------- /src/constants/rates.ts: -------------------------------------------------------------------------------- 1 | import { CurrencyKey } from './currency'; 2 | 3 | export type BaseRateUpdate = { 4 | timestamp: number; 5 | rate: number; 6 | }; 7 | 8 | export type BaseRateUpdates = BaseRateUpdate[]; 9 | 10 | export type RateUpdate = BaseRateUpdate & { 11 | block: number; 12 | synth: CurrencyKey; 13 | date: string; 14 | hash: string; 15 | }; 16 | 17 | export type RateUpdates = RateUpdate[]; 18 | -------------------------------------------------------------------------------- /src/styles/theme/dark.ts: -------------------------------------------------------------------------------- 1 | import { ThemeColors } from './types'; 2 | 3 | export const themeColors: ThemeColors = { 4 | brand: '#FFFFFF', 5 | surfaceL1: '#0E0D14', 6 | surfaceL2: '#14131E', 7 | surfaceL3: '#1C1A28', 8 | accentL1: '#262439', 9 | accentL2: '#3B375B', 10 | fontPrimary: '#FFFFFF', 11 | fontSecondary: '#CACAF1', 12 | fontTertiary: '#9492C4', 13 | }; 14 | 15 | export default themeColors; 16 | -------------------------------------------------------------------------------- /src/styles/theme/light.ts: -------------------------------------------------------------------------------- 1 | import { ThemeColors } from './types'; 2 | 3 | export const themeColors: ThemeColors = { 4 | brand: '#1E1A31', 5 | surfaceL1: '#F2F2F6', 6 | surfaceL2: '#F7F8FB', 7 | surfaceL3: '#FFFFFF', 8 | accentL1: '#F3F3FE', 9 | accentL2: '#E8E7FD', 10 | fontPrimary: '#484697', 11 | fontSecondary: '#6F6E98', 12 | fontTertiary: '#9492C4', 13 | }; 14 | 15 | export default themeColors; 16 | -------------------------------------------------------------------------------- /src/assets/currencies/crypto/XRP.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/images/finish.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/i18n.ts: -------------------------------------------------------------------------------- 1 | import i18n from 'i18next'; 2 | import { initReactI18next } from 'react-i18next'; 3 | 4 | import enTranslation from 'shared/translations/en.json'; 5 | 6 | i18n.use(initReactI18next).init({ 7 | resources: { 8 | en: { translation: enTranslation }, 9 | }, 10 | fallbackLng: 'en', 11 | lng: 'en', 12 | react: { 13 | useSuspense: true, 14 | wait: true, 15 | }, 16 | }); 17 | 18 | export default i18n; 19 | -------------------------------------------------------------------------------- /src/components/Dropdown/Dropdown.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | const Dropdown = ({ header, body }) => { 5 | return ( 6 | 7 |
{header}
8 | {body} 9 |
10 | ); 11 | }; 12 | 13 | const Container = styled.div``; 14 | const Header = styled.div``; 15 | const Body = styled.div``; 16 | 17 | export default Dropdown; 18 | -------------------------------------------------------------------------------- /.storybook/libs/i18n.js: -------------------------------------------------------------------------------- 1 | import i18n from 'i18next'; 2 | import { initReactI18next } from 'react-i18next'; 3 | 4 | import enTranslation from '../../src/shared/translations/en.json'; 5 | 6 | i18n.use(initReactI18next).init({ 7 | resources: { 8 | en: { translation: enTranslation }, 9 | }, 10 | lng: 'en', 11 | fallbackLng: 'en', 12 | react: { 13 | useSuspense: false, 14 | wait: true, 15 | }, 16 | }); 17 | 18 | export default i18n; 19 | -------------------------------------------------------------------------------- /src/components/Link/Link.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | import { Link as RouterLink, ExternalLink } from 'shared/commonStyles'; 4 | 5 | type LinkProps = { 6 | to: string; 7 | isExternal?: boolean; 8 | onClick?: () => void; 9 | }; 10 | 11 | export const Link: FC = ({ to, isExternal, ...rest }) => 12 | isExternal ? : ; 13 | 14 | export default Link; 15 | -------------------------------------------------------------------------------- /src/assets/currencies/crypto/EOS.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/Currency/commonStyles.tsx: -------------------------------------------------------------------------------- 1 | import styled, { css } from 'styled-components'; 2 | 3 | import { dataMediumCSS } from '../Typography/Data'; 4 | 5 | export const Container = styled.span<{ showIcon?: boolean }>` 6 | ${(props) => 7 | props.showIcon && 8 | css` 9 | display: inline-grid; 10 | align-items: center; 11 | grid-auto-flow: column; 12 | grid-gap: 8px; 13 | `} 14 | ${dataMediumCSS}; 15 | text-transform: none; 16 | `; 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | .env 21 | 22 | npm-debug.log* 23 | yarn-debug.log* 24 | yarn-error.log* 25 | 26 | .yalc 27 | yalc.lock 28 | -------------------------------------------------------------------------------- /src/components/Card/Card.stories.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Card from './Card'; 4 | import { HeadingSmall, DataMedium } from '../Typography'; 5 | 6 | export default { 7 | title: 'Card', 8 | }; 9 | 10 | export const card = () => ( 11 | 12 | 13 | Card Header 14 | 15 | 16 | Card Body 17 | 18 | 19 | ); 20 | -------------------------------------------------------------------------------- /src/components/Card/CardBody.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | export type CardBodyProps = { 5 | children: React.ReactNode; 6 | }; 7 | 8 | const CardBody: FC = ({ children, ...rest }) => ( 9 | {children} 10 | ); 11 | 12 | const Container = styled.div` 13 | position: relative; 14 | padding: 16px 12px 18px 12px; 15 | `; 16 | 17 | export default CardBody; 18 | -------------------------------------------------------------------------------- /src/pages/Root/components/AppHeader/common.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | import { labelSmallCSS } from 'components/Typography/Label'; 3 | 4 | export const BetaLabel = styled.span` 5 | border-radius: 100px; 6 | ${labelSmallCSS}; 7 | text-transform: uppercase; 8 | color: ${(props) => props.theme.colors.fontTertiary}; 9 | background-color: ${(props) => props.theme.colors.accentL1}; 10 | padding: 3px 6px 1px 6px; 11 | margin-left: 6px; 12 | `; 13 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [[headers]] 2 | for = "/*" 3 | [headers.values] 4 | X-Frame-Options = "DENY" 5 | X-XSS-Protection = "1; mode=block" 6 | Referrer-Policy = "no-referrer" 7 | X-Content-Type-Options = "nosniff" 8 | [build.environment] 9 | NODE_OPTIONS = "--max_old_space_size=4096" 10 | NODE_VERSION = "10.16.3" 11 | RUBY_VERSION = "2.6.2" 12 | REACT_APP_CONTEXT = "production" 13 | 14 | [context.branch-deploy.environment] 15 | REACT_APP_CONTEXT = "staging" 16 | 17 | -------------------------------------------------------------------------------- /src/pages/Home/Home.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | import Hero from './Hero'; 4 | import MarketsSection from 'pages/shared/components/MarketsSection'; 5 | import NewUserPromo from 'pages/shared/components/NewUserPromo'; 6 | import ExchangeFeatures from './ExchangeFeatures'; 7 | 8 | const Home: FC = () => ( 9 | <> 10 | 11 | 12 | 13 | 14 | 15 | ); 16 | 17 | export default Home; 18 | -------------------------------------------------------------------------------- /src/components/ChangePercent/ChangePercent.stories.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { ChangePercent } from './ChangePercent'; 3 | 4 | export default { 5 | title: 'Data/Label', 6 | }; 7 | 8 | export const positive = () => ; 9 | export const negative = () => ; 10 | export const positiveLabel = () => ; 11 | export const negativeLabel = () => ; 12 | -------------------------------------------------------------------------------- /src/components/Button/Button.stories.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { action } from '@storybook/addon-actions'; 3 | 4 | import ButtonPrimary, { ButtonPrimarySmall } from './ButtonPrimary'; 5 | 6 | export default { 7 | title: 'Buttons', 8 | }; 9 | 10 | export const primary = () => primary; 11 | 12 | export const primarySmall = () => ( 13 | primary small 14 | ); 15 | -------------------------------------------------------------------------------- /src/assets/currencies/fiat/JPY.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/ducks/trades/utils.ts: -------------------------------------------------------------------------------- 1 | import { HistoricalTrades } from './types'; 2 | import { SYNTHS_MAP } from 'constants/currency'; 3 | 4 | export const normalizeTrades = (trades: HistoricalTrades) => 5 | trades.map((trade) => ({ 6 | ...trade, 7 | price: 8 | trade.toCurrencyKey === SYNTHS_MAP.sUSD 9 | ? trade.fromAmountInUSD / trade.fromAmount 10 | : trade.toAmountInUSD / trade.toAmount, 11 | amount: trade.toCurrencyKey === SYNTHS_MAP.sUSD ? trade.fromAmountInUSD : trade.toAmountInUSD, 12 | })); 13 | -------------------------------------------------------------------------------- /src/assets/images/search.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/pages/Loans/components/LoanCards/CreateLoanCard/CreateLoanCard.stories.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { CreateLoanCard } from './CreateLoanCard'; 3 | import { connectedWalletWithBalances } from '../../../../../../.storybook/mocks/reducers/wallet'; 4 | 5 | export default { 6 | title: 'Loans/Cards', 7 | }; 8 | 9 | export const createLoan = () => ( 10 | 15 | ); 16 | -------------------------------------------------------------------------------- /src/pages/Synths/Synths.tsx: -------------------------------------------------------------------------------- 1 | import React, { lazy, FC } from 'react'; 2 | import { Switch, Route } from 'react-router-dom'; 3 | 4 | import ROUTES from 'constants/routes'; 5 | 6 | const Home = lazy(() => import('./Home')); 7 | const Overview = lazy(() => import('./Overview')); 8 | 9 | export const Synths: FC = () => ( 10 | <> 11 | 12 | 13 | 14 | 15 | 16 | ); 17 | 18 | export default Synths; 19 | -------------------------------------------------------------------------------- /src/pages/Trade/components/ChartCard/PairListPanel/common.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | import { Button } from 'components/Button'; 4 | 5 | export const StyledButton = styled(Button).attrs({ 6 | size: 'sm', 7 | palette: 'secondary', 8 | })` 9 | text-transform: none; 10 | font-size: 12px; 11 | `; 12 | 13 | export const IconButton = styled(StyledButton)` 14 | width: 32px; 15 | display: flex; 16 | align-items: center; 17 | justify-content: center; 18 | > * { 19 | flex-shrink: 0; 20 | } 21 | `; 22 | -------------------------------------------------------------------------------- /src/pages/Root/components/AppHeader/ThemeToggle/ThemeToggle.stories.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { ThemeToggle } from './ThemeToggle'; 3 | import { action } from '@storybook/addon-actions'; 4 | 5 | export default { 6 | title: 'Header', 7 | }; 8 | 9 | const sharedProps = { 10 | toggleTheme: () => action('toggle theme')(), 11 | }; 12 | 13 | export const themeToggleDark = () => ; 14 | export const themeToggleLight = () => ; 15 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "esModuleInterop": true, 8 | "allowSyntheticDefaultImports": true, 9 | "strict": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "module": "esnext", 12 | "moduleResolution": "node", 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "noEmit": true, 16 | "jsx": "react", 17 | "baseUrl": "src" 18 | }, 19 | "include": ["src"] 20 | } 21 | -------------------------------------------------------------------------------- /src/assets/currencies/crypto/BNB.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/currencies/crypto/XMR.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/pages/Root/components/AppHeader/Logo/Logo.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import { ReactComponent as SynthetixLogo } from 'assets/images/synthetix-logo.svg'; 5 | import { media } from 'shared/media'; 6 | 7 | const Logo: FC = (props) => ; 8 | 9 | const StyledSynthetixLogo = styled(SynthetixLogo)` 10 | color: ${(props) => props.theme.colors.brand}; 11 | ${media.small` 12 | width: 75px; 13 | height: 24px; 14 | `} 15 | `; 16 | 17 | export default Logo; 18 | -------------------------------------------------------------------------------- /src/assets/currencies/crypto/ETH.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/images/error-circle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/images/blocked.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "react-app" 4 | ], 5 | "plugins": [ 6 | "prettier" 7 | ], 8 | "rules": { 9 | "prettier/prettier": "error", 10 | "no-mixed-spaces-and-tabs": [ 11 | "warn", 12 | "smart-tabs" 13 | ], 14 | "comma-dangle": [ 15 | "error", 16 | { 17 | "arrays": "always-multiline", 18 | "objects": "always-multiline", 19 | "imports": "always-multiline", 20 | "exports": "always-multiline", 21 | "functions": "never" 22 | } 23 | ] 24 | }, 25 | "settings": { 26 | "import/resolver": { 27 | "typescript": {} 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/components/Typography/Table.tsx: -------------------------------------------------------------------------------- 1 | import { css } from 'styled-components'; 2 | 3 | const tableHeaderCSS = css` 4 | font-family: ${(props) => props.theme.fonts.medium}; 5 | text-transform: uppercase; 6 | `; 7 | 8 | export const tableHeaderSmallCSS = css` 9 | ${tableHeaderCSS}; 10 | font-size: 12px; 11 | `; 12 | 13 | export const tableHeaderLargeCSS = css` 14 | ${tableHeaderCSS}; 15 | font-size: 14px; 16 | `; 17 | 18 | export const tableDataSmallCSS = css` 19 | font-size: 12px; 20 | `; 21 | 22 | export const tableDataLargeCSS = css` 23 | font-size: 14px; 24 | line-height: 1.3; 25 | `; 26 | -------------------------------------------------------------------------------- /src/pages/Trade/components/OrderBookCard/AllTrades.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | import { useAllTradesQuery } from 'queries/myTrades'; 4 | import TradeHistory from './TradeHistory'; 5 | 6 | type AllTradesProps = {}; 7 | 8 | const AllTrades: FC = () => { 9 | const allTradesQuery = useAllTradesQuery(); 10 | 11 | return ( 12 | 17 | ); 18 | }; 19 | 20 | export default AllTrades; 21 | -------------------------------------------------------------------------------- /src/pages/Assets/Overview/Dashboard/SynthBreakdown/mockData.js: -------------------------------------------------------------------------------- 1 | import { SYNTHS_MAP } from 'constants/currency'; 2 | 3 | export const MOCK_DATA = [ 4 | { 5 | name: SYNTHS_MAP.sBTC, 6 | portfolioPercent: 0.4, 7 | }, 8 | { 9 | name: SYNTHS_MAP.sETH, 10 | portfolioPercent: 0.2, 11 | }, 12 | { 13 | name: SYNTHS_MAP.sUSD, 14 | portfolioPercent: 0.2, 15 | }, 16 | { 17 | name: SYNTHS_MAP.sBNB, 18 | portfolioPercent: 0.1, 19 | }, 20 | { 21 | name: SYNTHS_MAP.sLTC, 22 | portfolioPercent: 0.1, 23 | }, 24 | { 25 | name: SYNTHS_MAP.sXRP, 26 | portfolioPercent: 0.1, 27 | }, 28 | ]; 29 | -------------------------------------------------------------------------------- /src/pages/Loans/components/LoanCards/CloseLoanCard/CloseLoanCard.stories.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { CloseLoanCard } from './CloseLoanCard'; 3 | import { connectedWalletWithBalances } from '../../../../../../.storybook/mocks/reducers/wallet'; 4 | import { boolean } from '@storybook/addon-knobs'; 5 | 6 | export default { 7 | title: 'Loans/Cards', 8 | }; 9 | 10 | export const closeLoan = () => ( 11 | 17 | ); 18 | -------------------------------------------------------------------------------- /src/assets/currencies/crypto/DASH.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/pages/Assets/Overview/Dashboard/Dashboard.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import TotalBalance from './TotalBalance'; 5 | import BalanceChart from './BalanceChart'; 6 | import SynthBreakdown from './SynthBreakdown'; 7 | 8 | export const Dashboard = () => ( 9 | 10 | 11 | 12 | 13 | 14 | ); 15 | 16 | const Container = styled.div` 17 | display: grid; 18 | grid-template-columns: 1fr 1fr 1fr; 19 | grid-gap: 8px; 20 | margin-bottom: 8px; 21 | `; 22 | 23 | export default Dashboard; 24 | -------------------------------------------------------------------------------- /src/components/Currency/CurrencyPair/CurrencyPair.stories.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { CurrencyPair } from './CurrencyPair'; 3 | 4 | import { SYNTHS_MAP } from '../../../constants/currency'; 5 | 6 | export default { 7 | title: 'Currency/Pair', 8 | }; 9 | 10 | export const withIcon = () => ( 11 | 16 | ); 17 | 18 | export const withoutIcon = () => ( 19 | 24 | ); 25 | -------------------------------------------------------------------------------- /src/constants/ui.ts: -------------------------------------------------------------------------------- 1 | export const APP_HEADER_HEIGHT = '50px'; 2 | export const MOBILE_APP_HEADER_HEIGHT = '40px'; 3 | export const CARD_HEIGHT = '40px'; 4 | export const SECTION_MARGIN = '8px'; 5 | export const ELEMENT_BORDER_RADIUS = '1px'; 6 | export const CREATE_ORDER_CARD_WIDTH = '282px'; 7 | 8 | export const Z_INDEX = { 9 | BASE: 1, 10 | DROPDOWN: 50, 11 | TOOLTIP: 100, 12 | BLUR_MODAL: 125, 13 | DROPDOWN_PANEL: 150, 14 | MODAL: 1400, 15 | APP_HEADER: 1000, 16 | }; 17 | 18 | export const SEARCH_DEBOUNCE_MS = 300; 19 | export const DEFAULT_REQUEST_REFRESH_INTERVAL = 30000; // 30s 20 | export const SLIPPAGE_THRESHOLD = 0.1; 21 | -------------------------------------------------------------------------------- /src/ducks/index.ts: -------------------------------------------------------------------------------- 1 | import { combineReducers } from '@reduxjs/toolkit'; 2 | 3 | import ui from './ui'; 4 | import wallet from './wallet'; 5 | import synths from './synths'; 6 | import transaction from './transaction'; 7 | import loans from './loans'; 8 | import rates from './rates'; 9 | import historicalRates from './historicalRates'; 10 | import app from './app'; 11 | import markets from './markets'; 12 | import options from './options'; 13 | 14 | export default combineReducers({ 15 | app, 16 | wallet, 17 | ui, 18 | synths, 19 | transaction, 20 | loans, 21 | rates, 22 | historicalRates, 23 | markets, 24 | options, 25 | }); 26 | -------------------------------------------------------------------------------- /src/assets/images/arrow-back.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/pages/Options/Market/contexts/MarketContext.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC, createContext, useContext } from 'react'; 2 | import { OptionsMarketInfo } from 'pages/Options/types'; 3 | 4 | const MarketContext = createContext(null); 5 | 6 | type MarketContextProps = { 7 | children: React.ReactNode; 8 | optionsMarket: OptionsMarketInfo; 9 | }; 10 | 11 | export const MarketProvider: FC = ({ children, optionsMarket }) => ( 12 | {children} 13 | ); 14 | 15 | export const useMarketContext = () => useContext(MarketContext) as OptionsMarketInfo; 16 | -------------------------------------------------------------------------------- /src/shared/hooks/useInterval.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef } from 'react'; 2 | 3 | function useInterval(callback: () => void, delay: number | null) { 4 | const noop = () => {}; 5 | const savedCallback = useRef(noop); 6 | 7 | // Remember the latest callback. 8 | useEffect(() => { 9 | savedCallback.current = callback; 10 | }, [callback]); 11 | 12 | // Set up the interval. 13 | useEffect(() => { 14 | function tick() { 15 | savedCallback.current(); 16 | } 17 | if (delay !== null) { 18 | let id = setInterval(tick, delay); 19 | return () => clearInterval(id); 20 | } 21 | }, [delay]); 22 | } 23 | 24 | export default useInterval; 25 | -------------------------------------------------------------------------------- /src/pages/Options/Market/contexts/BOMContractContext.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC, createContext, useContext } from 'react'; 2 | import { ethers } from 'ethers'; 3 | 4 | const BOMContractContext = createContext(null); 5 | 6 | type BOMContractContextProps = { 7 | children: React.ReactNode; 8 | contract: ethers.Contract; 9 | }; 10 | 11 | export const BOMContractProvider: React.FC = ({ children, contract }) => ( 12 | {children} 13 | ); 14 | 15 | export const useBOMContractContext = () => useContext(BOMContractContext) as ethers.Contract; 16 | -------------------------------------------------------------------------------- /src/components/Typography/Form.tsx: -------------------------------------------------------------------------------- 1 | import { css } from 'styled-components'; 2 | 3 | export const formLabelCSS = css` 4 | font-family: ${(props) => props.theme.fonts.medium}; 5 | text-transform: uppercase; 6 | `; 7 | 8 | export const formLabelSmallCSS = css` 9 | ${formLabelCSS}; 10 | font-size: 12px; 11 | `; 12 | 13 | export const formLabelLargeCSS = css` 14 | ${formLabelCSS}; 15 | font-size: 14px; 16 | `; 17 | 18 | export const formInputSmallCSS = css` 19 | font-size: 12px; 20 | `; 21 | 22 | export const formInputLargeCSS = css` 23 | font-size: 14px; 24 | line-height: 1.3; 25 | `; 26 | 27 | export const formDataCSS = css` 28 | font-size: 12px; 29 | `; 30 | -------------------------------------------------------------------------------- /src/components/Typography/General.tsx: -------------------------------------------------------------------------------- 1 | import { css } from 'styled-components'; 2 | 3 | export const bodyCSS = css` 4 | font-size: 16px; 5 | `; 6 | 7 | export const captionCSS = css` 8 | font-family: ${(props) => props.theme.fonts.medium}; 9 | font-size: 12px; 10 | text-transform: uppercase; 11 | `; 12 | 13 | export const chartDataCSS = css` 14 | font-size: 10px; 15 | `; 16 | 17 | export const sectionTitleCSS = css` 18 | font-family: ${(props) => props.theme.fonts.medium}; 19 | font-size: 14px; 20 | `; 21 | 22 | export const subtitleLargeCSS = css` 23 | font-size: 24px; 24 | `; 25 | 26 | export const subtitleSmallCSS = css` 27 | font-size: 24px; 28 | `; 29 | -------------------------------------------------------------------------------- /src/components/TxErrorMessage/TxErrorMessage.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import DismissableMessage from 'components/DismissableMessage'; 5 | 6 | type TxErrorMessageProps = { 7 | children: React.ReactNode; 8 | onDismiss: () => void; 9 | }; 10 | 11 | export const TxErrorMessage: FC = ({ children, onDismiss, ...rest }) => ( 12 | 13 | {children} 14 | 15 | ); 16 | 17 | const ErrorMessage = styled(DismissableMessage)` 18 | margin-top: 8px; 19 | `; 20 | 21 | export default TxErrorMessage; 22 | -------------------------------------------------------------------------------- /src/components/Table/common.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import { formatCurrencyWithSign } from 'utils/formatters'; 5 | import { EMPTY_VALUE } from 'constants/placeholder'; 6 | 7 | type CurrencyColProps = { 8 | sign?: string; 9 | value: number | null; 10 | decimals?: number; 11 | }; 12 | export const CurrencyCol: FC = ({ sign = '', value, decimals }) => ( 13 | {value == null ? EMPTY_VALUE : formatCurrencyWithSign(sign, value, decimals)} 14 | ); 15 | 16 | export const RightAlignedCell = styled.div` 17 | display: flex; 18 | width: inherit; 19 | justify-content: flex-end; 20 | `; 21 | -------------------------------------------------------------------------------- /src/assets/images/clock-square.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/components/Typography/Label.tsx: -------------------------------------------------------------------------------- 1 | import styled, { css } from 'styled-components'; 2 | 3 | export const labelCSS = css` 4 | font-family: ${(props) => props.theme.fonts.medium}; 5 | `; 6 | 7 | export const labelSmallCSS = css` 8 | ${labelCSS} 9 | font-size: 12px; 10 | `; 11 | 12 | export const labelMediumCSS = css` 13 | ${labelCSS}; 14 | font-size: 14px; 15 | text-transform: uppercase; 16 | `; 17 | 18 | export const labelLargeCSS = css` 19 | ${labelCSS}; 20 | font-size: 16px; 21 | text-transform: uppercase; 22 | `; 23 | 24 | export const LabelMedium = styled.span` 25 | ${labelMediumCSS} 26 | `; 27 | 28 | export const LabelSmall = styled.span` 29 | ${labelSmallCSS} 30 | `; 31 | -------------------------------------------------------------------------------- /src/ducks/sagas.ts: -------------------------------------------------------------------------------- 1 | import { all } from 'redux-saga/effects'; 2 | 3 | import { watchFetchMarketsRequest } from './markets'; 4 | import { watchFetchWalletBalancesRequest } from './wallet/walletBalances'; 5 | import { watchFetchHistoricalRatesRequest } from './historicalRates'; 6 | import { watchFetchSystemStatusRequest } from './app'; 7 | import { watchFetchRatesRequest } from './rates'; 8 | 9 | const rootSaga = function* () { 10 | yield all([ 11 | watchFetchHistoricalRatesRequest(), 12 | watchFetchMarketsRequest(), 13 | watchFetchWalletBalancesRequest(), 14 | watchFetchRatesRequest(), 15 | watchFetchSystemStatusRequest(), 16 | ]); 17 | }; 18 | 19 | export default rootSaga; 20 | -------------------------------------------------------------------------------- /src/pages/Loans/components/MyLoans/Activity/ViewLink.jsx: -------------------------------------------------------------------------------- 1 | import styled, { css } from 'styled-components'; 2 | 3 | import { ExternalLink } from 'shared/commonStyles'; 4 | import { ReactComponent as ArrowHyperlinkIcon } from 'assets/images/arrow-hyperlink.svg'; 5 | 6 | const ViewLink = styled(ExternalLink)` 7 | color: ${(props) => props.theme.colors.hyperlink}; 8 | box-sizing: border-box; 9 | font-size: 13px; 10 | text-align: center; 11 | ${(props) => 12 | props.isDisabled && 13 | css` 14 | opacity: 0.3; 15 | pointer-events: none; 16 | `} 17 | `; 18 | 19 | export const ArrowIcon = styled(ArrowHyperlinkIcon)` 20 | margin-left: 5px; 21 | `; 22 | 23 | export default ViewLink; 24 | -------------------------------------------------------------------------------- /src/shared/hooks/useDebouncedMemo.ts: -------------------------------------------------------------------------------- 1 | import { useState, useEffect, DependencyList, useCallback } from 'react'; 2 | import debounce from 'lodash/debounce'; 3 | 4 | // source: https://github.com/SevenOutman/use-debounced-memo 5 | 6 | export function useDebouncedMemo( 7 | factory: () => T, 8 | deps: DependencyList | undefined, 9 | debounceMs: number 10 | ): T { 11 | const [state, setState] = useState(factory()); 12 | 13 | const debouncedSetState = useCallback(debounce(setState, debounceMs), []); 14 | 15 | useEffect(() => { 16 | debouncedSetState(factory()); 17 | // eslint-disable-next-line 18 | }, deps); 19 | 20 | return state; 21 | } 22 | 23 | export default useDebouncedMemo; 24 | -------------------------------------------------------------------------------- /src/typings/window.d.ts: -------------------------------------------------------------------------------- 1 | import { NetworkId } from 'utils/networkUtils'; 2 | 3 | interface RequestArguments { 4 | method: string; 5 | params?: unknown[] | object; 6 | } 7 | 8 | declare global { 9 | interface Window { 10 | web3?: { 11 | eth?: { 12 | net: { 13 | getId: () => NetworkId; 14 | }; 15 | }; 16 | version: { 17 | getNetwork(cb: (err: Error | undefined, networkId: string) => void): void; 18 | network: NetworkId; 19 | }; 20 | }; 21 | ethereum?: { 22 | on: (event: string, cb: () => void) => void; 23 | networkVersion: NetworkId; 24 | request: (args: RequestArguments) => Promise; 25 | isMetaMask: boolean; 26 | }; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/assets/images/close-cross.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/images/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/utils/errorMessages.js: -------------------------------------------------------------------------------- 1 | const USER_DENIED = { type: 'cancelled', message: 'User denied transaction signature' }; 2 | 3 | const ERROR_CODES = { 4 | Metamask: { 5 | '-32603': USER_DENIED, 6 | 4001: USER_DENIED, 7 | }, 8 | Ledger: { 9 | 27013: USER_DENIED, 10 | }, 11 | Trezor: {}, 12 | Coinbase: { 13 | '-32603': USER_DENIED, 14 | }, 15 | }; 16 | 17 | export default (error, walletType) => { 18 | if (!error.code && !error.statusCode) return error; 19 | const code = (error.code || error.statusCode).toString(); 20 | if (!code || !ERROR_CODES[walletType][code]) { 21 | return { message: error.message || 'Error' }; 22 | } 23 | return { code, ...ERROR_CODES[walletType][code] }; 24 | }; 25 | -------------------------------------------------------------------------------- /src/assets/images/sun.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/constants/events.ts: -------------------------------------------------------------------------------- 1 | export const EXCHANGE_EVENTS = { 2 | SYNTH_EXCHANGE: 'SynthExchange', 3 | }; 4 | 5 | export const LOAN_EVENTS = { 6 | LOAN_CREATED: 'LoanCreated', 7 | LOAN_CLOSED: 'LoanClosed', 8 | }; 9 | 10 | export const EXCHANGE_RATES_EVENTS = { 11 | RATES_UPDATED: 'RatesUpdated', 12 | }; 13 | 14 | export const SYSTEM_STATUS_EVENTS = { 15 | SYSTEM_SUSPENDED: 'SystemSuspended', 16 | SYSTEM_RESUMED: 'SystemResumed', 17 | }; 18 | 19 | export const APPROVAL_EVENTS = { 20 | APPROVAL: 'Approval', 21 | }; 22 | 23 | export const BINARY_OPTIONS_EVENTS = { 24 | MARKET_CREATED: 'MarketCreated', 25 | BID: 'Bid', 26 | REFUND: 'Refund', 27 | OPTIONS_CLAIMED: 'OptionsClaimed', 28 | OPTIONS_EXERCISED: 'OptionsExercised', 29 | }; 30 | -------------------------------------------------------------------------------- /src/assets/currencies/crypto/ETC.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/Input/Input.tsx: -------------------------------------------------------------------------------- 1 | import styled, { css } from 'styled-components'; 2 | import { INPUT_SIZES } from './constants'; 3 | 4 | export const inputCSS = css` 5 | width: 100%; 6 | min-width: 0; 7 | font-family: ${(props) => props.theme.fonts.regular}; 8 | background-color: ${(props) => props.theme.colors.surfaceL3}; 9 | border: 1px solid ${(props) => props.theme.colors.accentL2}; 10 | height: ${INPUT_SIZES.md}; 11 | padding: 0 10px; 12 | font-size: 14px; 13 | color: ${(props) => props.theme.colors.fontPrimary}; 14 | ::placeholder { 15 | color: ${(props) => props.theme.colors.fontTertiary}; 16 | } 17 | outline: none; 18 | `; 19 | 20 | export const Input = styled.input` 21 | ${inputCSS}; 22 | `; 23 | 24 | export default Input; 25 | -------------------------------------------------------------------------------- /src/ducks/trades/types.ts: -------------------------------------------------------------------------------- 1 | import { CurrencyKey } from 'constants/currency'; 2 | 3 | export type HistoricalTrade = { 4 | block: number; 5 | date: Date; 6 | feesInUSD: number; 7 | fromAddress: string; 8 | fromAmount: number; 9 | fromAmountInUSD: number; 10 | fromCurrencyKey: CurrencyKey; 11 | fromCurrencyKeyBytes: string; 12 | gasPrice: number; 13 | hash: string; 14 | timestamp: number; 15 | toAddress: string; 16 | toAmount: number; 17 | toAmountInUSD: number; 18 | toCurrencyKey: CurrencyKey; 19 | toCurrencyKeyBytes: string; 20 | price: number; 21 | amount: number; 22 | isSettled: boolean; 23 | reclaim: number; 24 | rebate: number; 25 | settledPrice: number; 26 | }; 27 | 28 | export type HistoricalTrades = HistoricalTrade[]; 29 | -------------------------------------------------------------------------------- /src/pages/Trade/components/OrderBookCard/ViewLink.tsx: -------------------------------------------------------------------------------- 1 | import styled, { css } from 'styled-components'; 2 | 3 | import { ExternalLink } from 'shared/commonStyles'; 4 | import { ReactComponent as ArrowHyperlinkIcon } from 'assets/images/arrow-hyperlink.svg'; 5 | 6 | const ViewLink = styled(ExternalLink)<{ isDisabled?: boolean }>` 7 | color: ${(props) => props.theme.colors.hyperlink}; 8 | box-sizing: border-box; 9 | flex: 150 0 auto; 10 | min-width: 0px; 11 | width: 150px; 12 | font-size: 13px; 13 | ${(props) => 14 | props.isDisabled && 15 | css` 16 | opacity: 0.3; 17 | pointer-events: none; 18 | `} 19 | `; 20 | 21 | export const ArrowIcon = styled(ArrowHyperlinkIcon)` 22 | margin-left: 5px; 23 | `; 24 | 25 | export default ViewLink; 26 | -------------------------------------------------------------------------------- /src/components/Currency/CurrencyIcon/CurrencyIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | import { getCurrencyKeyIcon } from 'utils/currency'; 4 | import { CurrencyKey } from 'constants/currency'; 5 | 6 | type CurrencyIconProps = { 7 | currencyKey: CurrencyKey; 8 | type?: 'synth' | 'asset'; 9 | }; 10 | 11 | export const CurrencyIcon: FC = ({ currencyKey, type = 'synth', ...rest }) => { 12 | const currencyIcon = getCurrencyKeyIcon(currencyKey); 13 | 14 | if (!currencyIcon) { 15 | return null; 16 | } 17 | 18 | const { SynthIcon, AssetIcon } = currencyIcon; 19 | 20 | const Icon = type === 'synth' && SynthIcon ? SynthIcon : AssetIcon; 21 | 22 | return ; 23 | }; 24 | 25 | export default CurrencyIcon; 26 | -------------------------------------------------------------------------------- /src/assets/images/exclamation.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/images/moon.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/components/Button/ButtonSort.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import { ReactComponent as SortIcon } from '../../assets/images/sort.svg'; 5 | 6 | import { DataSmall } from '../Typography'; 7 | 8 | const ButtonSort = ({ children, onClick }) => { 9 | return ( 10 | 14 | ); 15 | }; 16 | 17 | const Button = styled.button` 18 | border: none; 19 | outline: none; 20 | cursor: pointer; 21 | background-color: transparent; 22 | padding: 0; 23 | white-space: nowrap; 24 | `; 25 | 26 | const StyledSortIcon = styled(SortIcon)` 27 | width: 6.5px; 28 | height: 8px; 29 | margin-left: 5px; 30 | `; 31 | 32 | export default ButtonSort; 33 | -------------------------------------------------------------------------------- /src/utils/browserUtils.js: -------------------------------------------------------------------------------- 1 | const chromeExtension = 2 | 'https://chrome.google.com/webstore/detail/nkbihfbeogaeaoehlefnkodbefgpgknn'; 3 | const firefoxExtension = 'https://addons.mozilla.org/en-US/firefox/addon/ether-metamask/'; 4 | const operaExtension = 'https://addons.opera.com/en/extensions/details/metamask/'; 5 | 6 | export const getExtensionUri = () => { 7 | // Opera 8.0+ 8 | const isOpera = 9 | (!!window.opr && !!window.opr.addons) || 10 | !!window.opera || 11 | navigator.userAgent.indexOf(' OPR/') >= 0; 12 | if (isOpera) return operaExtension; 13 | // Firefox 1.0+ 14 | const isFirefox = typeof InstallTrigger !== 'undefined'; 15 | if (isFirefox) return firefoxExtension; 16 | // Chrome 1+ 17 | const isChrome = !!window.chrome && !!window.chrome.webstore; 18 | if (isChrome) return chromeExtension; 19 | }; 20 | -------------------------------------------------------------------------------- /src/components/Card/Card.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import CardHeader, { CardHeaderProps } from './CardHeader'; 5 | import CardBody, { CardBodyProps } from './CardBody'; 6 | 7 | type CardProps = { 8 | children: React.ReactNode; 9 | }; 10 | 11 | interface StaticComponents { 12 | Header: FC; 13 | Body: FC; 14 | } 15 | 16 | // @ts-ignore 17 | const Card: FC & StaticComponents = ({ children, ...rest }) => ( 18 | {children} 19 | ); 20 | 21 | Card.Header = CardHeader; 22 | Card.Body = CardBody; 23 | 24 | const Container = styled.div` 25 | background-color: ${(props) => props.theme.colors.surfaceL2}; 26 | display: flex; 27 | flex-direction: column; 28 | `; 29 | 30 | export default Card; 31 | -------------------------------------------------------------------------------- /src/assets/currencies/crypto/LINK.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/components/Card/CardHeader.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import { CARD_HEIGHT } from 'constants/ui'; 5 | 6 | import { FlexDivCentered } from 'shared/commonStyles'; 7 | 8 | export type CardHeaderProps = { 9 | children: React.ReactNode; 10 | }; 11 | 12 | const CardHeader: FC = ({ children, ...rest }) => ( 13 | {children} 14 | ); 15 | 16 | const Container = styled(FlexDivCentered)` 17 | background-color: ${(props) => props.theme.colors.surfaceL3}; 18 | color: ${(props) => props.theme.colors.fontPrimary}; 19 | height: ${CARD_HEIGHT}; 20 | padding: 0 18px; 21 | justify-content: flex-start; 22 | text-transform: uppercase; 23 | 24 | > * + * { 25 | margin-left: 10px; 26 | } 27 | `; 28 | 29 | export default CardHeader; 30 | -------------------------------------------------------------------------------- /src/pages/Options/Home/utils.ts: -------------------------------------------------------------------------------- 1 | import orderBy from 'lodash/orderBy'; 2 | import { SynthDefinitionMap } from 'ducks/synths'; 3 | import { PHASE, getPhaseAndEndDate } from '../constants'; 4 | import { OptionsMarkets } from '../types'; 5 | 6 | export const sortOptionsMarkets = (markets: OptionsMarkets, synthsMap: SynthDefinitionMap) => 7 | orderBy( 8 | markets.map((optionsMarket) => { 9 | const { phase, timeRemaining } = getPhaseAndEndDate( 10 | optionsMarket.biddingEndDate, 11 | optionsMarket.maturityDate, 12 | optionsMarket.expiryDate 13 | ); 14 | 15 | return { 16 | ...optionsMarket, 17 | phase, 18 | asset: synthsMap[optionsMarket.currencyKey]?.asset || optionsMarket.currencyKey, 19 | timeRemaining, 20 | phaseNum: PHASE[phase], 21 | }; 22 | }), 23 | ['phaseNum', 'timeRemaining'] 24 | ); 25 | -------------------------------------------------------------------------------- /src/pages/Options/components/NewToBinaryOptions/NewToBinaryOptions.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | import { Trans } from 'react-i18next'; 3 | 4 | import Link from 'components/Link'; 5 | import { LINKS } from 'constants/links'; 6 | import styled from 'styled-components'; 7 | 8 | type NewToBinaryOptionsProps = { 9 | className?: string; 10 | }; 11 | 12 | const NewToBinaryOptions: FC = (props) => ( 13 | 14 | ]} 17 | /> 18 | 19 | ); 20 | 21 | const Wrapper = styled.span` 22 | a { 23 | color: ${(props) => props.theme.colors.buttonDefault}; 24 | text-decoration: underline; 25 | } 26 | `; 27 | 28 | export default NewToBinaryOptions; 29 | -------------------------------------------------------------------------------- /src/assets/images/person.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/pages/Root/components/AppHeader/MobileAppHeader/Overlay/Overlay.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import styled from 'styled-components'; 4 | 5 | import { media } from 'shared/media'; 6 | import { APP_HEADER_HEIGHT, MOBILE_APP_HEADER_HEIGHT, Z_INDEX } from 'constants/ui'; 7 | 8 | type OverlayProps = { 9 | onClick: () => void; 10 | }; 11 | 12 | export const Overlay: FC = ({ onClick }) => 13 | ReactDOM.createPortal(, document.body); 14 | 15 | const Container = styled.div` 16 | top: ${APP_HEADER_HEIGHT}; 17 | bottom: 0; 18 | left: 0; 19 | right: 0; 20 | position: fixed; 21 | background-color: ${(props) => props.theme.colors.surfaceL1}; 22 | z-index: ${Z_INDEX.BASE}; 23 | ${media.small` 24 | top: ${MOBILE_APP_HEADER_HEIGHT} 25 | `} 26 | `; 27 | 28 | export default Overlay; 29 | -------------------------------------------------------------------------------- /src/pages/Root/components/AppHeader/MobileAppHeader/Dropdown/Dropdown.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import styled from 'styled-components'; 4 | 5 | import { media } from 'shared/media'; 6 | import { APP_HEADER_HEIGHT, MOBILE_APP_HEADER_HEIGHT, Z_INDEX } from 'constants/ui'; 7 | 8 | type DropdownProps = { 9 | children: React.ReactNode; 10 | }; 11 | 12 | export const Dropdown: FC = ({ children, ...rest }) => 13 | ReactDOM.createPortal({children}, document.body); 14 | 15 | const Container = styled.div` 16 | top: ${APP_HEADER_HEIGHT}; 17 | width: 100%; 18 | position: fixed; 19 | background-color: ${(props) => props.theme.colors.surfaceL3}; 20 | z-index: ${Z_INDEX.BASE}; 21 | ${media.small` 22 | top: ${MOBILE_APP_HEADER_HEIGHT} 23 | `} 24 | `; 25 | 26 | export default Dropdown; 27 | -------------------------------------------------------------------------------- /src/pages/Root/components/AppHeader/constants.ts: -------------------------------------------------------------------------------- 1 | import ROUTES from 'constants/routes'; 2 | 3 | export type MenuLink = { 4 | i18nLabel: string; 5 | link: string; 6 | isBeta?: boolean; 7 | }; 8 | 9 | export type MenuLinks = MenuLink[]; 10 | 11 | export const MENU_LINKS: MenuLinks = [ 12 | { 13 | i18nLabel: 'header.links.markets', 14 | link: ROUTES.Markets, 15 | }, 16 | { 17 | i18nLabel: 'header.links.synths', 18 | link: ROUTES.Synths.Home, 19 | }, 20 | { 21 | i18nLabel: 'header.links.trade', 22 | link: ROUTES.Trade, 23 | }, 24 | { 25 | i18nLabel: 'header.links.loans', 26 | link: ROUTES.Loans, 27 | }, 28 | { 29 | i18nLabel: 'header.links.options', 30 | link: ROUTES.Options.Home, 31 | isBeta: true, 32 | }, 33 | ]; 34 | 35 | export const MENU_LINKS_WALLET_CONNECTED: MenuLinks = [ 36 | { 37 | i18nLabel: 'header.links.assets', 38 | link: ROUTES.Assets.Home, 39 | }, 40 | ]; 41 | -------------------------------------------------------------------------------- /src/utils/explorers.js: -------------------------------------------------------------------------------- 1 | import { SUPPORTED_NETWORKS, isMainNet } from '../utils/networkUtils'; 2 | 3 | const getEtherScanBaseURL = (networkId) => { 4 | const network = SUPPORTED_NETWORKS[networkId]; 5 | 6 | if (isMainNet(networkId) || network == null) { 7 | return 'https://etherscan.io'; 8 | } 9 | 10 | return `https://${network.toLowerCase()}.etherscan.io`; 11 | }; 12 | 13 | export const getEtherscanTxLink = (networkId, txId) => { 14 | const baseURL = getEtherScanBaseURL(networkId); 15 | 16 | return `${baseURL}/tx/${txId}`; 17 | }; 18 | 19 | export const getEtherscanAddressLink = (networkId, address) => { 20 | const baseURL = getEtherScanBaseURL(networkId); 21 | 22 | return `${baseURL}/address/${address}`; 23 | }; 24 | 25 | export const getEtherscanTokenLink = (networkId, address) => { 26 | const baseURL = getEtherScanBaseURL(networkId); 27 | 28 | return `${baseURL}/token/${address}`; 29 | }; 30 | -------------------------------------------------------------------------------- /.storybook/preview.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { withThemesProvider } from 'storybook-addon-styled-component-theme'; 3 | import { addDecorator, addParameters } from '@storybook/react'; 4 | import { withKnobs, text, boolean, number } from '@storybook/addon-knobs'; 5 | 6 | import withReduxProvider from './providers/withReduxProvider'; 7 | import withReactRouterProvider from './providers/withReactRouterProvider'; 8 | 9 | import { themes, lightTheme, darkTheme } from '../src/styles/theme'; 10 | 11 | import './libs/i18n'; 12 | import '../src/index.css'; 13 | 14 | addDecorator(withReduxProvider); 15 | addDecorator(withReactRouterProvider); 16 | addDecorator(withThemesProvider(themes)); 17 | addDecorator(withKnobs); 18 | addParameters({ 19 | backgrounds: [ 20 | { name: 'dark', value: darkTheme.colors.surfaceL1, default: true }, 21 | { name: 'light', value: lightTheme.colors.surfaceL1 }, 22 | ], 23 | }); 24 | -------------------------------------------------------------------------------- /src/pages/Root/components/MaintenanceMessage/MaintenanceMessage.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | import styled, { ThemeProvider } from 'styled-components'; 3 | 4 | import { lightTheme } from 'styles/theme'; 5 | import { headingH3CSS } from 'components/Typography/Heading'; 6 | 7 | const MaintenanceMessage: FC = () => ( 8 | 9 | 10 | Synthetix.Exchange is currently down for maintenance. 11 | It will be back shortly. 12 | 13 | 14 | ); 15 | 16 | const Container = styled.div` 17 | position: absolute; 18 | width: 100%; 19 | left: 50%; 20 | top: 50%; 21 | transform: translate(-50%, -50%); 22 | text-align: center; 23 | `; 24 | 25 | const Title = styled.div` 26 | ${headingH3CSS}; 27 | color: ${(props) => props.theme.colors.fontPrimary}; 28 | `; 29 | 30 | export default MaintenanceMessage; 31 | -------------------------------------------------------------------------------- /src/assets/currencies/fiat/EUR.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/images/info-rounded.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/currencies/crypto/BTC.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/currencies/crypto/BCH.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/currencies/fiat/KRW.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/components/Currency/CurrencyPair/CurrencyPair.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | import { formatCurrencyPair } from '../../../utils/formatters'; 4 | 5 | import CurrencyIcon from '../CurrencyIcon'; 6 | 7 | import { Container } from '../commonStyles'; 8 | import { CurrencyKey } from 'constants/currency'; 9 | 10 | type CurrencyPairProps = { 11 | baseCurrencyKey: CurrencyKey; 12 | baseCurrencyAsset?: string; 13 | quoteCurrencyKey: CurrencyKey; 14 | showIcon?: boolean; 15 | iconProps?: any; 16 | }; 17 | 18 | export const CurrencyPair: FC = ({ 19 | baseCurrencyKey, 20 | baseCurrencyAsset, 21 | quoteCurrencyKey, 22 | showIcon = true, 23 | iconProps = {}, 24 | ...rest 25 | }) => ( 26 | 27 | {showIcon && } 28 | {formatCurrencyPair(baseCurrencyAsset || baseCurrencyKey, quoteCurrencyKey)} 29 | 30 | ); 31 | 32 | export default CurrencyPair; 33 | -------------------------------------------------------------------------------- /src/components/DismissableMessage/DismissableMessage.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import { ReactComponent as CloseIcon } from 'assets/images/close.svg'; 5 | 6 | import { Message, MessageProps } from 'shared/commonStyles'; 7 | 8 | type DismissableMessageProps = MessageProps & { 9 | children: React.ReactNode; 10 | onDismiss: () => void; 11 | }; 12 | 13 | export const DismissableMessage: FC = ({ 14 | children, 15 | onDismiss, 16 | ...rest 17 | }) => ( 18 | 19 | 20 | {children} 21 | 22 | 23 | 24 | ); 25 | 26 | const Container = styled.div` 27 | position: relative; 28 | `; 29 | 30 | const StyledMessage = styled(Message)` 31 | justify-content: space-between; 32 | `; 33 | 34 | const StyledCloseButton = styled(CloseIcon)` 35 | cursor: pointer; 36 | flex-shrink: 0; 37 | `; 38 | 39 | export default DismissableMessage; 40 | -------------------------------------------------------------------------------- /src/pages/Root/components/MaterialUIThemeProvider.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC, useContext } from 'react'; 2 | import { createMuiTheme, MuiThemeProvider } from '@material-ui/core/styles'; 3 | 4 | import { ThemeContext } from 'styled-components'; 5 | 6 | type MaterialUIThemeProviderProps = { 7 | children: React.ReactNode; 8 | }; 9 | 10 | const MaterialUIThemeProvider: FC = ({ children }) => { 11 | const { colors, fonts } = useContext(ThemeContext); 12 | 13 | const theme = createMuiTheme({ 14 | overrides: { 15 | MuiTooltip: { 16 | tooltip: { 17 | color: colors.fontPrimary, 18 | backgroundColor: colors.accentL1, 19 | fontSize: '12px', 20 | fontFamily: fonts.regular, 21 | borderRadius: '4px', 22 | padding: '5px 10px 6px 10px', 23 | }, 24 | arrow: { 25 | color: colors.accentL1, 26 | }, 27 | }, 28 | }, 29 | }); 30 | 31 | return {children}; 32 | }; 33 | 34 | export default MaterialUIThemeProvider; 35 | -------------------------------------------------------------------------------- /src/pages/Root/components/ProtectedRoute/ProtectedRoute.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | import { connect, ConnectedProps } from 'react-redux'; 3 | import { Route, Redirect, RouteProps } from 'react-router-dom'; 4 | 5 | import { ROUTES } from 'constants/routes'; 6 | 7 | import { RootState } from 'ducks/types'; 8 | import { getIsWalletConnected } from 'ducks/wallet/walletDetails'; 9 | 10 | const mapStateToProps = (state: RootState) => ({ 11 | isWalletConnected: getIsWalletConnected(state), 12 | }); 13 | 14 | const connector = connect(mapStateToProps); 15 | 16 | type PropsFromRedux = ConnectedProps; 17 | 18 | type ProtectedRouteProps = PropsFromRedux & RouteProps; 19 | 20 | export const ProtectedRoute: FC = ({ 21 | isWalletConnected, 22 | path, 23 | ...rest 24 | }) => { 25 | if (!isWalletConnected) { 26 | return ; 27 | } 28 | 29 | return ; 30 | }; 31 | 32 | export default connector(ProtectedRoute); 33 | -------------------------------------------------------------------------------- /src/assets/images/cog.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/Typography/Data.tsx: -------------------------------------------------------------------------------- 1 | import styled, { css } from 'styled-components'; 2 | import { color, typography } from 'styled-system'; 3 | 4 | // TODO: deprecate 5 | 6 | const dataCSS = css` 7 | color: ${(props) => props.theme.colors.fontPrimary}; 8 | `; 9 | 10 | export const dataLargeCSS = css` 11 | ${dataCSS}; 12 | font-size: 18px; 13 | text-transform: uppercase; 14 | `; 15 | 16 | export const dataMediumCSS = css` 17 | ${dataCSS}; 18 | font-size: 14px; 19 | font-family: ${(props) => props.theme.fonts.regular}; 20 | `; 21 | 22 | export const dataSmallCSS = css` 23 | ${dataCSS}; 24 | font-size: 12px; 25 | text-transform: uppercase; 26 | font-family: ${(props) => props.theme.fonts.medium}; 27 | `; 28 | 29 | export const DataLarge = styled.span` 30 | ${dataLargeCSS}; 31 | ${typography} 32 | `; 33 | 34 | export const DataMedium = styled.span` 35 | ${dataMediumCSS}; 36 | ${typography}; 37 | ${color}; 38 | `; 39 | 40 | export const DataSmall = styled.span` 41 | ${dataSmallCSS}; 42 | ${color}; 43 | ${typography}; 44 | `; 45 | -------------------------------------------------------------------------------- /src/pages/Loans/contexts/LoanContext.js: -------------------------------------------------------------------------------- 1 | import React, { createContext, useContext, useEffect, useState } from 'react'; 2 | import snxJSConnector from 'utils/snxJSConnector'; 3 | 4 | const LoanContext = createContext(null); 5 | 6 | export const LoanProvider = ({ children }) => { 7 | const [contractType, setContractType] = useState('sETH'); 8 | const [contract, setContract] = useState(null); 9 | 10 | useEffect(() => { 11 | const getSelectedContract = async () => { 12 | const { 13 | snxJS: { EtherCollateral, EtherCollateralsUSD }, 14 | } = snxJSConnector; 15 | if (contractType === 'sETH') { 16 | setContract(EtherCollateral.contract); 17 | } else { 18 | setContract(EtherCollateralsUSD.contract); 19 | } 20 | }; 21 | getSelectedContract(); 22 | }, [contractType]); 23 | 24 | return ( 25 | 26 | {children} 27 | 28 | ); 29 | }; 30 | 31 | export const useLoanContext = () => useContext(LoanContext); 32 | -------------------------------------------------------------------------------- /.storybook/mocks/reducers/wallet.js: -------------------------------------------------------------------------------- 1 | import { defaultNetwork } from '../../../src/utils/networkUtils'; 2 | 3 | export const walletReducerDefaults = { 4 | unlocked: false, 5 | unlockError: null, 6 | walletPaginatorIndex: 0, 7 | availableWallets: [], 8 | currentWallet: null, 9 | derivationPath: null, 10 | balances: null, 11 | networkId: defaultNetwork.networkId, 12 | networkName: defaultNetwork.name, 13 | }; 14 | 15 | export const connectedWallet = { 16 | ...walletReducerDefaults, 17 | unlocked: true, 18 | currentWallet: '0x1BC4230d996286ffD1dD4DC649AAd47Fa08cadc4', 19 | walletType: 'Metamask', 20 | }; 21 | 22 | export const balances = { 23 | synths: { 24 | balances: { 25 | sBTC: { 26 | balance: 0.000628320060412509, 27 | usdBalance: 6.50700536879026, 28 | }, 29 | }, 30 | usdBalance: 6.50700536879026, 31 | }, 32 | eth: { 33 | balance: 0.04243316499453552, 34 | usdBalance: 11.380247270217652, 35 | }, 36 | }; 37 | 38 | export const connectedWalletWithBalances = { 39 | ...connectedWallet, 40 | balances, 41 | }; 42 | -------------------------------------------------------------------------------- /src/components/Slider/Slider.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Slider, { Handle, createSliderWithTooltip } from 'rc-slider'; 3 | import Tooltip from 'rc-tooltip'; 4 | 5 | import 'rc-slider/assets/index.css'; 6 | import 'rc-tooltip/assets/bootstrap.css'; 7 | import './Slider.css'; 8 | 9 | const CustomSlider = createSliderWithTooltip(Slider); 10 | 11 | export const handle = (props) => { 12 | const { value, dragging, index, ...restProps } = props; 13 | return ( 14 | 21 | 22 | 23 | ); 24 | }; 25 | 26 | const SliderComponent = ({ min, max, value, tooltipRenderer, onChange }) => { 27 | return ( 28 | 37 | ); 38 | }; 39 | 40 | export default SliderComponent; 41 | -------------------------------------------------------------------------------- /src/pages/Trade/components/OrderBookCard/MyTrades.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | import { connect, ConnectedProps } from 'react-redux'; 3 | 4 | import { RootState } from 'ducks/types'; 5 | import { getCurrentWalletAddress } from 'ducks/wallet/walletDetails'; 6 | import TradeHistory from './TradeHistory'; 7 | 8 | import { useTradesQuery } from 'queries/myTrades'; 9 | 10 | const mapStateToProps = (state: RootState) => ({ 11 | walletAddress: getCurrentWalletAddress(state), 12 | }); 13 | 14 | const connector = connect(mapStateToProps); 15 | 16 | type PropsFromRedux = ConnectedProps; 17 | 18 | type MyTradesProps = PropsFromRedux; 19 | 20 | const MyTrades: FC = ({ walletAddress }) => { 21 | const tradesQuery = useTradesQuery({ walletAddress: walletAddress || '' }); 22 | 23 | return ( 24 | 30 | ); 31 | }; 32 | 33 | export default connector(MyTrades); 34 | -------------------------------------------------------------------------------- /src/assets/currencies/equities/NIKKEI.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/assets/images/wallets/trezor.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/styles/theme/index.ts: -------------------------------------------------------------------------------- 1 | import darkThemeColors from './dark'; 2 | import lightThemeColors from './light'; 3 | import colors from './colors'; 4 | import fonts from './fonts'; 5 | 6 | import { Theme } from './types'; 7 | 8 | export const isDarkTheme = (theme: Theme) => theme === 'dark'; 9 | export const isLightTheme = (theme: Theme) => theme === 'light'; 10 | 11 | const styledTheme = (themeName: Theme) => { 12 | const darkTheme = isDarkTheme(themeName); 13 | const lightTheme = isLightTheme(themeName); 14 | 15 | const colorStyle = darkTheme ? darkThemeColors : lightThemeColors; 16 | 17 | return { 18 | name: themeName, 19 | isDarkTheme: darkTheme, 20 | isLightTheme: lightTheme, 21 | colors: { ...colors, ...colorStyle }, 22 | fonts, 23 | }; 24 | }; 25 | 26 | export const darkTheme = styledTheme('dark'); 27 | export const lightTheme = styledTheme('light'); 28 | 29 | export type ThemeInterface = typeof darkTheme; 30 | 31 | export const themes = [darkTheme, lightTheme]; 32 | 33 | export const THEMES: Record = { 34 | DARK: 'dark', 35 | LIGHT: 'light', 36 | }; 37 | -------------------------------------------------------------------------------- /src/components/Currency/CurrencyName/CurrencyName.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import CurrencyIcon from '../CurrencyIcon'; 5 | 6 | import { Container } from '../commonStyles'; 7 | 8 | import { CurrencyKey } from 'constants/currency'; 9 | 10 | type CurrencyNameProps = { 11 | currencyKey: CurrencyKey; 12 | name?: string; 13 | showIcon?: boolean; 14 | iconProps?: object; 15 | currencyDesc?: string | null; 16 | }; 17 | 18 | export const CurrencyName: FC = ({ 19 | currencyKey, 20 | name, 21 | currencyDesc = null, 22 | showIcon = false, 23 | iconProps = {}, 24 | ...rest 25 | }) => ( 26 | 27 | {showIcon && } 28 | {name || currencyKey} 29 | {currencyDesc && {currencyDesc}} 30 | 31 | ); 32 | 33 | const Desc = styled.span` 34 | padding-left: 5px; 35 | color: ${({ theme }) => theme.colors.fontTertiary}; 36 | `; 37 | 38 | export default CurrencyName; 39 | -------------------------------------------------------------------------------- /src/utils/balances.js: -------------------------------------------------------------------------------- 1 | import get from 'lodash/get'; 2 | import { isSynth } from '../constants/currency'; 3 | 4 | const getSynthBalancePath = (currencyKey, field) => ['synths', 'balances', currencyKey, field]; 5 | 6 | // crypto appears as lowercased in balances 7 | const getCryptoCurrencyBalancePath = (currencyKey, field) => [currencyKey.toLowerCase(), field]; 8 | 9 | export const getCurrencyKeyBalance = (balances, currencyKey) => 10 | isSynth(currencyKey) 11 | ? get(balances, getSynthBalancePath(currencyKey, 'balance')) 12 | : get(balances, getCryptoCurrencyBalancePath(currencyKey, 'balance')); 13 | 14 | export const getCurrencyKeyUSDBalance = (balances, currencyKey) => 15 | isSynth(currencyKey) 16 | ? get(balances, getSynthBalancePath(currencyKey, 'usdBalance')) 17 | : get(balances, getCryptoCurrencyBalancePath(currencyKey, 'usdBalance')); 18 | 19 | export const getCurrencyKeyUSDBalanceBN = (balances, currencyKey) => 20 | isSynth(currencyKey) 21 | ? get(balances, getSynthBalancePath(currencyKey, 'balanceBN')) 22 | : get(balances, getCryptoCurrencyBalancePath(currencyKey, 'balanceBN')); 23 | -------------------------------------------------------------------------------- /src/components/Currency/CurrencyName/CurrencyName.stories.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | import { CurrencyName } from './CurrencyName'; 4 | 5 | import { SYNTHS, CRYPTO_CURRENCY, FIAT_CURRENCY } from '../../../constants/currency'; 6 | 7 | export default { 8 | title: 'Currency/List', 9 | }; 10 | 11 | export const synths = () => ( 12 | 13 | {SYNTHS.map((currencyKey) => ( 14 | 15 | ))} 16 | 17 | ); 18 | 19 | export const crypto = () => ( 20 | 21 | {CRYPTO_CURRENCY.map((currencyKey) => ( 22 | 23 | ))} 24 | 25 | ); 26 | 27 | export const fiat = () => ( 28 | 29 | {FIAT_CURRENCY.map((currencyKey) => ( 30 | 31 | ))} 32 | 33 | ); 34 | 35 | const Container = styled.div` 36 | display: grid; 37 | grid-gap: 20px; 38 | grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); 39 | `; 40 | -------------------------------------------------------------------------------- /src/pages/Root/components/AppHeader/SupportLink/SupportLink.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | import styled, { css } from 'styled-components'; 3 | 4 | import { RoundedIcon, ExternalLink } from 'shared/commonStyles'; 5 | 6 | import { ReactComponent as QuestionMark } from 'assets/images/question-mark.svg'; 7 | 8 | import { LINKS } from 'constants/links'; 9 | 10 | type SupportLinkProps = { 11 | isOnSplashPage?: boolean; 12 | }; 13 | 14 | const SupportLink: FC = ({ isOnSplashPage }) => ( 15 | 16 | 17 | 18 | 19 | 20 | ); 21 | 22 | const StyledQuestionMark = styled(QuestionMark)` 23 | color: ${({ theme }) => theme.colors.fontSecondary}; 24 | `; 25 | 26 | const StyledRoundedIcon = styled(RoundedIcon)<{ isOnSplashPage?: boolean }>` 27 | border-radius: 1px; 28 | ${(props) => 29 | props.isOnSplashPage && 30 | css` 31 | background-color: ${props.theme.colors.surfaceL3}; 32 | `} 33 | `; 34 | 35 | export default SupportLink; 36 | -------------------------------------------------------------------------------- /src/components/BaseTradingPairs/BaseTradingPairs.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | 3 | import { BASE_TRADING_PAIRS, CurrencyKey, getMarketPairByMC } from 'constants/currency'; 4 | import { buildTradeLink } from 'constants/routes'; 5 | 6 | import Link from 'components/Link'; 7 | import Currency from 'components/Currency'; 8 | 9 | type BaseTradingPairsProps = { 10 | currencyKey: CurrencyKey; 11 | }; 12 | 13 | const BaseTradingPairs: FC = ({ currencyKey }) => ( 14 | <> 15 | {BASE_TRADING_PAIRS.filter((quote) => quote !== currencyKey).map((quote) => { 16 | const { base: baseCurrencyKey, quote: quoteCurrencyKey } = getMarketPairByMC( 17 | currencyKey, 18 | quote 19 | ); 20 | 21 | return ( 22 | 26 | 31 | 32 | ); 33 | })} 34 | 35 | ); 36 | 37 | export default BaseTradingPairs; 38 | -------------------------------------------------------------------------------- /src/utils/synthOrdering.js: -------------------------------------------------------------------------------- 1 | export const synthWeight = { 2 | BTC: 1, 3 | ETH: 2, 4 | XRP: 3, 5 | LTC: 4, 6 | BNB: 5, 7 | XTZ: 6, 8 | TRX: 7, 9 | LINK: 8, 10 | }; 11 | 12 | // Ugly. Needs to find a better solution. 13 | export const pairWeight = (synth) => { 14 | if (synth.category === 'forex') return 1; 15 | if (synth.name === 'sBTC') return 2; 16 | if (synth.name === 'sETH') return 3; 17 | if (synth.category === 'commodity') return 4; 18 | if (synth.name === 'sXRP') return 5; 19 | if (synth.name === 'sLTC') return 6; 20 | if (synth.name === 'sBNB') return 7; 21 | if (synth.name === 'sXTZ') return 8; 22 | if (synth.name === 'sTRX') return 9; 23 | if (synth.name === 'sLINK') return 10; 24 | if (synth.name === 'iBTC') return 12; 25 | if (synth.name === 'iETH') return 13; 26 | if (synth.name === 'iXRP') return 14; 27 | if (synth.name === 'iLTC') return 15; 28 | if (synth.name === 'iBNB') return 16; 29 | if (synth.name === 'iXTZ') return 17; 30 | if (synth.name === 'iTRX') return 18; 31 | if (synth.name === 'iLINK') return 19; 32 | if (synth.category === 'index') return 21; 33 | return 22; 34 | }; 35 | -------------------------------------------------------------------------------- /src/components/RechartsResponsiveContainer/RechartsResponsiveContainer.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC, ReactElement } from 'react'; 2 | import styled from 'styled-components'; 3 | import { ResponsiveContainer } from 'recharts'; 4 | 5 | type RechartsResponsiveContainerProps = { 6 | aspect?: number; 7 | width?: string | number; 8 | height?: string | number; 9 | minWidth?: string | number; 10 | minHeight?: string | number; 11 | maxHeight?: number; 12 | children: ReactElement; 13 | debounce?: number; 14 | id?: string | number; 15 | className?: string | number; 16 | }; 17 | 18 | export const RechartsResponsiveContainer: FC = (props) => ( 19 | 20 | 21 | 22 | 23 | 24 | ); 25 | 26 | const OuterContainer = styled.div` 27 | width: 100%; 28 | height: 100%; 29 | position: relative; 30 | `; 31 | 32 | const InnerContainer = styled.div` 33 | width: 100%; 34 | height: 100%; 35 | position: absolute; 36 | top: 0; 37 | left: 0; 38 | `; 39 | 40 | export default RechartsResponsiveContainer; 41 | -------------------------------------------------------------------------------- /src/pages/Options/constants.ts: -------------------------------------------------------------------------------- 1 | import { Phase, Side } from './types'; 2 | 3 | export const PHASE: Record = { 4 | bidding: 0, 5 | trading: 1, 6 | maturity: 2, 7 | expiry: 3, 8 | }; 9 | 10 | export const SIDE: Record = { 11 | long: 0, 12 | short: 1, 13 | 0: 'long', 14 | 1: 'short', 15 | }; 16 | 17 | export const getPhaseAndEndDate = ( 18 | biddingEndDate: number, 19 | maturityDate: number, 20 | expiryDate: number 21 | ): { phase: Phase; timeRemaining: number } => { 22 | const now = Date.now(); 23 | 24 | if (biddingEndDate > now) { 25 | return { 26 | phase: 'bidding', 27 | timeRemaining: biddingEndDate, 28 | }; 29 | } 30 | 31 | if (maturityDate > now) { 32 | return { 33 | phase: 'trading', 34 | timeRemaining: maturityDate, 35 | }; 36 | } 37 | 38 | if (expiryDate > now) { 39 | return { 40 | phase: 'maturity', 41 | timeRemaining: expiryDate, 42 | }; 43 | } 44 | 45 | return { 46 | phase: 'expiry', 47 | timeRemaining: expiryDate, 48 | }; 49 | }; 50 | 51 | export const PHASES = ['bidding', 'trading', 'maturity', 'expiry'] as Phase[]; 52 | -------------------------------------------------------------------------------- /src/shared/media.ts: -------------------------------------------------------------------------------- 1 | import { css } from 'styled-components'; 2 | 3 | const cssUntyped = css as any; 4 | 5 | // https://github.com/JohnAlbin/styled-media-queries/blob/master/index.js 6 | export const mediaQuery = (...query: any) => (...rules: any) => 7 | cssUntyped` 8 | @media ${cssUntyped(...query)} { 9 | ${cssUntyped(...rules)} 10 | } 11 | `; 12 | 13 | export const breakpoint = { 14 | small: 480, 15 | medium: 768, 16 | large: 1150, 17 | extraLarge: 1300, 18 | }; 19 | 20 | export const smallMediaQuery = `(max-width: ${breakpoint.small}px)`; 21 | export const mediumMediaQuery = `(max-width: ${breakpoint.medium}px)`; 22 | export const largeMediaQuery = `(max-width: ${breakpoint.large}px)`; 23 | export const extraLargeMediaQuery = `(max-width: ${breakpoint.extraLarge}px)`; 24 | export const wideMediaQuery = `(min-width: ${breakpoint.extraLarge}px)`; 25 | 26 | export const media = { 27 | small: mediaQuery`${smallMediaQuery}`, 28 | medium: mediaQuery`${mediumMediaQuery}`, 29 | large: mediaQuery`${largeMediaQuery}`, 30 | extraLarge: mediaQuery`${extraLargeMediaQuery}`, 31 | wide: mediaQuery`${wideMediaQuery}`, 32 | }; 33 | -------------------------------------------------------------------------------- /src/pages/Options/Market/components/SideIcon/SideIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | import { Side } from 'pages/Options/types'; 5 | 6 | import { ReactComponent as TrendUpIcon } from 'assets/images/trend-up.svg'; 7 | import { ReactComponent as TrendDownIcon } from 'assets/images/trend-down.svg'; 8 | import { darkTheme } from 'styles/theme'; 9 | 10 | type SideIconProps = { 11 | side: Side; 12 | }; 13 | 14 | const SideIcon: FC = ({ side, ...rest }) => ( 15 | 16 | {side === 'long' ? : } 17 | 18 | ); 19 | 20 | const Container = styled.span<{ side: Side }>` 21 | display: inline-flex; 22 | align-items: center; 23 | justify-content: center; 24 | border-radius: 2px; 25 | width: 16px; 26 | height: 16px; 27 | background-color: ${(props) => 28 | props.side === 'long' ? props.theme.colors.green : props.theme.colors.red}; 29 | color: ${(props) => 30 | props.theme.isDarkTheme ? darkTheme.colors.surfaceL1 : darkTheme.colors.fontPrimary}; 31 | `; 32 | 33 | export default SideIcon; 34 | -------------------------------------------------------------------------------- /src/assets/images/dollar-sign.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/images/reverse-arrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/components/Slider/Slider.css: -------------------------------------------------------------------------------- 1 | .rc-slider .rc-slider-rail { 2 | position: absolute; 3 | width: 100%; 4 | background-image: linear-gradient(to right, #f4c14d, #d94454); 5 | height: 16px; 6 | border-radius: 2px; 7 | } 8 | .rc-slider .rc-slider-track { 9 | background-color: transparent; 10 | height: 8px; 11 | } 12 | .rc-slider .rc-slider-step { 13 | background-color: transparent; 14 | height: 8px; 15 | } 16 | .rc-slider .rc-slider-handle { 17 | position: absolute; 18 | width: 32px; 19 | height: 32px; 20 | cursor: pointer; 21 | cursor: -webkit-grab; 22 | margin-top: -8px; 23 | cursor: grab; 24 | border-radius: 50%; 25 | border: solid 8px #ffffff; 26 | background-color: transparent; 27 | touch-action: pan-x; 28 | box-shadow: 0px 0px 6px 4px rgba(119, 119, 119, 0.2); 29 | } 30 | 31 | .rc-slider-tooltip { 32 | z-index: 100001 !important; 33 | } 34 | 35 | .rc-slider-tooltip-inner { 36 | height: auto; 37 | width: auto; 38 | padding: 8px; 39 | background: white; 40 | color: #0e0d14; 41 | font-size: 14px; 42 | } 43 | 44 | .rc-slider-tooltip-placement-top .rc-slider-tooltip-arrow { 45 | border-top-color: white; 46 | color: black; 47 | } 48 | -------------------------------------------------------------------------------- /src/assets/images/charts-square.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/components/Currency/CurrencyIcon/CurrencyIcon.stories.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | import { CurrencyIcon } from './CurrencyIcon'; 4 | 5 | import { SYNTHS, CRYPTO_CURRENCY, FIAT_CURRENCY } from '../../../constants/currency'; 6 | 7 | export default { 8 | title: 'Currency/Icons', 9 | }; 10 | 11 | export const synths = () => ( 12 | 13 | {SYNTHS.map((currencyKey) => ( 14 | 15 | ))} 16 | 17 | ); 18 | 19 | export const crypto = () => ( 20 | 21 | {CRYPTO_CURRENCY.map((currencyKey) => ( 22 | 23 | ))} 24 | 25 | ); 26 | 27 | export const fiat = () => ( 28 | 29 | {FIAT_CURRENCY.map((currencyKey) => ( 30 | 31 | ))} 32 | 33 | ); 34 | 35 | const Container = styled.div` 36 | display: grid; 37 | grid-gap: 20px; 38 | grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); 39 | `; 40 | -------------------------------------------------------------------------------- /src/assets/images/arrows-rotated-square.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/assets/images/wallet.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/images/arrows-square.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/assets/currencies/indices/DEFI.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/pages/Root/components/MainLayout/MainLayout.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC, Suspense } from 'react'; 2 | import styled from 'styled-components'; 3 | import { createGlobalStyle } from 'styled-components'; 4 | 5 | import AppHeader from '../AppHeader'; 6 | 7 | import Spinner from 'components/Spinner'; 8 | 9 | import { FlexDiv } from 'shared/commonStyles'; 10 | 11 | type MainLayoutProps = { 12 | children: React.ReactNode; 13 | isAppReady: boolean; 14 | }; 15 | 16 | export const MainLayout: FC = ({ children, isAppReady }) => ( 17 | <> 18 | 19 | 20 | 21 | }> 22 | {isAppReady ? children : } 23 | 24 | 25 | 26 | ); 27 | 28 | const GlobalStyle = createGlobalStyle` 29 | body { 30 | background-color: ${({ theme }) => theme.colors.surfaceL1}; 31 | color: ${({ theme }) => theme.colors.fontPrimary}; 32 | } 33 | `; 34 | 35 | const FullScreenContainer = styled(FlexDiv)` 36 | flex-flow: column; 37 | width: 100%; 38 | height: 100vh; 39 | position: relative; 40 | `; 41 | 42 | export default MainLayout; 43 | -------------------------------------------------------------------------------- /src/components/Typography/Heading.tsx: -------------------------------------------------------------------------------- 1 | import styled, { css } from 'styled-components'; 2 | 3 | const headingCSS = css` 4 | font-family: ${(props) => props.theme.fonts.medium}; 5 | `; 6 | 7 | export const headingH1CSS = css` 8 | font-family: ${(props) => props.theme.fonts.bold}; 9 | font-size: 56px; 10 | line-height: 1.1; 11 | `; 12 | 13 | export const headingH2CSS = css` 14 | ${headingCSS}; 15 | font-size: 48px; 16 | line-height: 1.3; 17 | `; 18 | 19 | export const headingH3CSS = css` 20 | ${headingCSS}; 21 | font-size: 32px; 22 | `; 23 | 24 | export const headingH4CSS = css` 25 | ${headingCSS}; 26 | font-size: 24px; 27 | `; 28 | 29 | export const headingH5CSS = css` 30 | ${headingCSS}; 31 | font-size: 20px; 32 | `; 33 | 34 | export const headingH6CSS = css` 35 | ${headingCSS}; 36 | font-size: 16px; 37 | `; 38 | 39 | // TODO: deprecate these 40 | 41 | export const headingMediumCSS = css` 42 | ${headingCSS}; 43 | font-size: 32px; 44 | `; 45 | 46 | export const headingSmallCSS = css` 47 | ${headingCSS}; 48 | font-size: 14px; 49 | `; 50 | 51 | export const HeadingMedium = styled.div` 52 | ${headingMediumCSS}; 53 | `; 54 | 55 | export const HeadingSmall = styled.div` 56 | ${headingSmallCSS}; 57 | `; 58 | -------------------------------------------------------------------------------- /src/components/Spinner/Spinner.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | import styled, { keyframes } from 'styled-components'; 3 | 4 | import spinnerBig from 'assets/images/spinner-big.png'; 5 | import spinnerSmall from 'assets/images/spinner-small.png'; 6 | 7 | import { absoluteCenteredCSS } from 'shared/commonStyles'; 8 | 9 | type ImageSize = 'lg' | 'sm'; 10 | 11 | type SpinnerProps = { 12 | size?: ImageSize; 13 | className?: string; 14 | centered?: boolean; 15 | }; 16 | 17 | const Spinner: FC = ({ size = 'lg', className, centered = false, ...rest }) => ( 18 | 19 | {size === 'sm' ? ( 20 | spinner 21 | ) : ( 22 | spinner 23 | )} 24 | 25 | ); 26 | 27 | const Container = styled.div<{ centered: boolean }>` 28 | ${(props) => props.centered && absoluteCenteredCSS} 29 | `; 30 | 31 | const imageRotation = keyframes` 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(359deg); 37 | } 38 | `; 39 | 40 | const Img = styled.img` 41 | animation: ${imageRotation} 2s infinite linear; 42 | `; 43 | 44 | export default Spinner; 45 | -------------------------------------------------------------------------------- /src/pages/Synths/Home/Hero/Hero.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | import { useTranslation } from 'react-i18next'; 4 | 5 | import { headingH2CSS } from 'components/Typography/Heading'; 6 | import { media } from 'shared/media'; 7 | import { darkTheme } from 'styles/theme'; 8 | 9 | export const Hero = () => { 10 | const { t } = useTranslation(); 11 | 12 | return ( 13 | 14 | 15 | {t('synths.home.hero.title')} 16 | 17 | 18 | ); 19 | }; 20 | 21 | const Container = styled.div` 22 | width: 100%; 23 | text-align: center; 24 | 25 | padding: 125px 24px 0 24px; 26 | ${media.large` 27 | padding: 80px 24px 0 24px; 28 | `} 29 | ${media.medium` 30 | padding: 45px 24px 0 24px; 31 | `} 32 | `; 33 | 34 | const Content = styled.div` 35 | margin: 0 auto; 36 | `; 37 | 38 | const HeroTitle = styled.div` 39 | ${headingH2CSS}; 40 | color: ${darkTheme.colors.fontPrimary}; 41 | max-width: 850px; 42 | margin: 0 auto; 43 | padding-bottom: 24px; 44 | ${media.large` 45 | font-size: 40px; 46 | line-height: 40px; 47 | `} 48 | ${media.medium` 49 | font-size: 32px; 50 | line-height: 32px; 51 | `} 52 | `; 53 | 54 | export default Hero; 55 | -------------------------------------------------------------------------------- /src/assets/currencies/crypto/COMP.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/images/splash/github-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/Icons/Arrow.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | type Direction = 'left' | 'right' | 'up' | 'down'; 5 | 6 | type ArrowProps = { 7 | direction?: Direction; 8 | }; 9 | 10 | const Arrow: FC = ({ direction = 'left' }) => ( 11 | // @ts-ignore 12 | 13 | 14 | 20 | 21 | 22 | ); 23 | 24 | const getDirectionAngle = (direction: Direction) => { 25 | switch (direction) { 26 | case 'up': 27 | return -Math.PI / 2; 28 | case 'left': 29 | return Math.PI; 30 | case 'down': 31 | return Math.PI / 2; 32 | case 'right': 33 | return 0; 34 | default: 35 | return -Math.PI / 2; 36 | } 37 | }; 38 | 39 | const Container = styled.div<{ direction: Direction }>` 40 | width: 11px; 41 | height: 8px; 42 | display: flex; 43 | transform: ${(props) => 'rotate(' + getDirectionAngle(props.direction) + 'rad)'}; 44 | `; 45 | 46 | export default Arrow; 47 | -------------------------------------------------------------------------------- /src/constants/links.ts: -------------------------------------------------------------------------------- 1 | import { CurrencyKey } from './currency'; 2 | 3 | export const LINKS = { 4 | Support: 'https://synthetix.community/docs/other', 5 | Tokens: 'https://www.synthetix.io/tokens/', 6 | Trading: { 7 | DexAG: 'https://dex.ag/', 8 | Uniswap: 'https://uniswap.exchange/', 9 | OneInchLink: (base: CurrencyKey, quote: CurrencyKey) => 10 | `https://1inch.exchange/#/${base}/${quote}`, 11 | }, 12 | Learn: { 13 | Litepaper: 'https://docs.synthetix.io/litepaper/', 14 | Tokens: 'https://docs.synthetix.io/tokens/', 15 | Blog: 'https://blog.synthetix.io/', 16 | }, 17 | Products: { 18 | Mintr: 'https://mintr.synthetix.io', 19 | Dashboard: 'https://dashboard.synthetix.io/', 20 | }, 21 | Social: { 22 | Twitter: 'https://twitter.com/synthetix_io', 23 | Medium: 'https://blog.synthetix.io/', 24 | Discord: 'https://discordapp.com/invite/AEdUHzt', 25 | GitHub: 'https://github.com/synthetixio', 26 | }, 27 | Misc: { 28 | EthereumOrg: 'https://ethereum.org/', 29 | DefiNetwork: 'https://defi.network/', 30 | Messari: 'https://messari.io/asset/synthetix', 31 | }, 32 | Blog: { 33 | HowBinaryOptionsWork: 'https://blog.synthetix.io/how-binary-options-work/', 34 | HowFeeReclamationRebatesWork: 'https://blog.synthetix.io/how-fee-reclamation-rebates-work/', 35 | }, 36 | }; 37 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React, { Suspense } from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { Provider } from 'react-redux'; 4 | import store from './config/store'; 5 | import Root from './pages/Root'; 6 | 7 | import MaintenanceMessage from './pages/Root/components/MaintenanceMessage'; 8 | 9 | import './i18n'; 10 | import './index.css'; 11 | 12 | import bugsnag from '@bugsnag/js'; 13 | import bugsnagReact from '@bugsnag/plugin-react'; 14 | 15 | bugsnag.releaseStage = process.env.NODE_ENV; 16 | const bugsnagClient = bugsnag('5eab4fa004f3869741bb65684d7fb5e3', { 17 | notifyReleaseStages: ['production', 'staging'], 18 | }); 19 | 20 | window.var = process.env; 21 | console.log('NODE_ENV', process.env.NODE_ENV); 22 | console.log(bugsnag.releaseStage); 23 | 24 | bugsnagClient.use(bugsnagReact, React); 25 | 26 | const SYSTEM_ON_MAINTENANCE = false; 27 | 28 | const ErrorBoundary = bugsnagClient.getPlugin('react'); 29 | const App = () => { 30 | return ( 31 | }> 32 | 33 | 34 | 35 | 36 | ); 37 | }; 38 | 39 | ReactDOM.render( 40 | SYSTEM_ON_MAINTENANCE ? ( 41 | 42 | ) : ( 43 | 44 | 45 | 46 | ), 47 | document.getElementById('root') 48 | ); 49 | -------------------------------------------------------------------------------- /src/assets/currencies/crypto/XTZ.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | env_defaults: &env_defaults 2 | working_directory: ~ 3 | docker: 4 | - image: circleci/node:10.16 5 | 6 | version: 2.1 7 | jobs: 8 | build: 9 | <<: *env_defaults 10 | steps: 11 | - checkout 12 | 13 | # Download and cache dependencies 14 | - restore_cache: 15 | keys: 16 | - v1.0-dependencies-{{ checksum "package.json" }} 17 | # fallback to using the latest cache if no exact match is found 18 | - v1.0-dependencies- 19 | 20 | - run: npm install 21 | 22 | - save_cache: 23 | paths: 24 | - node_modules 25 | key: v1.0-dependencies-{{ checksum "package.json" }} 26 | 27 | - persist_to_workspace: 28 | root: . 29 | paths: 30 | - node_modules 31 | 32 | lint: 33 | <<: *env_defaults 34 | steps: 35 | - checkout 36 | - attach_workspace: 37 | at: . 38 | - run: npm run lint 39 | 40 | test: 41 | <<: *env_defaults 42 | steps: 43 | - checkout 44 | - attach_workspace: 45 | at: . 46 | - run: npm test 47 | 48 | workflows: 49 | version: 2 50 | 51 | build-lint-test: 52 | jobs: 53 | - build 54 | - lint: 55 | requires: 56 | - build 57 | - test: 58 | requires: 59 | - build 60 | -------------------------------------------------------------------------------- /src/utils/balances.spec.js: -------------------------------------------------------------------------------- 1 | import { getCurrencyKeyUSDBalance, getCurrencyKeyBalance } from './balances'; 2 | import { CRYPTO_CURRENCY_MAP, SYNTHS_MAP } from '../constants/currency'; 3 | 4 | const balances = { 5 | synths: { 6 | balances: { 7 | sBTC: { 8 | balance: 0.000628320060412509, 9 | usdBalance: 6.50700536879026, 10 | }, 11 | }, 12 | usdBalance: 6.50700536879026, 13 | }, 14 | eth: { 15 | balance: 0.04243316499453552, 16 | usdBalance: 11.380247270217652, 17 | }, 18 | }; 19 | 20 | describe('Balances', () => { 21 | describe('getCurrencyKeyBalance', () => { 22 | it('returns the correct currency balance for ETH', () => { 23 | expect(getCurrencyKeyBalance(balances, CRYPTO_CURRENCY_MAP.ETH)).toEqual(0.04243316499453552); 24 | }); 25 | 26 | it('returns the correct currency balance for sBTC', () => { 27 | expect(getCurrencyKeyBalance(balances, SYNTHS_MAP.sBTC)).toEqual(0.000628320060412509); 28 | }); 29 | }); 30 | 31 | describe('getCurrencyKeyUSDBalance', () => { 32 | it('returns the correct USD balance for ETH', () => { 33 | expect(getCurrencyKeyUSDBalance(balances, CRYPTO_CURRENCY_MAP.ETH)).toEqual( 34 | 11.380247270217652 35 | ); 36 | }); 37 | 38 | it('returns the correct USD balance for sBTC', () => { 39 | expect(getCurrencyKeyUSDBalance(balances, SYNTHS_MAP.sBTC)).toEqual(6.50700536879026); 40 | }); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /src/assets/images/splash/twitter-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/shared/hooks/useLocalStorage.ts: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | 3 | // https://usehooks.com/useLocalStorage 4 | export function useLocalStorage(key: string, initialValue: any) { 5 | // State to store our value 6 | // Pass initial state function to useState so logic is only executed once 7 | const [storedValue, setStoredValue] = useState(() => { 8 | try { 9 | // Get from local storage by key 10 | const item = window.localStorage.getItem(key); 11 | // Parse stored json or if none return initialValue 12 | return item ? JSON.parse(item) : initialValue; 13 | } catch (error) { 14 | // If error also return initialValue 15 | console.log(error); 16 | return initialValue; 17 | } 18 | }); 19 | 20 | // Return a wrapped version of useState's setter function that ... 21 | // ... persists the new value to localStorage. 22 | const setValue = (value: any) => { 23 | try { 24 | // Allow value to be a function so we have same API as useState 25 | const valueToStore = value instanceof Function ? value(storedValue) : value; 26 | // Save state 27 | setStoredValue(valueToStore); 28 | // Save to local storage 29 | window.localStorage.setItem(key, JSON.stringify(valueToStore)); 30 | } catch (error) { 31 | // A more advanced implementation would handle the error case 32 | console.log(error); 33 | } 34 | }; 35 | 36 | return [storedValue, setValue]; 37 | } 38 | -------------------------------------------------------------------------------- /src/pages/Loans/components/LoanCards/BlockingOverlay/BlockingOverlay.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | import { useTranslation } from 'react-i18next'; 4 | 5 | import { ButtonPrimary } from 'components/Button'; 6 | import { HeadingSmall } from 'components/Typography'; 7 | import Link from 'components/Link'; 8 | import { FlexDivCentered } from 'shared/commonStyles'; 9 | 10 | const ETHER_COLLATERAL_BLOG_POST_LINK = 'https://blog.synthetix.io/bug-disclosure/'; 11 | 12 | const BlockingOverlay = () => { 13 | const { t } = useTranslation(); 14 | return ( 15 | 16 | 17 | {t('loans.loan-card.create-loan.paused.message')} 18 | 19 | 20 | 21 | {t('loans.loan-card.create-loan.paused.button-label')} 22 | 23 | 24 | 25 | ); 26 | }; 27 | 28 | const OverlayContainer = styled(FlexDivCentered)` 29 | background-color: ${(props) => props.theme.colors.surfaceL2}; 30 | width: 100%; 31 | height: 100%; 32 | position: absolute; 33 | left: 0; 34 | top: 0; 35 | flex-direction: column; 36 | justify-content: center; 37 | `; 38 | 39 | const PauseMessage = styled.div` 40 | padding-bottom: 30px; 41 | `; 42 | 43 | export default BlockingOverlay; 44 | -------------------------------------------------------------------------------- /src/constants/period.ts: -------------------------------------------------------------------------------- 1 | export type Period = 'ONE_HOUR' | 'FOUR_HOURS' | 'ONE_DAY' | 'ONE_WEEK' | 'ONE_MONTH'; 2 | 3 | export const PERIOD_IN_HOURS: Record = { 4 | ONE_HOUR: 1, 5 | FOUR_HOURS: 4, 6 | ONE_DAY: 24, 7 | ONE_MONTH: 672, 8 | ONE_WEEK: 168, 9 | }; 10 | 11 | export const PERIOD: Record = { 12 | ONE_HOUR: 'ONE_HOUR', 13 | FOUR_HOURS: 'FOUR_HOURS', 14 | ONE_DAY: 'ONE_DAY', 15 | ONE_WEEK: 'ONE_WEEK', 16 | ONE_MONTH: 'ONE_MONTH', 17 | }; 18 | 19 | export type PeriodLabel = { 20 | period: Period; 21 | value: number; 22 | i18nLabel: string; 23 | }; 24 | 25 | export const PERIOD_LABELS_MAP: Record = { 26 | ONE_HOUR: { 27 | period: 'ONE_HOUR', 28 | value: PERIOD_IN_HOURS.ONE_HOUR, 29 | i18nLabel: 'common.chart-periods.1H', 30 | }, 31 | FOUR_HOURS: { 32 | period: 'FOUR_HOURS', 33 | value: PERIOD_IN_HOURS.FOUR_HOURS, 34 | i18nLabel: 'common.chart-periods.4H', 35 | }, 36 | ONE_DAY: { 37 | period: 'ONE_DAY', 38 | value: PERIOD_IN_HOURS.ONE_DAY, 39 | i18nLabel: 'common.chart-periods.1D', 40 | }, 41 | ONE_WEEK: { 42 | period: 'ONE_WEEK', 43 | value: PERIOD_IN_HOURS.ONE_WEEK, 44 | i18nLabel: 'common.chart-periods.1W', 45 | }, 46 | ONE_MONTH: { 47 | period: 'ONE_MONTH', 48 | value: PERIOD_IN_HOURS.ONE_MONTH, 49 | i18nLabel: 'common.chart-periods.1M', 50 | }, 51 | }; 52 | 53 | export const PERIOD_LABELS = Object.values(PERIOD_LABELS_MAP); 54 | -------------------------------------------------------------------------------- /src/assets/currencies/fiat/GBP.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/components/TrendLineChart/TrendLineChart.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC, useContext } from 'react'; 2 | import styled, { ThemeContext } from 'styled-components'; 3 | import { LineChart, Line, XAxis, YAxis } from 'recharts'; 4 | 5 | import { BaseRateUpdates } from 'constants/rates'; 6 | import RechartsResponsiveContainer from 'components/RechartsResponsiveContainer'; 7 | 8 | type TrendLineChartProps = { 9 | change: number; 10 | chartData: BaseRateUpdates; 11 | onClick?: () => void; 12 | className?: string; 13 | }; 14 | 15 | export const TrendLineChart: FC = ({ 16 | change, 17 | chartData = [], 18 | onClick, 19 | className, 20 | }) => { 21 | const { colors } = useContext(ThemeContext); 22 | 23 | return ( 24 | 25 | 26 | 27 | 28 | 29 | = 0 ? colors.green : colors.red} 32 | dot={false} 33 | strokeWidth={1.5} 34 | activeDot={false} 35 | isAnimationActive={false} 36 | /> 37 | 38 | 39 | 40 | ); 41 | }; 42 | 43 | const Container = styled.div` 44 | width: 100%; 45 | height: 100%; 46 | `; 47 | 48 | export default TrendLineChart; 49 | -------------------------------------------------------------------------------- /src/assets/currencies/crypto/REN.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /scripts/test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // Do this as the first thing so that any code reading it knows the right env. 4 | process.env.BABEL_ENV = 'test'; 5 | process.env.NODE_ENV = 'test'; 6 | process.env.PUBLIC_URL = ''; 7 | 8 | // Makes the script crash on unhandled rejections instead of silently 9 | // ignoring them. In the future, promise rejections that are not handled will 10 | // terminate the Node.js process with a non-zero exit code. 11 | process.on('unhandledRejection', err => { 12 | throw err; 13 | }); 14 | 15 | // Ensure environment variables are read. 16 | require('../config/env'); 17 | 18 | const jest = require('jest'); 19 | const execSync = require('child_process').execSync; 20 | let argv = process.argv.slice(2); 21 | 22 | function isInGitRepository() { 23 | try { 24 | execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' }); 25 | return true; 26 | } catch (e) { 27 | return false; 28 | } 29 | } 30 | 31 | function isInMercurialRepository() { 32 | try { 33 | execSync('hg --cwd . root', { stdio: 'ignore' }); 34 | return true; 35 | } catch (e) { 36 | return false; 37 | } 38 | } 39 | 40 | // Watch unless on CI or explicitly running all tests 41 | if (!process.env.CI && argv.indexOf('--watchAll') === -1) { 42 | // https://github.com/facebook/create-react-app/issues/5210 43 | const hasSourceControl = isInGitRepository() || isInMercurialRepository(); 44 | argv.push(hasSourceControl ? '--watch' : '--watchAll'); 45 | } 46 | 47 | jest.run(argv); 48 | -------------------------------------------------------------------------------- /src/pages/Trade/components/BlurBackground/BlurBackground.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | import { connect } from 'react-redux'; 3 | 4 | import { getBlurBackgroundIsVisible } from 'ducks/ui'; 5 | import styled, { keyframes, css } from 'styled-components'; 6 | import { Z_INDEX } from 'constants/ui'; 7 | import { RootState } from 'ducks/types'; 8 | 9 | type StateProps = { 10 | blurBackgroundIsVisible: boolean; 11 | }; 12 | 13 | type BlurBackgroundProps = StateProps; 14 | 15 | const BlurBackground: FC = ({ blurBackgroundIsVisible }) => ( 16 | 17 | ); 18 | 19 | const keyf = keyframes` 20 | from { 21 | backdrop-filter: blur(0px); 22 | opacity: 0; 23 | } 24 | to { 25 | backdrop-filter: blur(5px); 26 | opacity: 0.6 27 | } 28 | `; 29 | 30 | const isBlurred = css` 31 | animation: ${keyf} 0.1s linear forwards; 32 | `; 33 | 34 | const Blur = styled.div<{ isVisible: boolean }>` 35 | backdrop-filter: blur(0px); 36 | pointer-events: none; 37 | position: absolute; 38 | z-index: ${Z_INDEX.BLUR_MODAL}; 39 | opacity: 0; 40 | bottom: 0; 41 | top: 54px; 42 | width: 100%; 43 | background: ${(props) => props.theme.colors.surfaceL1}; 44 | ${(props) => props.isVisible && isBlurred} 45 | `; 46 | 47 | const mapStateToProps = (state: RootState): StateProps => ({ 48 | blurBackgroundIsVisible: getBlurBackgroundIsVisible(state), 49 | }); 50 | 51 | export default connect(mapStateToProps)(BlurBackground); 52 | -------------------------------------------------------------------------------- /src/components/Button/ButtonPrimary.js: -------------------------------------------------------------------------------- 1 | import styled, { css } from 'styled-components'; 2 | import { width } from 'styled-system'; 3 | 4 | const smallButtonCSS = css` 5 | height: 32px; 6 | font-size: 14px; 7 | padding: 0 12px; 8 | width: auto; 9 | line-height: 34px; 10 | `; 11 | 12 | const extraSmallButtonCSS = css` 13 | height: 24px; 14 | font-size: 11px; 15 | padding: 0 10px; 16 | width: auto; 17 | line-height: 24px; 18 | `; 19 | 20 | const ButtonPrimary = styled.button` 21 | border-radius: 1px; 22 | height: 48px; 23 | width: 100%; 24 | font-size: 16px; 25 | letter-spacing: 0.2px; 26 | font-family: ${(props) => props.theme.fonts.medium}; 27 | color: ${(props) => props.theme.colors.white}; 28 | cursor: pointer; 29 | padding: 0 6px; 30 | background-color: ${(props) => props.theme.colors.buttonDefault}; 31 | &:disabled { 32 | opacity: 0.5; 33 | cursor: default; 34 | } 35 | &:hover { 36 | &:not(:disabled) { 37 | background-color: ${(props) => props.theme.colors.buttonHover}; 38 | } 39 | } 40 | border: none; 41 | text-transform: uppercase; 42 | line-height: 44px; 43 | white-space: nowrap; 44 | ${width}; 45 | ${(props) => props.size === 'sm' && smallButtonCSS} 46 | ${(props) => props.size === 'xs' && extraSmallButtonCSS} 47 | `; 48 | 49 | export const ButtonPrimarySmall = styled(ButtonPrimary)` 50 | ${smallButtonCSS} 51 | `; 52 | 53 | export const ButtonPrimaryExtraSmall = styled(ButtonPrimary)` 54 | ${extraSmallButtonCSS} 55 | `; 56 | 57 | export default ButtonPrimary; 58 | -------------------------------------------------------------------------------- /src/assets/images/no-wallet.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![CircleCI](https://circleci.com/gh/Synthetixio/synthetix-exchange.svg?style=svg&circle-token=fd3dc3a4369c1e281e05262f695d59f94cf5340f)](https://circleci.com/gh/Synthetixio/synthetix-exchange) [![Netlify Status](https://api.netlify.com/api/v1/badges/36a95f47-4d7c-4fd2-be00-fc28fa5822e9/deploy-status)](https://app.netlify.com/sites/synthetix/deploys) [![Discord](https://img.shields.io/discord/413890591840272394.svg?color=768AD4&label=discord&logo=https%3A%2F%2Fdiscordapp.com%2Fassets%2F8c9701b98ad4372b58f13fd9f65f966e.svg)](https://discordapp.com/channels/413890591840272394/) 2 | [![Twitter Follow](https://img.shields.io/twitter/follow/synthetix_io.svg?label=synthetix_io&style=social)](https://twitter.com/synthetix_io) 3 | 4 | # Synthetix.Exchange 5 | 6 | The code for the [Synthetix.Exchange](https://synthetix.exchange) dApp.
7 | It is powered by [synthetix-data](https://github.com/Synthetixio/synthetix-data) and [synthetix-js](https://github.com/Synthetixio/synthetix-js). 8 | 9 | ## Available Scripts 10 | 11 | In the project directory, you can run: 12 | 13 | ### `npm start` 14 | 15 | Runs the app in the development mode.
16 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 17 | 18 | ### `npm test` 19 | 20 | Runs the tests. 21 | 22 | ### `npm run build` 23 | 24 | Builds the app for production to the `build` folder. 25 | 26 | ### `npm run storybook` 27 | 28 | Runs storybook.
29 | Open [http://localhost:6006](http://localhost:6006) to view it in the browser. 30 | -------------------------------------------------------------------------------- /src/constants/queryKeys.ts: -------------------------------------------------------------------------------- 1 | import { CurrencyKey } from './currency'; 2 | import { Period } from './period'; 3 | 4 | export const QUERY_KEYS = { 5 | Synths: { 6 | HistoricalRates: (currencyKey: CurrencyKey, period: Period) => [ 7 | 'synths', 8 | 'historicalRates', 9 | currencyKey, 10 | period, 11 | ], 12 | }, 13 | BinaryOptions: { 14 | Markets: ['binaryOptions', 'markets'], 15 | Market: (marketAddress: string) => ['binaryOptions', 'markets', marketAddress], 16 | AccountMarketInfo: (marketAddress: string, accountAddress: string) => [ 17 | 'binaryOptions', 18 | 'markets', 19 | marketAddress, 20 | accountAddress, 21 | ], 22 | RecentTransactions: (marketAddress: string) => ['binaryOptions', 'transactions', marketAddress], 23 | UserTransactions: (marketAddress: string, walletAddress: string) => [ 24 | 'binaryOptions', 25 | 'transactions', 26 | marketAddress, 27 | walletAddress, 28 | ], 29 | UserMarkets: (walletAddress: string) => ['binaryOptions', 'userMarkets', walletAddress], 30 | OptionPrices: (marketAddress: string, period: Period) => [ 31 | 'binaryOptions', 32 | marketAddress, 33 | period, 34 | ], 35 | }, 36 | HistoricalTrades: { 37 | AllTrades: ['historicalTrades', 'trades'], 38 | UserTrades: (walletAddress: string) => ['historicalTrades', 'trades', walletAddress], 39 | UserSettledTrades: (walletAddress: string) => [ 40 | 'historicalSettledTrades', 41 | 'trades', 42 | walletAddress, 43 | ], 44 | }, 45 | }; 46 | 47 | export default QUERY_KEYS; 48 | -------------------------------------------------------------------------------- /src/assets/currencies/fiat/CHF.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/components/ChangePercent/ChangePercent.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react'; 2 | import styled, { css } from 'styled-components'; 3 | 4 | import { formatPercentage } from 'utils/formatters'; 5 | 6 | type LabelSize = 'sm' | 'md' | 'lg'; 7 | 8 | type ChangePercentProps = { 9 | value: number; 10 | isLabel?: boolean; 11 | labelSize?: LabelSize; 12 | className?: string; 13 | }; 14 | 15 | export const ChangePercent: FC = ({ 16 | value, 17 | isLabel = false, 18 | labelSize = 'md', 19 | ...rest 20 | }) => ( 21 | = 0} isLabel={isLabel} labelSize={labelSize as LabelSize} {...rest}> 22 | {formatPercentage(value)} 23 | 24 | ); 25 | 26 | const Container = styled.span<{ isLabel: boolean; isPositive: boolean; labelSize: LabelSize }>` 27 | ${(props) => 28 | props.isLabel 29 | ? css` 30 | background-color: ${(props) => 31 | // @ts-ignore 32 | props.isPositive ? props.theme.colors.green : props.theme.colors.red}; 33 | 34 | border-radius: 1px; 35 | color: ${(props) => props.theme.colors.white}; 36 | padding: 4px 8px; 37 | text-align: center; 38 | ${(props) => 39 | // @ts-ignore 40 | props.labelSize === 'sm' && 41 | css` 42 | font-size: 12px; 43 | padding: 4px; 44 | `} 45 | ` 46 | : css` 47 | color: ${(props) => 48 | // @ts-ignore 49 | props.isPositive ? props.theme.colors.green : props.theme.colors.red}; 50 | `} 51 | `; 52 | 53 | export default ChangePercent; 54 | -------------------------------------------------------------------------------- /src/pages/Root/components/HomeLayout/HomeLayout.tsx: -------------------------------------------------------------------------------- 1 | import React, { Suspense, FC } from 'react'; 2 | import styled, { ThemeProvider, createGlobalStyle } from 'styled-components'; 3 | import { darkTheme, lightTheme } from 'styles/theme'; 4 | 5 | import Footer from './Footer'; 6 | import AppHeader from '../AppHeader'; 7 | 8 | import Spinner from 'components/Spinner'; 9 | 10 | type HomeLayoutProps = { 11 | children: React.ReactNode; 12 | isAppReady?: boolean; 13 | }; 14 | 15 | const LoadingContainer: FC = () => ( 16 | 17 | 18 | 19 | ); 20 | 21 | const HomeLayout: FC = ({ children, isAppReady }) => { 22 | let componentToRender = children; 23 | 24 | if (isAppReady != null) { 25 | componentToRender = isAppReady ? children : ; 26 | } 27 | 28 | return ( 29 | <> 30 | 31 | {/* force the app header to be in dark mode */} 32 | 33 | 34 | 35 | }>{componentToRender} 36 |