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

unit214 #532

Merged
merged 12 commits into from
Nov 19, 2024
1 change: 1 addition & 0 deletions cypress.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ export default defineConfig({
'Mozilla/5.0 (iPhone; CPU iPhone OS 17_5_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4.1 Mobile/15E148 Safari/604.1',
viewportHeight: 800,
viewportWidth: 400,
defaultCommandTimeout: 20000,
});
2 changes: 1 addition & 1 deletion src/components/ConfirmSwapModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
<span>{{ slippage }}%</span>
</div>
<div v-if="!isAeVsWae">
<span>{{ $t('confirmSwapModal.priceImpact') }}</span>
<span>{{ $t('confirmSwapModal.priceImpact', { token: from.symbol }) }}</span>
<span>{{ priceImpact?.toFixed(8) }}%</span>
</div>
<div class="no-border">
Expand Down
6 changes: 3 additions & 3 deletions src/components/explore/PairTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,15 @@ export default {
value: pair.tvlUsd,
},
volumeDay: {
text: formatUsdPretty(pair.volumeUsdDay, 0),
text: formatUsdPretty(pair.volumeUsdDay || 0, 0),
value: pair.volumeUsdDay,
},
volumeMonth: {
text: formatUsdPretty(pair.volumeUsdMonth, 0),
text: formatUsdPretty(pair.volumeUsdMonth || 0, 0),
value: pair.volumeUsdMonth,
},
volumeAll: {
text: formatUsdPretty(pair.volumeUsdAll, 0),
text: formatUsdPretty(pair.volumeUsdAll || 0, 0),
value: pair.volumeUsdAll,
},
}));
Expand Down
191 changes: 45 additions & 146 deletions src/components/explore/PriceHistoryGraph.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
v-for="label in labels"
:key="label"
class="p-16 hidden md:block"
:fill="label === selectedChart ? 'light' : 'transparent'"
:fill="label.type === selectedChart.type ? 'light' : 'transparent'"
@click="changeChartContent(label)"
>
{{ label }}
{{ label.text }}
</ButtonDefault>
<div class="border border-gray-800 p-2 md:hidden rounded-xl">
<label for="chart-select" class="hidden">Select Option</label>
Expand All @@ -18,7 +18,7 @@
@change="changeChartContent($event.target.value)"
>
<option v-for="label in labels" :key="label" :value="label" class="bg-gray-800">
{{ label }}
{{ label.text }}
</option>
</select>
</div>
Expand Down Expand Up @@ -71,7 +71,6 @@ import {
import { Line, Bar } from 'vue-chartjs';
import 'chartjs-adapter-date-fns';
import ButtonDefault from '@/components/ButtonDefault.vue';
import BigNumber from 'bignumber.js';

const TIME_FRAMES = {
'1H': 1,
Expand Down Expand Up @@ -102,18 +101,27 @@ export default {
Bar,
},
props: {
datasets: { type: Array, required: true },
x: { type: Array, required: true },
initialChart: { type: String, default: 'Volume' },
availableGraphTypes: { type: Array, required: true },
initialChart: { type: Object, required: true },
initialTimeFrame: { type: String, default: 'MAX' },
loading: { type: Boolean, default: false },
pairId: { type: String, default: null },
tokenId: { type: String, default: null },
},
data() {
return {
selectedTimeFrame: null,
selectedChart: null,
selectedChart: {
type: null,
text: null,
},
colors: ['red', 'green', 'blue', 'purple', 'orange'],
timeFrames: TIME_FRAMES,
graph: {
labels: [],
data: [],
graphType: null,
},
loading: false,
};
},
computed: {
Expand All @@ -137,180 +145,71 @@ export default {
offset: true,
min: Math.max(
Date.now() - 1000 * 60 * 60 * this.timeFrames[this.selectedTimeFrame],
this.filteredData.filteredTime[0],
this.graph.labels[0],
),
max: Date.now(),
},
y: {
ticks: {
// Include a dollar sign in the ticks
callback: (value) =>
['TVL', 'Fees', 'Volume'].includes(this.selectedChart) ? `$${value}` : value,
['TVL', 'Fees', 'Volume'].includes(this.selectedChart.type) ? `$${value}` : value,
},
},
},
};
},
labels() {
return this.datasets.map((d) => d.label);
},
filteredData() {
const selectedDataSet = this.datasets.find((d) => d.label === this.selectedChart);
const minTime =
this.selectedTimeFrame === 'MAX'
? Math.min(...this.x)
: Date.now() - 1000 * 60 * 60 * this.timeFrames[this.selectedTimeFrame];

const data = {
filteredData: selectedDataSet.data
.filter((_, i) => this.x[i] >= minTime)
.filter((d) => !new BigNumber(d).isNaN()),
excludedData: selectedDataSet.data
.filter((_, i) => this.x[i] < minTime)
.filter((d) => !new BigNumber(d).isNaN()),
filteredTime: this.x
.filter((_, i) => !new BigNumber(selectedDataSet.data[i]).isNaN())
.filter((d) => d >= minTime)
.map((d) => Number(d)),
excludedTime: this.x
.filter((_, i) => !new BigNumber(selectedDataSet.data[i]).isNaN())
.filter((d) => d < minTime)
.map((d) => Number(d)),
};

// interpolate data to show full frame
if (
(['TVL', 'Locked'].includes(this.selectedChart) || this.selectedChart.includes('Price')) &&
data.excludedData.length > 0
) {
// all of these are aggregated and summed, so we need to have baseline
data.filteredData.unshift(data.excludedData.pop());
data.filteredTime.unshift(minTime);
data.excludedTime.pop();
}

if (['Volume', 'Fees'].includes(this.selectedChart) && data.filteredData.length > 0) {
// these just show the last value, so we need to have a baseline for the graph time but no value
// if there is no data, we do not need to add anything as we can show "no data"
data.filteredData.unshift(0);
data.filteredTime.unshift(minTime);
}

if (this.selectedChart.includes('Price')) {
// as these always have current value, we need to add it to the end
// theoretically this is also required for TVL and locked, but we interpolate those in the graph based
// on the last value, so we don't need to add it here
data.filteredData.push(data.filteredData[data.filteredData.length - 1]);
data.filteredTime.push(Date.now());
}

return {
...data,
selectedDataSet,
minTime,
};
return this.availableGraphTypes;
},
graphData() {
// filter data based on selected time
const { filteredTime, filteredData, selectedDataSet, minTime } = this.filteredData;
if (
(filteredData.length === 0 || filteredTime.length === 0 || !selectedDataSet) &&
(this.selectedChart === 'Fees' || this.selectedChart === 'Volume')
) {
return {
labels: [],
datasets: [],
};
}

// aggregate data based on selected time
// retrieve min time from data or default to selected view
if (['TVL', 'Volume', 'Fees', 'Locked'].includes(this.selectedChart)) {
// these three charts are bar charts, so we need to calculate buckets
const bucketSize = (Date.now() - minTime) / 30;

// seed empty buckets
const emptyBuckets = Object.fromEntries(
Array.from({ length: 31 }).map((_, i) => {
const key = minTime + i * bucketSize;
return [key, []];
}),
);

const aggregatedData = filteredData.reduce((acc, d, i) => {
const time = filteredTime[i];
const bucketIndex = Math.floor((time - minTime) / bucketSize);
const key = minTime + bucketIndex * bucketSize;
acc[key].push(d);
return acc;
}, emptyBuckets);
let bucketedData;
// interpolate TVL
if (['TVL', 'Locked'].includes(this.selectedChart)) {
// average TVL
let prevArr = [];
bucketedData = Object.fromEntries(
Object.entries(aggregatedData).map(([time, bucketArr], index) => {
let aggregatedValue = bucketArr
.reduce((acc, v) => acc.plus(v), new BigNumber(0))
.div(bucketArr.length);
// interpolate TVL by filling in missing data with latest value from previous bucket
if (index > 0 && aggregatedValue.isNaN()) {
aggregatedValue = prevArr[prevArr.length - 1];
} else {
prevArr = [...bucketArr];
}
return [time, aggregatedValue];
}),
);
} else {
// sum fees and volume
bucketedData = Object.fromEntries(
Object.entries(aggregatedData).map(([time, bucketArr]) => [
time,
bucketArr.reduce((acc, v) => acc.plus(v), new BigNumber(0)),
]),
);
}
return {
labels: Object.keys(bucketedData).map((x) => Number(x)),
datasets: [
{
label: selectedDataSet.label,
data: Object.values(bucketedData).map((y) => Number(y)),
borderColor: 'rgb(0 255 157 / 80%)',
backgroundColor: 'rgb(0 255 157 / 80%)',
},
],
};
}

return {
labels: filteredTime.map((x) => Number(x)),
labels: this.graph.labels.map((l) => Number(l)),
datasets: [
{
label: selectedDataSet.label,
data: filteredData.map((y) => Number(y)),
label: this.graph.graphType,
data: this.graph.data?.map((n) => Number(n)),
borderColor: 'rgb(0 255 157 / 80%)',
backgroundColor: 'rgb(0 255 157 / 80%)',
},
],
};
},
showBar() {
return ['TVL', 'Volume', 'Fees', 'Locked'].includes(this.selectedChart);
return ['TVL', 'Volume', 'Fees', 'Locked'].includes(this.selectedChart.type);
},
},
async mounted() {
await this.fetchData();
},
created() {
this.selectedTimeFrame = this.initialTimeFrame;
this.selectedChart = this.initialChart;
},
methods: {
changeTimeFrame(newTimeFrame) {
this.selectedTimeFrame = newTimeFrame;
this.fetchData();
},
changeChartContent(newChart) {
this.selectedChart = newChart;
this.fetchData();
},
async fetchData() {
this.loading = true;
this.graph.data = [];
let options = {
graphType: this.selectedChart.type,
timeFrame: this.selectedTimeFrame,
};
if (this.pairId) {
options = { ...options, pairAddress: this.pairId };
}
if (this.tokenId) {
options = { ...options, tokenAddress: this.tokenId };
}
this.graph = await this.$store.dispatch('backend/fetchGraph', options);
this.loading = false;
},
},
};
Expand Down
6 changes: 3 additions & 3 deletions src/components/explore/TokenTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,15 @@ export default {
value: token.priceChangeMonth,
},
volumeDay: {
text: formatUsdPretty(token.volumeUsdDay, 0),
text: formatUsdPretty(token.volumeUsdDay || 0, 0),
value: token.volumeUsdDay,
},
volumeMonth: {
text: formatUsdPretty(token.volumeUsdMonth, 0),
text: formatUsdPretty(token.volumeUsdMonth || 0, 0),
value: token.volumeUsdMonth,
},
volumeAll: {
text: formatUsdPretty(token.volumeUsdAll, 0),
text: formatUsdPretty(token.volumeUsdAll || 0, 0),
value: token.volumeUsdAll,
},
}));
Expand Down
2 changes: 1 addition & 1 deletion src/lib/swapUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ const getPriceImpactForPairReserves = (pairReserves, amountA) => {
const marketPrice = BigNumber(1).div(ratioFromPairReserves(pairReserves));
const newPrice = BigNumber(amountA).div(receivedB);

return newPrice.minus(marketPrice).times(100).div(marketPrice).toNumber();
return -newPrice.minus(marketPrice).times(100).div(newPrice).toNumber();
};

/**
Expand Down
2 changes: 1 addition & 1 deletion src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"to": "To",
"transactionDetails": "Transaction Details",
"liquidityProviderFee": "Liquidity Provider Fee",
"priceImpact": "Price Impact",
"priceImpact": "Price Impact on {token}",
"allowedSlippage": "Allowed Slippage",
"minReceived": "Minimum received",
"maxSpent": "Maximum spent",
Expand Down
2 changes: 1 addition & 1 deletion src/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"to": "Pour",
"transactionDetails": "détails de la transaction",
"liquidityProviderFee": "Frais de fournisseur de liquidité",
"priceImpact": "Incidence sur les prix",
"priceImpact": "Incidence sur les prix de {token}",
"allowedSlippage": "Glissement autorisé",
"minReceived": "Minimum reçu",
"maxSpent": "Dépense maximale",
Expand Down
2 changes: 1 addition & 1 deletion src/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"to": "Получаете",
"transactionDetails": "Детали транзакции",
"liquidityProviderFee": "Комиссия поставщика ликвидности",
"priceImpact": "Влияние на цену",
"priceImpact": "Влияние на цену {token}",
"allowedSlippage": "Допустимое проскальзывание",
"minReceived": "Минимум к получению",
"maxSpent": "Максимум к продаже",
Expand Down
2 changes: 1 addition & 1 deletion src/locales/zh-cn.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"to": "到",
"transactionDetails": "交换详情",
"liquidityProviderFee": "Liquidity Provider Fee",
"priceImpact": "价格影响",
"priceImpact": "价格影响针对 {token}",
"allowedSlippage": "滑点",
"minReceived": "最小收益",
"maxSpent": "最多支付",
Expand Down
Loading
Loading