import { expect } from "vitest"; import { whatsabi } from "../index"; import { autoload } from "../auto"; import { test, online_test, cached_test, makeProvider } from "./env"; const TIMEOUT = 15000; test('autoload throws typed error', async () => { // @ts-expect-error: Expected 2 arguments, but got 1 await expect(autoload("0xf00")).rejects.toThrow(new RegExp("config is undefined")); const fakeProvider = { request: () => { }, }; await expect(autoload("abc.eth", { provider: fakeProvider })).rejects.toThrow(new RegExp("Failed to resolve ENS")); }); test('autoload sets hasCode to false if code is empty', async () => { const fakeProvider = (code: string) => ({ request: () => code, }); const address = "0x00000000219ab540356cBB839Cbe05303d7705Fa" await expect(autoload(address, { provider: fakeProvider("0x") })).resolves.toMatchObject({ hasCode: false }); await expect(autoload(address, { provider: fakeProvider("0x1234") })).resolves.toMatchObject({ hasCode: true }); }); online_test('autoload selectors', async ({ provider }) => { const address = "0x4A137FD5e7a256eF08A7De531A17D0BE0cc7B6b6"; // Random unverified contract const { abi } = await autoload(address, { provider: provider, abiLoader: false, signatureLookup: false, }); expect(abi).toContainEqual({ "selector": "0x6dbf2fa0", "type": "function" }); expect(abi).toContainEqual({ "selector": "0xec0ab6a7", "type": "function" }); }, TIMEOUT); online_test('autoload selectors with experimental metadata', async ({ provider }) => { const address = "0x4A137FD5e7a256eF08A7De531A17D0BE0cc7B6b6"; // Random unverified contract const { abi } = await autoload(address, { provider: provider, abiLoader: false, signatureLookup: false, enableExperimentalMetadata: true, }); expect(abi).toContainEqual({ "inputs": [{ "type": "bytes", "name": "" }], "payable": true, "selector": "0x6dbf2fa0", "stateMutability": "payable", "type": "function" }); expect(abi).toContainEqual({ "inputs": [{ "type": "bytes", "name": "" }], "payable": true, "selector": "0xec0ab6a7", "stateMutability": "payable", "type": "function" }); }, TIMEOUT); online_test('autoload full', async ({ provider, env }) => { const address = "0x4A137FD5e7a256eF08A7De531A17D0BE0cc7B6b6"; // Random unverified contract const { abi, abiLoadedFrom } = await autoload(address, { provider: provider, // Equivalent to: // ...whatsabi.loaders.defaultsWithEnv(env), abiLoader: new whatsabi.loaders.MultiABILoader([ new whatsabi.loaders.SourcifyABILoader(), new whatsabi.loaders.EtherscanV2ABILoader({ apiKey: env.ETHERSCAN_API_KEY }), ]), signatureLookup: new whatsabi.loaders.MultiSignatureLookup([ new whatsabi.loaders.OpenChainSignatureLookup(), new whatsabi.loaders.FourByteSignatureLookup(), ]), //onProgress: (phase: string, ...args: any[]) => { console.debug("PROGRESS", phase, args); }, }); expect(abiLoadedFrom).toBeFalsy(); expect(abi).toContainEqual({ "inputs": [ { "type": "address" }, { "type": "uint256" }, { "type": "bytes" } ], "name": "call", "stateMutability": "nonpayable", "selector": "0x6dbf2fa0", "sig": "call(address,uint256,bytes)", "type": "function" }); expect(abi).toContainEqual({ "inputs": [{ "type": "uint256" }, { "type": "address[]" }, { "type": "bytes[]" }], "name": "batchCall", "selector": "0xec0ab6a7", "sig": "batchCall(uint256,address[],bytes[])", "stateMutability": "nonpayable", "type": "function", }); }, TIMEOUT); online_test('autoload non-contract', async ({ provider, env }) => { const address = "0x0000000000000000000000000000000000000000"; // Random unverified contract const { abi } = await autoload(address, { provider: provider, ...whatsabi.loaders.defaultsWithEnv(env), }); expect(abi).toStrictEqual([]); }); online_test('autoload verified multi', async ({ provider, env }) => { const address = "0x8f8ef111b67c04eb1641f5ff19ee54cda062f163"; // Uniswap v3 pool, verified on Etherscan and Sourcify const result = await autoload(address, { provider: provider, ...whatsabi.loaders.defaultsWithEnv(env), }); expect(result.abiLoadedFrom?.name).toBeTruthy(); }); online_test('autoload loadContractResult verified etherscan', async ({ provider, env }) => { const address = "0xc3d688b66703497daa19211eedff47f25384cdc3"; // Compound USDC proxy const result = await autoload(address, { provider: provider, loadContractResult: true, followProxies: false, abiLoader: new whatsabi.loaders.EtherscanV2ABILoader({ apiKey: env.ETHERSCAN_API_KEY }), }); expect(result.abiLoadedFrom?.name).toBe("EtherscanV2ABILoader"); expect(result.contractResult?.ok).toBeTruthy(); expect(result.contractResult?.name).toBe("TransparentUpgradeableProxy"); expect(result.contractResult?.compilerVersion).toBe("v0.8.15+commit.e14f2714"); expect(result.contractResult?.loaderResult?.Proxy).toBe("1"); expect(result.contractResult?.loaderResult?.Implementation).toMatch(new RegExp("^0x[0-9a-f]{40}$")); }); cached_test('autoload isFactory', async ({ provider, env, withCache }) => { const address = "0x7dB8637A5fd20BbDab1176BdF49C943A96F2E9c6"; // Factory that makes proxies const code = await withCache( `${address}_code`, async () => { return await provider.getCode(address) }, ) const result = await autoload(address, { provider: whatsabi.providers.WithCachedCode(provider, { [address]: code, }), ...whatsabi.loaders.defaultsWithEnv(env), }); expect(result.isFactory).toBeTruthy(); }); cached_test('autoload ambiguous proxy', async ({ provider, env, withCache }) => { // Issue #173 const address = "0xe1164a7a364929c3ba3da9671c8003dd71975d2d"; const code = await withCache( `${address}_code`, async () => { return await provider.getCode(address) }, ) const result = await autoload(address, { provider: whatsabi.providers.WithCachedCode(provider, { [address]: code, }), ...whatsabi.loaders.defaultsWithEnv(env), }); expect(result.proxies.length).toBe(1); expect(result.followProxies).toBeFalsy(); }); online_test('autoload WithBlockNumber from getBlockNumber', async ({ provider }) => { const address = "0x4A137FD5e7a256eF08A7De531A17D0BE0cc7B6b6"; // Random unverified contract const blockNumber = await provider.provider.getBlockNumber(); expect(blockNumber).toBeGreaterThan(100); const blockProvider = whatsabi.providers.WithBlockNumber(provider, blockNumber); const result = await whatsabi.autoload(address, { provider: blockProvider }); expect(result.abi.length).toBeGreaterThan(0); });