@openocean.finance/widget-sdk
Version:
OpenOcean Any-to-Any Cross-Chain-Swap SDK
437 lines • 16.4 kB
JavaScript
import { isContractCallsRequestWithFromAmount, isContractCallsRequestWithToAmount, } from '@openocean.finance/widget-types';
import { config } from '../config.js';
import { SDKError } from '../errors/SDKError.js';
import { BaseError } from '../errors/baseError.js';
import { ErrorName } from '../errors/constants.js';
import { ValidationError } from '../errors/errors.js';
import { request } from '../request.js';
import { isRoutesRequest, isStep } from '../typeguards.js';
import { withDedupe } from '../utils/withDedupe.js';
/**
* Get a quote for a token transfer
* @param params - The configuration of the requested quote
* @param options - Request options
* @throws {OpenOceanError} - Throws a OpenOceanError if request fails
* @returns Quote for a token transfer
*/
export const getQuote = async (params, options) => {
const requiredParameters = [
'fromChain',
'fromToken',
'fromAddress',
'fromAmount',
'toChain',
'toToken',
];
for (const requiredParameter of requiredParameters) {
if (!params[requiredParameter]) {
throw new SDKError(new ValidationError(`Required parameter "${requiredParameter}" is missing.`));
}
}
const _config = config.get();
// apply defaults
params.integrator ??= _config.integrator;
params.order ??= _config.routeOptions?.order;
params.slippage ??= _config.routeOptions?.slippage;
params.referrer ??= _config.routeOptions?.referrer;
params.fee ??= _config.routeOptions?.fee;
params.allowBridges ??= _config.routeOptions?.bridges?.allow;
params.denyBridges ??= _config.routeOptions?.bridges?.deny;
params.preferBridges ??= _config.routeOptions?.bridges?.prefer;
params.allowExchanges ??= _config.routeOptions?.exchanges?.allow;
params.denyExchanges ??= _config.routeOptions?.exchanges?.deny;
params.preferExchanges ??= _config.routeOptions?.exchanges?.prefer;
for (const key of Object.keys(params)) {
if (!params[key]) {
delete params[key];
}
}
return await request(`${_config.apiUrl}/quote?${new URLSearchParams(params)}`, {
signal: options?.signal,
});
};
/**
* Get a set of routes for a request that describes a transfer of tokens.
* @param params - A description of the transfer.
* @param options - Request options
* @returns The resulting routes that can be used to realize the described transfer of tokens.
* @throws {OpenOceanError} Throws a OpenOceanError if request fails.
*/
export const getRoutes = async (params, options) => {
if (!isRoutesRequest(params)) {
throw new SDKError(new ValidationError('Invalid routes request.'));
}
const _config = config.get();
// apply defaults
params.options = {
integrator: _config.integrator,
..._config.routeOptions,
...params.options,
};
return await request(`${_config.apiUrl}/advanced/routes`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(params),
signal: options?.signal,
});
};
/**
* Get a quote for a destination contract call
* @param params - The configuration of the requested destination call
* @param options - Request options
* @throws {OpenOceanError} - Throws a OpenOceanError if request fails
* @returns - Returns step.
*/
export const getContractCallsQuote = async (params, options) => {
// validation
const requiredParameters = [
'fromChain',
'fromToken',
'fromAddress',
'toChain',
'toToken',
'contractCalls',
];
for (const requiredParameter of requiredParameters) {
if (!params[requiredParameter]) {
throw new SDKError(new ValidationError(`Required parameter "${requiredParameter}" is missing.`));
}
}
if (!isContractCallsRequestWithFromAmount(params) &&
!isContractCallsRequestWithToAmount(params)) {
throw new SDKError(new ValidationError(`Required parameter "fromAmount" or "toAmount" is missing.`));
}
const _config = config.get();
// apply defaults
// option.order is not used in this endpoint
params.integrator ??= _config.integrator;
params.slippage ??= _config.routeOptions?.slippage;
params.referrer ??= _config.routeOptions?.referrer;
params.fee ??= _config.routeOptions?.fee;
params.allowBridges ??= _config.routeOptions?.bridges?.allow;
params.denyBridges ??= _config.routeOptions?.bridges?.deny;
params.preferBridges ??= _config.routeOptions?.bridges?.prefer;
params.allowExchanges ??= _config.routeOptions?.exchanges?.allow;
params.denyExchanges ??= _config.routeOptions?.exchanges?.deny;
params.preferExchanges ??= _config.routeOptions?.exchanges?.prefer;
// send request
return await request(`${_config.apiUrl}/quote/contractCalls`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(params),
signal: options?.signal,
});
};
/**
* Get the transaction data for a single step of a route
* @param step - The step object.
* @param options - Request options
* @returns The step populated with the transaction data.
* @throws {OpenOceanError} Throws a OpenOceanError if request fails.
*/
export const getStepTransaction = async (step, options) => {
if (!isStep(step)) {
// While the validation fails for some users we should not enforce it
console.warn('SDK Validation: Invalid Step', step);
}
return await request(`${config.get().apiUrl}/advanced/stepTransaction`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(step),
signal: options?.signal,
});
};
/**
* Check the status of a transfer. For cross chain transfers, the "bridge" parameter is required.
* @param params - Configuration of the requested status
* @param options - Request options.
* @throws {OpenOceanError} - Throws a OpenOceanError if request fails
* @returns Returns status response.
*/
export const getStatus = async (params, options) => {
if (!params.txHash) {
throw new SDKError(new ValidationError('Required parameter "txHash" is missing.'));
}
const queryParams = new URLSearchParams(params);
return await request(`${config.get().apiUrl}/status?${queryParams}`, {
signal: options?.signal,
});
};
/**
* Get a relayer quote for a token transfer
* @param params - The configuration of the requested quote
* @param options - Request options
* @throws {OpenOceanError} - Throws a OpenOceanError if request fails
* @returns Relayer quote for a token transfer
*/
export const getRelayerQuote = async (params, options) => {
const requiredParameters = [
'fromChain',
'fromToken',
'fromAddress',
'fromAmount',
'toChain',
'toToken',
];
for (const requiredParameter of requiredParameters) {
if (!params[requiredParameter]) {
throw new SDKError(new ValidationError(`Required parameter "${requiredParameter}" is missing.`));
}
}
const _config = config.get();
// apply defaults
params.integrator ??= _config.integrator;
params.order ??= _config.routeOptions?.order;
params.slippage ??= _config.routeOptions?.slippage;
params.referrer ??= _config.routeOptions?.referrer;
params.fee ??= _config.routeOptions?.fee;
params.allowBridges ??= _config.routeOptions?.bridges?.allow;
params.denyBridges ??= _config.routeOptions?.bridges?.deny;
params.preferBridges ??= _config.routeOptions?.bridges?.prefer;
params.allowExchanges ??= _config.routeOptions?.exchanges?.allow;
params.denyExchanges ??= _config.routeOptions?.exchanges?.deny;
params.preferExchanges ??= _config.routeOptions?.exchanges?.prefer;
for (const key of Object.keys(params)) {
if (!params[key]) {
delete params[key];
}
}
const result = await request(`${config.get().apiUrl}/relayer/quote?${new URLSearchParams(params)}`, {
signal: options?.signal,
});
if (result.status === 'error') {
throw new BaseError(ErrorName.ServerError, result.data.code, result.data.message);
}
return result.data;
};
/**
* Relay a transaction through the relayer service
* @param params - The configuration for the relay request
* @param options - Request options
* @throws {OpenOceanError} - Throws a OpenOceanError if request fails
* @returns Task ID for the relayed transaction
*/
export const relayTransaction = async (params, options) => {
const requiredParameters = [
'typedData',
'transactionRequest',
];
for (const requiredParameter of requiredParameters) {
if (!params[requiredParameter]) {
throw new SDKError(new ValidationError(`Required parameter "${requiredParameter}" is missing.`));
}
}
const result = await request(`${config.get().apiUrl}/relayer/relay`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(params, (_, value) => {
if (typeof value === 'bigint') {
return value.toString();
}
return value;
}),
signal: options?.signal,
});
if (result.status === 'error') {
throw new BaseError(ErrorName.ServerError, result.data.code, result.data.message);
}
return result.data;
};
/**
* Get the status of a relayed transaction
* @param params - Parameters for the relay status request
* @param options - Request options
* @throws {OpenOceanError} - Throws a OpenOceanError if request fails
* @returns Status of the relayed transaction
*/
export const getRelayedTransactionStatus = async (params, options) => {
if (!params.taskId) {
throw new SDKError(new ValidationError('Required parameter "taskId" is missing.'));
}
const { taskId, ...otherParams } = params;
const queryParams = new URLSearchParams(otherParams);
const result = await request(`${config.get().apiUrl}/relayer/status/${taskId}?${queryParams}`, {
signal: options?.signal,
});
if (result.status === 'error') {
throw new BaseError(ErrorName.ServerError, result.data.code, result.data.message);
}
return result.data;
};
/**
* Get all available chains
* @returns A list of all available chains
* @throws {OpenOceanError} Throws a OpenOceanError if request fails.
*/
export const getChains = async () => {
const response = await withDedupe(() => request(`https://openapi-test.openocean.finance/v3/widgetv2/chains`), { id: `${getChains.name}` });
return convertChainData(response.data);
};
function convertChainData(data) {
return data.map(chain => ({
key: chain.code,
chainType: 'EVM',
name: chain.name,
coin: chain.symbol,
id: Number(chain.chainId),
mainnet: true,
logoURI: chain.icon,
tokenlistUrl: chain.tokenlistUrl,
multicallAddress: chain.multicallAddress,
relayerSupported: false,
metamask: chain.metamask,
nativeToken: chain.nativeToken,
diamondAddress: chain.exchangeAddress,
permit2: chain.permit2,
permit2Proxy: chain.permit2Proxy,
}));
}
/**
* Get all known tokens.
* @param params - The configuration of the requested tokens
* @param options - Request options
* @returns The tokens that are available on the requested chains
*/
export const getTokens = async (params, options) => {
if (params) {
for (const key of Object.keys(params)) {
if (!params[key]) {
delete params[key];
}
}
}
const urlSearchParams = new URLSearchParams(params).toString();
const response = await withDedupe(() => request(`${config.get().apiUrl}/tokens?${urlSearchParams}`, {
signal: options?.signal,
}), { id: `${getTokens.name}.${urlSearchParams}` });
return response;
};
/**
* Fetch information about a Token
* @param chain - Id or key of the chain that contains the token
* @param token - Address or symbol of the token on the requested chain
* @param options - Request options
* @throws {OpenOceanError} - Throws a OpenOceanError if request fails
* @returns Token information
*/
export const getToken = async (chain, token, options) => {
if (!chain) {
throw new SDKError(new ValidationError('Required parameter "chain" is missing.'));
}
if (!token) {
throw new SDKError(new ValidationError('Required parameter "token" is missing.'));
}
return await request(`${config.get().apiUrl}/token?${new URLSearchParams({
chain,
token,
})}`, {
signal: options?.signal,
});
};
/**
* Get the available tools to bridge and swap tokens.
* @param params - The configuration of the requested tools
* @param options - Request options
* @returns The tools that are available on the requested chains
*/
export const getTools = async (params, options) => {
if (params) {
for (const key of Object.keys(params)) {
if (!params[key]) {
delete params[key];
}
}
}
return await request(`${config.get().apiUrl}/tools?${new URLSearchParams(params)}`, {
signal: options?.signal,
});
};
/**
* Get gas recommendation for a certain chain
* @param params - Configuration of the requested gas recommendation.
* @param options - Request options
* @throws {OpenOceanError} Throws a OpenOceanError if request fails.
* @returns Gas recommendation response.
*/
export const getGasRecommendation = async (params, options) => {
if (!params.chainId) {
throw new SDKError(new ValidationError('Required parameter "chainId" is missing.'));
}
const url = new URL(`${config.get().apiUrl}/gas/suggestion/${params.chainId}`);
if (params.fromChain) {
url.searchParams.append('fromChain', params.fromChain);
}
if (params.fromToken) {
url.searchParams.append('fromToken', params.fromToken);
}
return await request(url.toString(), {
signal: options?.signal,
});
};
/**
* Get all the available connections for swap/bridging tokens
* @param connectionRequest ConnectionsRequest
* @param options - Request options
* @returns ConnectionsResponse
*/
export const getConnections = async (connectionRequest, options) => {
const url = new URL(`${config.get().apiUrl}/connections`);
const { fromChain, fromToken, toChain, toToken } = connectionRequest;
if (fromChain) {
url.searchParams.append('fromChain', fromChain);
}
if (fromToken) {
url.searchParams.append('fromToken', fromToken);
}
if (toChain) {
url.searchParams.append('toChain', toChain);
}
if (toToken) {
url.searchParams.append('toToken', toToken);
}
const connectionRequestArrayParams = [
'allowBridges',
'denyBridges',
'preferBridges',
'allowExchanges',
'denyExchanges',
'preferExchanges',
];
for (const parameter of connectionRequestArrayParams) {
const connectionRequestArrayParam = connectionRequest[parameter];
if (connectionRequestArrayParam?.length) {
for (const value of connectionRequestArrayParam) {
url.searchParams.append(parameter, value);
}
}
}
return await request(url, options);
};
export const getTransactionHistory = async ({ wallet, status, fromTimestamp, toTimestamp }, options) => {
if (!wallet) {
throw new SDKError(new ValidationError('Required parameter "wallet" is missing.'));
}
const _config = config.get();
const url = new URL(`${_config.apiUrl}/analytics/transfers`);
url.searchParams.append('integrator', _config.integrator);
url.searchParams.append('wallet', wallet);
if (status) {
url.searchParams.append('status', status);
}
if (fromTimestamp) {
url.searchParams.append('fromTimestamp', fromTimestamp.toString());
}
if (toTimestamp) {
url.searchParams.append('toTimestamp', toTimestamp.toString());
}
return await request(url, options);
};
//# sourceMappingURL=api.js.map