Commit 006fe9b3 authored by Ian Lapham's avatar Ian Lapham Committed by GitHub

Updated context keys, remove logs (#680)

* updated keys in pair context

* fix bug on imported liquidity

* Add price bar and spacing tweaks

* Header tweaks

* Base for token import, query params, styling updates

* remove unused imports

* query params, create flow

* set ETH as default for create

* Style tweaks and price bar location

* add mobile popups, mobile styling on header

* updated mobile styles

* style updates mobile, fix build
Co-authored-by: default avatarCallil Capuozzo <callil.capuozzo@gmail.com>
parent 50c9d997
...@@ -44,7 +44,8 @@ ...@@ -44,7 +44,8 @@
"react-use-gesture": "^6.0.14", "react-use-gesture": "^6.0.14",
"rebass": "^4.0.7", "rebass": "^4.0.7",
"styled-components": "^4.2.0", "styled-components": "^4.2.0",
"typescript": "^3.7.5" "typescript": "^3.7.5",
"use-media": "^1.4.0"
}, },
"scripts": { "scripts": {
"start": "react-scripts start", "start": "react-scripts start",
......
<svg viewBox="0 0 24 24" focusable="false" role="presentation" aria-hidden="true" class="css-yyruks"><g fill="none" stroke="currentColor" stroke-linecap="full" stroke-width="2"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><path d="M15 3h6v6"></path><path d="M10 14L21 3"></path></g></svg>
\ No newline at end of file
<svg width="28" height="32" viewBox="0 0 28 32" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="33" height="32" viewBox="0 0 33 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 0L5.12422 6.18906C5.15121 6.18906 6.57795 8.17535 7.79344 9.60057C11.2202 13.6184 10.9328 13.2596 10.8977 13.476C10.8547 13.7406 10.7171 13.9047 10.403 14.0654C10.0451 14.2485 9.64813 14.2945 9.11223 14.2148C8.73047 14.158 8.07753 13.476 8.49532 14.2393C8.1883 14.3851 7.69161 14.9624 7.46654 15.4351C7.21391 15.9658 7.13175 16.2874 6.99865 17.2658C6.75865 19.0306 6.73939 19.0768 5.75607 20.241C5.20764 20.8903 4.89786 21.363 4.72185 21.8193C4.42877 22.579 4.52586 23.9598 4.94118 24.9387C4.98988 25.0535 5.24011 25.4952 5.49728 25.9202C5.78253 26.3917 5.98897 26.7957 6.02681 26.9565L6.08882 27.2202L6.36634 27.1878C6.51897 27.1699 6.87129 27.0957 7.14929 27.0229C8.52529 26.6627 9.57892 26.0846 10.0943 25.4071C10.3386 25.086 10.4122 24.8418 10.4164 24.3381C10.4221 23.6638 10.1523 23.2643 9.27279 22.6446C8.69957 22.2407 8.17604 21.7116 8.00562 21.3639C7.78734 20.9186 7.78123 20.2568 7.98657 19.3015C8.07295 18.8996 8.181 18.1949 8.22657 17.7356C8.32422 16.752 8.43415 16.1902 8.58051 15.9264C8.76873 15.5872 9.10988 15.4129 9.58539 15.4129C9.93907 15.4129 10.5973 15.2425 10.918 15.068C11.4604 14.7728 11.8534 14.2365 11.9597 13.6467C12.0766 12.9983 12.0502 12.953 10.7089 11.4982C10.431 11.1967 9.30332 9.9636 8.20302 8.75786C7.10273 7.55213 6.07123 6.42397 5.91078 6.25083C5.75033 6.07775 4.82108 5.06185 3.84574 3.99335C2.33451 2.33774 0 0 0 0ZM6.37605 23.3865C6.56203 23.0815 6.48326 22.6968 6.18721 22.4639C6.00755 22.3227 5.6451 22.3152 5.52275 22.4504C5.39878 22.5874 5.4158 22.6965 5.57991 22.8173C5.70351 22.9083 5.71431 22.9362 5.65783 23.0174C5.48637 23.2641 5.46502 23.3522 5.54321 23.4909C5.71473 23.7951 6.16106 23.7392 6.37605 23.3865Z" fill="black"/> <path d="M14.3463 13.7365C14.9529 14.8091 13.5964 15.1416 12.9598 15.2028C11.9952 15.2969 11.7955 14.7385 11.9839 14.0369C12.0457 13.7857 12.183 13.5597 12.377 13.3896C12.571 13.2194 12.8125 13.1133 13.0686 13.0857C13.3209 13.0625 13.5747 13.1112 13.8007 13.2263C14.0267 13.3414 14.2158 13.5183 14.3463 13.7365Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.9532 10.924C14.1743 8.58875 13.1898 7.83039 11.4128 7.42624C11.0606 7.34612 11.0281 7.33056 11.2054 7.32685C11.321 7.32445 11.6146 7.34711 11.8579 7.37717C13.2783 7.55281 14.4435 8.24879 15.7822 9.72109L16.1325 10.1064L16.5912 10.0323C16.8947 9.98343 17.4565 9.959 18.2505 9.96025C19.3802 9.96198 19.4879 9.97075 20.0753 10.1089C20.8213 10.2842 21.2723 10.4404 21.9099 10.7443C22.516 11.0331 22.9288 11.5807 22.9318 11.6972C22.9331 11.7456 22.955 11.9614 22.9805 12.1767C23.0399 12.6773 22.9645 13.2674 22.7964 13.6173C22.6007 14.0247 23.053 14.2124 23.3403 14.2124C23.6761 14.2124 23.9736 13.6451 24.2017 12.5702L24.2345 12.4156L24.4161 12.6224C25.2346 13.5546 25.8485 14.6241 26.0818 15.5245C26.2029 15.9917 26.1611 16.0317 25.911 15.6876C25.2961 14.8411 24.5766 14.5991 22.374 14.4978C20.5066 14.4119 19.1757 14.0639 18.2284 13.4138C17.6507 13.0173 17.0326 12.341 15.9532 10.924ZM12.0051 12.2132C11.2248 11.2672 10.8254 10.1732 10.7743 8.842L10.7455 8.09101L10.9486 8.1288C11.8061 8.28825 12.4503 8.74894 12.777 9.43641C12.946 9.79203 12.9946 9.96401 13.2911 11.256C13.4357 11.8864 13.6185 12.3058 13.98 12.8367C14.2218 13.1918 14.2005 13.2941 13.8802 13.3148C13.388 13.3465 12.5186 12.8357 12.0051 12.2132ZM23.3796 9.35066C23.4128 8.96722 23.4784 8.54193 23.5253 8.40554C23.5721 8.26915 23.6141 8.15756 23.6186 8.15756C23.6231 8.1575 23.6184 8.42177 23.6082 8.74476C23.5874 9.40337 23.6643 9.94768 23.8274 10.2969C23.8883 10.4271 24.0957 10.6817 24.2951 10.871C24.7107 11.2655 25.4615 12.0963 25.5433 12.2524C25.5742 12.3112 25.4726 12.2403 25.3177 12.0948C25.1628 11.9492 24.8404 11.6852 24.6013 11.5079C24.2401 11.2401 24.1497 11.1947 24.0663 11.2394C23.9905 11.2799 23.966 11.3496 23.966 11.5241C23.966 11.9272 23.8274 12.4156 23.3403 13.4138C23.5817 12.0984 23.6216 11.2452 23.3425 10.8058C23.1592 10.5174 22.5858 10.1192 21.8141 9.74442C21.4972 9.5905 21.3932 9.52165 21.5128 9.54503C21.6951 9.58063 22.472 9.8377 22.9276 10.0132C23.0598 10.0641 23.202 10.0928 23.2436 10.0768C23.2997 10.0553 23.3346 9.86933 23.3796 9.35066ZM20.3369 18.1014C18.7929 17.1928 18.12 16.1813 18.12 14.7689V14.2621L18.391 14.4763C19.0507 14.9978 19.7437 15.2188 21.565 15.4884C23.8663 15.8291 24.8183 16.1098 25.7784 16.7309C26.8185 17.4037 27.5519 18.4674 27.8026 19.6669C27.9163 20.2103 27.9162 21.1076 27.8024 21.6503C27.7013 22.1331 27.456 22.7922 27.3072 22.9813L27.2045 23.1118L27.2033 22.9009C27.1991 22.1322 26.6955 21.332 25.8295 20.7177C25.2075 20.2766 24.6847 20.0237 22.7394 19.2226C21.4327 18.6844 20.9247 18.4473 20.3369 18.1014ZM20.1691 21.1305C20.3217 20.6394 20.3197 19.8385 20.1646 19.2754C20.059 18.892 20.0589 18.8866 20.1595 19.0144C20.3219 19.2206 20.6079 19.8491 20.6783 20.1546C20.7679 20.5434 20.7555 21.1958 20.6515 21.5559C20.3223 22.6964 19.3119 23.5251 17.9373 23.782C17.7077 23.825 17.0618 23.8867 16.502 23.9193C15.3158 23.9883 14.5634 24.0889 13.9456 24.2611C13.7023 24.3289 13.4953 24.3766 13.4858 24.367C13.4762 24.3575 13.5965 24.2763 13.7531 24.1867C14.4569 23.7841 15.2936 23.5381 16.6063 23.3479C17.6671 23.1942 18.1852 23.0626 18.6681 22.8241C19.4306 22.4473 19.9378 21.8751 20.1691 21.1305ZM21.4292 21.572C21.3129 21.1565 21.2975 20.2112 21.4005 19.8105C21.4467 19.631 21.4916 19.5488 21.531 19.572C21.564 19.5914 21.6787 19.6618 21.7858 19.7284C21.8928 19.795 22.4565 20.1111 23.0385 20.4308C23.6204 20.7505 24.3314 21.1657 24.6185 21.3535C25.2806 21.7868 26.0554 22.5562 26.3234 23.0466C27.5433 25.2785 26.7199 28.2667 24.526 29.5701C24.3309 29.686 24.1602 29.7696 24.1465 29.7559C24.1328 29.7423 24.1892 29.5806 24.2718 29.3966C24.4895 28.9113 24.5644 28.5495 24.557 28.0183C24.5429 27.0101 24.221 26.2805 22.9452 24.3645C22.0586 23.0329 21.6034 22.1946 21.4292 21.572Z" fill="black"/> <path d="M18.1331 11.752C17.4281 17.1689 26.9322 16.0416 26.7513 20.3529C27.6888 19.1287 28.0919 15.8024 25.3319 14.0903C22.8729 12.5637 19.6687 13.3991 18.1331 11.752Z" fill="black"/>
<path d="M14.4924 24.9463C13.7588 25.0644 13.3675 25.2425 11.93 26.1129C10.8431 26.771 9.73905 27.372 9.16839 27.6161L8.90741 27.7278L9.27487 27.7294C10.0675 27.7332 10.7622 28.0465 11.4171 28.696C11.6492 28.9261 11.9268 29.2484 12.034 29.4122C12.2774 29.7839 12.526 30.0046 12.898 30.1791C13.1497 30.2971 13.2557 30.3148 13.7095 30.3144C14.1607 30.314 14.2657 30.2965 14.4848 30.185C14.9709 29.9376 15.2209 29.4937 15.187 28.9378C15.1522 28.3664 14.8828 27.9843 14.4619 27.9088C14.2864 27.8774 14.2873 27.8788 14.5162 27.9998C15.0699 28.2922 15.1537 29.2005 14.6682 29.6469C14.3784 29.9133 13.7781 30.008 13.3946 29.8478C12.76 29.5826 12.4824 28.5586 12.8421 27.8095C13.1931 27.0783 13.9527 26.6959 14.9422 26.7522C15.3222 26.7738 15.4537 26.8074 15.7886 26.9685C16.0227 27.0811 16.3159 27.2802 16.5042 27.4546C17.1186 28.0234 17.4557 28.6181 17.9593 30.0212C18.2872 30.935 18.4403 31.2478 18.6865 31.5068C18.5307 31.2318 18.6122 30.3364 18.5133 29.5058C18.2615 27.3925 18.049 26.7226 17.4043 26.0102C16.9747 25.5355 16.5073 25.2381 15.8756 25.0374C15.631 24.9597 14.764 24.9026 14.4924 24.9463Z" fill="black"/> <path d="M23.6074 9.70952C23.5455 9.65207 23.4818 9.59557 23.4199 9.53906C23.4827 9.59651 23.5455 9.65678 23.6074 9.70952Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.1963 16.7216C14.4552 17.3498 14.0708 18.104 13.3379 18.406C12.6049 18.708 11.8009 18.4435 11.542 17.8153C11.2831 17.187 11.6674 16.4329 12.4004 16.1309C13.1334 15.8288 13.9374 16.0933 14.1963 16.7216ZM12.7137 16.8143C13.0819 16.6626 13.4164 16.7046 13.3226 16.477C13.2288 16.2494 12.8543 16.1878 12.4861 16.3396C12.1179 16.4913 11.8954 16.7988 11.9892 17.0264C12.083 17.254 12.3455 16.966 12.7137 16.8143Z" fill="black"/> <path d="M25.8167 13.6578L25.8111 13.6493C25.7253 13.4892 25.6275 13.3359 25.5186 13.1906C25.1981 12.7546 24.7385 12.4421 24.2164 12.3054C23.8689 12.2153 23.5135 12.1592 23.1552 12.1378C22.7924 12.1114 22.4221 12.0963 22.048 12.0766C21.2981 12.0351 20.5303 11.9579 19.7803 11.7432C19.5928 11.6895 19.4053 11.6311 19.2244 11.5605C19.1306 11.5266 19.0434 11.4899 18.9506 11.4503C18.8578 11.4107 18.7631 11.3655 18.6694 11.3175C18.3167 11.1235 17.9901 10.8852 17.6972 10.6084C17.1197 10.0688 16.666 9.45662 16.2113 8.86332C15.7827 8.26774 15.3227 7.69559 14.8333 7.14934C14.3504 6.6142 13.7796 6.16633 13.1458 5.82524C12.4896 5.4932 11.7768 5.28871 11.0449 5.22253C11.8041 5.13971 12.5721 5.23381 13.2892 5.49752C14.0129 5.77972 14.6744 6.20174 15.2364 6.73968C15.6033 7.08534 15.9477 7.45433 16.2676 7.84435C18.6488 7.37347 20.58 7.79161 22.064 8.6034L22.0977 8.62035C22.5701 8.8777 23.0127 9.18658 23.4177 9.54138C23.4824 9.59788 23.5461 9.65439 23.6052 9.71183C23.9213 10.0036 24.2155 10.3183 24.4855 10.6536L24.5061 10.6809C25.3826 11.7959 25.8157 12.9552 25.8167 13.6578Z" fill="black"/>
<path d="M8.70623 9.9941C8.77397 10.3193 8.79238 10.6259 8.77667 10.899C8.76148 11.1732 8.71346 11.4148 8.65145 11.6368C8.58944 11.8589 8.51213 12.0606 8.42548 12.2493C8.33883 12.438 8.24468 12.6157 8.14534 12.7857C8.17684 12.5583 8.20283 12.329 8.21881 12.0983C8.2348 11.8677 8.23817 11.6339 8.22649 11.4023C8.21401 11.171 8.18728 10.9417 8.13585 10.7271C8.08522 10.5122 8.01382 10.3147 7.92574 10.1441C7.77305 9.84684 7.8022 9.50851 7.99215 9.38751C8.18181 9.26805 8.45948 9.41124 8.61348 9.70939C8.65134 9.78243 8.67756 9.85904 8.69378 9.93426L8.70623 9.9941Z" fill="black"/> <path d="M25.8161 13.6577L25.8105 13.6465L25.8161 13.6577Z" fill="black"/>
<path d="M6.15145 6.81565C6.20358 7.08894 6.21466 7.346 6.19763 7.57447C6.18102 7.80396 6.13738 8.00559 6.08231 8.19069C6.02723 8.37578 5.95962 8.54361 5.88438 8.70041C5.80914 8.85721 5.72776 9.00474 5.64216 9.14574C5.67176 8.95573 5.69677 8.76405 5.71343 8.57108C5.73008 8.37811 5.73622 8.18236 5.72971 7.98824C5.72254 7.79439 5.7034 7.60189 5.66337 7.42146C5.62401 7.24075 5.567 7.07432 5.49565 6.93024C5.37198 6.6791 5.40119 6.39616 5.56198 6.29751C5.72252 6.20014 5.95304 6.324 6.0778 6.57588C6.10847 6.63759 6.12935 6.70212 6.14187 6.76535L6.15145 6.81565Z" fill="black"/> <path d="M11.1654 5.91992C11.7729 6.00845 12.3925 6.25142 12.7919 6.71476C13.1913 7.1781 13.3384 7.78082 13.4538 8.35434C13.5475 8.79885 13.6216 9.25183 13.7959 9.67279C13.8803 9.87809 14.004 10.058 14.1072 10.252C14.1925 10.413 14.3481 10.558 14.4081 10.7304C14.4188 10.7551 14.4228 10.7823 14.4197 10.8091C14.4166 10.8359 14.4064 10.8614 14.3903 10.8829C14.1784 11.1184 13.6066 10.8566 13.3909 10.7511C13.0182 10.5655 12.6843 10.3097 12.4075 9.99769C11.5423 9.0324 11.0951 7.64332 11.1223 6.37855C11.1283 6.225 11.1427 6.07189 11.1654 5.91992Z" fill="black"/>
<path d="M3.48964 3.6624C3.51939 3.82057 3.52542 3.96929 3.51524 4.10144C3.50529 4.23417 3.47976 4.35075 3.44762 4.45775C3.41549 4.56474 3.37613 4.66173 3.33237 4.75233C3.28862 4.84293 3.24132 4.92815 3.1916 5.00959C3.209 4.89971 3.22375 4.78887 3.23367 4.67726C3.24359 4.56565 3.24742 4.45242 3.24395 4.34011C3.24008 4.22796 3.22929 4.11658 3.2064 4.01214C3.18389 3.90754 3.15116 3.81118 3.1101 3.72773C3.03892 3.58226 3.05624 3.41862 3.1494 3.36179C3.24241 3.3057 3.37558 3.37769 3.44739 3.52359C3.46504 3.55933 3.47702 3.59669 3.48417 3.63329L3.48964 3.6624Z" fill="black"/> <path d="M21.326 16.8066C20.0136 20.486 25.9665 22.9544 23.7363 26.695C26.0246 25.7457 27.1112 22.8781 26.1615 20.6028C25.3309 18.6054 22.8747 17.8774 21.326 16.8066Z" fill="black"/>
<path d="M13.4531 21.6165C13.8108 21.3457 14.2018 21.1226 14.6165 20.9526C15.0361 20.7839 15.4714 20.6577 15.9159 20.5759C16.798 20.4073 17.6708 20.3659 18.4039 20.0693C18.7661 19.9272 19.0994 19.7197 19.3873 19.4571C19.666 19.197 19.8793 18.8743 20.0098 18.5154C20.1435 18.1367 20.1977 17.7343 20.1692 17.3335C20.1361 16.903 20.0391 16.4798 19.8814 16.0781C20.2082 16.4195 20.4461 16.8366 20.5741 17.2925C20.7022 17.7483 20.7163 18.2288 20.6154 18.6915C20.5007 19.1812 20.2531 19.6295 19.9001 19.9864C19.5507 20.3322 19.1294 20.5959 18.6664 20.7586C18.2246 20.9143 17.7639 21.0093 17.2968 21.0411C16.8468 21.0788 16.4118 21.0892 15.9843 21.1146C15.12 21.151 14.2664 21.3203 13.4531 21.6165Z" fill="black"/>
<path d="M21.8492 28.0849C21.7171 28.1904 21.5849 28.3025 21.4396 28.4004C21.2934 28.4972 21.1401 28.5828 20.9811 28.6566C20.6502 28.8188 20.2863 28.9016 19.9181 28.8986C18.9206 28.8798 18.2156 28.1339 17.8031 27.291C17.5219 26.7166 17.3278 26.0959 16.9941 25.5488C16.5169 24.7662 15.7004 24.1362 14.7441 24.2529C14.3542 24.3019 13.9885 24.478 13.772 24.818C13.202 25.7061 14.0204 26.9501 15.0638 26.774C15.1526 26.7604 15.2394 26.7364 15.3226 26.7024C15.4054 26.667 15.4828 26.6197 15.5522 26.5621C15.698 26.4402 15.8079 26.2806 15.87 26.1007C15.9386 25.913 15.9538 25.7098 15.9141 25.5139C15.8713 25.3092 15.751 25.1292 15.5785 25.012C15.779 25.1063 15.9353 25.2751 16.0144 25.4829C16.0965 25.6966 16.1176 25.9292 16.0754 26.1543C16.0344 26.3889 15.9314 26.6082 15.7772 26.7891C15.6953 26.8821 15.6006 26.963 15.496 27.0292C15.3923 27.0947 15.2812 27.1475 15.1651 27.1865C14.9296 27.2673 14.6789 27.2934 14.432 27.2628C14.0852 27.2132 13.7582 27.0707 13.4851 26.8503C13.1626 26.5941 12.9226 26.2589 12.6311 25.9707C12.2969 25.6184 11.9025 25.3291 11.4667 25.1165C11.1662 24.9839 10.8517 24.886 10.5293 24.8246C10.3671 24.7907 10.203 24.7662 10.039 24.7455C9.96397 24.7379 9.59648 24.656 9.54492 24.704C10.052 24.2351 10.6048 23.8187 11.1949 23.4609C11.8008 23.0997 12.4513 22.8201 13.1298 22.6294C13.8333 22.4305 14.569 22.3738 15.2944 22.4627C15.6678 22.5077 16.0336 22.6028 16.3819 22.7452C16.7469 22.8916 17.0838 23.1007 17.3775 23.363C17.6682 23.6381 17.9032 23.9672 18.0694 24.3321C18.2194 24.6736 18.3313 25.0308 18.4031 25.3972C18.6168 26.4924 18.5381 28.1904 19.9659 28.4409C20.0403 28.4554 20.1154 28.4661 20.1909 28.4729L20.4243 28.4786C20.5848 28.4671 20.7442 28.4441 20.9015 28.4098C21.2272 28.3329 21.5446 28.224 21.8492 28.0849Z" fill="black"/>
<path d="M13.5531 26.8907L13.5156 26.8613L13.5531 26.8907Z" fill="black"/>
<path d="M12.2721 11.4336C12.2201 11.6343 12.1293 11.8228 12.0049 11.9883C11.7733 12.2902 11.4669 12.5256 11.1162 12.6711C10.8007 12.8076 10.4667 12.8958 10.1253 12.9329C10.0512 12.9423 9.97433 12.9479 9.90027 12.9536C9.684 12.9618 9.47603 13.0394 9.30683 13.175C9.13763 13.3106 9.01608 13.497 8.95998 13.707C8.93429 13.8115 8.91519 13.9175 8.90279 14.0244C8.86905 14.3012 8.86342 14.5894 8.83342 14.9378C8.75997 15.5308 8.58922 16.1074 8.32812 16.6443C7.98876 17.3619 7.60815 17.9401 7.69627 18.767C7.75439 19.3038 8.02813 19.6635 8.39187 20.0346C9.0481 20.7089 10.5171 21.0102 10.189 22.6715C9.9912 23.6631 8.35437 24.7038 6.05382 25.0673C6.28256 25.0324 5.76039 24.1481 5.72757 24.0916C5.48102 23.7036 5.21103 23.3382 5.0151 22.9173C4.63073 22.1008 4.45261 21.1562 4.61011 20.2615C4.77604 19.3198 5.46977 18.5984 6.04632 17.8789C6.73255 17.0229 7.45252 15.9013 7.61189 14.79C7.64939 14.5207 7.67564 14.1835 7.73564 13.8482C7.79284 13.4768 7.90867 13.1169 8.07875 12.7822C8.19485 12.5626 8.3477 12.3648 8.53062 12.1974C8.62598 12.1085 8.6889 11.99 8.7093 11.8609C8.72969 11.7318 8.70639 11.5996 8.64311 11.4854L4.97572 4.85926L10.2434 11.3893C10.3034 11.465 10.3792 11.5265 10.4655 11.5694C10.5518 11.6123 10.6464 11.6357 10.7427 11.6377C10.839 11.6398 10.9345 11.6206 11.0225 11.5814C11.1106 11.5422 11.189 11.484 11.2521 11.411C11.3188 11.3328 11.3567 11.2339 11.3592 11.131C11.3618 11.0281 11.3289 10.9274 11.2662 10.846C10.9221 10.4043 10.5584 9.95412 10.2059 9.5115L8.8803 7.86344L6.21975 4.57297L2.5918 0L6.56099 4.27821L9.39309 7.42364L10.8059 9.00013C11.2746 9.53034 11.7433 10.0436 12.2121 10.6011L12.2889 10.6953L12.3058 10.8412C12.3287 11.0392 12.3173 11.2396 12.2721 11.4336Z" fill="black"/>
<path d="M13.4856 26.8466C13.231 26.6491 13.0046 26.4174 12.8125 26.1582C13.0186 26.405 13.2436 26.6352 13.4856 26.8466Z" fill="black"/>
</svg> </svg>
<svg width="78" height="12" viewBox="0 0 78 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M36.3965 1.03412C34.6091 1.48449 33.7713 2.88605 34.2793 4.5758C34.4969 5.29984 35.1665 6.03027 36.1133 6.57652C37.8197 7.56094 38.3221 7.95961 38.6139 8.56025C38.8574 9.06134 38.8785 9.22884 38.7557 9.68301C38.4676 10.7492 37.7153 11.3372 36.6391 11.3372C35.5405 11.3372 34.7691 10.721 34.597 9.70595C34.5278 9.29775 34.4426 9.1674 34.2454 9.1674C34.0098 9.1674 33.9852 9.27538 33.9852 10.3093V11.451L34.6997 11.6937C35.8154 12.0726 37.4024 12.0273 38.3494 11.5896C40.1941 10.7367 40.9011 9.04384 40.0731 7.46204C39.7635 6.87036 38.9864 6.20995 37.655 5.40685C36.2557 4.56266 35.6321 3.9486 35.5406 3.32451C35.4002 2.36545 36.2628 1.5717 37.4417 1.57509C38.3652 1.57767 38.7615 1.79628 39.0888 2.48357C39.2937 2.91387 39.4404 3.05611 39.6831 3.0599C39.9515 3.06397 39.9915 3.01394 39.923 2.75966C39.878 2.59191 39.8401 2.17125 39.8392 1.82489C39.8378 1.38509 39.7743 1.17109 39.6282 1.11535C39.2306 0.963192 36.9092 0.904878 36.3965 1.03412ZM0.505859 1.43744C0.505859 1.63258 0.596635 1.70866 0.829493 1.70866C1.48656 1.70866 1.52181 1.89826 1.59462 5.83132C1.65818 9.26736 1.68172 9.54172 1.95636 10.0489C2.34981 10.7754 2.88344 11.2588 3.70409 11.6324C4.2663 11.8883 4.62123 11.9426 5.74551 11.9449C6.96519 11.9472 7.18744 11.9079 7.88629 11.5659C8.31512 11.3561 8.84929 10.9628 9.07331 10.692C9.85 9.7531 9.9322 9.29938 10.0203 5.4668C10.105 1.77622 10.1166 1.71625 10.747 1.71069C10.8937 1.70947 10.9852 1.60451 10.9852 1.43744C10.9852 1.18126 10.8944 1.16621 9.35203 1.16621C7.82749 1.16621 7.71889 1.1837 7.71889 1.42889C7.71889 1.62553 7.82913 1.70215 8.15807 1.73402C8.88087 1.80386 8.93952 2.08162 8.9417 5.44728C8.94402 8.85945 8.82752 9.51593 8.09683 10.2069C7.41744 10.8496 6.87673 11.066 5.95102 11.066C4.62137 11.066 3.67905 10.4471 3.37011 9.37084C3.26614 9.00888 3.22789 7.67782 3.25511 5.37022L3.2958 1.91208L3.77214 1.75898C4.03412 1.67476 4.2682 1.507 4.29243 1.38603C4.33135 1.1917 4.11455 1.16621 2.42112 1.16621C0.596634 1.16621 0.505859 1.17909 0.505859 1.43744ZM13.1627 1.43744C13.1627 1.64737 13.2535 1.70866 13.5646 1.70866C14.2576 1.70866 14.6479 1.97502 14.8045 2.55477C14.8937 2.88444 14.9321 4.4589 14.9059 6.70913C14.8592 10.727 14.8041 10.9898 13.9731 11.1554C13.6992 11.21 13.571 11.3166 13.571 11.4898C13.571 11.7263 13.7041 11.744 15.4763 11.744C17.2174 11.744 17.3816 11.7232 17.3816 11.5009C17.3816 11.3279 17.2073 11.2114 16.7763 11.0965C16.241 10.9538 16.1545 10.876 16.0284 10.4243C15.8669 9.84451 15.8286 3.73664 15.9867 3.75427C16.0427 3.76051 16.5706 4.32504 17.1598 5.00867C17.7488 5.6923 19.3604 7.4874 20.7411 8.99787C22.9022 11.3619 23.3064 11.744 23.6459 11.744H24.0403L24.0794 6.93644C24.107 3.52292 24.1641 2.08337 24.2758 1.97203C24.3625 1.88578 24.6381 1.77349 24.8882 1.7225C25.1537 1.66839 25.3432 1.54728 25.3432 1.43188C25.3432 1.26995 25.0039 1.22723 23.4719 1.19631C21.6701 1.15997 21.6006 1.16878 21.6006 1.43363C21.6006 1.63488 21.6897 1.70866 21.9332 1.70866C22.1162 1.70866 22.4377 1.85581 22.6477 2.03577L23.0296 2.36287L23.0724 5.62951C23.0968 7.47386 23.0628 8.8962 22.9946 8.8962C22.9282 8.8962 22.5127 8.4843 22.0712 7.98077C21.6298 7.47724 20.3729 6.08898 19.278 4.89558C18.1831 3.70218 16.9869 2.37981 16.62 1.9571L15.9526 1.18845L14.5577 1.17733C13.2496 1.16689 13.1627 1.18316 13.1627 1.43744ZM27.4526 1.43744C27.4526 1.64425 27.5434 1.70866 27.8349 1.70866C28.0452 1.70866 28.336 1.79518 28.4814 1.90096C28.7307 2.08254 28.748 2.31663 28.7882 6.07109C28.8384 10.7592 28.7971 11.022 27.9919 11.1503C27.5863 11.215 27.4526 11.2992 27.4526 11.4902C27.4526 11.727 27.5898 11.744 29.4941 11.744C31.4447 11.744 31.5355 11.732 31.5355 11.4728C31.5355 11.2799 31.4447 11.2016 31.2213 11.2016C31.0484 11.2016 30.7882 11.1151 30.6429 11.0093C30.3926 10.8271 30.3766 10.5926 30.3392 6.5395C30.3008 2.38756 30.3078 2.25398 30.5774 1.98533C30.7301 1.83317 31.0081 1.70866 31.1953 1.70866C31.4447 1.70866 31.5355 1.63638 31.5355 1.43744C31.5355 1.17828 31.4447 1.16621 29.4941 1.16621C27.5434 1.16621 27.4526 1.17828 27.4526 1.43744ZM41.7031 1.43744C41.7472 1.60546 41.8888 1.70866 42.075 1.70866C42.2403 1.70866 42.5095 1.85065 42.6732 2.02437C42.8395 2.20067 43.77 4.43002 44.7817 7.07597L46.5928 11.8119L47.0676 11.8524L47.5424 11.893L48.8147 8.5299C49.5145 6.68027 50.1604 5.02047 50.2502 4.84146C50.4041 4.53498 50.4384 4.58165 50.8474 5.65517C51.0859 6.2817 51.7212 7.93848 52.2589 9.33693L53.2365 11.8797H53.6672C53.9043 11.8797 54.1293 11.7986 54.1675 11.6995C54.2056 11.6005 54.831 9.99843 55.5571 8.13958C56.2833 6.28086 57.0876 4.22158 57.3445 3.56358C57.9297 2.06519 58.0469 1.88021 58.5135 1.71815C58.7209 1.64614 58.8906 1.49251 58.8906 1.37669C58.8906 1.19822 58.6427 1.16621 57.2574 1.16621C55.7151 1.16621 55.6243 1.18126 55.6243 1.43744C55.6243 1.63394 55.7151 1.70866 55.9534 1.70866C56.4824 1.70866 56.7131 1.85187 56.7131 2.18046C56.7131 2.45467 54.1209 9.49028 53.9611 9.64935C53.863 9.74713 51.5223 3.21154 51.4376 2.60345C51.3554 2.01272 51.6077 1.70866 52.1799 1.70866C52.4033 1.70866 52.4941 1.63041 52.4941 1.43744C52.4941 1.17787 52.4033 1.16621 50.3846 1.16621C48.3659 1.16621 48.2752 1.17787 48.2752 1.43744C48.2752 1.59204 48.3659 1.70866 48.4861 1.70866C48.911 1.70866 49.4742 2.11767 49.619 2.53156C49.8268 3.12541 49.6678 3.72752 48.4442 6.9836L47.4047 9.74974L47.1808 9.22122C47.0577 8.9306 46.4168 7.21564 45.7569 5.41036C44.4602 1.86379 44.441 1.70866 45.2977 1.70866C45.5986 1.70866 45.6894 1.64587 45.6894 1.43744C45.6894 1.17828 45.5986 1.16621 43.6607 1.16621C41.6991 1.16621 41.6344 1.17516 41.7031 1.43744ZM69.2643 1.53106C69.2643 1.53106 69.2642 1.7162 69.287 1.76771C69.3098 1.81923 69.4562 1.83858 69.4562 1.83858C69.547 1.86294 69.6333 1.88433 69.7149 1.90453L69.715 1.90457C70.1264 2.00642 70.4153 2.07797 70.5307 2.348C70.6087 2.53041 70.6136 3.16468 70.6145 6.56497C70.6155 10.1505 70.6149 10.5898 70.519 10.8267C70.3999 11.1206 70.1722 11.2766 69.6469 11.4241C69.6469 11.4241 69.4145 11.4888 69.3519 11.5466C69.2893 11.6044 69.2775 11.7335 69.2775 11.7335C69.2775 11.7335 69.2726 11.8534 69.3262 11.911C69.3797 11.9685 69.5227 11.9411 69.5227 11.9411L70.8847 11.9447L73.1436 11.963C73.1436 11.963 73.2359 11.9752 73.2837 11.9141C73.3316 11.853 73.3194 11.7332 73.3194 11.7332C73.3194 11.7332 73.3194 11.6052 73.2599 11.5475C73.2004 11.4898 72.9696 11.4357 72.9696 11.4357C72.4595 11.3101 72.1977 11.1465 72.0819 10.8809C71.9959 10.6834 71.9867 10.1504 71.9738 9.04021V7.41256C72.0308 7.44472 72.0829 7.48119 72.138 7.51971C72.3983 7.70191 72.7244 7.93005 73.9424 7.9653C75.418 8.00801 76.3057 7.35142 76.8336 6.58882C77.3615 5.82621 77.5663 4.62811 77.179 3.3518C76.7917 2.07549 75.6552 1.30313 74.0574 1.22328C73.2246 1.18167 72.0128 1.22276 71.3357 1.25349L71.146 1.262C70.5307 1.28884 69.7934 1.34767 69.426 1.38261L69.425 1.38271C69.325 1.39222 69.3151 1.39316 69.2871 1.42867C69.2591 1.46429 69.2643 1.53106 69.2643 1.53106ZM75.2609 6.53069C75.8545 5.9727 75.8643 5.09985 75.8643 4.54224C75.806 3.66792 75.4537 1.98647 73.4581 1.98647C72.9915 1.9625 72.0369 2.04301 72.0106 2.69023C71.9816 2.80455 71.9687 3.60431 71.9761 4.8317L71.9879 6.79067L72.191 6.89765L72.202 6.90344C72.3122 6.96163 72.4552 7.03716 72.7052 7.08612C73.4986 7.24148 74.6673 7.08869 75.2609 6.53069ZM62.7751 1.33727C62.9229 1.28126 63.0203 1.24385 63.0203 1.24385C63.0203 1.24385 63.2412 1.15306 63.3126 1.24385C63.3345 1.27181 63.4146 1.47841 63.613 1.99046C63.652 2.0911 63.6956 2.20354 63.7442 2.32873C64.04 3.09094 64.4651 4.18501 64.6887 4.76001L65.6718 7.28853C65.9888 8.10422 66.3957 9.15065 66.5761 9.6139C66.7564 10.0772 66.9868 10.5589 67.0513 10.6468C67.0829 10.6899 67.1153 10.7435 67.1508 10.8023C67.29 11.033 67.4768 11.3427 67.852 11.4032C67.852 11.4032 68.1457 11.4518 68.1892 11.4978C68.2327 11.5439 68.2426 11.6275 68.2426 11.6275V11.7847C68.2426 11.7847 68.2376 11.8249 68.2134 11.859C68.1893 11.8931 68.1004 11.8837 68.1004 11.8837L65.8356 11.8838L64.2243 11.8954C64.2243 11.8954 64.1681 11.9023 64.1349 11.8748C64.1016 11.8474 64.0844 11.778 64.0844 11.778V11.6596C64.0844 11.6596 64.0705 11.5706 64.1349 11.4932C64.1992 11.4158 64.458 11.4068 64.458 11.4068C64.9457 11.3645 65.1394 10.949 65.239 10.735C65.2465 10.7191 65.2534 10.7042 65.2599 10.6907C65.3661 10.4696 65.3277 10.3256 64.8478 9.14352C64.5312 8.36338 64.4233 8.14427 64.3462 8.12482C64.2923 8.11116 63.4493 8.10611 62.473 8.11359L60.6981 8.12711L60.5919 8.41886C60.285 9.26276 60.0124 10.1011 59.9713 10.3278C59.8876 10.7889 60.0043 11.3019 60.6825 11.391C60.6825 11.391 60.934 11.4256 61.001 11.4763C61.0681 11.5269 61.0917 11.6566 61.0917 11.6566V11.7761C61.0917 11.7761 61.0789 11.833 61.0327 11.8712C60.9865 11.9095 60.8667 11.8956 60.8667 11.8956H59.1726L57.5336 11.9142C57.5336 11.9142 57.4636 11.9126 57.4119 11.8852C57.3602 11.8578 57.3519 11.8027 57.3519 11.8027V11.6892C57.3519 11.6892 57.3431 11.6154 57.4343 11.5253C57.5256 11.4351 57.772 11.411 57.772 11.411C58.22 11.3388 58.4738 10.862 58.6198 10.5875C58.6306 10.5673 58.6408 10.5481 58.6504 10.5303C58.7083 10.4234 58.9693 9.79988 59.2305 9.14464C59.4918 8.48942 59.7849 7.75638 59.882 7.51568C60.2121 6.69727 60.5258 5.91318 61.0007 4.71971C61.2615 4.06448 61.6475 3.09731 61.8585 2.57046L62.2422 1.6125L62.7751 1.33727ZM62.6353 3.6658C62.7175 3.873 62.8434 4.18479 62.9149 4.35862C62.9865 4.53246 63.1868 5.02479 63.3599 5.4527C63.5331 5.8806 63.7459 6.40133 63.8328 6.60989C63.9198 6.81849 63.9909 6.99899 63.9909 7.01105C63.9909 7.02316 63.3386 7.03303 62.5413 7.03303C61.626 7.03303 61.0917 7.01547 61.0917 6.98537C61.0917 6.95916 61.1223 6.85526 61.1598 6.75441C61.2194 6.59404 61.5169 5.74275 62.1738 3.85224C62.2752 3.56034 62.3693 3.30286 62.3828 3.28011C62.429 3.20226 62.4859 3.289 62.6353 3.6658Z" fill="black"/>
</svg>
...@@ -47,7 +47,6 @@ const HeaderRow = styled.div` ...@@ -47,7 +47,6 @@ const HeaderRow = styled.div`
const UpperSection = styled.div` const UpperSection = styled.div`
position: relative; position: relative;
background-color: ${({ theme }) => theme.bg1};
h5 { h5 {
margin: 0; margin: 0;
...@@ -134,6 +133,9 @@ const LowerSection = styled.div` ...@@ -134,6 +133,9 @@ const LowerSection = styled.div`
padding: 2rem; padding: 2rem;
flex-grow: 1; flex-grow: 1;
overflow: auto; overflow: auto;
background-color: ${({ theme }) => theme.bg2};
border-bottom-left-radius: 25px;
border-bottom-right-radius: 20px;
h5 { h5 {
margin: 0; margin: 0;
......
import React, { useState, useEffect } from 'react' import React, { useState, useEffect } from 'react'
import styled from 'styled-components' import styled from 'styled-components'
import { transparentize } from 'polished'
// import QR from '../../assets/svg/QR.svg' // import QR from '../../assets/svg/QR.svg'
import { isAddress } from '../../utils' import { isAddress } from '../../utils'
...@@ -8,14 +7,12 @@ import { useWeb3React, useDebounce } from '../../hooks' ...@@ -8,14 +7,12 @@ import { useWeb3React, useDebounce } from '../../hooks'
const InputPanel = styled.div` const InputPanel = styled.div`
${({ theme }) => theme.flexColumnNoWrap} ${({ theme }) => theme.flexColumnNoWrap}
box-shadow: 0 4px 8px 0 ${({ theme }) => transparentize(0.95, theme.shadow1)};
position: relative; position: relative;
border-radius: 1.25rem; border-radius: 1.25rem;
background-color: ${({ theme }) => theme.bg1}; background-color: ${({ theme }) => theme.bg1};
z-index: 1; z-index: 1;
width: 100%; width: 100%;
height: 60px; height: 60px;
` `
const ContainerRow = styled.div` const ContainerRow = styled.div`
......
...@@ -77,7 +77,7 @@ export default function AdvancedSettings({ setIsOpen, setDeadline, allowedSlippa ...@@ -77,7 +77,7 @@ export default function AdvancedSettings({ setIsOpen, setDeadline, allowedSlippa
}, [allowedSlippage, parseCustomInput]) }, [allowedSlippage, parseCustomInput])
return ( return (
<AutoColumn gap="20px"> <AutoColumn gap="lg">
<Link <Link
onClick={() => { onClick={() => {
setIsOpen(false) setIsOpen(false)
......
...@@ -199,7 +199,7 @@ export function ButtonError({ children, error, ...rest }) { ...@@ -199,7 +199,7 @@ export function ButtonError({ children, error, ...rest }) {
export function ButtonDropwdown({ disabled = false, children, ...rest }) { export function ButtonDropwdown({ disabled = false, children, ...rest }) {
return ( return (
<ButtonPrimary {...rest}> <ButtonPrimary {...rest} disabled={disabled}>
<RowBetween> <RowBetween>
<div style={{ display: 'flex', alignItems: 'center' }}>{children}</div> <div style={{ display: 'flex', alignItems: 'center' }}>{children}</div>
<ChevronDown size={24} /> <ChevronDown size={24} />
...@@ -210,7 +210,7 @@ export function ButtonDropwdown({ disabled = false, children, ...rest }) { ...@@ -210,7 +210,7 @@ export function ButtonDropwdown({ disabled = false, children, ...rest }) {
export function ButtonDropwdownLight({ disabled = false, children, ...rest }) { export function ButtonDropwdownLight({ disabled = false, children, ...rest }) {
return ( return (
<ButtonEmpty {...rest}> <ButtonEmpty {...rest} disabled={disabled}>
<RowBetween> <RowBetween>
<div style={{ display: 'flex', alignItems: 'center' }}>{children}</div> <div style={{ display: 'flex', alignItems: 'center' }}>{children}</div>
<ChevronDown size={24} /> <ChevronDown size={24} />
......
...@@ -5,8 +5,8 @@ import { Box } from 'rebass/styled-components' ...@@ -5,8 +5,8 @@ import { Box } from 'rebass/styled-components'
const Card = styled(Box)` const Card = styled(Box)`
width: 100%; width: 100%;
border-radius: 8px; border-radius: 16px;
padding: 1rem; padding: 1.25rem;
padding: ${({ padding }) => padding}; padding: ${({ padding }) => padding};
border: ${({ border }) => border}; border: ${({ border }) => border};
border-radius: ${({ borderRadius }) => borderRadius}; border-radius: ${({ borderRadius }) => borderRadius};
...@@ -14,7 +14,7 @@ const Card = styled(Box)` ...@@ -14,7 +14,7 @@ const Card = styled(Box)`
export default Card export default Card
export const LightCard = styled(Card)` export const LightCard = styled(Card)`
border: 1px solid ${({ theme }) => theme.bg3}; border: 1px solid ${({ theme }) => theme.bg2};
` `
export const GreyCard = styled(Card)` export const GreyCard = styled(Card)`
...@@ -24,27 +24,26 @@ export const GreyCard = styled(Card)` ...@@ -24,27 +24,26 @@ export const GreyCard = styled(Card)`
export const YellowCard = styled(Card)` export const YellowCard = styled(Card)`
background-color: rgba(243, 190, 30, 0.3); background-color: rgba(243, 190, 30, 0.3);
color: ${({ theme }) => theme.yellow2}; color: ${({ theme }) => theme.yellow2};
fontweight: 500; font-weight: 500;
` `
export const PinkCard = styled(Card)` export const PinkCard = styled(Card)`
background-color: rgba(255, 0, 122, 0.03); background-color: rgba(255, 0, 122, 0.03);
color: ${({ theme }) => theme.pink2}; color: ${({ theme }) => theme.pink2};
fontweight: 500; font-weight: 500;
` `
const BlueCardStyled = styled(Card)` const BlueCardStyled = styled(Card)`
background-color: ${({ theme }) => theme.blue5}; background-color: ${({ theme }) => theme.blue5};
color: ${({ theme }) => theme.blue1}; color: ${({ theme }) => theme.blue1};
border-radius: 12px; border-radius: 12px;
padding: 8px;
width: fit-content; width: fit-content;
` `
export const BlueCard = ({ children }) => { export const BlueCard = ({ children }) => {
return ( return (
<BlueCardStyled> <BlueCardStyled>
<Text textAlign="center" fontWeight={500} color="#2172E5"> <Text fontWeight={500} color="#2172E5">
{children} {children}
</Text> </Text>
</BlueCardStyled> </BlueCardStyled>
......
...@@ -13,7 +13,7 @@ export const ColumnCenter = styled(Column)` ...@@ -13,7 +13,7 @@ export const ColumnCenter = styled(Column)`
export const AutoColumn = styled.div` export const AutoColumn = styled.div`
display: grid; display: grid;
grid-auto-rows: auto; grid-auto-rows: auto;
grid-row-gap: ${({ gap }) => gap}; grid-row-gap: ${({ gap }) => (gap === 'sm' && '8px') || (gap === 'md' && '12px') || (gap === 'lg' && '24px') || gap};
justify-items: ${({ justify }) => justify && justify}; justify-items: ${({ justify }) => justify && justify};
` `
......
import React from 'react' import React from 'react'
import styled from 'styled-components' import styled from 'styled-components'
import { withRouter } from 'react-router-dom'
import Modal from '../Modal' import Modal from '../Modal'
import Loader from '../Loader' import Loader from '../Loader'
...@@ -31,7 +32,8 @@ const ConfirmedIcon = styled(ColumnCenter)` ...@@ -31,7 +32,8 @@ const ConfirmedIcon = styled(ColumnCenter)`
padding: 60px 0; padding: 60px 0;
` `
export default function ConfirmationModal({ function ConfirmationModal({
history,
isOpen, isOpen,
onDismiss, onDismiss,
hash, hash,
...@@ -44,7 +46,10 @@ export default function ConfirmationModal({ ...@@ -44,7 +46,10 @@ export default function ConfirmationModal({
}) { }) {
const { chainId } = useWeb3React() const { chainId } = useWeb3React()
function WrappedOnDismissed() { function WrappedOnDismissed(returnToPool = false) {
if (returnToPool && (history.location.pathname.match('/add') || history.location.pathname.match('/remove'))) {
history.push('/pool')
}
onDismiss() onDismiss()
} }
...@@ -89,7 +94,7 @@ export default function ConfirmationModal({ ...@@ -89,7 +94,7 @@ export default function ConfirmationModal({
View on Etherscan View on Etherscan
</Text> </Text>
</Link> </Link>
<ButtonPrimary onClick={WrappedOnDismissed} style={{ margin: '20px 0' }}> <ButtonPrimary onClick={() => WrappedOnDismissed(true)} style={{ margin: '20px 0' }}>
<Text fontWeight={500} fontSize={20}> <Text fontWeight={500} fontSize={20}>
Close Close
</Text> </Text>
...@@ -109,3 +114,5 @@ export default function ConfirmationModal({ ...@@ -109,3 +114,5 @@ export default function ConfirmationModal({
</Modal> </Modal>
) )
} }
export default withRouter(ConfirmationModal)
import React, { useState, useEffect } from 'react'
import { withRouter } from 'react-router-dom'
import { Token, JSBI, WETH } from '@uniswap/sdk'
import Row from '../Row'
import TokenLogo from '../TokenLogo'
import SearchModal from '../SearchModal'
import AddLiquidity from '../../pages/Supply/AddLiquidity'
import { Text } from 'rebass'
import { Plus } from 'react-feather'
import { BlueCard } from '../Card'
import { TYPE, Link } from '../../theme'
import { AutoColumn, ColumnCenter } from '../Column'
import { ButtonPrimary, ButtonDropwdown, ButtonDropwdownLight } from '../Button'
import { usePair } from '../../contexts/Pairs'
import { useToken } from '../../contexts/Tokens'
import { useWeb3React } from '../../hooks'
const Fields = {
TOKEN0: 0,
TOKEN1: 1
}
function CreatePool({ history }) {
const { chainId } = useWeb3React()
const [showSearch, setShowSearch] = useState<boolean>(false)
const [activeField, setActiveField] = useState<number>(Fields.TOKEN0)
const [token0Address, setToken0Address] = useState<string>(WETH[chainId].address)
const [token1Address, setToken1Address] = useState<string>()
const token0: Token = useToken(token0Address)
const token1: Token = useToken(token1Address)
const [step, setStep] = useState<number>(1)
const pair = usePair(token0, token1)
const pairExists = // used to detect new exchange
pair && JSBI.notEqual(pair.reserve0.raw, JSBI.BigInt(0)) && JSBI.notEqual(pair.reserve1.raw, JSBI.BigInt(0))
useEffect(() => {
if (token0Address && token1Address && pair && !pairExists) {
setStep(2)
}
}, [pair, pairExists, token0Address, token1Address])
if (step === 2 && !pairExists) {
return <AddLiquidity token0={token0Address} token1={token1Address} step={true} />
} else
return (
<AutoColumn gap="20px">
<BlueCard>
<AutoColumn gap="10px">
<TYPE.blue>{'Step ' + step + '.'} </TYPE.blue>
{step === 1 && <TYPE.blue fontWeight={400}>Select or add your 2nd token to continue.</TYPE.blue>}
</AutoColumn>
</BlueCard>
<AutoColumn gap="24px">
{!token0Address ? (
<ButtonDropwdown
onClick={() => {
setShowSearch(true)
setActiveField(Fields.TOKEN0)
}}
>
<Text fontSize={20}>Select first token</Text>
</ButtonDropwdown>
) : (
<ButtonDropwdownLight
onClick={() => {
setShowSearch(true)
setActiveField(Fields.TOKEN0)
}}
>
<Row>
<TokenLogo address={token0Address} />
<Text fontWeight={500} fontSize={20} marginLeft={'12px'}>
{token0?.symbol}
</Text>
</Row>
</ButtonDropwdownLight>
)}
<ColumnCenter>
<Plus size="16" color="#888D9B" />
</ColumnCenter>
{!token1Address ? (
<ButtonDropwdown
onClick={() => {
setShowSearch(true)
setActiveField(Fields.TOKEN1)
}}
disabled={step !== 1}
>
<Text fontSize={20}>Select second token</Text>
</ButtonDropwdown>
) : (
<ButtonDropwdownLight
onClick={() => {
setShowSearch(true)
setActiveField(Fields.TOKEN1)
}}
>
<Row>
<TokenLogo address={token1Address} />
<Text fontWeight={500} fontSize={20} marginLeft={'12px'}>
{token1?.symbol}
</Text>
</Row>
</ButtonDropwdownLight>
)}
{pairExists ? (
<TYPE.body>
Pool already exists! Join the pool{' '}
<Link onClick={() => history.push('/add/' + token0Address + '-' + token1Address)}>here.</Link>
</TYPE.body>
) : (
<ButtonPrimary disabled={step !== 2}>
<Text fontWeight={500} fontSize={20}>
Create Pool
</Text>
</ButtonPrimary>
)}
</AutoColumn>
<SearchModal
isOpen={showSearch}
filterType="tokens"
onTokenSelect={address => {
activeField === Fields.TOKEN0 ? setToken0Address(address) : setToken1Address(address)
}}
onDismiss={() => {
setShowSearch(false)
}}
hiddenToken={activeField === Fields.TOKEN0 ? token1Address : token0Address}
/>
</AutoColumn>
)
}
export default withRouter(CreatePool)
...@@ -6,39 +6,36 @@ import { darken } from 'polished' ...@@ -6,39 +6,36 @@ import { darken } from 'polished'
import TokenLogo from '../TokenLogo' import TokenLogo from '../TokenLogo'
import DoubleLogo from '../DoubleLogo' import DoubleLogo from '../DoubleLogo'
import SearchModal from '../SearchModal' import SearchModal from '../SearchModal'
import { TYPE } from '../../theme'
import { Text } from 'rebass'
import { RowBetween } from '../Row'
import { ReactComponent as DropDown } from '../../assets/images/dropdown.svg'
import { Input as NumericalInput } from '../NumericalInput' import { Input as NumericalInput } from '../NumericalInput'
import { ReactComponent as DropDown } from '../../assets/images/dropdown.svg'
import { useWeb3React } from '../../hooks'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { useAddressBalance } from '../../contexts/Balances'
const InputRow = styled.div` const InputRow = styled.div`
${({ theme }) => theme.flexRowNoWrap} ${({ theme }) => theme.flexRowNoWrap}
align-items: center; align-items: center;
padding: 0.75rem 0.5rem 0.75rem 1rem;
padding: 0.75rem 0.85rem 0.75rem;
` `
const CurrencySelect = styled.button` const CurrencySelect = styled.button`
align-items: center; align-items: center;
height: 2.2rem; height: 2.2rem;
font-size: 20px; font-size: 20px;
font-family: 'Inter';
font-weight: 500;
background-color: ${({ selected, theme }) => (selected ? theme.bg1 : theme.blue1)}; background-color: ${({ selected, theme }) => (selected ? theme.bg1 : theme.blue1)};
color: ${({ selected, theme }) => (selected ? theme.text1 : theme.white)}; color: ${({ selected, theme }) => (selected ? theme.text1 : theme.white)};
border-radius: 8px; border-radius: 12px;
box-shadow: ${({ selected, theme }) => (selected ? 'none' : '0px 6px 10px rgba(0, 0, 0, 0.075)')};
/* padding: 0px; */
outline: none; outline: none;
cursor: pointer; cursor: pointer;
user-select: none; user-select: none;
border: none;
border: 1px solid ${({ selected, theme }) => (selected ? darken(0.1, theme.bg3) : darken(0.1, theme.blue1))};
:focus, :focus,
:hover { :hover {
border: 1px solid ${({ selected, theme }) => (selected ? darken(0.2, theme.bg3) : darken(0.2, theme.blue1))}; background-color: ${({ selected, theme }) => (selected ? theme.bg2 : darken(0.05, theme.blue1))};
} }
` `
...@@ -49,11 +46,12 @@ const Aligner = styled.span` ...@@ -49,11 +46,12 @@ const Aligner = styled.span`
` `
const StyledDropDown = styled(DropDown)` const StyledDropDown = styled(DropDown)`
margin: 0 0.5rem 0 0.5rem; margin: 0 0.25rem 0 0.5rem;
height: 35%; height: 35%;
path { path {
stroke: ${({ selected, theme }) => (selected ? theme.text1 : theme.white)}; stroke: ${({ selected, theme }) => (selected ? theme.text1 : theme.white)};
stroke-width: 1.5px;
} }
` `
...@@ -61,45 +59,22 @@ const InputPanel = styled.div` ...@@ -61,45 +59,22 @@ const InputPanel = styled.div`
${({ theme }) => theme.flexColumnNoWrap} ${({ theme }) => theme.flexColumnNoWrap}
position: relative; position: relative;
border-radius: ${({ hideInput }) => (hideInput ? '8px' : '20px')}; border-radius: ${({ hideInput }) => (hideInput ? '8px' : '20px')};
background-color: ${({ theme }) => theme.bg1}; background-color: ${({ theme }) => theme.bg2};
z-index: 1; z-index: 1;
` `
const Container = styled.div` const Container = styled.div`
border-radius: ${({ hideInput }) => (hideInput ? '8px' : '20px')}; border-radius: ${({ hideInput }) => (hideInput ? '8px' : '20px')};
border: 1px solid ${({ error, theme }) => (error ? theme.red1 : theme.bg2)}; /* border: 1px solid ${({ error, theme }) => (error ? theme.red1 : theme.bg2)}; */
background-color: ${({ theme }) => theme.bg1}; border: 1px solid ${({ theme }) => theme.bg2};
`
const LabelRow = styled.div`
${({ theme }) => theme.flexRowNoWrap}
align-items: center;
color: ${({ theme }) => theme.text3};
font-size: 0.75rem;
line-height: 1rem;
padding: 0.5rem 1rem 1rem 1rem;
span:hover {
cursor: pointer;
color: ${({ theme }) => darken(0.2, theme.text3)};
}
`
const ErrorSpan = styled.span` background-color: ${({ theme }) => theme.bg1};
color: ${({ error, theme }) => error && theme.red1};
:hover {
cursor: pointer;
color: ${({ error, theme }) => error && darken(0.1, theme.red1)};
}
` `
const StyledTokenName = styled.span` const StyledTokenName = styled.span`
margin: 0 0.25rem 0 0.75rem; ${({ active }) => (active ? ' margin: 0 0.25rem 0 0.75rem;' : ' margin: 0 0.25rem 0 0.25rem;')}
` font-size: ${({ active }) => (active ? '20px' : '16px')};
const ClickableText = styled.div`
:hover {
cursor: pointer;
}
` `
const StyledBalanceMax = styled.button` const StyledBalanceMax = styled.button`
...@@ -128,6 +103,7 @@ export default function CurrencyInputPanel({ ...@@ -128,6 +103,7 @@ export default function CurrencyInputPanel({
onMax, onMax,
atMax, atMax,
error, error,
type = '',
urlAddedTokens = [], // used urlAddedTokens = [], // used
onTokenSelection = null, onTokenSelection = null,
token = null, token = null,
...@@ -140,12 +116,9 @@ export default function CurrencyInputPanel({ ...@@ -140,12 +116,9 @@ export default function CurrencyInputPanel({
showSendWithSwap = false showSendWithSwap = false
}) { }) {
const { t } = useTranslation() const { t } = useTranslation()
const { account } = useWeb3React()
const [modalOpen, setModalOpen] = useState(false) const [modalOpen, setModalOpen] = useState(false)
const userTokenBalance = useAddressBalance(account, token)
return ( return (
<InputPanel> <InputPanel>
<Container error={!!error} hideInput={hideInput}> <Container error={!!error} hideInput={hideInput}>
...@@ -158,7 +131,9 @@ export default function CurrencyInputPanel({ ...@@ -158,7 +131,9 @@ export default function CurrencyInputPanel({
onUserInput(field, val) onUserInput(field, val)
}} }}
/> />
{!!token?.address && !atMax && <StyledBalanceMax onClick={onMax}>MAX</StyledBalanceMax>} {!!token?.address && !atMax && type !== 'OUTPUT' && (
<StyledBalanceMax onClick={onMax}>MAX</StyledBalanceMax>
)}
{/* {renderUnlockButton()} */} {/* {renderUnlockButton()} */}
</> </>
)} )}
...@@ -182,25 +157,34 @@ export default function CurrencyInputPanel({ ...@@ -182,25 +157,34 @@ export default function CurrencyInputPanel({
{pair?.token0.symbol}:{pair?.token1.symbol} {pair?.token0.symbol}:{pair?.token1.symbol}
</StyledTokenName> </StyledTokenName>
) : ( ) : (
<StyledTokenName>{(token && token.symbol) || t('selectToken')}</StyledTokenName> <StyledTokenName active={token && token.symbol}>
{(token && token.symbol) || t('selectToken')}
</StyledTokenName>
)} )}
{!disableTokenSelect && <StyledDropDown selected={!!token?.address} />} {!disableTokenSelect && <StyledDropDown selected={!!token?.address} />}
</Aligner> </Aligner>
</CurrencySelect> </CurrencySelect>
</InputRow> </InputRow>
{!hideBalance && !!token && ( {/* {!hideBalance && !!token && (
<LabelRow> <LabelRow>
<RowBetween> <RowBetween>
<Text>{'-'}</Text> <Text fontSize={16} fontWeight={400}>
{'-'}
</Text>
{!!token?.address && type !== 'OUTPUT' && !atMax ? (
<MiniMax onClick={onMax}>MAX</MiniMax>
) : (
<Clear>Clear</Clear>
)}
<ErrorSpan data-tip={'Enter max'} error={!!error} onClick={() => {}}></ErrorSpan> <ErrorSpan data-tip={'Enter max'} error={!!error} onClick={() => {}}></ErrorSpan>
<ClickableText onClick={onMax}> <ClickableText fontWeight={500} onClick={onMax}>
<TYPE.body> <TYPE.body>
Balance: {customBalance ? customBalance?.toSignificant(4) : userTokenBalance?.toSignificant(4)} {customBalance ? customBalance?.toSignificant(4) : userTokenBalance?.toSignificant(4)} {token.symbol}
</TYPE.body> </TYPE.body>
</ClickableText> </ClickableText>
</RowBetween> </RowBetween>
</LabelRow> </LabelRow>
)} )} */}
</Container> </Container>
{!disableTokenSelect && ( {!disableTokenSelect && (
<SearchModal <SearchModal
......
...@@ -12,13 +12,16 @@ import AdvancedSettings from '../AdvancedSettings' ...@@ -12,13 +12,16 @@ import AdvancedSettings from '../AdvancedSettings'
import AddressInputPanel from '../AddressInputPanel' import AddressInputPanel from '../AddressInputPanel'
import ConfirmationModal from '../ConfirmationModal' import ConfirmationModal from '../ConfirmationModal'
import CurrencyInputPanel from '../CurrencyInputPanel' import CurrencyInputPanel from '../CurrencyInputPanel'
import { Copy } from 'react-feather'
import { Link } from '../../theme/components' import { Link } from '../../theme/components'
import { Text } from 'rebass' import { Text } from 'rebass'
import { TYPE } from '../../theme' import { TYPE } from '../../theme'
import { ArrowDown, ArrowUp } from 'react-feather' import { Hover } from '../../theme'
import { GreyCard, BlueCard, YellowCard } from '../../components/Card' import { ArrowDown } from 'react-feather'
import { AutoColumn, ColumnCenter } from '../../components/Column' import { AutoColumn, ColumnCenter } from '../../components/Column'
import { RowBetween, RowFixed, AutoRow } from '../../components/Row' import { RowBetween, RowFixed, AutoRow } from '../../components/Row'
import { GreyCard, BlueCard, YellowCard } from '../../components/Card'
import { ButtonPrimary, ButtonError, ButtonLight } from '../Button' import { ButtonPrimary, ButtonError, ButtonLight } from '../Button'
import { usePair } from '../../contexts/Pairs' import { usePair } from '../../contexts/Pairs'
...@@ -26,13 +29,13 @@ import { useToken } from '../../contexts/Tokens' ...@@ -26,13 +29,13 @@ import { useToken } from '../../contexts/Tokens'
import { usePopups } from '../../contexts/Application' import { usePopups } from '../../contexts/Application'
import { useRoute } from '../../contexts/Routes' import { useRoute } from '../../contexts/Routes'
// import { useTranslation } from 'react-i18next' // import { useTranslation } from 'react-i18next'
import { useTransactionAdder, usePendingApproval } from '../../contexts/Transactions'
import { useAddressAllowance } from '../../contexts/Allowances' import { useAddressAllowance } from '../../contexts/Allowances'
import { useWeb3React, useTokenContract } from '../../hooks' import { useWeb3React, useTokenContract } from '../../hooks'
import { useAddressBalance, useAllBalances } from '../../contexts/Balances' import { useAddressBalance, useAllBalances } from '../../contexts/Balances'
import { useTransactionAdder, usePendingApproval } from '../../contexts/Transactions'
import { INITIAL_TOKENS_CONTEXT } from '../../contexts/Tokens'
import { ROUTER_ADDRESSES } from '../../constants' import { ROUTER_ADDRESSES } from '../../constants'
import { INITIAL_TOKENS_CONTEXT } from '../../contexts/Tokens'
import { getRouterContract, calculateGasMargin, getProviderOrSigner, getEtherscanLink } from '../../utils' import { getRouterContract, calculateGasMargin, getProviderOrSigner, getEtherscanLink } from '../../utils'
const Wrapper = styled.div` const Wrapper = styled.div`
...@@ -40,8 +43,7 @@ const Wrapper = styled.div` ...@@ -40,8 +43,7 @@ const Wrapper = styled.div`
` `
const ArrowWrapper = styled.div` const ArrowWrapper = styled.div`
padding: 6px; padding: 2px;
border: 1px solid ${({ theme }) => theme.blue4};
border-radius: 12px; border-radius: 12px;
display: flex; display: flex;
justify-content: center; justify-content: center;
...@@ -55,18 +57,24 @@ const ArrowWrapper = styled.div` ...@@ -55,18 +57,24 @@ const ArrowWrapper = styled.div`
const FixedBottom = styled.div` const FixedBottom = styled.div`
position: absolute; position: absolute;
bottom: -200px; margin-top: 2rem;
width: 100%; width: 100%;
margin-bottom: 40px;
`
const BottomGrouping = styled.div`
margin-top: 20px;
position: relative;
` `
const ErrorText = styled(Text)` const ErrorText = styled(Text)`
color: ${({ theme, warningMedium, warningHigh }) => color: ${({ theme, warningLow, warningMedium, warningHigh }) =>
warningHigh ? theme.red1 : warningMedium ? theme.yellow1 : theme.text1}; warningHigh ? theme.red1 : warningMedium ? theme.yellow2 : warningLow ? theme.green1 : theme.text3};
` `
const InputGroup = styled(AutoColumn)` const InputGroup = styled(AutoColumn)`
position: relative; position: relative;
padding: 40px 0; padding: 40px 0 20px 0;
` `
const StyledNumerical = styled(NumericalInput)` const StyledNumerical = styled(NumericalInput)`
...@@ -83,13 +91,14 @@ const StyledNumerical = styled(NumericalInput)` ...@@ -83,13 +91,14 @@ const StyledNumerical = styled(NumericalInput)`
const MaxButton = styled.button` const MaxButton = styled.button`
position: absolute; position: absolute;
right: 70px; right: 70px;
padding: 0.5rem 1rem; padding: 0.5rem 0.5rem;
background-color: ${({ theme }) => theme.blue5}; background-color: ${({ theme }) => theme.blue5};
border: 1px solid ${({ theme }) => theme.blue5}; border: 1px solid ${({ theme }) => theme.blue5};
border-radius: 0.5rem; border-radius: 0.5rem;
font-size: 1rem; font-size: 0.75rem;
font-weight: 500; font-weight: 500;
cursor: pointer; cursor: pointer;
text-transform: uppercase;
margin-right: 0.5rem; margin-right: 0.5rem;
color: ${({ theme }) => theme.blue1}; color: ${({ theme }) => theme.blue1};
:hover { :hover {
...@@ -101,6 +110,28 @@ const MaxButton = styled.button` ...@@ -101,6 +110,28 @@ const MaxButton = styled.button`
} }
` `
// styles
const Dots = styled.span`
&::after {
display: inline-block;
animation: ellipsis 1.25s infinite;
content: '.';
width: 1em;
text-align: left;
}
@keyframes ellipsis {
0% {
content: '.';
}
33% {
content: '..';
}
66% {
content: '...';
}
}
`
enum Field { enum Field {
INPUT, INPUT,
OUTPUT OUTPUT
...@@ -117,15 +148,15 @@ interface SwapState { ...@@ -117,15 +148,15 @@ interface SwapState {
} }
} }
function initializeSwapState(inputAddress?: string, outputAddress?: string): SwapState { function initializeSwapState({ inputTokenAddress, outputTokenAddress, typedValue, independentField }): SwapState {
return { return {
independentField: Field.INPUT, independentField: independentField,
typedValue: '', typedValue: typedValue,
[Field.INPUT]: { [Field.INPUT]: {
address: inputAddress address: inputTokenAddress
}, },
[Field.OUTPUT]: { [Field.OUTPUT]: {
address: outputAddress address: outputTokenAddress
} }
} }
} }
...@@ -222,7 +253,7 @@ const DEFAULT_DEADLINE_FROM_NOW = 60 * 15 ...@@ -222,7 +253,7 @@ const DEFAULT_DEADLINE_FROM_NOW = 60 * 15
const ALLOWED_SLIPPAGE_MEDIUM = 100 const ALLOWED_SLIPPAGE_MEDIUM = 100
const ALLOWED_SLIPPAGE_HIGH = 500 const ALLOWED_SLIPPAGE_HIGH = 500
function ExchangePage({ sendingInput = false, history }) { function ExchangePage({ sendingInput = false, history, initialCurrency, params }) {
// text translation // text translation
// const { t } = useTranslation() // const { t } = useTranslation()
...@@ -238,8 +269,34 @@ function ExchangePage({ sendingInput = false, history }) { ...@@ -238,8 +269,34 @@ function ExchangePage({ sendingInput = false, history }) {
const [sendingWithSwap, setSendingWithSwap] = useState<boolean>(false) const [sendingWithSwap, setSendingWithSwap] = useState<boolean>(false)
const [recipient, setRecipient] = useState<string>('') const [recipient, setRecipient] = useState<string>('')
// trade details // trade details, check query params for initial state
const [state, dispatch] = useReducer(reducer, WETH[chainId].address, initializeSwapState) const [state, dispatch] = useReducer(
reducer,
{
independentField: params.outputTokenAddress && !params.inputTokenAddress ? Field.OUTPUT : Field.INPUT,
inputTokenAddress: params.inputTokenAddress
? params.inputTokenAddress
: initialCurrency
? initialCurrency
: WETH[chainId].address,
outputTokenAddress: params.outputTokenAddress ? params.outputTokenAddress : '',
typedValue:
params.inputTokenAddress && !params.outputTokenAddress
? params.inputTokenAmount
? params.inputTokenAmount
: ''
: !params.inputTokenAddress && params.outputTokenAddress
? params.outputTokenAmount
? params.outputTokenAmount
: ''
: params.inputTokenAddress && params.outputTokenAddress
? params.inputTokenAmount
? params.inputTokenAmount
: ''
: ''
},
initializeSwapState
)
const { independentField, typedValue, ...fieldData } = state const { independentField, typedValue, ...fieldData } = state
const dependentField: Field = independentField === Field.INPUT ? Field.OUTPUT : Field.INPUT const dependentField: Field = independentField === Field.INPUT ? Field.OUTPUT : Field.INPUT
const tradeType: TradeType = independentField === Field.INPUT ? TradeType.EXACT_INPUT : TradeType.EXACT_OUTPUT const tradeType: TradeType = independentField === Field.INPUT ? TradeType.EXACT_INPUT : TradeType.EXACT_OUTPUT
...@@ -263,14 +320,11 @@ function ExchangePage({ sendingInput = false, history }) { ...@@ -263,14 +320,11 @@ function ExchangePage({ sendingInput = false, history }) {
const importedTokenOutput = const importedTokenOutput =
tokens[Field.OUTPUT] && !!!INITIAL_TOKENS_CONTEXT?.[chainId]?.[tokens[Field.OUTPUT]?.address] tokens[Field.OUTPUT] && !!!INITIAL_TOKENS_CONTEXT?.[chainId]?.[tokens[Field.OUTPUT]?.address]
// entities for swap
const pair: Pair = usePair(tokens[Field.INPUT], tokens[Field.OUTPUT]) const pair: Pair = usePair(tokens[Field.INPUT], tokens[Field.OUTPUT])
// console.log(pair?.token0?.symbol)
// console.log(pair?.token1?.symbol)
// console.log('--------------')
const route = useRoute(tokens[Field.INPUT], tokens[Field.OUTPUT]) const route = useRoute(tokens[Field.INPUT], tokens[Field.OUTPUT])
// const route = useRoute(pair)
// check for invalid selection
const noRoute: boolean = !route && !!tokens[Field.INPUT] && !!tokens[Field.OUTPUT] const noRoute: boolean = !route && !!tokens[Field.INPUT] && !!tokens[Field.OUTPUT]
const emptyReserves = pair && JSBI.equal(JSBI.BigInt(0), pair.reserve0.raw) const emptyReserves = pair && JSBI.equal(JSBI.BigInt(0), pair.reserve0.raw)
...@@ -473,7 +527,7 @@ function ExchangePage({ sendingInput = false, history }) { ...@@ -473,7 +527,7 @@ function ExchangePage({ sendingInput = false, history }) {
}) })
.catch(e => { .catch(e => {
addPopup( addPopup(
<AutoColumn gap="10px"> <AutoColumn gap="sm">
<Text>Transaction Failed: try again.</Text> <Text>Transaction Failed: try again.</Text>
</AutoColumn> </AutoColumn>
) )
...@@ -499,7 +553,7 @@ function ExchangePage({ sendingInput = false, history }) { ...@@ -499,7 +553,7 @@ function ExchangePage({ sendingInput = false, history }) {
}) })
.catch(e => { .catch(e => {
addPopup( addPopup(
<AutoColumn gap="10px"> <AutoColumn gap="sm">
<Text>Transaction Failed: try again.</Text> <Text>Transaction Failed: try again.</Text>
</AutoColumn> </AutoColumn>
) )
...@@ -610,7 +664,7 @@ function ExchangePage({ sendingInput = false, history }) { ...@@ -610,7 +664,7 @@ function ExchangePage({ sendingInput = false, history }) {
}) })
.catch(() => { .catch(() => {
addPopup( addPopup(
<AutoColumn gap="10px"> <AutoColumn gap="sm">
<Text>Transaction Failed: try again.</Text> <Text>Transaction Failed: try again.</Text>
</AutoColumn> </AutoColumn>
) )
...@@ -696,16 +750,6 @@ function ExchangePage({ sendingInput = false, history }) { ...@@ -696,16 +750,6 @@ function ExchangePage({ sendingInput = false, history }) {
setIsValid(false) setIsValid(false)
} }
if (showInputUnlock && !(sending && !sendingWithSwap)) {
setInputError('Approval Needed')
setIsValid(false)
}
if (showOutputUnlock && !ignoreOutput) {
setOutputError('Approval Needed')
setIsValid(false)
}
if ( if (
userBalances[Field.INPUT] && userBalances[Field.INPUT] &&
parsedAmounts[Field.INPUT] && parsedAmounts[Field.INPUT] &&
...@@ -730,6 +774,10 @@ function ExchangePage({ sendingInput = false, history }) { ...@@ -730,6 +774,10 @@ function ExchangePage({ sendingInput = false, history }) {
]) ])
// warnings on slippage // warnings on slippage
const warningLow: boolean =
slippageFromTrade &&
parseFloat(slippageFromTrade.toFixed(4)) < ALLOWED_SLIPPAGE_MEDIUM / 100 &&
parseFloat(slippageFromTrade.toFixed(4)) > 0
const warningMedium: boolean = const warningMedium: boolean =
slippageFromTrade && parseFloat(slippageFromTrade.toFixed(4)) > ALLOWED_SLIPPAGE_MEDIUM / 100 slippageFromTrade && parseFloat(slippageFromTrade.toFixed(4)) > ALLOWED_SLIPPAGE_MEDIUM / 100
const warningHigh: boolean = const warningHigh: boolean =
...@@ -745,7 +793,7 @@ function ExchangePage({ sendingInput = false, history }) { ...@@ -745,7 +793,7 @@ function ExchangePage({ sendingInput = false, history }) {
function modalHeader() { function modalHeader() {
if (sending && !sendingWithSwap) { if (sending && !sendingWithSwap) {
return ( return (
<AutoColumn gap="30px" style={{ marginTop: '40px' }}> <AutoColumn gap="lg" style={{ marginTop: '40px' }}>
<RowBetween> <RowBetween>
<Text fontSize={36} fontWeight={500}> <Text fontSize={36} fontWeight={500}>
{parsedAmounts[Field.INPUT]?.toFixed(8)} {tokens[Field.INPUT]?.symbol} {parsedAmounts[Field.INPUT]?.toFixed(8)} {tokens[Field.INPUT]?.symbol}
...@@ -762,8 +810,8 @@ function ExchangePage({ sendingInput = false, history }) { ...@@ -762,8 +810,8 @@ function ExchangePage({ sendingInput = false, history }) {
if (sending && sendingWithSwap) { if (sending && sendingWithSwap) {
return ( return (
<AutoColumn gap="30px" style={{ marginTop: '40px' }}> <AutoColumn gap="lg" style={{ marginTop: '40px' }}>
<AutoColumn gap="10px"> <AutoColumn gap="sm">
<AutoRow gap="10px"> <AutoRow gap="10px">
<TokenLogo address={tokens[Field.OUTPUT]?.address} size={'30px'} /> <TokenLogo address={tokens[Field.OUTPUT]?.address} size={'30px'} />
<Text fontSize={36} fontWeight={500}> <Text fontSize={36} fontWeight={500}>
...@@ -774,7 +822,7 @@ function ExchangePage({ sendingInput = false, history }) { ...@@ -774,7 +822,7 @@ function ExchangePage({ sendingInput = false, history }) {
Via {parsedAmounts[Field.INPUT]?.toSignificant(4)} {tokens[Field.INPUT]?.symbol} swap Via {parsedAmounts[Field.INPUT]?.toSignificant(4)} {tokens[Field.INPUT]?.symbol} swap
</BlueCard> </BlueCard>
</AutoColumn> </AutoColumn>
<AutoColumn gap="10px"> <AutoColumn gap="sm">
<TYPE.darkGray fontSize={20}>To</TYPE.darkGray> <TYPE.darkGray fontSize={20}>To</TYPE.darkGray>
<TYPE.blue fontSize={36}> <TYPE.blue fontSize={36}>
{recipient?.slice(0, 6)}...{recipient?.slice(36, 42)} {recipient?.slice(0, 6)}...{recipient?.slice(36, 42)}
...@@ -786,7 +834,7 @@ function ExchangePage({ sendingInput = false, history }) { ...@@ -786,7 +834,7 @@ function ExchangePage({ sendingInput = false, history }) {
if (!sending) { if (!sending) {
return ( return (
<AutoColumn gap={'20px'} style={{ marginTop: '40px' }}> <AutoColumn gap={'lg'} style={{ marginTop: '40px' }}>
<RowBetween align="flex-end"> <RowBetween align="flex-end">
<Text fontSize={36} fontWeight={500}> <Text fontSize={36} fontWeight={500}>
{!!slippageAdjustedAmounts[Field.INPUT] && slippageAdjustedAmounts[Field.INPUT].toSignificant(6)} {!!slippageAdjustedAmounts[Field.INPUT] && slippageAdjustedAmounts[Field.INPUT].toSignificant(6)}
...@@ -843,30 +891,13 @@ function ExchangePage({ sendingInput = false, history }) { ...@@ -843,30 +891,13 @@ function ExchangePage({ sendingInput = false, history }) {
if (!sending || (sending && sendingWithSwap)) { if (!sending || (sending && sendingWithSwap)) {
return ( return (
<> <>
{route && route.midPrice && !emptyReserves && ( {route && route.midPrice && !emptyReserves && <PriceBar />}
<RowBetween>
<Text color="#565A69" fontWeight={500} fontSize={16}>
Price
</Text>
<Text fontWeight={500} fontSize={16}>
{`1 ${tokens[Field.INPUT]?.symbol} = ${route.midPrice.toFixed(6)} ${tokens[Field.OUTPUT]?.symbol}`}
</Text>
</RowBetween>
)}
<RowBetween>
<Text color="#565A69" fontWeight={500} fontSize={16}>
Slippage
</Text>
<ErrorText warningHigh={warningHigh} fontWeight={500}>
{slippageFromTrade && slippageFromTrade.toFixed(4)}%
</ErrorText>
</RowBetween>
<ButtonError onClick={onSwap} error={!!warningHigh} style={{ margin: '10px 0' }}> <ButtonError onClick={onSwap} error={!!warningHigh} style={{ margin: '10px 0' }}>
<Text fontSize={20} fontWeight={500}> <Text fontSize={20} fontWeight={500}>
{warningHigh ? (sending ? 'Send Anyway' : 'Swap Anyway') : sending ? 'Confirm Send' : 'Confirm Swap'} {warningHigh ? (sending ? 'Send Anyway' : 'Swap Anyway') : sending ? 'Confirm Send' : 'Confirm Swap'}
</Text> </Text>
</ButtonError> </ButtonError>
<AutoColumn justify="center" gap="20px"> <AutoColumn justify="center" gap="lg">
<TYPE.italic textAlign="center" style={{ width: '80%' }}> <TYPE.italic textAlign="center" style={{ width: '80%' }}>
{`Output is estimated. You will receive at least ${slippageAdjustedAmounts[Field.OUTPUT]?.toSignificant( {`Output is estimated. You will receive at least ${slippageAdjustedAmounts[Field.OUTPUT]?.toSignificant(
6 6
...@@ -885,6 +916,45 @@ function ExchangePage({ sendingInput = false, history }) { ...@@ -885,6 +916,45 @@ function ExchangePage({ sendingInput = false, history }) {
} }
} }
const PriceBar = function() {
return (
// <GreyCard>
<AutoRow justify="space-between">
<AutoColumn justify="center">
<Text fontWeight={500} fontSize={16} color="#000000">
{pair ? `${route.midPrice.toSignificant(6)} ` : '-'}
</Text>
<Text fontWeight={500} fontSize={14} color="#888D9B" pt={1}>
{tokens[Field.OUTPUT]?.symbol} / {tokens[Field.INPUT]?.symbol}
</Text>
</AutoColumn>
<AutoColumn justify="center">
<Text fontWeight={500} fontSize={16} color="#000000">
{pair ? `${route.midPrice.invert().toSignificant(6)} ` : '-'}
</Text>
<Text fontWeight={500} fontSize={14} color="#888D9B" pt={1}>
{tokens[Field.INPUT]?.symbol} / {tokens[Field.OUTPUT]?.symbol}
</Text>
</AutoColumn>
<AutoColumn justify="center">
<ErrorText
fontWeight={500}
fontSize={16}
warningLow={warningLow}
warningMedium={warningMedium}
warningHigh={warningHigh}
>
{slippageFromTrade ? slippageFromTrade.toFixed(4) : '0'}%
</ErrorText>
<Text fontWeight={500} fontSize={14} color="#888D9B" pt={1}>
Slippage
</Text>
</AutoColumn>
</AutoRow>
// </GreyCard>
)
}
// text to show while loading // text to show while loading
const pendingText: string = sending const pendingText: string = sending
? sendingWithSwap ? sendingWithSwap
...@@ -934,7 +1004,7 @@ function ExchangePage({ sendingInput = false, history }) { ...@@ -934,7 +1004,7 @@ function ExchangePage({ sendingInput = false, history }) {
{sending && !sendingWithSwap && ( {sending && !sendingWithSwap && (
<> <>
<InputGroup gap="24px" justify="center"> <InputGroup gap="lg" justify="center">
{!atMaxAmountInput && ( {!atMaxAmountInput && (
<MaxButton <MaxButton
onClick={() => { onClick={() => {
...@@ -945,7 +1015,7 @@ function ExchangePage({ sendingInput = false, history }) { ...@@ -945,7 +1015,7 @@ function ExchangePage({ sendingInput = false, history }) {
</MaxButton> </MaxButton>
)} )}
<StyledNumerical value={formattedAmounts[Field.INPUT]} onUserInput={val => onUserInput(Field.INPUT, val)} /> <StyledNumerical value={formattedAmounts[Field.INPUT]} onUserInput={val => onUserInput(Field.INPUT, val)} />
{!parsedAmounts[Field.INPUT] && <TYPE.gray>Enter an amount.</TYPE.gray>} {/* {!parsedAmounts[Field.INPUT] && <TYPE.gray>Enter an amount.</TYPE.gray>} */}
<CurrencyInputPanel <CurrencyInputPanel
field={Field.INPUT} field={Field.INPUT}
value={formattedAmounts[Field.INPUT]} value={formattedAmounts[Field.INPUT]}
...@@ -966,7 +1036,7 @@ function ExchangePage({ sendingInput = false, history }) { ...@@ -966,7 +1036,7 @@ function ExchangePage({ sendingInput = false, history }) {
</> </>
)} )}
<AutoColumn gap={'20px'}> <AutoColumn gap={'md'}>
{(!sending || sendingWithSwap) && ( {(!sending || sendingWithSwap) && (
<> <>
<CurrencyInputPanel <CurrencyInputPanel
...@@ -983,22 +1053,22 @@ function ExchangePage({ sendingInput = false, history }) { ...@@ -983,22 +1053,22 @@ function ExchangePage({ sendingInput = false, history }) {
onTokenSelection={address => onTokenSelection(Field.INPUT, address)} onTokenSelection={address => onTokenSelection(Field.INPUT, address)}
/> />
{sendingWithSwap ? ( {sendingWithSwap ? (
<RowBetween>
<ArrowWrapper onClick={onSwapTokens}>
<ArrowDown size="16" color="#2F80ED" />
<ArrowUp size="16" color="#2F80ED" />
</ArrowWrapper>
<ArrowWrapper onClick={() => setSendingWithSwap(false)} style={{ marginRight: '20px' }}>
<TYPE.blue>Remove Swap</TYPE.blue>
</ArrowWrapper>
</RowBetween>
) : (
<ColumnCenter> <ColumnCenter>
<ArrowWrapper onClick={onSwapTokens}> <RowBetween padding="0 8px">
<ArrowDown size="16" color="#2F80ED" /> <ArrowWrapper onClick={onSwapTokens}>
<ArrowUp size="16" color="#2F80ED" /> <ArrowDown size="16" color="#2F80ED" onClick={onSwapTokens} />
</ArrowWrapper> </ArrowWrapper>
<ArrowWrapper onClick={() => setSendingWithSwap(false)} style={{ marginRight: '20px' }}>
<TYPE.blue>Remove Swap</TYPE.blue>
</ArrowWrapper>
</RowBetween>
</ColumnCenter> </ColumnCenter>
) : (
<Hover>
<ColumnCenter>
<ArrowDown size="16" onClick={onSwapTokens} />
</ColumnCenter>
</Hover>
)} )}
<CurrencyInputPanel <CurrencyInputPanel
field={Field.OUTPUT} field={Field.OUTPUT}
...@@ -1007,46 +1077,29 @@ function ExchangePage({ sendingInput = false, history }) { ...@@ -1007,46 +1077,29 @@ function ExchangePage({ sendingInput = false, history }) {
onMax={() => { onMax={() => {
maxAmountOutput && onMaxOutput(maxAmountOutput.toExact()) maxAmountOutput && onMaxOutput(maxAmountOutput.toExact())
}} }}
type={'OUTPUT'}
atMax={atMaxAmountOutput} atMax={atMaxAmountOutput}
token={tokens[Field.OUTPUT]} token={tokens[Field.OUTPUT]}
onTokenSelection={address => onTokenSelection(Field.OUTPUT, address)} onTokenSelection={address => onTokenSelection(Field.OUTPUT, address)}
error={outputError} error={outputError}
pair={pair} pair={pair}
/> />
{!noRoute && ( // hide price if new exchange {sendingWithSwap && (
<RowBetween> <RowBetween padding="0 8px">
<Text fontWeight={500} color="#565A69"> <ArrowDown size="16" />
Price <div> </div>
</Text>
<Text fontWeight={500} color="#565A69">
{pair
? `1 ${tokens[Field.INPUT]?.symbol} = ${route?.midPrice.toSignificant(6)} ${
tokens[Field.OUTPUT]?.symbol
}`
: '-'}
</Text>
</RowBetween>
)}
{warningMedium && (
<RowBetween>
<Text fontWeight={500} color="#565A69">
Slippage
</Text>
<ErrorText fontWeight={500} warningMedium={warningMedium} warningHigh={warningHigh}>
{slippageFromTrade.toFixed(4)}%
</ErrorText>
</RowBetween> </RowBetween>
)} )}
</> </>
)} )}
{sending && ( {sending && (
<AutoColumn gap="10px"> <AutoColumn gap="sm">
<AddressInputPanel <AddressInputPanel
onChange={_onRecipient} onChange={_onRecipient}
onError={(error: boolean) => { onError={(error: boolean) => {
if (error) { if (error) {
setRecipientError('Inavlid Recipient') setRecipientError('Invalid Recipient')
} else { } else {
setRecipientError(null) setRecipientError(null)
} }
...@@ -1054,10 +1107,13 @@ function ExchangePage({ sendingInput = false, history }) { ...@@ -1054,10 +1107,13 @@ function ExchangePage({ sendingInput = false, history }) {
/> />
</AutoColumn> </AutoColumn>
)} )}
</AutoColumn>
<BottomGrouping>
{noRoute ? ( {noRoute ? (
<RowBetween style={{ margin: '10px 0' }}> <GreyCard style={{ textAlign: 'center' }}>
{/* <RowBetween style={{ margin: '10px 0' }}> */}
<TYPE.main>No exchange for this pair.</TYPE.main> <TYPE.main>No exchange for this pair.</TYPE.main>
<Link <Link
onClick={() => { onClick={() => {
history.push('/add/' + tokens[Field.INPUT]?.address + '-' + tokens[Field.OUTPUT]?.address) history.push('/add/' + tokens[Field.INPUT]?.address + '-' + tokens[Field.OUTPUT]?.address)
...@@ -1066,7 +1122,8 @@ function ExchangePage({ sendingInput = false, history }) { ...@@ -1066,7 +1122,8 @@ function ExchangePage({ sendingInput = false, history }) {
{' '} {' '}
Create one now Create one now
</Link> </Link>
</RowBetween> {/* </RowBetween> */}
</GreyCard>
) : showOutputUnlock ? ( ) : showOutputUnlock ? (
<ButtonLight <ButtonLight
onClick={() => { onClick={() => {
...@@ -1074,7 +1131,11 @@ function ExchangePage({ sendingInput = false, history }) { ...@@ -1074,7 +1131,11 @@ function ExchangePage({ sendingInput = false, history }) {
}} }}
disabled={pendingApprovalOutput} disabled={pendingApprovalOutput}
> >
{pendingApprovalOutput ? 'Waiting for unlock' : 'Unlock ' + tokens[Field.OUTPUT]?.symbol} {pendingApprovalOutput ? (
<Dots>Unlocking {tokens[Field.OUTPUT]?.symbol}</Dots>
) : (
'Unlock ' + tokens[Field.OUTPUT]?.symbol
)}
</ButtonLight> </ButtonLight>
) : showInputUnlock ? ( ) : showInputUnlock ? (
<ButtonLight <ButtonLight
...@@ -1083,9 +1144,11 @@ function ExchangePage({ sendingInput = false, history }) { ...@@ -1083,9 +1144,11 @@ function ExchangePage({ sendingInput = false, history }) {
}} }}
disabled={pendingApprovalInput} disabled={pendingApprovalInput}
> >
{!pendingApprovalInput && pendingApprovalInput {pendingApprovalInput ? (
? 'Waiting for unlock' <Dots>Unlocking {tokens[Field.INPUT]?.symbol}</Dots>
: 'Unlock ' + tokens[Field.INPUT]?.symbol} ) : (
'Unlock ' + tokens[Field.INPUT]?.symbol
)}
</ButtonLight> </ButtonLight>
) : ( ) : (
<ButtonError <ButtonError
...@@ -1116,12 +1179,17 @@ function ExchangePage({ sendingInput = false, history }) { ...@@ -1116,12 +1179,17 @@ function ExchangePage({ sendingInput = false, history }) {
</Text> </Text>
</ButtonError> </ButtonError>
)} )}
</AutoColumn> </BottomGrouping>
<FixedBottom> <FixedBottom>
<AutoColumn gap="20px"> {!noRoute && tokens[Field.OUTPUT] && (
<GreyCard pt={2} mb={2}>
<PriceBar />
</GreyCard>
)}
<AutoColumn gap="lg">
{importedTokenInput && ( {importedTokenInput && (
<YellowCard> <YellowCard style={{ paddingTop: '1rem' }}>
<AutoColumn gap="10px"> <AutoColumn gap="sm">
<TYPE.mediumHeader>Token imported via address</TYPE.mediumHeader> <TYPE.mediumHeader>Token imported via address</TYPE.mediumHeader>
<AutoRow gap="4px"> <AutoRow gap="4px">
<TokenLogo address={tokens[Field.INPUT]?.address || ''} /> <TokenLogo address={tokens[Field.INPUT]?.address || ''} />
...@@ -1129,6 +1197,7 @@ function ExchangePage({ sendingInput = false, history }) { ...@@ -1129,6 +1197,7 @@ function ExchangePage({ sendingInput = false, history }) {
<Link href={getEtherscanLink(chainId, tokens[Field.INPUT]?.address, 'address')}> <Link href={getEtherscanLink(chainId, tokens[Field.INPUT]?.address, 'address')}>
(View on Etherscan) (View on Etherscan)
</Link> </Link>
<Copy size={'16'} />
</AutoRow> </AutoRow>
<TYPE.subHeader> <TYPE.subHeader>
Please verify the legitimacy of this token before making any transactions. Please verify the legitimacy of this token before making any transactions.
...@@ -1137,8 +1206,8 @@ function ExchangePage({ sendingInput = false, history }) { ...@@ -1137,8 +1206,8 @@ function ExchangePage({ sendingInput = false, history }) {
</YellowCard> </YellowCard>
)} )}
{importedTokenOutput && ( {importedTokenOutput && (
<YellowCard> <YellowCard style={{ paddingTop: '1rem' }}>
<AutoColumn gap="10px"> <AutoColumn gap="sm">
<TYPE.mediumHeader>Token imported via address</TYPE.mediumHeader> <TYPE.mediumHeader>Token imported via address</TYPE.mediumHeader>
<AutoRow gap="4px"> <AutoRow gap="4px">
<TokenLogo address={tokens[Field.OUTPUT]?.address || ''} /> <TokenLogo address={tokens[Field.OUTPUT]?.address || ''} />
...@@ -1154,8 +1223,8 @@ function ExchangePage({ sendingInput = false, history }) { ...@@ -1154,8 +1223,8 @@ function ExchangePage({ sendingInput = false, history }) {
</YellowCard> </YellowCard>
)} )}
{warningHigh && ( {warningHigh && (
<GreyCard> <GreyCard style={{ paddingTop: '1rem' }}>
<AutoColumn gap="12px"> <AutoColumn gap="md" mt={2}>
<RowBetween> <RowBetween>
<Text fontWeight={500}>Slippage Warning</Text> <Text fontWeight={500}>Slippage Warning</Text>
<QuestionHelper text="" /> <QuestionHelper text="" />
......
...@@ -3,30 +3,36 @@ import styled from 'styled-components' ...@@ -3,30 +3,36 @@ import styled from 'styled-components'
import Row from '../Row' import Row from '../Row'
import Menu from '../Menu' import Menu from '../Menu'
import Logo from '../../assets/svg/logo.svg'
import Card, { YellowCard } from '../Card'
import Web3Status from '../Web3Status'
import { X } from 'react-feather'
import { Link } from '../../theme' import { Link } from '../../theme'
import { Text } from 'rebass' import { Text } from 'rebass'
import { AutoColumn } from '../Column' import { YellowCard } from '../Card'
import Web3Status from '../Web3Status'
import { WETH } from '@uniswap/sdk' import { WETH } from '@uniswap/sdk'
import { isMobile } from 'react-device-detect' import { isMobile } from 'react-device-detect'
import { useWeb3React } from '../../hooks' import { useWeb3React } from '../../hooks'
import { useAddressBalance } from '../../contexts/Balances' import { useAddressBalance } from '../../contexts/Balances'
import { useWalletModalToggle, usePopups } from '../../contexts/Application' import { useWalletModalToggle } from '../../contexts/Application'
import Logo from '../../assets/svg/logo.svg'
import Wordmark from '../../assets/svg/wordmark.svg'
const HeaderFrame = styled.div` const HeaderFrame = styled.div`
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
width: 100%; width: 100%;
position: absolute;
padding: 0 10px;
width: calc(100% - 20px);
${({ theme }) => theme.mediaWidth.upToExtraSmall`
padding: 10px;
width: calc(100% - 20px);
`};
` `
const HeaderElement = styled.div` const HeaderElement = styled.div`
margin: 1.25rem;
display: flex; display: flex;
min-width: 0; min-width: 0;
display: flex; display: flex;
...@@ -42,22 +48,22 @@ const Title = styled.div` ...@@ -42,22 +48,22 @@ const Title = styled.div`
} }
` `
const TitleText = styled.div` const TitleText = styled(Row)`
font-size: 24px; width: fit-content;
font-weight: 700; white-space: nowrap;
color: ${({ theme }) => theme.black}; ${({ theme }) => theme.mediaWidth.upToExtraSmall`
margin-left: 12px; display: none;
`};
` `
const AccountElement = styled.div` const AccountElement = styled.div`
display: flex; display: flex;
min-width: 0;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
background-color: ${({ theme, active }) => (!active ? theme.white : theme.bg3)}; background-color: ${({ theme, active }) => (!active ? theme.white : theme.bg3)};
border: 1px solid ${({ theme }) => theme.bg3}; border: 1px solid ${({ theme }) => theme.bg3};
border-radius: 8px; border-radius: 12px;
padding-left: ${({ active }) => (active ? '8px' : 0)}; padding-left: ${({ active }) => (active ? '8px' : 0)};
white-space: nowrap; white-space: nowrap;
...@@ -66,27 +72,21 @@ const AccountElement = styled.div` ...@@ -66,27 +72,21 @@ const AccountElement = styled.div`
} }
` `
const FixedPopupColumn = styled(AutoColumn)` const TestnetWrapper = styled.div`
position: absolute; white-space: nowrap;
top: 80px; width: fit-content;
right: 20px margin-left: 10px;
width: 380px;
`
const StyledClose = styled(X)`
position: absolute;
right: 10px;
:hover { ${({ theme }) => theme.mediaWidth.upToSmall`
cursor: pointer; display: none;
} `};
` `
const Popup = styled(Card)` const NetworkCard = styled(YellowCard)`
z-index: 9999; width: fit-content;
border-radius: 8px; margin-right: 10px;
padding: 1rem; border-radius: 12px;
background-color: white; padding: 8px 12px;
` `
export default function Header() { export default function Header() {
...@@ -95,8 +95,6 @@ export default function Header() { ...@@ -95,8 +95,6 @@ export default function Header() {
const userEthBalance = useAddressBalance(account, WETH[chainId]) const userEthBalance = useAddressBalance(account, WETH[chainId])
const toggleWalletModal = useWalletModalToggle() const toggleWalletModal = useWalletModalToggle()
const [activePopups, , removePopup] = usePopups()
return ( return (
<HeaderFrame> <HeaderFrame>
<HeaderElement> <HeaderElement>
...@@ -104,54 +102,35 @@ export default function Header() { ...@@ -104,54 +102,35 @@ export default function Header() {
<Link id="link" href="https://uniswap.io"> <Link id="link" href="https://uniswap.io">
<img src={Logo} alt="logo" /> <img src={Logo} alt="logo" />
</Link> </Link>
<Link id="link" href="https://uniswap.io"> {!isMobile && (
<TitleText>Uniswap</TitleText> <TitleText>
</Link> <Link id="link" href="https://uniswap.io">
<img style={{ marginLeft: '4px' }} src={Wordmark} alt="logo" />
</Link>
<p style={{ opacity: 0.6, marginLeft: '4px', fontSize: '16px' }}>{'/ Exchange'}</p>
</TitleText>
)}
</Title> </Title>
</HeaderElement> </HeaderElement>
<HeaderElement> <HeaderElement>
<TestnetWrapper>
{!isMobile && chainId === 4 && <NetworkCard>Rinkeby Testnet</NetworkCard>}
{!isMobile && chainId === 3 && <NetworkCard> Ropsten Testnet</NetworkCard>}
{!isMobile && chainId === 5 && <NetworkCard>Goerli Testnet</NetworkCard>}
{!isMobile && chainId === 42 && <NetworkCard>Kovan Testnet</NetworkCard>}
</TestnetWrapper>
<AccountElement active={!!account}> <AccountElement active={!!account}>
{!isMobile && account ? ( {account ? (
<Row style={{ marginRight: '-1.25rem', paddingRight: '1.75rem' }}> <Row style={{ marginRight: '-1.25rem', paddingRight: '1.75rem' }}>
<Text fontWeight={500}> {userEthBalance && userEthBalance?.toFixed(4) + ' ETH'}</Text> <Text fontWeight={400}> {userEthBalance && userEthBalance?.toFixed(4) + ' ETH'}</Text>
</Row> </Row>
) : ( ) : (
'' ''
)} )}
<Web3Status onClick={toggleWalletModal} /> <Web3Status onClick={toggleWalletModal} />
</AccountElement> </AccountElement>
{chainId === 4 && (
<YellowCard style={{ width: 'fit-content', marginLeft: '10px' }} padding={'6px'}>
Rinkeby Testnet
</YellowCard>
)}
{chainId === 3 && (
<YellowCard style={{ width: 'fit-content', marginLeft: '10px' }} padding={'6px'}>
Ropsten Testnet
</YellowCard>
)}
{chainId === 5 && (
<YellowCard style={{ width: 'fit-content', marginLeft: '10px' }} padding={'6px'}>
Goerli Testnet
</YellowCard>
)}
{chainId === 42 && (
<YellowCard style={{ width: 'fit-content', marginLeft: '10px' }} padding={'6px'}>
Kovan Testnet
</YellowCard>
)}
<Menu /> <Menu />
</HeaderElement> </HeaderElement>
<FixedPopupColumn gap="20px">
{activePopups.map(item => {
return (
<Popup key={item.key}>
<StyledClose color="#888D9B" onClick={() => removePopup(item.key)} />
{item.content}
</Popup>
)
})}
</FixedPopupColumn>
</HeaderFrame> </HeaderFrame>
) )
} }
...@@ -36,8 +36,9 @@ const StyledMenuButton = styled.button` ...@@ -36,8 +36,9 @@ const StyledMenuButton = styled.button`
} }
svg { svg {
width: 25px; margin-top: 2px;
height: 24px; /* width: 25px;
height: 24px; */
} }
` `
...@@ -65,11 +66,11 @@ const MenuFlyout = styled.span` ...@@ -65,11 +66,11 @@ const MenuFlyout = styled.span`
position: absolute; position: absolute;
top: 3rem; top: 3rem;
right: 0rem; right: 0rem;
z-index: 100;
` `
const MenuItem = styled(Link)` const MenuItem = styled(Link)`
flex: 1; flex: 1;
/* text-align: right; */
padding: 0.5rem 0.5rem; padding: 0.5rem 0.5rem;
color: ${({ theme }) => theme.text3}; color: ${({ theme }) => theme.text3};
:hover { :hover {
......
...@@ -4,9 +4,10 @@ import { darken } from 'polished' ...@@ -4,9 +4,10 @@ import { darken } from 'polished'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { withRouter, NavLink, Link as HistoryLink } from 'react-router-dom' import { withRouter, NavLink, Link as HistoryLink } from 'react-router-dom'
import QuestionHelper from '../Question' import { Hover } from '../../theme'
import { ArrowLeft } from 'react-feather' import { ArrowLeft } from 'react-feather'
import { RowBetween } from '../Row' import { RowBetween } from '../Row'
import QuestionHelper from '../Question'
import { useBodyKeyDown } from '../../hooks' import { useBodyKeyDown } from '../../hooks'
...@@ -31,7 +32,6 @@ const tabOrder = [ ...@@ -31,7 +32,6 @@ const tabOrder = [
const Tabs = styled.div` const Tabs = styled.div`
${({ theme }) => theme.flexRowNoWrap} ${({ theme }) => theme.flexRowNoWrap}
align-items: center; align-items: center;
height: 3rem;
border-radius: 3rem; border-radius: 3rem;
margin-bottom: 20px; margin-bottom: 20px;
` `
...@@ -44,7 +44,7 @@ const StyledNavLink = styled(NavLink).attrs({ ...@@ -44,7 +44,7 @@ const StyledNavLink = styled(NavLink).attrs({
${({ theme }) => theme.flexRowNoWrap} ${({ theme }) => theme.flexRowNoWrap}
align-items: center; align-items: center;
justify-content: center; justify-content: center;
height: 2.5rem; height: 3rem;
flex: 1 0 auto; flex: 1 0 auto;
border-radius: 3rem; border-radius: 3rem;
outline: none; outline: none;
...@@ -55,7 +55,7 @@ const StyledNavLink = styled(NavLink).attrs({ ...@@ -55,7 +55,7 @@ const StyledNavLink = styled(NavLink).attrs({
box-sizing: border-box; box-sizing: border-box;
&.${activeClassName} { &.${activeClassName} {
border-radius: 3rem; border-radius: 12px;
box-sizing: border-box; box-sizing: border-box;
font-weight: 500; font-weight: 500;
color: ${({ theme }) => theme.black}; color: ${({ theme }) => theme.black};
...@@ -99,15 +99,16 @@ function NavigationTabs({ location: { pathname }, history }) { ...@@ -99,15 +99,16 @@ function NavigationTabs({ location: { pathname }, history }) {
const adding = pathname.match('/add') const adding = pathname.match('/add')
const removing = pathname.match('/remove') const removing = pathname.match('/remove')
const finding = pathname.match('/find') const finding = pathname.match('/find')
const creating = pathname.match('/create')
return ( return (
<> <>
{adding || removing ? ( {adding || removing ? (
<Tabs> <Tabs>
<RowBetween style={{ padding: '1rem' }}> <RowBetween style={{ padding: '1rem' }}>
<HistoryLink to="/pool"> <Hover onClick={() => history.goBack()}>
<ArrowLink /> <ArrowLink />
</HistoryLink> </Hover>
<ActiveText>{adding ? 'Add' : 'Remove'} Liquidity</ActiveText> <ActiveText>{adding ? 'Add' : 'Remove'} Liquidity</ActiveText>
<QuestionHelper text={'helper text'} /> <QuestionHelper text={'helper text'} />
</RowBetween> </RowBetween>
...@@ -118,7 +119,17 @@ function NavigationTabs({ location: { pathname }, history }) { ...@@ -118,7 +119,17 @@ function NavigationTabs({ location: { pathname }, history }) {
<HistoryLink to="/pool"> <HistoryLink to="/pool">
<ArrowLink /> <ArrowLink />
</HistoryLink> </HistoryLink>
<ActiveText>Find a Pool</ActiveText> <ActiveText>Import Pool</ActiveText>
<QuestionHelper text={'helper text'} />
</RowBetween>
</Tabs>
) : creating ? (
<Tabs>
<RowBetween style={{ padding: '1rem' }}>
<HistoryLink to="/pool">
<ArrowLink />
</HistoryLink>
<ActiveText>Create Pool</ActiveText>
<QuestionHelper text={'helper text'} /> <QuestionHelper text={'helper text'} />
</RowBetween> </RowBetween>
</Tabs> </Tabs>
......
...@@ -3,10 +3,11 @@ import styled from 'styled-components' ...@@ -3,10 +3,11 @@ import styled from 'styled-components'
const StyledInput = styled.input` const StyledInput = styled.input`
color: ${({ error, theme }) => error && theme.red1}; color: ${({ error, theme }) => error && theme.red1};
background-color: ${({ theme }) => theme.bg1};
color: ${({ theme }) => theme.text1}; color: ${({ theme }) => theme.text1};
width: 0; width: 0;
font-size: 20px; font-size: 24px;
font-weight: 500;
font-family: 'Inter', sans-serif;
outline: none; outline: none;
border: none; border: none;
flex: 1 1 auto; flex: 1 1 auto;
......
import React, { useState } from 'react' import React, { useState, useEffect } from 'react'
import { withRouter } from 'react-router-dom' import { withRouter } from 'react-router-dom'
import { TokenAmount, JSBI, Token, Pair } from '@uniswap/sdk' import { TokenAmount, JSBI, Token, Pair } from '@uniswap/sdk'
...@@ -14,11 +14,12 @@ import { LightCard } from '../Card' ...@@ -14,11 +14,12 @@ import { LightCard } from '../Card'
import { AutoColumn, ColumnCenter } from '../Column' import { AutoColumn, ColumnCenter } from '../Column'
import { ButtonPrimary, ButtonDropwdown, ButtonDropwdownLight } from '../Button' import { ButtonPrimary, ButtonDropwdown, ButtonDropwdownLight } from '../Button'
import { usePair } from '../../contexts/Pairs'
import { useToken } from '../../contexts/Tokens' import { useToken } from '../../contexts/Tokens'
import { usePopups } from '../../contexts/Application' import { usePopups } from '../../contexts/Application'
import { usePrevious } from '../../hooks'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import { useAddressBalance } from '../../contexts/Balances' import { useAddressBalance } from '../../contexts/Balances'
import { usePair, useAllPairs } from '../../contexts/Pairs'
function PoolFinder({ history }) { function PoolFinder({ history }) {
const Fields = { const Fields = {
...@@ -44,21 +45,45 @@ function PoolFinder({ history }) { ...@@ -44,21 +45,45 @@ function PoolFinder({ history }) {
const newPair: boolean = pair && JSBI.equal(pair.reserve0.raw, JSBI.BigInt(0)) const newPair: boolean = pair && JSBI.equal(pair.reserve0.raw, JSBI.BigInt(0))
const allowImport: boolean = position && JSBI.greaterThan(position.raw, JSBI.BigInt(0)) const allowImport: boolean = position && JSBI.greaterThan(position.raw, JSBI.BigInt(0))
const allPairs = useAllPairs()
const pairCount = Object.keys(allPairs)?.length
const pairCountPrevious = usePrevious(pairCount)
const [newLiquidity, setNewLiquidity] = useState<boolean>(false) // check for unimported pair
// use previous ref to detect new pair added
useEffect(() => {
if (pairCount !== pairCountPrevious && pairCountPrevious) {
setNewLiquidity(true)
}
}, [pairCount, pairCountPrevious])
// reset the watcher if tokens change
useEffect(() => {
setNewLiquidity(false)
}, [token0, token1])
function endSearch() { function endSearch() {
history.goBack() // return to previous page history.goBack() // return to previous page
addPopup( newLiquidity &&
<Row> addPopup(
<DoubleTokenLogo a0={token0Address || ''} a1={token1Address || ''} margin={true} /> <AutoColumn gap={'10px'}>
<Text color="grey"> <Text fontSize={20} fontWeight={500}>
UNI {token0?.symbol} / {token1?.symbol} pool imported. Pool Imported
</Text> </Text>
</Row> <Row>
) <DoubleTokenLogo a0={token0Address || ''} a1={token1Address || ''} margin={true} />
<Text fontSize={16} fotnWeight={500}>
UNI {token0?.symbol} / {token1?.symbol}
</Text>
</Row>
<Link>View on Uniswap Info.</Link>
</AutoColumn>
)
} }
return ( return (
<> <>
<AutoColumn gap="24px"> <AutoColumn gap="md">
{!token0Address ? ( {!token0Address ? (
<ButtonDropwdown <ButtonDropwdown
onClick={() => { onClick={() => {
...@@ -111,9 +136,12 @@ function PoolFinder({ history }) { ...@@ -111,9 +136,12 @@ function PoolFinder({ history }) {
</ButtonDropwdownLight> </ButtonDropwdownLight>
)} )}
{allowImport && ( {allowImport && (
<ColumnCenter justify="center" style={{ backgroundColor: '#EBF4FF', padding: '8px', borderRadius: '12px' }}> <ColumnCenter
justify="center"
style={{ backgroundColor: '#EBF4FF', padding: '12px 0px', borderRadius: '12px' }}
>
<Text textAlign="center" fontWeight={500} color="#2172E5"> <Text textAlign="center" fontWeight={500} color="#2172E5">
Liquidity Found! {newLiquidity ? 'Pool Found!' : 'Pool already imported.'}
</Text> </Text>
</ColumnCenter> </ColumnCenter>
)} )}
...@@ -128,7 +156,7 @@ function PoolFinder({ history }) { ...@@ -128,7 +156,7 @@ function PoolFinder({ history }) {
/> />
) : ( ) : (
<LightCard padding="45px"> <LightCard padding="45px">
<AutoColumn gap="8px" justify="center"> <AutoColumn gap="sm" justify="center">
<Text color="">No position found.</Text> <Text color="">No position found.</Text>
<Link <Link
onClick={() => { onClick={() => {
...@@ -142,14 +170,14 @@ function PoolFinder({ history }) { ...@@ -142,14 +170,14 @@ function PoolFinder({ history }) {
) )
) : newPair ? ( ) : newPair ? (
<LightCard padding="45px"> <LightCard padding="45px">
<AutoColumn gap="8px" justify="center"> <AutoColumn gap="sm" justify="center">
<Text color="">No exchange found.</Text> <Text color="">No pool found.</Text>
<Link <Link
onClick={() => { onClick={() => {
history.push('/add/' + token0Address + '-' + token1Address) history.push('/add/' + token0Address + '-' + token1Address)
}} }}
> >
Create exchange instead. Create pool instead.
</Link> </Link>
</AutoColumn> </AutoColumn>
</LightCard> </LightCard>
...@@ -163,7 +191,7 @@ function PoolFinder({ history }) { ...@@ -163,7 +191,7 @@ function PoolFinder({ history }) {
<ButtonPrimary disabled={!allowImport} onClick={endSearch}> <ButtonPrimary disabled={!allowImport} onClick={endSearch}>
<Text fontWeight={500} fontSize={20}> <Text fontWeight={500} fontSize={20}>
Import {newLiquidity ? 'Import' : 'Close'}
</Text> </Text>
</ButtonPrimary> </ButtonPrimary>
</AutoColumn> </AutoColumn>
......
import React from 'react'
import styled from 'styled-components'
import { useMediaLayout } from 'use-media'
import { X } from 'react-feather'
import { Text } from 'rebass'
import { TYPE } from '../../theme'
import { Hover } from '../../theme/components'
import { PinkCard } from '../Card'
import { ButtonPink } from '../Button'
import { usePopups } from '../../contexts/Application'
import { AutoColumn } from '../Column'
import { useMigrationMessageManager } from '../../contexts/LocalStorage'
const StyledClose = styled(X)`
position: absolute;
right: 10px;
top: 10px;
:hover {
cursor: pointer;
}
`
const MobilePopupWrapper = styled.div`
position: relative;
max-width: 100%;
height: ${({ height }) => height}
margin: ${({ height }) => (height ? '0 auto;' : 0)}
margin-bottom: ${({ height }) => (height ? '20px' : 0)}}
`
const MobilePopupInner = styled.div`
height: 99%;
box-sizing: border-box;
white-space: nowrap;
overflow-x: auto;
overflow-y: hidden;
display: flex;
flex-direction: row;
-webkit-overflow-scrolling: touch;
::-webkit-scrollbar {
display: none;
}
`
const FixedPopupColumn = styled(AutoColumn)`
position: absolute;
top: 80px;
right: 20px
width: 380px;
${({ theme }) => theme.mediaWidth.upToSmall`
display: none;
`};
`
const Popup = styled.div`
display: inline-block;
width: 100%;
height: 120px;
padding: 1em;
box-sizing: border-box;
background-color: white;
margin: 0 10px;
position: relative;
border-radius: 10px;
padding: 20px;
padding-right: 35px;
whitespace: normal;
${({ theme }) => theme.mediaWidth.upToSmall`
min-width: 290px;
`}
`
const MobileCardPink = styled(PinkCard)`
z-index: 2;
padding: 20px;
white-space: normal;
`
export default function App() {
// get all popups
const [activePopups, , removePopup] = usePopups()
// local storage reference to show message
const [showMessage, hideMigrationMessage] = useMigrationMessageManager()
// switch view settings on mobile
const isMobile = useMediaLayout({ maxWidth: '600px' })
if (!isMobile) {
return (
<FixedPopupColumn gap="20px">
{activePopups.map(item => {
return (
<Popup key={item.key}>
<StyledClose color="#888D9B" onClick={() => removePopup(item.key)} />
{item.content}
</Popup>
)
})}
{showMessage && (
<PinkCard padding="20px" style={{ zIndex: '2' }}>
<AutoColumn justify={'center'} gap={'20px'}>
<TYPE.largeHeader>Uniswap has upgraded.</TYPE.largeHeader>
<Text textAlign="center">Are you a liquidity provider? Upgrade now using the migration helper.</Text>
<ButtonPink width={'265px'}>Migrate your liquidity </ButtonPink>
<Hover onClick={() => hideMigrationMessage()}>
<Text textAlign="center">Dismiss</Text>
</Hover>
</AutoColumn>
</PinkCard>
)}
</FixedPopupColumn>
)
}
//mobile
else
return (
<MobilePopupWrapper height={activePopups?.length > 0 || showMessage ? 'fit-content' : 0}>
<MobilePopupInner>
{activePopups // reverse so new items up front
.slice(0)
.reverse()
.map(item => {
return (
<Popup key={item.key}>
<StyledClose color="#888D9B" onClick={() => removePopup(item.key)} />
{item.content}
</Popup>
)
})}
{showMessage && (
<MobileCardPink>
<AutoColumn justify={'center'} gap={'20px'}>
<Text>Uniswap has upgraded.</Text>
<Text textAlign="center">Are you a liquidity provider? Upgrade now using the migration helper.</Text>
<ButtonPink width={'265px'}>Migrate your liquidity </ButtonPink>
<Hover onClick={() => hideMigrationMessage()}>
<Text textAlign="center">Dismiss</Text>
</Hover>
</AutoColumn>
</MobileCardPink>
)}
</MobilePopupInner>
</MobilePopupWrapper>
)
}
...@@ -51,27 +51,32 @@ function PositionCard({ pairAddress, token0, token1, history, minimal = false, . ...@@ -51,27 +51,32 @@ function PositionCard({ pairAddress, token0, token1, history, minimal = false, .
token0 && token0 &&
totalPoolTokens && totalPoolTokens &&
userPoolBalance && userPoolBalance &&
pair &&
totalPoolTokens &&
pair.liquidityToken.equals(totalPoolTokens.token) &&
pair.getLiquidityValue(token0, totalPoolTokens, userPoolBalance, false) pair.getLiquidityValue(token0, totalPoolTokens, userPoolBalance, false)
const token1Deposited = const token1Deposited =
token1 && token1 &&
totalPoolTokens && totalPoolTokens &&
userPoolBalance && userPoolBalance &&
totalPoolTokens &&
pair.liquidityToken.equals(totalPoolTokens.token) &&
pair.getLiquidityValue(token1, totalPoolTokens, userPoolBalance, false) pair.getLiquidityValue(token1, totalPoolTokens, userPoolBalance, false)
if (minimal) { if (minimal) {
return ( return (
<GreyCard {...rest}> <GreyCard {...rest}>
<AutoColumn gap="20px"> <AutoColumn gap="12px">
<FixedHeightRow> <FixedHeightRow>
<RowFixed> <RowFixed>
<Text fontWeight={500} fontSize={20}> <Text fontWeight={500} fontSize={16}>
Current Position Your current position
</Text> </Text>
</RowFixed> </RowFixed>
</FixedHeightRow> </FixedHeightRow>
<FixedHeightRow onClick={() => setShowMore(!showMore)}> <FixedHeightRow onClick={() => setShowMore(!showMore)}>
<RowFixed> <RowFixed>
<DoubleLogo a0={token0?.address || ''} a1={token1?.address || ''} margin={true} size={24} /> <DoubleLogo a0={token0?.address || ''} a1={token1?.address || ''} margin={true} size={20} />
<Text fontWeight={500} fontSize={20}> <Text fontWeight={500} fontSize={20}>
{token0?.symbol}:{token1?.symbol} {token0?.symbol}:{token1?.symbol}
</Text> </Text>
...@@ -82,15 +87,15 @@ function PositionCard({ pairAddress, token0, token1, history, minimal = false, . ...@@ -82,15 +87,15 @@ function PositionCard({ pairAddress, token0, token1, history, minimal = false, .
</Text> </Text>
</RowFixed> </RowFixed>
</FixedHeightRow> </FixedHeightRow>
<AutoColumn gap="12px"> <AutoColumn gap="4px">
<FixedHeightRow> <FixedHeightRow>
<Text color="#888D9B" fontSize={16} fontWeight={500}> <Text color="#888D9B" fontSize={14} fontWeight={500}>
{token0?.symbol}: {token0?.symbol}:
</Text> </Text>
{token0Deposited ? ( {token0Deposited ? (
<RowFixed> <RowFixed>
{!minimal && <TokenLogo address={token0?.address || ''} />} {!minimal && <TokenLogo address={token0?.address || ''} />}
<Text color="#888D9B" fontSize={16} fontWeight={500} marginLeft={'6px'}> <Text color="#888D9B" fontSize={14} fontWeight={500} marginLeft={'6px'}>
{token0Deposited?.toFixed(8)} {token0Deposited?.toFixed(8)}
</Text> </Text>
</RowFixed> </RowFixed>
...@@ -99,13 +104,13 @@ function PositionCard({ pairAddress, token0, token1, history, minimal = false, . ...@@ -99,13 +104,13 @@ function PositionCard({ pairAddress, token0, token1, history, minimal = false, .
)} )}
</FixedHeightRow> </FixedHeightRow>
<FixedHeightRow> <FixedHeightRow>
<Text color="#888D9B" fontSize={16} fontWeight={500}> <Text color="#888D9B" fontSize={14} fontWeight={500}>
{token1?.symbol}: {token1?.symbol}:
</Text> </Text>
{token1Deposited ? ( {token1Deposited ? (
<RowFixed> <RowFixed>
{!minimal && <TokenLogo address={token1?.address || ''} />} {!minimal && <TokenLogo address={token1?.address || ''} />}
<Text color="#888D9B" fontSize={16} fontWeight={500} marginLeft={'6px'}> <Text color="#888D9B" fontSize={14} fontWeight={500} marginLeft={'6px'}>
{token1Deposited?.toFixed(8)} {token1Deposited?.toFixed(8)}
</Text> </Text>
</RowFixed> </RowFixed>
...@@ -120,10 +125,10 @@ function PositionCard({ pairAddress, token0, token1, history, minimal = false, . ...@@ -120,10 +125,10 @@ function PositionCard({ pairAddress, token0, token1, history, minimal = false, .
} else } else
return ( return (
<HoverCard {...rest} onClick={() => setShowMore(!showMore)}> <HoverCard {...rest} onClick={() => setShowMore(!showMore)}>
<AutoColumn gap="20px"> <AutoColumn gap="12px">
<FixedHeightRow> <FixedHeightRow>
<RowFixed> <RowFixed>
<DoubleLogo a0={token0?.address || ''} a1={token1?.address || ''} margin={true} size={24} /> <DoubleLogo a0={token0?.address || ''} a1={token1?.address || ''} margin={true} size={20} />
<Text fontWeight={500} fontSize={20}> <Text fontWeight={500} fontSize={20}>
{token0?.symbol}:{token1?.symbol} {token0?.symbol}:{token1?.symbol}
</Text> </Text>
...@@ -140,15 +145,18 @@ function PositionCard({ pairAddress, token0, token1, history, minimal = false, . ...@@ -140,15 +145,18 @@ function PositionCard({ pairAddress, token0, token1, history, minimal = false, .
</RowFixed> </RowFixed>
</FixedHeightRow> </FixedHeightRow>
{showMore && ( {showMore && (
<AutoColumn gap="12px"> <AutoColumn gap="4px">
<FixedHeightRow> <FixedHeightRow>
<Text color="#888D9B" fontSize={16} fontWeight={500}> <RowFixed>
{token0?.symbol}: {!minimal && <TokenLogo size="16px" style={{ marginRight: '4px' }} address={token0?.address || ''} />}
</Text>
<Text color="#888D9B" fontSize={14} fontWeight={500}>
{token0?.symbol}:
</Text>
</RowFixed>
{token0Deposited ? ( {token0Deposited ? (
<RowFixed> <RowFixed>
{!minimal && <TokenLogo address={token0?.address || ''} />} <Text color="#888D9B" fontSize={14} fontWeight={500} marginLeft={'6px'}>
<Text color="#888D9B" fontSize={16} fontWeight={500} marginLeft={'6px'}>
{token0Deposited?.toFixed(8)} {token0Deposited?.toFixed(8)}
</Text> </Text>
</RowFixed> </RowFixed>
...@@ -157,26 +165,26 @@ function PositionCard({ pairAddress, token0, token1, history, minimal = false, . ...@@ -157,26 +165,26 @@ function PositionCard({ pairAddress, token0, token1, history, minimal = false, .
)} )}
</FixedHeightRow> </FixedHeightRow>
<FixedHeightRow> <FixedHeightRow>
<Text color="#888D9B" fontSize={16} fontWeight={500}> <RowFixed>
{token1?.symbol}: {!minimal && <TokenLogo size="16px" style={{ marginRight: '4px' }} address={token1?.address || ''} />}
</Text> <Text color="#888D9B" fontSize={14} fontWeight={500}>
{token1?.symbol}:
</Text>
</RowFixed>
{token1Deposited ? ( {token1Deposited ? (
<RowFixed> <Text color="#888D9B" fontSize={14} fontWeight={500} marginLeft={'6px'}>
{!minimal && <TokenLogo address={token1?.address || ''} />} {token1Deposited?.toFixed(8)}
<Text color="#888D9B" fontSize={16} fontWeight={500} marginLeft={'6px'}> </Text>
{token1Deposited?.toFixed(8)}
</Text>
</RowFixed>
) : ( ) : (
'-' '-'
)} )}
</FixedHeightRow> </FixedHeightRow>
{!minimal && ( {!minimal && (
<FixedHeightRow> <FixedHeightRow>
<Text color="#888D9B" fontSize={16} fontWeight={500}> <Text color="#888D9B" fontSize={14} fontWeight={500}>
Your pool share: Your pool share:
</Text> </Text>
<Text color="#888D9B" fontSize={16} fontWeight={500}> <Text color="#888D9B" fontSize={14} fontWeight={500}>
{poolTokenPercentage ? poolTokenPercentage.toFixed(2) + '%' : '-'} {poolTokenPercentage ? poolTokenPercentage.toFixed(2) + '%' : '-'}
</Text> </Text>
</FixedHeightRow> </FixedHeightRow>
......
import styled from 'styled-components' import styled from 'styled-components'
import { Box } from 'rebass/styled-components'
const Row = styled.div` const Row = styled(Box)`
width: 100%; width: 100%;
display: flex; display: flex;
padding: 0;
align-items: center; align-items: center;
align-items: ${({ align }) => align && align}; align-items: ${({ align }) => align && align};
padding: ${({ padding }) => padding};
border: ${({ border }) => border};
border-radius: ${({ borderRadius }) => borderRadius};
` `
export const RowBetween = styled(Row)` export const RowBetween = styled(Row)`
...@@ -19,6 +24,7 @@ export const RowFlat = styled.div` ...@@ -19,6 +24,7 @@ export const RowFlat = styled.div`
export const AutoRow = styled(Row)` export const AutoRow = styled(Row)`
flex-wrap: wrap; flex-wrap: wrap;
margin: -${({ gap }) => gap}; margin: -${({ gap }) => gap};
justify-content: ${({ justify }) => justify && justify};
& > * { & > * {
margin: ${({ gap }) => gap} !important; margin: ${({ gap }) => gap} !important;
......
...@@ -9,20 +9,25 @@ import { isMobile } from 'react-device-detect' ...@@ -9,20 +9,25 @@ import { isMobile } from 'react-device-detect'
import { withRouter } from 'react-router-dom' import { withRouter } from 'react-router-dom'
import { Link as StyledLink } from '../../theme/components' import { Link as StyledLink } from '../../theme/components'
import { Hover } from '../../theme'
import Modal from '../Modal' import Modal from '../Modal'
import Circle from '../../assets/images/circle.svg' import Circle from '../../assets/images/circle.svg'
import TokenLogo from '../TokenLogo' import TokenLogo from '../TokenLogo'
import DoubleTokenLogo from '../DoubleLogo' import DoubleTokenLogo from '../DoubleLogo'
import Column, { AutoColumn } from '../Column' import Column, { AutoColumn } from '../Column'
import { Text } from 'rebass' import { Text } from 'rebass'
import { Spinner } from '../../theme' import { LightCard } from '../Card'
import { ArrowLeft } from 'react-feather'
import { CloseIcon } from '../../theme/components' import { CloseIcon } from '../../theme/components'
import { ColumnCenter } from '../../components/Column' import { ColumnCenter } from '../../components/Column'
import { Spinner, TYPE } from '../../theme'
import { ButtonSecondary } from '../Button'
import { RowBetween, RowFixed } from '../Row' import { RowBetween, RowFixed } from '../Row'
import { isAddress } from '../../utils' import { isAddress } from '../../utils'
import { useAllPairs } from '../../contexts/Pairs' import { useAllPairs } from '../../contexts/Pairs'
import { useWeb3React } from '../../hooks' import { useWeb3React } from '../../hooks'
import { useSavedTokens } from '../../contexts/LocalStorage'
import { useAllBalances } from '../../contexts/Balances' import { useAllBalances } from '../../contexts/Balances'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { useToken, useAllTokens, INITIAL_TOKENS_CONTEXT } from '../../contexts/Tokens' import { useToken, useAllTokens, INITIAL_TOKENS_CONTEXT } from '../../contexts/Tokens'
...@@ -100,7 +105,7 @@ const PaddedColumn = styled(AutoColumn)` ...@@ -100,7 +105,7 @@ const PaddedColumn = styled(AutoColumn)`
const PaddedItem = styled(RowBetween)` const PaddedItem = styled(RowBetween)`
padding: 4px 24px; padding: 4px 24px;
width: calc(100% - 48px); /* width: calc(100% - 48px); */
height: 56px; height: 56px;
` `
...@@ -148,6 +153,17 @@ function SearchModal({ ...@@ -148,6 +153,17 @@ function SearchModal({
const [activeFilter, setActiveFilter] = useState(FILTERS.BALANCES) const [activeFilter, setActiveFilter] = useState(FILTERS.BALANCES)
const [showTokenImport, setShowTokenImport] = useState(false)
const [, saveUserToken] = useSavedTokens()
// reset view on close
useEffect(() => {
if (!isOpen) {
setShowTokenImport(false)
}
}, [isOpen])
const tokenList = useMemo(() => { const tokenList = useMemo(() => {
return Object.keys(allTokens) return Object.keys(allTokens)
.sort((a, b) => { .sort((a, b) => {
...@@ -188,23 +204,35 @@ function SearchModal({ ...@@ -188,23 +204,35 @@ function SearchModal({
const filteredTokenList = useMemo(() => { const filteredTokenList = useMemo(() => {
return tokenList.filter(tokenEntry => { return tokenList.filter(tokenEntry => {
const urlAdded = urlAddedTokens && urlAddedTokens.hasOwnProperty(tokenEntry.address)
const customAdded =
tokenEntry.address !== 'ETH' &&
INITIAL_TOKENS_CONTEXT[chainId] &&
!INITIAL_TOKENS_CONTEXT[chainId].hasOwnProperty(tokenEntry.address) &&
!urlAdded
// if token import page dont show preset list, else show all
const include = !showTokenImport || (showTokenImport && customAdded && searchQuery !== '')
const inputIsAddress = searchQuery.slice(0, 2) === '0x' const inputIsAddress = searchQuery.slice(0, 2) === '0x'
const regexMatches = Object.keys(tokenEntry).map(tokenEntryKey => { const regexMatches = Object.keys(tokenEntry).map(tokenEntryKey => {
if (tokenEntryKey === 'address') { if (tokenEntryKey === 'address') {
return ( return (
include &&
inputIsAddress && inputIsAddress &&
typeof tokenEntry[tokenEntryKey] === 'string' && typeof tokenEntry[tokenEntryKey] === 'string' &&
!!tokenEntry[tokenEntryKey].match(new RegExp(escapeStringRegex(searchQuery), 'i')) !!tokenEntry[tokenEntryKey].match(new RegExp(escapeStringRegex(searchQuery), 'i'))
) )
} }
return ( return (
include &&
typeof tokenEntry[tokenEntryKey] === 'string' && typeof tokenEntry[tokenEntryKey] === 'string' &&
!!tokenEntry[tokenEntryKey].match(new RegExp(escapeStringRegex(searchQuery), 'i')) !!tokenEntry[tokenEntryKey].match(new RegExp(escapeStringRegex(searchQuery), 'i'))
) )
}) })
return regexMatches.some(m => m) return regexMatches.some(m => m)
}) })
}, [tokenList, searchQuery]) }, [tokenList, urlAddedTokens, chainId, showTokenImport, searchQuery])
function _onTokenSelect(address) { function _onTokenSelect(address) {
setSearchQuery('') setSearchQuery('')
...@@ -334,6 +362,7 @@ function SearchModal({ ...@@ -334,6 +362,7 @@ function SearchModal({
</> </>
) )
} }
if (!filteredTokenList.length) { if (!filteredTokenList.length) {
return <TokenModalInfo>{t('noToken')}</TokenModalInfo> return <TokenModalInfo>{t('noToken')}</TokenModalInfo>
} }
...@@ -348,16 +377,11 @@ function SearchModal({ ...@@ -348,16 +377,11 @@ function SearchModal({
const zeroBalance = balance && JSBI.equal(JSBI.BigInt(0), balance.raw) const zeroBalance = balance && JSBI.equal(JSBI.BigInt(0), balance.raw)
// if token import page dont show preset list, else show all
return ( return (
<MenuItem <MenuItem
key={address} key={address}
onClick={() => onClick={() => (hiddenToken && hiddenToken === address ? () => {} : _onTokenSelect(address))}
hiddenToken && hiddenToken === address
? () => {}
: zeroBalance
? _onTokenSelect(address, true)
: _onTokenSelect(address)
}
disabled={hiddenToken && hiddenToken === address} disabled={hiddenToken && hiddenToken === address}
> >
<RowFixed> <RowFixed>
...@@ -428,42 +452,108 @@ function SearchModal({ ...@@ -428,42 +452,108 @@ function SearchModal({
initialFocusRef={isMobile ? undefined : inputRef} initialFocusRef={isMobile ? undefined : inputRef}
> >
<TokenModal> <TokenModal>
<PaddedColumn gap="20px"> {showTokenImport ? (
<RowBetween> <PaddedColumn gap="20px">
<Text fontWeight={500} fontSize={16}> <RowBetween>
{filterType === 'tokens' ? 'Select A Token' : 'Select A Pool'} <RowFixed>
</Text> <Hover>
<CloseIcon onClick={onDismiss} /> <ArrowLeft
</RowBetween>
<Input
type={'text'}
placeholder={t('tokenSearchPlaceholder')}
value={searchQuery}
ref={inputRef}
onChange={onInput}
/>
<RowBetween>
<div>
{filterType !== 'tokens' && (
<Text>
Don't see a pool?{' '}
<StyledLink
onClick={() => { onClick={() => {
history.push('/find') setShowTokenImport(false)
}} }}
> />
Import it. </Hover>
</StyledLink> <Text fontWeight={500} fontSize={16} marginLeft={'10px'}>
Import A Token
</Text> </Text>
</RowFixed>
<CloseIcon onClick={onDismiss} />
</RowBetween>
<TYPE.body style={{ marginTop: '40px' }}>
To import a custom token, paste the token address in the search bar.
</TYPE.body>
<Input
type={'text'}
placeholder={t('tokenSearchPlaceholder')}
value={searchQuery}
ref={inputRef}
onChange={onInput}
/>
<LightCard padding={filteredTokenList?.length === 0 ? '20px' : '0px'}>
{filteredTokenList?.length === 0 ? (
<AutoColumn gap="8px" justify="center">
<TYPE.body color="">No token found.</TYPE.body>
</AutoColumn>
) : (
renderTokenList()
)} )}
{filterType === 'tokens' && <Text>Token Symbol</Text>} </LightCard>
</div> {filteredTokenList?.length > 0 && (
<div /> <RowBetween>
<Filter title="Your Balances" filter={FILTERS.BALANCES} /> <ButtonSecondary
</RowBetween> width="48%"
</PaddedColumn> onClick={() => {
<div style={{ width: '100%', height: '1px', backgroundColor: '#E1E1E1' }} /> const newToken = filteredTokenList?.[0]
<TokenList>{filterType === 'tokens' ? renderTokenList() : renderPairsList()}</TokenList> saveUserToken(newToken?.address)
}}
>
Save To Your List
</ButtonSecondary>
<ButtonSecondary width="48%" onClick={() => _onTokenSelect(filteredTokenList[0].address)}>
Import
</ButtonSecondary>
</RowBetween>
)}
</PaddedColumn>
) : (
<PaddedColumn gap="20px">
<RowBetween>
<Text fontWeight={500} fontSize={16}>
{filterType === 'tokens' ? 'Select A Token' : 'Select A Pool'}
</Text>
<CloseIcon onClick={onDismiss} />
</RowBetween>
<Input
type={'text'}
placeholder={t('tokenSearchPlaceholder')}
value={searchQuery}
ref={inputRef}
onChange={onInput}
/>
<RowBetween>
<div>
{filterType !== 'tokens' && (
<Text fontWeight={500}>
{!isMobile && 'Dont see a pool? '}
<StyledLink
onClick={() => {
history.push('/find')
}}
>
{!isMobile ? 'Import it.' : 'Import pool.'}
</StyledLink>
</Text>
)}
{filterType === 'tokens' && (
<Text fontWeight={500}>
{!isMobile && 'Dont see a token? '}
<StyledLink
onClick={() => {
setShowTokenImport(true)
}}
>
{!isMobile ? 'Import it.' : 'Import custom token.'}
</StyledLink>
</Text>
)}
</div>
<div />
<Filter title="Your Balances" filter={FILTERS.BALANCES} />
</RowBetween>
</PaddedColumn>
)}
{!showTokenImport && <div style={{ width: '100%', height: '1px', backgroundColor: '#E1E1E1' }} />}
{!showTokenImport && <TokenList>{filterType === 'tokens' ? renderTokenList() : renderPairsList()}</TokenList>}
</TokenModal> </TokenModal>
</Modal> </Modal>
) )
......
...@@ -17,6 +17,7 @@ const Image = styled.img` ...@@ -17,6 +17,7 @@ const Image = styled.img`
height: ${({ size }) => size}; height: ${({ size }) => size};
background-color: white; background-color: white;
border-radius: 1rem; border-radius: 1rem;
box-shadow: 0px 6px 10px rgba(0, 0, 0, 0.075);
` `
const Emoji = styled.span` const Emoji = styled.span`
......
...@@ -39,7 +39,6 @@ const Wrapper = styled.div` ...@@ -39,7 +39,6 @@ const Wrapper = styled.div`
margin: 0; margin: 0;
padding: 0; padding: 0;
width: 100%; width: 100%;
background-color: ${({ theme }) => theme.bg2};
` `
const HeaderRow = styled.div` const HeaderRow = styled.div`
...@@ -55,12 +54,14 @@ const HeaderRow = styled.div` ...@@ -55,12 +54,14 @@ const HeaderRow = styled.div`
const ContentWrapper = styled.div` const ContentWrapper = styled.div`
background-color: ${({ theme }) => theme.bg2}; background-color: ${({ theme }) => theme.bg2};
padding: 2rem; padding: 2rem;
border-bottom-left-radius: 20px;
border-bottom-right-radius: 20px;
${({ theme }) => theme.mediaWidth.upToMedium`padding: 1rem`}; ${({ theme }) => theme.mediaWidth.upToMedium`padding: 1rem`};
` `
const UpperSection = styled.div` const UpperSection = styled.div`
position: relative; position: relative;
background-color: ${({ theme }) => theme.bg1};
h5 { h5 {
margin: 0; margin: 0;
......
...@@ -2,7 +2,7 @@ import React from 'react' ...@@ -2,7 +2,7 @@ import React from 'react'
import styled, { css } from 'styled-components' import styled, { css } from 'styled-components'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { useWeb3React, UnsupportedChainIdError } from '@web3-react/core' import { useWeb3React, UnsupportedChainIdError } from '@web3-react/core'
import { darken } from 'polished' import { darken, lighten } from 'polished'
import { Activity } from 'react-feather' import { Activity } from 'react-feather'
import { shortenAddress } from '../../utils' import { shortenAddress } from '../../utils'
...@@ -21,10 +21,10 @@ import Identicon from '../Identicon' ...@@ -21,10 +21,10 @@ import Identicon from '../Identicon'
const Web3StatusGeneric = styled.button` const Web3StatusGeneric = styled.button`
${({ theme }) => theme.flexRowNoWrap} ${({ theme }) => theme.flexRowNoWrap}
width: 100%; width: 100%;
font-size: 0.9rem; /* font-size: 0.9rem; */
align-items: center; align-items: center;
padding: 0.5rem; padding: 0.5rem;
border-radius: 10px; border-radius: 12px;
box-sizing: border-box; box-sizing: border-box;
cursor: pointer; cursor: pointer;
user-select: none; user-select: none;
...@@ -72,12 +72,12 @@ const Web3StatusConnect = styled(Web3StatusGeneric)` ...@@ -72,12 +72,12 @@ const Web3StatusConnect = styled(Web3StatusGeneric)`
` `
const Web3StatusConnected = styled(Web3StatusGeneric)` const Web3StatusConnected = styled(Web3StatusGeneric)`
background-color: ${({ pending, theme }) => (pending ? theme.blue1 : theme.bg1)}; background-color: ${({ pending, theme }) => (pending ? theme.blue1 : theme.bg2)};
border: 1px solid ${({ pending, theme }) => (pending ? theme.blue1 : theme.bg3)}; border: 1px solid ${({ pending, theme }) => (pending ? theme.blue1 : theme.bg3)};
color: ${({ pending, theme }) => (pending ? theme.white : theme.text3)}; color: ${({ pending, theme }) => (pending ? theme.white : theme.text1)};
font-weight: 400; font-weight: 500;
:hover { :hover {
background-color: ${({ pending, theme }) => (pending ? darken(0.05, theme.blue1) : darken(0.05, theme.bg1))}; background-color: ${({ pending, theme }) => (pending ? darken(0.05, theme.blue1) : lighten(0.05, theme.bg2))};
:focus { :focus {
border: 1px solid ${({ pending, theme }) => (pending ? darken(0.1, theme.blue1) : darken(0.1, theme.bg3))}; border: 1px solid ${({ pending, theme }) => (pending ? darken(0.1, theme.blue1) : darken(0.1, theme.bg3))};
...@@ -91,7 +91,7 @@ const Text = styled.p` ...@@ -91,7 +91,7 @@ const Text = styled.p`
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
margin: 0 0.5rem 0 0.25rem; margin: 0 0.5rem 0 0.25rem;
font-size: 0.83rem; font-size: 1rem;
width: fit-content; width: fit-content;
font-weight: 500; font-weight: 500;
` `
......
import React, { createContext, useContext, useReducer, useMemo, useCallback, useEffect, useState } from 'react' import React, { createContext, useContext, useReducer, useMemo, useCallback, useEffect } from 'react'
import { useWeb3React } from '../hooks' import { useWeb3React } from '../hooks'
import { safeAccess } from '../utils' import { safeAccess } from '../utils'
...@@ -7,6 +7,7 @@ const BLOCK_NUMBER = 'BLOCK_NUMBER' ...@@ -7,6 +7,7 @@ const BLOCK_NUMBER = 'BLOCK_NUMBER'
const USD_PRICE = 'USD_PRICE' const USD_PRICE = 'USD_PRICE'
const WALLET_MODAL_OPEN = 'WALLET_MODAL_OPEN' const WALLET_MODAL_OPEN = 'WALLET_MODAL_OPEN'
const POPUP_LIST = 'POPUP_LIST' const POPUP_LIST = 'POPUP_LIST'
const POPUP_KEY = 'POPUP_KEY'
const UPDATE_BLOCK_NUMBER = 'UPDATE_BLOCK_NUMBER' const UPDATE_BLOCK_NUMBER = 'UPDATE_BLOCK_NUMBER'
const TOGGLE_WALLET_MODAL = 'TOGGLE_WALLET_MODAL' const TOGGLE_WALLET_MODAL = 'TOGGLE_WALLET_MODAL'
...@@ -38,7 +39,7 @@ function reducer(state, { type, payload }) { ...@@ -38,7 +39,7 @@ function reducer(state, { type, payload }) {
case ADD_POPUP: { case ADD_POPUP: {
const { newList } = payload const { newList } = payload
return { ...state, [POPUP_LIST]: newList } return { ...state, [POPUP_LIST]: newList, [POPUP_KEY]: state?.[POPUP_KEY] + 1 }
} }
default: { default: {
...@@ -52,6 +53,7 @@ export default function Provider({ children }) { ...@@ -52,6 +53,7 @@ export default function Provider({ children }) {
[BLOCK_NUMBER]: {}, [BLOCK_NUMBER]: {},
[USD_PRICE]: {}, [USD_PRICE]: {},
[POPUP_LIST]: [], [POPUP_LIST]: [],
[POPUP_KEY]: 0,
[WALLET_MODAL_OPEN]: false [WALLET_MODAL_OPEN]: false
}) })
...@@ -142,8 +144,7 @@ export function useWalletModalToggle() { ...@@ -142,8 +144,7 @@ export function useWalletModalToggle() {
export function usePopups() { export function usePopups() {
const [state, { setPopups }] = useApplicationContext() const [state, { setPopups }] = useApplicationContext()
const [index, setIndex] = useState(0) const index = state[POPUP_KEY]
const currentPopups = state[POPUP_LIST] const currentPopups = state[POPUP_LIST]
function addPopup(content) { function addPopup(content) {
...@@ -154,7 +155,6 @@ export function usePopups() { ...@@ -154,7 +155,6 @@ export function usePopups() {
} }
currentPopups.push(newItem) currentPopups.push(newItem)
setPopups(currentPopups) setPopups(currentPopups)
setIndex(index + 1)
} }
function removePopup(key) { function removePopup(key) {
......
import React, { createContext, useContext, useReducer, useMemo, useCallback, useEffect } from 'react' import React, { createContext, useContext, useReducer, useMemo, useCallback, useEffect } from 'react'
import { useAllTokens } from './Tokens'
const UNISWAP = 'UNISWAP' const UNISWAP = 'UNISWAP'
...@@ -7,12 +8,16 @@ const CURRENT_VERSION = 0 ...@@ -7,12 +8,16 @@ const CURRENT_VERSION = 0
const LAST_SAVED = 'LAST_SAVED' const LAST_SAVED = 'LAST_SAVED'
const BETA_MESSAGE_DISMISSED = 'BETA_MESSAGE_DISMISSED' const BETA_MESSAGE_DISMISSED = 'BETA_MESSAGE_DISMISSED'
const MIGRATION_MESSAGE_DISMISSED = 'MIGRATION_MESSAGE_DISMISSED'
const DARK_MODE = 'DARK_MODE' const DARK_MODE = 'DARK_MODE'
const TOKEN_LIST = 'TOKEN_LIST'
const UPDATABLE_KEYS = [BETA_MESSAGE_DISMISSED, DARK_MODE] const UPDATABLE_KEYS = [BETA_MESSAGE_DISMISSED, MIGRATION_MESSAGE_DISMISSED, DARK_MODE]
const UPDATE_KEY = 'UPDATE_KEY' const UPDATE_KEY = 'UPDATE_KEY'
const UPDATE_TOKEN_LIST = 'UPDATE_TOKEN_LIST'
const LocalStorageContext = createContext() const LocalStorageContext = createContext()
function useLocalStorageContext() { function useLocalStorageContext() {
...@@ -32,6 +37,16 @@ function reducer(state, { type, payload }) { ...@@ -32,6 +37,16 @@ function reducer(state, { type, payload }) {
} }
} }
} }
case UPDATE_TOKEN_LIST: {
const { tokenAddress, token } = payload
return {
...state,
[TOKEN_LIST]: {
...state?.[TOKEN_LIST],
[tokenAddress]: token
}
}
}
default: { default: {
throw Error(`Unexpected action type in LocalStorageContext reducer: '${type}'.`) throw Error(`Unexpected action type in LocalStorageContext reducer: '${type}'.`)
} }
...@@ -42,6 +57,7 @@ function init() { ...@@ -42,6 +57,7 @@ function init() {
const defaultLocalStorage = { const defaultLocalStorage = {
[VERSION]: CURRENT_VERSION, [VERSION]: CURRENT_VERSION,
[BETA_MESSAGE_DISMISSED]: false, [BETA_MESSAGE_DISMISSED]: false,
[MIGRATION_MESSAGE_DISMISSED]: false,
[DARK_MODE]: false [DARK_MODE]: false
} }
...@@ -65,8 +81,14 @@ export default function Provider({ children }) { ...@@ -65,8 +81,14 @@ export default function Provider({ children }) {
dispatch({ type: UPDATE_KEY, payload: { key, value } }) dispatch({ type: UPDATE_KEY, payload: { key, value } })
}, []) }, [])
const updateTokenList = useCallback((tokenAddress, token) => {
dispatch({ type: UPDATE_TOKEN_LIST, payload: { tokenAddress, token } })
}, [])
return ( return (
<LocalStorageContext.Provider value={useMemo(() => [state, { updateKey }], [state, updateKey])}> <LocalStorageContext.Provider
value={useMemo(() => [state, { updateKey, updateTokenList }], [state, updateKey, updateTokenList])}
>
{children} {children}
</LocalStorageContext.Provider> </LocalStorageContext.Provider>
) )
...@@ -92,6 +114,16 @@ export function useBetaMessageManager() { ...@@ -92,6 +114,16 @@ export function useBetaMessageManager() {
return [!state[BETA_MESSAGE_DISMISSED], dismissBetaMessage] return [!state[BETA_MESSAGE_DISMISSED], dismissBetaMessage]
} }
export function useMigrationMessageManager() {
const [state, { updateKey }] = useLocalStorageContext()
const dismissMigrationMessage = useCallback(() => {
updateKey(MIGRATION_MESSAGE_DISMISSED, true)
}, [updateKey])
return [!state[MIGRATION_MESSAGE_DISMISSED], dismissMigrationMessage]
}
export function useDarkModeManager() { export function useDarkModeManager() {
const [state, { updateKey }] = useLocalStorageContext() const [state, { updateKey }] = useLocalStorageContext()
...@@ -106,3 +138,20 @@ export function useDarkModeManager() { ...@@ -106,3 +138,20 @@ export function useDarkModeManager() {
return [state[DARK_MODE], toggleDarkMode] return [state[DARK_MODE], toggleDarkMode]
} }
/**
* @todo is there a better place to store these? should we move into tokens context
*/
export function useSavedTokens() {
const [state, { updateTokenList }] = useLocalStorageContext()
const allTokens = useAllTokens()
const userList = state?.[TOKEN_LIST] || []
function addToken(tokenAddress) {
const token = allTokens?.[tokenAddress]
if (token) {
updateTokenList(token.address, token)
}
}
return [userList, addToken]
}
...@@ -4,6 +4,9 @@ import { useWeb3React, usePairContract } from '../hooks' ...@@ -4,6 +4,9 @@ import { useWeb3React, usePairContract } from '../hooks'
import { INITIAL_TOKENS_CONTEXT } from './Tokens' import { INITIAL_TOKENS_CONTEXT } from './Tokens'
import { ChainId, WETH, Token, TokenAmount, Pair, JSBI } from '@uniswap/sdk' import { ChainId, WETH, Token, TokenAmount, Pair, JSBI } from '@uniswap/sdk'
const ADDRESSES_KEY = 'ADDRESSES_KEY'
const ENTITIES_KEY = 'ENTITIES_KEY'
const UPDATE = 'UPDATE' const UPDATE = 'UPDATE'
const UPDATE_PAIR_ENTITY = 'UPDATE_PAIR_ENTITY' const UPDATE_PAIR_ENTITY = 'UPDATE_PAIR_ENTITY'
...@@ -29,14 +32,14 @@ const PAIR_MAP: { ...@@ -29,14 +32,14 @@ const PAIR_MAP: {
...pairMap, ...pairMap,
[tokens[0].chainId]: { [tokens[0].chainId]: {
...pairMap?.[tokens[0].chainId], ...pairMap?.[tokens[0].chainId],
addresses: { [ADDRESSES_KEY]: {
...pairMap?.[tokens[0].chainId]?.['addresses'], ...pairMap?.[tokens[0].chainId]?.[ADDRESSES_KEY],
[tokens[0].address]: { [tokens[0].address]: {
...pairMap?.[tokens[0].chainId]?.[tokens[0].address], ...pairMap?.[tokens[0].chainId]?.[ADDRESSES_KEY]?.[tokens[0].address],
[tokens[1].address]: Pair.getAddress(...tokens) [tokens[1].address]: Pair.getAddress(...tokens)
} }
}, },
entities: {} [ENTITIES_KEY]: {}
} }
} }
}, {}) }, {})
...@@ -58,10 +61,10 @@ function reducer(state, { type, payload }) { ...@@ -58,10 +61,10 @@ function reducer(state, { type, payload }) {
...state, ...state,
[tokensSorted[0].chainId]: { [tokensSorted[0].chainId]: {
...state?.[tokensSorted[0].chainId], ...state?.[tokensSorted[0].chainId],
addresses: { [ADDRESSES_KEY]: {
...state?.[tokensSorted[0].chainId]['addresses'], ...state?.[tokensSorted[0].chainId]?.[ADDRESSES_KEY],
[tokensSorted[0].address]: { [tokensSorted[0].address]: {
...state?.[tokensSorted[0].chainId]?.[tokensSorted[0].address], ...state?.[tokensSorted[0].chainId]?.[ADDRESSES_KEY]?.[tokensSorted[0].address],
[tokensSorted[1].address]: Pair.getAddress(tokensSorted[0], tokensSorted[1]) [tokensSorted[1].address]: Pair.getAddress(tokensSorted[0], tokensSorted[1])
} }
} }
...@@ -74,8 +77,8 @@ function reducer(state, { type, payload }) { ...@@ -74,8 +77,8 @@ function reducer(state, { type, payload }) {
...state, ...state,
[chainId]: { [chainId]: {
...state?.[chainId], ...state?.[chainId],
entities: { [ENTITIES_KEY]: {
...state?.[chainId]?.['entities'], ...state?.[chainId]?.[ENTITIES_KEY],
[pairAddress]: pair [pairAddress]: pair
} }
} }
...@@ -113,7 +116,7 @@ export function usePairAddress(tokenA?: Token, tokenB?: Token): string | undefin ...@@ -113,7 +116,7 @@ export function usePairAddress(tokenA?: Token, tokenB?: Token): string | undefin
const tokens: [Token, Token] = tokenA && tokenB && tokenA.sortsBefore(tokenB) ? [tokenA, tokenB] : [tokenB, tokenA] const tokens: [Token, Token] = tokenA && tokenB && tokenA.sortsBefore(tokenB) ? [tokenA, tokenB] : [tokenB, tokenA]
const address = state?.[chainId]?.['addresses']?.[tokens[0]?.address]?.[tokens[1]?.address] const address = state?.[chainId]?.[ADDRESSES_KEY]?.[tokens[0]?.address]?.[tokens[1]?.address]
useEffect(() => { useEffect(() => {
if (address === undefined && tokenA && tokenB) { if (address === undefined && tokenA && tokenB) {
...@@ -130,7 +133,7 @@ export function usePair(tokenA?: Token, tokenB?: Token): Pair | undefined { ...@@ -130,7 +133,7 @@ export function usePair(tokenA?: Token, tokenB?: Token): Pair | undefined {
const [state, { updatePairEntity }] = usePairContext() const [state, { updatePairEntity }] = usePairContext()
const address = usePairAddress(tokenA, tokenB) const address = usePairAddress(tokenA, tokenB)
const pair = state?.[chainId]?.['entities']?.[address] const pair = state?.[chainId]?.[ENTITIES_KEY]?.[address]
const tokenAmountA = useAddressBalance(address, tokenA) const tokenAmountA = useAddressBalance(address, tokenA)
const tokenAmountB = useAddressBalance(address, tokenB) const tokenAmountB = useAddressBalance(address, tokenB)
...@@ -148,7 +151,7 @@ export function useAllPairs() { ...@@ -148,7 +151,7 @@ export function useAllPairs() {
const { chainId } = useWeb3React() const { chainId } = useWeb3React()
const [state] = usePairContext() const [state] = usePairContext()
const allPairDetails = state?.[chainId]?.['addresses'] const allPairDetails = state?.[chainId]?.[ADDRESSES_KEY]
const allPairs = useMemo(() => { const allPairs = useMemo(() => {
if (!allPairDetails) { if (!allPairDetails) {
......
...@@ -77,8 +77,8 @@ export function useRoute(tokenA: Token, tokenB: Token) { ...@@ -77,8 +77,8 @@ export function useRoute(tokenA: Token, tokenB: Token) {
const defaultPair = usePair(tokenA, tokenB) const defaultPair = usePair(tokenA, tokenB)
// get token<->WETH pairs // get token<->WETH pairs
const aToETH = usePair(tokenA && chainId && !tokenA.equals(WETH[chainId]) ? tokenA : null, WETH[chainId]) const aToETH = usePair(tokenA && !tokenA.equals(WETH[chainId]) ? tokenA : null, WETH[chainId])
const bToETH = usePair(tokenB && chainId && !tokenB.equals(WETH[chainId]) ? tokenB : null, WETH[chainId]) const bToETH = usePair(tokenB && !tokenB.equals(WETH[chainId]) ? tokenB : null, WETH[chainId])
// needs to route through WETH // needs to route through WETH
const requiresHop = const requiresHop =
...@@ -95,7 +95,7 @@ export function useRoute(tokenA: Token, tokenB: Token) { ...@@ -95,7 +95,7 @@ export function useRoute(tokenA: Token, tokenB: Token) {
requiresHop && requiresHop &&
aToETH && aToETH &&
bToETH && bToETH &&
// check there is liquidity in both pairs, possibly to reference empty pair // check there is liquidity in both token<->ETH pairs
JSBI.notEqual(JSBI.BigInt(0), aToETH.reserve0.raw) && JSBI.notEqual(JSBI.BigInt(0), aToETH.reserve0.raw) &&
JSBI.notEqual(JSBI.BigInt(0), bToETH.reserve0.raw) JSBI.notEqual(JSBI.BigInt(0), bToETH.reserve0.raw)
) { ) {
......
...@@ -5,7 +5,7 @@ import { isAddress, getTokenName, getTokenSymbol, getTokenDecimals, safeAccess } ...@@ -5,7 +5,7 @@ import { isAddress, getTokenName, getTokenSymbol, getTokenDecimals, safeAccess }
const UPDATE = 'UPDATE' const UPDATE = 'UPDATE'
export const ALL_TOKENS = [ export let ALL_TOKENS = [
//Mainnet Tokens //Mainnet Tokens
WETH[ChainId.MAINNET], WETH[ChainId.MAINNET],
...@@ -24,10 +24,22 @@ export const ALL_TOKENS = [ ...@@ -24,10 +24,22 @@ export const ALL_TOKENS = [
new Token(ChainId.ROPSTEN, '0xaD6D458402F60fD3Bd25163575031ACDce07538D', 18, 'DAI', 'Dai Stablecoin'), new Token(ChainId.ROPSTEN, '0xaD6D458402F60fD3Bd25163575031ACDce07538D', 18, 'DAI', 'Dai Stablecoin'),
//Goerli Tokens //Goerli Tokens
WETH[ChainId.GÖRLI], WETH[ChainId.GÖRLI]
new Token(ChainId.GÖRLI, '0xaD6D458402F60fD3Bd25163575031ACDce07538D', 18, 'DAI', 'Dai Stablecoin')
] ]
/**
* @todo is there a better way to load these upfront?
*/
// add any tokens from local storage
const savedList = window?.localStorage?.UNISWAP && JSON.parse(window?.localStorage?.UNISWAP)?.TOKEN_LIST
if (savedList) {
const newTokens = Object.keys(savedList).map(key => {
const token = savedList[key]
return new Token(token.chainId, token.address, token.decimals, token.symbol, token.name)
})
ALL_TOKENS = ALL_TOKENS.concat(newTokens)
}
// only meant to be used in exchanges.ts! // only meant to be used in exchanges.ts!
export const INITIAL_TOKENS_CONTEXT = ALL_TOKENS.reduce((tokenMap, token) => { export const INITIAL_TOKENS_CONTEXT = ALL_TOKENS.reduce((tokenMap, token) => {
// ensure tokens are unique // ensure tokens are unique
......
import React, { Suspense, lazy, useState } from 'react' import React, { Suspense, lazy } from 'react'
import styled from 'styled-components' import styled from 'styled-components'
import { BrowserRouter, Redirect, Route, Switch } from 'react-router-dom' import { BrowserRouter, Redirect, Route, Switch } from 'react-router-dom'
import { Text } from 'rebass'
import Header from '../components/Header' import Header from '../components/Header'
import NavigationTabs from '../components/NavigationTabs' import NavigationTabs from '../components/NavigationTabs'
import Web3ReactManager from '../components/Web3ReactManager' import Web3ReactManager from '../components/Web3ReactManager'
import { TYPE } from '../theme'
import { Hover } from '../theme/components' import Popups from '../components/Popups'
import { AutoColumn } from '../components/Column'
import { PinkCard } from '../components/Card'
import { ButtonPink } from '../components/Button'
import { isAddress, getAllQueryParams } from '../utils' import { isAddress, getAllQueryParams } from '../utils'
const Swap = lazy(() => import('./Swap')) const Swap = lazy(() => import('./Swap'))
...@@ -19,11 +15,13 @@ const Pool = lazy(() => import('./Supply')) ...@@ -19,11 +15,13 @@ const Pool = lazy(() => import('./Supply'))
const Add = lazy(() => import('./Supply/AddLiquidity')) const Add = lazy(() => import('./Supply/AddLiquidity'))
const Remove = lazy(() => import('./Supply/RemoveLiquidity')) const Remove = lazy(() => import('./Supply/RemoveLiquidity'))
const Find = lazy(() => import('../components/PoolFinder')) const Find = lazy(() => import('../components/PoolFinder'))
const Create = lazy(() => import('../components/CreatePool'))
const AppWrapper = styled.div` const AppWrapper = styled.div`
display: flex; display: flex;
flex-flow: column; flex-flow: column;
align-items: flex-start; align-items: flex-start;
overflow-x: hidden;
height: 100vh; height: 100vh;
` `
...@@ -37,34 +35,33 @@ const BodyWrapper = styled.div` ...@@ -37,34 +35,33 @@ const BodyWrapper = styled.div`
display: flex; display: flex;
flex-direction: column; flex-direction: column;
width: 100%; width: 100%;
box-sizing: border-box;
justify-content: flex-start; justify-content: flex-start;
align-items: center; align-items: center;
flex: 1; flex: 1;
overflow: auto; overflow: auto;
padding-top: 40px; padding-top: 100px;
& > * { & > * {
max-width: calc(355px + 4rem); max-width: calc(355px + 4rem);
width: 90%; width: 90%;
margin-bottom: 20px;
} }
` `
const Body = styled.div` const Body = styled.div`
max-width: 355px; max-width: 355px;
width: 90%; width: 100%;
background: ${({ theme }) => theme.bg1}; background: ${({ theme }) => theme.bg1};
box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.01), 0px 4px 8px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04), box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.01), 0px 4px 8px rgba(0, 0, 0, 0.04), 0px 16px 24px rgba(0, 0, 0, 0.04),
0px 24px 32px rgba(0, 0, 0, 0.01); 0px 24px 32px rgba(0, 0, 0, 0.01);
border-radius: 20px; border-radius: 30px;
padding: 2rem 2rem 1rem 2rem; box-sizing: border-box;
padding: 1rem;
` `
export default function App() { export default function App() {
const params = getAllQueryParams() const params = getAllQueryParams()
const [showMigrationMessage, toggleShowMigrationMessage] = useState(true)
return ( return (
<> <>
<Suspense fallback={null}> <Suspense fallback={null}>
...@@ -73,18 +70,8 @@ export default function App() { ...@@ -73,18 +70,8 @@ export default function App() {
<Header /> <Header />
</HeaderWrapper> </HeaderWrapper>
<BodyWrapper> <BodyWrapper>
{showMigrationMessage && ( <Popups />
<PinkCard padding="20px">
<AutoColumn justify={'center'} gap={'20px'}>
<TYPE.largeHeader>Uniswap has upgraded.</TYPE.largeHeader>
<Text textAlign="center">Are you a liquidity provider? Upgrade now using the migration helper.</Text>
<ButtonPink width={'265px'}>Migrate your liquidity </ButtonPink>
<Hover onClick={() => toggleShowMigrationMessage(false)}>
<Text textAlign="center">Dismiss</Text>
</Hover>
</AutoColumn>
</PinkCard>
)}
<Body> <Body>
<Web3ReactManager> <Web3ReactManager>
<BrowserRouter> <BrowserRouter>
...@@ -94,6 +81,7 @@ export default function App() { ...@@ -94,6 +81,7 @@ export default function App() {
<Switch> <Switch>
<Route exact strict path="/" render={() => <Redirect to={{ pathname: '/swap' }} />} /> <Route exact strict path="/" render={() => <Redirect to={{ pathname: '/swap' }} />} />
<Route exact strict path="/find" component={() => <Find params={params} />} /> <Route exact strict path="/find" component={() => <Find params={params} />} />
<Route exact strict path="/create" component={() => <Create params={params} />} />
<Route exact strict path="/swap" component={() => <Swap params={params} />} /> <Route exact strict path="/swap" component={() => <Swap params={params} />} />
<Route <Route
exact exact
...@@ -136,8 +124,8 @@ export default function App() { ...@@ -136,8 +124,8 @@ export default function App() {
let t0 let t0
let t1 let t1
if (tokens) { if (tokens) {
t0 = tokens[0] === 'ETH' ? 'ETH' : isAddress(tokens[0]) t0 = tokens?.[0] === 'ETH' ? 'ETH' : isAddress(tokens[0])
t1 = tokens[1] === 'ETH' ? 'ETH' : isAddress(tokens[1]) t1 = tokens?.[1] === 'ETH' ? 'ETH' : isAddress(tokens[1])
} }
if (t0 && t1) { if (t0 && t1) {
return <Add params={params} token0={t0} token1={t1} /> return <Add params={params} token0={t0} token1={t1} />
...@@ -155,8 +143,8 @@ export default function App() { ...@@ -155,8 +143,8 @@ export default function App() {
let t0 let t0
let t1 let t1
if (tokens) { if (tokens) {
t0 = tokens[0] === 'ETH' ? 'ETH' : isAddress(tokens[0]) t0 = tokens?.[0] === 'ETH' ? 'ETH' : isAddress(tokens[0])
t1 = tokens[1] === 'ETH' ? 'ETH' : isAddress(tokens[1]) t1 = tokens?.[1] === 'ETH' ? 'ETH' : isAddress(tokens[1])
} }
if (t0 && t1) { if (t0 && t1) {
return <Remove params={params} token0={t0} token1={t1} /> return <Remove params={params} token0={t0} token1={t1} />
......
...@@ -2,6 +2,6 @@ import React from 'react' ...@@ -2,6 +2,6 @@ import React from 'react'
import ExchangePage from '../../components/ExchangePage' import ExchangePage from '../../components/ExchangePage'
export default function Send() { export default function Send({ initialCurrency, params }) {
return <ExchangePage sendingInput={true} /> return <ExchangePage sendingInput={true} initialCurrency={initialCurrency} params={params} />
} }
import React, { useReducer, useState, useCallback, useEffect } from 'react' import React, { useReducer, useState, useCallback, useEffect } from 'react'
import styled from 'styled-components' import styled from 'styled-components'
import { ethers } from 'ethers' import { ethers } from 'ethers'
import { withRouter } from 'react-router-dom'
import { parseUnits, parseEther } from '@ethersproject/units' import { parseUnits, parseEther } from '@ethersproject/units'
import { WETH, TokenAmount, JSBI, Percent, Route, Token, Pair } from '@uniswap/sdk' import { WETH, TokenAmount, JSBI, Percent, Route, Token, Pair, Price } from '@uniswap/sdk'
import TokenLogo from '../../components/TokenLogo' import TokenLogo from '../../components/TokenLogo'
import DoubleLogo from '../../components/DoubleLogo' import DoubleLogo from '../../components/DoubleLogo'
...@@ -13,9 +14,11 @@ import CurrencyInputPanel from '../../components/CurrencyInputPanel' ...@@ -13,9 +14,11 @@ import CurrencyInputPanel from '../../components/CurrencyInputPanel'
import { Text } from 'rebass' import { Text } from 'rebass'
import { TYPE } from '../../theme' import { TYPE } from '../../theme'
import { Plus } from 'react-feather' import { Plus } from 'react-feather'
import { BlueCard, LightCard } from '../../components/Card'
import { AutoColumn, ColumnCenter } from '../../components/Column' import { AutoColumn, ColumnCenter } from '../../components/Column'
import { ButtonPrimary, ButtonLight } from '../../components/Button' import { ButtonPrimary, ButtonLight } from '../../components/Button'
import Row, { RowBetween, RowFlat, RowFixed } from '../../components/Row' import Row, { AutoRow, RowBetween, RowFlat, RowFixed } from '../../components/Row'
import { GreyCard } from '../../components/Card'
import { useToken } from '../../contexts/Tokens' import { useToken } from '../../contexts/Tokens'
import { usePopups } from '../../contexts/Application' import { usePopups } from '../../contexts/Application'
...@@ -43,7 +46,7 @@ const Wrapper = styled.div` ...@@ -43,7 +46,7 @@ const Wrapper = styled.div`
const FixedBottom = styled.div` const FixedBottom = styled.div`
position: absolute; position: absolute;
bottom: -220px; margin-top: 2rem;
width: 100%; width: 100%;
` `
...@@ -135,7 +138,7 @@ function reducer( ...@@ -135,7 +138,7 @@ function reducer(
} }
} }
export default function AddLiquidity({ token0, token1 }) { function AddLiquidity({ token0, token1, step = false }) {
const { account, chainId, library } = useWeb3React() const { account, chainId, library } = useWeb3React()
const [, addPopup] = usePopups() const [, addPopup] = usePopups()
...@@ -170,7 +173,8 @@ export default function AddLiquidity({ token0, token1 }) { ...@@ -170,7 +173,8 @@ export default function AddLiquidity({ token0, token1 }) {
const pair: Pair = usePair(tokens[Field.INPUT], tokens[Field.OUTPUT]) const pair: Pair = usePair(tokens[Field.INPUT], tokens[Field.OUTPUT])
const route: Route = pair ? new Route([pair], tokens[independentField]) : undefined const route: Route = pair ? new Route([pair], tokens[independentField]) : undefined
const totalSupply: TokenAmount = useTotalSupply(tokens[Field.INPUT], tokens[Field.OUTPUT]) const totalSupply: TokenAmount = useTotalSupply(tokens[Field.INPUT], tokens[Field.OUTPUT])
const [noLiquidity, setNoLiquidity] = useState<boolean>(false) // used to detect new exchange const noLiquidity = // used to detect new exchange
pair && JSBI.equal(pair.reserve0.raw, JSBI.BigInt(0)) && JSBI.equal(pair.reserve1.raw, JSBI.BigInt(0))
// state for amount approvals // state for amount approvals
const inputApproval: TokenAmount = useAddressAllowance(account, tokens[Field.INPUT], routerAddress) const inputApproval: TokenAmount = useAddressAllowance(account, tokens[Field.INPUT], routerAddress)
...@@ -184,13 +188,6 @@ export default function AddLiquidity({ token0, token1 }) { ...@@ -184,13 +188,6 @@ export default function AddLiquidity({ token0, token1 }) {
[Field.OUTPUT]: useAddressBalance(account, tokens[Field.OUTPUT]) [Field.OUTPUT]: useAddressBalance(account, tokens[Field.OUTPUT])
} }
// check if no exchange or no liquidity
useEffect(() => {
if (pair && JSBI.equal(pair.reserve0.raw, JSBI.BigInt(0)) && JSBI.equal(pair.reserve1.raw, JSBI.BigInt(0))) {
setNoLiquidity(true)
}
}, [pair])
// track non relational amounts if first person to add liquidity // track non relational amounts if first person to add liquidity
const [nonrelationalAmounts, setNonrelationalAmounts] = useState({ const [nonrelationalAmounts, setNonrelationalAmounts] = useState({
[Field.INPUT]: null, [Field.INPUT]: null,
...@@ -240,13 +237,26 @@ export default function AddLiquidity({ token0, token1 }) { ...@@ -240,13 +237,26 @@ export default function AddLiquidity({ token0, token1 }) {
[dependentField]: parsedAmounts[dependentField] ? parsedAmounts[dependentField]?.toSignificant(8) : '' [dependentField]: parsedAmounts[dependentField] ? parsedAmounts[dependentField]?.toSignificant(8) : ''
} }
// used for displaying approximate starting price in UI
const derivedPrice =
parsedAmounts[Field.INPUT] &&
parsedAmounts[Field.OUTPUT] &&
new Price(
parsedAmounts[Field.INPUT].token,
parsedAmounts[Field.OUTPUT].token,
parsedAmounts[Field.INPUT].raw,
parsedAmounts[Field.OUTPUT].raw
)
// check for estimated liquidity minted // check for estimated liquidity minted
const liquidityMinted: TokenAmount = const liquidityMinted: TokenAmount =
!!pair && !!pair &&
!!parsedAmounts[Field.INPUT] && !!parsedAmounts[Field.INPUT] &&
!!parsedAmounts[Field.OUTPUT] && !!parsedAmounts[Field.OUTPUT] &&
!JSBI.equal(parsedAmounts[Field.INPUT].raw, JSBI.BigInt(0)) && !JSBI.equal(parsedAmounts[Field.INPUT].raw, JSBI.BigInt(0)) &&
!JSBI.equal(parsedAmounts[Field.OUTPUT].raw, JSBI.BigInt(0)) !JSBI.equal(parsedAmounts[Field.OUTPUT].raw, JSBI.BigInt(0)) &&
totalSupply &&
totalSupply.token.equals(pair.liquidityToken) // if stale value for pair
? pair.getLiquidityMinted( ? pair.getLiquidityMinted(
totalSupply ? totalSupply : new TokenAmount(pair?.liquidityToken, JSBI.BigInt(0)), totalSupply ? totalSupply : new TokenAmount(pair?.liquidityToken, JSBI.BigInt(0)),
parsedAmounts[Field.INPUT], parsedAmounts[Field.INPUT],
...@@ -347,14 +357,6 @@ export default function AddLiquidity({ token0, token1 }) { ...@@ -347,14 +357,6 @@ export default function AddLiquidity({ token0, token1 }) {
setGeneralError('Enter an amount') setGeneralError('Enter an amount')
setIsValid(false) setIsValid(false)
} }
if (showInputUnlock) {
setInputError('Approve Amount')
setIsValid(false)
}
if (showOutputUnlock) {
setOutputError('Approve Amount')
setIsValid(false)
}
if ( if (
parsedAmounts?.[Field.INPUT] && parsedAmounts?.[Field.INPUT] &&
userBalances?.[Field.INPUT] && userBalances?.[Field.INPUT] &&
...@@ -487,7 +489,41 @@ export default function AddLiquidity({ token0, token1 }) { ...@@ -487,7 +489,41 @@ export default function AddLiquidity({ token0, token1 }) {
} }
const modalHeader = () => { const modalHeader = () => {
return ( return noLiquidity ? (
<AutoColumn gap="12px">
<LightCard margin={'30px 0'} borderRadius="20px">
<ColumnCenter>
<RowFixed>
<Text fontSize={36} fontWeight={500} marginRight={20}>
{tokens[Field.INPUT]?.symbol + '-' + tokens[Field.OUTPUT]?.symbol}
</Text>{' '}
<DoubleLogo a0={tokens[Field.INPUT]?.address} a1={tokens[Field.OUTPUT]?.address} size={36} />
</RowFixed>
</ColumnCenter>
</LightCard>
<TYPE.body>Starting pool prices</TYPE.body>
<LightCard borderRadius="20px">
<TYPE.mediumHeader>
{parsedAmounts[0] &&
parsedAmounts[1] &&
JSBI.greaterThan(parsedAmounts[0].raw, JSBI.BigInt(0)) &&
JSBI.greaterThan(parsedAmounts[1].raw, JSBI.BigInt(0)) &&
derivedPrice?.invert().toSignificant(6)}{' '}
{tokens[Field.INPUT]?.symbol + '/' + tokens[Field.OUTPUT]?.symbol}
</TYPE.mediumHeader>
</LightCard>
<LightCard borderRadius="20px">
<TYPE.mediumHeader>
{parsedAmounts[0] &&
parsedAmounts[1] &&
JSBI.greaterThan(parsedAmounts[0].raw, JSBI.BigInt(0)) &&
JSBI.greaterThan(parsedAmounts[1].raw, JSBI.BigInt(0)) &&
derivedPrice?.toSignificant(6)}{' '}
{tokens[Field.OUTPUT]?.symbol + '/' + tokens[Field.INPUT]?.symbol}
</TYPE.mediumHeader>
</LightCard>
</AutoColumn>
) : (
<AutoColumn gap="20px"> <AutoColumn gap="20px">
<RowFlat style={{ marginTop: '60px' }}> <RowFlat style={{ marginTop: '60px' }}>
<Text fontSize="48px" fontWeight={500} lineHeight="32px" marginRight={10}> <Text fontSize="48px" fontWeight={500} lineHeight="32px" marginRight={10}>
...@@ -537,17 +573,51 @@ export default function AddLiquidity({ token0, token1 }) { ...@@ -537,17 +573,51 @@ export default function AddLiquidity({ token0, token1 }) {
</RowBetween> </RowBetween>
<ButtonPrimary style={{ margin: '20px 0' }} onClick={onAdd}> <ButtonPrimary style={{ margin: '20px 0' }} onClick={onAdd}>
<Text fontWeight={500} fontSize={20}> <Text fontWeight={500} fontSize={20}>
Confirm Supply {noLiquidity ? 'Supply & Create Pool' : 'Confirm Supply'}
</Text> </Text>
</ButtonPrimary> </ButtonPrimary>
<TYPE.italic fontSize={12} color="#565A69" textAlign="center"> <TYPE.italic fontSize={12} color="#565A69" textAlign="center">
{`Output is estimated. You will receive at least ${liquidityMinted?.toFixed(6)} UNI ${ {`Output is estimated. You will receive at least ${liquidityMinted?.toSignificant(6)} UNI ${
tokens[Field.INPUT]?.symbol tokens[Field.INPUT]?.symbol
}/${tokens[Field.OUTPUT]?.symbol} or the transaction will revert.`} }/${tokens[Field.OUTPUT]?.symbol} or the transaction will revert.`}
</TYPE.italic> </TYPE.italic>
</> </>
) )
} }
const PriceBar = function(props) {
return (
// <GreyCard>
<AutoRow justify="space-between">
<AutoColumn justify="center">
<Text fontWeight={500} fontSize={16} color="#000000">
{pair ? `${route.midPrice.toSignificant(6)} ` : '-'}
</Text>
<Text fontWeight={500} fontSize={14} color="#888D9B" pt={1}>
{tokens[Field.OUTPUT]?.symbol} / {tokens[Field.INPUT]?.symbol}
</Text>
</AutoColumn>
<AutoColumn justify="center">
<Text fontWeight={500} fontSize={16} color="#000000">
{pair ? `${route.midPrice.invert().toSignificant(6)} ` : '-'}
</Text>
<Text fontWeight={500} fontSize={14} color="#888D9B" pt={1}>
{tokens[Field.INPUT]?.symbol} / {tokens[Field.OUTPUT]?.symbol}
</Text>
</AutoColumn>
<AutoColumn justify="center">
<Text fontWeight={500} fontSize={16} color="#000000">
{poolTokenPercentage ? poolTokenPercentage?.toFixed(2) : '0.0'}
{'%'}
</Text>
<Text fontWeight={500} fontSize={14} color="#888D9B" pt={1}>
Pool Share
</Text>
</AutoColumn>
</AutoRow>
// </GreyCard>
)
}
const pendingText: string = `Supplied ${parsedAmounts[Field.INPUT]?.toSignificant(6)} ${ const pendingText: string = `Supplied ${parsedAmounts[Field.INPUT]?.toSignificant(6)} ${
tokens[Field.INPUT]?.symbol tokens[Field.INPUT]?.symbol
...@@ -568,7 +638,7 @@ export default function AddLiquidity({ token0, token1 }) { ...@@ -568,7 +638,7 @@ export default function AddLiquidity({ token0, token1 }) {
topContent={() => modalHeader()} topContent={() => modalHeader()}
bottomContent={modalBottom} bottomContent={modalBottom}
pendingText={pendingText} pendingText={pendingText}
title="You will receive" title={noLiquidity ? 'You are creating a pool' : 'You will receive'}
/> />
<SearchModal <SearchModal
isOpen={showSearch} isOpen={showSearch}
...@@ -579,12 +649,15 @@ export default function AddLiquidity({ token0, token1 }) { ...@@ -579,12 +649,15 @@ export default function AddLiquidity({ token0, token1 }) {
<AutoColumn gap="20px"> <AutoColumn gap="20px">
{noLiquidity && ( {noLiquidity && (
<ColumnCenter> <ColumnCenter>
<TYPE.main textAlign="center"> <BlueCard>
<span role="img" aria-label="Thinking"> <AutoColumn gap="10px">
🥇 {step && <TYPE.blue fontWeight={400}>Step 2.</TYPE.blue>}
</span>{' '} <TYPE.blue fontWeight={400}>
You are the first to add liquidity. Make sure you're setting rates correctly. You are the first liquidity provider. The ratio of tokens you add will set the price of this pool.
</TYPE.main> </TYPE.blue>
<TYPE.blue fontWeight={400}>Once you are happy with the rate. Click create pool to review.</TYPE.blue>
</AutoColumn>
</BlueCard>
</ColumnCenter> </ColumnCenter>
)} )}
<CurrencyInputPanel <CurrencyInputPanel
...@@ -596,10 +669,9 @@ export default function AddLiquidity({ token0, token1 }) { ...@@ -596,10 +669,9 @@ export default function AddLiquidity({ token0, token1 }) {
}} }}
atMax={atMaxAmountInput} atMax={atMaxAmountInput}
token={tokens[Field.INPUT]} token={tokens[Field.INPUT]}
onTokenSelection={onTokenSelection} onTokenSelection={address => onTokenSelection(Field.INPUT, address)}
error={inputError} error={inputError}
pair={pair} pair={pair}
disableTokenSelect
/> />
<ColumnCenter> <ColumnCenter>
<Plus size="16" color="#888D9B" /> <Plus size="16" color="#888D9B" />
...@@ -613,12 +685,11 @@ export default function AddLiquidity({ token0, token1 }) { ...@@ -613,12 +685,11 @@ export default function AddLiquidity({ token0, token1 }) {
}} }}
atMax={atMaxAmountOutput} atMax={atMaxAmountOutput}
token={tokens[Field.OUTPUT]} token={tokens[Field.OUTPUT]}
onTokenSelection={onTokenSelection} onTokenSelection={address => onTokenSelection(Field.OUTPUT, address)}
error={outputError} error={outputError}
pair={pair} pair={pair}
disableTokenSelect
/> />
{!noLiquidity && ( {/* {!noLiquidity && (
<RowBetween> <RowBetween>
Rate: Rate:
<div> <div>
...@@ -626,7 +697,7 @@ export default function AddLiquidity({ token0, token1 }) { ...@@ -626,7 +697,7 @@ export default function AddLiquidity({ token0, token1 }) {
{tokens[dependentField]?.symbol} {tokens[dependentField]?.symbol}
</div> </div>
</RowBetween> </RowBetween>
)} )} */}
{showOutputUnlock ? ( {showOutputUnlock ? (
<ButtonLight <ButtonLight
onClick={() => { onClick={() => {
...@@ -655,17 +726,32 @@ export default function AddLiquidity({ token0, token1 }) { ...@@ -655,17 +726,32 @@ export default function AddLiquidity({ token0, token1 }) {
</Text> </Text>
</ButtonPrimary> </ButtonPrimary>
)} )}
{!noLiquidity && ( </AutoColumn>
<FixedBottom>
{!noLiquidity && (
<FixedBottom>
<AutoColumn>
{tokens[Field.OUTPUT] && (
<GreyCard pt={2} mb={2}>
<PriceBar />
{/* <AutoRow justify="center" gap="8px">
<Link fontSize="14px" fontWeight={400} href="">
Show Advanced
</Link>
</AutoRow> */}
</GreyCard>
)}
<PositionCard <PositionCard
pairAddress={pair?.liquidityToken?.address} pairAddress={pair?.liquidityToken?.address}
token0={tokens[Field.INPUT]} token0={tokens[Field.INPUT]}
token1={tokens[Field.OUTPUT]} token1={tokens[Field.OUTPUT]}
minimal={true} minimal={true}
/> />
</FixedBottom> </AutoColumn>
)} </FixedBottom>
</AutoColumn> )}
</Wrapper> </Wrapper>
) )
} }
export default withRouter(AddLiquidity)
...@@ -42,7 +42,7 @@ const Wrapper = styled.div` ...@@ -42,7 +42,7 @@ const Wrapper = styled.div`
const FixedBottom = styled.div` const FixedBottom = styled.div`
position: absolute; position: absolute;
bottom: -220px; top: 100px;
width: 100%; width: 100%;
` `
...@@ -694,32 +694,34 @@ export default function RemoveLiquidity({ token0, token1 }) { ...@@ -694,32 +694,34 @@ export default function RemoveLiquidity({ token0, token1 }) {
</div> </div>
</RowBetween> </RowBetween>
</div> </div>
<ButtonPrimary <div style={{ position: 'relative' }}>
onClick={() => { <ButtonPrimary
setShowConfirm(true) onClick={() => {
}} setShowConfirm(true)
disabled={!isValid} }}
> disabled={!isValid}
<Text fontSize={20} fontWeight={500}> >
{inputError <Text fontSize={20} fontWeight={500}>
? inputError {inputError
: outputError ? inputError
? outputError : outputError
: poolTokenError ? outputError
? poolTokenError : poolTokenError
: generalError ? poolTokenError
? generalError : generalError
: 'Remove'} ? generalError
</Text> : 'Remove'}
</ButtonPrimary> </Text>
<FixedBottom> </ButtonPrimary>
<PositionCard <FixedBottom>
pairAddress={pair?.liquidityToken.address} <PositionCard
token0={pair?.token0} pairAddress={pair?.liquidityToken.address}
token1={pair?.token1} token0={pair?.token0}
minimal={true} token1={pair?.token1}
/> minimal={true}
</FixedBottom> />
</FixedBottom>
</div>
</AutoColumn> </AutoColumn>
</Wrapper> </Wrapper>
) )
......
...@@ -8,9 +8,10 @@ import SearchModal from '../../components/SearchModal' ...@@ -8,9 +8,10 @@ import SearchModal from '../../components/SearchModal'
import PositionCard from '../../components/PositionCard' import PositionCard from '../../components/PositionCard'
import { Link } from '../../theme' import { Link } from '../../theme'
import { Text } from 'rebass' import { Text } from 'rebass'
import { AutoColumn } from '../../components/Column'
import { RowBetween } from '../../components/Row' import { RowBetween } from '../../components/Row'
import { ButtonPrimary } from '../../components/Button' import { ButtonPrimary } from '../../components/Button'
import { GreyCard } from '../../components/Card'
import { AutoColumn, ColumnCenter } from '../../components/Column'
import { useAllPairs } from '../../contexts/Pairs' import { useAllPairs } from '../../contexts/Pairs'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
...@@ -19,7 +20,13 @@ import { useAllBalances, useAccountLPBalances } from '../../contexts/Balances' ...@@ -19,7 +20,13 @@ import { useAllBalances, useAccountLPBalances } from '../../contexts/Balances'
const Positions = styled.div` const Positions = styled.div`
position: relative; position: relative;
margin-top: 38px; width: 100%;
`
const FixedBottom = styled.div`
position: absolute;
bottom: -80px;
width: 100%;
` `
function Supply({ history }) { function Supply({ history }) {
...@@ -33,8 +40,6 @@ function Supply({ history }) { ...@@ -33,8 +40,6 @@ function Supply({ history }) {
// initiate listener for LP balances // initiate listener for LP balances
useAccountLPBalances(account) useAccountLPBalances(account)
// console.log(allPairs)
const filteredExchangeList = Object.keys(allPairs) const filteredExchangeList = Object.keys(allPairs)
.filter((pairAddress, i) => { .filter((pairAddress, i) => {
return ( return (
...@@ -56,7 +61,7 @@ function Supply({ history }) { ...@@ -56,7 +61,7 @@ function Supply({ history }) {
}) })
return ( return (
<> <AutoColumn gap="lg" justify="center">
<ButtonPrimary <ButtonPrimary
onClick={() => { onClick={() => {
setShowPoolSearch(true) setShowPoolSearch(true)
...@@ -67,13 +72,13 @@ function Supply({ history }) { ...@@ -67,13 +72,13 @@ function Supply({ history }) {
<Positions> <Positions>
<AutoColumn gap="20px"> <AutoColumn gap="20px">
{filteredExchangeList?.length !== 0 && ( {filteredExchangeList?.length !== 0 && (
<RowBetween> <RowBetween padding={'0 8px'}>
<Text fontWeight={500}>Your Pooled Liquidity</Text> <Text fontWeight={500}>Your Pooled Liquidity</Text>
<Question text="filler text" /> <Question text="filler text" />
</RowBetween> </RowBetween>
)} )}
{filteredExchangeList} {filteredExchangeList}
<AutoColumn justify="center"> <GreyCard style={{ textAlign: 'center', padding: '0.5rem 1.25rem 1rem 1.25rem' }}>
<Text color="#AEAEAE"> <Text color="#AEAEAE">
{filteredExchangeList?.length !== 0 ? `Don't see a pool you joined? ` : 'Already joined a pool?'}{' '} {filteredExchangeList?.length !== 0 ? `Don't see a pool you joined? ` : 'Already joined a pool?'}{' '}
<Link <Link
...@@ -81,14 +86,21 @@ function Supply({ history }) { ...@@ -81,14 +86,21 @@ function Supply({ history }) {
history.push('/find') history.push('/find')
}} }}
> >
Find it. Import it.
</Link> </Link>
</Text> </Text>
</AutoColumn> </GreyCard>
</AutoColumn> </AutoColumn>
<FixedBottom>
<ColumnCenter>
<ButtonPrimary width="120px" padding="8px" borderRadius="10px" onClick={() => history.push('/create')}>
Create Pool
</ButtonPrimary>
</ColumnCenter>
</FixedBottom>
</Positions> </Positions>
<SearchModal isOpen={showPoolSearch} onDismiss={() => setShowPoolSearch(false)} /> <SearchModal isOpen={showPoolSearch} onDismiss={() => setShowPoolSearch(false)} />
</> </AutoColumn>
) )
} }
export default withRouter(Supply) export default withRouter(Supply)
...@@ -2,5 +2,5 @@ import React from 'react' ...@@ -2,5 +2,5 @@ import React from 'react'
import ExchangePage from '../../components/ExchangePage' import ExchangePage from '../../components/ExchangePage'
export default function Swap({ initialCurrency, params }) { export default function Swap({ initialCurrency, params }) {
return <ExchangePage sendingInput={false} /> return <ExchangePage sendingInput={false} initialCurrency={initialCurrency} params={params} />
} }
...@@ -8,6 +8,7 @@ import { Text } from 'rebass' ...@@ -8,6 +8,7 @@ import { Text } from 'rebass'
export * from './components' export * from './components'
const MEDIA_WIDTHS = { const MEDIA_WIDTHS = {
upToExtraSmall: 500,
upToSmall: 600, upToSmall: 600,
upToMedium: 960, upToMedium: 960,
upToLarge: 1280 upToLarge: 1280
...@@ -77,6 +78,12 @@ const theme = darkMode => ({ ...@@ -77,6 +78,12 @@ const theme = darkMode => ({
yellow1: '#FFE270', yellow1: '#FFE270',
yellow2: '#F3841E', yellow2: '#F3841E',
grids: {
sm: 8,
md: 12,
lg: 24
},
//shadows //shadows
shadow1: darkMode ? '#000' : '#2F80ED', shadow1: darkMode ? '#000' : '#2F80ED',
...@@ -115,7 +122,7 @@ export const TYPE = { ...@@ -115,7 +122,7 @@ export const TYPE = {
</Text> </Text>
), ),
body: ({ children, ...rest }) => ( body: ({ children, ...rest }) => (
<Text fontWeight={500} fontSize={16} color={'#565A69'} {...rest}> <Text fontWeight={400} fontSize={16} color={'#888D9B'} {...rest}>
{children} {children}
</Text> </Text>
), ),
...@@ -153,7 +160,11 @@ export const TYPE = { ...@@ -153,7 +160,11 @@ export const TYPE = {
export const GlobalStyle = createGlobalStyle` export const GlobalStyle = createGlobalStyle`
@import url('https://rsms.me/inter/inter.css'); @import url('https://rsms.me/inter/inter.css');
html { font-family: 'Inter', sans-serif; } html {
font-family: 'Inter', sans-serif;
letter-spacing: -0.018em;
font-feature-settings: 'cv01', 'cv02', 'cv03', 'cv04';
}
@supports (font-variation-settings: normal) { @supports (font-variation-settings: normal) {
html { font-family: 'Inter var', sans-serif; } html { font-family: 'Inter var', sans-serif; }
} }
......
...@@ -56,6 +56,23 @@ export function getQueryParam(windowLocation, name) { ...@@ -56,6 +56,23 @@ export function getQueryParam(windowLocation, name) {
export function getAllQueryParams() { export function getAllQueryParams() {
let params = {} let params = {}
params.inputTokenAddress = isAddress(getQueryParam(window.location, 'inputTokenAddress'))
? isAddress(getQueryParam(window.location, 'inputTokenAddress'))
: ''
params.outputTokenAddress = isAddress(getQueryParam(window.location, 'outputTokenAddress'))
? isAddress(getQueryParam(window.location, 'outputTokenAddress'))
: ''
params.inputTokenAmount = !isNaN(getQueryParam(window.location, 'inputTokenAmount'))
? getQueryParam(window.location, 'inputTokenAmount')
: ''
params.outputTokenAmount = !isNaN(getQueryParam(window.location, 'outputTokenAmount'))
? getQueryParam(window.location, 'outputTokenAmount')
: ''
return params return params
} }
......
...@@ -15441,6 +15441,11 @@ usb@^1.6.0: ...@@ -15441,6 +15441,11 @@ usb@^1.6.0:
nan "2.13.2" nan "2.13.2"
prebuild-install "^5.3.3" prebuild-install "^5.3.3"
use-media@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/use-media/-/use-media-1.4.0.tgz#e777bf1f382a7aacabbd1f9ce3da2b62e58b2a98"
integrity sha512-XsgyUAf3nhzZmEfhc5MqLHwyaPjs78bgytpVJ/xDl0TF4Bptf3vEpBNBBT/EIKOmsOc8UbuECq3mrP3mt1QANA==
use@^3.1.0: use@^3.1.0:
version "3.1.1" version "3.1.1"
resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment