├── .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 |
4 |
--------------------------------------------------------------------------------
/src/assets/images/arrow-down.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/images/sort-up.svg:
--------------------------------------------------------------------------------
1 |
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 |
4 |
--------------------------------------------------------------------------------
/src/assets/images/sort.svg:
--------------------------------------------------------------------------------
1 |
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 |
4 |
--------------------------------------------------------------------------------
/src/assets/images/trend-down.svg:
--------------------------------------------------------------------------------
1 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
5 |
--------------------------------------------------------------------------------
/src/assets/images/blocked.svg:
--------------------------------------------------------------------------------
1 |
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 |
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 |
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 |
5 |
--------------------------------------------------------------------------------
/src/assets/images/close.svg:
--------------------------------------------------------------------------------
1 |
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 |
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 |
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 |
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 |
5 |
--------------------------------------------------------------------------------
/src/assets/images/info-rounded.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/currencies/crypto/BTC.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/currencies/crypto/BCH.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/currencies/fiat/KRW.svg:
--------------------------------------------------------------------------------
1 |
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 |
10 |
--------------------------------------------------------------------------------
/src/assets/images/wallets/trezor.svg:
--------------------------------------------------------------------------------
1 |
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 |
4 |
--------------------------------------------------------------------------------
/src/assets/images/reverse-arrow.svg:
--------------------------------------------------------------------------------
1 |
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 |
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 |
6 |
--------------------------------------------------------------------------------
/src/assets/images/wallet.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/assets/images/arrows-square.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/src/assets/currencies/indices/DEFI.svg:
--------------------------------------------------------------------------------
1 |
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 |
21 | ) : (
22 |
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 |
5 |
--------------------------------------------------------------------------------
/src/assets/images/splash/github-logo.svg:
--------------------------------------------------------------------------------
1 |
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 |
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 |
--------------------------------------------------------------------------------
/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 |
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 |
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://circleci.com/gh/Synthetixio/synthetix-exchange) [](https://app.netlify.com/sites/synthetix/deploys) [](https://discordapp.com/channels/413890591840272394/)
2 | [](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 |
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 |
37 | >
38 | );
39 | };
40 |
41 | const LoaderContainer = styled.div`
42 | position: relative;
43 | height: 400px;
44 | `;
45 |
46 | const GlobalStyle = createGlobalStyle`
47 | body {
48 | background-color: ${darkTheme.colors.surfaceL1};
49 | color: ${lightTheme.colors.fontPrimary};
50 | }
51 | `;
52 |
53 | export default HomeLayout;
54 |
--------------------------------------------------------------------------------
/src/config/store.js:
--------------------------------------------------------------------------------
1 | import { createStore, applyMiddleware, compose } from 'redux';
2 | import thunk from 'redux-thunk';
3 | import createSagaMiddleware from 'redux-saga';
4 |
5 | import reducers from '../ducks';
6 | import rootSaga from '../ducks/sagas';
7 |
8 | export function persistState(reducerModule, update) {
9 | try {
10 | let state = {};
11 | const serializedState = localStorage.getItem('persistedState');
12 | if (serializedState !== null) {
13 | state = JSON.parse(serializedState);
14 | }
15 | state[reducerModule] = state[reducerModule] || {};
16 | Object.assign(state[reducerModule], update);
17 | localStorage.setItem('persistedState', JSON.stringify(state));
18 | } catch (err) {
19 | // empty
20 | }
21 | }
22 |
23 | export function getPersistedState(reducerModule) {
24 | let persistedState = {};
25 | try {
26 | const serializedState = localStorage.getItem('persistedState');
27 | if (serializedState !== null) {
28 | persistedState = JSON.parse(serializedState);
29 | return persistedState[reducerModule];
30 | }
31 | } catch (err) {
32 | // empty
33 | }
34 |
35 | return {};
36 | }
37 |
38 | const sagaMiddleware = createSagaMiddleware();
39 |
40 | const middleware = [thunk, sagaMiddleware];
41 |
42 | const finalCreateStore = compose(
43 | applyMiddleware(...middleware),
44 | window.devToolsExtension ? window.__REDUX_DEVTOOLS_EXTENSION__() : (f) => f
45 | )(createStore);
46 |
47 | const store = finalCreateStore(reducers);
48 |
49 | sagaMiddleware.run(rootSaga);
50 |
51 | export default store;
52 |
--------------------------------------------------------------------------------
/src/pages/Home/Hero/Hero.js:
--------------------------------------------------------------------------------
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('home.hero.title')}
16 | {t('home.hero.subtitle')}
17 |
18 |
19 | );
20 | };
21 |
22 | const Container = styled.div`
23 | width: 100%;
24 | text-align: center;
25 |
26 | padding: 125px 24px 0 24px;
27 | ${media.large`
28 | padding: 80px 24px 0 24px;
29 | `}
30 | ${media.medium`
31 | padding: 45px 24px 0 24px;
32 | `}
33 | `;
34 |
35 | const Content = styled.div`
36 | margin: 0 auto;
37 | `;
38 |
39 | const HeroTitle = styled.div`
40 | ${headingH2CSS};
41 | color: ${darkTheme.colors.fontPrimary};
42 | padding-bottom: 24px;
43 | ${media.large`
44 | font-size: 40px;
45 | line-height: 40px;
46 | `}
47 | ${media.medium`
48 | font-size: 32px;
49 | line-height: 32px;
50 | `}
51 | `;
52 |
53 | const HeroSubtitle = styled.div`
54 | font-size: 24px;
55 | color: ${darkTheme.colors.fontTertiary};
56 | font-family: ${(props) => props.theme.fonts.regular};
57 | ${media.large`
58 | font-size: 16px;
59 | `}
60 | ${media.medium`
61 | font-size: 14px;
62 | `}
63 | `;
64 |
65 | export default Hero;
66 |
--------------------------------------------------------------------------------
/src/pages/Options/Market/ChartCard/common.ts:
--------------------------------------------------------------------------------
1 | import styled, { css } from 'styled-components';
2 | import { GridDivCenteredRow, absoluteCenteredCSS } from 'shared/commonStyles';
3 | import { subtitleSmallCSS } from 'components/Typography/General';
4 |
5 | export const ChartContainer = styled.div<{ semiTransparent: boolean }>`
6 | height: 300px;
7 | position: relative;
8 | ${(props) =>
9 | props.semiTransparent &&
10 | css`
11 | opacity: 0.5;
12 | filter: blur(3px);
13 | `}
14 |
15 | .ref-line-label {
16 | font-size: 10px;
17 | font-family: ${(props) => props.theme.fonts.regular};
18 | text-transform: uppercase;
19 | }
20 | .ref-line-label-long {
21 | fill: ${(props) => props.theme.colors.green};
22 | }
23 | .ref-line-label-short {
24 | fill: ${(props) => props.theme.colors.red};
25 | }
26 | .ref-line-label-strike-price {
27 | fill: ${(props) => props.theme.colors.fontSecondary};
28 | }
29 | .recharts-tooltip-label,
30 | .recharts-tooltip-item {
31 | color: ${(props) => props.theme.colors.fontPrimary} !important;
32 | }
33 | `;
34 |
35 | export const NoChartData = styled(GridDivCenteredRow)`
36 | ${absoluteCenteredCSS};
37 | ${subtitleSmallCSS};
38 | grid-gap: 10px;
39 | color: ${(props) => props.theme.colors.fontPrimary};
40 | padding: 20px;
41 | background-color: ${(props) => props.theme.colors.surfaceL3};
42 | border-radius: 2px;
43 | font-size: 12px;
44 | font-family: ${(props) => props.theme.fonts.medium};
45 | justify-items: center;
46 | svg {
47 | color: ${(props) => props.theme.colors.accentL2};
48 | }
49 | `;
50 |
--------------------------------------------------------------------------------
/src/pages/Options/Market/TransactionsCard/RecentTransactions/RecentTransactions.tsx:
--------------------------------------------------------------------------------
1 | import React, { FC } from 'react';
2 | import { useTranslation } from 'react-i18next';
3 | import { useQuery } from 'react-query';
4 |
5 | import snxData from 'synthetix-data';
6 |
7 | import { OptionsMarketInfo, OptionsTransactions } from 'pages/Options/types';
8 |
9 | import QUERY_KEYS from 'constants/queryKeys';
10 | import TransactionsTable from '../components/TransactionsTable';
11 |
12 | import { TableNoResults } from 'shared/commonStyles';
13 |
14 | type RecentTransactionsProps = {
15 | marketAddress: OptionsMarketInfo['address'];
16 | };
17 |
18 | const RecentTransactions: FC = ({ marketAddress }) => {
19 | const { t } = useTranslation();
20 |
21 | const transactionsQuery = useQuery(
22 | QUERY_KEYS.BinaryOptions.RecentTransactions(marketAddress),
23 | () => snxData.binaryOptions.optionTransactions({ market: marketAddress })
24 | );
25 |
26 | const noResults =
27 | transactionsQuery.isSuccess && transactionsQuery.data && transactionsQuery.data.length === 0;
28 |
29 | return (
30 |
36 | {t('options.market.transactions-card.table.no-results-recent-activity')}
37 |
38 | ) : undefined
39 | }
40 | />
41 | );
42 | };
43 |
44 | export default RecentTransactions;
45 |
--------------------------------------------------------------------------------
/src/assets/currencies/indices/CEX.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/pages/Options/Market/TradeCard/common.ts:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import { GridDivCenteredCol } from 'shared/commonStyles';
3 | import Card from 'components/Card';
4 | import { formLabelSmallCSS } from 'components/Typography/Form';
5 | import { Button } from 'components/Button';
6 | import { sectionTitleCSS } from 'components/Typography/General';
7 |
8 | import TimeRemaining from 'pages/Options/Home/components/TimeRemaining';
9 |
10 | export const StyledCardHeader = styled(Card.Header)`
11 | padding: 0 16px;
12 | ${sectionTitleCSS};
13 | `;
14 |
15 | export const CardContent = styled.div`
16 | padding: 12px;
17 | border-bottom: 1px solid
18 | ${(props) =>
19 | props.theme.isDarkTheme ? props.theme.colors.accentL1 : props.theme.colors.accentL2};
20 | &:last-child {
21 | border-bottom: 0;
22 | }
23 | `;
24 |
25 | export const StyledCardBody = styled(Card.Body)`
26 | padding: 0;
27 | `;
28 |
29 | export const WalletBalance = styled(GridDivCenteredCol)`
30 | font-family: ${(props) => props.theme.fonts.medium};
31 | font-size: 12px;
32 | grid-gap: 8px;
33 | color: ${(props) => props.theme.colors.fontSecondary};
34 | `;
35 |
36 | export const Title = styled.div`
37 | ${formLabelSmallCSS};
38 | `;
39 |
40 | export const ActionButton = styled(Button)`
41 | width: 100%;
42 | `;
43 |
44 | export const PhaseEnd = styled.div`
45 | font-size: 12px;
46 | text-transform: uppercase;
47 | text-align: center;
48 | padding-top: 12px;
49 | `;
50 |
51 | export const StyledTimeRemaining = styled(TimeRemaining)`
52 | background: none;
53 | font-size: 12px;
54 | padding: 0;
55 | display: inline;
56 | `;
57 |
--------------------------------------------------------------------------------
/src/pages/Options/Market/TransactionsCard/YourTransactions/YourTransactions.tsx:
--------------------------------------------------------------------------------
1 | import React, { FC } from 'react';
2 | import { useTranslation } from 'react-i18next';
3 | import snxData from 'synthetix-data';
4 | import { useQuery } from 'react-query';
5 |
6 | import { OptionsMarketInfo, OptionsTransactions } from 'pages/Options/types';
7 | import TransactionsTable from '../components/TransactionsTable';
8 |
9 | import QUERY_KEYS from 'constants/queryKeys';
10 | import { TableNoResults } from 'shared/commonStyles';
11 |
12 | type RecentTransactionsProps = {
13 | marketAddress: OptionsMarketInfo['address'];
14 | walletAddress: string;
15 | };
16 |
17 | const RecentTransactions: FC = ({ marketAddress, walletAddress }) => {
18 | const { t } = useTranslation();
19 |
20 | const transactionsQuery = useQuery(
21 | QUERY_KEYS.BinaryOptions.UserTransactions(marketAddress, walletAddress),
22 | () =>
23 | snxData.binaryOptions.optionTransactions({ market: marketAddress, account: walletAddress })
24 | );
25 |
26 | const noResults =
27 | transactionsQuery.isSuccess && transactionsQuery.data && transactionsQuery.data.length === 0;
28 |
29 | return (
30 |
36 | {t('options.market.transactions-card.table.no-results-your-activity')}
37 |
38 | ) : undefined
39 | }
40 | />
41 | );
42 | };
43 |
44 | export default RecentTransactions;
45 |
--------------------------------------------------------------------------------
/src/components/deprecated/Table/Table.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import { color } from 'styled-system';
3 |
4 | import { DataSmall } from '../../Typography';
5 |
6 | export const Table = styled.table`
7 | width: 100%;
8 | height: ${(props) => (props.height ? props.height : '100%')};
9 | display: flex;
10 | flex-direction: column;
11 | background-color: ${(props) => props.theme.colors.surfaceL2};
12 | `;
13 |
14 | export const Thead = styled.thead`
15 | background-color: ${(props) => props.theme.colors.surfaceL3};
16 | `;
17 |
18 | export const Tbody = styled.tbody`
19 | overflow: auto;
20 | min-height: 0;
21 | `;
22 |
23 | export const Tr = styled.tr`
24 | display: flex;
25 | `;
26 |
27 | export const Th = styled.th`
28 | display: flex;
29 | flex-direction: column;
30 | flex-basis: 100%;
31 | justify-content: center;
32 | height: 42px;
33 | line-height: 12px;
34 | text-align: right;
35 | align-items: flex-end;
36 | &:first-child {
37 | text-align: left;
38 | align-items: flex-start;
39 | }
40 | padding: 0 18px;
41 | @media screen and (max-width: 1440px) {
42 | padding: 6px 8px;
43 | }
44 | `;
45 |
46 | export const Td = styled.td`
47 | display: flex;
48 | flex-direction: column;
49 | flex-basis: 100%;
50 | text-align: right;
51 | &:first-child {
52 | text-align: left;
53 | }
54 | padding: 6px 18px;
55 | @media screen and (max-width: 1440px) {
56 | padding: 6px 8px;
57 | }
58 | `;
59 |
60 | export const DataLabel = styled(DataSmall)`
61 | text-transform: none;
62 | color: ${(props) => props.theme.colors.fontPrimary};
63 | font-family: 'apercu-regular', sans-serif;
64 | ${color};
65 | `;
66 |
--------------------------------------------------------------------------------
/src/pages/Options/Market/MarketContainer.tsx:
--------------------------------------------------------------------------------
1 | import React, { FC, useEffect, useState } from 'react';
2 | import { RouteComponentProps } from 'react-router-dom';
3 | import snxJSConnector from 'utils/snxJSConnector';
4 | import { ethers } from 'ethers';
5 |
6 | import binaryOptionMarketContract from 'utils/contracts/binaryOptionsMarketContract';
7 |
8 | import { LoaderContainer } from 'shared/commonStyles';
9 | import Spinner from 'components/Spinner';
10 |
11 | import ROUTES, { navigateTo } from 'constants/routes';
12 |
13 | import { BOMContractProvider } from './contexts/BOMContractContext';
14 |
15 | import Market from './Market';
16 |
17 | type MarketContainerProps = RouteComponentProps<{
18 | marketAddress: string;
19 | }>;
20 |
21 | const MarketContainer: FC = ({ match }) => {
22 | const [BOMContract, setBOMContract] = useState();
23 |
24 | useEffect(() => {
25 | const { params } = match;
26 |
27 | if (params && params.marketAddress) {
28 | setBOMContract(
29 | new ethers.Contract(
30 | params.marketAddress,
31 | binaryOptionMarketContract.abi,
32 | (snxJSConnector as any).provider
33 | )
34 | );
35 | } else {
36 | navigateTo(ROUTES.Options.Home);
37 | }
38 | // eslint-disable-next-line react-hooks/exhaustive-deps
39 | }, [match]);
40 |
41 | return BOMContract ? (
42 |
43 |
44 |
45 | ) : (
46 |
47 |
48 |
49 | );
50 | };
51 |
52 | export default MarketContainer;
53 |
--------------------------------------------------------------------------------
/src/ducks/options/pendingTransaction.ts:
--------------------------------------------------------------------------------
1 | import { createSlice, PayloadAction } from '@reduxjs/toolkit';
2 | import { RootState } from '../types';
3 | import { OptionsTransactions, OptionsTransaction } from 'pages/Options/types';
4 |
5 | const sliceName = 'pendingTransaction';
6 |
7 | const initialState: OptionsTransactions = [];
8 |
9 | export const pendingTransactionsSlice = createSlice({
10 | name: sliceName,
11 | initialState,
12 | reducers: {
13 | addOptionsPendingTransaction: (
14 | state,
15 | action: PayloadAction<{
16 | optionTransaction: Omit;
17 | }>
18 | ) => {
19 | const { optionTransaction } = action.payload;
20 |
21 | const optionTransactionWithStatus: OptionsTransaction = {
22 | ...optionTransaction,
23 | status: 'pending',
24 | timestamp: Date.now(),
25 | };
26 |
27 | state.unshift(optionTransactionWithStatus);
28 | },
29 | updateOptionsPendingTransactionStatus: (
30 | state,
31 | action: PayloadAction<{
32 | hash: OptionsTransaction['hash'];
33 | status: OptionsTransaction['status'];
34 | }>
35 | ) => {
36 | const { hash, status } = action.payload;
37 |
38 | state.forEach((optionTransaction, idx) => {
39 | if (optionTransaction.hash === hash) {
40 | state[idx].status = status;
41 | }
42 | });
43 | },
44 | },
45 | });
46 |
47 | export const getOptionsPendingTransactions = (state: RootState) => state.options[sliceName];
48 |
49 | export const {
50 | addOptionsPendingTransaction,
51 | updateOptionsPendingTransactionStatus,
52 | } = pendingTransactionsSlice.actions;
53 |
54 | export default pendingTransactionsSlice.reducer;
55 |
--------------------------------------------------------------------------------
/src/components/Input/SearchInput.tsx:
--------------------------------------------------------------------------------
1 | import React, { FC } from 'react';
2 | import { useTranslation } from 'react-i18next';
3 | import styled from 'styled-components';
4 |
5 | import { ReactComponent as SearchIcon } from 'assets/images/search.svg';
6 |
7 | import GenericInput from './Input';
8 | import { INPUT_SIZES } from './constants';
9 |
10 | type SearchInputProps = {
11 | onChange: (event: React.ChangeEvent) => void;
12 | value: string;
13 | placeholder?: string;
14 | tabIndex?: number;
15 | autoFocus?: boolean;
16 | };
17 |
18 | export const SearchInput: FC = ({
19 | onChange,
20 | value,
21 | placeholder,
22 | tabIndex,
23 | autoFocus,
24 | ...rest
25 | }) => {
26 | const { t } = useTranslation();
27 |
28 | return (
29 |
30 |
31 |
42 |
43 | );
44 | };
45 |
46 | const Container = styled.div`
47 | position: relative;
48 | `;
49 |
50 | const StyledInput = styled(GenericInput)`
51 | height: ${INPUT_SIZES.xs};
52 | border-radius: 1px;
53 | padding: 0 10px 0 25px;
54 | &::placeholder {
55 | text-transform: uppercase;
56 | }
57 | `;
58 |
59 | const StyledSearchIcon = styled(SearchIcon)`
60 | width: 12px;
61 | height: 12px;
62 | position: absolute;
63 | top: 50%;
64 | left: 10px;
65 | transform: translateY(-50%);
66 | `;
67 |
68 | export default SearchInput;
69 |
--------------------------------------------------------------------------------
/src/assets/images/splash/medium-logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------