From 0091fc6e57f10e2ed10a6cbb2ea052f5faa6a0c7 Mon Sep 17 00:00:00 2001 From: Thibaut Sardan <33178835+Tbaut@users.noreply.github.com> Date: Tue, 26 May 2020 11:49:12 +0200 Subject: [PATCH] Add attestation to claims (#2734) * init * Attest component * Add top notification bar * better english * back to 3 steps * clean up * in the middle of the refactoring * Make TS pass * Clea up some comments * isPreclaimed * isOldClaimProcess * Attest vs Claim (#2737) * Choose between Claim and Attest * fix lint * fix flow between claim and attest (#2738) * Jaco's comments + Fetch StatementKind (#2741) * Fix small bug in flow * Add condition for the warning banner (#2742) * prevent crash for older chains * with useEffect * should work * back to something simple * remove hoc * fix CI * Add ETH address field for non preclaimed addresses (#2746) * Eth field * fix * remove stray logs * Update packages/page-claims/src/index.tsx Co-authored-by: Jaco Greeff * Update packages/page-claims/src/index.tsx Co-authored-by: Jaco Greeff * Update packages/apps/src/overlays/Attest.tsx Co-authored-by: Jaco Greeff * Show the amount of token that will be claimed (#2747) * show amount in attest * fix isApiReady * fix lint * Use counter instead of overlay (#2750) * Use counter instead of overlay * Add warning to claim (#2752) * add warning * css cleanup * fix unused const Co-authored-by: Thibaut Sardan <33178835+Tbaut@users.noreply.github.com> * Update packages/page-claims/src/Warning.tsx Co-authored-by: Jaco Greeff * Update packages/page-claims/src/index.tsx Co-authored-by: Jaco Greeff * Update packages/page-claims/src/index.tsx Co-authored-by: Jaco Greeff * Update packages/page-claims/src/index.tsx Co-authored-by: Jaco Greeff * Update packages/page-claims/src/index.tsx Co-authored-by: Jaco Greeff * address comment shortcut * set Ethereum address outside transfor and fix typos * lint * extract claims.preclaims to a hook * address comments EthereumAddress type and avoid casting * Missing isUnsigned * use AddressMini in warning * use a proper step for eth address field * Add loading state * remove log * unwrapOrNull * Update packages/page-claims/src/Warning.tsx Co-authored-by: Jaco Greeff * fix for account plural translation * lint * Add getStatement function * nits * Fix lint * Update packages/page-claims/src/Warning.tsx Co-authored-by: Jaco Greeff * add statement * statement component * address comment unWrapOr * test styling with long md * add md to jest * Update packages/page-claims/src/Statement.tsx Co-authored-by: Amaury Martiny * copy text before * lint * Remove EthreumAddress type to avoid unexpected behaviors (#2796) * remove EthreumAddress type * createType when needed * revert * typo * Enhance UX for claim process (#2797) * update content * init * comment * Add HTML components for statements (#2798) * Add HTML components for statements * Update packages/page-claims/src/statements/saft.tsx * Update to final statements * More nits * Nits * OnSuccess * prevent display of empty statement when attested * Small fixmes * Update packages/page-claims/src/index.tsx * fix isError not being red as expected * remove word-break * statement text in black * attestation for -> accounc balance * Update packages/page-claims/src/Statement.tsx Co-authored-by: Logan Saether * margin left instead of space * I agree * Use iframe * update saft to QmXEkMahfhHJPzT3RjkXiZVFi77ZeVeuxtAjhojGRNYckz * remove hash and duplications (#2814) Co-authored-by: Amaury Martiny Co-authored-by: Jaco Greeff Co-authored-by: Logan Saether --- packages/apps-routing/src/claims.ts | 5 +- packages/page-claims/src/Attest.tsx | 87 ++++ packages/page-claims/src/Claim.tsx | 139 +++--- packages/page-claims/src/Statement.tsx | 82 ++++ packages/page-claims/src/Warning.tsx | 57 +++ packages/page-claims/src/index.tsx | 418 ++++++++++-------- packages/page-claims/src/useCounter.ts | 11 + .../src/usePreclaimPolkadotAddresses.ts | 27 ++ packages/page-claims/src/util.ts | 33 +- packages/react-components/src/Card.tsx | 2 +- 10 files changed, 627 insertions(+), 234 deletions(-) create mode 100644 packages/page-claims/src/Attest.tsx create mode 100644 packages/page-claims/src/Statement.tsx create mode 100644 packages/page-claims/src/Warning.tsx create mode 100644 packages/page-claims/src/useCounter.ts create mode 100644 packages/page-claims/src/usePreclaimPolkadotAddresses.ts diff --git a/packages/apps-routing/src/claims.ts b/packages/apps-routing/src/claims.ts index 1e6a144685..42a63c4cb4 100644 --- a/packages/apps-routing/src/claims.ts +++ b/packages/apps-routing/src/claims.ts @@ -4,7 +4,7 @@ import { Route } from './types'; -import Claims from '@polkadot/app-claims'; +import Claims, { useCounter } from '@polkadot/app-claims'; export default function create (t: (key: string, text: string, options: { ns: string }) => T): Route { return { @@ -17,6 +17,7 @@ export default function create (t: (key: string, text: string, opti }, icon: 'star', name: 'claims', - text: t('nav.claims', 'Claim Tokens', { ns: 'apps-routing' }) + text: t('nav.claims', 'Claim Tokens', { ns: 'apps-routing' }), + useCounter }; } diff --git a/packages/page-claims/src/Attest.tsx b/packages/page-claims/src/Attest.tsx new file mode 100644 index 0000000000..5416278c0f --- /dev/null +++ b/packages/page-claims/src/Attest.tsx @@ -0,0 +1,87 @@ +// Copyright 2017-2020 @polkadot/app-claims authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import React, { useEffect, useState } from 'react'; +import styled from 'styled-components'; +import { Button, Card, TxButton } from '@polkadot/react-components'; +import { TxCallback } from '@polkadot/react-components/Status/types'; +import { useApi } from '@polkadot/react-hooks'; +import { FormatBalance } from '@polkadot/react-query'; +import { Option } from '@polkadot/types'; +import { BalanceOf, EthereumAddress, StatementKind } from '@polkadot/types/interfaces'; + +import { ClaimStyles } from './Claim'; +import Statement from './Statement'; +import { useTranslation } from './translate'; +import { getStatement } from './util'; + +interface Props { + accountId: string; + className?: string; + ethereumAddress: EthereumAddress | null; + onSuccess?: TxCallback; + statementKind?: StatementKind; + systemChain: string; +} + +function Attest ({ accountId, className, ethereumAddress, onSuccess, statementKind, systemChain }: Props): React.ReactElement | null { + const { t } = useTranslation(); + const { api } = useApi(); + const [claimValue, setClaimValue] = useState(null); + const [isBusy, setIsBusy] = useState(false); + + useEffect((): void => { + if (!ethereumAddress) { + return; + } + + setIsBusy(true); + + api.query.claims + .claims>(ethereumAddress) + .then((claim): void => { + setClaimValue(claim.unwrapOr(null)); + setIsBusy(false); + }) + .catch((): void => setIsBusy(false)); + }, [api, ethereumAddress]); + + if (isBusy) { + return null; + } + + const hasClaim = claimValue && claimValue.gten(0); + const statementSentence = getStatement(systemChain, statementKind)?.sentence; + + if (!hasClaim || !statementSentence) { + return null; + } + + return ( + +
+ +

('Account balance:')} + value={claimValue} />

+ + ('I agree')} + onSuccess={onSuccess} + params={[statementSentence]} + tx='claims.attest' + /> + +
+
+ ); +} + +export default React.memo(styled(Attest)`${ClaimStyles}`); diff --git a/packages/page-claims/src/Claim.tsx b/packages/page-claims/src/Claim.tsx index ab2c6fa811..cf55a636ae 100644 --- a/packages/page-claims/src/Claim.tsx +++ b/packages/page-claims/src/Claim.tsx @@ -3,52 +3,75 @@ // of the Apache-2.0 license. See the LICENSE file for details. import { Option } from '@polkadot/types'; -import { BalanceOf, EthereumAddress } from '@polkadot/types/interfaces'; +import { BalanceOf, EthereumAddress, StatementKind } from '@polkadot/types/interfaces'; -import React, { useCallback, useEffect, useState } from 'react'; +import React, { useEffect, useState } from 'react'; import styled from 'styled-components'; -import { Button, Card } from '@polkadot/react-components'; +import { Button, Card, TxButton } from '@polkadot/react-components'; +import { TxCallback } from '@polkadot/react-components/Status/types'; import { useApi } from '@polkadot/react-hooks'; import { FormatBalance } from '@polkadot/react-query'; import { useTranslation } from './translate'; -import { addrToChecksum } from './util'; +import { addrToChecksum, getStatement } from './util'; interface Props { - button: React.ReactNode; + accountId: string; className?: string; ethereumAddress: EthereumAddress | null; + ethereumSignature: string | null; + // Do we sign with `claims.claimAttest` (new) instead of `claims.claim` (old)? + isOldClaimProcess: boolean; + onSuccess?: TxCallback; + statementKind?: StatementKind; + systemChain: string; } -function Claim ({ button, className = '', ethereumAddress }: Props): React.ReactElement | null { +interface ConstructTx { + params?: any[]; + tx?: string; +} + +// Depending on isOldClaimProcess, construct the correct tx. +function constructTx ( + systemChain: string, + accountId: string, + ethereumSignature: string | null, + kind: StatementKind | undefined, + isOldClaimProcess: boolean +): ConstructTx { + if (!ethereumSignature || !kind) { + return {}; + } + + return isOldClaimProcess + ? { params: [accountId, ethereumSignature], tx: 'claims.claim' } + : { params: [accountId, ethereumSignature, getStatement(systemChain, kind)?.sentence], tx: 'claims.claimAttest' }; +} + +function Claim ({ accountId, className = '', ethereumAddress, ethereumSignature, isOldClaimProcess, onSuccess, statementKind, systemChain }: Props): React.ReactElement | null { const { t } = useTranslation(); const { api } = useApi(); const [claimValue, setClaimValue] = useState(null); - const [claimAddress, setClaimAddress] = useState(null); const [isBusy, setIsBusy] = useState(false); - const _fetchClaim = useCallback( - (address: EthereumAddress): void => { - setIsBusy(true); - - api.query.claims - .claims>(address) - .then((claim): void => { - setClaimValue(claim.unwrapOr(null)); - setIsBusy(false); - }) - .catch((): void => setIsBusy(false)); - }, - [api] - ); - useEffect((): void => { - setClaimAddress(ethereumAddress); + if (!ethereumAddress) { + return; + } - ethereumAddress && _fetchClaim(ethereumAddress); - }, [_fetchClaim, ethereumAddress]); + setIsBusy(true); - if (isBusy || !claimAddress) { + api.query.claims + .claims>(ethereumAddress) + .then((claim): void => { + setClaimValue(claim.unwrapOr(null)); + setIsBusy(false); + }) + .catch((): void => setIsBusy(false)); + }, [api, ethereumAddress]); + + if (!ethereumAddress || isBusy) { return null; } @@ -61,13 +84,23 @@ function Claim ({ button, className = '', ethereumAddress }: Props): React.React >
{t('Your Ethereum account')} -

{addrToChecksum(claimAddress.toString())}

+

{addrToChecksum(ethereumAddress.toString())}

{hasClaim && claimValue ? ( <> {t('has a valid claim for')}

- {button} + + + ) : ( @@ -80,29 +113,31 @@ function Claim ({ button, className = '', ethereumAddress }: Props): React.React ); } -export default React.memo(styled(Claim)` - font-size: 1.15rem; - display: flex; - flex-direction: column; - justify-content: center; - min-height: 12rem; - align-items: center; - margin: 0 1rem; +export const ClaimStyles = ` +font-size: 1.15rem; +display: flex; +flex-direction: column; +justify-content: center; +min-height: 12rem; +align-items: center; +margin: 0 1rem; - h3 { - font-family: monospace; - font-size: 1.5rem; - max-width: 100%; - margin: 0.5rem; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } +h3 { + font-family: monospace; + font-size: 1.5rem; + max-width: 100%; + margin: 0.5rem; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} - h2 { - margin: 0.5rem 0 2rem; - font-family: monospace; - font-size: 2.5rem; - font-weight: 200; - } -`); +h2 { + margin: 0.5rem 0 2rem; + font-family: monospace; + font-size: 2.5rem; + font-weight: 200; +} +`; + +export default React.memo(styled(Claim)`${ClaimStyles}`); diff --git a/packages/page-claims/src/Statement.tsx b/packages/page-claims/src/Statement.tsx new file mode 100644 index 0000000000..3101c8d44d --- /dev/null +++ b/packages/page-claims/src/Statement.tsx @@ -0,0 +1,82 @@ +// Copyright 2017-2020 @polkadot/app-claims authors & contributors +// This software may be modified and distributed under the terms +// of the Apache-2.0 license. See the LICENSE file for details. + +import { StatementKind } from '@polkadot/types/interfaces'; + +import React from 'react'; +import styled from 'styled-components'; + +import { useTranslation } from './translate'; +import { getStatement } from './util'; + +export interface Props { + className?: string; + kind?: StatementKind; + systemChain: string; +} + +// Get the full hardcoded text for a statement +function StatementFullText ({ statementUrl, systemChain }: { statementUrl?: string; systemChain: string }): React.ReactElement | null { + const { t } = useTranslation(); + + switch (systemChain) { + case 'Polkadot CC1': { + if (!statementUrl) { + return null; + } + + return