Skip to content
Draft
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
12 changes: 12 additions & 0 deletions packages/assets-controllers/src/TokenListController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,18 @@ export type TokenListToken = {
occurrences: number;
aggregators: string[];
iconUrl: string;
rwaData?: {
instrumentType: string;
ticker: string;
market: {
nextOpen: string;
nextClose: string;
};
nextPause: {
start: string;
end: string;
};
};
};

export type TokenListMap = Record<string, TokenListToken>;
Expand Down
138 changes: 128 additions & 10 deletions packages/assets-controllers/src/token-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import type { CaipChainId, Hex } from '@metamask/utils';

import { isTokenListSupportedForNetwork } from './assetsUtil';

export const TOKEN_END_POINT_API = 'https://token.api.cx.metamask.io';
// export const TOKEN_END_POINT_API = 'https://token.api.cx.metamask.io';
// TODO change it back after development is done
export const TOKEN_END_POINT_API = 'https://token.dev-api.cx.metamask.io';
export const TOKEN_METADATA_NO_SUPPORT_ERROR =
'TokenService Error: Network does not support fetchTokenMetadata';

Expand All @@ -18,7 +20,7 @@ export const TOKEN_METADATA_NO_SUPPORT_ERROR =
* @param chainId - The chain ID of the network the tokens requested are on.
* @returns The tokens URL.
*/
function getTokensURL(chainId: Hex) {
function getTokensURL(chainId: Hex): string {
const occurrenceFloor = chainId === ChainId['linea-mainnet'] ? 1 : 3;

return `${TOKEN_END_POINT_API}/tokens/${convertHexToDecimal(
Expand All @@ -33,7 +35,7 @@ function getTokensURL(chainId: Hex) {
* @param tokenAddress - The token address.
* @returns The token metadata URL.
*/
function getTokenMetadataURL(chainId: Hex, tokenAddress: string) {
function getTokenMetadataURL(chainId: Hex, tokenAddress: string): string {
return `${TOKEN_END_POINT_API}/token/${convertHexToDecimal(
chainId,
)}?address=${tokenAddress}`;
Expand Down Expand Up @@ -62,12 +64,12 @@ function getTokenSearchURL(
query: string,
limit = 10,
includeMarketData = false,
) {
): string {
const encodedQuery = encodeURIComponent(query);
const encodedChainIds = chainIds
.map((id) => encodeURIComponent(id))
.join(',');
return `${TOKEN_END_POINT_API}/tokens/search?networks=${encodedChainIds}&query=${encodedQuery}&limit=${limit}&includeMarketData=${includeMarketData}`;
return `${TOKEN_END_POINT_API}/tokens/search?networks=${encodedChainIds}&query=${encodedQuery}&limit=${limit}&includeMarketData=${includeMarketData}&includeRwaData=true`;
}

/**
Expand Down Expand Up @@ -142,16 +144,74 @@ export async function fetchTokenListByChainId(
if (response) {
const result = await parseJsonResponse(response);
if (Array.isArray(result) && chainId === ChainId['linea-mainnet']) {
return result.filter(
const filteredResult = result.filter(
(elm) =>
elm.aggregators.includes('lineaTeam') || elm.aggregators.length >= 3,
elm.aggregators.includes('lineaTeam') ?? elm.aggregators.length >= 3,
);
// TODO: remove this after development is done
// if the filteredResult has an aggregator that includes 'Ondo' then append rwaData as metadata.
const filteredResultWithRwaData = filteredResult.map((elm) => {
const metadata = {
rwaData: {
instrumentType: 'stock',
ticker: elm.name?.split(' ')[0] ?? '',
market: {
nextOpen: new Date(new Date().setHours(9, 0, 0, 0)).toISOString(),
nextClose: new Date(
new Date().setHours(16, 0, 0, 0),
).toISOString(),
},
nextPause: {
start: new Date(new Date().setHours(16, 0, 0, 0)).toISOString(),
end: new Date(new Date().setHours(17, 0, 0, 0)).toISOString(),
},
},
};
if (elm.aggregators.includes('Ondo')) {
return { ...elm, ...metadata };
}
return elm;
});

console.log('filteredResult', filteredResult);
return filteredResultWithRwaData;
}

if (Array.isArray(result)) {
// TODO: remove this after development is done
// if the filteredResult has an aggregator that includes 'Ondo' then append rwaData as metadata.
const filteredResultWithRwaData = result.map((elm) => {
const metadata = {
rwaData: {
instrumentType: 'stock',
ticker: elm.name?.split(' ')[0] ?? '',
market: {
nextOpen: new Date(new Date().setHours(9, 0, 0, 0)).toISOString(),
nextClose: new Date(
new Date().setHours(16, 0, 0, 0),
).toISOString(),
},
nextPause: {
start: new Date(new Date().setHours(16, 0, 0, 0)).toISOString(),
end: new Date(new Date().setHours(17, 0, 0, 0)).toISOString(),
},
},
};
if (elm.aggregators.includes('Ondo')) {
return { ...elm, ...metadata };
}
return elm;
});

console.log('filteredResultWithRwaData', filteredResultWithRwaData);
return filteredResultWithRwaData;
}
return result;
}
return undefined;
}

// TODO This end point already contain RwaData, so we don't need to append it here.
/**
* Search for tokens across one or more networks by query string using CAIP format chain IDs.
*
Expand Down Expand Up @@ -180,7 +240,7 @@ export async function searchTokens(
// The API returns an object with structure: { count: number, data: array, pageInfo: object }
if (result && typeof result === 'object' && Array.isArray(result.data)) {
return {
count: result.count || result.data.length,
count: result.count ?? result.data.length,
data: result.data,
};
}
Expand Down Expand Up @@ -214,6 +274,18 @@ export type TrendingAsset = {
h24?: string;
};
labels?: string[];
rwaData?: {
instrumentType: string;
ticker: string;
market: {
nextOpen: string;
nextClose: string;
};
nextPause: {
start: string;
end: string;
};
};
};

/**
Expand Down Expand Up @@ -271,7 +343,27 @@ export async function getTrendingTokens({

// Validate that the API returned an array
if (Array.isArray(result)) {
return result;
// TODO hack the results to include RwaData
const filteredResultWithRwaData = result.map((elm) => {
const metadata = {
rwaData: {
instrumentType: 'stock',
ticker: elm.name?.split(' ')[0] ?? '',
market: {
nextOpen: new Date(new Date().setHours(9, 0, 0, 0)).toISOString(),
nextClose: new Date(
new Date().setHours(16, 0, 0, 0),
).toISOString(),
},
nextPause: {
start: new Date(new Date().setHours(16, 0, 0, 0)).toISOString(),
end: new Date(new Date().setHours(17, 0, 0, 0)).toISOString(),
},
},
};
return { ...elm, ...metadata };
});
return filteredResultWithRwaData;
}

// Handle non-expected responses
Expand Down Expand Up @@ -306,7 +398,33 @@ export async function fetchTokenMetadata<T>(
const tokenMetadataURL = getTokenMetadataURL(chainId, tokenAddress);
const response = await queryApi(tokenMetadataURL, abortSignal, timeout);
if (response) {
return parseJsonResponse(response) as Promise<T>;
const result = await parseJsonResponse(response);
if (Array.isArray(result)) {
const filteredResultWithRwaData = result.map((elm) => {
const metadata = {
rwaData: {
instrumentType: 'stock',
ticker: elm.name?.split(' ')[0] ?? '',
market: {
nextOpen: new Date(new Date().setHours(9, 0, 0, 0)).toISOString(),
nextClose: new Date(
new Date().setHours(16, 0, 0, 0),
).toISOString(),
},
nextPause: {
start: new Date(new Date().setHours(16, 0, 0, 0)).toISOString(),
end: new Date(new Date().setHours(17, 0, 0, 0)).toISOString(),
},
},
};
if (elm.aggregators.includes('Ondo')) {
return { ...elm, ...metadata };
}
return elm;
});
return filteredResultWithRwaData as unknown as T;
}
return result as T;
}
return undefined;
}
Expand Down
17 changes: 16 additions & 1 deletion packages/bridge-controller/src/utils/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,22 @@ export async function fetchBridgeTokens(
const transformedTokens: Record<string, BridgeAsset> = {};
tokens.forEach((token: unknown) => {
if (validateSwapsTokenObject(token)) {
transformedTokens[token.address] = token;
// TODO hack the results to include RwaData
const metadata = {
rwaData: {
instrumentType: 'stock',
ticker: token.name?.split(' ')[0] ?? '',
market: {
nextOpen: new Date(new Date().setHours(9, 0, 0, 0)).toISOString(),
nextClose: new Date(new Date().setHours(16, 0, 0, 0)).toISOString(),
},
nextPause: {
start: new Date(new Date().setHours(16, 0, 0, 0)).toISOString(),
end: new Date(new Date().setHours(17, 0, 0, 0)).toISOString(),
},
},
};
transformedTokens[token.address] = { ...token, ...metadata };
}
});
return transformedTokens;
Expand Down
15 changes: 15 additions & 0 deletions packages/bridge-controller/src/utils/validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,21 @@ export const BridgeAssetSchema = type({
* URL for token icon
*/
iconUrl: optional(nullable(string())),

rwaData: optional(
type({
instrumentType: string(),
ticker: string(),
market: type({
nextOpen: string(),
nextClose: string(),
}),
nextPause: type({
start: string(),
end: string(),
}),
}),
),
});

const DefaultPairSchema = type({
Expand Down
Loading