From 5494c084e8f42cbdb962e39651b136c3dda196a6 Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 9 Mar 2022 18:20:39 +0100 Subject: [PATCH] feat: properly display finished auctions (#90) --- core/src/auctions.ts | 42 +++++++++++++--- core/src/date.ts | 9 +++- core/src/fetch.ts | 16 +++--- core/src/helpers/parseAuctionId.ts | 22 +++++++++ core/src/types.ts | 8 ++- frontend/components/Auction.vue | 35 ++++++++++--- frontend/components/AuctionEventsBlock.vue | 32 ++++++++++++ frontend/components/AuctionsTable.vue | 6 +-- frontend/components/MainFlow.stories.js | 4 +- frontend/components/MainFlow.vue | 24 +++++++-- frontend/components/utils/FormatAddress.vue | 8 ++- frontend/containers/AuctionsContainer.vue | 11 +++-- frontend/helpers/generateFakeAuction.js | 6 +-- frontend/store/auctions.ts | 55 +++++++++++++++++---- 14 files changed, 228 insertions(+), 50 deletions(-) create mode 100644 core/src/helpers/parseAuctionId.ts create mode 100644 frontend/components/AuctionEventsBlock.vue diff --git a/core/src/auctions.ts b/core/src/auctions.ts index 9a53e4af6..9fc621a48 100644 --- a/core/src/auctions.ts +++ b/core/src/auctions.ts @@ -1,4 +1,4 @@ -import type { Auction, AuctionInitialInfo, AuctionTransaction, Notifier } from './types'; +import type { Auction, AuctionInitialInfo, AuctionTransaction, Notifier, TakeEvent } from './types'; import BigNumber from './bignumber'; import fetchAuctionsByCollateralType, { fetchAuctionStatus } from './fetch'; import { getCalleeData, getMarketPrice } from './calleeFunctions'; @@ -13,10 +13,12 @@ import { calculateTransactionGrossProfitDate, } from './price'; import { getSupportedCollateralTypes } from './addresses'; -import { getClipperNameByCollateralType } from './contracts'; +import getContract, { getClipperNameByCollateralType } from './contracts'; import convertNumberTo32Bytes from './helpers/convertNumberTo32Bytes'; import { enrichAuctionWithTransactionFees, getApproximateTransactionFees } from './fees'; -import getNetworkDate from './date'; +import parseAuctionId from './helpers/parseAuctionId'; +import { EventFilter } from 'ethers'; +import getNetworkDate, { fetchDateByBlockNumber } from './date'; const enrichAuctionWithActualNumbers = async function ( network: string, @@ -30,7 +32,7 @@ const enrichAuctionWithActualNumbers = async function ( totalPrice: new BigNumber(0), }; } - const auctionStatus = await fetchAuctionStatus(network, auction.collateralType, auction.auctionId); + const auctionStatus = await fetchAuctionStatus(network, auction.collateralType, auction.index); return { ...auction, ...auctionStatus, @@ -136,6 +138,34 @@ export const enrichAuction = async function ( return auctionWithFees; }; +const enrichTakeEventWithDate = async function (network: string, takeEvent: TakeEvent): Promise { + const date = await fetchDateByBlockNumber(network, takeEvent.blockNumber); + return { + ...takeEvent, + transactionDate: date, + }; +}; + +export const fetchTakeEvents = async function (network: string, auctionId: string): Promise> { + const { collateralType, index } = parseAuctionId(auctionId); + const encodedAuctionIndex = convertNumberTo32Bytes(index); + + const contractName = getClipperNameByCollateralType(collateralType); + const contract = await getContract(network, contractName); + + const eventFilters: EventFilter = contract.filters.Take(encodedAuctionIndex); + const events = await contract.queryFilter(eventFilters); + + return await Promise.all( + events.map(event => + enrichTakeEventWithDate(network, { + transactionHash: event.transactionHash, + blockNumber: event.blockNumber, + }) + ) + ); +}; + export const restartAuction = async function ( network: string, auction: Auction, @@ -143,7 +173,7 @@ export const restartAuction = async function ( notifier?: Notifier ): Promise { const contractName = getClipperNameByCollateralType(auction.collateralType); - return executeTransaction(network, contractName, 'redo', [auction.auctionId, profitAddress], notifier, false); + return executeTransaction(network, contractName, 'redo', [auction.index, profitAddress], notifier, false); }; export const bidOnTheAuction = async function ( @@ -156,7 +186,7 @@ export const bidOnTheAuction = async function ( const calleeData = await getCalleeData(network, auction.collateralType, profitAddress); const contractName = getClipperNameByCollateralType(auction.collateralType); const contractParameters = [ - convertNumberTo32Bytes(auction.auctionId), + convertNumberTo32Bytes(auction.index), auction.collateralAmount.shiftedBy(WAD_NUMBER_OF_DIGITS).toFixed(), auction.unitPrice.shiftedBy(RAY_NUMBER_OF_DIGITS).toFixed(), calleeAddress, diff --git a/core/src/date.ts b/core/src/date.ts index ece8d081c..01c8fa2a6 100644 --- a/core/src/date.ts +++ b/core/src/date.ts @@ -4,13 +4,18 @@ import { getNetworkConfigByType } from './constants/NETWORKS'; const CURRENT_BLOCK_DATE_CACHE_EXPIRY_MS = 60 * 1000; -const fetchLatestBlockDate = async function (network: string): Promise { +export const fetchDateByBlockNumber = async function (network: string, blockNumber: number): Promise { const provider = await getProvider(network); - const blockNumber = await provider.getBlockNumber(); const block = await provider.getBlock(blockNumber); return new Date(block.timestamp * 1000); }; +const fetchLatestBlockDate = async function (network: string): Promise { + const provider = await getProvider(network); + const blockNumber = await provider.getBlockNumber(); + return fetchDateByBlockNumber(network, blockNumber); +}; + const _fetchLatestBlockDateAndCacheDate = async function ( network: string ): Promise<{ blockDate: Date; cacheDate: Date }> { diff --git a/core/src/fetch.ts b/core/src/fetch.ts index ba8bb0302..49d0aec29 100644 --- a/core/src/fetch.ts +++ b/core/src/fetch.ts @@ -42,20 +42,20 @@ export const fetchAuctionStatus = async function ( }; }; -const fetchAuctionByCollateralTypeAndAuctionId = async function ( +const fetchAuctionByCollateralTypeAndAuctionIndex = async function ( network: string, collateralType: string, - auctionId: number + auctionIndex: number ): Promise { const maximumAuctionDurationInSeconds = await fetchMaximumAuctionDurationInSeconds(network, collateralType); const contract = await getContract(network, getClipperNameByCollateralType(collateralType)); - const auctionData = await contract.sales(auctionId); + const auctionData = await contract.sales(auctionIndex); const startTimestamp = new BigNumber(auctionData.tic._hex).times(1000).toNumber(); const endDate = new Date(startTimestamp + maximumAuctionDurationInSeconds * 1000); return { network, - id: `${collateralType}:${auctionId}`, - auctionId, + id: `${collateralType}:${auctionIndex}`, + index: auctionIndex, collateralType, collateralSymbol: getCollateralConfigByType(collateralType).symbol, collateralAmount: new BigNumber(auctionData.lot._hex).div(WAD), @@ -72,9 +72,9 @@ const fetchAuctionByCollateralTypeAndAuctionId = async function ( const fetchAuctionsByCollateralType = async function (network: string, collateralType: string) { const contract = await getContract(network, getClipperNameByCollateralType(collateralType)); - const activeAuctionIds = await contract.list(); - const activeAuctionPromises = activeAuctionIds.map((auctionId: BigNumber) => { - return fetchAuctionByCollateralTypeAndAuctionId(network, collateralType, auctionId.toNumber()); + const activeAuctionIndexes = await contract.list(); + const activeAuctionPromises = activeAuctionIndexes.map((auctionIndex: BigNumber) => { + return fetchAuctionByCollateralTypeAndAuctionIndex(network, collateralType, auctionIndex.toNumber()); }); return await Promise.all(activeAuctionPromises); }; diff --git a/core/src/helpers/parseAuctionId.ts b/core/src/helpers/parseAuctionId.ts new file mode 100644 index 000000000..57ef29b10 --- /dev/null +++ b/core/src/helpers/parseAuctionId.ts @@ -0,0 +1,22 @@ +import { getCollateralConfigByType } from '../constants/COLLATERALS'; + +function parseAuctionId(id: string): { collateralType: string; index: number } { + const parts = id.split(':'); + const collateralType = parts[0]; + const index = parts[1]; + + // Check if we support the CollateralType + getCollateralConfigByType(collateralType); + + // Check if auction id is a valid auction id + if (Number.isNaN(parseInt(index))) { + throw new Error(`"${index}" is not a valid Auction Index!`); + } + + return { + collateralType, + index: parseInt(index), + }; +} + +export default parseAuctionId; diff --git a/core/src/types.ts b/core/src/types.ts index aae61a77f..1b7055031 100644 --- a/core/src/types.ts +++ b/core/src/types.ts @@ -3,7 +3,7 @@ import BigNumber from 'bignumber.js'; export declare interface AuctionInitialInfo { network: string; id: string; - auctionId: number; + index: number; collateralType: string; collateralSymbol: string; collateralAmount: BigNumber; @@ -114,3 +114,9 @@ export declare interface MessageContent { export declare interface Notifier { (messageType: 'loading' | 'error' | 'success' | 'info', messageContent: MessageContent): void; } + +export declare interface TakeEvent { + transactionHash: string; + blockNumber: number; + transactionDate?: Date; +} diff --git a/frontend/components/Auction.vue b/frontend/components/Auction.vue index 0c89c37e4..d5b4df80f 100644 --- a/frontend/components/Auction.vue +++ b/frontend/components/Auction.vue @@ -233,12 +233,17 @@ - + + diff --git a/frontend/components/AuctionsTable.vue b/frontend/components/AuctionsTable.vue index a3eb29003..722d91289 100644 --- a/frontend/components/AuctionsTable.vue +++ b/frontend/components/AuctionsTable.vue @@ -124,9 +124,9 @@ export default Vue.extend({ return [ { - title: 'ID', - dataIndex: 'auctionId', - sorter: compareBy('auctionId'), + title: 'Index', + dataIndex: 'index', + sorter: compareBy('index'), }, { title: 'Auction Amount', diff --git a/frontend/components/MainFlow.stories.js b/frontend/components/MainFlow.stories.js index 175dea6e6..4b1a1f0cb 100644 --- a/frontend/components/MainFlow.stories.js +++ b/frontend/components/MainFlow.stories.js @@ -33,7 +33,7 @@ storiesOf('Main Flow', module) MainFlow, }, data: () => ({ fakeAuctions, randomSelectedAuctionId }), - template: ``, + template: ``, })) .add('Selected Auction Expert', () => ({ components: { @@ -68,5 +68,5 @@ storiesOf('Main Flow', module) MainFlow, }, data: () => ({ fakeAuctions: [], randomSelectedAuctionId }), - template: ``, + template: ``, })); diff --git a/frontend/components/MainFlow.vue b/frontend/components/MainFlow.vue index 5b37e73f9..104803a4a 100644 --- a/frontend/components/MainFlow.vue +++ b/frontend/components/MainFlow.vue @@ -10,7 +10,7 @@ ref="mainText" :auctions="auctions" :auctions-error="auctionsError" - :is-auctions-loading="isAuctionsLoading" + :is-auctions-loading="areAuctionsFetching" :selected-auction-id="selectedAuctionId" :is-explanations-shown="isExplanationsShown" @selectedAuctionId:update="$emit('selectedAuctionId:update', $event)" @@ -24,12 +24,15 @@ :is-explanations-shown="isExplanationsShown" class="mt-6 mb-8 mx-8" :auction="selectedAuction" + :take-events="selectedTakeEvents" :wallet-address="walletAddress" :auction-id="selectedAuctionId" - :is-auctions-loading="isAuctionsLoading" + :are-auctions-fetching="areAuctionsFetching" + :are-take-events-fetching="areTakeEventsFetching" @restart="$emit('restart', $event)" @connect="$emit('connect')" @swap="step = 2" + @fetchTakeEventsFromAuction="$emit('fetchTakeEventsFromAuction', $event)" /> @@ -57,6 +60,7 @@