From cbf572753d9dde45d03ff63be8a62cbe03f70548 Mon Sep 17 00:00:00 2001 From: Abdelrhman Farag <85403429+aomafarag@users.noreply.github.com> Date: Mon, 7 Nov 2022 15:49:41 +0100 Subject: [PATCH] feat: Multi-callee support for the frontend (#498) --- core/src/auctions.ts | 24 ++-- core/src/calleeFunctions/index.ts | 2 +- .../CollateralAuctionSwapTransaction.vue | 12 +- .../CollateralAuctionSwapTransactionTable.vue | 64 +++++++--- .../MarketPriceSelection.stories.js | 18 +++ .../collateral/MarketPriceSelection.vue | 120 ++++++++++++++++++ frontend/helpers/generateFakeAuction.ts | 67 ++++++++-- 7 files changed, 262 insertions(+), 45 deletions(-) create mode 100644 frontend/components/auction/collateral/MarketPriceSelection.stories.js create mode 100644 frontend/components/auction/collateral/MarketPriceSelection.vue diff --git a/core/src/auctions.ts b/core/src/auctions.ts index 934359d97..ebbbe2032 100644 --- a/core/src/auctions.ts +++ b/core/src/auctions.ts @@ -86,31 +86,34 @@ export const enrichMarketDataRecordsWithValues = async function ( for (const marketId in marketDataRecords) { let marketData = marketDataRecords[marketId]; // enrich with values dependent on marketUnitPrice - if (marketData.marketUnitPrice.isNaN()) { + let marketUnitPrice = marketData.marketUnitPrice; + if (marketUnitPrice.isNaN()) { enrichedMarketDataRecords = { ...enrichedMarketDataRecords, [marketId]: { ...marketData }, }; continue; } + marketUnitPrice = marketUnitPrice.plus(exchangeFeePerUnitDAI); marketData = { ...marketData, - marketUnitPrice: marketData.marketUnitPrice.plus(exchangeFeePerUnitDAI), + marketUnitPrice, marketUnitPriceToUnitPriceRatio: auction.approximateUnitPrice - .minus(marketData.marketUnitPrice) - .dividedBy(marketData.marketUnitPrice), + .minus(marketUnitPrice) + .dividedBy(marketUnitPrice), ...exchangeFees, transactionGrossProfit: calculateTransactionGrossProfit( - marketData.marketUnitPrice, + marketUnitPrice, amount, auction.approximateUnitPrice ), }; // enrich with values dependent on fees if (marketData.transactionGrossProfit && auction.combinedSwapFeesDAI) { + const transactionGrossProfit = marketData.transactionGrossProfit; marketData = { ...marketData, - transactionNetProfit: marketData.transactionGrossProfit.minus(auction.combinedSwapFeesDAI), + transactionNetProfit: transactionGrossProfit.minus(auction.combinedSwapFeesDAI), }; } // enrich with values dependent on currentDate @@ -118,11 +121,7 @@ export const enrichMarketDataRecordsWithValues = async function ( const currentDate = await getNetworkDate(auction.network); marketData = { ...marketData, - transactionGrossProfitDate: calculateTransactionGrossProfitDate( - auction, - marketData.marketUnitPrice, - currentDate - ), + transactionGrossProfitDate: calculateTransactionGrossProfitDate(auction, marketUnitPrice, currentDate), }; } catch {} enrichedMarketDataRecords = { @@ -159,13 +158,14 @@ export const enrichAuctionWithMarketDataRecords = async function ( const transactionNetProfit = enrichedMarketDataRecords[suggestedMarketId].transactionNetProfit; return { ...auction, + collateralToCoverDebt, suggestedMarketId, marketUnitPrice, marketUnitPriceToUnitPriceRatio, transactionGrossProfit, transactionGrossProfitDate, transactionNetProfit: transactionNetProfit ? transactionNetProfit : new BigNumber(NaN), - marketDataRecords, + marketDataRecords: enrichedMarketDataRecords, }; } catch (error: any) { // since it's expected that some collaterals are not tradable on some networks diff --git a/core/src/calleeFunctions/index.ts b/core/src/calleeFunctions/index.ts index 950007ba2..428615aa9 100644 --- a/core/src/calleeFunctions/index.ts +++ b/core/src/calleeFunctions/index.ts @@ -108,7 +108,7 @@ export const getBestMarketId = async function (marketDataRecords: Record - + Please note, the transaction fee is a suggested value based on the current gas prices on the market; the Transaction Net Profit is also approximate, since it is extrapolated from the exchange rates and may change @@ -87,7 +91,7 @@ @execute=" $emit('execute', { id: auctionTransaction.id, - marketId: auctionTransaction.suggestedMarketId, + marketId: marketSuggestionOrSelection, alternativeDestinationAddress: $event, }) " @@ -157,6 +161,7 @@ export default Vue.extend({ }, data() { return { + currentMarketId: '', isWalletConnectedCheck: false, isWalletDAIAuthorizationCheckPassed: false, isWalletCollateralAuthorizationCheckPassed: false, @@ -183,6 +188,9 @@ export default Vue.extend({ } return fees; }, + marketSuggestionOrSelection(): string | undefined { + return this.currentMarketId || this.auctionTransaction.suggestedMarketId; + }, }, }); diff --git a/frontend/components/auction/collateral/CollateralAuctionSwapTransactionTable.vue b/frontend/components/auction/collateral/CollateralAuctionSwapTransactionTable.vue index 8156f97f5..7b4ee0820 100644 --- a/frontend/components/auction/collateral/CollateralAuctionSwapTransactionTable.vue +++ b/frontend/components/auction/collateral/CollateralAuctionSwapTransactionTable.vue @@ -21,21 +21,12 @@ {{ auctionTransaction.collateralSymbol }} -
-
Price On Uniswap
-
- - Unknown -
-
+
Market Difference
- diff --git a/frontend/components/auction/collateral/MarketPriceSelection.stories.js b/frontend/components/auction/collateral/MarketPriceSelection.stories.js new file mode 100644 index 000000000..c866663ac --- /dev/null +++ b/frontend/components/auction/collateral/MarketPriceSelection.stories.js @@ -0,0 +1,18 @@ +import { storiesOf } from '@storybook/vue'; +import MarketPriceSelection from './MarketPriceSelection'; +import { generateFakeAuctionTransaction } from '~/helpers/generateFakeAuction.ts'; + +const fakeAuctionTransaction = generateFakeAuctionTransaction(); + +const common = { + components: { + MarketPriceSelection, + }, + data: () => ({ + auctionTransaction: fakeAuctionTransaction, + marketId: '', + }), + template: ``, +}; + +storiesOf('Auction/Collateral/MarketPriceSelection', module).add('Default', () => ({ ...common })); diff --git a/frontend/components/auction/collateral/MarketPriceSelection.vue b/frontend/components/auction/collateral/MarketPriceSelection.vue new file mode 100644 index 000000000..a58df534f --- /dev/null +++ b/frontend/components/auction/collateral/MarketPriceSelection.vue @@ -0,0 +1,120 @@ + + + + + diff --git a/frontend/helpers/generateFakeAuction.ts b/frontend/helpers/generateFakeAuction.ts index 319dcbbf1..33cdb9339 100644 --- a/frontend/helpers/generateFakeAuction.ts +++ b/frontend/helpers/generateFakeAuction.ts @@ -2,26 +2,61 @@ import faker from 'faker'; import { random } from 'lodash'; import BigNumber from 'bignumber.js'; import COLLATERALS from 'auctions-core/src/constants/COLLATERALS'; -import { AuctionTransaction } from '~/../core/src/types'; +import { AuctionTransaction, MarketData } from '~/../core/src/types'; -export const generateFakeAuction = function () { - const index = faker.datatype.number(); - const collateralAmount = new BigNumber(parseFloat(faker.finance.amount())); - const totalPrice = new BigNumber(parseFloat(faker.finance.amount())); - const debtDAI = totalPrice.multipliedBy(faker.datatype.number({ min: 0.1, max: 0.5, precision: 0.001 })); - const isActive = faker.datatype.boolean(); - const isFinished = faker.datatype.boolean(); - const approximateUnitPrice = totalPrice.dividedBy(collateralAmount); +const FAKE_CALLEES = ['Uniswap V3', '1inch']; // Curve V3 marketUnitPrice is NaN (see below) + +export const generateFakeMarketData = function ( + isActive: boolean, + approximateUnitPrice: BigNumber, + collateralAmount: BigNumber +) { const marketUnitPriceToUnitPriceRatio = isActive ? new BigNumber(faker.datatype.number({ min: -0.3, max: 0.3, precision: 0.001 })) : undefined; - const collateralObject = faker.helpers.randomize(Object.values(COLLATERALS)); const marketUnitPrice = approximateUnitPrice.multipliedBy( new BigNumber(1).minus(marketUnitPriceToUnitPriceRatio || 0) ); const transactionGrossProfit = marketUnitPrice .multipliedBy(collateralAmount) .minus(approximateUnitPrice.multipliedBy(collateralAmount)); + const transactionGrossProfitDate = faker.date.future(); + return { + marketUnitPrice, + marketUnitPriceToUnitPriceRatio, + transactionGrossProfit, + transactionGrossProfitDate, + }; +}; + +export const generateFakeAuction = function () { + const index = faker.datatype.number(); + const collateralAmount = new BigNumber(parseFloat(faker.finance.amount())); + const totalPrice = new BigNumber(parseFloat(faker.finance.amount())); + const debtDAI = totalPrice.multipliedBy(faker.datatype.number({ min: 0.1, max: 0.5, precision: 0.001 })); + const isActive = faker.datatype.boolean(); + const isFinished = faker.datatype.boolean(); + const approximateUnitPrice = totalPrice.dividedBy(collateralAmount); + const collateralObject = faker.helpers.randomize(Object.values(COLLATERALS)); + const suggestedMarketId = faker.helpers.randomize(FAKE_CALLEES); + const marketDataRecords: Record = { + 'Uniswap V3': { + ...generateFakeMarketData(isActive, approximateUnitPrice, collateralAmount), + route: [collateralObject.symbol, 'USDC'], + }, + 'Curve V3': { + marketUnitPrice: new BigNumber(NaN), + route: [collateralObject.symbol], + }, + '1inch': { + ...generateFakeMarketData(isActive, approximateUnitPrice, collateralAmount), + route: [collateralObject.symbol], + }, + }; + const marketUnitPriceToUnitPriceRatio = marketDataRecords[suggestedMarketId].marketUnitPriceToUnitPriceRatio; + const marketUnitPrice = marketDataRecords[suggestedMarketId].marketUnitPrice; + const transactionGrossProfit = marketDataRecords[suggestedMarketId].transactionGrossProfit; + const transactionGrossProfitDate = marketDataRecords[suggestedMarketId].transactionGrossProfitDate; const secondsBetweenPriceDrops = faker.datatype.number(120); const secondsTillNextPriceDrop = faker.datatype.number(secondsBetweenPriceDrops); return { @@ -40,6 +75,8 @@ export const generateFakeAuction = function () { approximateUnitPrice, unitPrice: approximateUnitPrice, marketUnitPrice, + marketDataRecords, + suggestedMarketId, isActive, transactionGrossProfit, isFinished, @@ -51,7 +88,7 @@ export const generateFakeAuction = function () { collateralToCoverDebt: collateralAmount.multipliedBy(debtDAI.dividedBy(totalPrice)), minimumBidDai: new BigNumber(faker.finance.amount()), priceDropRatio: new BigNumber(faker.datatype.number({ min: 0.5, max: 1, precision: 0.0001 })), - transactionGrossProfitDate: faker.date.future(), + transactionGrossProfitDate, fetchedAt: new Date(), }; }; @@ -66,7 +103,13 @@ export const generateFakeAuctionTransaction = function (): AuctionTransaction { const authTransactionFeeDAI = authTransactionFeeETH.multipliedBy(1000); const restartTransactionFeeETH = new BigNumber(faker.datatype.float({ min: 0, max: 0.001, precision: 0.000001 })); const restartTransactionFeeDAI = restartTransactionFeeETH.multipliedBy(1000); - const transactionNetProfit = auction.transactionGrossProfit.minus(swapTransactionFeeDAI); + for (const marketData of Object.values(auction.marketDataRecords)) { + if (marketData.transactionGrossProfit) { + marketData.transactionNetProfit = marketData.transactionGrossProfit.minus(swapTransactionFeeDAI); + } + } + const transactionNetProfit = + auction.marketDataRecords[auction.suggestedMarketId].transactionNetProfit || new BigNumber(NaN); const combinedSwapFeesETH = swapTransactionFeeETH.plus(authTransactionFeeETH).plus(authTransactionFeeETH); const combinedSwapFeesDAI = combinedSwapFeesETH.multipliedBy(1000); const combinedBidFeesETH = bidTransactionFeeETH.plus(authTransactionFeeETH).plus(authTransactionFeeETH);