Interleave bids & crowdloan on results (#4951)

* Interleave bds & crowdloan on results

* Display crowdload flag
This commit is contained in:
Jaco Greeff 2021-03-26 18:04:23 +01:00 committed by GitHub
parent 3d11bac0a6
commit 9d971b9aca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 65 additions and 24 deletions

View File

@ -1,9 +1,9 @@
// Copyright 2017-2021 @polkadot/app-parachains authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { AuctionInfo, Winning } from '../types';
import type { AuctionInfo, Campaigns, WinnerData, Winning } from '../types';
import React, { useRef } from 'react';
import React, { useCallback, useRef } from 'react';
import { Table } from '@polkadot/react-components';
@ -12,19 +12,36 @@ import WinRange from './WinRange';
interface Props {
auctionInfo?: AuctionInfo;
campaigns: Campaigns;
className?: string;
winningData?: Winning[];
}
function Auction ({ auctionInfo, className, winningData }: Props): React.ReactElement<Props> {
function Auction ({ auctionInfo, campaigns, className, winningData }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const headerRef = useRef([
[t('bids'), 'start', 4],
[t('bids'), 'start', 3],
[t('bidder'), 'address'],
[t('crowdloan')],
[t('periods')],
[t('value')]
]);
const interleave = useCallback(
(winners: WinnerData[], asIs: boolean): WinnerData[] =>
asIs
? winners
: winners.map((w): WinnerData =>
campaigns.funds?.find(({ firstSlot, lastSlot, value }) =>
w.firstSlot === firstSlot &&
w.lastSlot === lastSlot &&
w.value.lt(value)
) || w
),
[campaigns]
);
return (
<Table
className={className}
@ -40,7 +57,7 @@ function Auction ({ auctionInfo, className, winningData }: Props): React.ReactEl
>
{auctionInfo && winningData?.map(({ blockNumber, winners }, round) => (
<tbody key={round}>
{winners.map((value, index) => (
{interleave(winners, round !== 0 || winningData.length !== 1).map((value, index) => (
<WinRange
auctionInfo={auctionInfo}
blockNumber={blockNumber}

View File

@ -21,7 +21,7 @@ interface Props {
value: WinnerData;
}
function WinRanges ({ auctionInfo, blockNumber, className = '', isFirst, isLatest, value: { accountId, firstSlot, lastSlot, paraId, value } }: Props): React.ReactElement<Props> {
function WinRanges ({ auctionInfo, blockNumber, className = '', isFirst, isLatest, value: { accountId, firstSlot, isCrowdloan, lastSlot, paraId, value } }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
return (
@ -37,6 +37,7 @@ function WinRanges ({ auctionInfo, blockNumber, className = '', isFirst, isLates
<td className='number'><h1>{formatNumber(paraId)}</h1></td>
<td className='badge'><ParaLink id={paraId} /></td>
<td className='address'><AddressMini value={accountId} /></td>
<td className='all number'>{isCrowdloan ? t<string>('Yes') : t<string>('No')}</td>
<td className='all number'>
<Digits value={`${formatNumber(firstSlot)} - ${formatNumber(lastSlot)}`} />
</td>

View File

@ -1,7 +1,7 @@
// Copyright 2017-2021 @polkadot/app-parachains authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { AuctionInfo, OwnedId, Winning } from '../types';
import type { AuctionInfo, Campaigns, OwnedId, Winning } from '../types';
import React from 'react';
@ -13,12 +13,13 @@ import Summary from './Summary';
interface Props {
auctionInfo?: AuctionInfo;
campaigns: Campaigns;
className?: string;
ownedIds: OwnedId[];
winningData?: Winning[];
}
function Auctions ({ auctionInfo, className, ownedIds, winningData }: Props): React.ReactElement<Props> {
function Auctions ({ auctionInfo, campaigns, className, ownedIds, winningData }: Props): React.ReactElement<Props> {
const lastWinners = winningData && winningData[0];
return (
@ -36,6 +37,7 @@ function Auctions ({ auctionInfo, className, ownedIds, winningData }: Props): Re
</Button.Group>
<Auction
auctionInfo={auctionInfo}
campaigns={campaigns}
winningData={winningData}
/>
</div>

View File

@ -62,7 +62,7 @@ function Funds ({ bestNumber, className, value }: Props): React.ReactElement<Pro
<Fund
bestNumber={bestNumber}
isOngoing
key={fund.key}
key={fund.accountId}
value={fund}
/>
))}
@ -75,7 +75,7 @@ function Funds ({ bestNumber, className, value }: Props): React.ReactElement<Pro
{ended?.map((fund) => (
<Fund
bestNumber={bestNumber}
key={fund.key}
key={fund.accountId}
value={fund}
/>
))}

View File

@ -1,9 +1,13 @@
// Copyright 2017-2021 @polkadot/app-parachains authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { stringToU8a } from '@polkadot/util';
export const RANGES: [number, number][] = [
[0, 0], [0, 1], [0, 2], [0, 3],
[1, 1], [1, 2], [1, 3],
[2, 2], [2, 3],
[3, 3]
];
export const CROWD_PREFIX = stringToU8a('modlpy/cfund');

View File

@ -67,6 +67,7 @@ function ParachainsApp ({ basePath, className }: Props): React.ReactElement<Prop
<Route path={`${basePath}/auctions`}>
<Auctions
auctionInfo={auctionInfo}
campaigns={campaigns}
ownedIds={ownedIds}
winningData={winningData}
/>

View File

@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
import type BN from 'bn.js';
import type { AccountId, AuctionIndex, BalanceOf, BlockNumber, FundInfo, LeasePeriodOf, ParachainProposal, ParaId, ParaInfo, SessionIndex } from '@polkadot/types/interfaces';
import type { AuctionIndex, BlockNumber, FundInfo, LeasePeriodOf, ParachainProposal, ParaId, ParaInfo, SessionIndex } from '@polkadot/types/interfaces';
export interface AuctionInfo {
endBlock: BlockNumber | null;
@ -30,14 +30,12 @@ export interface Campaigns {
totalRaised: BN;
}
export interface Campaign {
export interface Campaign extends WinnerData {
info: FundInfo;
isCapped?: boolean;
isEnded?: boolean;
isRetired?: boolean;
isWinner?: boolean;
key: string;
paraId: ParaId;
retireEnd?: BN;
}
@ -66,11 +64,12 @@ export interface OwnerInfo {
}
export interface WinnerData {
accountId: AccountId;
accountId: string;
firstSlot: number;
isCrowdloan: boolean;
lastSlot: number;
paraId: ParaId;
value: BalanceOf;
value: BN;
}
export interface Winning {

View File

@ -10,7 +10,10 @@ import BN from 'bn.js';
import { useEffect, useState } from 'react';
import { useApi, useBestNumber, useCall, useEventTrigger } from '@polkadot/react-hooks';
import { BN_ZERO, stringToU8a, u8aConcat } from '@polkadot/util';
import { BN_ZERO, u8aConcat } from '@polkadot/util';
import { encodeAddress } from '@polkadot/util-crypto';
import { CROWD_PREFIX } from './constants';
const EMPTY: Campaigns = {
activeCap: BN_ZERO,
@ -20,11 +23,14 @@ const EMPTY: Campaigns = {
totalRaised: BN_ZERO
};
const PREFIX = stringToU8a('modlpy/cfund');
const EMPTY_U8A = new Uint8Array(32);
function createAddress (paraId: ParaId): Uint8Array {
return u8aConcat(CROWD_PREFIX, paraId.toU8a(), EMPTY_U8A).subarray(0, 32);
}
function isCrowdloadAccount (paraId: ParaId, accountId: AccountId): boolean {
return accountId.eq(u8aConcat(PREFIX, paraId.toU8a(), EMPTY_U8A).subarray(0, 32));
return accountId.eq();
}
function hasLease (paraId: ParaId, leased: ParaId[]): boolean {
@ -116,9 +122,13 @@ const optFundMulti = {
.map((paraId, i): [ParaId, FundInfo | null] => [paraId, optFunds[i].unwrapOr(null)])
.filter((v): v is [ParaId, FundInfo] => !!v[1])
.map(([paraId, info]): Campaign => ({
accountId: encodeAddress(createAddress(paraId)),
firstSlot: info.firstSlot.toNumber(),
info,
key: paraId.toString(),
paraId
isCrowdloan: true,
lastSlot: info.lastSlot.toNumber(),
paraId,
value: info.raised
}))
.sort((a, b) =>
a.info.end.cmp(b.info.end) ||

View File

@ -9,9 +9,9 @@ import BN from 'bn.js';
import { useEffect, useRef, useState } from 'react';
import { useApi, useBestNumber, useCall, useEventTrigger } from '@polkadot/react-hooks';
import { BN_ONE, BN_ZERO } from '@polkadot/util';
import { BN_ONE, BN_ZERO, u8aEq } from '@polkadot/util';
import { RANGES } from './constants';
import { CROWD_PREFIX, RANGES } from './constants';
const FIRST_PARAM = [0];
@ -36,7 +36,14 @@ function extractWinners (auctionInfo: AuctionInfo, optData: Option<WinningData>)
const period = auctionInfo.leasePeriod?.toNumber() || 0;
const [first, last] = RANGES[index];
winners.push({ accountId, firstSlot: first + period, lastSlot: last + period, paraId, value });
winners.push({
accountId: accountId.toString(),
firstSlot: first + period,
isCrowdloan: u8aEq(CROWD_PREFIX, accountId.subarray(0, CROWD_PREFIX.length)),
lastSlot: last + period,
paraId,
value
});
}
return winners;