Skip to content

feat: Extract useRoutes into common Squid lib #2433

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { createContext } from 'react';
import { Squid } from '@0xsquid/sdk';
import { TokenBalance } from '@0xsquid/sdk/dist/types';
import { Chain, RouteData, Token } from '../../lib/squid/types';

export interface SquidState {
squid: Squid | null;
chains: Chain[] | null;
balances: TokenBalance[] | null;
tokens: Token[] | null;
routes: RouteData[];
}

export const initialSquidState: SquidState = {
squid: null,
chains: null,
balances: null,
tokens: null,
routes: [],
};

export interface SquidContextState {
squidState: SquidState;
squidDispatch: React.Dispatch<SquidAction>;
}

export interface SquidAction {
payload: SquidActionPayload;
}

type SquidActionPayload =
| SetSquidPayload
| SetChainsPayload
| SetBalancesPayload
| SetTokensPayload
| SetRoutesPayload;

export enum SquidActions {
SET_SQUID = 'SET_SQUID',
SET_CHAINS = 'SET_CHAINS',
SET_BALANCES = 'SET_BALANCES',
SET_TOKENS = 'SET_TOKENS',
SET_ROUTES = 'SET_ROUTES',
}

export interface SetSquidPayload {
type: SquidActions.SET_SQUID;
squid: Squid;
}

export interface SetChainsPayload {
type: SquidActions.SET_CHAINS;
chains: Chain[];
}

export interface SetBalancesPayload {
type: SquidActions.SET_BALANCES;
balances: TokenBalance[];
}

export interface SetTokensPayload {
type: SquidActions.SET_TOKENS;
tokens: Token[];
}

export interface SetRoutesPayload {
type: SquidActions.SET_ROUTES;
routes: RouteData[];
}

// eslint-disable-next-line @typescript-eslint/naming-convention
export const SquidContext = createContext<SquidContextState>({
squidState: initialSquidState,
squidDispatch: () => {},
});

export type Reducer<S, A> = (prevState: S, action: A) => S;

export const squidReducer: Reducer<SquidState, SquidAction> = (
state: SquidState,
action: SquidAction,
) => {
switch (action.payload.type) {
case SquidActions.SET_SQUID:
return {
...state,
squid: action.payload.squid,
};
case SquidActions.SET_CHAINS:
return {
...state,
chains: action.payload.chains,
};
case SquidActions.SET_BALANCES:
return {
...state,
balances: action.payload.balances,
};
case SquidActions.SET_TOKENS:
return {
...state,
tokens: action.payload.tokens,
};
case SquidActions.SET_ROUTES:
return {
...state,
routes: action.payload.routes,
};
default:
return state;
}
};
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { BigNumber, utils } from 'ethers';

import { tokenValueFormat } from '../../../lib/utils';
import { DEFAULT_TOKEN_FORMATTING_DECIMALS } from '../../../lib/constants';
import { DEFAULT_TOKEN_FORMATTING_DECIMALS } from './constants';
import { tokenValueFormat } from './utils';

/**
* Formats a number to a string with a maximum number of decimals
Expand Down
3 changes: 3 additions & 0 deletions packages/checkout/widgets-lib/src/lib/squid/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const SQUID_SDK_BASE_URL = 'https://apiplus.squidrouter.com';

export const SQUID_NATIVE_TOKEN = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE';
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ChainId, type TokenInfo } from '@imtbl/checkout-sdk';
import { Token } from '../types';
import { SQUID_NATIVE_TOKEN } from '../utils/config';
import { Token } from './types';
import { SQUID_NATIVE_TOKEN } from './config';

export function convertToUsd(
tokens: Token[] | null,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Web3Provider } from '@ethersproject/providers';
import { Squid } from '@0xsquid/sdk';
import { CosmosBalance, TokenBalance } from '@0xsquid/sdk/dist/types';
import { Chain } from '../types';
import { Chain } from './types';

export const fetchBalances = async (
squid: Squid,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Squid } from '@0xsquid/sdk';
import { Chain } from '../types';
import { Chain } from '../../widgets/add-tokens/types';

type SquidChain = {
chainId: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Token } from '../types';
import { SQUID_SDK_BASE_URL } from '../utils/config';
import { Token } from './types';
import { SQUID_SDK_BASE_URL } from './config';

type SquidTokenResponse = {
chainId: number;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { RouteData } from '../types';
import { getFormattedAmounts, getFormattedNumber } from './getFormattedNumber';
import { RouteData } from './types';
import { getFormattedAmounts, getFormattedNumber } from '../getFormattedNumber';

export type RouteBalance = {
routeBalance: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { RouteResponse } from '@0xsquid/squid-types';
import { Chain } from '../types';
import { Chain } from './types';

/**
* Find a chain by its id
Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,41 @@
import { TokenBalance } from '@0xsquid/sdk/dist/types';
import { RouteResponse, ActionType } from '@0xsquid/squid-types';
import { Squid } from '@0xsquid/sdk';
import { RouteResponse, ActionType, Hook } from '@0xsquid/squid-types';
import { BigNumber, utils } from 'ethers';
import { useContext, useRef } from 'react';
import { delay } from '../functions/delay';
import { delay } from '../../delay';
import {
AmountData, RouteData, RouteResponseData, Token,
} from '../types';
import { sortRoutesByFastestTime } from '../functions/sortRoutesByFastestTime';
import { AddTokensActions, AddTokensContext } from '../context/AddTokensContext';
import { retry } from '../../../lib/retry';
import { sortRoutesByFastestTime } from '../sortRoutesByFastestTime';
import { retry } from '../../retry';
import { useAnalytics, UserJourney } from '../../../context/analytics-provider/SegmentAnalyticsProvider';
import { useProvidersContext } from '../../../context/providers-context/ProvidersContext';
import { isPassportProvider } from '../../../lib/provider';
import { isPassportProvider } from '../../provider';
import { SquidActions, SquidContext } from '../../../context/squid-provider/SquidContext';

const BASE_SLIPPAGE = 0.02;

type SquidPostHook = Omit<Hook, 'fundAmount' | 'fundToken'>;

export const useRoutes = () => {
const latestRequestIdRef = useRef<number>(0);

const { addTokensState: { id }, addTokensDispatch } = useContext(AddTokensContext);
const { squidDispatch } = useContext(SquidContext);

const {
providersState: {
toProvider,
},
} = useProvidersContext();

const { squidState: { squid } } = useContext(SquidContext);

const { track } = useAnalytics();

const setRoutes = (routes: RouteData[]) => {
addTokensDispatch({
squidDispatch({
payload: {
type: AddTokensActions.SET_ROUTES,
type: SquidActions.SET_ROUTES,
routes,
},
});
Expand Down Expand Up @@ -148,15 +151,15 @@ export const useRoutes = () => {
};

const getRouteWithRetry = async (
squid: Squid,
fromToken: Token,
toToken: Token,
toAddress: string,
fromAmount: string,
fromAddress?: string,
quoteOnly = true,
postHook?: SquidPostHook,
): Promise<RouteResponse | undefined> => await retry(
() => squid.getRoute({
() => squid?.getRoute({
fromChain: fromToken.chainId,
fromToken: fromToken.address,
fromAmount: convertToFormattedAmount(fromAmount, fromToken.decimals),
Expand All @@ -167,6 +170,7 @@ export const useRoutes = () => {
quoteOnly,
enableBoost: true,
receiveGasOnDestination: !isPassportProvider(toProvider),
postHook,
}),
{
retryIntervalMs: 1000,
Expand All @@ -189,24 +193,28 @@ export const useRoutes = () => {
};

const getRoute = async (
squid: Squid,
context: {
id: string,
userJourney: UserJourney,
},
fromToken: Token,
toToken: Token,
toAddress: string,
fromAmount: string,
toAmount: string,
fromAddress?: string,
quoteOnly = true,
postHook?: SquidPostHook,
): Promise<RouteResponseData> => {
try {
const routeResponse = await getRouteWithRetry(
squid,
fromToken,
toToken,
toAddress,
fromAmount,
fromAddress,
quoteOnly,
postHook,
);

if (!routeResponse?.route) {
Expand All @@ -223,13 +231,13 @@ export const useRoutes = () => {
);

const newRoute = await getRouteWithRetry(
squid,
fromToken,
toToken,
toAddress,
newFromAmount,
fromAddress,
quoteOnly,
postHook,
);

if (!newRoute?.route) {
Expand All @@ -241,11 +249,11 @@ export const useRoutes = () => {
}

track({
userJourney: UserJourney.ADD_TOKENS,
userJourney: context.userJourney,
screen: 'Routes',
action: 'Failed',
extras: {
contextId: id,
contextId: context.id,
fromToken: fromToken.symbol,
toToken: toToken.symbol,
fromChain: fromToken.chainId,
Expand Down Expand Up @@ -273,12 +281,15 @@ export const useRoutes = () => {
};

const getRoutes = async (
squid: Squid,
context: {
id: string,
userJourney: UserJourney,
},
amountDataArray: AmountData[],
toTokenAddress: string,
): Promise<RouteData[]> => {
const routePromises = amountDataArray.map((data) => getRoute(
squid,
context,
data.fromToken,
data.toToken,
toTokenAddress,
Expand All @@ -297,7 +308,10 @@ export const useRoutes = () => {
};

const fetchRoutesWithRateLimit = async (
squid: Squid,
context: {
id: string,
userJourney: UserJourney,
},
tokens: Token[],
balances: TokenBalance[],
toChanId: string,
Expand Down Expand Up @@ -334,7 +348,7 @@ export const useRoutes = () => {
}, [] as (typeof amountDataArray)[])
.map(async (slicedAmountDataArray) => {
allRoutes.push(
...(await getRoutes(squid, slicedAmountDataArray, toTokenAddress)),
...(await getRoutes(context, slicedAmountDataArray, toTokenAddress)),
);
await delay(delayMs);
}),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Squid } from '@0xsquid/sdk';
import { Checkout, SquidConfig } from '@imtbl/checkout-sdk';
import { useCallback, useEffect, useState } from 'react';
import { SQUID_SDK_BASE_URL } from '../utils/config';
import { SQUID_SDK_BASE_URL } from '../config';

export const useSquid = (checkout: Checkout) => {
const [squid, setSquid] = useState<Squid | null>(null);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Checkout, SquidConfig } from '@imtbl/checkout-sdk';
import { useCallback, useEffect, useState } from 'react';
import { fetchTokens } from '../functions/fetchTokens';
import { fetchTokens } from '../fetchTokens';
import { Token } from '../types';

export const useTokens = (checkout: Checkout) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import { SQUID_NATIVE_TOKEN } from '../utils/config';
import { SQUID_NATIVE_TOKEN } from './config';

export const isSquidNativeToken = (token: string) => token.toLowerCase() === SQUID_NATIVE_TOKEN.toLowerCase();
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { RouteData } from '../types';
import { RouteData } from './types';

export const sortRoutesByFastestTime = (routes: RouteData[]): RouteData[] => {
if (!routes) return [];
Expand Down
Loading