diff --git a/src/config.ts b/src/config.ts index 9c322fc1..f9ef0703 100644 --- a/src/config.ts +++ b/src/config.ts @@ -5,7 +5,7 @@ import type { RPCUrls, SDKBaseConfig, SDKConfig } from './types/internal.js' export const config = (() => { const _config: SDKBaseConfig = { integrator: 'lifi-sdk', - apiUrl: 'https://li.quest/v1', + apiUrl: 'https://li.quest', rpcUrls: {}, chains: [], providers: [], @@ -20,6 +20,10 @@ export const config = (() => { get() { return _config }, + getApiUrl(version: 'v1' | 'v2' = 'v1'): string { + const baseUrl = new URL(_config.apiUrl).origin + return `${baseUrl}/${version}` + }, set(options: SDKConfig) { const { chains, providers, rpcUrls, ...otherOptions } = options Object.assign(_config, otherOptions) diff --git a/src/core/execution.unit.handlers.ts b/src/core/execution.unit.handlers.ts index 1431cde3..e1b28234 100644 --- a/src/core/execution.unit.handlers.ts +++ b/src/core/execution.unit.handlers.ts @@ -7,10 +7,10 @@ import { mockStepTransactionWithTxRequest, } from './execution.unit.mock.js' -const _config = config.get() +const apiUrl = config.getApiUrl() export const lifiHandlers = [ - http.post(`${_config.apiUrl}/advanced/stepTransaction`, async () => + http.post(`${apiUrl}/advanced/stepTransaction`, async () => HttpResponse.json( mockStepTransactionWithTxRequest( buildStepObject({ @@ -19,12 +19,10 @@ export const lifiHandlers = [ ) ) ), - http.get(`${_config.apiUrl}/chains`, async () => + http.get(`${apiUrl}/chains`, async () => HttpResponse.json({ chains: mockChainsResponse, }) ), - http.get(`${_config.apiUrl}/status`, async () => - HttpResponse.json(mockStatus) - ), + http.get(`${apiUrl}/status`, async () => HttpResponse.json(mockStatus)), ] diff --git a/src/request.unit.spec.ts b/src/request.unit.spec.ts index 67618c7b..e6f9d5c1 100644 --- a/src/request.unit.spec.ts +++ b/src/request.unit.spec.ts @@ -21,7 +21,7 @@ import type { SDKBaseConfig } from './types/internal.js' import type { ExtendedRequestInit } from './types/request.js' import { version } from './version.js' -const apiUrl = config.get().apiUrl +const apiUrl = config.getApiUrl() describe('request new', () => { const server = setupServer(...handlers) diff --git a/src/services/api.ts b/src/services/api.ts index 4a4ae98f..605525ca 100644 --- a/src/services/api.ts +++ b/src/services/api.ts @@ -12,6 +12,8 @@ import { isContractCallsRequestWithFromAmount, isContractCallsRequestWithToAmount, type LiFiStep, + type PaginatedResponse, + type PaginationQuery, type RelayerQuoteResponse, type RelayRequest, type RelayResponse, @@ -31,7 +33,6 @@ import { type ToolsRequest, type ToolsResponse, type TransactionAnalyticsRequest, - type TransactionAnalyticsResponse, } from '@lifi/types' import { config } from '../config.js' import { BaseError } from '../errors/baseError.js' @@ -126,7 +127,7 @@ export async function getQuote( } return await request( - `${_config.apiUrl}/${isFromAmountRequest ? 'quote' : 'quote/toAmount'}?${new URLSearchParams( + `${config.getApiUrl()}/${isFromAmountRequest ? 'quote' : 'quote/toAmount'}?${new URLSearchParams( params as unknown as Record )}`, { @@ -157,14 +158,17 @@ export const getRoutes = async ( ...params.options, } - return await request(`${_config.apiUrl}/advanced/routes`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(params), - signal: options?.signal, - }) + return await request( + `${config.getApiUrl()}/advanced/routes`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(params), + signal: options?.signal, + } + ) } /** @@ -220,7 +224,7 @@ export const getContractCallsQuote = async ( params.denyExchanges ??= _config.routeOptions?.exchanges?.deny params.preferExchanges ??= _config.routeOptions?.exchanges?.prefer // send request - return await request(`${_config.apiUrl}/quote/contractCalls`, { + return await request(`${config.getApiUrl()}/quote/contractCalls`, { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -247,7 +251,7 @@ export const getStepTransaction = async ( } return await request( - `${config.get().apiUrl}/advanced/stepTransaction`, + `${config.getApiUrl()}/advanced/stepTransaction`, { method: 'POST', headers: { @@ -279,7 +283,7 @@ export const getStatus = async ( params as unknown as Record ) return await request( - `${config.get().apiUrl}/status?${queryParams}`, + `${config.getApiUrl()}/status?${queryParams}`, { signal: options?.signal, } @@ -335,7 +339,7 @@ export const getRelayerQuote = async ( } const result = await request( - `${config.get().apiUrl}/relayer/quote?${new URLSearchParams( + `${config.getApiUrl()}/relayer/quote?${new URLSearchParams( params as unknown as Record )}`, { @@ -386,7 +390,7 @@ export const relayTransaction = async ( : '/advanced/relay' const result = await request( - `${config.get().apiUrl}${relayerPath}`, + `${config.getApiUrl()}${relayerPath}`, { method: 'POST', headers: { @@ -435,7 +439,7 @@ export const getRelayedTransactionStatus = async ( otherParams as unknown as Record ) const result = await request( - `${config.get().apiUrl}/relayer/status/${taskId}?${queryParams}`, + `${config.getApiUrl()}/relayer/status/${taskId}?${queryParams}`, { signal: options?.signal, } @@ -476,7 +480,7 @@ export const getChains = async ( const response = await withDedupe( () => request( - `${config.get().apiUrl}/chains?${urlSearchParams}`, + `${config.getApiUrl()}/chains?${urlSearchParams}`, { signal: options?.signal, } @@ -519,7 +523,7 @@ export async function getTokens( () => request< typeof isExtended extends true ? TokensExtendedResponse : TokensResponse - >(`${config.get().apiUrl}/tokens?${urlSearchParams}`, { + >(`${config.getApiUrl()}/tokens?${urlSearchParams}`, { signal: options?.signal, }), { id: `${getTokens.name}.${urlSearchParams}` } @@ -551,7 +555,7 @@ export const getToken = async ( ) } return await request( - `${config.get().apiUrl}/token?${new URLSearchParams({ + `${config.getApiUrl()}/token?${new URLSearchParams({ chain, token, } as Record)}`, @@ -579,7 +583,7 @@ export const getTools = async ( } } return await request( - `${config.get().apiUrl}/tools?${new URLSearchParams( + `${config.getApiUrl()}/tools?${new URLSearchParams( params as Record )}`, { @@ -605,7 +609,7 @@ export const getGasRecommendation = async ( ) } - const url = new URL(`${config.get().apiUrl}/gas/suggestion/${params.chainId}`) + const url = new URL(`${config.getApiUrl()}/gas/suggestion/${params.chainId}`) if (params.fromChain) { url.searchParams.append('fromChain', params.fromChain as unknown as string) } @@ -628,7 +632,7 @@ export const getConnections = async ( connectionRequest: ConnectionsRequest, options?: RequestOptions ): Promise => { - const url = new URL(`${config.get().apiUrl}/connections`) + const url = new URL(`${config.getApiUrl()}/connections`) const { fromChain, fromToken, toChain, toToken } = connectionRequest @@ -665,21 +669,26 @@ export const getConnections = async ( } export const getTransactionHistory = async ( - { wallet, status, fromTimestamp, toTimestamp }: TransactionAnalyticsRequest, + { + wallet, + status, + fromTimestamp, + toTimestamp, + limit = 10, + next, + previous, + }: TransactionAnalyticsRequest & PaginationQuery, options?: RequestOptions -): Promise => { - if (!wallet) { - throw new SDKError( - new ValidationError('Required parameter "wallet" is missing.') - ) - } - +): Promise> => { const _config = config.get() - const url = new URL(`${_config.apiUrl}/analytics/transfers`) - + const url = new URL(`${config.getApiUrl('v2')}/analytics/transfers`) url.searchParams.append('integrator', _config.integrator) - url.searchParams.append('wallet', wallet) + url.searchParams.append('limit', limit.toString()) + + if (wallet) { + url.searchParams.append('wallet', wallet) + } if (status) { url.searchParams.append('status', status) @@ -693,5 +702,13 @@ export const getTransactionHistory = async ( url.searchParams.append('toTimestamp', toTimestamp.toString()) } - return await request(url, options) + if (next) { + url.searchParams.append('next', next.toString()) + } + + if (previous) { + url.searchParams.append('previous', previous.toString()) + } + + return await request>(url, options) } diff --git a/src/services/api.unit.handlers.ts b/src/services/api.unit.handlers.ts index 6149b608..1fb32bfe 100644 --- a/src/services/api.unit.handlers.ts +++ b/src/services/api.unit.handlers.ts @@ -3,35 +3,35 @@ import { ChainId, CoinKey } from '@lifi/types' import { HttpResponse, http } from 'msw' import { config } from '../config.js' -const _config = config.get() +const apiUrl = config.getApiUrl() export const handlers = [ - http.post(`${_config.apiUrl}/advanced/routes`, async () => { + http.post(`${apiUrl}/advanced/routes`, async () => { return HttpResponse.json({}) }), - http.post(`${_config.apiUrl}/advanced/possibilities`, async () => + http.post(`${apiUrl}/advanced/possibilities`, async () => HttpResponse.json({}) ), - http.get(`${_config.apiUrl}/token`, async () => HttpResponse.json({})), - http.get(`${_config.apiUrl}/quote`, async () => HttpResponse.json({})), - http.get(`${_config.apiUrl}/status`, async () => HttpResponse.json({})), - http.get(`${_config.apiUrl}/chains`, async () => + http.get(`${apiUrl}/token`, async () => HttpResponse.json({})), + http.get(`${apiUrl}/quote`, async () => HttpResponse.json({})), + http.get(`${apiUrl}/status`, async () => HttpResponse.json({})), + http.get(`${apiUrl}/chains`, async () => HttpResponse.json({ chains: [{ id: 1 }] }) ), - http.get(`${_config.apiUrl}/tools`, async () => + http.get(`${apiUrl}/tools`, async () => HttpResponse.json({ bridges: [], exchanges: [] }) ), - http.get(`${_config.apiUrl}/tokens`, async () => + http.get(`${apiUrl}/tokens`, async () => HttpResponse.json({ tokens: { [ChainId.ETH]: [findDefaultToken(CoinKey.ETH, ChainId.ETH)], }, }) ), - http.post(`${_config.apiUrl}/advanced/stepTransaction`, async () => + http.post(`${apiUrl}/advanced/stepTransaction`, async () => HttpResponse.json({}) ), - http.get(`${_config.apiUrl}/gas/suggestion/${ChainId.OPT}`, async () => + http.get(`${apiUrl}/gas/suggestion/${ChainId.OPT}`, async () => HttpResponse.json({}) ), ] diff --git a/src/services/api.unit.spec.ts b/src/services/api.unit.spec.ts index 109368b5..13a77be7 100644 --- a/src/services/api.unit.spec.ts +++ b/src/services/api.unit.spec.ts @@ -34,7 +34,6 @@ import { handlers } from './api.unit.handlers.js' const mockedFetch = vi.spyOn(request, 'request') describe('ApiService', () => { - const _config = config.get() const server = setupServer(...handlers) beforeAll(() => { setupTestEnvironment() @@ -561,7 +560,7 @@ describe('ApiService', () => { describe('getAvailableConnections', () => { it('returns empty array in response', async () => { server.use( - http.get(`${_config.apiUrl}/connections`, async () => + http.get(`${config.getApiUrl()}/connections`, async () => HttpResponse.json({ connections: [] }) ) ) @@ -595,7 +594,7 @@ describe('ApiService', () => { describe('getTransactionHistory', () => { it('returns empty array in response', async () => { server.use( - http.get(`${_config.apiUrl}/analytics/transfers`, async () => + http.get(`${config.getApiUrl('v2')}/analytics/transfers`, async () => HttpResponse.json({}) ) ) @@ -607,7 +606,7 @@ describe('ApiService', () => { } const generatedURL = - 'https://li.quest/v1/analytics/transfers?integrator=lifi-sdk&wallet=0x5520abcd&fromTimestamp=1696326609361&toTimestamp=1696326609362' + 'https://li.quest/v2/analytics/transfers?integrator=lifi-sdk&limit=10&wallet=0x5520abcd&fromTimestamp=1696326609361&toTimestamp=1696326609362' await expect( ApiService.getTransactionHistory(walletAnalyticsRequest)