├── landing ├── assets │ ├── js │ │ ├── main.js │ │ └── main.js.map │ ├── fonts │ │ ├── SpaceMono-Bold.ttf │ │ ├── SpaceMono-Bold.woff2 │ │ ├── SpaceMono-Regular.ttf │ │ └── SpaceMono-Regular.woff2 │ └── images │ │ ├── logo_2.svg │ │ ├── logo_4.svg │ │ ├── logo_1.svg │ │ └── logo_3.svg └── favicon.png ├── src ├── integrations │ ├── index.ts │ ├── types.ts │ └── walletIntegration.ts ├── assets │ ├── bg.jpg │ ├── dutchx.png │ ├── favicon.png │ ├── tokens │ │ ├── 1ST.png │ │ ├── ETH.svg │ │ ├── MKR.svg │ │ ├── TOKEN_LIST.svg │ │ ├── index.ts │ │ ├── DAI.svg │ │ ├── CVC.svg │ │ ├── SNT.svg │ │ ├── REQ.svg │ │ ├── RDN.svg │ │ ├── OST.svg │ │ ├── OMG.svg │ │ └── LRC.svg │ ├── pdf │ │ └── PrivacyPolicy.pdf │ ├── JauntyHarshIrishsetter.gif │ ├── img │ │ ├── gnosis_logo_favicon.png │ │ ├── icons │ │ │ ├── icon_coinbase.png │ │ │ ├── icon_checkmark.svg │ │ │ ├── icon_incomeForecast.svg │ │ │ ├── icon_user.svg │ │ │ ├── icon_cross.svg │ │ │ ├── providerIcons.js │ │ │ ├── icon_status.svg │ │ │ ├── icon_metamask.svg │ │ │ ├── icon_currency.svg │ │ │ ├── icon_countdown.svg │ │ │ ├── icon_enddate.svg │ │ │ ├── icon_etherTokens.svg │ │ │ ├── icon_market.svg │ │ │ ├── icon_achievementBadge.svg │ │ │ ├── icon_gear.svg │ │ │ ├── icon_earnedTokens.svg │ │ │ ├── icon_oracle.svg │ │ │ └── icon_defaultWallet.svg │ │ └── gnosis_logo_icon.svg │ ├── brand │ │ ├── fonts │ │ │ ├── SpaceMono-Bold.ttf │ │ │ ├── SpaceMono-Bold.woff2 │ │ │ ├── SpaceMono-Regular.ttf │ │ │ └── SpaceMono-Regular.woff2 │ │ └── images │ │ │ ├── logo_2.svg │ │ │ ├── logo_4.svg │ │ │ ├── logo_1.svg │ │ │ └── logo_3.svg │ ├── content │ │ ├── dutchX_slowtrade.png │ │ ├── LC_reduction_model_bg.png │ │ └── step_by_step_fee_calculation.png │ ├── alert.svg │ ├── arrowDownStep.svg │ ├── arrowSidesRight.svg │ ├── arrowPrev.svg │ ├── copy.svg │ ├── berliner.svg │ ├── arrowSides.svg │ ├── identicon-demo.svg │ ├── ok.svg │ ├── settings.svg │ ├── claim.svg │ ├── auction.svg │ ├── auctionStep.svg │ ├── 404.svg │ ├── walletStep.svg │ ├── wallet-ok.svg │ ├── arrowDown-white.svg │ └── arrowDown.svg ├── public │ └── google96dd53efdc540a07.html ├── styles │ ├── fonts │ │ ├── other │ │ │ ├── Megrim.ttf │ │ │ └── LibreBarcode128Text-Regular.ttf │ │ ├── Montserrat-500.woff │ │ ├── Montserrat-600.woff │ │ ├── Montserrat-500.woff2 │ │ ├── Montserrat-600.woff2 │ │ ├── Montserrat-Light.woff │ │ └── Montserrat-Light.woff2 │ ├── components │ │ ├── appValidator │ │ │ └── _appValidator.scss │ │ ├── icons │ │ │ ├── _icons.scss │ │ │ └── _svgAnimations.scss │ │ ├── pagenotfound │ │ │ └── _pagenotfound.scss │ │ ├── inputs │ │ │ └── _inputs.scss │ │ ├── cookies │ │ │ └── _cookies.scss │ │ └── footer │ │ │ └── _footer.scss │ ├── global.scss │ └── core │ │ └── _fonts.scss ├── actions │ ├── tx.ts │ ├── panelChange.ts │ ├── approvedTokens.ts │ ├── tokenBalances.ts │ ├── modal.ts │ ├── ratioPairs.ts │ ├── auctions.ts │ ├── index.ts │ ├── ipfs.ts │ ├── tokenList.ts │ ├── tokenPair.ts │ └── tokenOverlay.ts ├── selectors │ ├── index.ts │ ├── auctions.ts │ ├── ratioPairs.ts │ └── tokens.ts ├── utils │ ├── prototypes.ts │ └── location.ts ├── html │ └── index.html ├── blocked_codes.json ├── middlewares │ ├── index.ts │ ├── CrashReporter.ts │ ├── NoScroll.ts │ ├── TokenTradableChecker.ts │ └── AppLoadBypass.ts ├── reducers │ ├── approvedTokens.ts │ ├── ratioPairs.ts │ ├── settings.ts │ ├── tokenBalances.ts │ ├── modal.ts │ ├── tokenOverlay.ts │ ├── auctions.ts │ ├── index.ts │ └── ipfs.ts ├── test │ └── utils │ │ ├── index.ts │ │ └── trufflescriptsUtils.js ├── containers │ ├── MGN │ │ └── index.ts │ ├── MenuFeeBalance │ │ └── index.ts │ ├── TopAuctions │ │ └── index.ts │ ├── NoWallet │ │ └── index.tsx │ ├── RedirectToDisclaimer │ │ └── index.ts │ ├── MenuAuctions │ │ └── index.ts │ ├── AuctionPriceBar │ │ └── index.ts │ ├── AuctionProgress │ │ └── index.ts │ ├── AuctionStatus │ │ └── index.ts │ ├── Home │ │ └── index.tsx │ ├── WalletPanel │ │ └── index.ts │ ├── AuctionAmountSummary │ │ └── index.ts │ ├── TokenUpload │ │ └── index.ts │ ├── AuctionWalletSummary │ │ └── index.ts │ ├── Disclaimer │ │ └── index.ts │ ├── TokenPicker │ │ └── index.ts │ ├── AuctionPanel │ │ └── index.ts │ ├── AuctionSellingGetting │ │ └── index.ts │ ├── OrderPanel │ │ └── index.ts │ ├── TokenOverlay │ │ └── index.ts │ ├── TokenPair │ │ └── index.ts │ └── MenuWallet │ │ └── index.ts ├── components │ ├── AuctionHeader │ │ └── index.tsx │ ├── AuctionContainer │ │ └── index.tsx │ ├── Imprint │ │ └── index.tsx │ ├── AuctionPriceBar │ │ └── index.tsx │ ├── AuctionWalletSummary │ │ └── index.tsx │ ├── Home │ │ └── index.tsx │ ├── ScrollToLink.tsx │ ├── TopAuctions │ │ └── index.tsx │ ├── MGN │ │ └── index.tsx │ ├── TokenOverlayHeader │ │ └── index.tsx │ ├── TokenList │ │ └── index.tsx │ ├── PageNotFound │ │ └── index.tsx │ ├── ButtonCTA │ │ └── index.tsx │ ├── AuctionAmountSummary │ │ └── index.tsx │ ├── GoogleAnalyticsTracking │ │ └── index.tsx │ ├── MenuFeeBalance │ │ └── index.tsx │ ├── App │ │ └── index.tsx │ ├── UserProviderConnection │ │ └── index.tsx │ ├── TextSquare │ │ └── index.tsx │ ├── AuctionProgress │ │ └── index.tsx │ ├── WalletPanel │ │ └── index.tsx │ ├── Loader │ │ └── index.tsx │ ├── Header │ │ └── index.tsx │ ├── RedirectIf │ │ └── index.tsx │ └── TokenPicker │ │ └── index.tsx ├── api │ ├── PriceOracle.ts │ ├── apiTesting.ts │ └── IPFS.ts ├── types │ └── global.d.ts ├── tokens │ └── token-lists │ │ ├── KOVAN │ │ └── prod-token-list.json │ │ └── RINKEBY │ │ └── dev-token-list.json ├── config.json └── store.ts ├── jsconfig.json ├── postcss.config.js ├── stories ├── helpers │ ├── index.ts │ ├── data.ts │ └── decorators.tsx ├── Hamburger.tsx ├── Home.tsx ├── Header.tsx ├── AuctionProgress.tsx ├── AuctionAmountSummary.tsx ├── TopAuctions.tsx ├── MenuWallet.tsx ├── ButtonCTA.tsx ├── AuctionPriceBar.tsx ├── Modals.tsx ├── AuctionWalletSummary.tsx ├── MenuAuction.tsx ├── TextSquare.tsx ├── NoWallet.tsx ├── AuctionHeader.tsx ├── AuctionFooter.tsx ├── AuctionStatus.tsx ├── TokenOverlay.tsx ├── AuctionSellingGetting.tsx ├── TokenPicker.tsx ├── TokenItem.tsx └── TokenPair.tsx ├── .storybook ├── addons.js ├── extraTypings.ts ├── config.js └── webpack.config.js ├── migrations ├── 1_initial_migration.js ├── 2_DEV_Migrate_Dependencies.js └── 3_DEV_Deploy_Tokens.js ├── contracts ├── DevDependenciesGetter.sol └── Migrations.sol ├── .gitattributes ├── .bootstraprc ├── test ├── contracts │ ├── TokenOMG.sol │ └── TokenRDN.sol ├── trufflescripts │ ├── snapshot.js │ ├── get_account_deposits.js │ ├── get_account_balances.js │ ├── revert.js │ ├── withdraw.js │ ├── give_tokens.js │ └── topup_accounts.js └── scripts │ └── add2ipfs.js ├── .babelrc ├── .gitignore ├── travis ├── prepare_production_deployment.sh └── deploy_pull_request.sh ├── .stylelintrc ├── tsconfig.json ├── tslint.json ├── LICENSE ├── ADD_TOKEN_REQUEST_TEMPLATE.md └── truffle-config.js /landing/assets/js/main.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | // # sourceMappingURL=main.js.map 4 | -------------------------------------------------------------------------------- /src/integrations/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './walletIntegration' 2 | -------------------------------------------------------------------------------- /src/assets/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnosis/dx-react/HEAD/src/assets/bg.jpg -------------------------------------------------------------------------------- /landing/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnosis/dx-react/HEAD/landing/favicon.png -------------------------------------------------------------------------------- /src/assets/dutchx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnosis/dx-react/HEAD/src/assets/dutchx.png -------------------------------------------------------------------------------- /src/public/google96dd53efdc540a07.html: -------------------------------------------------------------------------------- 1 | google-site-verification: google96dd53efdc540a07.html -------------------------------------------------------------------------------- /src/assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnosis/dx-react/HEAD/src/assets/favicon.png -------------------------------------------------------------------------------- /src/assets/tokens/1ST.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnosis/dx-react/HEAD/src/assets/tokens/1ST.png -------------------------------------------------------------------------------- /src/assets/pdf/PrivacyPolicy.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnosis/dx-react/HEAD/src/assets/pdf/PrivacyPolicy.pdf -------------------------------------------------------------------------------- /src/styles/fonts/other/Megrim.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnosis/dx-react/HEAD/src/styles/fonts/other/Megrim.ttf -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "experimentalDecorators": true, 4 | "baseUrl": "./src" 5 | } 6 | } -------------------------------------------------------------------------------- /src/styles/fonts/Montserrat-500.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnosis/dx-react/HEAD/src/styles/fonts/Montserrat-500.woff -------------------------------------------------------------------------------- /src/styles/fonts/Montserrat-600.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnosis/dx-react/HEAD/src/styles/fonts/Montserrat-600.woff -------------------------------------------------------------------------------- /src/assets/JauntyHarshIrishsetter.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnosis/dx-react/HEAD/src/assets/JauntyHarshIrishsetter.gif -------------------------------------------------------------------------------- /src/assets/img/gnosis_logo_favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnosis/dx-react/HEAD/src/assets/img/gnosis_logo_favicon.png -------------------------------------------------------------------------------- /src/assets/img/icons/icon_coinbase.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnosis/dx-react/HEAD/src/assets/img/icons/icon_coinbase.png -------------------------------------------------------------------------------- /src/styles/fonts/Montserrat-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnosis/dx-react/HEAD/src/styles/fonts/Montserrat-500.woff2 -------------------------------------------------------------------------------- /src/styles/fonts/Montserrat-600.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnosis/dx-react/HEAD/src/styles/fonts/Montserrat-600.woff2 -------------------------------------------------------------------------------- /src/styles/fonts/Montserrat-Light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnosis/dx-react/HEAD/src/styles/fonts/Montserrat-Light.woff -------------------------------------------------------------------------------- /landing/assets/fonts/SpaceMono-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnosis/dx-react/HEAD/landing/assets/fonts/SpaceMono-Bold.ttf -------------------------------------------------------------------------------- /landing/assets/fonts/SpaceMono-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnosis/dx-react/HEAD/landing/assets/fonts/SpaceMono-Bold.woff2 -------------------------------------------------------------------------------- /src/assets/brand/fonts/SpaceMono-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnosis/dx-react/HEAD/src/assets/brand/fonts/SpaceMono-Bold.ttf -------------------------------------------------------------------------------- /src/assets/content/dutchX_slowtrade.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnosis/dx-react/HEAD/src/assets/content/dutchX_slowtrade.png -------------------------------------------------------------------------------- /src/styles/fonts/Montserrat-Light.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnosis/dx-react/HEAD/src/styles/fonts/Montserrat-Light.woff2 -------------------------------------------------------------------------------- /landing/assets/fonts/SpaceMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnosis/dx-react/HEAD/landing/assets/fonts/SpaceMono-Regular.ttf -------------------------------------------------------------------------------- /src/actions/tx.ts: -------------------------------------------------------------------------------- 1 | import { createAction } from 'redux-actions' 2 | 3 | export const addTXReceipt = createAction<{}>('ADD_TX_RECEIPT') 4 | -------------------------------------------------------------------------------- /src/assets/brand/fonts/SpaceMono-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnosis/dx-react/HEAD/src/assets/brand/fonts/SpaceMono-Bold.woff2 -------------------------------------------------------------------------------- /landing/assets/fonts/SpaceMono-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnosis/dx-react/HEAD/landing/assets/fonts/SpaceMono-Regular.woff2 -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | // eslint-disable-next-line 4 | require('autoprefixer'), 5 | ], 6 | } 7 | -------------------------------------------------------------------------------- /src/assets/brand/fonts/SpaceMono-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnosis/dx-react/HEAD/src/assets/brand/fonts/SpaceMono-Regular.ttf -------------------------------------------------------------------------------- /src/assets/brand/fonts/SpaceMono-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnosis/dx-react/HEAD/src/assets/brand/fonts/SpaceMono-Regular.woff2 -------------------------------------------------------------------------------- /src/assets/content/LC_reduction_model_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnosis/dx-react/HEAD/src/assets/content/LC_reduction_model_bg.png -------------------------------------------------------------------------------- /stories/helpers/index.ts: -------------------------------------------------------------------------------- 1 | export * from './data' 2 | export * from './fn' 3 | export * from './mockStore' 4 | export * from './decorators' 5 | -------------------------------------------------------------------------------- /src/selectors/index.ts: -------------------------------------------------------------------------------- 1 | export * from './auctions' 2 | export * from './blockchain' 3 | export * from './ratioPairs' 4 | export * from './tokens' 5 | -------------------------------------------------------------------------------- /.storybook/addons.js: -------------------------------------------------------------------------------- 1 | import '@storybook/addon-knobs/register' 2 | import 'storybook-addon-jsx/register' 3 | import '@storybook/addon-actions/register' -------------------------------------------------------------------------------- /landing/assets/js/main.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["source.js"],"names":[],"mappings":"AAAA","file":"main.js","sourcesContent":["\"use strict\";"]} -------------------------------------------------------------------------------- /src/assets/content/step_by_step_fee_calculation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnosis/dx-react/HEAD/src/assets/content/step_by_step_fee_calculation.png -------------------------------------------------------------------------------- /migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | const Migrations = artifacts.require('./Migrations.sol') 2 | 3 | module.exports = deployer => deployer.deploy(Migrations) 4 | -------------------------------------------------------------------------------- /src/styles/fonts/other/LibreBarcode128Text-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnosis/dx-react/HEAD/src/styles/fonts/other/LibreBarcode128Text-Regular.ttf -------------------------------------------------------------------------------- /src/utils/prototypes.ts: -------------------------------------------------------------------------------- 1 | // set last () => any on Array prototype 2 | Array.prototype.__last = function getLast() { 3 | return this[this.length - 1] 4 | } 5 | -------------------------------------------------------------------------------- /.storybook/extraTypings.ts: -------------------------------------------------------------------------------- 1 | import '@storybook/react' 2 | 3 | declare module '@storybook/react' { 4 | export interface Story { 5 | addWithJSX: Story['add'] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/actions/panelChange.ts: -------------------------------------------------------------------------------- 1 | import { createAction } from 'redux-actions' 2 | 3 | // TODO: fill payload 4 | export const continueToOrder = createAction('CONTINUE_TO_ORDER', () => { }) 5 | -------------------------------------------------------------------------------- /src/actions/approvedTokens.ts: -------------------------------------------------------------------------------- 1 | import { createAction } from 'redux-actions' 2 | import { Account } from 'types' 3 | 4 | export const setApprovedTokens = createAction('SET_APPROVED_TOKENS') 5 | -------------------------------------------------------------------------------- /src/assets/alert.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /stories/helpers/data.ts: -------------------------------------------------------------------------------- 1 | export const tokenArr = [ 2 | 'GNO', 3 | 'ETH', 4 | '1ST', 5 | 'BIT', 6 | 'EQO', 7 | '666', 8 | 'COIN', 9 | 'YO', 10 | 'GHTO', 11 | 'POLKA', 12 | 'AUGR', 13 | ] 14 | -------------------------------------------------------------------------------- /src/actions/tokenBalances.ts: -------------------------------------------------------------------------------- 1 | import { createAction } from 'redux-actions' 2 | import { BigNumber } from 'types' 3 | 4 | export const setTokenBalance = createAction<{address: string, balance: BigNumber}>('SET_TOKEN_BALANCE') 5 | -------------------------------------------------------------------------------- /landing/assets/images/logo_2.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /landing/assets/images/logo_4.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/brand/images/logo_2.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/brand/images/logo_4.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /landing/assets/images/logo_1.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/actions/modal.ts: -------------------------------------------------------------------------------- 1 | import { createAction } from 'redux-actions' 2 | import { Modal } from 'types' 3 | 4 | export const openModal = createAction>('OPEN_MODAL') 5 | export const closeModal = createAction('CLOSE_MODAL', () => {}) 6 | -------------------------------------------------------------------------------- /src/actions/ratioPairs.ts: -------------------------------------------------------------------------------- 1 | import { createAction } from 'redux-actions' 2 | import { Balance, TokenCode } from 'types' 3 | 4 | export const setClosingPrice = createAction<{sell: TokenCode, buy: TokenCode, price: Balance}>('SET_CLOSING_PRICE') 5 | -------------------------------------------------------------------------------- /src/assets/brand/images/logo_1.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /landing/assets/images/logo_3.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/brand/images/logo_3.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/tokens/ETH.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /contracts/DevDependenciesGetter.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.2; 2 | 3 | import "@gnosis.pm/dx-contracts/contracts/DxDevDependencies.sol"; 4 | import "../test/contracts/TokenOMG.sol"; 5 | import "../test/contracts/TokenRDN.sol"; 6 | 7 | contract DevDependenciesGetter {} 8 | -------------------------------------------------------------------------------- /src/assets/arrowDownStep.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/arrowSidesRight.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/img/icons/icon_checkmark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/img/icons/icon_incomeForecast.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/actions/auctions.ts: -------------------------------------------------------------------------------- 1 | import { createAction } from 'redux-actions' 2 | import { OngoingAuctions } from 'types' 3 | 4 | export const setOngoingAuctions = createAction('SET_ONGOING_AUCTIONS') 5 | export const setAvailableAuctions = createAction('SET_AVAILABLE_AUCTIONS') 6 | -------------------------------------------------------------------------------- /src/selectors/auctions.ts: -------------------------------------------------------------------------------- 1 | import { createSelector } from 'reselect' 2 | import { State } from 'types' 3 | 4 | export const auctionClaimable = createSelector( 5 | (state: State) => state.auctions.ongoingAuctions, 6 | auctions => auctions && auctions.some((auc: any) => auc.claim || auc.claimInverse), 7 | ) 8 | -------------------------------------------------------------------------------- /src/assets/arrowPrev.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/copy.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/img/icons/icon_user.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Slow.trade | good trades take time 7 | 8 | 9 |
10 | 11 | 12 | -------------------------------------------------------------------------------- /src/blocked_codes.json: -------------------------------------------------------------------------------- 1 | [ 2 | "AE", 3 | "AF", 4 | "BA", 5 | "CD", 6 | "CF", 7 | "CN", 8 | "CU", 9 | "ER", 10 | "ET", 11 | "GW", 12 | "IQ", 13 | "IR", 14 | "KP", 15 | "LB", 16 | "LY", 17 | "RU", 18 | "SD", 19 | "SO", 20 | "SS", 21 | "SY", 22 | "UG", 23 | "US", 24 | "VU", 25 | "YE" 26 | ] -------------------------------------------------------------------------------- /src/middlewares/index.ts: -------------------------------------------------------------------------------- 1 | import CrashReporter from './CrashReporter' 2 | import NoScroll from './NoScroll' 3 | import AppLoadBypass from './AppLoadBypass' 4 | import TokenTradableChecker from './TokenTradableChecker' 5 | 6 | export { 7 | CrashReporter, 8 | NoScroll, 9 | AppLoadBypass, 10 | TokenTradableChecker, 11 | } 12 | -------------------------------------------------------------------------------- /src/assets/berliner.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/arrowSides.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/reducers/approvedTokens.ts: -------------------------------------------------------------------------------- 1 | import { setApprovedTokens } from 'actions' 2 | import { handleActions } from 'redux-actions' 3 | import { AccountsSet } from 'types' 4 | 5 | const reducer = handleActions( 6 | { 7 | [setApprovedTokens.toString()]: (_, action) => new Set(action.payload), 8 | }, 9 | new Set(), 10 | ) 11 | 12 | export default reducer 13 | -------------------------------------------------------------------------------- /src/test/utils/index.ts: -------------------------------------------------------------------------------- 1 | export const delay = (timeout = 20000) => new Promise((res) => { 2 | console.log(`start delay ${timeout / 1000} sec`) 3 | 4 | setTimeout(() => (console.log('end delay'), res()), timeout) 5 | }) 6 | 7 | export const metamaskWarning = (acc: string, addr: string) => 8 | console.log(`If testing with METAMASK you need to be on the ${acc} (${addr}) account`) 9 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text eol=lf 3 | 4 | # Denote all files that are truly binary and should not be modified. 5 | *.png binary 6 | *.gif binary 7 | *.jpg binary 8 | *.jpeg binary 9 | 10 | *.eot binary 11 | *.ttf binary 12 | *.otf binary 13 | *.woff binary 14 | *.woff2 binary 15 | *.pdf binary 16 | *.PDF binary 17 | -------------------------------------------------------------------------------- /src/reducers/ratioPairs.ts: -------------------------------------------------------------------------------- 1 | import { handleActions } from 'redux-actions' 2 | import { RatioPairs } from 'types' 3 | 4 | // import { setClosingPrice } from 'actions/ratioPairs' 5 | 6 | // TODO: fill in when we have actions 7 | export default handleActions( 8 | { 9 | // [setClosingPrice.toString()]: (state, action) => [...state, action.payload] as any, 10 | }, 11 | [], 12 | ) 13 | -------------------------------------------------------------------------------- /src/assets/img/icons/icon_cross.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/tokens/MKR.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.bootstraprc: -------------------------------------------------------------------------------- 1 | { 2 | "useFlexbox": true, 3 | 4 | "styles": true, 5 | 6 | "scripts": false, 7 | "bootstrapVersion": 3, 8 | "env": { 9 | "development": { 10 | "styleLoaders": ["style-loader", "css-loader", "sass-loader"] 11 | }, 12 | "production": { 13 | "extractStyles": true, 14 | "styleLoaders": ["style-loader", "css-loader?minimize", "sass-loader?sourceMap=false"] 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/reducers/settings.ts: -------------------------------------------------------------------------------- 1 | import { handleActions } from 'redux-actions' 2 | 3 | import { saveSettings } from 'actions/settings' 4 | import { Settings, CookieSettings } from 'types' 5 | 6 | const reducer = handleActions({ 7 | [saveSettings.toString()]: (state, action) => ({ 8 | ...state, 9 | ...action.payload, 10 | }), 11 | }, {} as Settings & CookieSettings) 12 | 13 | export default reducer 14 | -------------------------------------------------------------------------------- /src/actions/index.ts: -------------------------------------------------------------------------------- 1 | export * from './auctions' 2 | export * from './blockchain' 3 | export * from './ipfs' 4 | export * from './modal' 5 | export * from './panelChange' 6 | export * from './ratioPairs' 7 | export * from './tokenList' 8 | export * from './tokenBalances' 9 | export * from './tokenOverlay' 10 | export * from './tokenPair' 11 | export * from './modal' 12 | export * from './approvedTokens' 13 | export * from './settings' 14 | -------------------------------------------------------------------------------- /src/containers/MGN/index.ts: -------------------------------------------------------------------------------- 1 | import { connect } from 'react-redux' 2 | 3 | import { State } from 'types' 4 | 5 | import MGN from 'components/MGN' 6 | 7 | const mapState = ({ blockchain: { currentAccount , activeProvider, providers, network } }: State) => ({ 8 | currentAccount, 9 | network, 10 | now: providers[activeProvider] ? providers[activeProvider].timestamp : null, 11 | }) 12 | 13 | export default connect(mapState)(MGN) 14 | -------------------------------------------------------------------------------- /src/assets/tokens/TOKEN_LIST.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/img/icons/providerIcons.js: -------------------------------------------------------------------------------- 1 | export * from 'assets/img/icons/icon_gnosis_safe1.svg' 2 | export * from 'assets/img/icons/icon_ledger.svg' 3 | export * from 'assets/img/icons/icon_metamask.svg' 4 | export * from 'assets/img/icons/icon_metamask2.svg' 5 | export * from 'assets/img/icons/icon_metamask3.svg' 6 | export * from 'assets/img/icons/icon_status.svg' 7 | export * from 'assets/img/icons/icon_cross.svg' 8 | export * from 'assets/img/icons/icon_coinbase.png' 9 | -------------------------------------------------------------------------------- /src/assets/identicon-demo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/AuctionHeader/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Link } from 'react-router-dom' 3 | 4 | export interface AuctionHeaderProps { 5 | backTo?: string, 6 | } 7 | 8 | const AuctionHeader: React.SFC = ({ children, backTo }) => ( 9 |
10 |

{children}

11 | {backTo && } 12 |
13 | ) 14 | 15 | export default AuctionHeader 16 | -------------------------------------------------------------------------------- /test/contracts/TokenOMG.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.2; 2 | 3 | import "@gnosis.pm/util-contracts/contracts/GnosisStandardToken.sol"; 4 | 5 | contract TokenOMG is GnosisStandardToken { 6 | string public constant symbol = "OMG"; 7 | string public constant name = "Omisego Token"; 8 | uint8 public constant decimals = 18; 9 | 10 | constructor( 11 | uint amount 12 | ) 13 | public 14 | { 15 | balances[msg.sender] = amount; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test/contracts/TokenRDN.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.2; 2 | 3 | import "@gnosis.pm/util-contracts/contracts/GnosisStandardToken.sol"; 4 | 5 | contract TokenRDN is GnosisStandardToken { 6 | string public constant symbol = "RDN"; 7 | string public constant name = "Raiden Token"; 8 | uint8 public constant decimals = 18; 9 | 10 | constructor( 11 | uint amount 12 | ) 13 | public 14 | { 15 | balances[msg.sender] = amount; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/assets/img/icons/icon_status.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /stories/Hamburger.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { storiesOf } from '@storybook/react' 4 | import { makeTopDecorator } from './helpers' 5 | 6 | const TopRightDecorator = makeTopDecorator({ 7 | style: { 8 | justifyContent: 'flex-end', 9 | }, 10 | }) 11 | 12 | import Hamburger from 'components/Hamburger' 13 | 14 | storiesOf('Hamburger', module) 15 | .addDecorator(TopRightDecorator) 16 | .addWithJSX('Hamburger Component', () => 17 | , 18 | ) 19 | -------------------------------------------------------------------------------- /migrations/2_DEV_Migrate_Dependencies.js: -------------------------------------------------------------------------------- 1 | /* global artifacts */ 2 | /* eslint no-undef: "error" */ 3 | 4 | const migrateDx = require('@gnosis.pm/dx-contracts/src/migrations-truffle-5') 5 | 6 | module.exports = (deployer, network, accounts) => migrateDx({ 7 | artifacts, 8 | deployer, 9 | network, 10 | accounts, 11 | web3, 12 | thresholdNewTokenPairUsd: process.env.THRESHOLD_NEW_TOKEN_PAIR_USD, 13 | thresholdAuctionStartUsd: process.env.THRESHOLD_AUCTION_START_USD, 14 | }) 15 | -------------------------------------------------------------------------------- /src/components/AuctionContainer/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | export interface AuctionContainerProps { 4 | auctionDataScreen: string, 5 | } 6 | 7 | export const AuctionContainer: React.SFC = ({ auctionDataScreen = 'details', children }) => 8 |
9 |
10 | {children} 11 |
12 |
13 | 14 | export default AuctionContainer 15 | -------------------------------------------------------------------------------- /src/containers/MenuFeeBalance/index.ts: -------------------------------------------------------------------------------- 1 | import { connect } from 'react-redux' 2 | 3 | import MenuFeeBalance from 'components/MenuFeeBalance' 4 | 5 | import { State } from 'types' 6 | 7 | const mapState = ({ blockchain: { currentAccount, feeRatio, mgnSupply } }: State) => ({ 8 | feeRatio, 9 | mgnSupply, 10 | showFeeRatio: currentAccount && mgnSupply && (typeof feeRatio === 'number' && feeRatio.toString() !== 'NaN'), 11 | }) 12 | 13 | export default connect(mapState)(MenuFeeBalance) 14 | -------------------------------------------------------------------------------- /src/containers/TopAuctions/index.ts: -------------------------------------------------------------------------------- 1 | import { connect } from 'react-redux' 2 | import TopAuctions from 'components/TopAuctions' 3 | import { selectTokenPairAndSetClosingPrice } from 'actions' 4 | import { State } from 'types' 5 | import { selectTop5Pairs } from 'selectors/ratioPairs' 6 | 7 | const mapStateToProps = (state: State) => ({ 8 | pairs: selectTop5Pairs(state), 9 | }) 10 | 11 | export default connect(mapStateToProps, { selectTokenPairAndSetClosingPrice })(TopAuctions as any) 12 | -------------------------------------------------------------------------------- /src/reducers/tokenBalances.ts: -------------------------------------------------------------------------------- 1 | import { handleActions } from 'redux-actions' 2 | import { TokenBalances } from 'types' 3 | 4 | import { setTokenBalance, resetAppState } from 'actions' 5 | 6 | export default handleActions( 7 | { 8 | [setTokenBalance.toString()]: (state: any, action: any) => ({ 9 | ...state, 10 | [action.payload.address]: action.payload.balance, 11 | }), 12 | [resetAppState.toString()]: () => ({}), 13 | }, 14 | // zeroBalance 15 | {}, 16 | ) 17 | -------------------------------------------------------------------------------- /src/assets/tokens/index.ts: -------------------------------------------------------------------------------- 1 | const allSVGs = { 2 | DEFAULT_TOKEN: require('./DEFAULT_TOKEN.svg'), 3 | ETH: require('./ETH.svg'), 4 | WETH: require('./WETH.svg'), 5 | 6 | DAI: require('./DAI.svg'), 7 | GEN: require('./GEN.svg'), 8 | GNO: require('./GNO.svg'), 9 | GNT: require('./GNT.svg'), 10 | KNC: require('./KNC.svg'), 11 | MKR: require('./MKR.svg'), 12 | OMG: require('./OMG.svg'), 13 | RDN: require('./RDN.svg'), 14 | REP: require('./REP.svg'), 15 | } 16 | 17 | export default allSVGs 18 | -------------------------------------------------------------------------------- /test/trufflescripts/snapshot.js: -------------------------------------------------------------------------------- 1 | /* eslint no-console:0 */ 2 | const { makeSnapshot } = require('./utils')(web3) 3 | 4 | /** 5 | * truffle exec test/trufflescripts/snapshot.js 6 | * Created snapshot of blockchain state and assigns a Block-ID 7 | * Block-ID can be reverted back to via revert.js 8 | */ 9 | 10 | module.exports = () => { 11 | const snapshot = makeSnapshot() 12 | console.log(` 13 | SNAPSHOT CREATED: # ${snapshot} 14 | BLOCK-NUMBER: ${web3.eth.blockNumber} 15 | `) 16 | } 17 | -------------------------------------------------------------------------------- /stories/Home.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { storiesOf } from '@storybook/react' 4 | import StoryRouter from 'storybook-router' 5 | import { storeInit, bcMetamask, makeProviderDecorator } from './helpers' 6 | 7 | const store = storeInit(bcMetamask) 8 | 9 | const ProviderDecor = makeProviderDecorator(store) 10 | 11 | import Home from 'containers/Home' 12 | 13 | storiesOf('Home', module) 14 | .addDecorator(StoryRouter()) 15 | .addDecorator(ProviderDecor) 16 | .add('Home', () => ) 17 | -------------------------------------------------------------------------------- /stories/Header.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { storiesOf } from '@storybook/react' 4 | import StoryRouter from 'storybook-router' 5 | import { storeInit, bcMetamask, makeProviderDecorator } from './helpers' 6 | 7 | const store = storeInit(bcMetamask) 8 | 9 | const ProviderDecor = makeProviderDecorator(store) 10 | 11 | import Header from 'components/Header' 12 | 13 | storiesOf('Header [v2]', module) 14 | .addDecorator(StoryRouter()) 15 | .addDecorator(ProviderDecor) 16 | .add('Header', () =>
) 17 | -------------------------------------------------------------------------------- /src/middlewares/CrashReporter.ts: -------------------------------------------------------------------------------- 1 | import { Middleware } from 'redux' 2 | import { push } from 'connected-react-router' 3 | // import { State } from 'types' 4 | 5 | /** 6 | * Sends crash reports as state is updated and listeners are notified. 7 | */ 8 | const CrashReporter: Middleware = () => next => (action: any) => { 9 | try { 10 | return next(action) 11 | } catch (err) { 12 | console.error('Caught an exception!', err) 13 | next(push('/')) 14 | throw err 15 | } 16 | } 17 | 18 | export default CrashReporter 19 | -------------------------------------------------------------------------------- /src/assets/ok.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/containers/NoWallet/index.tsx: -------------------------------------------------------------------------------- 1 | import { connect } from 'react-redux' 2 | import { State } from 'types' 3 | import { getSelectedProvider, getAccount } from 'selectors/blockchain' 4 | 5 | import NoWallet from 'components/NoWallet' 6 | 7 | const mapStateToProps = (state: State) => { 8 | const selectedProvider = getSelectedProvider(state) 9 | return { 10 | walletUnavailable: !(selectedProvider && selectedProvider.available), 11 | walletLocked: !getAccount(state), 12 | } 13 | } 14 | 15 | export default connect(mapStateToProps)(NoWallet) 16 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["@babel/preset-env", { "modules": false }], 4 | "@babel/preset-react" 5 | ], 6 | "plugins": [ 7 | "react-hot-loader/babel", 8 | "@babel/plugin-proposal-object-rest-spread", 9 | ["@babel/plugin-proposal-class-properties", { "loose": true }], 10 | ["@babel/transform-runtime", 11 | { 12 | "regenerator": true 13 | } 14 | ] 15 | ], 16 | "env": { 17 | "production": { 18 | "plugins": [["transform-remove-console", { "exclude": [ "error", "warn"] }]] 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /src/api/PriceOracle.ts: -------------------------------------------------------------------------------- 1 | import { promisedContractsMap } from './contracts' 2 | import { PriceOracle } from './types' 3 | 4 | let priceOracle: PriceOracle 5 | 6 | export const promisedPriceOracle = async () => priceOracle || (priceOracle = await init()) 7 | 8 | async function init(): Promise { 9 | const { PriceOracleInterface: po } = await promisedContractsMap() 10 | 11 | const getUSDETHPrice = () => po.getUSDETHPrice.call() 12 | 13 | return { 14 | get address() { 15 | return po.address 16 | }, 17 | getUSDETHPrice, 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/assets/tokens/DAI.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/containers/RedirectToDisclaimer/index.ts: -------------------------------------------------------------------------------- 1 | import { connect } from 'react-redux' 2 | import { State } from 'types' 3 | 4 | import { RedirectToDisclaimer, RedirectToDisclaimerProps } from 'components/RedirectIf' 5 | import { withRouter } from 'react-router' 6 | import { ComponentClass } from 'react' 7 | 8 | const mapStateToProps = ({ settings }: State) => ({ 9 | disclaimer_accepted: settings.disclaimer_accepted || false, 10 | }) 11 | 12 | export default withRouter(connect>(mapStateToProps, null)(RedirectToDisclaimer) as ComponentClass) 13 | -------------------------------------------------------------------------------- /src/actions/ipfs.ts: -------------------------------------------------------------------------------- 1 | import { createAction } from 'redux-actions' 2 | import { DefaultTokenObject } from 'types' 3 | 4 | export const setUploadFileParams: Function = createAction<{ oFile: File, fileBuffer: ArrayBuffer, json: DefaultTokenObject[] }>('SET_UPLOAD_FILE_PARAMS') 5 | export const setIPFSFileHash: Function = createAction('SET_IPFS_FILE_HASH') 6 | export const setIPFSFileHashAndPath: Function = createAction<{ fileHash: string, filePath: string }>('SET_IPFS_FILE_HASH_AND_PATH') 7 | export const getFileContentFromIPFS: Function = createAction<{ fileContent: string }>('GET_FILE_CONTENT_FROM_IPFS') 8 | -------------------------------------------------------------------------------- /.storybook/config.js: -------------------------------------------------------------------------------- 1 | import { addDecorator, configure, setAddon } from '@storybook/react' 2 | import { withKnobs } from '@storybook/addon-knobs' 3 | import JSXAddon from 'storybook-addon-jsx' 4 | 5 | import '../src/styles/global.scss' 6 | 7 | window.regeneratorRuntime = require('babel-runtime/regenerator') 8 | require('./extraTypings.ts') 9 | 10 | const req = require.context('../stories', false, /\.tsx$/) 11 | 12 | addDecorator(withKnobs) 13 | setAddon(JSXAddon) 14 | 15 | function loadStories() { 16 | req.keys().forEach((filename) => req(filename)) 17 | } 18 | 19 | configure(loadStories, module) 20 | -------------------------------------------------------------------------------- /contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.2; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | modifier restricted() { 8 | if (msg.sender == owner) _; 9 | } 10 | 11 | constructor () public { 12 | owner = msg.sender; 13 | } 14 | 15 | function setCompleted(uint completed) public restricted { 16 | last_completed_migration = completed; 17 | } 18 | 19 | function upgrade(address new_address) public restricted { 20 | Migrations upgraded = Migrations(new_address); 21 | upgraded.setCompleted(last_completed_migration); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/containers/MenuAuctions/index.ts: -------------------------------------------------------------------------------- 1 | import { connect } from 'react-redux' 2 | import { push } from 'connected-react-router' 3 | 4 | import { State } from 'types' 5 | 6 | import MenuAuctions from 'components/MenuAuctions' 7 | import { claimAndWithdrawSellerFundsFromSeveral } from 'actions' 8 | 9 | import { auctionClaimable } from 'selectors' 10 | 11 | const mapStateToProps = (state: State) => ({ 12 | ongoingAuctions: state.auctions.ongoingAuctions, 13 | claimable: auctionClaimable(state), 14 | }) 15 | 16 | export default connect(mapStateToProps, { claimAndWithdrawSellerFundsFromSeveral, push })(MenuAuctions as any) 17 | -------------------------------------------------------------------------------- /src/assets/tokens/CVC.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /migrations/3_DEV_Deploy_Tokens.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | const TokenOMG = artifacts.require('TokenOMG') 3 | const TokenRDN = artifacts.require('TokenRDN') 4 | 5 | module.exports = (deployer, network) => { 6 | let toBN 7 | if (typeof web3.version === 'string') { 8 | // 1.X.xx Web3 9 | ({ toBN } = web3.utils) 10 | } else { 11 | toBN = web3.toBigNumber 12 | } 13 | if (network === 'development') return deployer.deploy(TokenOMG, toBN(50000).mul(toBN(10).pow(toBN(18)))).then(() => deployer.deploy(TokenRDN, toBN(50000).mul(toBN(10).pow(toBN(18))))) 14 | 15 | return console.log('Not running on development, skipping.') 16 | } 17 | -------------------------------------------------------------------------------- /src/assets/img/icons/icon_metamask.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .DS_STORE 3 | node_modules 4 | *~ 5 | *.pyc 6 | static 7 | .grunt 8 | _SpecRunner.html 9 | __benchmarks__ 10 | dist/ 11 | build/ 12 | coverage/ 13 | .module-cache 14 | *.gem 15 | docs/.bundle 16 | docs/code 17 | docs/_site 18 | docs/.sass-cache 19 | docs/js/* 20 | docs/downloads/*.zip 21 | docs/vendor/bundle 22 | examples/shared/*.js 23 | examples/**/bundle.js 24 | test/the-files-to-test.generated.js 25 | *.log* 26 | chrome-user-data 27 | *.sublime-project 28 | *.sublime-workspace 29 | .idea 30 | *.iml 31 | .vscode 32 | /semantic.json 33 | /semantic 34 | yarn-error.log 35 | 36 | records.json 37 | stats.json 38 | .awcache 39 | .eslintcache 40 | .stylelintcache 41 | .history 42 | -------------------------------------------------------------------------------- /src/assets/img/icons/icon_currency.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/img/icons/icon_countdown.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/img/icons/icon_enddate.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/reducers/modal.ts: -------------------------------------------------------------------------------- 1 | import { openModal, closeModal } from 'actions/modal' 2 | import { handleActions } from 'redux-actions' 3 | import { Modal } from 'types' 4 | 5 | const initialState: Modal = { 6 | isOpen: false, 7 | modalName: undefined, 8 | modalProps: undefined, 9 | } 10 | 11 | const reducer = handleActions( 12 | { 13 | [openModal.toString()]: (state, action) => { 14 | const { modalName, modalProps } = action.payload 15 | 16 | return { 17 | ...state, 18 | modalName, 19 | modalProps, 20 | isOpen: true, 21 | } 22 | }, 23 | [closeModal.toString()]: () => initialState, 24 | }, 25 | initialState, 26 | ) 27 | 28 | export default reducer 29 | -------------------------------------------------------------------------------- /src/containers/AuctionPriceBar/index.ts: -------------------------------------------------------------------------------- 1 | import { connect } from 'react-redux' 2 | 3 | import { State } from 'types' 4 | 5 | import AuctionPriceBar from 'components/AuctionPriceBar' 6 | import { EMPTY_TOKEN } from 'tokens' 7 | 8 | // TODO: create state for lastAuctionPrice for each token 9 | const mapState = (state: State) => { 10 | // TODO: change price acquisition 11 | const { buy = EMPTY_TOKEN, sell = EMPTY_TOKEN, lastPrice: price } = state.tokenPair 12 | 13 | return { 14 | sellTokenSymbol: sell.symbol || sell.name || sell.address, 15 | sellTokenPrice: price, 16 | buyTokenSymbol: buy.symbol || buy.name || buy.address, 17 | } 18 | } 19 | 20 | export default connect(mapState)(AuctionPriceBar) 21 | -------------------------------------------------------------------------------- /src/containers/AuctionProgress/index.ts: -------------------------------------------------------------------------------- 1 | import { connect } from 'react-redux' 2 | import AuctionProgress from 'components/AuctionProgress' 3 | // import { State } from 'types' 4 | import { AuctionStatus as Status } from 'globals' 5 | 6 | const status2progress = { 7 | [Status.INIT]: 1, 8 | [Status.PLANNED]: 2, 9 | [Status.ACTIVE]: 3, 10 | [Status.ENDED]: 4, 11 | } 12 | 13 | const getAuctionProgress = (status: Status) => status2progress[status] || 0 14 | 15 | const mapStateToProps = () => ({ 16 | // TODO: populate AuctionStatus in store by querying DutchX regularly or listening for Events 17 | progress: getAuctionProgress(Status.INIT), 18 | }) 19 | 20 | export default connect(mapStateToProps)(AuctionProgress) 21 | -------------------------------------------------------------------------------- /travis/prepare_production_deployment.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ev 4 | 5 | # Only: 6 | # - Tagged commits 7 | # - Security env variables are available. 8 | if [ -n "$TRAVIS_TAG" ] && [ -n "$PROD_DEPLOYMENT_HOOK_TOKEN" ] && [ -n "$PROD_DEPLOYMENT_HOOK_URL_DOMAIN" ] && [ -n "$PROD_DEPLOYMENT_HOOK_ID" ] 9 | then 10 | curl --silent --output /dev/null --write-out "%{http_code}" -X POST \ 11 | -F token="$PROD_DEPLOYMENT_HOOK_TOKEN" \ 12 | -F ref=master \ 13 | -F "variables[TRIGGER_RELEASE_COMMIT_TAG]=$TRAVIS_TAG" \ 14 | https://"$PROD_DEPLOYMENT_HOOK_URL_DOMAIN"/api/v4/projects/$PROD_DEPLOYMENT_HOOK_ID/trigger/pipeline 15 | else 16 | echo "[ERROR] Production deployment could not be prepared" 17 | fi 18 | -------------------------------------------------------------------------------- /src/containers/AuctionStatus/index.ts: -------------------------------------------------------------------------------- 1 | import { connect } from 'react-redux' 2 | import AuctionStatus from 'components/AuctionStatus' 3 | 4 | import { toBigNumber } from 'web3/lib/utils/utils.js' 5 | 6 | import { State } from 'types' 7 | import { AuctionStatus as Status } from 'globals' 8 | 9 | const mapStateToProps = ({ tokenPair: { sell, buy } }: State) => ({ 10 | sellToken: sell, 11 | buyToken: buy, 12 | // TODO: get buyAmount based on what can be claimed, i.e. at the end of auction 13 | buyAmount: toBigNumber(2.5520300), 14 | // TODO: make sure time and status are populated in the store by DutchX 15 | timeLeft: 73414, 16 | status: Status.INIT, 17 | }) 18 | 19 | export default connect(mapStateToProps)(AuctionStatus) 20 | -------------------------------------------------------------------------------- /src/containers/Home/index.tsx: -------------------------------------------------------------------------------- 1 | import { connect } from 'react-redux' 2 | import { getActiveProvider, getSelectedProvider, getAccount } from 'selectors/blockchain' 3 | import { supportedProviders } from 'globals' 4 | 5 | import { State } from 'types' 6 | 7 | import Home from 'components/Home' 8 | 9 | const mapStateToProps = (state: State) => { 10 | const activeProvider = getActiveProvider(state) 11 | const selectedProvider = getSelectedProvider(state) 12 | return { 13 | walletEnabled: supportedProviders.has(activeProvider) 14 | && selectedProvider && (selectedProvider.available || selectedProvider.keyName === 'LEDGER') 15 | && !!getAccount(state), 16 | } 17 | } 18 | 19 | export default connect(mapStateToProps)(Home) 20 | -------------------------------------------------------------------------------- /src/assets/img/icons/icon_etherTokens.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/Imprint/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const Imprint = ({ noTitle, cssClass = 'disclaimer' }: { noTitle?: boolean, cssClass?: string }) => 4 |
5 |
6 | {!noTitle &&

IMPRINT

} 7 |

8 | d.ex OÜ

9 | Ahtri 12,
10 | Tallinn 10151
11 | Estonia 12 |

13 |

14 | E-Mail: info@slow.trade 15 |

16 |

17 | Company registration No. 14553524 18 |

19 | 20 |
21 |
22 | 23 | export default Imprint 24 | -------------------------------------------------------------------------------- /src/assets/tokens/SNT.svg: -------------------------------------------------------------------------------- 1 | Artboard 2 copy 9 -------------------------------------------------------------------------------- /src/utils/location.ts: -------------------------------------------------------------------------------- 1 | import { URLS } from 'globals' 2 | 3 | const MAIN_RINKEBY_URL = 'https://slow.trade/rinkeby' 4 | 5 | const locationListener = (history: any) => { 6 | if (typeof window === 'undefined') return 7 | 8 | // history listen on change 9 | if (window.location.hostname !== URLS.APP_URLS_PROD.MAIN[0]) { 10 | history.listen((loc: any) => { 11 | const searchParams = new URLSearchParams(loc.search) 12 | searchParams.has('retro-x') && document.body.classList.add('THEME') 13 | }) 14 | } 15 | // fix slow.trade/rinkeby && rinkeby#/ issue 16 | if (window.location.href.startsWith(MAIN_RINKEBY_URL)) { 17 | window.location.replace(`https://${URLS.APP_URLS_PROD.RINKEBY[0]}`) 18 | } 19 | } 20 | 21 | export default locationListener 22 | -------------------------------------------------------------------------------- /src/components/AuctionPriceBar/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { Balance } from 'types' 4 | 5 | export interface AuctionPriceBarProps { 6 | buyTokenSymbol: string, 7 | header: string, 8 | sellTokenSymbol: string, 9 | sellTokenPrice: Balance, 10 | } 11 | 12 | const AuctionPriceBar: React.SFC = ({ sellTokenSymbol, sellTokenPrice, buyTokenSymbol, header }) => { 13 | if (!sellTokenSymbol || !buyTokenSymbol) return null 14 | 15 | return ( 16 |
17 | {`${header} of last auction:`} 18 | {sellTokenSymbol && buyTokenSymbol && {`1 ${sellTokenSymbol} = ${sellTokenPrice} ${buyTokenSymbol}`}} 19 |
20 | ) 21 | } 22 | 23 | export default AuctionPriceBar 24 | -------------------------------------------------------------------------------- /.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "stylelint-config-standard", 3 | "rules": { 4 | "selector-list-comma-newline-after": null, 5 | "function-comma-space-after": null, 6 | "number-leading-zero": null, 7 | "declaration-empty-line-before": ["always", { 8 | except: [ 9 | "first-nested" 10 | ], 11 | ignore: [ 12 | "after-comment", 13 | "inside-single-line-block", 14 | "after-declaration" 15 | ], 16 | }], 17 | "at-rule-no-unknown": [true, { 18 | "ignoreAtRules": ["function", "return", "if", "else", "for", "each", "mixin", "while", "include", "extend", "at-root"] 19 | }], 20 | "declaration-block-no-redundant-longhand-properties": [true, { 21 | "ignoreShorthands": ["/grid/"] 22 | }] 23 | } 24 | } -------------------------------------------------------------------------------- /src/components/AuctionWalletSummary/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | // TODO: get types from global types/ 4 | export interface AuctionWalletSummaryProps { 5 | address: string, 6 | provider: string, 7 | network: string, 8 | connected: boolean 9 | } 10 | 11 | const AuctionWalletSummary: React.SFC = ({ address, provider, network, connected }) => ( 12 |
13 | 14 | Connected Wallet 15 | {provider} 16 | {network} 17 | 18 | 19 | 20 | YOUR WALLET ADDRESS 21 | {address} 22 | 23 |
24 | ) 25 | 26 | export default AuctionWalletSummary 27 | -------------------------------------------------------------------------------- /src/assets/img/icons/icon_market.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/containers/WalletPanel/index.ts: -------------------------------------------------------------------------------- 1 | import WalletPanel from 'components/WalletPanel' 2 | 3 | import { SyntheticEvent } from 'react' 4 | import { connect } from 'react-redux' 5 | 6 | import { checkUserStateAndSell, openModal } from 'actions' 7 | import { getProviderName } from 'selectors' 8 | 9 | import { RedirectHomeHOC } from 'components/RedirectIf' 10 | 11 | import { State } from 'types' 12 | 13 | const mapState = (state: State) => { 14 | const activeProvider = getProviderName(state) 15 | return ({ 16 | activeProvider, 17 | sellAmount: state.tokenPair.sellAmount, 18 | }) 19 | } 20 | 21 | export default connect( 22 | mapState, 23 | { checkUserStateAndSell: (e: SyntheticEvent) => (e.preventDefault(), checkUserStateAndSell()), openModal }, 24 | )(RedirectHomeHOC(WalletPanel)) 25 | -------------------------------------------------------------------------------- /src/components/Home/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import NoWallet from 'containers/NoWallet' 4 | import TextSquare from 'components/TextSquare' 5 | import TokenPicker from 'containers/TokenPicker' 6 | import { ClaimOnly } from 'components/NoWallet' 7 | 8 | export interface HomeProps { 9 | walletEnabled: boolean, 10 | showPicker?: boolean, 11 | needsTokens?: boolean, 12 | claimOnly?: boolean, 13 | } 14 | 15 | const Home: React.SFC = ({ claimOnly, walletEnabled, showPicker }) => 16 |
17 | 18 | { 19 | !walletEnabled ? 20 | : 21 | claimOnly ? 22 | : 23 | 24 | } 25 |
26 | 27 | export default Home 28 | -------------------------------------------------------------------------------- /src/assets/tokens/REQ.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/types/global.d.ts: -------------------------------------------------------------------------------- 1 | interface Window { 2 | __REDUX_DEVTOOLS_EXTENSION_COMPOSE__: any, 3 | TextDecoder: any, 4 | ethereum: any, 5 | mist: any, 6 | web3: any, 7 | } 8 | 9 | declare module 'ipfs' 10 | declare module 'storybook-router' 11 | declare module 'truffle-contract' 12 | declare module 'web3' 13 | declare module 'web3/lib/utils/utils.js' 14 | declare module 'ethjs-abi' 15 | 16 | declare module '*.svg' { 17 | const content: any 18 | export default content 19 | } 20 | 21 | declare module '*.png' { 22 | const content: any 23 | export default content 24 | } 25 | 26 | declare module '*.json' { 27 | const content: any 28 | export default content 29 | } 30 | 31 | declare const before: typeof beforeAll 32 | declare const after: typeof afterAll 33 | 34 | declare interface Array { 35 | __last: () => T; 36 | } 37 | -------------------------------------------------------------------------------- /src/assets/img/icons/icon_achievementBadge.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/settings.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /stories/AuctionProgress.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { storiesOf } from '@storybook/react' 4 | import { number } from '@storybook/addon-knobs' 5 | import { makeCenterDecorator } from './helpers' 6 | 7 | import AuctionProgress from 'components/AuctionProgress' 8 | 9 | const CenterDecor = makeCenterDecorator({ 10 | style: { 11 | backgroundColor: null, 12 | width: null, 13 | height: null, 14 | padding: '130px 0 75px', 15 | }, 16 | className: 'auctionContainer', 17 | }) 18 | 19 | const range = () => number('progress', 2, { 20 | range: true, 21 | min: 0, 22 | max: 4, 23 | step: 1, 24 | }) 25 | 26 | storiesOf('AuctionProgress', module) 27 | .addDecorator(CenterDecor) 28 | .addWithJSX('ongoing auction', () => ( 29 | 30 | )) 31 | -------------------------------------------------------------------------------- /src/components/ScrollToLink.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { Link, LinkProps } from 'react-router-dom' 4 | 5 | interface ScrollToLinkProps extends LinkProps { 6 | hash: string, 7 | } 8 | 9 | export default class ScrollToLink extends React.Component { 10 | 11 | handleScrollToHash = (e: any) => { 12 | e.preventDefault() 13 | 14 | const { children, hash, to } = this.props 15 | if (hash) { 16 | const elem = document.querySelector(hash) 17 | if (elem) elem.scrollIntoView() 18 | } 19 | return ({children}) 20 | } 21 | 22 | render() { 23 | const { children, hash, to } = this.props 24 | if (hash) return {children} 25 | 26 | return {children} 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/styles/components/appValidator/_appValidator.scss: -------------------------------------------------------------------------------- 1 | .offlineBanner, .geoBlockBanner { 2 | position: relative; 3 | background: $yellow; 4 | color: $red; 5 | line-height: initial; 6 | text-align: center; 7 | width: 100%; 8 | font-size: 1.4em; 9 | font-weight: $normal; 10 | padding: 20px 10px; 11 | border-bottom: 1px solid #dce0e4; 12 | 13 | > span { 14 | color: inherit; 15 | font-size: inherit; 16 | } 17 | 18 | > span::before { 19 | content: ""; 20 | background: url('#{$images}alert.svg') no-repeat center/contain; 21 | width: 17px; 22 | height: 15px; 23 | display: inline-block; 24 | margin: -3px 6px 0 0; 25 | vertical-align: middle; 26 | } 27 | 28 | @media #{$mobile} { 29 | position: relative; 30 | // top: 136px; 31 | font-size: 16px; 32 | z-index: 88; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/styles/components/icons/_icons.scss: -------------------------------------------------------------------------------- 1 | .icon { 2 | height: 20px; 3 | width: 20px; 4 | display: inline-block; 5 | margin: 0 0 0 5px; 6 | } 7 | 8 | [data-icon="ok"]::before { 9 | content: " "; 10 | display: inline-block; 11 | margin: -2px 4px 0 0; 12 | vertical-align: middle; 13 | height: 14px; 14 | width: 14px; 15 | background: url('#{$images}ok.svg') no-repeat center / contain; 16 | } 17 | 18 | .icon-walletUnlock { 19 | background: url('#{$images}wallet-unlock.svg') no-repeat center / contain; 20 | } 21 | 22 | .icon-walletOK { 23 | background: url('#{$images}wallet-ok.svg') no-repeat center / contain; 24 | } 25 | 26 | .icon-arrowDown { 27 | background: url('#{$images}arrowDown.svg') no-repeat center / contain; 28 | } 29 | 30 | .icon-tokenUpload { 31 | background: url('#{$images}tokenUpload.svg') no-repeat center / contain; 32 | } 33 | -------------------------------------------------------------------------------- /stories/AuctionAmountSummary.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { storiesOf } from '@storybook/react' 4 | import { text, number } from '@storybook/addon-knobs' 5 | 6 | import AuctionAmountSummary from 'components/AuctionAmountSummary' 7 | 8 | import { makeCenterDecorator } from './helpers' 9 | 10 | const CenterDecor = makeCenterDecorator({ 11 | style: { 12 | height: null, 13 | padding: '60px 0', 14 | }, 15 | }) 16 | 17 | storiesOf('AuctionAmountSummary', module) 18 | .addDecorator(CenterDecor) 19 | .addWithJSX('PANEL 3', () => ( 20 | 26 | )) 27 | -------------------------------------------------------------------------------- /src/containers/AuctionAmountSummary/index.ts: -------------------------------------------------------------------------------- 1 | import { connect } from 'react-redux' 2 | 3 | import { State } from 'types' 4 | import AuctionAmountSummary from 'components/AuctionAmountSummary' 5 | import { FIXED_DECIMALS } from 'globals' 6 | 7 | const mapState = (state: State) => { 8 | // TODO: always have some price for every pair in RatioPairs 9 | const { sell, buy, lastPrice: price } = state.tokenPair 10 | const { sellAmount } = state.tokenPair 11 | return ({ 12 | // TODO: change prop to sellTokenBalance 13 | sellTokenSymbol: sell.symbol || sell.name || sell.address, 14 | buyTokenSymbol: buy.symbol || buy.name || buy.address, 15 | sellTokenAmount: sellAmount, 16 | // TODO: use BN.mult() inside component 17 | buyTokenAmount: (+price * +sellAmount).toFixed(FIXED_DECIMALS), 18 | }) 19 | } 20 | 21 | export default connect(mapState)(AuctionAmountSummary) 22 | -------------------------------------------------------------------------------- /src/reducers/tokenOverlay.ts: -------------------------------------------------------------------------------- 1 | import { handleActions } from 'redux-actions' 2 | 3 | import { 4 | closeOverlay, 5 | openOverlay, 6 | selectTokenAndCloseOverlay, 7 | resetTokenPairAndCloseOverlay, 8 | } from 'actions' 9 | import { TokenOverlay } from 'types' 10 | 11 | const closeOverlayReducer = (state: TokenOverlay): TokenOverlay => ({ 12 | ...state, 13 | open: false, 14 | mod: null, 15 | }) 16 | 17 | export default handleActions( 18 | { 19 | [openOverlay.toString()]: (state, action) => ({ 20 | ...state, 21 | open: true, 22 | mod: action.payload.mod, 23 | }), 24 | [closeOverlay.toString()]: closeOverlayReducer, 25 | [selectTokenAndCloseOverlay.toString()]: closeOverlayReducer, 26 | [resetTokenPairAndCloseOverlay.toString()]: closeOverlayReducer, 27 | }, 28 | { 29 | open: false, 30 | mod: null, 31 | }, 32 | ) 33 | -------------------------------------------------------------------------------- /src/components/TopAuctions/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { RatioPairs, TokenPair } from 'types' 3 | 4 | export interface TopAuctionsProps { 5 | pairs: RatioPairs, 6 | selectTokenPairAndSetClosingPrice(pair: Pick): any 7 | } 8 | 9 | const TopAuctions: React.SFC = ({ pairs, selectTokenPairAndSetClosingPrice }) => ( 10 | Object.keys(pairs).length > 0 && 11 |
12 |

HIGH VOLUME TOKEN PAIR AUCTIONS

13 |
    14 | {pairs.map(({ sell, buy, price }) => { 15 | const pair = `${buy}/${sell}` 16 | return ( 17 |
  • selectTokenPairAndSetClosingPrice({ sell, buy })}> 18 | {pair} {price} 19 |
  • 20 | ) 21 | })} 22 |
23 |
24 | ) 25 | 26 | export default TopAuctions 27 | -------------------------------------------------------------------------------- /src/containers/TokenUpload/index.ts: -------------------------------------------------------------------------------- 1 | import { connect } from 'react-redux' 2 | 3 | import { 4 | setIPFSFileHash, 5 | setNewIPFSCustomListAndUpdateBalances, 6 | setTokenListType, 7 | openModal, 8 | } from 'actions' 9 | 10 | import IPFSHOC from 'components/IPFSHOC' 11 | import TokenUpload from 'components/TokenUpload' 12 | 13 | import { State } from 'types' 14 | 15 | const mapState = ({ 16 | ipfs: { 17 | fileHash, 18 | filePath, 19 | json, 20 | }, 21 | tokenList: { 22 | customTokenList, 23 | }, 24 | }: Partial) => ({ 25 | fileHash, 26 | filePath, 27 | json, 28 | customTokenList, 29 | potentiallyValidHash: fileHash.length === 46, 30 | }) 31 | 32 | export default connect( 33 | mapState, 34 | { 35 | setIPFSFileHash, 36 | setNewIPFSCustomListAndUpdateBalances, 37 | setTokenListType, 38 | openModal, 39 | })(IPFSHOC(TokenUpload) as any) 40 | -------------------------------------------------------------------------------- /src/assets/claim.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/containers/AuctionWalletSummary/index.ts: -------------------------------------------------------------------------------- 1 | import { connect } from 'react-redux' 2 | 3 | import { State } from 'types' 4 | import AuctionWalletSummary from 'components/AuctionWalletSummary' 5 | 6 | const mapState = ({ blockchain }: State) => { 7 | const { activeProvider, providers } = blockchain 8 | const currentProvider = providers[activeProvider] 9 | 10 | if (!currentProvider) { 11 | return ({ 12 | address: 'NO WALLET DETECTED', 13 | provider: 'NONE DETECTED', 14 | network: 'NO NETWORK DETECTED', 15 | connected: false, 16 | }) 17 | } else { 18 | const { name: provider = '', account: address = '', network = '', loaded, available } = currentProvider 19 | 20 | return ({ 21 | address, 22 | provider, 23 | network, 24 | connected: loaded && available, 25 | }) 26 | } 27 | } 28 | 29 | export default connect(mapState)(AuctionWalletSummary) 30 | -------------------------------------------------------------------------------- /src/components/MGN/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import './styles.scss' 3 | import MGN, { MGNprops } from './MGN' 4 | import { promisedContractsMap } from 'api/contracts' 5 | import { MGNInterface } from 'api/types' 6 | 7 | interface WaitForContractState { 8 | mgn: MGNInterface 9 | } 10 | 11 | class WaitForContract extends React.Component, WaitForContractState> { 12 | state: WaitForContractState = { mgn: null } 13 | unmounted = false 14 | componentDidMount() { 15 | promisedContractsMap().then(contracts => { 16 | if (this.unmounted) return 17 | this.setState({ mgn: contracts.TokenMGN }) 18 | }) 19 | } 20 | 21 | componentWillUnmount() { 22 | this.unmounted = true 23 | } 24 | 25 | render() { 26 | if (!this.state.mgn) return null 27 | 28 | return 29 | } 30 | } 31 | 32 | export default WaitForContract 33 | -------------------------------------------------------------------------------- /src/components/TokenOverlayHeader/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | interface TokenOverlayHeaderProps { 4 | onChange(e: React.ChangeEvent): void, 5 | closeOverlay(): void, 6 | value: string, 7 | resettable?: boolean, 8 | reset(): void, 9 | } 10 | 11 | const TokenOverlayHeader: React.SFC = ({ 12 | value, 13 | onChange, 14 | closeOverlay, 15 | resettable, 16 | reset, 17 | }) => ( 18 | 19 | 27 | {resettable && } 28 |