= P & { 4 | className?: string; 5 | style?: CSSProperties; 6 | }; 7 | 8 | export type CP
= P & { 9 | children?: ReactNode; 10 | className?: string; 11 | style?: CSSProperties; 12 | }; 13 | 14 | export type FCx
= FC
34 | );
35 | };
36 |
37 | export default Identicon;
38 |
--------------------------------------------------------------------------------
/src/modules/smart-alpha/views/kpi-option/statistics/s.module.scss:
--------------------------------------------------------------------------------
1 | .statistics {
2 | display: flex;
3 | flex-direction: column;
4 | }
5 |
6 | .defs {
7 | margin: 0;
8 | padding: 24px;
9 | }
10 |
11 | .def {
12 | display: flex;
13 | align-items: center;
14 | margin-bottom: 24px;
15 |
16 | &:last-of-type {
17 | margin-bottom: 0;
18 | }
19 |
20 | dt {
21 | font: var(--font-sm);
22 | font-weight: 600;
23 | color: var(--theme-secondary-color);
24 | }
25 |
26 | dd {
27 | font: var(--font-p1);
28 | font-weight: 600;
29 | color: var(--theme-primary-color);
30 | margin: 0 0 0 auto;
31 | display: flex;
32 | align-items: center;
33 | }
34 | }
35 |
36 | .footer {
37 | display: flex;
38 | align-items: center;
39 | background-color: var(--theme-body-color);
40 | border-radius: 4px;
41 | margin: auto 4px 4px;
42 | padding: 16px;
43 | }
44 |
45 | .footerReward {
46 | display: flex;
47 | align-items: center;
48 | margin-bottom: 4px;
49 | }
50 |
--------------------------------------------------------------------------------
/src/modules/smart-yield/views/pool-view/statistics/s.module.scss:
--------------------------------------------------------------------------------
1 | .statistics {
2 | display: flex;
3 | flex-direction: column;
4 | }
5 |
6 | .defs {
7 | margin: 0;
8 | padding: 24px;
9 | }
10 |
11 | .def {
12 | display: flex;
13 | align-items: center;
14 | margin-bottom: 24px;
15 |
16 | &:last-of-type {
17 | margin-bottom: 0;
18 | }
19 |
20 | dt {
21 | font: var(--font-sm);
22 | font-weight: 600;
23 | color: var(--theme-secondary-color);
24 | }
25 |
26 | dd {
27 | font: var(--font-p1);
28 | font-weight: 600;
29 | color: var(--theme-primary-color);
30 | margin: 0 0 0 auto;
31 | display: flex;
32 | align-items: center;
33 | }
34 | }
35 |
36 | .footer {
37 | display: flex;
38 | align-items: center;
39 | background-color: var(--theme-body-color);
40 | border-radius: 4px;
41 | margin: auto 4px 4px;
42 | padding: 16px;
43 | }
44 |
45 | .footerReward {
46 | display: flex;
47 | align-items: center;
48 | margin-bottom: 4px;
49 | }
50 |
--------------------------------------------------------------------------------
/src/components/antd/modal/s.module.scss:
--------------------------------------------------------------------------------
1 | .component {
2 | :global(.ant-modal-content) {
3 | box-shadow: 0 16px 32px rgba(19, 32, 43, 0.4), 0 0 0.5px rgba(6, 10, 13, 0.4);
4 | }
5 |
6 | :global(.ant-modal-close) {
7 | top: 32px;
8 | right: 32px;
9 | }
10 |
11 | :global(.ant-modal-close-x) {
12 | width: 24px;
13 | height: 24px;
14 | line-height: 24px;
15 | }
16 |
17 | :global(.ant-modal-close-x) svg {
18 | color: var(--theme-icon-color);
19 | }
20 |
21 | :global(.ant-modal-header) {
22 | padding: 32px;
23 | background: var(--theme-card-color);
24 | border-bottom: 1px solid var(--theme-border-color);
25 |
26 | :global(.ant-modal-title) {
27 | font: var(--font-p1);
28 | font-weight: 600;
29 | color: var(--theme-primary-color);
30 | }
31 | }
32 |
33 | :global(.ant-modal-body) {
34 | background: var(--theme-card-color);
35 | border-bottom-left-radius: 4px;
36 | border-bottom-right-radius: 4px;
37 | overflow-y: auto;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/global.d.ts:
--------------------------------------------------------------------------------
1 | import BN from 'bignumber.js/bignumber';
2 |
3 | declare module 'bignumber.js' {
4 | export default class BigNumber extends BN {
5 | static ZERO: BigNumber;
6 | static MAX_UINT_256: BigNumber;
7 |
8 | static from(value?: BN.Value): BigNumber | undefined;
9 |
10 | static parse(value: BN.Value): BigNumber;
11 |
12 | static sumEach
= Partial | ((prevState: S) => Partial);
4 |
5 | export function mergeState(state: Partial): (prevState: S) => S {
6 | return (prevState: S): S => {
7 | return {
8 | ...prevState,
9 | ...state,
10 | };
11 | };
12 | }
13 |
14 | function useMergeState(
15 | initialState: S | (() => S),
16 | callback?: (state: S) => void,
17 | ): [S, React.Dispatch(initialState);
19 |
20 | const setState = React.useCallback(
21 | (updater: MergeStateUpdate) => {
22 | set(prev => {
23 | const next = {
24 | ...prev,
25 | ...(typeof updater === 'function' ? (updater as (value: S) => S)(prev) : updater),
26 | };
27 |
28 | if (typeof callback === 'function') {
29 | callback(next);
30 | }
31 |
32 | return next;
33 | });
34 | },
35 | [callback],
36 | );
37 |
38 | return [state, setState];
39 | }
40 |
41 | export default useMergeState;
42 |
--------------------------------------------------------------------------------
/src/wallets/connectors/wallet-connect/index.ts:
--------------------------------------------------------------------------------
1 | import { AbstractConnector } from '@web3-react/abstract-connector';
2 | import { WalletConnectConnector } from '@web3-react/walletconnect-connector';
3 |
4 | import WalletConnectLogo from 'resources/svg/wallets/walletconnect-logo.svg';
5 |
6 | import { Web3Network } from 'networks/types';
7 | import { BaseWalletConfig } from 'wallets/types';
8 |
9 | const WalletConnectConfig: BaseWalletConfig = {
10 | id: 'walletconnect',
11 | logo: WalletConnectLogo,
12 | name: 'WalletConnect',
13 | factory(network: Web3Network): AbstractConnector {
14 | return new WalletConnectConnector({
15 | rpc: {
16 | [network.meta.chainId]: network.rpc.httpsUrl,
17 | },
18 | pollingInterval: network.rpc.poolingInterval,
19 | bridge: network.config.wallets.walletConnectBridge,
20 | qrcode: true,
21 | });
22 | },
23 | onDisconnect(connector?: WalletConnectConnector): void {
24 | connector?.close();
25 | },
26 | onError(error: Error): Error | undefined {
27 | return error;
28 | },
29 | };
30 |
31 | export default WalletConnectConfig;
32 |
--------------------------------------------------------------------------------
/src/modules/smart-alpha/views/portfolio-view/s.module.scss:
--------------------------------------------------------------------------------
1 | .portfolioContainer {
2 | column-gap: 32px;
3 | display: grid;
4 | grid-template-columns: 40% 1fr;
5 | margin-bottom: 32px;
6 |
7 | @media (max-width: 768px) {
8 | gap: 8px;
9 | grid-template-columns: 1fr;
10 | }
11 | }
12 |
13 | .positionsCards {
14 | display: grid;
15 | grid-template-columns: 1fr 1fr 1fr;
16 | column-gap: 32px;
17 | align-items: start;
18 |
19 | > * {
20 | min-height: 250px;
21 | }
22 | }
23 |
24 | .positionsWalletSecondaryValues {
25 | display: flex;
26 | align-items: center;
27 | background-color: var(--theme-body-color);
28 | padding: 8px 16px;
29 | border-radius: 55px;
30 | margin-left: auto;
31 | margin-right: auto;
32 | }
33 |
34 | .positionsWalletSecondaryValue {
35 | display: flex;
36 | align-items: center;
37 |
38 | &:not(:last-of-type) {
39 | border-right: 2px solid var(--theme-border-color);
40 | padding-right: 16px;
41 | margin-right: 16px;
42 | }
43 | }
44 |
45 | .spinner {
46 | position: absolute;
47 | top: calc(50% - 12px);
48 | left: calc(50% - 12px);
49 | }
50 |
--------------------------------------------------------------------------------
/src/modules/smart-alpha/views/simulate-epoch/s.module.scss:
--------------------------------------------------------------------------------
1 | .cards {
2 | display: grid;
3 | grid-template-columns: 438px 1fr;
4 | column-gap: 32px;
5 | row-gap: 32px;
6 | align-items: flex-start;
7 |
8 | @media (max-width: 1200px) {
9 | grid-template-columns: 320px 1fr;
10 | }
11 |
12 | @media (max-width: 1024px) {
13 | grid-template-columns: 1fr;
14 | }
15 | }
16 |
17 | .legend {
18 | display: flex;
19 | align-items: flex-start;
20 | justify-content: center;
21 | gap: 16px 24px;
22 | margin-top: 32px;
23 | overflow-y: auto;
24 |
25 | @media (max-width: 768px) {
26 | justify-content: flex-start;
27 | }
28 | }
29 |
30 | .legendItem {
31 | background: var(--theme-body-color);
32 | border-radius: 4px;
33 | padding: 8px 12px;
34 | }
35 |
36 | .legendTitle {
37 | position: relative;
38 | display: flex;
39 | align-items: center;
40 |
41 | &::before {
42 | content: '';
43 | width: 8px;
44 | height: 8px;
45 | background-color: var(--dot-color, var(--theme-primary-color));
46 | border-radius: 50%;
47 | margin-right: 8px;
48 | flex-shrink: 0;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/components/antd/progress/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import AntdProgress, { ProgressProps as AntdProgressProps } from 'antd/lib/progress';
3 | import cn from 'classnames';
4 |
5 | import s from './s.module.scss';
6 |
7 | export type ProgressProps = AntdProgressProps & {
8 | className?: string;
9 | acceptance?: number;
10 | };
11 |
12 | const Progress: React.FC
41 |
34 | {notifications
35 | .sort((a, b) => b.startsOn - a.startsOn)
36 | .map(n => (
37 |
42 | );
43 | };
44 |
45 | export default Notifications;
46 |
--------------------------------------------------------------------------------
/src/components/custom/grid/s.module.scss:
--------------------------------------------------------------------------------
1 | $gaps: 4, 8, 12, 16, 24, 32, 48, 64;
2 | $align-items: start, center, end;
3 | $justify-contents: start, center, end, space-between;
4 |
5 | .grid {
6 | display: grid;
7 |
8 | &.row {
9 | grid-auto-flow: row;
10 | grid-template-rows: repeat(auto-fit, minmax(0, max-content));
11 |
12 | @each $align in $align-items {
13 | &.align-#{$align} {
14 | justify-items: #{$align};
15 | }
16 |
17 | &.align-self-#{$align} {
18 | justify-self: #{$align};
19 | }
20 | }
21 |
22 | @each $justify in $justify-contents {
23 | &.justify-#{$justify} {
24 | align-content: #{$justify};
25 | }
26 |
27 | &.justify-self-#{$justify} {
28 | align-self: #{$justify};
29 | }
30 | }
31 | }
32 |
33 | &.col {
34 | grid-auto-flow: column;
35 | grid-template-columns: repeat(auto-fit, minmax(0, max-content));
36 |
37 | @each $align in $align-items {
38 | &.align-#{$align} {
39 | align-items: #{$align};
40 | }
41 |
42 | &.align-self-#{$align} {
43 | align-self: #{$align};
44 | }
45 | }
46 |
47 | @each $justify in $justify-contents {
48 | &.justify-#{$justify} {
49 | justify-content: #{$justify};
50 | }
51 |
52 | &.justify-self-#{$justify} {
53 | justify-self: #{$justify};
54 | }
55 | }
56 | }
57 |
58 | @each $gap in $gaps {
59 | &.row-gap-#{$gap} {
60 | grid-row-gap: #{$gap}px;
61 | }
62 |
63 | &.col-gap-#{$gap} {
64 | grid-column-gap: #{$gap}px;
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/stories/assets/repo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/safari-pinned-tab.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
26 |
--------------------------------------------------------------------------------
/src/wallets/components/install-metamask-modal/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import Button from 'components/antd/button';
4 | import Modal, { ModalProps } from 'components/antd/modal';
5 | import Grid from 'components/custom/grid';
6 | import { Text } from 'components/custom/typography';
7 |
8 | const METAMASK_CHROME_EXT_URL = 'https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn';
9 |
10 | const InstallMetaMaskModal: React.FC
27 | Once you have installed it, please refresh the page
28 |
52 | {tokenNames.map((name, idx) => (
53 |
67 | >
68 | );
69 |
--------------------------------------------------------------------------------
/src/utils/chart.ts:
--------------------------------------------------------------------------------
1 | import { PeriodTabsKey } from 'components/custom/tabs';
2 |
3 | import { formatDate, formatTime } from './date';
4 |
5 | export function formatTick(value: string, filter: string) {
6 | if (typeof value !== 'string') {
7 | return '';
8 | }
9 |
10 | const date = new Date(value);
11 |
12 | if (date.toString() === 'Invalid Date') {
13 | return '';
14 | }
15 |
16 | switch (filter) {
17 | case PeriodTabsKey.day:
18 | return formatTime(date);
19 | case PeriodTabsKey.week:
20 | return formatDate(date, { weekday: 'short' });
21 | case PeriodTabsKey.month:
22 | return formatDate(date, { month: '2-digit', day: '2-digit' });
23 | default:
24 | return '';
25 | }
26 | }
27 |
28 | export function generateTicks(items: { point: string }[], filter: string): number[] {
29 | const dates = items.map(d => new Date(d.point).getTime());
30 | const minDate = Math.min(...dates);
31 | const maxDate = Math.max(...dates);
32 |
33 | if (!Number.isFinite(minDate) || !Number.isFinite(maxDate)) {
34 | return [];
35 | }
36 |
37 | let count = 0;
38 | let range = 0;
39 |
40 | switch (filter) {
41 | case '24h':
42 | count = 3;
43 | range = 8 * 60 * 60 * 1_000; // 8 hours
44 | break;
45 | case '1w':
46 | count = 7;
47 | range = 24 * 60 * 60 * 1_000; // 24 hours
48 | break;
49 | case '30d':
50 | count = 4;
51 | range = 7 * 24 * 60 * 60 * 1_000; // 7 days
52 | break;
53 | default:
54 | return [];
55 | }
56 |
57 | const minDt = maxDate - count * range;
58 |
59 | return Array.from({ length: count + 1 }).map((_, index) => minDt + range * index);
60 | // .map(tick => new Date(tick).toJSON());
61 | }
62 |
--------------------------------------------------------------------------------
/src/components/modal/s.module.scss:
--------------------------------------------------------------------------------
1 | .dialog {
2 | position: fixed;
3 | top: 0;
4 | right: 0;
5 | bottom: 0;
6 | left: 0;
7 | background: rgba(0, 0, 0, 0.6);
8 | z-index: 10;
9 | }
10 |
11 | .inner {
12 | position: absolute;
13 | top: 50%;
14 | left: 50%;
15 | transform: translate(-50%, -50%);
16 | width: 100%;
17 | max-width: 578px;
18 | background-color: var(--theme-card-color);
19 | border-radius: 4px;
20 | padding: 32px;
21 | overflow-y: auto;
22 | max-height: 100vh;
23 |
24 | &.fullscreen {
25 | max-width: none;
26 | height: 100%;
27 | border-radius: 0;
28 | padding: 64px;
29 | }
30 |
31 | @media (max-width: 768px) {
32 | top: auto;
33 | bottom: 16px;
34 | left: 16px;
35 | right: 16px;
36 | transform: none;
37 | max-width: initial;
38 | width: auto;
39 | }
40 | }
41 |
42 | .closeButton {
43 | background-color: transparent;
44 | border: 0;
45 | padding: 0;
46 | display: flex;
47 | flex-shrink: 0;
48 | color: var(--theme-icon-color);
49 |
50 | &:hover {
51 | color: var(--theme-icon-hover-color);
52 | }
53 |
54 | &.fullscreen {
55 | background-color: rgba(var(--theme-border-color-rgb), 0.4);
56 | padding: 8px;
57 | border-radius: 50%;
58 | }
59 | }
60 |
61 | .header {
62 | // padding: 32px;
63 | // border-bottom: 1px solid #ccc;
64 | max-width: 1240px;
65 | margin-left: auto;
66 | margin-right: auto;
67 | margin-bottom: 32px;
68 | display: flex;
69 | align-items: center;
70 | }
71 |
72 | .heading {
73 | flex-grow: 1;
74 | display: flex;
75 | align-items: center;
76 | }
77 |
78 | .content {
79 | &.fullscreen {
80 | max-width: 1240px;
81 | margin-left: auto;
82 | margin-right: auto;
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/components/antd/tabs/s.module.scss:
--------------------------------------------------------------------------------
1 | .tabs {
2 | > :global(.ant-tabs-nav) {
3 | margin: 0;
4 | padding: 0 24px;
5 | background: var(--theme-card-color);
6 | border: 1px solid var(--theme-border-color);
7 |
8 | &::before {
9 | border: 0;
10 | }
11 |
12 | > :global(.ant-tabs-nav-wrap) {
13 | > :global(.ant-tabs-nav-list) {
14 | > :global(.ant-tabs-tab) {
15 | > :global(.ant-tabs-tab-btn) {
16 | font: var(--font-p1);
17 | font-weight: 600;
18 | display: flex;
19 | flex-direction: row;
20 | column-gap: 8px;
21 | align-items: center;
22 | color: var(--theme-secondary-color);
23 |
24 | &:hover {
25 | color: var(--theme-primary-color);
26 |
27 | svg {
28 | color: var(--theme-red-color);
29 | }
30 | }
31 |
32 | svg {
33 | :global(.no-flexbox-gap) & {
34 | margin-right: 8px;
35 | }
36 | }
37 | }
38 |
39 | &:global(.ant-tabs-tab-active) {
40 | > :global(.ant-tabs-tab-btn) {
41 | color: var(--theme-primary-color);
42 |
43 | > svg {
44 | color: var(--theme-red-color);
45 | }
46 | }
47 | }
48 | }
49 |
50 | > :global(.ant-tabs-ink-bar) {
51 | height: 2px;
52 | background: var(--theme-red-color);
53 | border-radius: 4px 4px 0 0;
54 | }
55 | }
56 | }
57 | }
58 |
59 | &.simple {
60 | > :global(.ant-tabs-nav) {
61 | padding: 0;
62 | background: transparent;
63 | border: 0;
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/components/warning/index.tsx:
--------------------------------------------------------------------------------
1 | import { useLocalStorage } from 'react-use-storage';
2 | import classNames from 'classnames';
3 |
4 | import { Button } from 'components/button';
5 | import Grid from 'components/custom/grid';
6 | import { Text } from 'components/custom/typography';
7 | import { Icon } from 'components/icon';
8 | import { WarnType, useNotifications } from 'components/providers/notificationsProvider';
9 |
10 | import s from './s.module.scss';
11 |
12 | type WarnProps = WarnType & {
13 | onClose?: () => void;
14 | };
15 |
16 | const Warn: React.FC