@phiresky/eth-scan
Version:
An efficient Ether and token balance scanner
3 lines • 4.88 kB
JavaScript
import ERC20Artifact from"@openzeppelin/contracts/build/contracts/IERC20.json";import{waffle,ethers}from"hardhat";import BalanceScannerArtifact from"../artifacts/contracts/BalanceScanner.sol/BalanceScanner.json";import ERC20InvalidMockArtifact from"../artifacts/contracts/mocks/ERC20InvalidMock.sol/ERC20InvalidMock.json";import{getEtherBalances,getTokenBalances,getTokensBalance,getTokensBalances}from"./eth-scan";const{deployContract,deployMockContract,createFixtureLoader,provider}=waffle,loadFixture=createFixtureLoader(provider.getWallets(),provider);// eslint-disable-next-line jest/no-export
export const fixture=async(a,b)=>{const c=a[0],d=await deployContract(c,BalanceScannerArtifact),e=await deployMockContract(c,ERC20Artifact.abi),f=await deployMockContract(a[0],ERC20Artifact.abi);await f.mock.balanceOf.returns("1000");const g=await deployMockContract(a[0],ERC20Artifact.abi);await g.mock.balanceOf.returns("1");const h=await Promise.all(a.slice(1).map(a=>a.getAddress())),i=await deployContract(c,ERC20InvalidMockArtifact,[h[0],1e3]);return{contract:d,signers:a,addresses:h,provider:b,token:e,tokenA:f,tokenB:g,invalidToken:i}};describe("eth-scan",()=>{describe("getEtherBalances",()=>{it("returns the ether balances for multiple addresses as a BalanceMap",async()=>{const{contract:a,addresses:b}=await loadFixture(fixture),c=await getEtherBalances(ethers.provider,b,{contractAddress:a.address});for(const a of b){const b=BigInt((await ethers.provider.getBalance(a)).toHexString());expect(b).toBe(c[a])}})}),describe("getTokenBalances",()=>{it("returns the token balances of one token, for multiple addresses",async()=>{const{contract:a,addresses:b,token:c}=await loadFixture(fixture);await c.mock.balanceOf.returns("1000");const d=await getTokenBalances(ethers.provider,b,c.address,{contractAddress:a.address});for(const a of b)expect(d[a]).toBe(1000n)}),it("does not throw for invalid contracts",async()=>{const{contract:a,addresses:b,token:c}=await loadFixture(fixture);await expect(()=>getTokenBalances(ethers.provider,b,c.address,{contractAddress:a.address})).not.toThrow()}),it("retries failed contract calls",async()=>{const{contract:a,addresses:b,invalidToken:c}=await loadFixture(fixture),d=await getTokenBalances(ethers.provider,[b[0],b[1]],c.address,{contractAddress:a.address});expect(d[b[0]]).toBe(1000n),expect(d[b[1]]).toBe(0n)})}),describe("getTokensBalances",()=>{it("returns multiple token balances, for multiple addresses",async()=>{const{contract:a,signers:b,addresses:c,tokenA:d,tokenB:e}=await loadFixture(fixture),f=await getTokensBalances(ethers.provider,c,[d.address,e.address],{contractAddress:a.address});for(const a of c)expect(Object.keys(f[a])).toHaveLength(2),expect(Object.keys(f[a])[0]).toBe(d.address),expect(Object.keys(f[a])[1]).toBe(e.address),expect(f[a][d.address]).toBe(1000n),expect(f[a][e.address]).toBe(1n)}),it("does not throw for invalid contracts",async()=>{const{contract:a,signers:b,addresses:c}=await loadFixture(fixture),d=await deployMockContract(b[0],ERC20Artifact.abi),e=await deployMockContract(b[0],ERC20Artifact.abi);await expect(()=>getTokensBalances(ethers.provider,c,[d.address,e.address],{contractAddress:a.address})).not.toThrow()}),it("retries failed contract calls",async()=>{const{contract:a,addresses:b,token:c,tokenA:d,invalidToken:e}=await loadFixture(fixture),f=await getTokensBalances(ethers.provider,[b[0],b[1]],[d.address,e.address,c.address],{contractAddress:a.address});expect(f[b[0]][c.address]).toBe(0n),expect(f[b[0]][d.address]).toBe(1000n),expect(f[b[0]][e.address]).toBe(1000n),expect(f[b[1]][c.address]).toBe(0n),expect(f[b[1]][d.address]).toBe(1000n),expect(f[b[1]][e.address]).toBe(0n)})}),describe("getTokensBalance",()=>{it("returns multiple token balances for a single address",async()=>{const{contract:a,addresses:b,tokenA:c,tokenB:d}=await loadFixture(fixture),e=await getTokensBalance(ethers.provider,b[0],[c.address,d.address],{contractAddress:a.address});expect(Object.keys(e)).toHaveLength(2),expect(Object.keys(e)[0]).toBe(c.address),expect(Object.keys(e)[1]).toBe(d.address),expect(e[c.address]).toBe(1000n),expect(e[d.address]).toBe(1n)}),it("does not throw for invalid contracts",async()=>{const{contract:a,signers:b,addresses:c}=await loadFixture(fixture),d=await deployMockContract(b[0],ERC20Artifact.abi),e=await deployMockContract(b[0],ERC20Artifact.abi);await expect(()=>getTokensBalance(ethers.provider,c[0],[d.address,e.address],{contractAddress:a.address})).not.toThrow()}),it("retries failed contract calls",async()=>{const{contract:a,addresses:b,token:c,tokenA:d,invalidToken:e}=await loadFixture(fixture),f=await getTokensBalance(ethers.provider,b[0],[c.address,d.address,e.address],{contractAddress:a.address});expect(f[c.address]).toBe(0n),expect(f[d.address]).toBe(1000n),expect(f[e.address]).toBe(1000n)})})});
//# sourceMappingURL=eth-scan.test.js.map