-
Notifications
You must be signed in to change notification settings - Fork 230
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6680c4c
commit bb80419
Showing
85 changed files
with
7,641 additions
and
5,021 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 9 additions & 0 deletions
9
playground/nextjs-app-router/components/demo/WalletAdvancedDefault.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { WalletAdvancedDefault } from '@coinbase/onchainkit/wallet'; | ||
|
||
export default function WalletAdvancedDefaultDemo() { | ||
return ( | ||
<div className="mx-auto flex justify-end"> | ||
<WalletAdvancedDefault /> | ||
</div> | ||
); | ||
} |
5 changes: 5 additions & 0 deletions
5
playground/nextjs-app-router/components/demo/WalletIsland.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { WalletIsland } from '@coinbase/onchainkit/wallet'; | ||
|
||
export default function WalletIslandDemo() { | ||
return <WalletIsland />; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
126 changes: 126 additions & 0 deletions
126
src/core-react/wallet/hooks/usePortfolioTokenBalances.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
import { getPortfolioTokenBalances } from '@/core/api/getPortfolioTokenBalances'; | ||
import type { | ||
PortfolioTokenBalances, | ||
PortfolioTokenWithFiatValue, | ||
} from '@/core/api/types'; | ||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; | ||
import { renderHook, waitFor } from '@testing-library/react'; | ||
import { beforeEach, describe, expect, it, vi } from 'vitest'; | ||
import { usePortfolioTokenBalances } from './usePortfolioTokenBalances'; | ||
|
||
vi.mock('@/core/api/getPortfolioTokenBalances'); | ||
|
||
const mockAddress: `0x${string}` = '0x123'; | ||
const mockTokens: PortfolioTokenWithFiatValue[] = [ | ||
{ | ||
address: '0x123', | ||
chainId: 8453, | ||
decimals: 6, | ||
image: '', | ||
name: 'Token', | ||
symbol: 'TOKEN', | ||
cryptoBalance: 100, | ||
fiatBalance: 100, | ||
}, | ||
]; | ||
const mockPortfolioTokenBalances: PortfolioTokenBalances = { | ||
address: mockAddress, | ||
portfolioBalanceInUsd: 100, | ||
tokenBalances: mockTokens, | ||
}; | ||
|
||
const createWrapper = () => { | ||
const queryClient = new QueryClient({ | ||
defaultOptions: { | ||
queries: { | ||
retry: false, | ||
}, | ||
}, | ||
}); | ||
return ({ children }: { children: React.ReactNode }) => ( | ||
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider> | ||
); | ||
}; | ||
|
||
describe('usePortfolioTokenBalances', () => { | ||
beforeEach(() => { | ||
vi.clearAllMocks(); | ||
}); | ||
|
||
it('should fetch token balances successfully', async () => { | ||
vi.mocked(getPortfolioTokenBalances).mockResolvedValueOnce({ | ||
portfolios: [mockPortfolioTokenBalances], | ||
}); | ||
|
||
const { result } = renderHook( | ||
() => usePortfolioTokenBalances({ address: mockAddress }), | ||
{ wrapper: createWrapper() }, | ||
); | ||
|
||
expect(result.current.isLoading).toBe(true); | ||
|
||
await waitFor(() => expect(result.current.isSuccess).toBe(true)); | ||
|
||
expect(getPortfolioTokenBalances).toHaveBeenCalledWith({ | ||
addresses: [mockAddress], | ||
}); | ||
|
||
expect(result.current.data).toEqual(mockPortfolioTokenBalances); | ||
}); | ||
|
||
it('should handle API errors', async () => { | ||
vi.mocked(getPortfolioTokenBalances).mockResolvedValueOnce({ | ||
code: 'API Error', | ||
error: 'API Error', | ||
message: 'API Error', | ||
}); | ||
|
||
const { result } = renderHook( | ||
() => usePortfolioTokenBalances({ address: mockAddress }), | ||
{ wrapper: createWrapper() }, | ||
); | ||
|
||
await waitFor(() => expect(result.current.isError).toBe(true)); | ||
|
||
expect(result.current.error).toBeInstanceOf(Error); | ||
expect(result.current.error?.message).toBe('API Error'); | ||
}); | ||
|
||
it('should not fetch when address is empty', () => { | ||
renderHook( | ||
() => usePortfolioTokenBalances({ address: '' as `0x${string}` }), | ||
{ | ||
wrapper: createWrapper(), | ||
}, | ||
); | ||
|
||
expect(getPortfolioTokenBalances).not.toHaveBeenCalled(); | ||
}); | ||
|
||
it('should not fetch when address is undefined', () => { | ||
renderHook(() => usePortfolioTokenBalances({ address: undefined }), { | ||
wrapper: createWrapper(), | ||
}); | ||
|
||
expect(getPortfolioTokenBalances).not.toHaveBeenCalled(); | ||
}); | ||
|
||
it('should return empty data when portfolios is empty', async () => { | ||
vi.mocked(getPortfolioTokenBalances).mockResolvedValueOnce({ | ||
portfolios: [], | ||
}); | ||
|
||
const { result } = renderHook( | ||
() => usePortfolioTokenBalances({ address: mockAddress }), | ||
{ wrapper: createWrapper() }, | ||
); | ||
|
||
await waitFor(() => expect(result.current.isSuccess).toBe(true)); | ||
|
||
expect(result.current.data).toEqual({ | ||
address: '0x123', | ||
portfolioBalanceUsd: 0, | ||
tokenBalances: [], | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { getPortfolioTokenBalances } from '@/core/api/getPortfolioTokenBalances'; | ||
import type { PortfolioTokenBalances } from '@/core/api/types'; | ||
import { isApiError } from '@/core/utils/isApiResponseError'; | ||
import { type UseQueryResult, useQuery } from '@tanstack/react-query'; | ||
import type { Address } from 'viem'; | ||
|
||
export function usePortfolioTokenBalances({ | ||
address, | ||
}: { | ||
address: Address | undefined | null; | ||
}): UseQueryResult<PortfolioTokenBalances> { | ||
return useQuery({ | ||
queryKey: ['usePortfolioTokenBalances', address], | ||
queryFn: async () => { | ||
const response = await getPortfolioTokenBalances({ | ||
addresses: [address as Address], // Safe to coerce to Address because useQuery's enabled flag will prevent the query from running if address is undefined | ||
}); | ||
|
||
if (isApiError(response)) { | ||
throw new Error(response.message); | ||
} | ||
|
||
if (response.portfolios.length === 0) { | ||
return { | ||
address, | ||
portfolioBalanceUsd: 0, | ||
tokenBalances: [], | ||
}; | ||
} | ||
|
||
return response.portfolios[0]; | ||
}, | ||
retry: false, | ||
enabled: !!address, | ||
refetchOnWindowFocus: true, // refresh on window focus | ||
staleTime: 1000 * 60 * 5, // refresh on mount every 5 minutes | ||
refetchOnMount: true, | ||
refetchInterval: 1000 * 60 * 15, // refresh in background every 15 minutes | ||
refetchIntervalInBackground: true, | ||
}); | ||
} |
Oops, something went wrong.