Skip to content

Commit e3572f9

Browse files
committed
fix: nativeCurrency supported
1 parent 06afae3 commit e3572f9

File tree

2 files changed

+89
-13
lines changed

2 files changed

+89
-13
lines changed

src/test/utils/getTokens.test.ts

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,24 @@
11
import { getInstance } from "@/core/uniDevKitV4Factory";
22
import { getTokens } from "@/utils/getTokens";
33
import { Token } from "@uniswap/sdk-core";
4-
import { type Address, erc20Abi } from "viem";
4+
import { type Address, erc20Abi, zeroAddress } from "viem";
55
import { beforeEach, describe, expect, it, vi } from "vitest";
66

77
// Mock the SDK instance
88
vi.mock("@/core/uniDevKitV4Factory", () => ({
99
getInstance: vi.fn(),
1010
}));
1111

12+
vi.mock("@/constants/chains", () => ({
13+
getChainById: () => ({
14+
nativeCurrency: {
15+
decimals: 18,
16+
symbol: "ETH",
17+
name: "Ethereum",
18+
},
19+
}),
20+
}));
21+
1222
describe("getTokens", () => {
1323
const mockClient = {
1424
multicall: vi.fn(),
@@ -81,6 +91,54 @@ describe("getTokens", () => {
8191
});
8292
});
8393

94+
it("should handle native currency (zeroAddress)", async () => {
95+
const addresses: [Address, ...Address[]] = [
96+
zeroAddress,
97+
"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" as Address, // WETH
98+
];
99+
100+
const mockResults = [
101+
"WETH", // symbol for WETH
102+
"Wrapped Ether", // name for WETH
103+
18, // decimals for WETH
104+
];
105+
106+
mockClient.multicall.mockResolvedValueOnce(mockResults);
107+
108+
const result = await getTokens({
109+
addresses,
110+
});
111+
112+
expect(result).not.toBeNull();
113+
expect(result).toHaveLength(2);
114+
expect(result?.[0]).toBeInstanceOf(Token);
115+
expect(result?.[1]).toBeInstanceOf(Token);
116+
117+
// Verify native token
118+
expect(result?.[0].symbol).toBe("ETH");
119+
expect(result?.[0].name).toBe("Ethereum");
120+
expect(result?.[0].decimals).toBe(18);
121+
expect(result?.[0].chainId).toBe(1);
122+
expect(result?.[0].address).toBe(zeroAddress);
123+
124+
// Verify WETH token
125+
expect(result?.[1].symbol).toBe("WETH");
126+
expect(result?.[1].name).toBe("Wrapped Ether");
127+
expect(result?.[1].decimals).toBe(18);
128+
expect(result?.[1].chainId).toBe(1);
129+
expect(result?.[1].address).toBe(addresses[1]);
130+
131+
// Verify multicall was called only for non-native token
132+
expect(mockClient.multicall).toHaveBeenCalledWith({
133+
contracts: [
134+
{ address: addresses[1], abi: erc20Abi, functionName: "symbol" },
135+
{ address: addresses[1], abi: erc20Abi, functionName: "name" },
136+
{ address: addresses[1], abi: erc20Abi, functionName: "decimals" },
137+
],
138+
allowFailure: false,
139+
});
140+
});
141+
84142
it("should throw error when SDK instance is not found", async () => {
85143
(getInstance as unknown as ReturnType<typeof vi.fn>).mockReturnValue(null);
86144

src/utils/getTokens.ts

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
import { getChainById } from "@/constants/chains";
12
import { getInstance } from "@/core/uniDevKitV4Factory";
23
import { Token } from "@uniswap/sdk-core";
3-
import { type Address, erc20Abi } from "viem";
4+
import { type Address, erc20Abi, zeroAddress } from "viem";
45

56
/**
67
* Retrieves Token instances for a list of token addresses on a specific chain.
@@ -18,18 +19,22 @@ export async function getTokens({
1819
chainId?: number;
1920
}): Promise<Token[] | null> {
2021
const sdk = getInstance(chainId);
22+
const currentChainId = chainId || sdk.getChainId();
23+
const chain = getChainById(currentChainId);
2124

2225
if (!sdk) {
2326
throw new Error("SDK not found. Please create an instance first.");
2427
}
2528

2629
const client = sdk.getClient();
2730

28-
const calls = addresses.flatMap((address) => [
29-
{ address, abi: erc20Abi, functionName: "symbol" },
30-
{ address, abi: erc20Abi, functionName: "name" },
31-
{ address, abi: erc20Abi, functionName: "decimals" },
32-
]);
31+
const calls = addresses
32+
.filter((address) => address !== zeroAddress) // filter out native currency
33+
.flatMap((address) => [
34+
{ address, abi: erc20Abi, functionName: "symbol" },
35+
{ address, abi: erc20Abi, functionName: "name" },
36+
{ address, abi: erc20Abi, functionName: "decimals" },
37+
]);
3338

3439
try {
3540
const results = await client.multicall({
@@ -41,12 +46,25 @@ export async function getTokens({
4146
let resultIndex = 0;
4247

4348
for (const address of addresses) {
44-
const symbol = results[resultIndex++] as string;
45-
const name = results[resultIndex++] as string;
46-
const decimals = results[resultIndex++] as number;
47-
tokens.push(
48-
new Token(sdk.getChainId(), address, decimals, symbol, name) as Token,
49-
);
49+
if (address === zeroAddress) {
50+
// For native currency, use chain data from wagmi
51+
const nativeCurrency = chain.nativeCurrency;
52+
tokens.push(
53+
new Token(
54+
currentChainId,
55+
address,
56+
nativeCurrency.decimals,
57+
nativeCurrency.symbol,
58+
nativeCurrency.name,
59+
),
60+
);
61+
} else {
62+
// For ERC20 tokens, use multicall results
63+
const symbol = results[resultIndex++] as string;
64+
const name = results[resultIndex++] as string;
65+
const decimals = results[resultIndex++] as number;
66+
tokens.push(new Token(currentChainId, address, decimals, symbol, name));
67+
}
5068
}
5169

5270
return tokens;

0 commit comments

Comments
 (0)