From a443d1fad42b59f5d2b3d774b9d2ba90e68bc8be Mon Sep 17 00:00:00 2001 From: Aleksandar Djordjevic Date: Tue, 28 Jul 2020 13:52:26 +0200 Subject: [PATCH 01/12] Adding stake pool api integration with graphql --- .../stake-pools/api/StakePoolBool.graphql | 16 ++++ .../stake-pools/api/StakePoolOrderBy.graphql | 8 ++ .../stake-pools/api/StakePoolOverview.graphql | 17 ++++ .../stake-pools/api/getStakePools.graphql | 19 +++++ source/features/stake-pools/api/index.ts | 20 +++++ .../features/stake-pools/api/transformers.ts | 80 +++++++++++++++++++ 6 files changed, 160 insertions(+) create mode 100644 source/features/stake-pools/api/StakePoolBool.graphql create mode 100644 source/features/stake-pools/api/StakePoolOrderBy.graphql create mode 100644 source/features/stake-pools/api/StakePoolOverview.graphql create mode 100644 source/features/stake-pools/api/getStakePools.graphql create mode 100644 source/features/stake-pools/api/index.ts create mode 100644 source/features/stake-pools/api/transformers.ts diff --git a/source/features/stake-pools/api/StakePoolBool.graphql b/source/features/stake-pools/api/StakePoolBool.graphql new file mode 100644 index 00000000..085e63e2 --- /dev/null +++ b/source/features/stake-pools/api/StakePoolBool.graphql @@ -0,0 +1,16 @@ +fragment StakePoolBool on StakePool_bool_exp { + _and + _not + _o + hash + margin + metadataHash + owners + pledge + registrationTransaction + relays + retirement + rewardAddress + url + withdrawals +} diff --git a/source/features/stake-pools/api/StakePoolOrderBy.graphql b/source/features/stake-pools/api/StakePoolOrderBy.graphql new file mode 100644 index 00000000..3f935bf0 --- /dev/null +++ b/source/features/stake-pools/api/StakePoolOrderBy.graphql @@ -0,0 +1,8 @@ +fragment StakePoolOrder on StakePool_order_by { + fixedCost + hash + margin + pledge + updatedIn + url +} diff --git a/source/features/stake-pools/api/StakePoolOverview.graphql b/source/features/stake-pools/api/StakePoolOverview.graphql new file mode 100644 index 00000000..a7403237 --- /dev/null +++ b/source/features/stake-pools/api/StakePoolOverview.graphql @@ -0,0 +1,17 @@ +fragment StakePoolOverivew on StakePool { + fixedCost + hash + margin + metadataHash + owners + pledge, + relays + retirement { + announcedIn + retirement + } + rewardAddress + updatedIn + url + withdrawals +} diff --git a/source/features/stake-pools/api/getStakePools.graphql b/source/features/stake-pools/api/getStakePools.graphql new file mode 100644 index 00000000..91d57071 --- /dev/null +++ b/source/features/stake-pools/api/getStakePools.graphql @@ -0,0 +1,19 @@ +#import "./StakePoolOverview.graphql" +#import "./StakePoolOrderBy.graphql" +#import "./StakePoolBool.graphql" + +query getStakePools( + $limit: Int! + $order: [StakePoolOrder!] + $offset: Int! + $where: StakePoolBool +) { + stakePools( + limit: $limit + order_by: $order + where: $where + offset: $offset + ) { + ...StakePoolOverview + } +} diff --git a/source/features/stake-pools/api/index.ts b/source/features/stake-pools/api/index.ts new file mode 100644 index 00000000..0526eb52 --- /dev/null +++ b/source/features/stake-pools/api/index.ts @@ -0,0 +1,20 @@ +import { GraphQLClient } from 'graphql-request'; +import { + GetStakePoolsQuery, + GetStakePoolsQueryVariables, +} from '../../../../generated/typings/graphql-schema'; +import { GraphQLRequest } from '../../../lib/graphql/GraphQLRequest'; +import getStakePoolsQuery from './getBlocksInRange.graphql'; + +export class StakePoolsApi { + public getStakePoolsQuery: GraphQLRequest< + GetStakePoolsQuery, + GetStakePoolsQueryVariables + >; + constructor(client: GraphQLClient) { + this.getStakePoolsQuery = new GraphQLRequest( + client, + getStakePoolsQuery + ); + } +} diff --git a/source/features/stake-pools/api/transformers.ts b/source/features/stake-pools/api/transformers.ts new file mode 100644 index 00000000..abf6340c --- /dev/null +++ b/source/features/stake-pools/api/transformers.ts @@ -0,0 +1,80 @@ +import { Currency } from 'cardano-js'; +import { + BlockDetailsFragment, + BlockOverviewFragment, +} from '../../../../generated/typings/graphql-schema'; +import { isDefined } from '../../../lib/types'; +import { transactionDetailsTransformer } from '../../transactions/api/transformers'; +import { IBlockDetailed, IBlockOverview } from '../types'; + +export const blockOverviewTransformer = ( + b: BlockOverviewFragment +): IBlockOverview => { + let epoch: number | '-'; + if (!b.epochNo && b.epochNo !== 0) { + epoch = '-'; + } else { + epoch = b.epochNo; + } + return { + ...b, + createdAt: b.forgedAt, + createdBy: formatCreatedBy(b.slotLeader.description), + epoch, + id: b.hash, + number: b.number || '-', + output: Currency.Util.lovelacesToAda( + b.transactions_aggregate?.aggregate?.sum?.totalOutput || '0' + ), + slotWithinEpoch: formatSlotWithinEpoch(b.slotNo), + transactionsCount: + b.transactions_aggregate?.aggregate?.count.toString() || '0', + }; +}; + +export const blockDetailsTransformer = ( + b: BlockDetailsFragment +): IBlockDetailed => ({ + ...blockOverviewTransformer(b), + merkleRoot: b.merkelRoot || '', + nextBlock: { + id: b.nextBlock?.hash || '', + number: b.nextBlock?.number || '-', + }, + prevBlock: { + id: b.previousBlock?.hash || '', + number: b.previousBlock?.number || '-', + }, + transactions: b.transactions + .filter(isDefined) + .map(transactionDetailsTransformer), +}); + +function formatCreatedBy(value: IBlockOverview['createdBy']): string { + + switch (value) { + case 'Genesis slot leader': + return 'Genesis'; + case 'Epoch boundary slot leader': + return 'EBB'; + default: + const selection = value.split('-'); + if (!Array.isArray(selection)) { + return '' + } + return selection[1].substring(0,7) + } +} + +function formatSlotWithinEpoch( + value: BlockOverviewFragment['slotNo'] +): IBlockOverview['slotWithinEpoch'] { + switch (value) { + case 0: + return value; + case null || undefined: + return '-'; + default: + return value || '-'; + } +} From 6fd621616e86bbe0dba6f46f7aa20d16a4d59254 Mon Sep 17 00:00:00 2001 From: Aleksandar Djordjevic Date: Wed, 29 Jul 2020 22:32:59 +0200 Subject: [PATCH 02/12] Adding stake pool api integration with graphql --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index bbf4860d..d2ea2a1e 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,8 @@ "prettier:format": "yarn prettier --write --loglevel warn", "prettier:fix-staged": "pretty-quick --staged", "storybook": "start-storybook -s ./source/public -p 6006", - "storybook:build": "build-storybook -o build/storybook" + "storybook:build": "build-storybook -o build/storybook", + "next": "next dev source -p 4000" }, "husky": { "hooks": { From dbaf02ce50829d0f9146eaf1fc1cfc73cb8bf62c Mon Sep 17 00:00:00 2001 From: Dominik Guzei Date: Thu, 3 Sep 2020 17:45:44 +0200 Subject: [PATCH 03/12] issue-333 Fix stake pools graphQL query --- .../stake-pools/api/StakePoolBool.graphql | 16 ---- .../stake-pools/api/StakePoolOrderBy.graphql | 8 -- .../stake-pools/api/StakePoolOverview.graphql | 18 +++-- .../stake-pools/api/getStakePools.graphql | 6 +- .../features/stake-pools/api/transformers.ts | 80 ------------------- 5 files changed, 13 insertions(+), 115 deletions(-) delete mode 100644 source/features/stake-pools/api/StakePoolBool.graphql delete mode 100644 source/features/stake-pools/api/StakePoolOrderBy.graphql diff --git a/source/features/stake-pools/api/StakePoolBool.graphql b/source/features/stake-pools/api/StakePoolBool.graphql deleted file mode 100644 index 085e63e2..00000000 --- a/source/features/stake-pools/api/StakePoolBool.graphql +++ /dev/null @@ -1,16 +0,0 @@ -fragment StakePoolBool on StakePool_bool_exp { - _and - _not - _o - hash - margin - metadataHash - owners - pledge - registrationTransaction - relays - retirement - rewardAddress - url - withdrawals -} diff --git a/source/features/stake-pools/api/StakePoolOrderBy.graphql b/source/features/stake-pools/api/StakePoolOrderBy.graphql deleted file mode 100644 index 3f935bf0..00000000 --- a/source/features/stake-pools/api/StakePoolOrderBy.graphql +++ /dev/null @@ -1,8 +0,0 @@ -fragment StakePoolOrder on StakePool_order_by { - fixedCost - hash - margin - pledge - updatedIn - url -} diff --git a/source/features/stake-pools/api/StakePoolOverview.graphql b/source/features/stake-pools/api/StakePoolOverview.graphql index a7403237..329c01d6 100644 --- a/source/features/stake-pools/api/StakePoolOverview.graphql +++ b/source/features/stake-pools/api/StakePoolOverview.graphql @@ -1,17 +1,21 @@ -fragment StakePoolOverivew on StakePool { +fragment StakePoolOverview on StakePool { fixedCost hash margin metadataHash - owners + owners { + hash + } pledge, - relays retirement { - announcedIn - retirement + announcedIn { + includedAt + } + inEffectFrom { + number + startedAt + } } rewardAddress - updatedIn url - withdrawals } diff --git a/source/features/stake-pools/api/getStakePools.graphql b/source/features/stake-pools/api/getStakePools.graphql index 91d57071..c0ff7299 100644 --- a/source/features/stake-pools/api/getStakePools.graphql +++ b/source/features/stake-pools/api/getStakePools.graphql @@ -1,12 +1,10 @@ #import "./StakePoolOverview.graphql" -#import "./StakePoolOrderBy.graphql" -#import "./StakePoolBool.graphql" query getStakePools( $limit: Int! - $order: [StakePoolOrder!] + $order: [StakePool_order_by!] $offset: Int! - $where: StakePoolBool + $where: StakePool_bool_exp ) { stakePools( limit: $limit diff --git a/source/features/stake-pools/api/transformers.ts b/source/features/stake-pools/api/transformers.ts index abf6340c..e69de29b 100644 --- a/source/features/stake-pools/api/transformers.ts +++ b/source/features/stake-pools/api/transformers.ts @@ -1,80 +0,0 @@ -import { Currency } from 'cardano-js'; -import { - BlockDetailsFragment, - BlockOverviewFragment, -} from '../../../../generated/typings/graphql-schema'; -import { isDefined } from '../../../lib/types'; -import { transactionDetailsTransformer } from '../../transactions/api/transformers'; -import { IBlockDetailed, IBlockOverview } from '../types'; - -export const blockOverviewTransformer = ( - b: BlockOverviewFragment -): IBlockOverview => { - let epoch: number | '-'; - if (!b.epochNo && b.epochNo !== 0) { - epoch = '-'; - } else { - epoch = b.epochNo; - } - return { - ...b, - createdAt: b.forgedAt, - createdBy: formatCreatedBy(b.slotLeader.description), - epoch, - id: b.hash, - number: b.number || '-', - output: Currency.Util.lovelacesToAda( - b.transactions_aggregate?.aggregate?.sum?.totalOutput || '0' - ), - slotWithinEpoch: formatSlotWithinEpoch(b.slotNo), - transactionsCount: - b.transactions_aggregate?.aggregate?.count.toString() || '0', - }; -}; - -export const blockDetailsTransformer = ( - b: BlockDetailsFragment -): IBlockDetailed => ({ - ...blockOverviewTransformer(b), - merkleRoot: b.merkelRoot || '', - nextBlock: { - id: b.nextBlock?.hash || '', - number: b.nextBlock?.number || '-', - }, - prevBlock: { - id: b.previousBlock?.hash || '', - number: b.previousBlock?.number || '-', - }, - transactions: b.transactions - .filter(isDefined) - .map(transactionDetailsTransformer), -}); - -function formatCreatedBy(value: IBlockOverview['createdBy']): string { - - switch (value) { - case 'Genesis slot leader': - return 'Genesis'; - case 'Epoch boundary slot leader': - return 'EBB'; - default: - const selection = value.split('-'); - if (!Array.isArray(selection)) { - return '' - } - return selection[1].substring(0,7) - } -} - -function formatSlotWithinEpoch( - value: BlockOverviewFragment['slotNo'] -): IBlockOverview['slotWithinEpoch'] { - switch (value) { - case 0: - return value; - case null || undefined: - return '-'; - default: - return value || '-'; - } -} From a06e1e2780caee723448f45afebf4d1293165ba1 Mon Sep 17 00:00:00 2001 From: Dominik Guzei Date: Thu, 3 Sep 2020 17:52:18 +0200 Subject: [PATCH 04/12] issue-333 Fix graphql dev endpoint --- source/environment.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/environment.ts b/source/environment.ts index 47396a97..58826f0e 100755 --- a/source/environment.ts +++ b/source/environment.ts @@ -9,9 +9,9 @@ export const environment = { GRAPHQL: { HTTP_URL: `${process.env.GRAPHQL_API_PROTOCOL || 'https'}://${ process.env.GRAPHQL_API_HOST || - 'cardano-graphql-mainnet.daedalus-operations.com' + `explorer.cardano-${process.env.CARDANO_NETWORK || 'mainnet'}.iohk.io` }:${process.env.GRAPHQL_API_PORT || '443'}/${ - process.env.GRAPHQL_API_PATH || '' + process.env.GRAPHQL_API_PATH || 'graphql' }`, }, NETWORK: @@ -24,7 +24,7 @@ export const environment = { IS_SERVER: !isNavigatorDefined, PACKAGE: { HOMEPAGE: process.env.PACKAGE_HOMEPAGE, - VERSION: process.env.PACKAGE_VERSION + VERSION: process.env.PACKAGE_VERSION, }, POLLING_INTERVAL: Number(process.env.POLLING_INTERVAL) || 10000, }; From 14d1b12e06596f60067d9d4b87b059812d2d4d28 Mon Sep 17 00:00:00 2001 From: Dominik Guzei Date: Thu, 3 Sep 2020 19:05:13 +0200 Subject: [PATCH 05/12] issue-333 Prepare stake pools page to match design --- .../epochs/ui/EpochProgress.module.scss | 24 ++++++ .../epochs/ui/EpochSummary.module.scss | 57 +-------------- source/features/epochs/ui/EpochSummary.tsx | 19 ++--- .../epochs/ui/EpochSummaryProgress.tsx | 25 +++++++ .../landing-page/LandingPage.module.scss | 73 ------------------- source/features/landing-page/LandingPage.tsx | 26 +------ .../components/StakePoolsSearch.tsx | 3 + .../StakePoolsComponentContainer.tsx | 6 +- .../ui/StakePoolStatistics.module.scss | 16 ++++ .../stake-pools/ui/StakePoolStatistics.tsx | 55 ++++++++++++++ .../stake-pools/ui/StakePoolsPage.module.scss | 6 ++ .../stake-pools/ui/StakePoolsPage.tsx | 43 +++++++++++ .../stake-pools/ui/pages/StakePoolsPage.tsx | 56 -------------- source/pages/[locale]/stake-pools.tsx | 2 +- source/styles/mixins/info-panel.scss | 30 ++++++++ .../layout/EnlargedHeaderLayout.module.scss | 72 ++++++++++++++++++ .../widgets/layout/EnlargedHeaderLayout.tsx | 34 +++++++++ source/widgets/layout/Header.tsx | 13 ++-- 18 files changed, 326 insertions(+), 234 deletions(-) create mode 100644 source/features/epochs/ui/EpochProgress.module.scss create mode 100644 source/features/epochs/ui/EpochSummaryProgress.tsx create mode 100644 source/features/stake-pools/ui/StakePoolStatistics.module.scss create mode 100644 source/features/stake-pools/ui/StakePoolStatistics.tsx create mode 100644 source/features/stake-pools/ui/StakePoolsPage.module.scss create mode 100644 source/features/stake-pools/ui/StakePoolsPage.tsx delete mode 100644 source/features/stake-pools/ui/pages/StakePoolsPage.tsx create mode 100644 source/styles/mixins/info-panel.scss create mode 100644 source/widgets/layout/EnlargedHeaderLayout.module.scss create mode 100644 source/widgets/layout/EnlargedHeaderLayout.tsx diff --git a/source/features/epochs/ui/EpochProgress.module.scss b/source/features/epochs/ui/EpochProgress.module.scss new file mode 100644 index 00000000..2f60204b --- /dev/null +++ b/source/features/epochs/ui/EpochProgress.module.scss @@ -0,0 +1,24 @@ +.progressTextContent { + align-items: center; + display: flex; + flex-direction: column; + justify-content: center; +} + +.progressTextLabel { + color: var(--info-text-color); + font-family: ProximaNova, sans-serif; + font-size: 10px; + font-weight: 300; + letter-spacing: 0.5px; + line-height: 1.4; + margin-bottom: 5px; +} + +.progressTextValue { + color: var(--solid-text-color); + font-family: ProximaNova, sans-serif; + font-size: 46px; + font-weight: 300; + letter-spacing: 2.3px; +} diff --git a/source/features/epochs/ui/EpochSummary.module.scss b/source/features/epochs/ui/EpochSummary.module.scss index 0e164383..260aab51 100644 --- a/source/features/epochs/ui/EpochSummary.module.scss +++ b/source/features/epochs/ui/EpochSummary.module.scss @@ -1,3 +1,5 @@ +@import '../../../styles/mixins/info-panel'; + .epochSummaryContainer { margin: 0 auto; max-width: 872px; @@ -11,60 +13,7 @@ align-items: center; display: flex; - .progressTextContent { - align-items: center; - display: flex; - flex-direction: column; - justify-content: center; - - .progressTextLabel { - color: var(--info-text-color); - font-family: ProximaNova, sans-serif; - font-size: 10px; - font-weight: 300; - letter-spacing: 0.5px; - line-height: 1.4; - margin-bottom: 5px; - } - - .progressTextValue { - color: var(--solid-text-color); - font-family: ProximaNova, sans-serif; - font-size: 46px; - font-weight: 300; - letter-spacing: 2.3px; - } - } - - .infoPanel { - color: var(--info-text-color); - margin-left: 60px; - - .infoRow { - align-items: center; - display: flex; - font-size: 12px; - letter-spacing: 0.6px; - line-height: 1.33; - margin-bottom: 10px; - - .infoLabel { - font-family: ProximaNova, sans-serif; - font-weight: 600; - width: 130px; - } - - .infoValue { - font-family: ProximaNova, sans-serif; - font-weight: 300; - } - } - - @media (max-width: 768px) { - margin-left: 0; - padding-top: 40px; - } - } + @include info-panel($label-width: 130px); @media (max-width: 768px) { flex-direction: column; diff --git a/source/features/epochs/ui/EpochSummary.tsx b/source/features/epochs/ui/EpochSummary.tsx index a11c8006..9b771307 100644 --- a/source/features/epochs/ui/EpochSummary.tsx +++ b/source/features/epochs/ui/EpochSummary.tsx @@ -1,13 +1,12 @@ import dayjs from 'dayjs'; import utc from 'dayjs/plugin/utc'; import { observer } from 'mobx-react-lite'; -import CircularProgress, { - CircularProgressSize, -} from '../../../widgets/circular-progress/CircularProgress'; +import React from 'react'; import DividerWithTitle from '../../../widgets/divider-with-title/DividerWithTitle'; import { useI18nFeature } from '../../i18n/context'; import { IEpochOverview } from '../types'; import styles from './EpochSummary.module.scss'; +import { EpochSummaryProgress } from './EpochSummaryProgress'; dayjs.extend(utc); @@ -24,18 +23,10 @@ const EpochSummary = ({ title, epoch }: IEpochSummaryProps) => {
- -
- {translate('epochSummary.epoch')} -
-
{epoch.number}
-
- } + title={translate('epochSummary.epoch')} />
diff --git a/source/features/epochs/ui/EpochSummaryProgress.tsx b/source/features/epochs/ui/EpochSummaryProgress.tsx new file mode 100644 index 00000000..b10a948e --- /dev/null +++ b/source/features/epochs/ui/EpochSummaryProgress.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import CircularProgress, { + CircularProgressSize, +} from '../../../widgets/circular-progress/CircularProgress'; +import styles from './EpochProgress.module.scss'; + +export interface IEpochProgressProps { + epochNumber: number; + percentage: number; + title: string; +} + +export const EpochSummaryProgress = (props: IEpochProgressProps) => ( + +
{props.title}
+
{props.epochNumber}
+
+ } + /> +); diff --git a/source/features/landing-page/LandingPage.module.scss b/source/features/landing-page/LandingPage.module.scss index fdd3d4e8..758ad61c 100644 --- a/source/features/landing-page/LandingPage.module.scss +++ b/source/features/landing-page/LandingPage.module.scss @@ -1,48 +1,3 @@ -.headerBgContainer { - display: flex; - justify-content: center; - left: 0; - position: absolute; - top: 0; - width: 100%; - - .headerBg { - display: flex; - flex-direction: column; - align-items: center; - position: relative; - img { - height: 415px; - margin-top: -25px; - margin-left: 11px; - } - } -} - -.sideBgContainer { - position: absolute; - bottom: 0; - height: 100%; - width: 100%; - display: flex; - z-index: -1; -} - -.sideBackgroundImageContainer { - align-items: flex-end; - bottom: 0; - display: flex; - position: absolute; - right: 0; - - .sideBackgroundImage { - height: auto; - object-fit: contain; - opacity: 0.3; - width: 596.5px; - } -} - .epochList { margin-top: 71px; margin-bottom: 21px; @@ -60,31 +15,3 @@ margin-bottom: 83px; } } - -.footer { - padding: 0 0 92px; -} - -.mainNetHeaderImage, -.testNetHeaderImage { - left: 0; - margin-left: auto; - margin-right: auto; - position: absolute; - right: 0; - top: -113px; - width: 1100px; - - @media (max-width: 1000px) { - width: 100%; - } - - @media (max-width: 768px) { - display: none; - } -} - -.testNetHeaderImage { - top: -173px !important; - width: 620px !important; -} diff --git a/source/features/landing-page/LandingPage.tsx b/source/features/landing-page/LandingPage.tsx index dd592118..d8789890 100755 --- a/source/features/landing-page/LandingPage.tsx +++ b/source/features/landing-page/LandingPage.tsx @@ -1,19 +1,13 @@ import Head from 'next/head'; import React from 'react'; -import { BrandType, CardanoNetwork } from '../../constants'; -import { environment } from '../../environment'; import { StaticLayoutProps } from '../../lib/types'; -import SideBackgroundImage from '../../public/assets/images/main-side-background.svg'; -import { Footer, Header, Layout } from '../../widgets/layout'; +import { EnlargedHeaderLayout } from '../../widgets/layout/EnlargedHeaderLayout'; import { BlocksFeatureProvider } from '../blocks/ui/BlocksFeatureProvider'; import { LatestBlocks } from '../blocks/ui/LatestBlocks'; import { EpochsFeatureProvider } from '../epochs/ui/EpochsFeatureProvider'; import { LatestEpochs } from '../epochs/ui/LatestEpochs'; import { useI18nFeature } from '../i18n/context'; import { i18nInitialProps } from '../i18n/utils'; -import { SearchBar } from '../search/ui/SearchBar'; -const mainNetHeaderImage = require('../../public/assets/images/header/mainnet.png'); -const testNetHeaderImage = require('../../public/assets/images/header/testnet.png'); import styles from './LandingPage.module.scss'; export const LandingPage = () => ( @@ -36,23 +30,7 @@ const StaticLayout = (props: StaticLayoutProps) => { {translate('index.pageTitle')} - {environment.CARDANO.NETWORK === CardanoNetwork.MAINNET && ( - - )} - {environment.CARDANO.NETWORK === CardanoNetwork.TESTNET && ( - - )} - -
- - {props.children} -