Skip to content
Closed
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
92 changes: 50 additions & 42 deletions src/API/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import axios from 'axios';
import seedrandom from 'seedrandom';
import { BACKEND_URL } from '../manifestEnvs';

const SATURATION = 76293289283071;

const backendUrl: string = BACKEND_URL;

const BIAS_POOL_IDS = [
'dbda39c8d064ff9801e376f8350efafe67c07e9e9244dd613aee5125', // EMURA
// '359d3f8e355c873b0b5cae1e18eb12e44dcfc2ad212706d93ac314ab', // EMURB
'8efb053977341471256685b1069d67f4aca7166bc3f94e27ebad217f', // EMUR7
'0ef7aa564933ce75b695cdad66be4a39b43a22726de7c58908e0e033', // EMUR8
// '0ef7aa564933ce75b695cdad66be4a39b43a22726de7c58908e0e033', // EMUR8
'359d3f8e355c873b0b5cae1e18eb12e44dcfc2ad212706d93ac314ab', // EMURB
'2a8294ad7538b15353b9ffd81e26dafe846ffc3f6b9e331d4c1dc030', // YORO1
'b19f2d9498845652ae6eea5da77952b37e2bca9f59b2a98c56694cae', // YORO2
];
Expand All @@ -28,13 +30,13 @@ const brackets = [
{ startIndex: 53, positionGap: 27 },
];

export type HistBPE = {|
type HistBPE = {|
+val: string,
+time: string,
+e: number,
|};

export type SocialMediaHandles = {|
type SocialMediaHandles = {|
tw: ?string,
tg: ?string,
fb: ?string,
Expand Down Expand Up @@ -74,14 +76,7 @@ export type Pool = {|
+saturation: number,
|};

export type World = {|
+epoch: string,
+slot: string,
+stake: string,
+supply: number,
+pools: string,
+price: number,
+delegators: string,
type World = {|
+saturation: number,
|};

Expand All @@ -102,7 +97,7 @@ export const SortingDirections = Object.freeze({
});

export type SortingEnum = $Values<typeof Sorting>;
export type SortingDirEnum = $Values<typeof SortingDirections>;
type SortingDirEnum = $Values<typeof SortingDirections>;

export type SearchParams = {|
limit?: number,
Expand All @@ -111,38 +106,54 @@ export type SearchParams = {|
sortDirection?: SortingDirEnum,
|};

export type ApiPoolsResponse = {|
type ApiPoolsResponse = {|
world?: World,
pools?: {| [string]: Pool |},
pools?: Array<Pool>,
|};

const toPoolArray: (?{| [string]: Pool |}) => Array<Pool> = (pools) => {
if (pools == null) return [];
return Object.keys(pools)
.map((key) => pools[key])
.filter((x) => x != null);
};

export function getPools(body: SearchParams): Promise<ApiPoolsResponse> {
function transformData(poolsResponse) {
return {
world: {
saturation: SATURATION,
},
pools: poolsResponse?.data?.data?.map((pool) => (
{
id: pool.pool_id,
id_bech: pool.pool_id_hash_raw,
db_ticker: pool.pool_name.ticker,
db_name: pool.pool_name.name,
pledge: String(pool.pledged),
pledge_real: String(pool.pledged),
total_stake: String(pool.live_stake),
tax_fix: String(pool.pool_update.live.fixed_cost),
tax_ratio: String(pool.pool_update.live.margin),
blocks_epoch: pool.blocks.epoch,
roa: String(pool.stats.lifetime.roa),
handles: {},
saturation: pool.live_stake / SATURATION,
}
)) ?? [],
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Missing Pool Properties Break UI Sorting and UI

The transformData function creates Pool objects missing many required properties from the Pool type definition. Most critically, it's missing total_size, score, pool_pic, fullname, tax_computed, hist_bpe, hist_roa, last_rewards, position, and the color_* properties. The missing total_size property will break the pool size sorting feature in HomeRevamp.js (lines 112-115) since sorting by undefined values will result in NaN comparisons. Other missing properties may cause issues elsewhere in the UI.

Fix in Cursor Fix in Web

}

function getPools(network: 'mainnet' | 'preprod', body: SearchParams): Promise<ApiPoolsResponse> {
const requestBody = {
...{ search: '', sort: Sorting.SCORE, limit: 250 },
...{ order: 'ranking', limit: 250},
...body,
//fixme
//network,
};

const encodeForm = (data) => {
return (Object.keys(data): any)
.map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`)
.join('&');
};
const searchParams = new URLSearchParams();
Object.keys(requestBody).forEach((key) => {
searchParams.append(key, String(requestBody[key]));
});

return axios(`${backendUrl}`, {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'post',
data: encodeForm(requestBody),
})
return axios(`${backendUrl}?${searchParams.toString()}`)
.then((response) => {
const poolsResponse: ApiPoolsResponse = response.data;
return poolsResponse;
return transformData(poolsResponse);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Empty Pools Break Runtime Array Operations Across API

The error handler in getPools returns pools: {} (empty object) instead of pools: [] (empty array). Since the ApiPoolsResponse type specifies pools?: Array<Pool>, this type mismatch will cause runtime errors when the code tries to call array methods like .filter() on the pools property (e.g., at line 219 where biasedPoolsResponse.pools.filter(...) is called).

Fix in Cursor Fix in Web

})
.catch((error) => {
console.error('API::getPools Error: ', error);
Expand Down Expand Up @@ -181,11 +192,12 @@ export type ListBiasedPoolsResponse = {|
|};

export async function listBiasedPools(
network: 'mainnet' | 'preprod',
externalSeed: string,
searchParams: SearchParams,
): Promise<ListBiasedPoolsResponse> {
const unbiasedPoolsResponse = await getPools(searchParams);
const originalPools = toPoolArray(unbiasedPoolsResponse.pools);
const unbiasedPoolsResponse = await getPools(network, searchParams);
const originalPools = unbiasedPoolsResponse.pools;

const saturationLimit = unbiasedPoolsResponse.world?.saturation;

Expand All @@ -202,9 +214,9 @@ export async function listBiasedPools(
const internalSeed = tail(p1?.id) + tail(p2?.id) + tail(p3?.id);

try {
const biasedPoolsResponse = await getPools({ search: BIAS_POOLS_SEARCH_QUERY });
const biasedPoolsResponse = await getPools(network, { search: BIAS_POOLS_SEARCH_QUERY });
if (!biasedPoolsResponse) return { pools: unbiasedPools, saturationLimit };
const biasedPools = toPoolArray(biasedPoolsResponse.pools)
const biasedPools = biasedPoolsResponse.pools
.filter((x) => x.id && BIAS_POOL_IDS.indexOf(x.id) >= 0)
.sort((a, b) => {
// this sorting is to ensure that changes in the backend response order is not affecting the final ordering
Expand Down Expand Up @@ -242,7 +254,3 @@ export async function listBiasedPools(
return { pools: unbiasedPools, saturationLimit };
}
}

export function listPools(): Promise<ApiPoolsResponse> {
return getPools(({}: any));
}
3 changes: 2 additions & 1 deletion src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { Node } from 'react';
import GlobalStyle from './helpers/globalStyles';
import Home from './containers/Home';
import HomeRevamp from './containers/HomeRevamp';
import type { UrlParams } from './containers/Home';
import type { UrlParams } from './types';

const parseIds = (array: ?string): Array<string> => {
if (array == null) return [];
Expand All @@ -25,6 +25,7 @@ const extractParams = (locationSearch: string): UrlParams => {
layout: params.get('layout'),
bias: params.get('bias'),
theme: params.get('theme'),
network: params.get('network') === 'preprod' ? 'preprod' : 'mainnet',
};
};

Expand Down
18 changes: 4 additions & 14 deletions src/containers/Home.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import Modal from '../components/common/Modal';
import SaturatedPoolAlert from '../components/SaturatedPoolAlert';
import cexplorerIconMini from '../assets/cexplorer-logo-mini.svg';
import cexplorerIcon from '../assets/cexplorer-logo-extend.svg';
import type { UrlParams } from '../types';

const Header = styled.div`
display: flex;
Expand Down Expand Up @@ -71,17 +72,6 @@ const CreditSection = styled.div`
height: 32px;
}
`;
export type UrlParams = {|
chromeId: ?string,
mozId: ?string,
source: ?string,
selectedPoolIds: ?Array<string>,
lang: ?string,
totalAda: ?number,
layout: ?string,
bias: ?string,
theme: ?string,
|};

export type HomeProps = {|
urlParams: UrlParams,
Expand Down Expand Up @@ -111,7 +101,7 @@ function Home(props: HomeProps): Node {

useEffect(() => {
setStatus('pending');
listBiasedPools(seed, {})
listBiasedPools(props.urlParams.network, seed, {})
.then((resp: ListBiasedPoolsResponse) => {
setStatus('resolved');
setRowData(resp.pools);
Expand All @@ -130,7 +120,7 @@ function Home(props: HomeProps): Node {
};
setFilterOptions(newSearch);
setStatus('pending');
listBiasedPools(seed, newSearch)
listBiasedPools(props.urlParams.network, seed, newSearch)
.then((resp: ListBiasedPoolsResponse) => {
setStatus('resolved');
setRowData(resp.pools);
Expand All @@ -148,7 +138,7 @@ function Home(props: HomeProps): Node {
};
setFilterOptions(newSearch);
setStatus('pending');
listBiasedPools(seed, newSearch)
listBiasedPools(props.urlParams.network, seed, newSearch)
.then((resp: ListBiasedPoolsResponse) => {
setStatus('resolved');
setRowData(resp.pools);
Expand Down
17 changes: 3 additions & 14 deletions src/containers/HomeRevamp.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import DesktopTableRevamp from '../components/DesktopTableRevamp';
import SearchRevamp from '../components/SearchRevamp';
import MobileTableRevamp from '../components/MobileTableRevamp';
import { formatCostLabel } from '../utils/utils';
import type { UrlParams } from '../types';

const Header = styled.div`
display: flex;
Expand Down Expand Up @@ -89,18 +90,6 @@ const CreditSection = styled.div`
height: 32px;
}
`;
export type UrlParams = {|
chromeId: ?string,
mozId: ?string,
source: ?string,
selectedPoolIds: ?Array<string>,
lang: ?string,
totalAda: ?number,
layout: ?string,
bias: ?string,
theme: ?string,
|};

export type HomeProps = {|
urlParams: UrlParams,
|};
Expand Down Expand Up @@ -168,7 +157,7 @@ function Home(props: HomeProps): Node {

useEffect(() => {
setStatus('pending');
listBiasedPools(seed, {})
listBiasedPools(props.urlParams.network, seed, {})
.then((resp: ListBiasedPoolsResponse) => {
setStatus('resolved');
setRowData(resp.pools);
Expand All @@ -189,7 +178,7 @@ function Home(props: HomeProps): Node {
};
setFilterOptions(newSearch);
setStatus('pending');
listBiasedPools(seed, newSearch)
listBiasedPools(props.urlParams.network, seed, newSearch)
.then((resp: ListBiasedPoolsResponse) => {
setStatus('resolved');
setRowData(resp.pools);
Expand Down
4 changes: 1 addition & 3 deletions src/manifestEnvs.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// @flow

const BACKEND_URL /*: string */ = process.env.BACKEND_URL != null
? process.env.BACKEND_URL
: 'https://a.cexplorer.io/yoroi-api/';
const BACKEND_URL = 'https://api-mainnet-stage.cexplorer.io/v1/pool/list';

module.exports = {
BACKEND_URL,
Expand Down
14 changes: 14 additions & 0 deletions src/types.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// @flow

export type UrlParams = {|
chromeId: ?string,
mozId: ?string,
source: ?string,
selectedPoolIds: ?Array<string>,
lang: ?string,
totalAda: ?number,
layout: ?string,
bias: ?string,
theme: ?string,
network: 'mainnet' | 'preprod',
|};