Skip to content

Commit

Permalink
add token balance fetching
Browse files Browse the repository at this point in the history
  • Loading branch information
bh2smith committed Jun 12, 2024
1 parent cdd68c9 commit 3a75bd6
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 2 deletions.
4 changes: 2 additions & 2 deletions src/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
} from "viem/chains";

// All supported networks
const SUPPORTED_NETWORKS = createNetworkMap([
export const SUPPORTED_NETWORKS = createNetworkMap([
mainnet,
gnosis,
sepolia,
Expand Down Expand Up @@ -58,7 +58,7 @@ export class Network implements NetworkFields {
}
}

type NetworkMap = { [key: number]: NetworkFields };
export type NetworkMap = { [key: number]: NetworkFields };

/// Dynamically generate network map accessible by chainId.
function createNetworkMap(supportedNetworks: Chain[]): NetworkMap {
Expand Down
45 changes: 45 additions & 0 deletions src/token/balance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { JsonRpcProvider, ethers } from "ethers";
import { NetworkMap } from "../network";
import { TOKEN_LIST } from "./list";

// This function fetches the balance of a specific ERC-20 token for a given address.
export async function getSingleTokenBalance(
tokenAddress: string,
walletAddress: string,
provider: JsonRpcProvider
): Promise<bigint> {
// Define the ERC-20 token ABI (only the `balanceOf` function is necessary for this task)
const tokenAbi = ["function balanceOf(address owner) view returns (uint256)"];

// Create a new ethers Contract instance to interact with the token
const tokenContract = new ethers.Contract(tokenAddress, tokenAbi, provider);

// Fetch the token balance
const balanceWei: bigint = await tokenContract.balanceOf(walletAddress);

// Convert the balance from wei to a more readable format (assuming it's a standard ERC-20 with 18 decimals)
return balanceWei;
}

export async function getBalancesForAccount(
walletAddress: string,
networks: NetworkMap
): Promise<void> {
for (const [key, network] of Object.entries(networks)) {
const provider = new ethers.JsonRpcProvider(network.rpcUrl);
const tokens = TOKEN_LIST[network.chainId];
console.log(key, network, tokens);
if (tokens !== undefined) {
const balances = await Promise.all(
tokens.map((x) =>
getSingleTokenBalance(x.address, walletAddress, provider)
)
);
console.log(
`Processed Balances for Chain ID: ${key}, got balances ${balances}`
);
} else {
console.log(`no tokens for ${network.name}`);
}
}
}
102 changes: 102 additions & 0 deletions src/token/list.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
type Token = {
symbol: string;
name: string;
address: string;
decimals: number;
chainId: number;
logoURI: string;
};

type TokenList = {
[key: number]: Token[];
};

export const TOKEN_LIST: TokenList = {
100: [
{
symbol: "COW",
name: "CoW Protocol Token",
address: "0x177127622c4A00F3d409B75571e12cB3c8973d3c",
decimals: 18,
chainId: 100,
logoURI:
"https://gateway.pinata.cloud/ipfs/QmQxFkVZzXFyWf73rcFwNPaEqG5hBwYXrwrBEX3aWJrn2r/cowprotocol.png",
},
],
1: [
{
symbol: "USDC",
name: "USD Coin",
address: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
decimals: 6,
chainId: 1,
logoURI:
"https://tokens.1inch.io/0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48.png",
},
{
symbol: "WETH",
name: "Wrapped Ether",
address: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
decimals: 18,
chainId: 1,
logoURI:
"https://tokens.1inch.io/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2.png",
},
{
symbol: "USDT",
name: "Tether USD",
address: "0xdac17f958d2ee523a2206206994597c13d831ec7",
decimals: 6,
chainId: 1,
logoURI:
"https://tokens.1inch.io/0xdac17f958d2ee523a2206206994597c13d831ec7.png",
},
{
symbol: "DAI",
name: "Dai Stablecoin",
address: "0x6b175474e89094c44da98b954eedeac495271d0f",
decimals: 18,
chainId: 1,
logoURI:
"https://tokens.1inch.io/0x6b175474e89094c44da98b954eedeac495271d0f.png",
},
{
symbol: "GNO",
name: "Gnosis",
address: "0x6810e776880c02933d47db1b9fc05908e5386b96",
decimals: 18,
chainId: 1,
logoURI:
"https://tokens.1inch.io/0x6810e776880c02933d47db1b9fc05908e5386b96.png",
},
{
symbol: "COW",
name: "CoW Protocol Token",
address: "0xDEf1CA1fb7FBcDC777520aa7f396b4E015F497aB",
decimals: 18,
chainId: 1,
logoURI:
"https://gateway.pinata.cloud/ipfs/QmQxFkVZzXFyWf73rcFwNPaEqG5hBwYXrwrBEX3aWJrn2r/cowprotocol.png",
},
],
11155111: [
{
symbol: "COW",
name: "CoW Protocol Token",
address: "0x0625afb445c3b6b7b929342a04a22599fd5dbb59",
decimals: 18,
chainId: 11155111,
logoURI:
"https://gateway.pinata.cloud/ipfs/QmQxFkVZzXFyWf73rcFwNPaEqG5hBwYXrwrBEX3aWJrn2r/cowprotocol.png",
},
{
symbol: "USDC",
name: "USDC (Sepolia)",
address: "0xbe72e441bf55620febc26715db68d3494213d8cb",
decimals: 6,
chainId: 11155111,
logoURI:
"https://tokens.1inch.io/0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48.png",
},
],
};
29 changes: 29 additions & 0 deletions tests/token.balance.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { sepolia } from "viem/chains";
import {
getSingleTokenBalance,
getBalancesForAccount,
} from "../src/token/balance";
import { ethers } from "ethers";
import { SUPPORTED_NETWORKS } from "../src/network";

describe("Transaction Builder Functions", () => {
it("getBalance", async () => {
const provider = new ethers.JsonRpcProvider(
sepolia.rpcUrls.default.http[0]
);
const balance = await getSingleTokenBalance(
"0x0625afb445c3b6b7b929342a04a22599fd5dbb59",
"0x8d99F8b2710e6A3B94d9bf465A98E5273069aCBd",
provider
);
console.log(balance);
});

it.only("getBalance", async () => {
const balance = await getBalancesForAccount(
"0x8d99F8b2710e6A3B94d9bf465A98E5273069aCBd",
SUPPORTED_NETWORKS
);
console.log(balance);
});
});

0 comments on commit 3a75bd6

Please sign in to comment.