diff --git a/backend-api-demo/package-lock.json b/backend-api-demo/package-lock.json index 126cc19..bbd6a89 100644 --- a/backend-api-demo/package-lock.json +++ b/backend-api-demo/package-lock.json @@ -9,7 +9,8 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "axios": "^1.7.3" + "axios": "^1.7.3", + "csv-string": "^4.1.1" } }, "node_modules/asynckit": { @@ -35,6 +36,15 @@ "node": ">= 0.8" } }, + "node_modules/csv-string": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/csv-string/-/csv-string-4.1.1.tgz", + "integrity": "sha512-KGvaJEZEdh2O/EVvczwbPLqJZtSQaWQ4cEJbiOJEG4ALq+dBBqNmBkRXTF4NV79V25+XYtiqbco1IWrmHLm5FQ==", + "license": "MIT", + "engines": { + "node": ">=12.0" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "license": "MIT", diff --git a/backend-api-demo/package.json b/backend-api-demo/package.json index 9424886..5e98f87 100644 --- a/backend-api-demo/package.json +++ b/backend-api-demo/package.json @@ -10,6 +10,7 @@ "author": "Manh Cao Duy", "license": "ISC", "dependencies": { - "axios": "^1.7.3" + "axios": "^1.7.3", + "csv-string": "^4.1.1" } } diff --git a/backend-api-demo/src/const.ts b/backend-api-demo/src/const.ts index 6566424..d2680da 100644 --- a/backend-api-demo/src/const.ts +++ b/backend-api-demo/src/const.ts @@ -1 +1 @@ -export const EXTERNAL_DOMAIN = `https://api-v2.pendle.finance/api/external`; \ No newline at end of file +export const CORE_DOMAIN = `https://api-v2.pendle.finance/api/core`; \ No newline at end of file diff --git a/backend-api-demo/src/get-asset-prices.ts b/backend-api-demo/src/get-asset-prices.ts index df9c226..454dd86 100644 --- a/backend-api-demo/src/get-asset-prices.ts +++ b/backend-api-demo/src/get-asset-prices.ts @@ -1,5 +1,6 @@ -import { EXTERNAL_DOMAIN } from "./const"; +import { CORE_DOMAIN } from "./const"; import axios from "axios"; +import { parse } from "csv-string"; interface GetSpotPriceParam { chainId: number; @@ -10,7 +11,9 @@ interface GetSpotPriceQuery { } interface GetSpotPriceResponse { - prices: Record; + total: number; + addresses: string[]; + pricesUsd: (number | null)[]; } interface GetHistoricalPricesParam { @@ -34,11 +37,11 @@ interface HistoricalPriceData { interface GetHistoricalPricesResponse { total: number; - limit: number; currency: string; - timestampStart: string; - timestampEnd: string; - data: HistoricalPriceData; + timeFrame: string; + timestamp_start: number; + timestamp_end: number; + results: string; } export async function getAssetPrices() { @@ -48,14 +51,17 @@ export async function getAssetPrices() { chainId: 1, // Ethereum }; - const targetPath = `/v1/${param.chainId}/assets/prices`; + const targetPath = `/v1/${param.chainId}/prices/assets/all`; + + const { data } = await axios.get(CORE_DOMAIN + targetPath); + + const {total, pricesUsd, addresses} = data; - const { data } = await axios.get(EXTERNAL_DOMAIN + targetPath); + console.log('result info', {total}); - const { prices } = data; + const address = addresses[0]; - const key = Object.keys(prices)[0]; - console.log(`prices of ${key} is ${prices[key]} USD`); + console.log(`prices of ${address} is ${pricesUsd[0] ?? 0} USD`); } export async function getHistoricalAssetPrices() { @@ -72,16 +78,19 @@ export async function getHistoricalAssetPrices() { timestampEnd: new Date("2024-08-11T00:00:00.000+00:00"), }; - const targetPath = `/v1/${param.chainId}/assets/${param.address}/historical-prices`; - const { data: response } = await axios.get(EXTERNAL_DOMAIN + targetPath, { params: query }); - console.log('response data', {total: response.total, limit: response.limit, currency: response.currency, timestampStart: response.timestampStart, timestampEnd: response.timestampEnd}); + const targetPath = `/v4/${param.chainId}/prices/${param.address}/ohlcv`; + const { data: response } = await axios.get(CORE_DOMAIN + targetPath, { params: query }); + console.log('response data', {total: response.total, currency: response.currency, timestamp_start: response.timestamp_start, timestamp_end: response.timestamp_end }); + + const {results} = response; + + const data = parse(results, {output: 'objects'}) - const {data} = response; console.log('first data point info', { - timestamp: data.timestamps[0], - high: data.highs[0], - low: data.lows[0], - open: data.opens[0], - close: data.closes[0], + timestamp: data[0].time, + high: data[0].open, + low: data[0].low, + open: data[0].open, + close: data[0].close, }) } \ No newline at end of file diff --git a/backend-api-demo/src/get-list-assets.ts b/backend-api-demo/src/get-list-assets.ts index e6f209f..0cb169e 100644 --- a/backend-api-demo/src/get-list-assets.ts +++ b/backend-api-demo/src/get-list-assets.ts @@ -1,37 +1,60 @@ import axios from "axios"; -import { EXTERNAL_DOMAIN } from "./const"; +import { CORE_DOMAIN } from "./const"; interface Param { chainId: number; } +interface Query { + order_by?: string; + skip?: number; + limit?: number; + is_expired?: boolean; + zappable?: boolean; + type?: string; + address?: string; + q?: string; +} + interface AssetInfo { name: string; decimals: number; address: string; symbol: string; - tags: string[]; + types: string[]; expiry: string; } interface Response { - assets: AssetInfo[]; + results: AssetInfo[]; + total: number; + limit: number; + skip: number; } -export async function getAssetList() { +export async function getAssets() { // This is an example of how to get list of Pendle assets on Ethereum const param: Param = { chainId: 1, // Ethereum } - const targetPath = `/v1/${param.chainId}/assets/all`; + const query: Query = { + order_by: 'name:1', + skip: 0, + limit: 10, + is_expired: false, + } + + const targetPath = `/v1/${param.chainId}/assets`; + + const { data } = await axios.get(CORE_DOMAIN + targetPath, {params: query}); - const { data } = await axios.get(EXTERNAL_DOMAIN + targetPath); + const {total, limit, skip, results: assets} = data; - const { assets } = data; + console.log('result info', {limit, total, skip}); - const {name, address, decimals, expiry, symbol, tags} = assets[0]; + const {name, address, decimals, expiry, symbol, types} = assets[0]; - console.log('first asset', {name, address, decimals, expiry, symbol, tags}); + console.log('first asset', {name, address, decimals, expiry, symbol, types}); } \ No newline at end of file diff --git a/backend-api-demo/src/get-list-markets.ts b/backend-api-demo/src/get-list-markets.ts index 991415c..3fb8bdb 100644 --- a/backend-api-demo/src/get-list-markets.ts +++ b/backend-api-demo/src/get-list-markets.ts @@ -1,55 +1,87 @@ import axios from "axios"; -import { EXTERNAL_DOMAIN } from "./const"; +import { CORE_DOMAIN } from "./const"; interface Param { chainId: number; } +interface Query { + order_by?: string; + skip?: number; + limit?: number; + is_expired?: boolean; + select?: string; + pt?: string; + yt?: string; + sy?: string; + q?: string; + is_active?: boolean; + categoryId?: string; +} + interface MarketInfo { name: string; address: string; expiry: string; - pt: string; - yt: string; - sy: string; + pt: { + id: string; + }; + yt: { + id: string; + }; + sy: { + id: string; + }; + liquidity: { + usd: number; + acc: number; + }; + underlyingInterestApy: number; + underlyingRewardApy: number, + underlyingApy: number; + impliedApy: number; + ytFloatingApy: number; + aggregatedApy: number; + maxBoostedApy: number; + lpRewardApy: number; + voterApy: number; } interface Response { - markets: MarketInfo[]; + total: number; + limit: number; + skip: number; + results: MarketInfo[]; } -export async function getActiveMarkets() { +export async function getMarkets() { // This is an example of how to get list of active Pendle markets on Ethereum const param: Param = { chainId: 1, // Ethereum } - const targetPath = `/v1/${param.chainId}/markets/active`; - - const { data } = await axios.get(EXTERNAL_DOMAIN + targetPath); - - const { markets } = data; - - const {name, address, expiry, pt, sy, yt} = markets[0]; - - console.log('first active market', {name, address, expiry, pt, sy, yt}); -} - -export async function getInactiveMarkets() { - // This is an example of how to get list of inactive Pendle markets on Ethereum - - const param: Param = { - chainId: 1, // Ethereum + const query: Query = { + order_by: 'name:1', + skip: 0, + limit: 10, + is_expired: false, + select: 'pro', } - const targetPath = `/v1/${param.chainId}/markets/inactive`; + const targetPath = `/v1/${param.chainId}/markets`; + + const { data } = await axios.get(CORE_DOMAIN + targetPath, {params: query}); - const { data } = await axios.get(EXTERNAL_DOMAIN + targetPath); + const { results: markets, skip, limit, total } = data; - const { markets } = data; + console.log('result info', {limit, total, skip}); - const {name, address, expiry, pt, sy, yt} = markets[0]; + const {name, address, expiry, pt, sy, yt, liquidity, impliedApy, aggregatedApy, underlyingApy, lpRewardApy, underlyingInterestApy, underlyingRewardApy, maxBoostedApy, voterApy, ytFloatingApy} = markets[0]; + const {id: ptId} = pt; + const {id: syId} = sy; + const {id: ytId} = yt; + const {usd: liquidityUSD } = liquidity; - console.log('first inactive market', {name, address, expiry, pt, sy, yt}); + console.log('first active market', {name, address, expiry, ptId, syId, ytId, liquidityUSD, impliedApy, aggregatedApy, underlyingApy, lpRewardApy, underlyingInterestApy, underlyingRewardApy, maxBoostedApy, voterApy, ytFloatingApy }); } \ No newline at end of file diff --git a/backend-api-demo/src/get-market-historical-data.ts b/backend-api-demo/src/get-market-historical-data.ts index ce780e7..0ca9fbb 100644 --- a/backend-api-demo/src/get-market-historical-data.ts +++ b/backend-api-demo/src/get-market-historical-data.ts @@ -1,5 +1,6 @@ -import { EXTERNAL_DOMAIN } from "./const"; +import { CORE_DOMAIN } from "./const"; import axios from "axios"; +import { parse } from "csv-string"; interface Param { chainId: number; @@ -20,11 +21,9 @@ interface MarketHistoricalData { interface Response { total: number; - limit: number; - currency: string; - timestampStart: string; - timestampEnd: string; - data: MarketHistoricalData; + timestamp_start: string; + timestamp_end: string; + results: string; } export async function getMarketHistoricalData() { @@ -41,15 +40,19 @@ export async function getMarketHistoricalData() { timestampEnd: new Date("2024-08-11T00:00:00.000+00:00"), } - const targetPath = `/v1/${param.chainId}/markets/${param.address}/historical-data`; + const targetPath = `/v2/${param.chainId}/markets/${param.address}/apy-history`; - const { data: response } = await axios.get(EXTERNAL_DOMAIN + targetPath, {params: query}); - console.log('response data', {total: response.total, limit: response.limit, timestampStart: response.timestampStart, timestampEnd: response.timestampEnd}); + const { data: response } = await axios.get(CORE_DOMAIN + targetPath, {params: query}); + + console.log('response data', {total: response.total, timestamp_start: response.timestamp_start, timestamp_end: response.timestamp_end }); + + const {results} = response; + + const data = parse(results, {output: 'objects'}) - const {data} = response; console.log('first data point info', { - timestamp: data.timestamps[0], - underlyingApy: data.underlyingApys[0], - impliedApy: data.impliedApys[0], + timestamp: data[0].timestamp, + underlyingApy: data[0].underlyingApy, + impliedApy: data[0].impliedApy, }) } \ No newline at end of file diff --git a/backend-api-demo/src/get-swapping-prices.ts b/backend-api-demo/src/get-swapping-prices.ts deleted file mode 100644 index 91edcc9..0000000 --- a/backend-api-demo/src/get-swapping-prices.ts +++ /dev/null @@ -1,32 +0,0 @@ -import axios from "axios"; -import { EXTERNAL_DOMAIN } from "./const"; - -interface Param { - chainId: number; - address: string; -} - -interface Response { - underlyingTokenToPtRate: number; - ptToUnderlyingTokenRate: number; - underlyingTokenToYtRate: number; - ytToUnderlyingTokenRate: number; - impliedApy: number; -} - -export async function getSwappingPrices() { - // This is an example of how to get swapping prices of USD0++ market on Ethereum - - const param: Param = { - chainId: 1, // Ethereum - address: '0x00b321d89a8c36b3929f20b7955080baed706d1b', // USDO++ - } - - const targetPath = `/v1/${param.chainId}/markets/${param.address}/swapping-prices`; - - const { data } = await axios.get(EXTERNAL_DOMAIN + targetPath); - - const { underlyingTokenToPtRate, ptToUnderlyingTokenRate, underlyingTokenToYtRate, ytToUnderlyingTokenRate, impliedApy } = data; - - console.log('swapping prices', {underlyingTokenToPtRate, ptToUnderlyingTokenRate, underlyingTokenToYtRate, ytToUnderlyingTokenRate, impliedApy }); -} \ No newline at end of file diff --git a/backend-api-demo/src/index.ts b/backend-api-demo/src/index.ts index 275e675..018405c 100644 --- a/backend-api-demo/src/index.ts +++ b/backend-api-demo/src/index.ts @@ -1,15 +1,12 @@ -import { getAssetList } from "./get-list-assets"; -import { getActiveMarkets, getInactiveMarkets } from "./get-list-markets"; +import { getAssets } from "./get-list-assets"; +import { getMarkets } from "./get-list-markets"; import { getAssetPrices, getHistoricalAssetPrices } from "./get-asset-prices"; import { getMarketHistoricalData } from "./get-market-historical-data"; -import { getSwappingPrices } from "./get-swapping-prices"; async function main() { - await getAssetList(); - await getActiveMarkets(); - await getInactiveMarkets(); + await getAssets(); + await getMarkets(); await getAssetPrices(); - await getSwappingPrices(); await getHistoricalAssetPrices(); await getMarketHistoricalData(); }