Skip to content

Commit

Permalink
feat: adapt new graph endpoint for ExploreView
Browse files Browse the repository at this point in the history
  • Loading branch information
tmrdlt authored and mmpetarpeshev committed Nov 19, 2024
1 parent aeac9b4 commit ad285d5
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 150 deletions.
170 changes: 28 additions & 142 deletions src/components/explore/PriceHistoryGraph.vue
Original file line number Diff line number Diff line change
Expand Up @@ -102,18 +102,23 @@ export default {
Bar,
},
props: {
availableGraphTypes: { type: Array, required: true },
datasets: { type: Array, required: true },
x: { type: Array, required: true },
initialChart: { type: String, default: 'Volume' },
initialTimeFrame: { type: String, default: 'MAX' },
loading: { type: Boolean, default: false },
},
data() {
return {
selectedTimeFrame: null,
selectedChart: null,
colors: ['red', 'green', 'blue', 'purple', 'orange'],
timeFrames: TIME_FRAMES,
graph: {
labels: [],
datasets: [],
},
loading: false,
};
},
computed: {
Expand All @@ -137,7 +142,7 @@ 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(),
},
Expand All @@ -152,166 +157,47 @@ export default {
};
},
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)),
datasets: [
{
label: selectedDataSet.label,
data: filteredData.map((y) => Number(y)),
borderColor: 'rgb(0 255 157 / 80%)',
backgroundColor: 'rgb(0 255 157 / 80%)',
},
],
labels: this.graph.labels.map((l) => Number(l)),
datasets: this.graph.datasets.map((d) => ({
label: d.label,
data: d.data.map((d) => Number(d)),
borderColor: 'rgb(0 255 157 / 80%)',
backgroundColor: 'rgb(0 255 157 / 80%)',
})),
};
},
showBar() {
return ['TVL', 'Volume', 'Fees', 'Locked'].includes(this.selectedChart);
},
},
async mounted() {
this.fetchData();
},
created() {
this.selectedTimeFrame = this.initialTimeFrame;
this.selectedChart = this.initialChart;
},
methods: {
changeTimeFrame(newTimeFrame) {
this.selectedTimeFrame = newTimeFrame;
this.fetchData();
},
changeChartContent(newChart) {
this.selectedChart = newChart;
},
async fetchData() {
this.loading = true;
this.graph.datasets = [];
this.graph = await this.$store.dispatch('backend/fetchGraph', {
graphType: this.selectedChart,
timeFrame: this.selectedTimeFrame,
});
this.loading = false;
},
},
};
</script>
Expand Down
5 changes: 5 additions & 0 deletions src/store/modules/dexBackend.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,5 +204,10 @@ export default {
async fetchPairsByTokenUsd({ dispatch }, tokenId) {
return dispatch('safeFetch', { url: `pairs?token=${tokenId}` });
},

async fetchGraph({ dispatch }, options) {
const queryString = new URLSearchParams(options).toString();
return dispatch('safeFetch', { url: `graph?${queryString}` });
},
},
};
10 changes: 2 additions & 8 deletions src/views/ExploreView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@
<PriceHistoryGraph
v-if="graphData"
:x="graphData.x"
:available-graph-types="['TVL']"
:datasets="tvl"
initial-chart="TVL"
:loading="loading"
/>
</div>
<div class="flex-1">
<h1 class="text-2xl">Volume</h1>
<PriceHistoryGraph
v-if="graphData"
:x="graphData.x"
:available-graph-types="['Volume']"
:datasets="volume"
initial-chart="Volume"
:loading="loading"
/>
</div>
</div>
Expand Down Expand Up @@ -97,7 +97,6 @@ export default defineComponent({
history: [],
tokenMap: new Map(),
activeTab: 'Tokens',
loading: false,
};
},
computed: {
Expand Down Expand Up @@ -165,17 +164,12 @@ export default defineComponent({
},
},
async mounted() {
this.loading = true;
// fetch all tokens
const tokens = await this.$store.dispatch('backend/getAllTokens');
this.tokenMap = new Map(tokens.map((token) => [token.address, detectAndModifyWAE(token)]));
// fetch all pairs
const fetchResult = await this.$store.dispatch('backend/fetchPairs');
this.pairs = Object.values(fetchResult);
// fetch all history
this.history = await this.$store.dispatch('backend/fetchHistory');
this.loading = false;
},
methods: {
pairToToken(pairAddress) {
Expand Down

0 comments on commit ad285d5

Please sign in to comment.