Skip to content

Commit c9efda3

Browse files
add useFundSwapTokens utility
1 parent 766712c commit c9efda3

File tree

4 files changed

+225
-0
lines changed

4 files changed

+225
-0
lines changed

src/swap/constants.ts

+23
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import type { Token } from '../token';
2+
import { base } from 'viem/chains';
3+
14
export const FALLBACK_DEFAULT_MAX_SLIPPAGE = 3;
25
export const GENERAL_SWAP_ERROR_CODE = 'SWAP_ERROR';
36
export const GENERAL_SWAP_QUOTE_ERROR_CODE = 'SWAP_QUOTE_ERROR';
@@ -23,3 +26,23 @@ export enum SwapMessage {
2326
TOO_MANY_REQUESTS = 'Too many requests. Please try again later.',
2427
USER_REJECTED = 'User rejected the transaction',
2528
}
29+
30+
export const ethToken: Token = {
31+
name: 'ETH',
32+
address: '',
33+
symbol: 'ETH',
34+
decimals: 18,
35+
image:
36+
'https://wallet-api-production.s3.amazonaws.com/uploads/tokens/eth_288.png',
37+
chainId: base.id,
38+
};
39+
40+
export const usdcToken: Token = {
41+
name: 'USDC',
42+
address: '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913',
43+
symbol: 'USDC',
44+
decimals: 6,
45+
image:
46+
'https://d3r81g40ycuhqg.cloudfront.net/wallet/wais/44/2b/442b80bd16af0c0d9b22e03a16753823fe826e5bfd457292b55fa0ba8c1ba213-ZWUzYjJmZGUtMDYxNy00NDcyLTg0NjQtMWI4OGEwYjBiODE2',
47+
chainId: base.id,
48+
};
+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import { act, renderHook } from '@testing-library/react';
2+
import { base } from 'viem/chains';
3+
import { type Mock, beforeEach, describe, expect, it, vi } from 'vitest';
4+
import { useValue } from '../../internal/hooks/useValue';
5+
import type { Token } from '../../token';
6+
import { USDC_TOKEN } from '../mocks';
7+
import { useFundSwapTokens } from './useFundSwapTokens';
8+
import { useSwapBalances } from './useSwapBalances';
9+
10+
vi.mock('./useSwapBalances', () => ({
11+
useSwapBalances: vi.fn(),
12+
}));
13+
14+
vi.mock('../../internal/hooks/useValue', () => ({
15+
useValue: vi.fn(),
16+
}));
17+
18+
const toToken: Token = {
19+
name: 'DEGEN',
20+
address: '0x4ed4e862860bed51a9570b96d89af5e1b0efefed',
21+
symbol: 'DEGEN',
22+
decimals: 18,
23+
image:
24+
'https://d3r81g40ycuhqg.cloudfront.net/wallet/wais/3b/bf/3bbf118b5e6dc2f9e7fc607a6e7526647b4ba8f0bea87125f971446d57b296d2-MDNmNjY0MmEtNGFiZi00N2I0LWIwMTItMDUyMzg2ZDZhMWNm',
25+
chainId: base.id,
26+
};
27+
28+
describe('useFundSwapTokens', () => {
29+
beforeEach(() => {
30+
vi.clearAllMocks();
31+
});
32+
33+
it('should return correct values', () => {
34+
(useSwapBalances as Mock).mockReturnValue({
35+
fromBalanceString: '100',
36+
fromTokenBalanceError: null,
37+
fromTokenResponse: { refetch: vi.fn() },
38+
toBalanceString: '200',
39+
toTokenBalanceError: null,
40+
toTokenResponse: { refetch: vi.fn() },
41+
});
42+
(useValue as Mock).mockImplementation((props) => ({
43+
...props,
44+
amount: '100',
45+
amountUSD: '150',
46+
response: props.response,
47+
setAmount: vi.fn(),
48+
setAmountUSD: vi.fn(),
49+
setLoading: vi.fn(),
50+
token: USDC_TOKEN,
51+
}));
52+
const { result } = renderHook(() => useFundSwapTokens(toToken, '0x123'));
53+
expect(result.current.fromETH).toEqual({
54+
amount: '100',
55+
amountUSD: '150',
56+
balance: '100',
57+
balanceResponse: { refetch: expect.any(Function) },
58+
error: null,
59+
loading: false,
60+
setAmount: expect.any(Function),
61+
setAmountUSD: expect.any(Function),
62+
setLoading: expect.any(Function),
63+
token: USDC_TOKEN,
64+
});
65+
expect(result.current.to).toEqual({
66+
amount: '100',
67+
amountUSD: '150',
68+
balance: '200',
69+
balanceResponse: { refetch: expect.any(Function) },
70+
error: null,
71+
loading: false,
72+
setAmount: expect.any(Function),
73+
setAmountUSD: expect.any(Function),
74+
setLoading: expect.any(Function),
75+
token: USDC_TOKEN,
76+
});
77+
});
78+
79+
it('should call fromTokenResponse.refetch when fromETH.response.refetch is called', async () => {
80+
const mockFromRefetch = vi.fn().mockResolvedValue(undefined);
81+
const mockToRefetch = vi.fn().mockResolvedValue(undefined);
82+
(useSwapBalances as Mock).mockReturnValue({
83+
fromTokenResponse: { refetch: mockFromRefetch },
84+
toTokenResponse: { refetch: mockToRefetch },
85+
});
86+
(useValue as Mock).mockImplementation((props) => ({
87+
...props,
88+
response: props.response,
89+
}));
90+
const { result } = renderHook(() => useFundSwapTokens(toToken, '0x123'));
91+
await act(async () => {
92+
await result.current.fromETH.balanceResponse?.refetch();
93+
});
94+
expect(mockFromRefetch).toHaveBeenCalledTimes(1);
95+
expect(mockToRefetch).not.toHaveBeenCalled();
96+
});
97+
98+
it('should call toTokenResponse.refetch when to.response.refetch is called', async () => {
99+
const mockFromRefetch = vi.fn().mockResolvedValue(undefined);
100+
const mockToRefetch = vi.fn().mockResolvedValue(undefined);
101+
(useSwapBalances as Mock).mockReturnValue({
102+
fromTokenResponse: { refetch: mockFromRefetch },
103+
toTokenResponse: { refetch: mockToRefetch },
104+
});
105+
(useValue as Mock).mockImplementation((props) => ({
106+
...props,
107+
response: props.response,
108+
}));
109+
const { result } = renderHook(() => useFundSwapTokens(toToken, '0x123'));
110+
await act(async () => {
111+
await result.current.to.balanceResponse?.refetch();
112+
});
113+
expect(mockToRefetch).toHaveBeenCalledTimes(1);
114+
expect(mockFromRefetch).not.toHaveBeenCalled();
115+
});
116+
});

src/swap/hooks/useFundSwapTokens.ts

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { useState } from 'react';
2+
import type { Address } from 'viem';
3+
import { ethToken, usdcToken } from '../constants';
4+
import { useValue } from '../../internal/hooks/useValue';
5+
import type { Token } from '../../token';
6+
import type { FundSwapTokens } from '../types';
7+
import { useSwapBalances } from './useSwapBalances';
8+
9+
export const useFundSwapTokens = (
10+
toToken: Token,
11+
address?: Address,
12+
): FundSwapTokens => {
13+
const [toAmount, setToAmount] = useState('');
14+
const [toAmountUSD, setToAmountUSD] = useState('');
15+
const [toLoading, setToLoading] = useState(false);
16+
const [fromETHAmount, setFromETHAmount] = useState('');
17+
const [fromETHAmountUSD, setFromETHAmountUSD] = useState('');
18+
const [fromETHLoading, setFromETHLoading] = useState(false);
19+
const [fromUSDCAmount, setFromUSDCAmount] = useState('');
20+
const [fromUSDCAmountUSD, setFromUSDCAmountUSD] = useState('');
21+
const [fromUSDCLoading, setFromUSDCLoading] = useState(false);
22+
23+
const {
24+
fromBalanceString: fromETHBalanceString,
25+
fromTokenBalanceError: fromEthBalanceError,
26+
toBalanceString,
27+
toTokenBalanceError,
28+
fromTokenResponse: fromETHResponse,
29+
toTokenResponse,
30+
} = useSwapBalances({ address, fromToken: ethToken, toToken });
31+
32+
const {
33+
fromBalanceString: fromUSDCBalanceString,
34+
fromTokenBalanceError: fromUSDCBalanceError,
35+
fromTokenResponse: fromUSDCResponse,
36+
} = useSwapBalances({ address, fromToken: usdcToken, toToken });
37+
38+
const fromETH = useValue({
39+
balance: fromETHBalanceString,
40+
balanceResponse: fromETHResponse,
41+
amount: fromETHAmount,
42+
setAmount: setFromETHAmount,
43+
amountUSD: fromETHAmountUSD,
44+
setAmountUSD: setFromETHAmountUSD,
45+
token: ethToken,
46+
loading: fromETHLoading,
47+
setLoading: setFromETHLoading,
48+
error: fromEthBalanceError,
49+
});
50+
51+
const fromUSDC = useValue({
52+
balance: fromUSDCBalanceString,
53+
balanceResponse: fromUSDCResponse,
54+
amount: fromUSDCAmount,
55+
setAmount: setFromUSDCAmount,
56+
amountUSD: fromUSDCAmountUSD,
57+
setAmountUSD: setFromUSDCAmountUSD,
58+
token: usdcToken,
59+
loading: fromUSDCLoading,
60+
setLoading: setFromUSDCLoading,
61+
error: fromUSDCBalanceError,
62+
});
63+
64+
const to = useValue({
65+
balance: toBalanceString,
66+
balanceResponse: toTokenResponse,
67+
amount: toAmount,
68+
amountUSD: toAmountUSD,
69+
setAmountUSD: setToAmountUSD,
70+
setAmount: setToAmount,
71+
token: toToken,
72+
loading: toLoading,
73+
setLoading: setToLoading,
74+
error: toTokenBalanceError,
75+
});
76+
77+
return { fromETH, fromUSDC, to };
78+
};

src/swap/types.ts

+8
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,14 @@ export type FromTo = {
5151
to: SwapUnit;
5252
};
5353

54+
export type FundSwapTokens = {
55+
fromETH: FundSwapUnit;
56+
fromUSDC: FundSwapUnit;
57+
to: FundSwapUnit;
58+
};
59+
60+
export type FundSwapUnit = Omit<SwapUnit, 'setToken'>;
61+
5462
export type GetSwapMessageParams = {
5563
address?: Address;
5664
lifecycleStatus: LifecycleStatus;

0 commit comments

Comments
 (0)