Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add multi-callee support to the frontend #498

Merged
merged 19 commits into from
Nov 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions core/src/auctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,43 +86,42 @@ 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
try {
const currentDate = await getNetworkDate(auction.network);
marketData = {
...marketData,
transactionGrossProfitDate: calculateTransactionGrossProfitDate(
auction,
marketData.marketUnitPrice,
currentDate
),
transactionGrossProfitDate: calculateTransactionGrossProfitDate(auction, marketUnitPrice, currentDate),
};
} catch {}
enrichedMarketDataRecords = {
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion core/src/calleeFunctions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export const getBestMarketId = async function (marketDataRecords: Record<string,
if (b[1].marketUnitPrice.isNaN()) {
return -1;
}
return a[1].marketUnitPrice.minus(b[1].marketUnitPrice).toNumber();
return a[1].marketUnitPrice.minus(b[1].marketUnitPrice).multipliedBy(-1).toNumber();
});
return marketDataRecordsSorted[0][0];
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@
type="error"
/>
<Alert v-if="auctionTransaction.isFinished" message="This auction is finished" type="error" />
<CollateralAuctionSwapTransactionTable :auction-transaction="auctionTransaction" class="mt-4" />
<CollateralAuctionSwapTransactionTable
:auction-transaction="auctionTransaction"
:market-id.sync="currentMarketId"
class="mt-4"
/>
<TextBlock class="TextBlock mt-4 mb-8">
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
Expand Down Expand Up @@ -87,7 +91,7 @@
@execute="
$emit('execute', {
id: auctionTransaction.id,
marketId: auctionTransaction.suggestedMarketId,
marketId: marketSuggestionOrSelection,
alternativeDestinationAddress: $event,
})
"
Expand Down Expand Up @@ -157,6 +161,7 @@ export default Vue.extend({
},
data() {
return {
currentMarketId: '',
isWalletConnectedCheck: false,
isWalletDAIAuthorizationCheckPassed: false,
isWalletCollateralAuthorizationCheckPassed: false,
Expand All @@ -183,6 +188,9 @@ export default Vue.extend({
}
return fees;
},
marketSuggestionOrSelection(): string | undefined {
return this.currentMarketId || this.auctionTransaction.suggestedMarketId;
},
},
});
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,12 @@
<span class="uppercase">{{ auctionTransaction.collateralSymbol }}</span>
</div>
</div>
<div class="flex w-full justify-between">
<div>Price On Uniswap</div>
<div class="RightInfo">
<template v-if="auctionTransaction.isActive && auctionTransaction.marketUnitPrice">
<FormatCurrency :value="auctionTransaction.marketUnitPrice" currency="DAI" /> per
<span class="uppercase">{{ auctionTransaction.collateralSymbol }}</span>
</template>
<span v-else class="opacity-50">Unknown</span>
</div>
</div>
<MarketPriceSelection :auction-transaction="auctionTransaction" :market-id.sync="currentMarketId" />
<div class="flex w-full justify-between">
<div>Market Difference</div>
<div class="RightInfo">
<template v-if="auctionTransaction.isActive && auctionTransaction.marketUnitPriceToUnitPriceRatio">
<FormatMarketValue :value="auctionTransaction.marketUnitPriceToUnitPriceRatio" />
<template v-if="auctionTransaction.isActive && marketUnitPriceToUnitPriceRatio">
<FormatMarketValue :value="marketUnitPriceToUnitPriceRatio" />
</template>
<span v-else class="opacity-50">Unknown</span>
</div>
Expand All @@ -50,9 +41,9 @@
<div>Transaction Gross Profit</div>
<div class="RightInfo">
<FormatCurrency
v-if="auctionTransaction.transactionGrossProfit"
v-if="transactionGrossProfit"
show-sign
:value="auctionTransaction.transactionGrossProfit"
:value="transactionGrossProfit"
currency="DAI"
/>
<span v-else class="opacity-50">Unknown</span>
Expand Down Expand Up @@ -84,9 +75,9 @@
<div class="font-extrabold">Transaction Net Profit</div>
<div class="RightInfo">
<FormatCurrency
v-if="auctionTransaction.transactionNetProfit"
v-if="transactionNetProfit"
show-sign
:value="auctionTransaction.transactionNetProfit"
:value="transactionNetProfit"
currency="DAI"
class="font-extrabold"
/>
Expand All @@ -97,20 +88,23 @@
</template>
<script lang="ts">
import Vue from 'vue';
import BigNumber from 'bignumber.js';
import PriceDropAnimation from '~/components/auction/collateral/PriceDropAnimation.vue';
import FormatCurrency from '~/components/common/formatters/FormatCurrency.vue';
import MarketPriceSelection from '~/components/auction/collateral/MarketPriceSelection.vue';
import TimeTillProfitable from '~/components/auction/collateral/TimeTillProfitable.vue';
import TimeTill from '~/components/common/formatters/TimeTill.vue';
import FormatCurrency from '~/components/common/formatters/FormatCurrency.vue';
import FormatMarketValue from '~/components/common/formatters/FormatMarketValue.vue';
import TextBlock from '~/components/common/other/TextBlock.vue';
import { AuctionTransaction } from '~/../core/src/types';

export default Vue.extend({
components: {
PriceDropAnimation,
FormatCurrency,
MarketPriceSelection,
TextBlock,
TimeTill,
FormatCurrency,
FormatMarketValue,
TimeTillProfitable,
},
Expand All @@ -119,6 +113,40 @@ export default Vue.extend({
type: Object as Vue.PropType<AuctionTransaction>,
required: true,
},
marketId: {
type: String,
default: '',
},
},
data() {
return {
currentMarketId: '',
};
},
computed: {
marketUnitPriceToUnitPriceRatio(): BigNumber | undefined {
if (!this.currentMarketId || !this.auctionTransaction.marketDataRecords) {
return this.auctionTransaction.marketUnitPriceToUnitPriceRatio;
}
return this.auctionTransaction.marketDataRecords[this.currentMarketId].marketUnitPriceToUnitPriceRatio;
},
transactionGrossProfit(): BigNumber | undefined {
if (!this.currentMarketId || !this.auctionTransaction.marketDataRecords) {
return this.auctionTransaction.transactionGrossProfit;
}
return this.auctionTransaction.marketDataRecords[this.currentMarketId].transactionGrossProfit;
},
transactionNetProfit(): BigNumber | undefined {
if (!this.currentMarketId || !this.auctionTransaction.marketDataRecords) {
return this.auctionTransaction.transactionNetProfit;
}
return this.auctionTransaction.marketDataRecords[this.currentMarketId].transactionNetProfit;
},
},
watch: {
currentMarketId(): void {
this.$emit('update:marketId', this.currentMarketId);
},
},
});
</script>
Expand Down
Original file line number Diff line number Diff line change
@@ -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: `<MarketPriceSelection :auction-transaction="auctionTransaction" :market-id.sync="marketId" />`,
};

storiesOf('Auction/Collateral/MarketPriceSelection', module).add('Default', () => ({ ...common }));
120 changes: 120 additions & 0 deletions frontend/components/auction/collateral/MarketPriceSelection.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<template>
<div>
<div class="flex justify-between">
<button class="Title" type="button" @click="isExpanded = !isExpanded">
<Icon v-if="!isExpanded" type="caret-right" class="Icon" />
<Icon v-else type="caret-down" class="Icon" />
Market Unit Price
<span class="text-gray-300">({{ suggestionOrSelection }})</span>
</button>
<div v-show="!isExpanded">
<FormatCurrency :value="marketUnitPrice" currency="DAI" /> per
<span class="uppercase">{{ auctionTransaction.collateralSymbol }}</span>
</div>
</div>
<CollapseTransition>
<div v-show="isExpanded" class="Content overflow-x-auto">
<table class="table-auto">
<tbody>
<tr v-for="callee in callees" :key="callee[0]">
<td class="pr-2 whitespace-nowrap">{{ callee[0] }}</td>
<td class="pr-2 whitespace-nowrap">
<span v-for="currency in callee[1].route" :key="currency"
>{{ currency }} &#8594;
</span>
DAI
</td>
<td class="w-full text-right whitespace-nowrap">
<div v-if="callee[1].marketUnitPrice && !callee[1].marketUnitPrice.isNaN()">
<button type="button" @click="$emit('update:marketId', callee[0])">
<span v-if="suggestionOrSelection === callee[0]" class="opacity-50"
>Selected</span
>
<span v-else class="text-green-500">Select</span>
</button>
<span class="pl-1">
<FormatCurrency :value="callee[1].marketUnitPrice" currency="DAI" /> per
<span class="uppercase">{{ auctionTransaction.collateralSymbol }}</span>
</span>
</div>
<div v-else class="opacity-50">Unknown</div>
</td>
</tr>
</tbody>
</table>
</div>
</CollapseTransition>
</div>
</template>

<script lang="ts">
import Vue from 'vue';
import BigNumber from 'bignumber.js';
import { Icon } from 'ant-design-vue';
import CollapseTransition from '@ivanv/vue-collapse-transition';
import { AuctionTransaction, MarketData } from 'auctions-core/src/types';
import FormatCurrency from '~/components/common/formatters/FormatCurrency.vue';

export default Vue.extend({
components: {
Icon,
FormatCurrency,
CollapseTransition,
},
props: {
auctionTransaction: {
type: Object as Vue.PropType<AuctionTransaction>,
required: true,
},
marketId: {
type: String,
default: '',
},
},
data() {
return {
isExpanded: false,
};
},
computed: {
suggestionOrSelection(): string | undefined {
return this.marketId || this.auctionTransaction.suggestedMarketId;
},
marketUnitPrice(): BigNumber | undefined {
if (this.auctionTransaction.marketDataRecords && this.suggestionOrSelection) {
return this.auctionTransaction.marketDataRecords[this.suggestionOrSelection].marketUnitPrice;
}
return undefined;
},
callees(): [string, MarketData][] {
const marketDataRecordsSorted = Object.entries(this.auctionTransaction.marketDataRecords || {});
marketDataRecordsSorted.sort((a, b) => {
// push NaNs to the end
if (a[1].marketUnitPrice.isNaN() && b[1].marketUnitPrice.isNaN()) {
return 1;
}
if (a[1].marketUnitPrice.isNaN()) {
return 1;
}
if (b[1].marketUnitPrice.isNaN()) {
return -1;
}
return a[1].marketUnitPrice.minus(b[1].marketUnitPrice).multipliedBy(-1).toNumber();
});
return marketDataRecordsSorted;
},
},
});
</script>

<style scoped>
.Title {
@apply text-left text-green-500;
}
.Icon {
@apply inline;
}
.Content {
@apply pl-4;
}
</style>
Loading